Skip to content
pgsalomePublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

9 Commits

Folders and files

Repository files navigation

RN-D3

Paper License: PolyForm Noncommercial 1.0.0 Python

Detect, differentiate, and delineate radiation necrosis on post-contrast MRI.

rn-d3 is a registry-driven command-line toolkit for radiation necrosis (RN) MRI workflows. It supports two connected use cases:

  1. Run RN segmentation inference with configured nnU-Net, Spark3D, and STU-Net model backends.
  2. Compare segmentation methods on matched image/mask registries using DSC, surface Dice, and lesion-detection metrics.

RN-D3 separates the workflow into two explicit inputs: registry JSON files describe the image/mask cohort, and YAML model configs describe how each checkpoint is run. Images, masks, and weights can live in local folders such as data/ and weights/, or any other path referenced by those config files.

The associated paper is RN-D3: Detection, differentiation, and delineation of radiation necrosis on post-contrast MRI.

Quick Start

git clone https://github.com/pgsalome/rn-d3.git
cd rn-d3
python -m venv .venv
source .venv/bin/activate
pip install -e .

Build a registry from image and mask lists:

rnd3 registry build \
  --images image_paths.txt \
  --masks mask_paths.txt \
  --out registries/external.json

Create paired left-right and anterior-posterior augmentations:

rnd3 augment \
  --registry registries/external.json \
  --out-dir data/augmented \
  --out-registry registries/external_augmented.json

Compare existing prediction folders:

rnd3 compare \
  --registry registries/external.json \
  --pred-dir nnunet=predictions/nnunet \
  --pred-dir spark3d=predictions/spark3d \
  --pred-dir stunet=predictions/stunet \
  --out-dir results/model_comparison \
  --surface-mm 2.0

Run one configured model on one image:

cp configs/models.local.example.yaml configs/models.local.yaml
rnd3 predict \
  --model spark3d \
  --image data/images/case001_t1ce.nii.gz \
  --out outputs/spark3d_case001_mask.nii.gz \
  --models-config configs/models.local.yaml

Table Of Contents

  1. Study context
  2. How it works
  3. Registry format
  4. Data augmentation
  5. Compare segmentation models
  6. One-command inference
  7. Understand the output
  8. Data and weights
  9. Testing
  10. Citation
  11. License

Study Context

Radiation necrosis is an important complication of radiation therapy and is challenging to assess radiographically because lesions are prone to inconsistent delineation and may require intracranial surgery for diagnosis. The RN-D3 study evaluated how established deep learning segmentation models can be retrained on an institutional RN cohort, tested for external generalization, and integrated into an end-to-end workflow for RN detection, differentiation, and delineation.

Models were trained on 52 patients with RN after proton beam radiation therapy at Massachusetts General Hospital between 2004 and 2016. External validation used 29 patients with 39 RN lesions from the MOLAB brain metastasis dataset, collected across five Spanish institutions between 2005 and 2021 after photon-based radiation therapy.

Six segmentation architectures were evaluated: nnU-Net, STU-Net, TRIAD PlainConv, Spark3D, SwinUNETR, and TRIAD SwinB. Performance was assessed with Dice similarity coefficient (DSC), surface Dice at 2 mm, and lesion detection rate. The best segmentation components were combined with an RN-versus-non-RN classifier using deep encoder features and shape radiomics.

Key external findings from the study were:

  • Spark3D and STU-Net had the highest external DSC: Spark3D 0.69 [IQR 0.50-0.84] and STU-Net 0.65 [0.29-0.88].
  • nnU-Net followed with external DSC 0.61 [0.39-0.83].
  • For lesions >=1 mL, Spark3D and STU-Net detected 100% of lesions, with median DSC 0.77 and 0.73.
  • For lesions <1 mL, Spark3D and STU-Net detected 78% and 67%, with median DSC 0.60 and 0.58.
  • Small-lesion detection remained the main translational bottleneck.
  • RN-D3 achieved high RN-versus-non-RN differentiation performance on external brain-metastasis lesions, with end-to-end sensitivity and specificity reported in the associated Frontiers article.

