Repository navigation
feat(dynacell): Spotlight v2 arm leaves, controls and eval waves - #507
Merged
Merged
Conversation
…2 wave1c 8 buckets for the predict-only pix2pix2d_unetvit_last stores (nucleus and membrane, iPSC plus 3 A549 legs), so that GAN arm-vs-baseline compares final checkpoints on both sides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…n L1 The MixedLoss UNeXt2-2D membrane baseline is a failed fit (Dice 0.380), and the L1-only probe trains (0.889), matching segaux (0.874). So the segaux arm only showed that a seg term rescues a broken recipe as well as fixing the loss does. This adds the comparison on the recipe that trains: - l1segaux: L1 + SegAuxDice at w=0.18, calibrated on the l1 probe's best checkpoint (median ||grad base||/||grad dice|| over 20 batches, IQR 0.15-0.27; the replay matches the recorded val loss to 1.0%). - l1seed1: L1 at seed 1, as the noise floor. - The l1 probe also predicts the 3 A549 legs, as their baseline. A test pins each new arm to the l1 probe plus its own keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
t = 0.30 in the FNet-2D segaux prediction's units (a z-score of the training target): the mean-Dice optimum of (pred >= t) vs fg_mask over 20 training-store val FOVs (0.774, with 0.25-0.40 within 0.0021). No test FOV informed it. The 3D C-cond arm keeps the unparseable placeholder until its FNet-3D segaux store exists and is tuned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
31 conditions in 8 buckets: - CELL-Diff-2D segaux, seed1 and cjoint. - UNeXt2-2D nucleus segaux and seed1. - The first segauxself arms (FNet-2D and CELL-Diff-2D, nucleus). - The jointsteps probe. - The l1 probe's A549 legs, whose iPSC leg is in wave1b. All stores pass the completeness gate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
55 conditions in 8 buckets: - The 2D segauxself arms and the L1-recipe UNeXt2-2D membrane arms. - FNet-3D segaux and seed1. - The finished pix2pix3d and CELL-Diff-3D test legs. - The CELL-Diff-2D C-cond arm. wave1 keeps only the legs still predicting, plus the not-yet-predicted UNeXt2-3D and 3D C-cond arms, narrowed per leg so that no condition sits in two waves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
t = 0.40, in the FNet-3D segaux prediction's units (a z-score of the training target). It is the mean-Dice optimum of (GT target >= t) vs fg_mask over 20 training-store val FOVs x 44 planes: 0.699, with 0.30-0.50 within 0.004. A CPU forward of FNet-3D over val FOVs takes about 57 min per FOV, so the prediction-based optimum (0.10 above the GT one in 2D) is unmeasured for 3D. No test FOV informed the choice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
3 conditions (segaux zikv; v2 mock and denv) that finished after wave2a; removed from wave1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
Most arm effects in the v2 readouts are A549-transfer effects, e.g.
FNet-3D nucleus segaux Dice +0.40 and membrane -0.38. The seed
replicates were iPSC-only, so those effects had no noise floor. The
FNet-3D baseline store also predates this pipeline (April, provenance
unknown), and its seed replicate checks it on A549. This adds 30
predict leaves: seed1 x {fnet2d, UNeXt2-2D, pix2pix2d, CELL-Diff-2D} x 2
organelles, FNet-3D nucleus seed1 and UNeXt2-2D l1seed1, each x 3 A549
legs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
A fixed threshold tuned on iPSC does not transfer. FNet's A549 predictions sit on a different intensity scale: FNet-2D segaux has a median of about +1.2 and p99 of about +18, against +0.04 / +2.1 on iPSC. t = 0.30 therefore marked 96-97% of A549 pixels foreground, and C-cond A549 Dice fell by 0.30. threshold="otsu" thresholds each window at its own Otsu level; a constant window gives an all-background mask. On the 20 iPSC val FOVs its Dice vs fg_mask is 0.769, against 0.774 for the tuned t=0.30. The float path is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
The fixed thresholds (2D 0.30, 3D 0.40) were tuned on iPSC and conditioned CELL-Diff on near-all-foreground masks on A549. All 8 C-cond predict leaves now use threshold="otsu", so the arm has one label-free definition on every test leg. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…re-predict Its wave2a scores used the fixed t=0.30 mask. They are kept aside as <leg>.fixed_t030 in the v2 root, and the arm returns to wave1 until the Otsu predicts finish. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
… v2 as wave2c The seed1 A549 predicts give the A549 run-to-run noise floor that the arm-vs-baseline deltas are judged against; fnet3d_paper_seed1 also checks whether the April FNet-3D baseline store is representative. The fresh UNeXt2-3D membrane baseline moves out of the still-pending wave1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…ix2pix3d v2 On A549 the two FNet baseline draws differ by up to 0.39 Dice, so an arm effect only counts when it holds against both baseline draws, and every arm and the pix2pix3d v2 baseline so far rest on one run. A `<suffix>_seed1` arm re-draws its source arm with seed_everything: 1 and nothing else: fnet2d_segaux_seed1 (nucleus+membrane), fnet3d_paper_segaux_seed1 (nucleus) and pix2pix3d_unetvit_v2_seed1 (nucleus+membrane), each with its 4 predicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
PAPER_KEY, the grouped generator's token map, _DETERMINISTIC_MODELS and the Spotlight arm skip set gain fnet2d_segaux_seed1, fnet3d_paper_segaux_seed1 and pix2pix3d_unetvit_v2_seed1, so their stores score under their own keys and stay out of the canonical buckets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
… wave2d Both fits finished at ep199/200; predicts are from --ckpt best (segaux ep95, v2 ep81, read from each last.ckpt's best_k_models). They move out of the still-pending wave1 so they do not wait on the CELL-Diff-3D legs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…rane segauxself ZIKV as wave2e The CELL-Diff-2D and -3D C-cond iPSC predicts and the CELL-Diff-2D membrane segauxself ZIKV predict finished; score them now instead of waiting on the rest of wave1. wave1 keeps only the C-cond A549 legs, so no condition is scored in two waves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…aseline wave2d scored the UNeXt2-3D nucleus segaux arm against its v2 baseline: on the three A549 legs instance Dice +0.029..+0.047 and PCC -0.020..-0.025, bootstrap CIs excluding 0. The plan drew this baseline a second time only if that verdict came back non-null, because on A549 a single draw has proved unreliable (the FNet baseline draws differ by up to 0.39 Dice). The replicate differs from the v2 leaf only in names and seed_everything: 1, and keeps the 7-day 4-GPU wall. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…l token PAPER_KEY, the grouped generator's token map, _DETERMINISTIC_MODELS and the Spotlight arm skip set gain fcmae_vscyto3d_scratch_v2_seed1 (unext2_v2_seed1), so its stores score under their own key and stay out of the canonical buckets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
FNet-3D nucleus is the one Spotlight v2 cell whose A549 effect held against both baseline draws (Dice +0.21..+0.44, mAP +0.15..+0.22 at the calibrated w=1.9), so it is the first Stage 2 ablation: the segaux arm at 0.5x and 2x seg_aux_weight (0.95, 3.8), nothing else changed. The test pins that each sweep leaf equals the segaux arm's up to names and the scaled weight. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…tokens PAPER_KEY, the grouped generator's token map, _DETERMINISTIC_MODELS and the Spotlight arm skip set gain fnet3d_paper_segaux_halfw and fnet3d_paper_segaux_doublew, so their stores score under their own keys and stay out of the canonical buckets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…s eval model tokens PAPER_KEY, the grouped generator's token map, _DETERMINISTIC_MODELS and the Spotlight arm skip set gain fnet3d_paper_histmatch, pix2pix3d_unetvit_v2_histmatch and fcmae_vscyto3d_scratch_v2_histmatch: each 3D nucleus v2 baseline's A549 prediction histogram-matched per volume to its segaux arm, the control that tells a cosmetic intensity effect on the segmenter from a structural one. Without the keys the stores would collapse onto their baselines by longest prefix. They have no training leaf, so the tests pin them as a separate controls set next to the leaf generator's arms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
Scores the FNet-2D segaux second draw (nucleus and membrane, all four legs) and the UNeXt2-3D membrane segaux arm (fit ep199/200, predicted from --ckpt best ep125). The membrane segaux arm moves out of wave1 so each (organelle, model, leg) stays in exactly one wave. 12 conditions, 8 buckets; the store gate passed on all 12. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…oster wave ctrl1 On A549 the 3D nucleus segaux arms beat their baselines on instance Dice and mAP while PCC drops and semantic Dice barely moves, which an intensity-only change the segmenter prefers could also produce. ctrl1 scores each v2 baseline (FNet-3D, pix2pix3d, UNeXt2-3D) with its segaux arm's per-volume intensity histogram imposed and its spatial structure kept, on the three A549 legs. If the matched baselines recover most of the gain, the effect is cosmetic. The stores sit outside the canonical grammar, so the entries give pred_paths; the three generated buckets hold three conditions each. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…baseline The UNeXt2-3D membrane segaux arm came back non-null in wave2f and, unlike every other family, improves in-domain on every metric: iPSC mAP +0.128, instance Dice +0.099, PCC +0.027, SI_SSIM +0.034, CellDINO KID -3.2 (bootstrap CIs exclude 0). That is a single baseline draw, and on A549 the FNet baselines' two draws differ by up to 0.39 Dice, so the membrane v2 baseline gets its seed_everything: 1 replicate, as nucleus already has. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
The v2_seed1 fit leaves (nucleus and membrane) take the long 4-GPU wall from generate_spotlight_v2_leaves.LONG_WALL_MODELS, but the allow-list in test_only_measured_slow_fits_get_the_long_wall only named the v2 and segaux leaves, so both failed. A second draw is the same recipe with seed_everything: 1, so the measured ~2.0 ep/h (~100 h for 200 epochs) applies unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
The UNeXt2-3D membrane segaux arm is the only one that improves every in-domain metric (wave2f: iPSC mAP +0.128, instance Dice +0.099, PCC +0.027, SI_SSIM +0.034, KID -3.2; A549 Dice +0.12..+0.18). With the v2_seed1 baseline draw already queued, a seed_everything: 1 draw of the arm completes the 2x2 (arm draw x baseline draw) that the A549 verdict needs: on A549 the FNet-2D arm's two draws disagreed (nucleus Dice +0.15..+0.20 vs +0.01..+0.02 over the same baseline). Registers the unext2_segaux_seed1 eval token and puts the leaf on the 7-day wall with the rest of the UNeXt2-3D fits (same measured recipe). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
Brings in the eval standardization fixes (#499 GT-fit CP feature space, #500 float32 CP min/max, #501 CP z-clip at +/-20), the MicroMS3IM calibration fixes (#502, #506), the cubic 0.9.0a2 pin (#503), the 40-48 GB eval GPU constraint (#504) and the Cytoland checkpoint-dir fix. No conflicts; paths.py auto-merged. dynacell tools + test_paths + test_benchmark_config_composition pass on the merged tree (2677). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
Contributor
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The changes require final human review because they are too complex or risky for automated approval.
Review effort: Balanced
Findings: None
What changed in this PR
This PR adds Spotlight v2 experiment recipes and isolated evaluation waves to compare segmentation-aware training arms with their corresponding baselines across model families.
Changes:
- Adds seed replicates, loss-weight sweeps, and generated fit and prediction leaves.
- Adds Otsu-based C-cond masks and histogram-matched evaluation controls.
- Registers model tokens and routes Spotlight evaluations outside the canonical paper-output directories.
| File | Description |
|---|---|
| applications/dynacell/tools/generate_grouped_eval_configs_test.py | Updated as part of this pull request. |
| applications/dynacell/tests/test_paths.py | Updated as part of this pull request. |
| applications/dynacell/tests/test_benchmark_config_composition.py | Updated as part of this pull request. |
| applications/dynacell/src/dynacell/mask_conditioning.py | Updated as part of this pull request. |
| applications/dynacell/src/dynacell/evaluation/paths.py | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/pix2pix3d_unetvit_v2_seed1/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/pix2pix3d_unetvit_v2_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/pix2pix3d_unetvit_v2_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/pix2pix2d_unetvit_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/pix2pix2d_unetvit_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/pix2pix2d_unetvit_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_seed1/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_halfw/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_halfw/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_halfw/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_halfw/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_doublew/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_doublew/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_doublew/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_segaux_doublew/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet3d_paper_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet2d_segaux_seed1/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet2d_segaux_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet2d_segaux_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet2d_segaux_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet2d_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet2d_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fnet2d_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fcmae_vscyto3d_scratch_v2_seed1/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fcmae_vscyto3d_scratch_v2_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fcmae_vscyto2d_scratch_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fcmae_vscyto2d_scratch_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/fcmae_vscyto2d_scratch_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/celldiff_ccond/ipsc_confocal/predict__ipsc_confocal__iterative.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/celldiff_ccond/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/celldiff_ccond/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/celldiff_ccond/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/celldiff_2d_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/celldiff_2d_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/celldiff_2d_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/celldiff_2d_ccond/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/celldiff_2d_ccond/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/celldiff_2d_ccond/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/nucleus/celldiff_2d_ccond/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/pix2pix3d_unetvit_v2_seed1/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/pix2pix3d_unetvit_v2_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/pix2pix2d_unetvit_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/pix2pix2d_unetvit_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/pix2pix2d_unetvit_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fnet2d_segaux_seed1/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fnet2d_segaux_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fnet2d_segaux_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fnet2d_segaux_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fnet2d_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fnet2d_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fnet2d_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto3d_scratch_v2_seed1/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto3d_scratch_segaux_seed1/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto2d_scratch_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto2d_scratch_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto2d_scratch_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto2d_scratch_l1segaux/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto2d_scratch_l1segaux/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto2d_scratch_l1seed1/ipsc_confocal/predict__ipsc_confocal.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto2d_scratch_l1seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto2d_scratch_l1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto2d_scratch_l1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/fcmae_vscyto2d_scratch_l1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/celldiff_2d_seed1/ipsc_confocal/predict__a549_mantis_zikv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/celldiff_2d_seed1/ipsc_confocal/predict__a549_mantis_mock.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/membrane/celldiff_2d_seed1/ipsc_confocal/predict__a549_mantis_denv.yml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_ipsc__wave2f/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_ipsc__wave2e/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_ipsc__wave2d/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_ipsc__wave1c/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_a549_zikv__wave2f/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_a549_zikv__wave2b/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_a549_zikv__wave1c/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_a549_mock__wave2f/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_a549_mock__wave2b/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_a549_mock__wave1c/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_a549_denv__wave2f/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_a549_denv__wave2b/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_nucleus_a549_denv__wave1c/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_membrane_ipsc__wave2f/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_membrane_ipsc__wave2c/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_membrane_ipsc__wave1c/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_membrane_a549_zikv__wave2e/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_membrane_a549_zikv__wave1c/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_membrane_a549_mock__wave1c/eval_grouped.yaml | Updated as part of this pull request. |
| applications/dynacell/configs/benchmarks/virtual_staining/_internal/leaf/grouped/spotlight_v2_membrane_a549_denv__wave1c/eval_grouped.yaml | Updated as part of this pull request. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…copying them Generated leaves are byte-identical (282 leaves, 0 written). Three things change inside the generator: - The C-cond threshold placeholder and the comment `_render` spliced in were dead once "otsu" replaced the val-tuned value (0 of 282 leaves matched). CCOND_THRESHOLDS held "otsu" for both baselines, so it is now the single constant CCOND_THRESHOLD. - l1segaux and l1seed1 re-wrote the segaux and seed deltas inline. They now compose l1 with segaux (at the l1-calibrated weight) and go through the second-draw path. SEED_SOURCES replaces the `_seed1` suffix rule so l1seed1, which has no underscore, can use it. - A second draw inherits its source arm's 7-day wall through `_long_wall` instead of being listed in LONG_WALL_MODELS by hand. Found by /simplify on PR #507. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…erator tests Seven tests each called build_leaves() (~6-8 s per call, 282 leaves). They only read the result, so a module-scoped fixture generates it once: the file went from 150 s to 121 s wall (one run each). The weight-sweep test compares against _FIT_RENAMES instead of an inline copy, and the count test's docstring no longer claims the seed replicates are iPSC-only (seed1 and l1 predict the A549 legs too). Found by /simplify on PR #507. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…rator's ARMS
_SPOTLIGHT_ARM_MODELS listed every v2 arm by hand, and a test asserted it
equalled the v1 arms, the histmatch controls and {arm.model for arm in
ARMS}. The skip list is now built from exactly that expression, so a new
arm is skipped without a sixth registration edit, and the test that only
restated the definition is gone. test_walk_predictions_skips_spotlight_arms
still checks the skip behaviour. generate_spotlight_v2_leaves imports only
the standard library and yaml, so the sibling import adds no cycle.
Found by /simplify on PR #507.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
The wave2b and wave2c comments sat above wave2f, leaving both blocks uncommented, and the wave1 note still described seed replicates and recipe probes that moved to later waves. Comments only: the parsed roster is identical. Found by /simplify on PR #507. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…g it out HCSPredictionWriter zero-fills its store (create_zeros), so an unwritten mask-source window reads back as constant 0.0, not NaN, and the NaN check never fired. The Otsu path then returned an all-background mask for it, and a float threshold did the same, so C-cond would condition on "no nuclei" without an error. A real prediction window is never exactly constant, so CondMaskSource.read now raises on any constant window, whatever the threshold. The test covers an unwritten window under both thresholds, next to a written one that still reads. Found by internal review of PR #507. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…tor docstring The module docstring still said the ccond predict leaves carry a string PLACEHOLDER threshold that fails at parse; they read `threshold: otsu`. Found by internal review of PR #507. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…aw that exists The allow-list crossed both organelles with segaux_seed1, which also named nucleus/fcmae_vscyto3d_scratch_segaux_seed1, a leaf the generator never emits. The list's rule is that only measured slow fits get the long wall, so a phantom entry would quietly grant it to any leaf later created under that name. segaux_seed1 is now listed for membrane only. Found by internal review of PR #507. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
…ding C-cond windows A partly written FNet mask window mixes predicted values with the writer's zero fill. It is not constant, so the constant-window guard missed it, and Otsu then treated the unwritten zeros as background. No pixel test can tell such a window from a finished one. CondMaskSource.read now refuses any position whose channel lacks the writer's completion marker (viscy_prediction_complete with a source_shape). That covers unwritten, partly written and pre-marker stores. The constant-window check stays only where it means something: Otsu has no split on a constant window. All 272 positions of the eight live C-cond mask sources (fnet2d_segaux, fnet3d_paper_segaux x 4 legs) carry a complete marker whose source TYX matches the array, so no current C-cond input is refused. Addresses the Copilot review of PR #507. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
Scores the CELL-Diff A549 nucleus legs that finished after wave2f: the CELL-Diff-2D C-cond arm re-predicted with the Otsu threshold (all three legs), the CELL-Diff-3D segaux MOCK/ZIKV legs and the first CELL-Diff-2D seed1 A549 leg. wave1 now lists exactly the 17 CELL-Diff A549 legs still predicting, including the CELL-Diff-2D seed1 and membrane segauxself legs it had not tracked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Follow-up to #498 (the
SegAuxDiceloss and its engine hooks). This branch holds the Spotlight v2 experiment configs: which arms get trained, how they are predicted, and how their predictions are scored against each family's own baseline. The question it answers is whether adding a segmentation-aware auxiliary loss improves a family over the same model trained without it. It covers FNet, UNeXt2 (from scratch), pix2pix and CELL-Diff, in 2D and 3D.What's in it
Code (10 non-config files, +455/-45)
mask_conditioning.CondMaskSourcegainsthreshold="otsu". It thresholds each predict window at the Otsu value of its own voxels, so a C-cond mask survives an intensity-scale shift between iPSC and A549. The fixed float threshold tuned on iPSC marked 96-97% of A549 voxels as foreground. A constant window gives an all-background mask. Three tests intest_training_integration.pycover this, including an affinely rescaled store where the float threshold fails and Otsu does not.tools/generate_spotlight_v2_leaves.pygenerates every arm's fit and predict leaves from its baseline leaf in one pass, so an arm and its control share one recipe by construction. The arms are:segaux,segauxself,cjoint/ccond, the UNeXt2-2Dl1*rebuild, andlast(predict-only) armsseed1,segaux_seed1andv2_seed1second drawssegaux_halfwx0.5,segaux_doublewx2)Its test pins the leaf counts (56 fits / 226 predicts). It also pins that each derived arm differs from its source only by the intended keys: seed, weight scale or renames.
tools/spotlight_v2_eval_roster.yamlandgenerate_spotlight_v2_eval_configs.pyhold the eval waves (wave1*,wave2a-wave2f) andctrl1.ctrl1is a cosmetic-vs-structural control: each 3D nucleus baseline's A549 prediction histogram-matched per volume to its segaux arm's. Each (organelle, model, leg) appears in exactly one wave. A store gate refuses absent or partial prediction stores.evaluation/paths.pyandtools/generate_grouped_eval_configs.pyregister the new model tokens.test_only_measured_slow_fits_get_the_long_wallallows the 7-day wall for the UNeXt2-3Dv2_seed1/segaux_seed1draws. They are the same recipe as the measuredv2/segauxfits (~2.0 ep/h, ~100 h for 200 epochs).Configs (149 files): generated fit/predict leaves under
configs/benchmarks/virtual_staining/{nucleus,membrane}/and grouped eval buckets under_internal/leaf/grouped/spotlight_v2_*. Every one is regenerable from the two generators above. Eval outputs go to a separate root (.../_spotlight_v2), never the canonical dirs the paper tables read.Merge:
dynacell-models@ c39d59f merged in (f1a0245, no conflicts). It brings #499-#504 and #506, so evals launched from this branch now need thecpdino-eval-cubic090a2venv (therun_eval_direct.slurmdefault).Testing
On 03249b6 (tools/paths/config suites were last run on 9cad49e; 03249b6 only touches
mask_conditioning.pyand its test), against the workspace.venvwith the worktree'ssrcdirs onPYTHONPATH:applications/dynacell/tools/+tests/test_paths.py+tests/test_benchmark_config_composition.py: 2676 passed, 0 failedtests/test_training_integration.py -k "cond or mask or seg_aux or segaux": 32 passed, 0 failedgenerate_spotlight_v2_leaves.py: 282 leaves, 0 written. The simplify and review commits leave every generated leaf byte-identical.Review follow-ups
/simplify:l1segaux/l1seed1composel1, second draws come from aSEED_SOURCESmap, and their long wall is derived._SPOTLIGHT_ARM_MODELSis derived fromARMS.CondMaskSourcerefuses to read unwritten mask windows. The writer zero-fills, so such a window read back as 0.0 and C-cond conditioned silently on an empty mask.segaux_seed1leaf that does not exist.CondMaskSourcenow requires the writer's per-channel completion marker instead (03249b6). All 272 positions of the 8 live C-cond mask sources carry that marker.Notes for review
applications/dynacell/experiments/2026-09-24_spotlight-v2/and are not part of this PR._seed1and sweep leaves exist because of a measured noise floor. On A549 the two FNet baseline draws differ by up to 0.39 Dice, so an arm effect only counts when it has the same sign against both baseline draws.🤖 Generated with Claude Code
https://claude.ai/code/session_01Gwn9hwgT8uJSoWaCxCAm8J