Getting Started

Getting Started

Prerequisites, environment setup, the one external dependency, the expected data layout, and the commands for training, inference, scoring and the nnU-Net baseline.

1. Prerequisites

RequirementNotes
Python 3.11+ The project targets 3.11 or newer.
uv Used for environment creation and dependency resolution against the committed lockfile.
NVIDIA GPU with CUDA Training and inference both require a GPU. Multi-GPU is supported and is the default training path.
Fast local storage Converted volumes, checkpoints and prediction volumes are all large, and none of them belong inside the repository.
Competition data CT volumes and labels, converted to the array layout the dataset expects.
The external metrics package See the callout below — required for any scoring pass.

2. Install

git clone <repository>
cd vesuvius
uv sync

uv sync creates the virtual environment and installs exactly the versions recorded in the lockfile. Use it in preference to a bare pip install: the lockfile is what makes an environment reproducible across machines.

Install the metrics package separately The competition metric is supplied as an external, separately versioned package rather than as a declared dependency of this project, so it is not installed by uv sync. Install it into the same environment before running anything that imports the metrics module — typically as an editable install pointing at a local checkout of the metrics implementation. If a scoring run fails immediately with an unresolved import for the topological metrics package, this is the cause. The requirement is described in Dependencies.

3. Environment variables

Runtime paths and tracking settings are supplied through the environment. The conventional pattern in this repository is to keep them in a .env file at the repository root and export the whole file before invoking a command, which is exactly what the Makefile does:

set -a && . .env && set +a
VariablePurposeRequired
BASE_DIR Root directory used to locate the shared configuration files and, from there, the data and output directories. Defaults to the repository root when unset, so it only needs setting if configuration lives elsewhere. Optional
NVME_DIR Fast-storage root used by the data conversion and synthetic-data generation scripts. For those scripts
WANDB_* Tracking project, entity, run name, directory and mode. Normally set programmatically from the resolved configuration rather than by hand, but they can be exported to override it. Optional
CUDA_VISIBLE_DEVICES Restricts which devices a process may use. Essential for the partitioned nnU-Net prediction path, where each worker is pinned to a single GPU. For multi-GPU work
NNUNET_* The nnU-Net raw, preprocessed and results directories. The nnU-Net driver sets these itself from its own configuration, so they rarely need setting by hand. Set by the driver

Note the interaction between the distributed launcher and CUDA_VISIBLE_DEVICES: the launcher sets a local rank per process, and the code uses that rank to select a device. Setting CUDA_VISIBLE_DEVICES on top of that renumbers the visible devices, so the two are best used separately — launcher-driven for training, explicit pinning for the partitioned prediction path.

4. Data layout

Scans arrive as TIFF and are converted once to NumPy arrays. Training reads the converted form, so the conversion step is a one-time preparation rather than part of the training loop:

<data_dir>/
├── train_images/<case_id>.npy     input volumes
└── train_labels/<case_id>.npy     label volumes (0 / 1 / 2)

<base_dir>/
├── configs/                        shared configuration
└── data/raw/kaggle_converted/      where scoring expects to find labels

The case identifier is the filename stem, and the same identifier appears in prediction filenames and score reports. Keeping that naming convention intact is what makes a case traceable from a metric back to the volume that produced it.

5. Run training

Every run is identified by an approach and an experiment. The multi-GPU entry point is the Makefile target, which is the most complete example of the expected invocation:

make unetbasic-train

# equivalently, spelled out:
set -a && . .env && set +a
PYTHONPATH=$(pwd)/src uv run torchrun \
    --nproc_per_node=2 \
    src/approach/unetbasic/train.py \
    --experiment exp_v0

Points to be aware of when adapting this:

  • PYTHONPATH must include src/, because the approach packages live under src/approach/ rather than at the top level.
  • --nproc_per_node should match the number of GPUs you want to use; the code derives rank and world size from the launcher’s environment.
  • The experiment name selects the YAML under the approach’s configs/experiments/ directory. Switching experiments is switching a name, not editing code.
  • For a single-GPU run, invoke train.py directly instead of under the distributed launcher.

A run writes everything into outputs/<approach>/<experiment>/ — checkpoints, the resolved configuration, and tracking logs. The layout is documented in Deployment.

6. Run inference

Inference is a separate entry point that loads a checkpoint and writes predictions for a directory of images:

make dynclassreg-infer      # single-GPU example, edit CHECKPOINT first

# equivalently:
PYTHONPATH=$(pwd)/src uv run python \
    src/approach/unetbasic/inference.py \
    --experiment exp_v0 \
    --checkpoint <checkpoint_dir> \
    --images_dir <input_images_dir> \
    --output_dir <output_dir> \
    --batch_size 1 \
    --num_workers 4

The output directory receives one probability array and one distance array per case, plus the metadata that ties each prediction to its source case. Both arrays are written in half precision to keep whole-volume artifacts a manageable size.

Check the defaults before you rely on them Several inference arguments have absolute default paths baked in from the machine the pipeline was developed on. Always pass --checkpoint, --images_dir and --output_dir explicitly rather than depending on the defaults.

7. Score a prediction

Scoring consumes a directory of predictions and reports the four numbers that matter: SurfaceDice, TopoScore, VoiScore and the composite score. Two entry points exist:

Entry pointUse it for
src/approach/unetbasic/metrics/kaggle_metrics.py The scoring path used during development: threshold, apply a post-processing configuration, and average the component metrics over cases.
exploration/scoring/ Comparing post-processing strategies. This is where you sweep approaches rather than accept one, and where new strategies are registered.

A scoring pass is CPU-bound and parallelises across cases, so it benefits from a large core count. Both entry points accept a sequential mode, which is much easier to debug when a single case produces an unexpected number.

8. Run the nnU-Net baseline

The nnU-Net pipeline is a self-contained driver that can run end to end or stage by stage:

PYTHONPATH=$(pwd)/src uv run python scripts/nnunetbaseline/train_nnunetv2.py

Its stages are dataset preparation, preprocessing, training, prediction and TIFF export. Run the stages individually while iterating: preprocessing is the slowest step and there is rarely a reason to repeat it because a training setting changed.

9. First things to check

SymptomLikely cause
Import error for the topological metrics package The external metrics package has not been installed into this environment.
ModuleNotFoundError for approach.* PYTHONPATH does not include src/.
Training starts but data is not found The data directory in the resolved configuration does not match where the converted arrays live.
Out-of-memory error on the GPU Patch size, batch size and gradient accumulation in the experiment configuration.
Checkpoints written to an unexpected place Absolute defaults in the inference or training arguments; pass explicit paths.
Scoring reports zeros No prediction files were found in the directory passed to the scorer, or the patch metadata does not match the predictions.