Commit 96ba900
Brain extraction overhaul: SynthStrip primary + BET hardening + posterior-fossa QC (#111)
* Brain extraction overhaul: SynthStrip primary + BET hardening + posterior-fossa QC
Bring brain extraction in line with 2020-2025 best practice, prioritizing
brainstem/posterior-fossa preservation. The previous primary path was a
template-free Otsu heuristic with a bare `bet -m -f 0.5` fallback and no
anatomical prior - the worst choice for a brainstem/pons study (BET clips the
cerebellum/brainstem).
Changes:
- Add SynthStrip (FreeSurfer mri_synthstrip) as the PRIMARY method. Contrast-
agnostic, works directly on T1/FLAIR/SWI/DWI with no template mismatch.
- New config BRAIN_EXTRACTION_METHOD (synthstrip|ants|bet, default synthstrip)
with an ordered, graceful fallback chain (synthstrip -> ants -> bet); missing
or failing tools degrade to the next available method, never hard-crash.
- Harden the BET fallback: robustfov neck removal for large-FOV sagittal 3D
inputs, `-R` robust centre estimation + `-c` centre-of-gravity when available,
and modality-specific `-f` (BET_F_T1=0.3, BET_F_FLAIR=0.2).
- Add a non-fatal posterior-fossa QC gate that warns when the brain mask looks
like it clipped the cerebellum/brainstem (inferior-slab voxel fraction vs
BRAIN_QC_INFERIOR_FRACTION).
- Soften the ANTs Otsu-path morphological open from radius 4 to a config-driven
BRAIN_MASK_MORPH_RADIUS (default 1) to avoid severing the brainstem->cord
taper / rounding off the pons.
The perform_brain_extraction() signature and output naming
(<prefix>BrainExtractionBrain.nii.gz / <prefix>BrainExtractionMask.nii.gz) are
unchanged, so preprocess.sh and pipeline.sh stage 3 are unaffected.
Follow-ups (out of scope): mask propagation (extract once on T1, warp mask to
FLAIR); the analysis.sh antsBrainExtraction path uses an MNI152-T1 binary mask
on FLAIR (a misconfiguration worth fixing separately).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Generalize robustfov to a shared pre-extraction FOV-normalization step
robustfov neck/FOV removal previously only ran inside the BET fallback, so
with SynthStrip as the primary method it almost never fired - losing its
benefit exactly on the large-FOV sagittal 3D inputs (T1_MPRAGE_SAG /
T2_SPACE_FLAIR_Sag) it was meant to help.
Make robustfov a shared, optional pre-extraction step that benefits ALL
methods (synthstrip/ants/bet) without changing the native geometry of the
final outputs:
- Add should_run_fov_crop() (gated by BRAIN_EXTRACTION_ROBUSTFOV plus an
optional BRAIN_EXTRACTION_ROBUSTFOV_MIN_Z_MM superior-inferior FOV
heuristic), compute_fov_cropped_for_extraction() (runs robustfov, emits
cropped image + ROI->full affine), and map_mask_to_original_grid() (maps
the cropped-space mask back onto the original grid and rebuilds the brain
in native space).
- perform_brain_extraction() now optionally crops, runs the chosen method on
the cropped image, then maps the mask back to the ORIGINAL native space and
geometry. If mapping fails it re-extracts on the original image. Signature
and output naming are unchanged.
- The mask is resampled with the ROI->full affine DIRECTLY (robustfov's -m is
"roi to full fov"); empirically this preserves the mask voxel count exactly
while the inverse shifts it ~1 voxel and drops voxels.
- Factor the synthstrip/ants/bet dispatch into a single run_extraction_chain()
used by both the cropped and original-image paths (no duplicated switch).
- Add verify_mask_alignment() (dim + non-empty sanity check) after mapping.
- Remove the now-redundant inline robustfov from brain_extraction_bet() so we
never double-crop; BET keeps its -R + centre-of-gravity behavior.
- New config vars documented in config/default_config.sh near the other
extraction settings. robustfov-absent path degrades gracefully (non-fatal
skip, extract on original).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>1 parent 675c26a commit 96ba900
3 files changed
Lines changed: 627 additions & 98 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
351 | 351 | | |
352 | 352 | | |
353 | 353 | | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
354 | 405 | | |
355 | 406 | | |
356 | 407 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
844 | 844 | | |
845 | 845 | | |
846 | 846 | | |
847 | | - | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
848 | 850 | | |
849 | 851 | | |
850 | 852 | | |
| |||
0 commit comments