Add edema and swim bladder segmentation and align the model presets with the webapp - #5
Merged
MarkDanielArndt merged 12 commits intoJul 30, 2026
Conversation
Also refreshes general/DESY body and eye models to the webapp's current 512px checkpoints (issue #109), found while verifying model provenance for this feature.
Corrects an oversight in the earlier body/eye model refresh (#109): best_model_body_3400_vgg19.pth was mistaken for a stale legacy file and simply replaced, when it is actually the webapp's own current, still-offered Fast & Easy preset — the only one that runs at 256px instead of 512px, useful for users without a fast local GPU.
The webapp's preset table lists None for some eye/edema/swim bladder filenames, which means "use the pipeline default" — not "unavailable". Reading it as the latter wrongly gated edema to DESY and stripped Fast & Easy down to body-only. All three presets now carry all five roles, differing only in weights, input resolution and — for Fast & Easy's swim bladder — architecture (Unet + vgg16 instead of FPN + vgg19). Verified against both the live Hugging Face Space and the webapp's GitHub repo, which are identical.
The combo box called the 512px preset "General Model" while the webapp calls it "Complex & Slower" — the same preset under two names across the two tools. Labels are now verbatim; the stable ids stay untouched because saved scenes carry them. Model labels in the download dialog gain the matching preset name, so it is visible which selection pulled which file.
The model repo has a 256px edema model and a 512px DESY one, but no 512px general counterpart. The webapp fills that gap by falling through to its pipeline default, feeding a 256px-trained net 512px input. Rather than reproduce that, the "general" preset drops the role: the checkbox greys out with a hint naming the presets that do offer it, and an inconsistent request (a scene saved while it was still offered) raises an actionable error instead of a bare KeyError or a silently empty column.
CORE_SOURCE.md existed only on the superseded webapp-parity branch, so this branch ported compute_tube_metrics without updating the table that exists to keep the next manual re-sync a diff rather than an excavation. Its length.py row even predicted this port as still outstanding. Recovered and brought up to date: the newly ported function, the seg.py re-sync, the model preset table the manifest mirrors, and the one deliberate deviation from the webapp with its rollback condition.
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.
Summary
Brings the extension's segmentation options in line with the reference webapp: edema and swim bladder segmentation, the three model presets the webapp actually offers, and the current model weights.
Depends on #4. Both branches target
main, so until #4 merges the commit list here also contains its five commits. The six commits above8dc98e1are the ones belonging to this change; the diff shrinks to those on its own once #4 lands.What is in here
Edema segmentation — manifest entry, checkbox, subprocess plumbing, an
Edemasegment in the MRML scene with anEdemaArea_um2column, an overlay colour, and Excel/CSV export.Swim bladder segmentation — the same end-to-end wiring, plus two things it does not share with the other roles. It uses FPN rather than Unet, so the model loader gained a
model_typeparameter; and its measurements come fromcompute_tube_metrics(), ported near-verbatim from the webapp, which fits a minimum-area rotated rectangle so the reported width is the tube's cross-section regardless of how it sits in the frame.Three presets instead of two —
Fast & Easy (256 px),Complex & Slower (512 px)andFine-tuned DESY, named exactly as the webapp names them. Input resolution is now per preset rather than a single global default.Current model weights — the general and DESY body/eye entries still pointed at 256px-era files that the webapp had already replaced with 512px ones. All refreshed, with checksums and revisions computed from the actual downloaded files rather than copied.
Two things that were wrong on the way here
Edema is not DESY-only. The work started from the assumption that the webapp offers edema only on its DESY preset, because the preset table lists
Nonefor the others. The comment directly above that table reads "None for eye/edema/swimbladder filenames means use the pipeline default" —Noneselects the default file, it does not disable the feature, and the call site confirms it by passing an empty kwargs dict.best_model_body_3400_vgg19.pthis not a legacy file. It was initially replaced as stale during the weight refresh. It is the webapp's current Fast & Easy preset — the only one running at 256px, which matters for anyone without a fast local GPU, where 512px inference is noticeably slower.Both were caught by checking the live Hugging Face Space against the webapp's own repository; the two sources are byte-identical for
app.pyandseg.py.One deliberate deviation from the webapp
Edema is offered on Fast & Easy and DESY, but not on Complex & Slower, where the checkbox greys out with a hint naming the presets that do offer it.
The model repository has a 256px edema model and a 512px DESY one, but no 512px general counterpart. The webapp fills that gap by falling back to the 256px model and feeding it 512px input. That runs without error and produces a plausible-looking number, which is the failure mode worth avoiding — a wrong measurement is worse than an unavailable one. The rule is now "offer the role where a resolution-matched model exists"; if a 512px general edema model appears, wiring it in re-enables the checkbox with no other change.
An inconsistent request — for example a scene saved while the role was still offered — raises an actionable error rather than a bare
KeyErroror a silently empty column.Verification
pytest tests/— 594 passed.Beyond the wiring, the tests pin the two mistakes that are invisible at runtime: an FPN checkpoint loaded into a Unet, and a 512px-trained net fed 256px input, both complete without raising and simply produce meaningless masks. A parametrised test asserts each preset reaches the segmentation pipeline with both its own resolution and its own architecture. Another fails on any manifest entry reachable from no preset — the shape that let the edema entry be mistaken for dead weight in the first place.
Manually verified in Slicer across the presets, including the new segments appearing in the Segment Editor and surviving a scene save and reload.