How It Works

  1. Define a registry with one row per lesion or case, including image, mask, patient, lesion, and split metadata.
  2. Optionally create paired deterministic augmentations from the registry.
  3. Configure model backends for nnU-Net, Spark3D, STU-Net, or another compatible segmentation runner. A backend only needs to accept {image} and write a binary NIfTI mask to {out}.
  4. Run prediction over one image or an entire registry.
  5. Compare models on the same cases. The comparison step computes per-case DSC, surface Dice, overlap-based detection, foreground volume counts, and summary statistics.
  6. Inspect the per-case CSV when debugging failures. Missing predictions are treated as empty masks, so missed lesions are visible in the output rather than silently dropped.

Registry Format

A registry is a JSON file with one row per lesion or case:

{
  "cases": [
    {
      "case_id": "case001_lesion1",
      "patient_id": "case001",
      "lesion_id": "lesion1",
      "image": "data/images/case001_t1ce.nii.gz",
      "mask": "data/masks/case001_lesion1_mask.nii.gz",
      "split": "external"
    }
  ]
}

Required fields for comparison are case_id, image, and mask. patient_id is strongly recommended so uncertainty analyses can be grouped at the patient level.

Build a registry from two file lists:

rnd3 registry build \
  --images image_paths.txt \
  --masks mask_paths.txt \
  --out registries/external.json

Or from shell-expanded file paths:

