Skip to content

Commit e5a9821

Browse files
simplifying readme
1 parent c4f7c89 commit e5a9821

5 files changed

Lines changed: 336 additions & 223 deletions

File tree

README.md

Lines changed: 60 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,31 @@
44

55
[Challenge website](https://bic-mac-challenge.github.io/)
66

7+
[Dataset](https://huggingface.co/datasets/DEPICT-RH/BIC-MAC)
8+
9+
[CodaBench submission & leaderboard](https://www.codabench.org/competitions/12555/)
10+
711
---
812

913
## Table of Contents
1014

1115
- [Overview](#overview)
1216
- [Documentation](#documentation)
13-
- [Repository Structure](#repository-structure)
1417
- [Getting Started](#getting-started)
1518
- [Data Format](#data-format)
16-
- [Baseline](#baseline-srcbaseline)
17-
- [Reconstruction Pipeline](#reconstruction-pipeline-srcrecon)
19+
- [Pseudo-CT Baseline](#baseline-srcbaseline)
20+
- [Reconstruction](#reconstruction-pipeline-srcrecon)
1821
- [Evaluation](#evaluation-srcevaluation)
1922
- [Submission](#submission)
20-
- [Tips & FAQ](#tips--faq)
21-
- [Organizers](#organizers)
2223

2324
---
2425

2526
## 🧠 Overview
2627

27-
Your algorithm receives the files under `features/` for each subject and must output a predicted CT volume as a NIfTI file in Hounsfield units (HU). Predictions are evaluated two ways:
28+
Your algorithm receives the files under `features/` for each subject and must output a pseudo-CT volume as a NIfTI file in Hounsfield units (HU). Predictions are evaluated two ways:
2829

29-
1. **CT accuracy**predicted CT is compared directly against the ground-truth CT
30-
2. **PET accuracy**predicted CT is fed into the reconstruction pipeline to produce an attenuation-corrected PET image, which is then compared against the ground-truth PET
30+
1. **CT accuracy**Predicted pseudo-CT is compared directly against the ground-truth CT
31+
2. **PET accuracy**Predicted pseudo-CT is fed into the reconstruction pipeline to produce an attenuation-corrected PET image, which is then compared against the ground-truth PET
3132

3233
Note that no PET reconstruction experience is needed to participate in the challenge, and the main purpose of the reconstruction is to enable clinically meaningful metrics.
3334

@@ -39,7 +40,7 @@ The dataset comprises 99 subject-unique cases, with 20 reserved for testing and
3940
| `train/` (no recon) | 67 | `features/` + `ct-label/` |
4041
| `val/` | 4 | `features/` + `recon/` |
4142

42-
All train cases have CT labels, but due to the size of the sinograms, only 8 include the recon and pet-label folders needed for closed loop reconstruction. Validation subjects have sinogram data but no labels — submit predicted CTs and reconstructed PET to Codabench to get live leaderboard metrics throughout the challenge.
43+
All train cases have CT labels, but due to the size of the sinograms, only 8 include the `recon/` and `pet-label/` folders needed for closed loop reconstruction. Validation subjects have sinogram `recon/` data but no labels — submit predicted pseudo-CTs and reconstructed PETs to Codabench to get live leaderboard metrics during the challenge.
4344

4445
---
4546

@@ -48,19 +49,10 @@ All train cases have CT labels, but due to the size of the sinograms, only 8 inc
4849
| Guide | Description |
4950
|-------|-------------|
5051
| [PET Background](docs/pet-background.md) | PET physics and attenuation correction — start here if you're new to PET |
52+
| [Reconstruction Pipeline](docs/reconstruction.md) | How the pseudo-CT is turned into an AC-PET image; how to run it locally |
5153
| [Submission Guide](docs/submission-guide.md) | Validation, dry-run, and final submission phases explained |
5254
| [Docker Packaging](docs/docker-packaging.md) | How to containerize your model, with baseline as a worked example |
53-
54-
---
55-
56-
## 📁 Repository Structure
57-
58-
```
59-
src/
60-
├── baseline/ # Baseline pseudo-CT model (patch-based MONAI 3D UNet, NAC-PET input)
61-
├── evaluation/ # Five-metric evaluation suite
62-
└── recon/ # PET reconstruction pipeline (STIR-based, Dockerized)
63-
```
55+
| [Tips & FAQ](docs/tips-and-faq.md) | Common questions, pitfalls, and practical advice |
6456

6557
---
6658

@@ -72,17 +64,26 @@ src/
7264
uv sync
7365
```
7466

75-
**Dataset:** Download from Hugging Face Hub (link available at challenge launch — see [website](https://bic-mac-challenge.github.io/)).
67+
The `src/` directory contains three components:
68+
69+
```
70+
src/
71+
├── baseline/ # Baseline pseudo-CT model (patch-based 3D UNet)
72+
├── evaluation/ # Metric defintinitions and scripts
73+
└── recon/ # PET reconstruction script (and Docker)
74+
```
7675

7776
---
7877

79-
## 🗂️ Data Format
78+
## 🗂️ Dataset structure
8079
All images are resampled to the label CT image (tensor size: 512x512x531, voxel size 1.52x1.52,2.00mm^3) and structured in four folders per case.
81-
- `features/` All the files you can use as input to your generative CT model at inference.
82-
-
83-
```
80+
- `features/` All the files you can use as input to your pseudo-CT model during inference.
81+
- `ct-label/` The CT target (`ct.nii.gz`) and segmentations for evaluation.
82+
- `pet-label/` The PET target (`pet.nii.gz`) and segmentations for evaluation.
83+
- `recon/` Sinograms and metadata for PET reconstructions.
8484

8585

86+
```
8687
train/
8788
└── sub-000/
8889
├── features/ # generative model inputs
@@ -112,14 +113,13 @@ train/
112113

113114
---
114115

115-
## 📦 Baseline (`src/baseline/`)
116+
## 📦 Pseudo-CT Baseline (`src/baseline/`)
116117

117118
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.
118119

119-
**Direct Python usage:**
120+
**Python usage:**
120121

121122
```bash
122-
python src/baseline/predict.py --features_dir <features_dir> --output_ct <ct.nii.gz>
123123
# Example:
124124
python src/baseline/predict.py --features_dir data/sub-000/features/ --output_ct results/sub-000/ct.nii.gz
125125
```
@@ -131,80 +131,44 @@ docker pull ghcr.io/bic-mac-challenge/baseline:latest
131131

132132
docker run --rm \
133133
--gpus all \
134-
-v /path/to/sub-XXX/features:/data/features:ro \
134+
-v /path/to/sub-000/features:/data/features:ro \
135135
-v /path/to/output:/data/output \
136136
ghcr.io/bic-mac-challenge/baseline:latest
137137
```
138138

139-
The predicted CT is written to `/data/output/ct.nii.gz`. All weights and dependencies are baked into the image no internet access needed at runtime.
139+
The predicted CT is written to `/data/output/ct.nii.gz`. All weights and dependencies are baked into the image - no internet access is allowed at runtime.
140140

141141
---
142142

143-
## ⚙️ Reconstruction Pipeline (`src/recon/`)
144-
145-
Converts a predicted pseudo-CT into a reconstructed ACPET image using [STIR](http://stir.sourceforge.net/) (Software for Tomographic Image Reconstruction). The pipeline:
146-
147-
1. Validates CT shape, affine, and HU range
148-
2. Swaps face and scanner bed region back from ground-truth CT (to avoid evaluating face/bed prediction)
149-
3. Converts HU → linear attenuation coefficients (μ-map) at 511 keV using the Carney et al. (2006) bilinear model
150-
4. Smooths the μ-map (4mm FWHM Gaussian)
151-
5. Resamples the μ-map to STIR format (ring spacing 3.29114 mm)
152-
6. Computes the ACF (attenuation correction factor) sinogram
153-
7. Applies ACF to the additive sinogram
154-
8. Applies ACF to the multiplicative sinogram
155-
9. Reconstructs using OSEM (ordered subsets expectation maximisation, with post-filter)
156-
10. Converts to NIfTI with correct bed/gantry offset origin
157-
158-
### Option 1: Docker (recommended)
143+
## ⚙️ Reconstruction (`src/recon/`)
159144

160-
A pre-built image with STIR and all dependencies is available (see [website](https://bic-mac-challenge.github.io/)).
145+
Converts a CT (ground-truth or pseudo-CT) and PET sinograms into an attenuation-corrected PET image using [STIR](http://stir.sourceforge.net/). See [docs/reconstruction.md](docs/reconstruction.md) for pipeline details and local usage instructions.
161146

162147
```bash
163-
docker pull ghcr.io/bic-mac-challenge/recon:latest
164-
165-
docker run --rm \
166-
-v /path/to/sub-000/recon:/data/recon \
167-
-v /path/to/ct_pred.nii.gz:/data/ct/ct.nii.gz \
168-
-v /path/to/output:/data/output \
169-
ghcr.io/bic-mac-challenge/recon:latest
170-
```
171-
172-
The reconstructed PET is written to `/data/output/pet.nii.gz`. Intermediate files (mu-map, ACF sinogram, etc.) are written to `/data/output/intermediates/` and a full debug log to `/data/output/intermediates/recon.log`.
173-
174-
The pipeline resumes from any existing intermediates automatically; set `OVERWRITE=1` to forcefully restart from scratch:
148+
docker pull ghcr.io/bic-mac-challenge/recon:latest
175149

176-
```bash
177150
docker run --rm \
178-
-e OVERWRITE=1 \
179151
-v /path/to/sub-000/recon:/data/recon \
180-
-v /path/to/ct_pred.nii.gz:/data/ct/ct.nii.gz \
152+
-v /path/to/ct.nii.gz:/data/ct/ct.nii.gz \
181153
-v /path/to/output:/data/output \
182154
ghcr.io/bic-mac-challenge/recon:latest
183155
```
184156

185-
Set `VERBOSE=1` to stream STIR subprocess output to the terminal in addition to the log file.
186-
187-
### Option 2: Direct Python (requires local STIR)
188-
189-
```bash
190-
python src/recon/main.py --recon_dir <recon_dir> --ct <ct.nii.gz> --output_dir <output_dir> [-w] [-v]
191-
```
192-
193-
`pet.nii.gz` and `intermediates/` are written inside `output_dir`. Use `-w`/`--overwrite` to rerun from scratch and `-v`/`--verbose` to stream STIR output to the terminal.
157+
The reconstructed PET is written to `/data/output/pet.nii.
194158

195159
---
196160

197161
## 📊 Evaluation (`src/evaluation/`)
198162

199163
Five metrics compare predicted PET and CT outputs against the ground truth:
200164

201-
| Metric | Flag | Description | Region |
165+
| Metric | Modality | Description | Region |
202166
|--------|------|-------------|--------|
203-
| 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 |
204-
| Brain Outlier Score | `brain_outlier` | AUC of fraction of brain voxels within relative error thresholds (5%, 10%, 15%) | Brain |
205-
| 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 |
206-
| CT MAE | `ct_mae` | Mean absolute error of attenuation coefficients (μ at 511 keV) between predicted and ground-truth CT after HU→μ conversion | Body mask, excluding ±4 cm around liver|
207-
167+
| Whole-body SUV MAE | `PET` | Mean absolute error in standardised uptake value (SUV = activity × weight / total dose) | Body mask, excluding ±4 cm around liver |
168+
| Brain Outlier Score | `PET` | AUC of fraction of brain voxels within relative error thresholds (5%, 10%, 15%) | Brain |
169+
| Organ Bias | `PET` | Mean absolute relative error of mean SUV in 8 organs: brain, liver, spleen, heart, pancreas, muscle, adipose, extremities | TotalSegmentator organ labels |
170+
| CT MU MAE | `CT` | Mean absolute error of attenuation coefficients (μ at 511 keV) between predicted and ground-truth CT after HU→μ conversion | Body mask, excluding ±4 cm axial slices at top of liver|
171+
| TAC Bias | `Dynamic PET` | Absolute relative error of the integral of time-activity-curves (TACs) for the aorta and selected brain regions. NOTE: Metric is computed only for the final test set due to the size of the dynamic sinograms. | Brain regions and aorta|
208172
**Evaluate a single subject:**
209173

210174
```bash
@@ -217,42 +181,37 @@ python src/evaluation/eval_subject.py \
217181
`--pred_pet` and `--pred_ct` are both optional — omit either to skip PET or CT metrics.
218182
Note: Brain Outlier Score is a dataset-level metric and requires multiple subjects (see below).
219183

220-
**Evaluate a full dataset (matches challenge leaderboard):**
184+
**Evaluate multiple subjects:**
221185

222186
```bash
223187
python src/evaluation/eval_dataset.py \
224188
--dataset_dir <dataset_dir> \
225189
--pred_dir <predictions_dir>
226190
```
227191

228-
`<predictions_dir>` must contain one sub-folder per subject, each with `ct.nii.gz` and `pet.nii.gz`.
229-
230-
---
192+
`<predictions_dir>` must contain one sub-folder per subject with consistent contents — either CT only, PET only, or both:
231193

232-
## 📬 Submission
233-
234-
There are three submission phases — **Validation** (NIfTI upload to Codabench), **Dry Run** (container sanity check), and **Final Test** (container + full recon + evaluation). Validation and Dry Run run concurrently during the pre-evaluation period (May 15 – Jun 15).
235-
236-
See [docs/submission-guide.md](docs/submission-guide.md) for full instructions on each phase.
237-
238-
For phases requiring a Docker container, your image must:
239-
240-
- Read from `/data/features/` (read-only mount)
241-
- Write `ct.nii.gz` to `/data/output/`
242-
- Run within 5 minutes, with 128 GB RAM and no network access
243-
244-
See [docs/docker-packaging.md](docs/docker-packaging.md) for a step-by-step guide to building and testing your container, with the baseline as a worked example.
194+
```
195+
predictions_dir/
196+
├── sub-000/
197+
│ ├── ct.nii.gz # optional
198+
│ └── pet.nii.gz # optional
199+
├── sub-001/
200+
│ ├── ct.nii.gz
201+
│ └── pet.nii.gz
202+
└── ...
203+
```
245204

246205
---
247206

248-
## 💡 Tips & FAQ
249-
250-
_Coming soon._
207+
## 📬 Submission
251208

252-
---
209+
| Phase | What you submit |
210+
|-------|----------------|
211+
| **Validation** | Zip of NIfTI predictions for the 4 `val/` subjects (CT + optional PET) uploaded to Codabench — you run prediction and reconstruction locally using the provided data and tools |
212+
| **Dry Run** | Docker container emailed to us — we run it on the 4 `val/` subjects on our hardware and return CT metrics, or error logs if the container failed |
213+
| **Final Test** | Docker container emailed to us — we run prediction, reconstruction, and full evaluation on the unseen test set |
253214

254-
## 🏛️ Organizers
215+
Validation and Dry Run are open concurrently throughout the challenge. See [docs/submission-guide.md](docs/submission-guide.md) for full instructions, and [docs/docker-packaging.md](docs/docker-packaging.md) for how to build and test your container.
255216

256-
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/).
257217

258-
For full details, timeline, and registration: [bic-mac-challenge.github.io](https://bic-mac-challenge.github.io/)

docs/reconstruction.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# PET Reconstruction Pipeline
2+
3+
The reconstruction pipeline (`src/recon/`) converts a pseudo-CT into an attenuation-corrected PET image using [STIR](http://stir.sourceforge.net/) (Software for Tomographic Image Reconstruction). You do **not** need to understand or modify the pipeline to participate — it is run by the challenge organisers on your submissions. This guide is for participants who want to run it locally for closed-loop training or debugging.
4+
5+
---
6+
7+
## Pipeline Steps
8+
9+
Given a CT (ground-truth or pseudo-CT) and the subject's sinogram data (`recon/`), the pipeline produces a reconstructed PET NIfTI:
10+
11+
1. **Validate CT** — checks shape, affine, and HU range against the ground-truth CT
12+
2. **Swap face and bed** — replaces the face and scanner bed region with ground-truth CT values (so face/bed prediction is not penalised)
13+
3. **HU → μ-map** — converts Hounsfield units to linear attenuation coefficients at 511 keV using the Carney et al. (2006) bilinear model at 120 kVp
14+
4. **Smooth μ-map** — applies a 4 mm FWHM Gaussian to match scanner resolution
15+
5. **Resample to STIR** — resamples the μ-map onto the STIR z-axis grid (ring spacing 3.29114 mm)
16+
6. **Compute ACF sinogram** — forward-projects the μ-map to produce the attenuation correction factor (ACF) sinogram
17+
7. **Apply ACF to additive sinogram** — multiplies ACF into the scatter+randoms estimate
18+
8. **Apply ACF to multiplicative sinogram** — multiplies ACF into the detector normalisation sinogram
19+
9. **OSEM reconstruction** — reconstructs PET via ordered-subsets expectation maximisation with a 4 mm post-filter
20+
10. **Convert to NIfTI** — writes the reconstructed PET with the correct bed/gantry offset origin
21+
22+
Intermediate outputs (μ-map, ACF sinogram, STIR-format files) are written to `output_dir/intermediates/`. The pipeline skips steps whose outputs already exist, so it resumes automatically from a partial run.
23+
24+
---
25+
26+
## Running the Pipeline
27+
28+
### Option 1: Docker (recommended)
29+
30+
A pre-built image with STIR and all dependencies is available.
31+
32+
```bash
33+
docker pull ghcr.io/bic-mac-challenge/recon:latest
34+
35+
docker run --rm \
36+
-v /path/to/sub-000/recon:/data/recon \
37+
-v /path/to/ct.nii.gz:/data/ct/ct.nii.gz \
38+
-v /path/to/output:/data/output \
39+
ghcr.io/bic-mac-challenge/recon:latest
40+
```
41+
42+
The reconstructed PET is written to `/data/output/pet.nii.gz`. A full debug log is written to `/data/output/intermediates/recon.log`.
43+
44+
**Environment variables:**
45+
46+
| Variable | Default | Effect |
47+
|----------|---------|--------|
48+
| `OVERWRITE` | `0` | Set to `1` to ignore existing intermediates and rerun from scratch |
49+
| `VERBOSE` | `0` | Set to `1` to stream STIR subprocess output to the terminal |
50+
51+
```bash
52+
docker run --rm \
53+
-e OVERWRITE=1 \
54+
-e VERBOSE=1 \
55+
-v /path/to/sub-000/recon:/data/recon \
56+
-v /path/to/ct.nii.gz:/data/ct/ct.nii.gz \
57+
-v /path/to/output:/data/output \
58+
ghcr.io/bic-mac-challenge/recon:latest
59+
```
60+
61+
### Option 2: Direct Python (requires local STIR)
62+
63+
```bash
64+
python src/recon/main.py \
65+
--recon_dir <subject_recon_dir> \
66+
--ct <ct.nii.gz> \
67+
--output_dir <output_dir> \
68+
[-w] [-v]
69+
```
70+
71+
| Argument | Description |
72+
|----------|-------------|
73+
| `--recon_dir` | Subject's `recon/` directory (contains sinograms, offset.json, face mask) |
74+
| `--ct` | CT NIfTI file in Hounsfield units |
75+
| `--output_dir` | Directory where `pet.nii.gz` and `intermediates/` will be written |
76+
| `-w` / `--overwrite` | Rerun from scratch, ignoring existing intermediates |
77+
| `-v` / `--verbose` | Stream STIR subprocess output to the terminal |
78+
79+
---
80+
81+
## Expected `recon/` Contents
82+
83+
```
84+
recon/
85+
├── add_nac_rd85.hs / .s # additive sinogram (scatter + randoms)
86+
├── mult_nac_rd85.hs / .s # multiplicative sinogram (normalisation, decay)
87+
├── prompts_rd85.hs / .s # raw prompt coincidences
88+
├── offset.json # bed position and gantry offset
89+
├── ct_face_and_bed.nii.gz # ground-truth CT values at face + scanner bed
90+
└── face_and_bed_mask.nii.gz # binary face + scanner bed mask
91+
```
92+
93+
Only subjects in the full `train/` split and the `val/` split include `recon/` data (see the main README).
94+
95+
---
96+
97+
## Further Reading
98+
99+
- Carney et al. (2006) — *"Method for Transforming CT Images for Attenuation Correction in PET/CT Scanners"*, Medical Physics. The bilinear HU→μ model used in this pipeline.
100+
- Thielemans et al. (2012) — *"STIR: Software for Tomographic Image Reconstruction Release 2"*, Physics in Medicine and Biology. The reconstruction library used here.

0 commit comments

Comments
 (0)