Mayo-LDCT rebuild plan (2026-06-14)

The old Mayo leaderboard was discarded (scored with the bg→0 calibration bug, on a slice subset, before the v3 geometry + truncation-corrected FBP path was hard-wired). This is the plan to rebuild it correctly. Nothing below is executed until the user approves the plan.

Guiding constraints (from the user):


The frozen production path (what “hard-wired” means)

Stage Setting Source of truth
SSR rebin geometry v3 + s_z=1.001665 MAYO_LDCT_SSR_DEFAULTS
staged sinos staged_helix2fan_v3 STAGED_HELIX2FAN_SUBDIR
FBP geometry Powell sod=595.362 / sdd=1086.803 / ps=0.700857 / du=1.285044 FanBeamGeometry.mayo_ldct_fitted()
detector offset −0.0397 mm MAYO_LDCT_DET_OFFSET
truncation water-cylinder, pad=384 MAYO_LDCT_TRUNCATION
per-patient FOV ps_eff = 0.700857·truth_ps/0.703125 truth DICOM PixelSpacing
calibration two-point affine, bg_target="truth" evaluate_calibrated(..., bg_target="truth")

Phase 0 — HD vs LD FBP baseline (all slices) — in progress

scripts/compare_hd_ld_fbp_allslices.py reconstructs every truth slice of all 10 Wagner patients, both doses, on the frozen path, and scores calibrated SSIM/PSNR. This defines the headroom endpoints: score = (metric − LD_FBP) / (HD_FBP − LD_FBP) per split.

Outputs (→ results/mayo_debug/allslices_hd_ld/): per-split oracle/baseline table, per-patient SSIM-vs-z curves, per-patient representative-slice montages (GT | HD | LD | diff), and a summary box/bar figure. These become the baseline rows + first images of the new leaderboard.

Phase 1 — Hard-wire the path into the training/eval pipeline

Audit (2026-06-14) found two gaps that made old results spurious:

  1. scripts/learned_solver_search_agent.py scores Mayo with the default bg_target=None (bg→0). Fix: route all Mayo calibrated scoring through bg_target="truth".
  2. Solver FBP projectors don’t carry det_offset_mm + truncation. Fix: build the Mayo solver projector with MAYO_LDCT_DET_OFFSET + MAYO_LDCT_TRUNCATION (already productionised in PyronnFanBeamProjector).

ddssl_ldct/staged_dataset.py already uses the Powell FBP geometry + staged_helix2fan_v3 (verified). Add a single assertion/log at startup that prints the active geometry + calibration so no run can drift silently.

Phase 2 — All-slices Wagner dataset + evaluator

Phase 3 — Adjust agentic loop; TPE honours all-slices

Orchestration model: Opus 4.8 (1M context) (claude-opus-4-8[1m]), chosen 2026-06-14. The loop has no LLM baked into the cluster jobs — the driving Claude Code session reads results, writes the next per-iter CFG_JSON, decides keep/discard, and dispatches the next sbatch. The cluster does all the heavy compute, so the LLM cost is only the short orchestration turns. TPE/Optuna search is LLM-free. An autonomous continuation (scheduled agent / /loop) must be launched with Opus 4.8.

Phase 4 — Repopulate leaderboard + dashboard with images

Phase 5 — Re-run the solver inventory (the science)

Re-run solvers on the corrected all-slices path via TPE, in priority order (former front-runners first: LPD, DD-UNet supervised, USwin, ItNet, diff_recon DCstep; then the rest). Populate leaderboard rows + dashboard cards as each lands. Absolute SSIM rises vs the old numbers (corrected calibration); headroom is recomputed against the new HD/LD endpoints, so it is NOT comparable to the discarded headroom values.


Open decisions for the user

  1. Leaderboard reference image: fixed slice (e.g. L277 central) + a per-patient montage? Or a different reference?
  2. Solver scope first pass: re-run the full 19-solver inventory, or a prioritised shortlist (top ~6) to repopulate quickly, then backfill?
  3. Agentic train-subset size: how many slices per fast iteration (e.g. 200 stratified) — trade iteration speed vs. signal.