Dependencies
The runtime stack grouped by layer, the externally supplied metrics package, the hardware the pipeline assumes, and the internal module import graph.
1. Runtime stack
The project targets Python 3.11 or newer and is managed with uv against a lockfile,
so the resolved dependency set is byte-reproducible. Dependencies group into six functional
families, each corresponding to a distinct layer of the system:
| Family | Packages | Role |
|---|---|---|
| Deep learning core | torch, torchvision |
Tensors, autograd, distributed training primitives, 3D convolution. |
| Medical imaging | monai, nibabel |
The DynUNet backbone, all pre-processing transforms, sliding-window inference. |
| Training ergonomics | transformers, accelerate, peft |
The Trainer abstraction that supplies the training loop, gradient
accumulation, checkpointing and callbacks.
|
| Configuration & tracking | hydra-core, omegaconf, wandb |
Layered experiment configuration and experiment tracking. |
| nnU-Net | nnunetv2 |
Dataset fingerprinting, automatic configuration and the second training pipeline. |
| Scientific computing & IO |
numpy, scipy, scikit-image,
scikit-learn, pandas, tifffile,
imagecodecs, einops, matplotlib
|
Array maths, connected-component and morphology work, metadata handling, TIFF encoding and visualisation. |
surface-distance supplies the boundary-overlap computation, and
pyarrow supports tabular metadata. Notebook tooling
(ipykernel, ipywidgets, ipympl) is included for local
exploratory analysis; the notebooks themselves are working files and are not part of the
published repository.
2. The external metrics package
One prerequisite is supplied outside this repository
The competition metric implementation is an installable package
(topometrics) that the metrics module imports. It is not declared in
this project’s dependency manifest and not installed as a normal transitive dependency. The
environment must provide it, typically as an editable install pointing at a local checkout of the
metrics implementation. Without it, importing the metrics module — and therefore running any
scoring pass — fails immediately with an unresolved import.
This is a reasonable boundary: the metric is a shared, separately versioned artifact that should not be forked into every participating repository. But it does mean the environment has one non-obvious prerequisite, and the Getting Started page documents how to satisfy it.
3. Hardware assumptions
| Resource | Assumption | Where it bites |
|---|---|---|
| GPU | One or more CUDA devices; multi-GPU training is the default entry point. | Training throughput and the launch form of the entry point. |
| GPU memory | The default patch size is chosen to fit a single large-memory device, with a batch size of one patch per step and gradient accumulation where more effective batch size is needed. | Patch size and batch size in the experiment configuration. |
| Storage | Converted arrays are held on fast local storage separate from the repository; a run writes checkpoints and a resolved configuration per experiment. | Path configuration; the data directory is not inside the repository. |
| CPU / workers | Enough cores for a substantial dataloader worker pool and prefetching. | Training-loop stall behaviour, and the parallel scoring pass. |
4. Import graph and dependency direction
The custom pipeline has a clean, one-directional internal dependency structure:
train.py
├─ configs/ (resolved configuration)
├─ data/dataset.py ──→ MONAI transforms, custom transforms
├─ models/unet.py ──→ MONAI DynUNet
├─ utils/losses.py ──→ signed/unsigned distance fields
├─ utils/loss_weight_schedule.py
└─ utils/logger.py
inference.py ──→ models/unet.py
metrics/kaggle_metrics.py ──→ external topometrics package, scikit-image
The important property is that data/, models/ and
utils/ do not import the training entry point, and inference depends on the model
definition without depending on the trainer. That means a model can be instantiated, an
inference run performed, or a loss evaluated without constructing the training stack —
which is exactly what happens in tests and in the scoring lab.
5. Dependency management
uv sync install the locked environment
uv add <package> add a dependency and update the lockfile
uv lock --upgrade-package <pkg> move one package within its constraints
Because the lockfile is committed, environment drift between machines is a lockfile diff rather
than an invisible difference in resolved versions. Two practical consequences: a dependency change
should always land together with its lockfile update, and reproducing a historical run requires
checking out the lockfile from that point in time rather than just uv sync on the
current commit.