GenMI-Lab logo GenMI-LabMBZUAI

SCALA

SCALA: Semi-supervised Cascade for Left Atrial Scar, Cavity, and Multi-Structure CT Segmentation

Atharva Atul RegeAdinath Madhavrao DukreSarth Santosh ShahImran Razzak

Three tasks, one recipe, no shared weights.
Find the atrium first, then the scar.
Pseudo-label the unlabeled scans.

CARE 2026 MICCAI LeftAtrium

01 / ABSTRACT

Abstract

Segmenting left atrial structures remains challenging on both magnetic resonance imaging and computed tomography: atrial scar is small and wall-adherent, LGE-MRI intensity carries no absolute scale, acquisition varies between centers, and thin pulmonary veins dominate boundary-based metrics. We introduce SCALA, a semi-supervised cascade for the three tasks of the MICCAI 2026 CARE LeftAtrium challenge, covering atrial scar quantification on LGE-MRI, left atrial cavity segmentation, and multi-structure cardiac CT segmentation. Three task-specific residual-encoder nnU-Net models share one training recipe and one deployment pipeline but no parameters, and are never trained jointly. For scar, an out-of-fold cavity prediction supplies anatomical localization and two derived channels, an intensity ratio normalized by the blood pool and a signed distance to the endocardial surface. We exploit the nested annotation structure through self-training and ensemble complementary members, then convert probability into the reported metric with structure-specific decision rules, an on-wall component filter for scar and a double-threshold vein hysteresis for CT. A residual acquisition-grid mismatch is corrected by sub-slice offset voting fixed by the spacing ratio. Cross-validation gives surface scar Dice 0.722, cavity Dice 0.925 and CT mean Dice 0.961, while the hidden test sets return generalized Dice (G-DSC) 0.363 for scar and Dice 0.830 and 0.954 for cavity and CT.

Figure 1
Figure 1. Overview. One recipe is instantiated three times and trained separately; the only path between tasks is the out-of-fold cavity prediction conditioning the scar model. Image panels are real slices, the 3D shapes and icons schematic.

02 / METHOD

Method

SCALA uses three task-specific residual-encoder nnU-Net pipelines. They share one training recipe and one deployment path but no parameters.

03 / RESULTS

Results

Scar (Task 1) Cavity (Task 2) CT (Task 3)
5-fold cross-validation surface Dice 0.722 Dice 0.925 mean Dice 0.961
Hidden test set (organizers) G-DSC 0.363 Dice 0.830, HD 22.55 mm Dice 0.954, HD 9.33 mm

From the paper

Table 1. LA scar, surface metrics over the 60 out-of-fold cases, means with the standard deviation of the five per-fold means. Best per column in bold. The first four rows use nnU-Net’s default 0.5 threshold, so the operating point is its own step.
Table 1
Figure 2
Figure 2. (a) Dice contributed by each component against the configuration above it, with each task’s baseline and deployed score in the legend; gains are additive up to rounding, and a component measured at zero is labelled rather than left blank, vein hysteresis being an HD95-only intervention. (b) Surface scar Dice against decision threshold on 15 out-of-fold cases: the evaluation grid costs 0.022 at the deployed threshold and offset voting returns 0.014.
Figure 3
Figure 3. Manual annotation (top) and deployed prediction (bottom) on the best-scoring case of each task, reconstructed from the out-of-fold probabilities; the teal contour on the scar panels is the out-of-fold cavity.

04 / CODE

Code and usage

Installation
git clone https://github.com/adinathdukre/SCALA.git
cd SCALA
pip install -e .
Note

Tested with nnU-Net v2.8.0 and dynamic_network_architectures 0.4.4; PyTorch 2.12 for training and PyTorch 2.8 in the Docker image.

Custom trainers are loaded through nnU-Net's nnUNet_extTrainer hook, so the nnU-Net installation is never modified. scripts/env.sh sets this variable and the nnU-Net paths. Edit the /path/to/... defaults in it, or export SCALA_DATA, SCALA_WORK, nnUNet_raw, nnUNet_preprocessed and nnUNet_results first:

source scripts/env.sh
Pretrained Checkpoints

All checkpoints are on Hugging Face: adidukre/SCALA

huggingface-cli download adidukre/SCALA --local-dir /path/to/checkpoints
Folder Task Training data Trainer
cavity_resenc 1, 2 Dataset501 (130 LGE-MRI) nnUNetTrainer (ResEnc-L)
cavity_mednext 2 Dataset501 nnUNetTrainerMedNeXt
scar_resenc 1 Dataset512 (60 labeled + 40 pseudo-labeled) nnUNetTrainer (ResEnc-L)
scar_surface 1 Dataset512 nnUNetTrainerScarSurface
ct_resenc 3 Dataset522 (50 labeled + 99 pseudo-labeled) nnUNetTrainer (ResEnc-L)
ct_stunet 3 Dataset522 STUNetTrainer_base_ft

Each folder is a standard nnU-Net result folder: plans.json, dataset.json, and fold_0 to fold_4, each holding checkpoint_best.pth.