rnd3 registry build \
  --images data/images/*.nii.gz \
  --masks data/masks/*.nii.gz \
  --out registries/external.json

Validate a registry:

rnd3 registry validate registries/external.json

Data Augmentation

rnd3 augment creates deterministic paired image/mask augmentations from a registry. The current operations are:

  • flip-lr: flip the image and mask along voxel axis 0.
  • flip-ap: flip the image and mask along voxel axis 1.

Run both operations, which is the default:

rnd3 augment \
  --registry registries/train.json \
  --out-dir data/augmented \
  --out-registry registries/train_augmented.json

Run only one operation:

rnd3 augment \
  --registry registries/train.json \
  --out-dir data/augmented_lr \
  --out-registry registries/train_augmented_lr.json \
  --operations flip-lr

Include the original rows alongside augmented rows:

rnd3 augment \
  --registry registries/train.json \
  --out-dir data/augmented \
  --out-registry registries/train_augmented_with_originals.json \
  --include-original

The augmented registry keeps the same patient_id as the source row. This is intentional: augmented versions of the same patient must stay in the same fold for patient-level cross-validation.

Compare Segmentation Models

If predictions already exist, compare prediction masks against registry masks:

rnd3 compare \
  --registry registries/external.json \
  --pred-dir nnunet=predictions/nnunet \
  --pred-dir spark3d=predictions/spark3d \
  --pred-dir stunet=predictions/stunet \
  --out-dir results/model_comparison \
  --surface-mm 2.0

The comparison looks for prediction filenames in each model directory using common names:

  • {case_id}.nii.gz
  • {case_id}_pred.nii.gz
  • {patient_id}.nii.gz
  • {patient_id}_pred.nii.gz
  • the input image basename

One-Command Inference

Copy the portable config template and edit it to point to your installed model runners and checkpoint files:

cp configs/models.local.example.yaml configs/models.local.yaml

The recommended portable backend is command, where each model entry is a shell command that receives {image}, {out}, and {work_dir} placeholders:

models:
  spark3d:
    backend: command
    command: >
      spark3d-predict
      --image {image}
      --out {out}
      --checkpoint ${RND3_WEIGHTS_DIR}/spark3d/best_model.pth

The config loader expands environment variables, so paths such as ${RND3_WEIGHTS_DIR}/spark3d/best_model.pth are portable across machines.

Run one model on one image:

rnd3 predict \
  --model spark3d \
  --image data/images/case001_t1ce.nii.gz \
  --out outputs/spark3d_case001_mask.nii.gz \
  --models-config configs/models.local.yaml

Run all configured models on one image:

rnd3 predict-all \
  --image data/images/case001_t1ce.nii.gz \
  --out-dir outputs/predictions \
  --models-config configs/models.local.yaml

Run all configured models over a registry:

rnd3 predict-registry \
  --registry registries/external.json \
  --out-dir outputs/predictions \
  --models-config configs/models.local.yaml \
  --models nnunet,spark3d,stunet

Run prediction and comparison together:

rnd3 benchmark \
  --registry registries/external.json \
  --models-config configs/models.local.yaml \
  --models nnunet,spark3d,stunet \
  --out-dir results/benchmark_external \
  --surface-mm 2.0

This writes predictions under results/benchmark_external/predictions/<model>/ and metrics under results/benchmark_external/metrics/.

The package also includes an nnunetv2 backend for standard nnU-Net v2 installations. Use the command backend for custom Spark3D or STU-Net runners that write binary NIfTI masks to {out}.

Understand The Output

per_case_metrics.csv contains one row per case and model:

Column Meaning
case_id Registry case identifier.
patient_id Patient/group identifier from the registry.
lesion_id Optional lesion identifier.
model Model name from --pred-dir or config.
prediction Prediction mask path, blank if missing.
missing_prediction Whether the prediction was absent and evaluated as an empty mask.
dsc Dice similarity coefficient.
surface_dice Surface Dice at the requested tolerance.
detected Overlap-based lesion detection flag.
gt_voxels Reference-mask foreground voxels.
pred_voxels Prediction foreground voxels.

summary_metrics.csv aggregates each model across the registry and reports mean, median, IQR, detection rate, and missing-prediction count. Use the per-case file for audit/debugging and the summary file for model-level reporting.

Data And Weights

Place cohort files and checkpoints wherever appropriate on your machine, then reference them from a registry and a model config. A common local layout is:

data/
  images/
  masks/
weights/
  nnunet/
  spark3d/
  stunet/
registries/
outputs/
results/

The example data/, weights/, outputs/, and results/ folders are ignored by Git so local datasets, checkpoints, predictions, and metrics stay outside the source history.

Testing

Install development dependencies and run the test suite:

pip install -e '.[dev]'
pytest

The tests cover:

  • Registry read/write/validation.
  • Paired registry augmentation for image/mask flips.
  • DSC, surface Dice, and lesion-detection metrics.
  • Environment-variable expansion in model configs.
  • A CLI smoke test that creates synthetic NIfTI files, builds a registry, runs rnd3 compare, and verifies the generated CSV outputs.

Citation

If you use RN-D3, please cite the associated paper:

@article{salome2026rnd3,
  title = {RN-D3: Detection, differentiation, and delineation of radiation necrosis on post-contrast MRI},
  author = {Salome, Patrick and Cogno, Nicolò and Lee, Hoyeon and Buti, Gregory and Shah, Keyur Devendra and Ehret, Felix and Wisdom, Amy Jordan and Shih, Helen A. and Paganetti, Harald and Chamseddine, Ibrahim},
  journal = {Frontiers in Artificial Intelligence},
  volume = {9},
  year = {2026},
  doi = {10.3389/frai.2026.1891883},
  url = {https://www.frontiersin.org/journals/artificial-intelligence/articles/10.3389/frai.2026.1891883/full}
}

A machine-readable citation is also provided in CITATION.cff.

License

This software is source-available under the PolyForm Noncommercial License 1.0.0.

Noncommercial use, modification, and redistribution are permitted subject to the license terms. Commercial use requires a separate written agreement.

This is not an OSI-approved open-source license.

Maintainer

Patrick Salome

Clinical Use

This repository is research software. It is not a cleared medical device and is not intended for clinical decision-making without independent validation and appropriate regulatory review.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages