|
1 | | -# BIC-MAC Challenge: Big Cross-Modal Attenuation Correction |
| 1 | +# BIC-MAC Challenge Codebase |
2 | 2 |
|
3 | | -Synthesizing pseudo-CT (mu-map) for PET attenuation correction from multimodal inputs (PET, MRI, Topogram). |
| 3 | +**Big Cross-Modal Attenuation Correction** — synthesize pseudo-CT from multi-modal PET/MRI input to enable CT-less PET reconstruction. |
4 | 4 |
|
5 | | -## Tasks |
| 5 | +[Challenge website](https://bic-mac-challenge.github.io/) |
6 | 6 |
|
7 | | -**Task 1**: Generate mu-map in CT-space (evaluated vs reference CT-mu-map) |
| 7 | +--- |
8 | 8 |
|
9 | | -**Task 2**: Generate mu-map for PET reconstruction in PET-space (evaluated vs reference CT-AC PET) |
| 9 | +## Overview |
10 | 10 |
|
11 | | -## Docker Interface |
| 11 | +PET/CT scanners combine functional PET imaging with anatomical CT. The CT is used to compute an attenuation correction factor (ACF) — a correction for how much the body absorbs the 511 keV photons emitted during PET scanning. While PET tracer doses have dropped significantly with modern scanners, the CT component remains the primary radiation source in a PET/CT exam. |
12 | 12 |
|
13 | | -### Task 1 and 2: Mu-map Prediction |
| 13 | +This challenge asks participants to synthesize a pseudo-CT from three radiation-free inputs: non-attenuation-corrected PET (NAC-PET), whole-body MRI, and a 2D topogram (scout X-ray). The predicted CT is then used as a drop-in replacement in the standard reconstruction pipeline, producing an attenuation-corrected PET (ACPET) image without a volumetric CT scan. Eliminating the CT dose is particularly valuable for radiation-sensitive populations such as children and pregnant patients. |
| 14 | + |
| 15 | +The dataset comprises 100 healthy volunteers acquired on a **Siemens Biograph Vision Quadra** (PET/CT) and **MAGNETOM Vida** (MRI), with 75 training cases and 4 validation cases. Both static and dynamic acquisition protocols are included. |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | +## Repository Structure |
| 20 | + |
| 21 | +``` |
| 22 | +src/ |
| 23 | +├── baseline/ # Baseline pseudo-CT model (patch-based MONAI 3D UNet, NAC-PET input) |
| 24 | +├── evaluation/ # Five-metric evaluation suite |
| 25 | +└── recon/ # PET reconstruction pipeline (STIR-based, Dockerized) |
| 26 | +``` |
| 27 | + |
| 28 | +--- |
| 29 | + |
| 30 | +## Getting Started |
| 31 | + |
| 32 | +**Requirements:** Python 3.12, [uv](https://github.com/astral-sh/uv), Docker |
14 | 33 |
|
15 | 34 | ```bash |
16 | | -docker run --rm \ |
17 | | - -v /path/to/subject:/input:ro \ |
18 | | - -v /path/to/output/dir:/output \ |
19 | | - your-solution:latest \ |
20 | | - /input /output/predicted_ct.nii.gz |
| 35 | +uv sync |
| 36 | +``` |
| 37 | + |
| 38 | +**Dataset:** Download from Hugging Face Hub (link available at challenge launch — see [website](https://bic-mac-challenge.github.io/)). |
| 39 | + |
| 40 | +--- |
| 41 | + |
| 42 | +## Data Format |
| 43 | + |
| 44 | +Each subject is a directory with four subdirectories: |
| 45 | + |
| 46 | +``` |
| 47 | +sub-000/ |
| 48 | +├── features/ # Inputs to your model |
| 49 | +├── ct-label/ # Ground-truth CT and segmentations |
| 50 | +├── recon/ # Sinogram data for reconstruction |
| 51 | +└── pet-label/ # Ground-truth ACPET and segmentations |
21 | 52 | ``` |
22 | 53 |
|
23 | | -**Arguments:** |
24 | | -1. Input directory: PET, MRI, Topogram, metadata.json |
25 | | -2. Output file path: Predicted CT (NIfTI) |
| 54 | +### `features/` — model inputs |
| 55 | + |
| 56 | +| File | Description | |
| 57 | +|------|-------------| |
| 58 | +| `nacpet.nii.gz` | Non-attenuation-corrected PET (NAC-PET) | |
| 59 | +| `topogram.nii.gz` | 2D scout X-ray (topogram) resampled to 3D CT grid | |
| 60 | +| `mri_chunk_*_*.nii.gz` | DIXON MRI chunks (in-phase and out-of-phase) | |
| 61 | +| `mri_combined_*_phase.nii.gz` | Combined whole-body DIXON MRI | |
| 62 | +| `metadata.json` | Demographics: `{sex, age, height, weight}` | |
| 63 | + |
| 64 | +### `ct-label/` — ground-truth CT |
| 65 | + |
| 66 | +| File | Description | |
| 67 | +|------|-------------| |
| 68 | +| `ct.nii.gz` | Anonymized ground-truth CT in Hounsfield units (HU) | |
| 69 | +| `body_seg.nii.gz` | Binary body mask | |
| 70 | +| `organ_seg.nii.gz` | TotalSegmentator organ labels | |
| 71 | +| `face_seg.nii.gz` | Face mask (used for anonymization) | |
| 72 | + |
| 73 | +### `recon/` — reconstruction inputs |
| 74 | + |
| 75 | +| File | Description | |
| 76 | +|------|-------------| |
| 77 | +| `mult_factors_forSTIR_SSRB.hs/.s` | Multiplicative correction sinogram | |
| 78 | +| `additive_term_SSRB.hs/.s` | Additive correction sinogram (scatter + randoms) | |
| 79 | +| `prompts_SSRB.hs/.s` | Prompt (raw) sinogram | |
| 80 | +| `offset.json` | Bed position and gantry offset for origin alignment | |
| 81 | +| `ct_face.nii.gz` | Ground-truth CT face region (for optional face swap) | |
| 82 | +| `face_mask.nii.gz` | Face mask for anonymization | |
| 83 | + |
| 84 | +### `pet-label/` — ground-truth ACPET |
| 85 | + |
| 86 | +| File | Description | |
| 87 | +|------|-------------| |
| 88 | +| `acpet.nii.gz` | Ground-truth CT-attenuation-corrected PET (reference) | |
| 89 | +| `body_seg.nii.gz` | Body mask resampled to PET space | |
| 90 | +| `organ_seg.nii.gz` | Organ labels resampled to PET space | |
| 91 | +| `brain_seg.nii.gz` | SynthSeg brain segmentation | |
| 92 | + |
| 93 | +--- |
| 94 | + |
| 95 | +## Baseline (`src/baseline/`) |
26 | 96 |
|
27 | | -**Input files:** |
28 | | -- `*nacstat_pet.nii.gz` |
29 | | -- `*DIXONbodyIN_T1w.nii.gz`, `*DIXONbodyOUT_T1w.nii.gz` |
30 | | -- `*DIXONbodyIN_chunk-{1-4}_T1w.nii.gz`, `*DIXONbodyOUT_chunk-{1-4}_T1w.nii.gz` |
31 | | -- `*DIXONheadIN_T1w.nii.gz`, `*DIXONheadOUT_T1w.nii.gz` |
32 | | -- `*acq-TOPOGRAM_rec-tr20f_Xray.nii.gz` |
33 | | -- `metadata.json` |
| 97 | +A simple patch-based MONAI 3D UNet that predicts pseudo-CT from NAC-PET only. It is provided as a starting-point reference — participants are expected to improve on it by incorporating MRI and topogram inputs. |
34 | 98 |
|
35 | | -### Task 2: PET Reconstruction |
| 99 | +A pre-built Docker image is available for download (see [website](https://bic-mac-challenge.github.io/)). |
| 100 | + |
| 101 | +**Direct Python usage:** |
36 | 102 |
|
37 | 103 | ```bash |
38 | | -docker run --rm \ |
39 | | - -v /path/to/predicted_ct.nii.gz:/input_ct:ro \ |
40 | | - -v /path/to/recon_dir:/recon:ro \ |
41 | | - -v /path/to/output/dir:/output \ |
42 | | - reconstruction-software:latest \ |
43 | | - /input_ct /recon /output/reconstructed_pet.nii.gz |
| 104 | +python src/baseline/model.py <input_dir> <output_ct.nii.gz> |
| 105 | +# Example: |
| 106 | +python src/baseline/model.py data/sub-000/features/ results/sub-000/ct_pred.nii.gz |
44 | 107 | ``` |
45 | 108 |
|
46 | | -**Arguments:** |
47 | | -1. Input CT: Predicted mu-map from Task 1 |
48 | | -2. Reconstruction directory: Sinograms, scatter maps, normalization data |
49 | | -3. Output file path: Reconstructed PET (NIfTI) |
| 109 | +--- |
| 110 | + |
| 111 | +## Reconstruction Pipeline (`src/recon/`) |
| 112 | + |
| 113 | +Converts a predicted pseudo-CT into a reconstructed ACPET image using [STIR](http://stir.sourceforge.net/) (Software for Tomographic Image Reconstruction). The pipeline: |
50 | 114 |
|
51 | | -## Baseline |
| 115 | +1. Validates CT shape, affine, and HU range |
| 116 | +2. Converts HU → linear attenuation coefficients (μ-map) at 511 keV using the Carney et al. (2006) bilinear model |
| 117 | +3. Smooths the μ-map (4mm FWHM Gaussian) |
| 118 | +4. Resamples the μ-map to STIR sinogram format |
| 119 | +5. Computes the ACF (attenuation correction factor) sinogram |
| 120 | +6. Applies ACF to multiplicative/additive sinograms |
| 121 | +7. Reconstructs using OSEM (ordered subsets expectation maximisation) |
| 122 | +8. Applies 4mm post-reconstruction filter |
| 123 | +9. Converts to NIfTI with correct bed/gantry offset origin |
| 124 | + |
| 125 | +### Option 1: Docker (recommended) |
| 126 | + |
| 127 | +A pre-built image with STIR and all dependencies is available (see [website](https://bic-mac-challenge.github.io/)). |
52 | 128 |
|
53 | 129 | ```bash |
54 | | -cd src/baseline |
55 | | -docker build -t baseline-solution:latest . |
| 130 | +docker pull ghcr.io/bic-mac-challenge/recon:latest # placeholder — final name on website |
56 | 131 |
|
57 | 132 | docker run --rm \ |
58 | | - -v /path/to/subject:/input:ro \ |
59 | | - -v /path/to/output:/output \ |
60 | | - baseline-solution:latest \ |
61 | | - /input /output/predicted_ct.nii.gz |
| 133 | + -v /path/to/sub-000/recon:/data/recon \ |
| 134 | + -v /path/to/ct_pred.nii.gz:/data/ct/ct.nii.gz \ |
| 135 | + -v /path/to/output:/data/output \ |
| 136 | + ghcr.io/bic-mac-challenge/recon:latest |
62 | 137 | ``` |
63 | 138 |
|
64 | | -## Evaluation |
| 139 | +The reconstructed PET is written to `/data/output/pet.nii.gz`. |
65 | 140 |
|
66 | | -### Task 1 |
| 141 | +Set `OVERWRITE=1` to re-run over existing outputs: |
67 | 142 |
|
68 | 143 | ```bash |
69 | | -python src/evaluation/run_docker_model.py your-solution:latest /path/to/subject /path/to/output.nii.gz |
70 | | -python src/evaluation/evaluate_task1.py /path/to/predictions /path/to/ground_truth |
| 144 | +docker run --rm -e OVERWRITE=1 \ |
| 145 | + -v /path/to/sub-000/recon:/data/recon \ |
| 146 | + ... |
71 | 147 | ``` |
72 | 148 |
|
73 | | -### Task 2 |
| 149 | +### Option 2: Direct Python (requires local STIR) |
74 | 150 |
|
75 | 151 | ```bash |
76 | | -python src/evaluation/run_docker_model.py your-solution:latest /path/to/subject /path/to/predicted_ct.nii.gz |
77 | | -python src/evaluation/run_docker_reconstruction.py reconstruction-software:latest /path/to/predicted_ct.nii.gz /path/to/recon_dir /path/to/output_pet.nii.gz |
78 | | -python src/evaluation/evaluate_task2.py /path/to/reconstructed_pets /path/to/reference_ct_ac_pets |
| 152 | +python src/recon/main.py <recon_dir> <ct.nii.gz> <pet_out.nii.gz> \ |
| 153 | + [--overwrite] [--intermediates_dir <dir>] |
79 | 154 | ``` |
| 155 | + |
| 156 | +--- |
| 157 | + |
| 158 | +## Evaluation (`src/evaluation/`) |
| 159 | + |
| 160 | +Five metrics compare predicted PET and CT outputs against the ground truth: |
| 161 | + |
| 162 | +| Metric | Flag | Description | Region | |
| 163 | +|--------|------|-------------|--------| |
| 164 | +| Whole-body SUV MAE | `whole_body_mae` | Mean absolute error in standardised uptake value (SUV = activity × weight / total dose) | Body mask, excluding ±4 cm around liver | |
| 165 | +| Brain Outlier Score | `brain_outlier` | AUC of fraction of brain voxels within relative error thresholds (5%, 10%, 15%) | Brain | |
| 166 | +| Organ Bias (MARE) | `organ_bias` | Mean absolute relative error of mean SUV in 8 organs: brain, liver, spleen, heart, pancreas, muscle, adipose, extremities | TotalSegmentator organ labels | |
| 167 | +| TAC Bias | `tac_bias` | AUC MARE for time-activity curves in aorta + 6 brain regions (4D dynamic PET only) | Aorta + brain regions | |
| 168 | +| CT MAE | `ct_mae` | Mean absolute error in HU between predicted and ground-truth CT | Body mask | |
| 169 | + |
| 170 | +**Run all metrics:** |
| 171 | + |
| 172 | +```bash |
| 173 | +python src/evaluation/eval.py <subject_dir> <pred_pet.nii.gz> <pred_ct.nii.gz> -all |
| 174 | +``` |
| 175 | + |
| 176 | +**Run a single metric:** |
| 177 | + |
| 178 | +```bash |
| 179 | +python src/evaluation/eval.py <subject_dir> <pred_pet.nii.gz> <pred_ct.nii.gz> \ |
| 180 | + -specific_metric <metric> |
| 181 | +# <metric>: whole_body_mae | brain_outlier | organ_bias | tac_bias | ct_mae |
| 182 | +``` |
| 183 | + |
| 184 | +--- |
| 185 | + |
| 186 | +## Tips & FAQ |
| 187 | + |
| 188 | +_Coming soon._ |
| 189 | + |
| 190 | +--- |
| 191 | + |
| 192 | +## Organizers |
| 193 | + |
| 194 | +This challenge is organized by [Rigshospitalet](https://www.rigshospitalet.dk/), [Technical University of Denmark (DTU)](https://www.dtu.dk/), [University of Copenhagen (KU)](https://www.ku.dk/), and [KU Leuven](https://www.kuleuven.be/), with support from [QIM](https://qim.dk/) and [SyneRBI](https://www.synergistic-biomedical-imaging.eu/). |
| 195 | + |
| 196 | +For full details, timeline, and registration: [bic-mac-challenge.github.io](https://bic-mac-challenge.github.io/) |
0 commit comments