Inference
python -m scala.predict --task task1 -i /path/to/input -o /path/to/output -m /path/to/checkpoints
Argument Meaning
--task task1 (scar), task2 (cavity) or task3 (CT)
-i the challenge layout (input/taskN/<case>/<image>.nii.gz), a folder of case subfolders, or a flat folder of .nii.gz images
--folds default 0,1,2,3,4 (all five)
--tta mirror TTA, off in our submission
--device e.g. cpu

Output follows the challenge naming (<case>/<id>_pred.nii.gz), on the input grid, as uint8. Task 1 and Task 2 write binary masks; Task 3 writes labels {0: background, 1: LA, 2: LAA, 3: PV}.

Tip

Task 1 is end-to-end: the cavity is predicted inside the pipeline, so only the LGE image is needed.

Docker
bash docker/build.sh task1 /path/to/checkpoints scala-task1
docker run --rm --gpus all -v /path/to/input:/input:ro -v /path/to/output:/output scala-task1
  • The build copies only the members the task needs.
  • The build runs a self-test that loads every model, so a broken image fails at build time.
  • The container falls back to single-process preprocessing when /dev/shm is small, so it also works with Docker's default 64 MB.
Training

Place the challenge training data under $SCALA_DATA, which should contain the three released task folders. Then run the stages below in order. In every nnUNetv2_train loop, F runs over folds 0 to 4.

1. Convert the data and write the patient-level splits (cavity and scar share the same splits)
source scripts/env.sh
python -m scala.data.convert --task all
nnUNetv2_plan_and_preprocess -d 501 521 -pl nnUNetPlannerResEncL -c 3d_fullres --verify_dataset_integrity
python -m scala.data.splits --dataset cavity
python -m scala.data.splits --dataset cardiac
2. Train the cavity models (Task 2, and the Task 1 localizer)
nnUNetv2_train 501 3d_fullres F -p nnUNetResEncUNetLPlans
nnUNetv2_train 501 3d_fullres F -p nnUNetResEncUNetLPlans -tr nnUNetTrainerMedNeXt
3. Build the scar dataset from out-of-fold cavity predictions, then train the scar teacher
python -m scala.data.cavity_oof
python -m scala.data.scar_cavity_map
python -m scala.data.build_scar_dataset
nnUNetv2_plan_and_preprocess -d 511 -pl nnUNetPlannerResEncL -c 3d_fullres --verify_dataset_integrity
python -m scala.data.splits --dataset scar
nnUNetv2_train 511 3d_fullres F -p nnUNetResEncUNetLPlans
4. Scar self-training and the two scar members (Task 1)
python -m scala.semisup.scar_pseudo_label
nnUNetv2_plan_and_preprocess -d 512 -pl nnUNetPlannerResEncL -c 3d_fullres --verify_dataset_integrity
python -m scala.data.splits --dataset scar_ssl
nnUNetv2_train 512 3d_fullres F -p nnUNetResEncUNetLPlans
nnUNetv2_train 512 3d_fullres F -p nnUNetResEncUNetLPlans -tr nnUNetTrainerScarSurface
5. CT teacher, self-training and the two CT members (Task 3)
Important

For the STU-Net member, first download the TotalSegmentator-pretrained STU-Net-B weights (base_ep4k.model) from the STU-Net repository.

nnUNetv2_train 521 3d_fullres F -p nnUNetResEncUNetLPlans
python -m scala.semisup.ct_pseudo_label
nnUNetv2_plan_and_preprocess -d 522 -pl nnUNetPlannerResEncL -c 3d_fullres --verify_dataset_integrity
python -m scala.data.splits --dataset cardiac_ssl
nnUNetv2_train 522 3d_fullres F -p nnUNetResEncUNetLPlans
python scripts/train_stunet.py 522 3d_fullres F -p nnUNetResEncUNetLPlans \
    -tr STUNetTrainer_base_ft -pretrained_weights /path/to/base_ep4k.model
6. Export slim checkpoints in the layout scala.predict expects
python scripts/export_checkpoints.py --out /path/to/checkpoints

Training schedule. We stopped each fold once its EMA pseudo-Dice had plateaued, then kept checkpoint_best.pth:

Members Epochs per fold
Scar 101 to 151
Cavity 250 to 418 (MedNeXt: 250-epoch budget)
CT 155 to 443

All models were trained on a single 96 GB NVIDIA RTX PRO 6000 Blackwell GPU.

05 / CITATION

BibTeX

@inproceedings{rege2026scala,
  title={SCALA: Semi-supervised Cascade for Left Atrial Scar, Cavity, and Multi-Structure CT Segmentation},
  author={Rege, Atharva Atul and Dukre, Adinath Madhavrao and Shah, Sarth Santosh and Razzak, Imran},
  booktitle={CARE 2026: Comprehensive Analysis of REal-world medical images-heart and liver},
  year={2026},
  url={https://openreview.net/forum?id=WylqMXauzj}
}

Acknowledgments

This work builds on:

We thank the CARE 2026 organizers for the data and the evaluation.

Contact

For questions or collaboration, please open an issue or reach out to Adinath Madhavrao Dukre.

Important

SCALA is intended for research only. It is not approved for clinical use and must not inform any diagnostic or treatment decision.