Upload folder using huggingface_hub
Browse files- code/scripts/gen_hires_512_manifest.py +42 -0
- code/scripts/gen_hires_768_recap_manifest.py +50 -0
- code/scripts/gen_hires_manifest.py +55 -0
- code/scripts/gen_pannuke_fw_manifest.py +39 -0
- code/scripts/gen_pannuke_fw_rerun.py +33 -0
- code/scripts/hf_upload_baselines.py +166 -0
- code/scripts/nnunet_eval_only_seggen.sh +38 -0
- code/scripts/nnunet_eval_par_heavy.sh +37 -0
- code/scripts/nnunet_predict_eval_remaining.sh +41 -0
- code/scripts/pannuke_cv_nnunet.sh +28 -0
- code/scripts/pannuke_cv_preprocess.sh +34 -0
- code/scripts/pannuke_cv_umamba.sh +30 -0
- code/scripts/umamba_predict_eval.sh +63 -0
- code/scripts/umamba_preprocess.sh +44 -0
code/scripts/gen_hires_512_manifest.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Rebuild the 768 recap manifest at R=512 for fives/refuge2/idridd (user chose to
|
| 2 |
+
drop 768->512: still high-res & resolution-fair, 300ep/3seed protocol intact, but
|
| 3 |
+
~2.3x less compute -> ~6-8 days instead of ~12-18). Reuses the capped 768 manifest's
|
| 4 |
+
36 jobs (thread caps already injected; cv2.setNumThreads(1) is in the code) and only:
|
| 5 |
+
--img_size 768 -> 512, --batch_size 4 -> 8 (batch 8 matches finished kvasir/busi@512).
|
| 6 |
+
expected_output paths unchanged (metrics.json gets written at whatever res trained).
|
| 7 |
+
Run ON a100: TS=$(date -u +%Y%m%dT%H%M%SZ) python3 scripts/gen_hires_512_manifest.py
|
| 8 |
+
"""
|
| 9 |
+
import json, os
|
| 10 |
+
|
| 11 |
+
SRC = os.path.expanduser("~/.aris_queue/runs/hires768_20260611T004855Z/manifest.json")
|
| 12 |
+
|
| 13 |
+
man = json.load(open(SRC))
|
| 14 |
+
top = {k: v for k, v in man.items() if k != "phases"}
|
| 15 |
+
src_jobs = man.get("jobs") or man["phases"][0]["jobs"]
|
| 16 |
+
|
| 17 |
+
jobs = []
|
| 18 |
+
for j in src_jobs:
|
| 19 |
+
c = j["cmd"]
|
| 20 |
+
if "--img_size 768" not in c or "--batch_size 4" not in c:
|
| 21 |
+
raise SystemExit("anchor not found in " + j["id"])
|
| 22 |
+
j2 = dict(j)
|
| 23 |
+
j2["id"] = j["id"].replace("rc_hr_", "r512_")
|
| 24 |
+
j2["cmd"] = c.replace("--img_size 768", "--img_size 512").replace("--batch_size 4", "--batch_size 8")
|
| 25 |
+
jobs.append(j2)
|
| 26 |
+
|
| 27 |
+
if not jobs:
|
| 28 |
+
raise SystemExit("no jobs")
|
| 29 |
+
|
| 30 |
+
man2 = dict(top)
|
| 31 |
+
man2["project"] = "baselines_hires_512"
|
| 32 |
+
# GPU5 hosts a non-campaign DDIM job (~43GB); lower the free-mem gate so the queue can
|
| 33 |
+
# still place light 512 jobs (~16GB) in GPU5's spare room instead of pinning to GPU4.
|
| 34 |
+
man2["gpu_free_threshold_mib"] = 30000
|
| 35 |
+
man2["phases"] = [{"name": "r512", "depends_on": [], "jobs": jobs}]
|
| 36 |
+
|
| 37 |
+
RUN = "hires512_" + os.environ["TS"]
|
| 38 |
+
rd = os.path.expanduser("~/.aris_queue/runs/" + RUN)
|
| 39 |
+
os.makedirs(rd + "/logs", exist_ok=True)
|
| 40 |
+
json.dump(man2, open(rd + "/manifest.json", "w"), indent=2)
|
| 41 |
+
print("RUN=" + RUN, "jobs=" + str(len(jobs)))
|
| 42 |
+
print("sample:", jobs[0]["cmd"][:200])
|
code/scripts/gen_hires_768_recap_manifest.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Rebuild a queue manifest for ONLY the 768-res datasets (fives/refuge2/idridd),
|
| 2 |
+
injecting CPU thread caps to fix the dataloader thread-oversubscription that starved
|
| 3 |
+
the GPU (epoch ~750s -> ~180s). Reuses the original hires manifest's jobs verbatim
|
| 4 |
+
(img_size 768, batch 4, num_workers 8, PCI_BUS_ID) and only:
|
| 5 |
+
(1) keeps the 3 R=768 datasets' jobs,
|
| 6 |
+
(2) prepends OMP/MKL/OPENBLAS/NUMEXPR/VECLIB_NUM_THREADS=8 to each export line.
|
| 7 |
+
The already-finished cvc/kvasir/busi (512/384) cells are untouched.
|
| 8 |
+
Run ON a100: TS=$(date -u +%Y%m%dT%H%M%SZ) python3 scripts/gen_hires_768_recap_manifest.py
|
| 9 |
+
"""
|
| 10 |
+
import json, os, glob
|
| 11 |
+
|
| 12 |
+
SRC = os.path.expanduser("~/.aris_queue/runs/hires_20260610T021920Z/manifest.json")
|
| 13 |
+
DS768_PREFIXES = ("hr_fives_", "hr_refuge2_", "hr_idridd_segmentation_")
|
| 14 |
+
CAP = ("OMP_NUM_THREADS=8 MKL_NUM_THREADS=8 OPENBLAS_NUM_THREADS=8 "
|
| 15 |
+
"NUMEXPR_NUM_THREADS=8 VECLIB_MAXIMUM_THREADS=8")
|
| 16 |
+
OLD = "export CUDA_DEVICE_ORDER=PCI_BUS_ID CUDA_VISIBLE_DEVICES=${GPU}"
|
| 17 |
+
NEW = "export CUDA_DEVICE_ORDER=PCI_BUS_ID CUDA_VISIBLE_DEVICES=${GPU} " + CAP
|
| 18 |
+
|
| 19 |
+
man = json.load(open(SRC))
|
| 20 |
+
top = {k: v for k, v in man.items() if k != "phases"}
|
| 21 |
+
src_jobs = man.get("jobs") or man["phases"][0]["jobs"]
|
| 22 |
+
|
| 23 |
+
jobs = []
|
| 24 |
+
for j in src_jobs:
|
| 25 |
+
if not j["id"].startswith(DS768_PREFIXES):
|
| 26 |
+
continue
|
| 27 |
+
# skip any that somehow already finished
|
| 28 |
+
if os.path.isfile(os.path.join(top.get("cwd", "."), j["expected_output"])):
|
| 29 |
+
continue
|
| 30 |
+
c = j["cmd"]
|
| 31 |
+
if OLD not in c:
|
| 32 |
+
raise SystemExit("export anchor not found in: " + j["id"])
|
| 33 |
+
j2 = dict(j)
|
| 34 |
+
j2["id"] = "rc_" + j["id"] # rc_ = recapped
|
| 35 |
+
j2["cmd"] = c.replace(OLD, NEW)
|
| 36 |
+
jobs.append(j2)
|
| 37 |
+
|
| 38 |
+
if not jobs:
|
| 39 |
+
raise SystemExit("no 768 jobs to (re)run")
|
| 40 |
+
|
| 41 |
+
man2 = dict(top)
|
| 42 |
+
man2["project"] = "baselines_hires_768_recap"
|
| 43 |
+
man2["phases"] = [{"name": "rc768", "depends_on": [], "jobs": jobs}]
|
| 44 |
+
|
| 45 |
+
RUN = "hires768_" + os.environ["TS"]
|
| 46 |
+
rd = os.path.expanduser("~/.aris_queue/runs/" + RUN)
|
| 47 |
+
os.makedirs(rd + "/logs", exist_ok=True)
|
| 48 |
+
json.dump(man2, open(rd + "/manifest.json", "w"), indent=2)
|
| 49 |
+
print("RUN=" + RUN, "jobs=" + str(len(jobs)))
|
| 50 |
+
print("sample cmd:", jobs[0]["cmd"][:160])
|
code/scripts/gen_hires_manifest.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Resolution-aligned RE-TRAIN manifest: the 4 fully-conv framework methods on the
|
| 2 |
+
6 resolution-mismatched datasets, at a per-dataset higher img_size (matching ~nnU-Net's
|
| 3 |
+
working resolution). Reuses each arch's original command, swaps in --img_size R +
|
| 4 |
+
smaller batch for the bigger inputs, injects CUDA_DEVICE_ORDER=PCI_BUS_ID (else jobs
|
| 5 |
+
land on busy L40s). 4 archs x 6 datasets x 3 seeds = 72 jobs."""
|
| 6 |
+
import json, glob, re, os
|
| 7 |
+
|
| 8 |
+
# (dataset, protocol, R, batch)
|
| 9 |
+
DS = [
|
| 10 |
+
("cvc_clinicdb", "official", 384, 16),
|
| 11 |
+
("kvasir_seg", "official", 512, 8),
|
| 12 |
+
("busi", "fold01", 512, 8),
|
| 13 |
+
("fives", "official", 768, 4),
|
| 14 |
+
("refuge2", "official", 768, 4),
|
| 15 |
+
("idridd_segmentation", "fold01", 768, 4),
|
| 16 |
+
]
|
| 17 |
+
ARCHS = ["unet", "unetpp", "deeplabv3plus", "attention_unet"] # SwinUNet/TransUNet are res-locked
|
| 18 |
+
|
| 19 |
+
base = {} # (dataset, arch) -> seed0 cmd
|
| 20 |
+
for p in sorted(glob.glob(os.path.expanduser("~/.aris_queue/runs/20260605T13*/manifest.json"))):
|
| 21 |
+
d = json.load(open(p)); js = d.get("jobs") or d.get("phases", [{}])[0].get("jobs", [])
|
| 22 |
+
for j in js:
|
| 23 |
+
c = j.get("cmd", "")
|
| 24 |
+
m = re.search(r"--dataset (\S+).*?--arch (\S+)", c)
|
| 25 |
+
if m and "--seed 0" in c:
|
| 26 |
+
base.setdefault((m.group(1), m.group(2)), c)
|
| 27 |
+
|
| 28 |
+
jobs, missing = [], []
|
| 29 |
+
for ds, proto, R, B in DS:
|
| 30 |
+
for a in ARCHS:
|
| 31 |
+
bc = base.get((ds, a))
|
| 32 |
+
if not bc:
|
| 33 |
+
missing.append((ds, a)); continue
|
| 34 |
+
for s in (0, 1, 2):
|
| 35 |
+
c = bc
|
| 36 |
+
c = c.replace("export CUDA_VISIBLE_DEVICES=${GPU}",
|
| 37 |
+
"export CUDA_DEVICE_ORDER=PCI_BUS_ID CUDA_VISIBLE_DEVICES=${GPU}")
|
| 38 |
+
c = c.replace("--batch_size 16", "--batch_size %d" % B)
|
| 39 |
+
c = c.replace("--seed 0", "--img_size %d --seed %d" % (R, s)) # hits train.py AND test.py
|
| 40 |
+
out = "results/baselines/%s_%s/%s/seed%d/metrics.json" % (ds, proto, a, s)
|
| 41 |
+
jobs.append({"id": "hr_%s_%s_s%d" % (ds, a, s), "cmd": c, "expected_output": out})
|
| 42 |
+
|
| 43 |
+
if missing:
|
| 44 |
+
raise SystemExit("missing base cmds: %s" % missing)
|
| 45 |
+
|
| 46 |
+
manifest = {"project": "baselines_hires", "cwd": "/home/wzhang/LSC/Code/NPJ", "conda": "seggen",
|
| 47 |
+
"ssh": "a100", "gpus": [4, 5], "jobs_per_gpu": 2, "max_parallel": 4,
|
| 48 |
+
"gpu_free_threshold_mib": 40000, "oom_retry": {"delay": 300, "max_attempts": 3},
|
| 49 |
+
"phases": [{"name": "hr", "depends_on": [], "jobs": jobs}]}
|
| 50 |
+
|
| 51 |
+
RUN = "hires_" + os.environ["TS"]
|
| 52 |
+
rd = os.path.expanduser("~/.aris_queue/runs/" + RUN)
|
| 53 |
+
os.makedirs(rd + "/logs", exist_ok=True)
|
| 54 |
+
json.dump(manifest, open(rd + "/manifest.json", "w"), indent=2)
|
| 55 |
+
print("RUN=" + RUN, "jobs=" + str(len(jobs)))
|
code/scripts/gen_pannuke_fw_manifest.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Generate the framework PanNuke fold02/fold03 manifest (12 jobs = 6 archs x 2
|
| 2 |
+
folds, seed0) by reusing the EXACT fold01 commands (preserves per-arch encoder /
|
| 3 |
+
pretrained ckpt / epochs), swapping only the protocol. Writes to a run dir."""
|
| 4 |
+
import json, glob, re, os
|
| 5 |
+
|
| 6 |
+
base = {}
|
| 7 |
+
for p in sorted(glob.glob(os.path.expanduser("~/.aris_queue/runs/20260605T13*/manifest.json"))):
|
| 8 |
+
d = json.load(open(p)); js = d.get("jobs") or d.get("phases", [{}])[0].get("jobs", [])
|
| 9 |
+
for j in js:
|
| 10 |
+
c = j.get("cmd", "")
|
| 11 |
+
if "pannuke" in c and "--protocol fold01" in c and "--seed 0" in c:
|
| 12 |
+
m = re.search(r"--arch (\S+)", c)
|
| 13 |
+
if m:
|
| 14 |
+
base.setdefault(m.group(1), c)
|
| 15 |
+
|
| 16 |
+
archs = ["unet", "unetpp", "deeplabv3plus", "attention_unet", "transunet", "swinunet"]
|
| 17 |
+
assert all(a in base for a in archs), "missing base cmd: %s" % [a for a in archs if a not in base]
|
| 18 |
+
|
| 19 |
+
jobs = []
|
| 20 |
+
for proto in ["fold02", "fold03"]:
|
| 21 |
+
for a in archs:
|
| 22 |
+
c = base[a].replace("--protocol fold01", "--protocol " + proto)
|
| 23 |
+
# CRITICAL: without PCI_BUS_ID, CVD=4/5 map to L40s (44GB, other users) not
|
| 24 |
+
# the A100s -> ECC/OOM. Force PCI bus order so 4/5 == nvidia-smi A100 #4/#5.
|
| 25 |
+
c = c.replace("export CUDA_VISIBLE_DEVICES=${GPU}",
|
| 26 |
+
"export CUDA_DEVICE_ORDER=PCI_BUS_ID CUDA_VISIBLE_DEVICES=${GPU}")
|
| 27 |
+
out = "results/baselines/pannuke_semantic_%s/%s/seed0/metrics.json" % (proto, a)
|
| 28 |
+
jobs.append({"id": "fw_%s_%s" % (proto, a), "cmd": c, "expected_output": out})
|
| 29 |
+
|
| 30 |
+
manifest = {"project": "pannuke_fw_cv", "cwd": "/home/wzhang/LSC/Code/NPJ", "conda": "seggen",
|
| 31 |
+
"ssh": "a100", "gpus": [4, 5], "jobs_per_gpu": 3, "max_parallel": 6,
|
| 32 |
+
"gpu_free_threshold_mib": 60000, "oom_retry": {"delay": 180, "max_attempts": 3},
|
| 33 |
+
"phases": [{"name": "fw", "depends_on": [], "jobs": jobs}]}
|
| 34 |
+
|
| 35 |
+
RUN = "pannuke_fw_" + os.environ["TS"]
|
| 36 |
+
rd = os.path.expanduser("~/.aris_queue/runs/" + RUN)
|
| 37 |
+
os.makedirs(rd + "/logs", exist_ok=True)
|
| 38 |
+
json.dump(manifest, open(rd + "/manifest.json", "w"), indent=2)
|
| 39 |
+
print("RUN=" + RUN, "jobs=" + str(len(jobs)))
|
code/scripts/gen_pannuke_fw_rerun.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Re-run manifest for the 10 framework PanNuke fold02/03 jobs that died on a
|
| 2 |
+
transient GPU4 uncorrectable-ECC burst. Excludes attention_unet (those 2 are
|
| 3 |
+
finishing in the original queue). Lower concurrency (jobs_per_gpu=2)."""
|
| 4 |
+
import json, glob, re, os
|
| 5 |
+
|
| 6 |
+
base = {}
|
| 7 |
+
for p in sorted(glob.glob(os.path.expanduser("~/.aris_queue/runs/20260605T13*/manifest.json"))):
|
| 8 |
+
d = json.load(open(p)); js = d.get("jobs") or d.get("phases", [{}])[0].get("jobs", [])
|
| 9 |
+
for j in js:
|
| 10 |
+
c = j.get("cmd", "")
|
| 11 |
+
if "pannuke" in c and "--protocol fold01" in c and "--seed 0" in c:
|
| 12 |
+
m = re.search(r"--arch (\S+)", c)
|
| 13 |
+
if m:
|
| 14 |
+
base.setdefault(m.group(1), c)
|
| 15 |
+
|
| 16 |
+
archs = ["unet", "unetpp", "deeplabv3plus", "transunet", "swinunet"] # attention_unet excluded
|
| 17 |
+
jobs = []
|
| 18 |
+
for proto in ["fold02", "fold03"]:
|
| 19 |
+
for a in archs:
|
| 20 |
+
c = base[a].replace("--protocol fold01", "--protocol " + proto)
|
| 21 |
+
out = "results/baselines/pannuke_semantic_%s/%s/seed0/metrics.json" % (proto, a)
|
| 22 |
+
jobs.append({"id": "fw_%s_%s" % (proto, a), "cmd": c, "expected_output": out})
|
| 23 |
+
|
| 24 |
+
manifest = {"project": "pannuke_fw_rerun", "cwd": "/home/wzhang/LSC/Code/NPJ", "conda": "seggen",
|
| 25 |
+
"ssh": "a100", "gpus": [4, 5], "jobs_per_gpu": 2, "max_parallel": 4,
|
| 26 |
+
"gpu_free_threshold_mib": 60000, "oom_retry": {"delay": 240, "max_attempts": 3},
|
| 27 |
+
"phases": [{"name": "fw", "depends_on": [], "jobs": jobs}]}
|
| 28 |
+
|
| 29 |
+
RUN = "pannuke_fwre_" + os.environ["TS"]
|
| 30 |
+
rd = os.path.expanduser("~/.aris_queue/runs/" + RUN)
|
| 31 |
+
os.makedirs(rd + "/logs", exist_ok=True)
|
| 32 |
+
json.dump(manifest, open(rd + "/manifest.json", "w"), indent=2)
|
| 33 |
+
print("RUN=" + RUN, "jobs=" + str(len(jobs)))
|
code/scripts/hf_upload_baselines.py
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Upload the BASELINE snapshot (code + confirmed results + curated weights) to a
|
| 2 |
+
private HF model repo. SegGen WIP is excluded. Run ON a100 (where code/results/weights live).
|
| 3 |
+
|
| 4 |
+
# dry-run: print manifest, upload nothing
|
| 5 |
+
HF_TOKEN=... python scripts/hf_upload_baselines.py --dry-run
|
| 6 |
+
# real:
|
| 7 |
+
HF_TOKEN=... python scripts/hf_upload_baselines.py
|
| 8 |
+
|
| 9 |
+
Curation: code = framework (minus synth/__pycache__) + scripts + envs/{seggen,nnunet,umamba}.yml.
|
| 10 |
+
results = all metrics.json + summary.{html,csv,md,tex} + efficiency.md. weights = best seed per
|
| 11 |
+
(dataset,arch) for framework + best fold per dataset for nnU-Net/U-Mamba.
|
| 12 |
+
"""
|
| 13 |
+
import os, glob, json, argparse, sys
|
| 14 |
+
|
| 15 |
+
REPO = "MaybeRichard/GenSeg-Baselines"
|
| 16 |
+
ROOT = "/home/wzhang/LSC/Code/NPJ"
|
| 17 |
+
NNRAW_IDS = { # results/baselines cell name -> nnU-Net Dataset id
|
| 18 |
+
"cvc_clinicdb_official":1, "kvasir_seg_official":2, "fives_official":3,
|
| 19 |
+
"refuge2_official":4, "busi_fold01":5, "idridd_segmentation_fold01":6,
|
| 20 |
+
"acdc_png_official":7, "pannuke_semantic_fold01":8,
|
| 21 |
+
"medsegdb_isic2018_holdout":9, "medsegdb_kits19_fold01":10,
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
def sz(p):
|
| 25 |
+
try: return os.path.getsize(p)
|
| 26 |
+
except OSError: return 0
|
| 27 |
+
|
| 28 |
+
def human(n): return f"{n/1024**3:.2f} GB" if n>=1024**3 else f"{n/1024**2:.1f} MB"
|
| 29 |
+
|
| 30 |
+
def curate_framework():
|
| 31 |
+
"""best seed per (cell,arch) -> best.pth"""
|
| 32 |
+
best = {}
|
| 33 |
+
for mj in glob.glob(f"{ROOT}/results/baselines/*/*/seed*/metrics.json"):
|
| 34 |
+
parts = mj.split("/"); cell, arch = parts[-4], parts[-3]
|
| 35 |
+
if arch in ("nnunet","umamba"): continue # handled separately
|
| 36 |
+
try: dice = json.load(open(mj)).get("metrics",{}).get("dice_mean",0)
|
| 37 |
+
except Exception: continue
|
| 38 |
+
pth = os.path.join(os.path.dirname(mj),"best.pth")
|
| 39 |
+
if not os.path.isfile(pth): continue
|
| 40 |
+
k = (cell,arch)
|
| 41 |
+
if k not in best or dice > best[k][0]:
|
| 42 |
+
best[k] = (dice, pth, f"weights/framework/{cell}/{arch}.pth")
|
| 43 |
+
return best
|
| 44 |
+
|
| 45 |
+
def curate_nn(method, results_dir):
|
| 46 |
+
"""best fold per dataset -> checkpoint_best.pth (matched via results/baselines metrics)"""
|
| 47 |
+
out = {}
|
| 48 |
+
for cell, did in NNRAW_IDS.items():
|
| 49 |
+
# best fold by our scored metrics
|
| 50 |
+
folds = []
|
| 51 |
+
for mj in glob.glob(f"{ROOT}/results/baselines/{cell}/{method}/seed*/metrics.json"):
|
| 52 |
+
f = int(mj.split("/seed")[-1].split("/")[0])
|
| 53 |
+
try: d = json.load(open(mj)).get("metrics",{}).get("dice_mean",0)
|
| 54 |
+
except Exception: d = 0
|
| 55 |
+
folds.append((d,f))
|
| 56 |
+
if not folds: continue
|
| 57 |
+
_, bf = max(folds)
|
| 58 |
+
cks = glob.glob(f"{results_dir}/Dataset{did:03d}_*/**/fold_{bf}/checkpoint_best.pth", recursive=True)
|
| 59 |
+
if not cks: continue
|
| 60 |
+
ck = max(cks, key=sz)
|
| 61 |
+
out[cell] = (ck, f"weights/{method}/{cell}_fold{bf}.pth")
|
| 62 |
+
return out
|
| 63 |
+
|
| 64 |
+
def list_code():
|
| 65 |
+
inc = []
|
| 66 |
+
for r,_,fs in os.walk(f"{ROOT}/framework"):
|
| 67 |
+
if "/synth" in r or "__pycache__" in r: continue
|
| 68 |
+
for f in fs:
|
| 69 |
+
if f.endswith(".pyc"): continue
|
| 70 |
+
inc.append(os.path.join(r,f))
|
| 71 |
+
for r,_,fs in os.walk(f"{ROOT}/scripts"):
|
| 72 |
+
if "__pycache__" in r: continue
|
| 73 |
+
for f in fs: inc.append(os.path.join(r,f))
|
| 74 |
+
for y in ("seggen","nnunet","umamba"):
|
| 75 |
+
p=f"{ROOT}/envs/{y}.yml"
|
| 76 |
+
if os.path.isfile(p): inc.append(p)
|
| 77 |
+
return inc
|
| 78 |
+
|
| 79 |
+
def list_results():
|
| 80 |
+
out = glob.glob(f"{ROOT}/results/baselines/**/metrics.json", recursive=True)
|
| 81 |
+
for pat in ("summary.html","summary.csv","summary.md","summary.tex","efficiency.md"):
|
| 82 |
+
out += glob.glob(f"{ROOT}/results/baselines/{pat}")
|
| 83 |
+
return out
|
| 84 |
+
|
| 85 |
+
def main():
|
| 86 |
+
ap = argparse.ArgumentParser(); ap.add_argument("--dry-run",action="store_true"); a=ap.parse_args()
|
| 87 |
+
code, res = list_code(), list_results()
|
| 88 |
+
fw = curate_framework()
|
| 89 |
+
nn = curate_nn("nnunet", f"{ROOT}/nnunet_workspace/results_nnunet")
|
| 90 |
+
um = curate_nn("umamba", f"{ROOT}/nnunet_workspace/results_umamba")
|
| 91 |
+
w_fw = sum(sz(v[1]) for v in fw.values())
|
| 92 |
+
w_nn = sum(sz(v[0]) for v in nn.values()); w_um = sum(sz(v[0]) for v in um.values())
|
| 93 |
+
code_sz = sum(sz(p) for p in code); res_sz = sum(sz(p) for p in res)
|
| 94 |
+
print("="*60)
|
| 95 |
+
print(f"REPO: {REPO} (private)")
|
| 96 |
+
print(f"CODE : {len(code):4d} files {human(code_sz)} (framework w/o synth + scripts + 3 envs)")
|
| 97 |
+
print(f"RESULTS: {len(res):4d} files {human(res_sz)} (metrics.json + summary.* + efficiency.md)")
|
| 98 |
+
print(f"WEIGHTS framework: {len(fw):3d} cells {human(w_fw)} (best seed per dataset x arch)")
|
| 99 |
+
print(f"WEIGHTS nnU-Net : {len(nn):3d} dsets {human(w_nn)} (best fold)")
|
| 100 |
+
print(f"WEIGHTS U-Mamba : {len(um):3d} dsets {human(w_um)} (best fold)")
|
| 101 |
+
print(f"TOTAL : {human(code_sz+res_sz+w_fw+w_nn+w_um)}")
|
| 102 |
+
print("="*60)
|
| 103 |
+
print("sample framework weights:")
|
| 104 |
+
for k in list(fw)[:3]: print(" ", fw[k][2], "<-", os.path.relpath(fw[k][1],ROOT))
|
| 105 |
+
print("sample nnU-Net/U-Mamba weights:")
|
| 106 |
+
for d in (nn,um):
|
| 107 |
+
for k in list(d)[:2]: print(" ", d[k][1], "<-", os.path.relpath(d[k][0],ROOT))
|
| 108 |
+
miss = [c for c in NNRAW_IDS if c not in nn] + [c for c in NNRAW_IDS if c not in um]
|
| 109 |
+
if miss: print("NOTE missing nn/um ckpts for:", sorted(set(miss)))
|
| 110 |
+
if a.dry_run:
|
| 111 |
+
print("\n[dry-run] nothing uploaded.")
|
| 112 |
+
return
|
| 113 |
+
# ---- real upload ----
|
| 114 |
+
from huggingface_hub import HfApi, create_repo
|
| 115 |
+
api = HfApi()
|
| 116 |
+
create_repo(REPO, repo_type="model", private=True, exist_ok=True)
|
| 117 |
+
readme = """---
|
| 118 |
+
license: cc-by-nc-4.0
|
| 119 |
+
tags: [medical-imaging, segmentation, benchmark]
|
| 120 |
+
---
|
| 121 |
+
|
| 122 |
+
# GenSeg-Baselines
|
| 123 |
+
|
| 124 |
+
Baseline benchmark for 2D medical image segmentation: **8 methods x 10 datasets x 3 seeds/folds, 7 metrics**.
|
| 125 |
+
Companion to the [GenSegDataset](https://huggingface.co/datasets/MaybeRichard/GenSegDataset).
|
| 126 |
+
|
| 127 |
+
**Methods:** UNet, UNet++, DeepLabV3+ (ResNet-50/ImageNet), Attention-UNet (scratch),
|
| 128 |
+
TransUNet (R50-ViT-B/16), Swin-UNet (Swin-Tiny), nnU-Net v2 (250ep), U-Mamba (UMambaBot, 100ep).
|
| 129 |
+
|
| 130 |
+
**Datasets:** cvc_clinicdb, kvasir_seg, fives, busi, refuge2, acdc, idridd, pannuke, isic2018, kits19.
|
| 131 |
+
|
| 132 |
+
**Metrics:** Dice, IoU, HD95, ASSD, Sensitivity, Specificity, Precision (+ efficiency).
|
| 133 |
+
|
| 134 |
+
## Layout
|
| 135 |
+
- `code/` - baseline framework (train/test/aggregate), scripts, conda envs. *(Generative SegGen code excluded.)*
|
| 136 |
+
- `results/` - per-run `metrics.json` + aggregated `summary.{html,csv,md,tex}` + `efficiency.md`.
|
| 137 |
+
- `weights/` - curated checkpoints: best seed per (dataset, arch) for framework; best fold for nnU-Net / U-Mamba.
|
| 138 |
+
|
| 139 |
+
## Note
|
| 140 |
+
These are the **256-px baseline** (confirmed). A resolution-fair re-evaluation (conv methods retrained at a
|
| 141 |
+
higher per-dataset resolution; all methods scored at a common R so HD95 is comparable) is in progress and
|
| 142 |
+
will be added later.
|
| 143 |
+
"""
|
| 144 |
+
import tempfile
|
| 145 |
+
tmp = os.path.join(tempfile.gettempdir(), "GENSEG_README.md")
|
| 146 |
+
open(tmp,"w").write(readme)
|
| 147 |
+
api.upload_file(path_or_fileobj=tmp, repo_id=REPO, path_in_repo="README.md")
|
| 148 |
+
print("repo ready; uploading code+results ...")
|
| 149 |
+
api.upload_folder(folder_path=f"{ROOT}/framework", repo_id=REPO, path_in_repo="code/framework",
|
| 150 |
+
ignore_patterns=["synth/*","**/__pycache__/*","*.pyc"])
|
| 151 |
+
api.upload_folder(folder_path=f"{ROOT}/scripts", repo_id=REPO, path_in_repo="code/scripts",
|
| 152 |
+
ignore_patterns=["**/__pycache__/*","*.pyc"])
|
| 153 |
+
for y in ("seggen","nnunet","umamba"):
|
| 154 |
+
api.upload_file(path_or_fileobj=f"{ROOT}/envs/{y}.yml", repo_id=REPO, path_in_repo=f"code/envs/{y}.yml")
|
| 155 |
+
api.upload_folder(folder_path=f"{ROOT}/results/baselines", repo_id=REPO, path_in_repo="results",
|
| 156 |
+
allow_patterns=["**/metrics.json","summary.*","efficiency.md"])
|
| 157 |
+
print("uploading weights ...")
|
| 158 |
+
for v in fw.values():
|
| 159 |
+
api.upload_file(path_or_fileobj=v[1], repo_id=REPO, path_in_repo=v[2])
|
| 160 |
+
for d in (nn,um):
|
| 161 |
+
for v in d.values():
|
| 162 |
+
api.upload_file(path_or_fileobj=v[0], repo_id=REPO, path_in_repo=v[1])
|
| 163 |
+
print("DONE:", f"https://huggingface.co/{REPO}")
|
| 164 |
+
|
| 165 |
+
if __name__ == "__main__":
|
| 166 |
+
main()
|
code/scripts/nnunet_eval_only_seggen.sh
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# Re-score ALL 10 nnU-Net datasets (fold 0/1/2) from cached test predictions,
|
| 3 |
+
# running in the *seggen* env (which has MONAI+medpy) so HD95/ASSD are real, not
|
| 4 |
+
# NaN. Idempotent: overwrites results/baselines/<ds>/nnunet/seed<f>/metrics.json.
|
| 5 |
+
set -u
|
| 6 |
+
cd /home/wzhang/LSC/Code/NPJ
|
| 7 |
+
source /opt/anaconda3/etc/profile.d/conda.sh
|
| 8 |
+
conda activate seggen
|
| 9 |
+
DATA_ROOT=/home/wzhang/LSC/Dataset/Segmentation/processed_unified
|
| 10 |
+
RAW=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/raw
|
| 11 |
+
PRED=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/predTs
|
| 12 |
+
|
| 13 |
+
SPECS=(
|
| 14 |
+
"1:cvc_clinicdb:official"
|
| 15 |
+
"2:kvasir_seg:official"
|
| 16 |
+
"3:fives:official"
|
| 17 |
+
"4:refuge2:official"
|
| 18 |
+
"5:busi:fold01"
|
| 19 |
+
"6:idridd_segmentation:fold01"
|
| 20 |
+
"7:acdc_png:official"
|
| 21 |
+
"8:pannuke_semantic:fold01"
|
| 22 |
+
"9:medsegdb_isic2018:holdout"
|
| 23 |
+
"10:medsegdb_kits19:fold01"
|
| 24 |
+
)
|
| 25 |
+
for spec in "${SPECS[@]}"; do
|
| 26 |
+
IFS=: read -r id ds proto <<< "$spec"
|
| 27 |
+
for f in 0 1 2; do
|
| 28 |
+
outdir=$PRED/d${id}_f${f}
|
| 29 |
+
if [ ! -d "$outdir" ] || [ -z "$(ls -A "$outdir"/*.png 2>/dev/null)" ]; then
|
| 30 |
+
echo "[skip] $ds fold$f: no predictions in $outdir"; continue
|
| 31 |
+
fi
|
| 32 |
+
python framework/nnunet_eval.py --data_root "$DATA_ROOT" \
|
| 33 |
+
--dataset "$ds" --protocol "$proto" --raw "$RAW" \
|
| 34 |
+
--dataset_id "$id" --fold "$f" --pred_dir "$outdir" \
|
| 35 |
+
--arch nnunet --exp_name baselines
|
| 36 |
+
done
|
| 37 |
+
done
|
| 38 |
+
echo EVAL_ONLY_ALL_DONE
|
code/scripts/nnunet_eval_par_heavy.sh
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# Parallel HD95/ASSD re-score for the heavy nnU-Net datasets (IDs 6-10), all folds,
|
| 3 |
+
# seggen env. Datasets 1-5 are already scored correctly and are left untouched.
|
| 4 |
+
# Each (dataset,fold) runs as its own process; 384 cores easily absorb 15 at once.
|
| 5 |
+
set -u
|
| 6 |
+
cd /home/wzhang/LSC/Code/NPJ
|
| 7 |
+
source /opt/anaconda3/etc/profile.d/conda.sh
|
| 8 |
+
conda activate seggen
|
| 9 |
+
# Cap intra-op threads: MONAI/torch otherwise grab all 384 cores per process, so
|
| 10 |
+
# 15 procs oversubscribe (load ~880) and thrash. 8 threads x 15 procs = ~120 << 384.
|
| 11 |
+
export OMP_NUM_THREADS=8 MKL_NUM_THREADS=8 OPENBLAS_NUM_THREADS=8 NUMEXPR_NUM_THREADS=8
|
| 12 |
+
DATA_ROOT=/home/wzhang/LSC/Dataset/Segmentation/processed_unified
|
| 13 |
+
RAW=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/raw
|
| 14 |
+
PRED=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/predTs
|
| 15 |
+
LOGD=nnunet_workspace/eval_par_logs
|
| 16 |
+
mkdir -p "$LOGD"
|
| 17 |
+
|
| 18 |
+
for id in 6 7 8 9 10; do
|
| 19 |
+
case $id in
|
| 20 |
+
6) ds=idridd_segmentation; proto=fold01;;
|
| 21 |
+
7) ds=acdc_png; proto=official;;
|
| 22 |
+
8) ds=pannuke_semantic; proto=fold01;;
|
| 23 |
+
9) ds=medsegdb_isic2018; proto=holdout;;
|
| 24 |
+
10) ds=medsegdb_kits19; proto=fold01;;
|
| 25 |
+
esac
|
| 26 |
+
for f in 0 1 2; do
|
| 27 |
+
(
|
| 28 |
+
python framework/nnunet_eval.py --data_root "$DATA_ROOT" \
|
| 29 |
+
--dataset "$ds" --protocol "$proto" --raw "$RAW" \
|
| 30 |
+
--dataset_id "$id" --fold "$f" --pred_dir "$PRED/d${id}_f${f}" \
|
| 31 |
+
--arch nnunet --exp_name baselines > "$LOGD/d${id}_f${f}.log" 2>&1
|
| 32 |
+
echo "done d${id}_f${f}: $(tail -1 "$LOGD/d${id}_f${f}.log")"
|
| 33 |
+
) &
|
| 34 |
+
done
|
| 35 |
+
done
|
| 36 |
+
wait
|
| 37 |
+
echo PAR_EVAL_DONE
|
code/scripts/nnunet_predict_eval_remaining.sh
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# Bulk predict-on-test + 7-metric eval for the 6 remaining nnU-Net datasets
|
| 3 |
+
# (IDs 005-010, each fold 0/1/2). Splits work across the two idle A100s (#4,#5).
|
| 4 |
+
set -u
|
| 5 |
+
cd /home/wzhang/LSC/Code/NPJ
|
| 6 |
+
source /opt/anaconda3/etc/profile.d/conda.sh
|
| 7 |
+
conda activate nnunet
|
| 8 |
+
export CUDA_DEVICE_ORDER=PCI_BUS_ID
|
| 9 |
+
export nnUNet_raw=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/raw
|
| 10 |
+
export nnUNet_preprocessed=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/preprocessed
|
| 11 |
+
export nnUNet_results=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/results_nnunet
|
| 12 |
+
DATA_ROOT=/home/wzhang/LSC/Dataset/Segmentation/processed_unified
|
| 13 |
+
PRED=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/predTs
|
| 14 |
+
|
| 15 |
+
run_ds () {
|
| 16 |
+
local gpu=$1; shift
|
| 17 |
+
for spec in "$@"; do
|
| 18 |
+
IFS=: read -r id ds proto <<< "$spec"
|
| 19 |
+
dsname=$(printf "Dataset%03d_%s_%s" "$id" "$ds" "$proto")
|
| 20 |
+
for f in 0 1 2; do
|
| 21 |
+
outdir=$PRED/d${id}_f${f}
|
| 22 |
+
mkdir -p "$outdir"
|
| 23 |
+
echo "[predict] gpu=$gpu $dsname fold$f -> $outdir"
|
| 24 |
+
CUDA_VISIBLE_DEVICES=$gpu nnUNetv2_predict \
|
| 25 |
+
-i "$nnUNet_raw/$dsname/imagesTs" -o "$outdir" \
|
| 26 |
+
-d "$id" -c 2d -f "$f" -tr nnUNetTrainer_250epochs --disable_tta \
|
| 27 |
+
> "$outdir/predict.log" 2>&1
|
| 28 |
+
echo "[eval] $dsname fold$f"
|
| 29 |
+
python framework/nnunet_eval.py --data_root "$DATA_ROOT" \
|
| 30 |
+
--dataset "$ds" --protocol "$proto" --raw "$nnUNet_raw" \
|
| 31 |
+
--dataset_id "$id" --fold "$f" --pred_dir "$outdir" \
|
| 32 |
+
--arch nnunet --exp_name baselines > "$outdir/eval.log" 2>&1
|
| 33 |
+
tail -1 "$outdir/eval.log"
|
| 34 |
+
done
|
| 35 |
+
done
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
run_ds 4 "5:busi:fold01" "6:idridd_segmentation:fold01" "7:acdc_png:official" &
|
| 39 |
+
run_ds 5 "8:pannuke_semantic:fold01" "9:medsegdb_isic2018:holdout" "10:medsegdb_kits19:fold01" &
|
| 40 |
+
wait
|
| 41 |
+
echo ALL_NNUNET_PREDICT_EVAL_DONE
|
code/scripts/pannuke_cv_nnunet.sh
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# nnU-Net PanNuke fold02(d11)+fold03(d12): train fold0 on both A100s, predict, score.
|
| 3 |
+
set -u
|
| 4 |
+
cd /home/wzhang/LSC/Code/NPJ
|
| 5 |
+
source /opt/anaconda3/etc/profile.d/conda.sh
|
| 6 |
+
RAW=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/raw
|
| 7 |
+
PRED=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/predTs
|
| 8 |
+
DATA_ROOT=/home/wzhang/LSC/Dataset/Segmentation/processed_unified
|
| 9 |
+
export CUDA_DEVICE_ORDER=PCI_BUS_ID
|
| 10 |
+
|
| 11 |
+
conda activate nnunet
|
| 12 |
+
export nnUNet_raw=$RAW
|
| 13 |
+
export nnUNet_preprocessed=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/preprocessed_nnunet
|
| 14 |
+
export nnUNet_results=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/results_nnunet
|
| 15 |
+
export nnUNet_n_proc_DA=8 OMP_NUM_THREADS=4
|
| 16 |
+
CUDA_VISIBLE_DEVICES=4 nnUNetv2_train 11 2d 0 -tr nnUNetTrainer_250epochs > nnunet_workspace/train_nnunet_d11.log 2>&1 &
|
| 17 |
+
CUDA_VISIBLE_DEVICES=5 nnUNetv2_train 12 2d 0 -tr nnUNetTrainer_250epochs > nnunet_workspace/train_nnunet_d12.log 2>&1 &
|
| 18 |
+
wait
|
| 19 |
+
echo NNUNET_CV_TRAIN_DONE
|
| 20 |
+
CUDA_VISIBLE_DEVICES=4 nnUNetv2_predict -i "$RAW/Dataset011_pannuke_semantic_fold02/imagesTs" -o "$PRED/d11_f0" -d 11 -c 2d -f 0 -tr nnUNetTrainer_250epochs --disable_tta > nnunet_workspace/pred_nnunet_d11.log 2>&1 &
|
| 21 |
+
CUDA_VISIBLE_DEVICES=5 nnUNetv2_predict -i "$RAW/Dataset012_pannuke_semantic_fold03/imagesTs" -o "$PRED/d12_f0" -d 12 -c 2d -f 0 -tr nnUNetTrainer_250epochs --disable_tta > nnunet_workspace/pred_nnunet_d12.log 2>&1 &
|
| 22 |
+
wait
|
| 23 |
+
|
| 24 |
+
conda deactivate; conda activate seggen
|
| 25 |
+
export OMP_NUM_THREADS=8 MKL_NUM_THREADS=8 OPENBLAS_NUM_THREADS=8
|
| 26 |
+
python framework/nnunet_eval.py --data_root "$DATA_ROOT" --dataset pannuke_semantic --protocol fold02 --raw "$RAW" --dataset_id 11 --fold 0 --pred_dir "$PRED/d11_f0" --arch nnunet --exp_name baselines
|
| 27 |
+
python framework/nnunet_eval.py --data_root "$DATA_ROOT" --dataset pannuke_semantic --protocol fold03 --raw "$RAW" --dataset_id 12 --fold 0 --pred_dir "$PRED/d12_f0" --arch nnunet --exp_name baselines
|
| 28 |
+
echo NNUNET_CV_DONE
|
code/scripts/pannuke_cv_preprocess.sh
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# Preprocess pannuke fold02 (d11) + fold03 (d12) for BOTH nnU-Net and U-Mamba
|
| 3 |
+
# (separate preprocessed dirs, separate envs), CPU-only, thread-capped. Copies the
|
| 4 |
+
# fixed splits into each preprocessed dataset.
|
| 5 |
+
set -u
|
| 6 |
+
cd /home/wzhang/LSC/Code/NPJ
|
| 7 |
+
source /opt/anaconda3/etc/profile.d/conda.sh
|
| 8 |
+
RAW=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/raw
|
| 9 |
+
export OMP_NUM_THREADS=4 MKL_NUM_THREADS=4 OPENBLAS_NUM_THREADS=4
|
| 10 |
+
|
| 11 |
+
( conda activate nnunet
|
| 12 |
+
export nnUNet_raw=$RAW
|
| 13 |
+
export nnUNet_preprocessed=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/preprocessed_nnunet
|
| 14 |
+
export nnUNet_results=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/results_nnunet
|
| 15 |
+
for id in 11 12; do
|
| 16 |
+
nnUNetv2_plan_and_preprocess -d "$id" -c 2d -np 12 > "nnunet_workspace/pp_nnunet_d${id}.log" 2>&1
|
| 17 |
+
name=$(basename "$(ls -d $RAW/Dataset0${id}_*)")
|
| 18 |
+
cp "$RAW/$name/splits_final.json" "$nnUNet_preprocessed/$name/splits_final.json"
|
| 19 |
+
echo "nnunet d$id preprocessed ($name)"
|
| 20 |
+
done ) &
|
| 21 |
+
|
| 22 |
+
( conda activate umamba
|
| 23 |
+
export nnUNet_raw=$RAW
|
| 24 |
+
export nnUNet_preprocessed=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/preprocessed_umamba
|
| 25 |
+
export nnUNet_results=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/results_umamba
|
| 26 |
+
for id in 11 12; do
|
| 27 |
+
nnUNetv2_plan_and_preprocess -d "$id" -c 2d -np 12 > "nnunet_workspace/pp_umamba_d${id}.log" 2>&1
|
| 28 |
+
name=$(basename "$(ls -d $RAW/Dataset0${id}_*)")
|
| 29 |
+
cp "$RAW/$name/splits_final.json" "$nnUNet_preprocessed/$name/splits_final.json"
|
| 30 |
+
echo "umamba d$id preprocessed ($name)"
|
| 31 |
+
done ) &
|
| 32 |
+
|
| 33 |
+
wait
|
| 34 |
+
echo PANNUKE_PP_DONE
|
code/scripts/pannuke_cv_umamba.sh
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# U-Mamba PanNuke fold02(d11)+fold03(d12): train fold0 (100ep) on both A100s, predict, score.
|
| 3 |
+
set -u
|
| 4 |
+
cd /home/wzhang/LSC/Code/NPJ
|
| 5 |
+
source /opt/anaconda3/etc/profile.d/conda.sh
|
| 6 |
+
RAW=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/raw
|
| 7 |
+
PRED=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/predTs_umamba
|
| 8 |
+
DATA_ROOT=/home/wzhang/LSC/Dataset/Segmentation/processed_unified
|
| 9 |
+
TR=nnUNetTrainerUMambaBot_100epochs
|
| 10 |
+
export CUDA_DEVICE_ORDER=PCI_BUS_ID
|
| 11 |
+
mkdir -p "$PRED"
|
| 12 |
+
|
| 13 |
+
conda activate umamba
|
| 14 |
+
export nnUNet_raw=$RAW
|
| 15 |
+
export nnUNet_preprocessed=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/preprocessed_umamba
|
| 16 |
+
export nnUNet_results=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/results_umamba
|
| 17 |
+
export nnUNet_n_proc_DA=8 OMP_NUM_THREADS=4
|
| 18 |
+
CUDA_VISIBLE_DEVICES=4 nnUNetv2_train 11 2d 0 -tr "$TR" > nnunet_workspace/train_umamba_d11.log 2>&1 &
|
| 19 |
+
CUDA_VISIBLE_DEVICES=5 nnUNetv2_train 12 2d 0 -tr "$TR" > nnunet_workspace/train_umamba_d12.log 2>&1 &
|
| 20 |
+
wait
|
| 21 |
+
echo UMAMBA_CV_TRAIN_DONE
|
| 22 |
+
CUDA_VISIBLE_DEVICES=4 nnUNetv2_predict -i "$RAW/Dataset011_pannuke_semantic_fold02/imagesTs" -o "$PRED/d11_f0" -d 11 -c 2d -f 0 -tr "$TR" --disable_tta > nnunet_workspace/pred_umamba_d11.log 2>&1 &
|
| 23 |
+
CUDA_VISIBLE_DEVICES=5 nnUNetv2_predict -i "$RAW/Dataset012_pannuke_semantic_fold03/imagesTs" -o "$PRED/d12_f0" -d 12 -c 2d -f 0 -tr "$TR" --disable_tta > nnunet_workspace/pred_umamba_d12.log 2>&1 &
|
| 24 |
+
wait
|
| 25 |
+
|
| 26 |
+
conda deactivate; conda activate seggen
|
| 27 |
+
export OMP_NUM_THREADS=8 MKL_NUM_THREADS=8 OPENBLAS_NUM_THREADS=8
|
| 28 |
+
python framework/nnunet_eval.py --data_root "$DATA_ROOT" --dataset pannuke_semantic --protocol fold02 --raw "$RAW" --dataset_id 11 --fold 0 --pred_dir "$PRED/d11_f0" --arch umamba --exp_name baselines
|
| 29 |
+
python framework/nnunet_eval.py --data_root "$DATA_ROOT" --dataset pannuke_semantic --protocol fold03 --raw "$RAW" --dataset_id 12 --fold 0 --pred_dir "$PRED/d12_f0" --arch umamba --exp_name baselines
|
| 30 |
+
echo UMAMBA_CV_DONE
|
code/scripts/umamba_predict_eval.sh
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# U-Mamba finale: predict test sets (umamba env, both A100s) then score the 7
|
| 3 |
+
# framework metrics (seggen env, thread-capped). Mirrors the nnU-Net predict+eval
|
| 4 |
+
# flow but with results_umamba / preprocessed_umamba / trainer 100ep / arch=umamba.
|
| 5 |
+
set -u
|
| 6 |
+
cd /home/wzhang/LSC/Code/NPJ
|
| 7 |
+
source /opt/anaconda3/etc/profile.d/conda.sh
|
| 8 |
+
export CUDA_DEVICE_ORDER=PCI_BUS_ID
|
| 9 |
+
RAW=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/raw
|
| 10 |
+
PRE=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/preprocessed_umamba
|
| 11 |
+
RES=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/results_umamba
|
| 12 |
+
PRED=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/predTs_umamba
|
| 13 |
+
DATA_ROOT=/home/wzhang/LSC/Dataset/Segmentation/processed_unified
|
| 14 |
+
TR=nnUNetTrainerUMambaBot_100epochs
|
| 15 |
+
mkdir -p "$PRED"
|
| 16 |
+
|
| 17 |
+
dsname () { case $1 in
|
| 18 |
+
1) echo cvc_clinicdb official;; 2) echo kvasir_seg official;; 3) echo fives official;;
|
| 19 |
+
4) echo refuge2 official;; 5) echo busi fold01;; 6) echo idridd_segmentation fold01;;
|
| 20 |
+
7) echo acdc_png official;; 8) echo pannuke_semantic fold01;; 9) echo medsegdb_isic2018 holdout;;
|
| 21 |
+
10) echo medsegdb_kits19 fold01;;
|
| 22 |
+
esac; }
|
| 23 |
+
rawname () { printf "Dataset%03d_%s_%s" "$1" "$2" "$3"; }
|
| 24 |
+
|
| 25 |
+
# ---------- Phase 1: predict (umamba env), ids split across GPU4 / GPU5 ----------
|
| 26 |
+
conda activate umamba
|
| 27 |
+
export nnUNet_raw=$RAW nnUNet_preprocessed=$PRE nnUNet_results=$RES
|
| 28 |
+
export OMP_NUM_THREADS=4 MKL_NUM_THREADS=4
|
| 29 |
+
predict_ids () {
|
| 30 |
+
local gpu=$1; shift
|
| 31 |
+
for id in "$@"; do
|
| 32 |
+
read -r ds proto < <(dsname "$id"); dn=$(rawname "$id" "$ds" "$proto")
|
| 33 |
+
for f in 0 1 2; do
|
| 34 |
+
out=$PRED/d${id}_f${f}; mkdir -p "$out"
|
| 35 |
+
echo "[predict gpu$gpu] $dn f$f"
|
| 36 |
+
CUDA_VISIBLE_DEVICES=$gpu nnUNetv2_predict -i "$RAW/$dn/imagesTs" -o "$out" \
|
| 37 |
+
-d "$id" -c 2d -f "$f" -tr "$TR" --disable_tta > "$out/predict.log" 2>&1
|
| 38 |
+
done
|
| 39 |
+
done
|
| 40 |
+
}
|
| 41 |
+
predict_ids 4 1 2 3 4 5 &
|
| 42 |
+
predict_ids 5 6 7 8 9 10 &
|
| 43 |
+
wait
|
| 44 |
+
echo PREDICT_DONE
|
| 45 |
+
|
| 46 |
+
# ---------- Phase 2: eval (seggen env), parallel, thread-capped, max 10 ----------
|
| 47 |
+
conda deactivate; conda activate seggen
|
| 48 |
+
export OMP_NUM_THREADS=8 MKL_NUM_THREADS=8 OPENBLAS_NUM_THREADS=8 NUMEXPR_NUM_THREADS=8
|
| 49 |
+
for id in 1 2 3 4 5 6 7 8 9 10; do
|
| 50 |
+
read -r ds proto < <(dsname "$id")
|
| 51 |
+
for f in 0 1 2; do
|
| 52 |
+
while (( $(jobs -rp | wc -l) >= 10 )); do wait -n; done
|
| 53 |
+
(
|
| 54 |
+
python framework/nnunet_eval.py --data_root "$DATA_ROOT" \
|
| 55 |
+
--dataset "$ds" --protocol "$proto" --raw "$RAW" \
|
| 56 |
+
--dataset_id "$id" --fold "$f" --pred_dir "$PRED/d${id}_f${f}" \
|
| 57 |
+
--arch umamba --exp_name baselines > "$PRED/d${id}_f${f}/eval.log" 2>&1
|
| 58 |
+
echo "evaled d${id}_f${f}: $(tail -1 "$PRED/d${id}_f${f}/eval.log")"
|
| 59 |
+
) &
|
| 60 |
+
done
|
| 61 |
+
done
|
| 62 |
+
wait
|
| 63 |
+
echo EVAL_DONE
|
code/scripts/umamba_preprocess.sh
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# U-Mamba preprocessing for datasets 2-10 (cvc/d1 already done) into a SEPARATE
|
| 3 |
+
# preprocessed_umamba dir (U-Mamba's nnunetv2 2.1.x plans differ from the 2.7.0
|
| 4 |
+
# nnunet env). Runs in the umamba env. Sequential + thread-capped so the planner's
|
| 5 |
+
# BLAS threads don't oversubscribe the 384-core box. Copies the 3-identical-fold
|
| 6 |
+
# splits_final.json into each preprocessed dataset afterward.
|
| 7 |
+
set -u
|
| 8 |
+
cd /home/wzhang/LSC/Code/NPJ
|
| 9 |
+
source /opt/anaconda3/etc/profile.d/conda.sh
|
| 10 |
+
conda activate umamba
|
| 11 |
+
export nnUNet_raw=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/raw
|
| 12 |
+
export nnUNet_preprocessed=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/preprocessed_umamba
|
| 13 |
+
export nnUNet_results=/home/wzhang/LSC/Code/NPJ/nnunet_workspace/results_umamba
|
| 14 |
+
export OMP_NUM_THREADS=2 MKL_NUM_THREADS=2 OPENBLAS_NUM_THREADS=2 NUMEXPR_NUM_THREADS=2
|
| 15 |
+
mkdir -p "$nnUNet_preprocessed" "$nnUNet_results"
|
| 16 |
+
LOGD=nnunet_workspace/umamba_preprocess_logs; mkdir -p "$LOGD"
|
| 17 |
+
|
| 18 |
+
dsname () {
|
| 19 |
+
case $1 in
|
| 20 |
+
2) echo Dataset002_kvasir_seg_official;;
|
| 21 |
+
3) echo Dataset003_fives_official;;
|
| 22 |
+
4) echo Dataset004_refuge2_official;;
|
| 23 |
+
5) echo Dataset005_busi_fold01;;
|
| 24 |
+
6) echo Dataset006_idridd_segmentation_fold01;;
|
| 25 |
+
7) echo Dataset007_acdc_png_official;;
|
| 26 |
+
8) echo Dataset008_pannuke_semantic_fold01;;
|
| 27 |
+
9) echo Dataset009_medsegdb_isic2018_holdout;;
|
| 28 |
+
10) echo Dataset010_medsegdb_kits19_fold01;;
|
| 29 |
+
esac
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
for id in 2 3 4 5 6 7 8 9 10; do
|
| 33 |
+
name=$(dsname "$id")
|
| 34 |
+
echo "=== preprocess d$id ($name) ==="
|
| 35 |
+
nnUNetv2_plan_and_preprocess -d "$id" -c 2d -np 16 > "$LOGD/d${id}.log" 2>&1
|
| 36 |
+
rc=$?
|
| 37 |
+
if [ -d "$nnUNet_preprocessed/$name" ]; then
|
| 38 |
+
cp "nnunet_workspace/raw/$name/splits_final.json" "$nnUNet_preprocessed/$name/splits_final.json"
|
| 39 |
+
echo "d$id rc=$rc splits_copied=$( [ -f "$nnUNet_preprocessed/$name/splits_final.json" ] && echo Y || echo N )"
|
| 40 |
+
else
|
| 41 |
+
echo "d$id rc=$rc FAILED_no_preprocessed_dir"
|
| 42 |
+
fi
|
| 43 |
+
done
|
| 44 |
+
echo UMAMBA_PREPROCESS_DONE
|