Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8ad3d53
address dilation components first for speedup
Hendrik-code Jun 1, 2026
acf65e0
added flair
Hendrik-code Jun 1, 2026
9bab59c
changed rescale_ to from_to_() function
Hendrik-code Jun 1, 2026
70881c7
Merge branch 'main' into resolution_fixes
Hendrik-code Jun 1, 2026
d2785d3
refactor: extract inference-config magic numbers to named constants
Hendrik-code Jun 1, 2026
2470c06
refactor: name domain magic numbers in post-processing and labeling-p…
Hendrik-code Jun 1, 2026
c0f5e65
refactor: name magic numbers in pipeline, pre and semantic phases
Hendrik-code Jun 1, 2026
36901ca
refactor: de-duplicate model lookup and name model magic numbers
Hendrik-code Jun 1, 2026
54f1b4f
refactor: name labeling magic numbers and resolve cost-matrix TODOs
Hendrik-code Jun 1, 2026
965af80
refactor: name instance-segmentation and run magic numbers
Hendrik-code Jun 1, 2026
17a9132
docs: add Google-style docstrings across the codebase
Hendrik-code Jun 1, 2026
9f1202b
fix: MetaEnum.__contains__ returns False for unknown names instead of…
Hendrik-code Jun 1, 2026
6f15417
test: add 109 unit tests for pure functions (coverage 43% -> 46%)
Hendrik-code Jun 1, 2026
6c5601b
docs: add MkDocs documentation site (mirroring TPTBox setup)
Hendrik-code Jun 1, 2026
e4a6cfa
docs: add type annotations to resolve mkdocstrings/griffe warnings
Hendrik-code Jun 1, 2026
374dd8f
test: add mocked-inference tests for GPU model paths (coverage 46% ->…
Hendrik-code Jun 1, 2026
c92babb
test: cover the classifier forward path (lab_model 27% -> 77%)
Hendrik-code Jun 1, 2026
088394d
feat: mm-based dynamic thresholds in instance phase (CT support, step 1)
Hendrik-code Jun 1, 2026
f851491
feat: mm-based dynamic thresholds in semantic/post/pre phases (CT sup…
Hendrik-code Jun 1, 2026
b7530e5
test: add resolution-helper tests; fix stale constant references in d…
Hendrik-code Jun 1, 2026
3b26f71
refactor: de-duplicate constants shared across modules
Hendrik-code Jun 1, 2026
d68b8d5
fix: same_modelzoom_as_model must compare absolute zoom difference
Hendrik-code Jun 1, 2026
3c43d11
test: prefix unused unpacked variables with underscore (RUF059)
Hendrik-code Jun 1, 2026
ff1cbf2
build: enable RUF059 in ruff config so pre-commit catches unused unpa…
Hendrik-code Jun 1, 2026
2ec41e4
docs: link the hosted documentation from project metadata and README
Hendrik-code Jun 1, 2026
31e1042
docs: harden Read the Docs build to avoid installing heavy runtime deps
Hendrik-code Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 2

build:
os: ubuntu-24.04
tools:
python: "3.12"
jobs:
# Install only the docs toolchain. The SPINEPS package itself is intentionally NOT installed:
# its heavy runtime dependencies (torch, nnunetv2, antspyx, monai, ...) can exceed Read the Docs
# build time/memory limits. mkdocstrings' griffe backend reads the package source statically
# (see the `paths` option in mkdocs.yml), so those dependencies are not needed to render the docs.
post_install:
# ruff is only used by mkdocstrings to format rendered signatures (lightweight, no build deps).
- pip install "mkdocs>=1.6" "mkdocs-material>=9.5" "mkdocstrings[python]>=0.25" ruff

mkdocs:
configuration: mkdocs.yml
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
[![codecov](https://codecov.io/gh/Hendrik-code/spineps/graph/badge.svg?token=A7FWUKO9Y4)](https://codecov.io/gh/Hendrik-code/spineps)
[![tests](https://github.com/Hendrik-code/spineps/actions/workflows/tests.yml/badge.svg)](https://github.com/Hendrik-code/spineps/actions/workflows/tests.yml)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Documentation Status](https://readthedocs.org/projects/spineps/badge/?version=latest)](https://spineps.readthedocs.io)

# SPINEPS – Automatic Whole Spine Segmentation of T2w MR images using a Two-Phase Approach to Multi-class Semantic and Instance Segmentation.
# and
Expand All @@ -14,6 +15,20 @@ This is a segmentation pipeline to automatically, and robustly, segment the whol

![pipeline_process](spineps/example/figures/pipeline_processflow.png?raw=true)

## Documentation

📖 **Online documentation: [spineps.readthedocs.io](https://spineps.readthedocs.io)**

The documentation source lives in the [`docs/`](docs/) folder and is built with [MkDocs](https://www.mkdocs.org/)
(Material theme + [mkdocstrings](https://mkdocstrings.github.io/)). To build and preview it locally:

```bash
pip install mkdocs mkdocs-material "mkdocstrings[python]"
mkdocs serve # then open http://127.0.0.1:8000
```

Start with [`docs/index.md`](docs/index.md) and the [Getting Started](docs/getting-started.md) guide.

## Citation

If you are using SPINEPS, please cite the following:
Expand Down
19 changes: 19 additions & 0 deletions docs/api/architectures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Architectures

Network architectures and the vertebra label definitions used by the models.

## spineps.architectures.read_labels

::: spineps.architectures.read_labels

## spineps.architectures.pl_densenet

::: spineps.architectures.pl_densenet

## spineps.architectures.pl_unet

::: spineps.architectures.pl_unet

## spineps.architectures.unet3D

::: spineps.architectures.unet3D
11 changes: 11 additions & 0 deletions docs/api/enums.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Enums & Config

Enumerations and the inference-configuration model used throughout SPINEPS.

## spineps.seg_enums

::: spineps.seg_enums

## spineps.utils.seg_modelconfig

::: spineps.utils.seg_modelconfig
15 changes: 15 additions & 0 deletions docs/api/models.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Models

Model discovery/loading and the segmentation/labeling model classes.

## spineps.get_models

::: spineps.get_models

## spineps.seg_model

::: spineps.seg_model

## spineps.lab_model

::: spineps.lab_model
23 changes: 23 additions & 0 deletions docs/api/phases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Processing Phases

The per-phase processing functions that make up the pipeline.

## spineps.phase_pre

::: spineps.phase_pre

## spineps.phase_semantic

::: spineps.phase_semantic

## spineps.phase_instance

::: spineps.phase_instance

## spineps.phase_labeling

::: spineps.phase_labeling

## spineps.phase_post

::: spineps.phase_post
15 changes: 15 additions & 0 deletions docs/api/pipeline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Pipeline & Run

Top-level orchestration: process a single image or a whole dataset, and shared pipeline helpers.

## spineps.seg_run

::: spineps.seg_run

## spineps.seg_pipeline

::: spineps.seg_pipeline

## spineps.seg_utils

::: spineps.seg_utils
31 changes: 31 additions & 0 deletions docs/api/utils.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Utilities

Image processing, the vertebra-labeling path solver, disc labeling and other helpers.

## spineps.utils.proc_functions

::: spineps.utils.proc_functions

## spineps.utils.find_min_cost_path

::: spineps.utils.find_min_cost_path

## spineps.utils.generate_disc_labels

::: spineps.utils.generate_disc_labels

## spineps.utils.filepaths

::: spineps.utils.filepaths

## spineps.utils.auto_download

::: spineps.utils.auto_download

## spineps.utils.citation_reminder

::: spineps.utils.citation_reminder

## spineps.utils.compat

::: spineps.utils.compat
128 changes: 128 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Getting Started

This guide walks you through installing SPINEPS and running your first segmentation.

## Installation (Ubuntu)

This installation assumes you are comfortable with conda and virtual environments. **The order of the
following steps matters.**

### 1. Create a virtual environment

```bash
conda create --name spineps python=3.11
conda activate spineps
conda install pip
```

### 2. Install PyTorch

Go to [pytorch.org/get-started/locally](https://pytorch.org/get-started/locally/) and install a PyTorch
build that matches your machine. Then confirm the install works:

```bash
nvidia-smi # should show your GPU
python -c "import torch; print(torch.cuda.is_available())" # should print True
```

### 3. Install SPINEPS

From PyPI:

```bash
pip install spineps
```

Or, for local development, clone the repository, `cd` into it and run:

```bash
pip install -e .
```

## Model weights

SPINEPS automatically downloads the latest model weights on first use, so no manual setup is required.

If you prefer to manage weights manually, download them from the GitHub release page and extract them into
a models folder with the following structure:

```text
<models_folder>
├── <model_name 1>
│ ├── inference_config.json
│ └── <other model-specific files>
├── <model_name 2>
│ ├── inference_config.json
│ └── ...
```

Point SPINEPS at that folder via an environment variable (otherwise it defaults to `spineps/spineps/models/`):

```bash
export SPINEPS_SEGMENTOR_MODELS=<PATH-to-your-folder>
echo ${SPINEPS_SEGMENTOR_MODELS} # verify it is set
```

## Usage

### Command line

```bash
spineps -h # top-level help
spineps sample -h # options for a single file
spineps dataset -h # options for a whole dataset
```

Segment a single scan:

```bash
# T2w sagittal
spineps sample -ignore_bids_filter -ignore_inference_compatibility \
-i /path/sub-testsample_T2w.nii.gz -model_semantic t2w -model_instance instance

# T1w sagittal
spineps sample -ignore_bids_filter -ignore_inference_compatibility \
-i /path/sub-testsample_T1w.nii.gz -model_semantic t1w -model_instance instance
```

Process a whole [BIDS](https://bids-specification.readthedocs.io/en/stable/) dataset:

```bash
spineps dataset -i /path/to/dataset -model_semantic t2w -model_instance instance
```

### Adding vertebra labels (VERIDAH)

To assign anatomical vertebra labels after segmentation, additionally pass a labeling model:

```bash
spineps sample -i /path/sub-test_T2w.nii.gz \
-model_semantic t2w -model_instance instance -model_labeling labeling
```

### From Python

```python
from TPTBox import BIDS_FILE
from spineps import get_semantic_model, get_instance_model, process_img_nii

semantic = get_semantic_model("t2w")
instance = get_instance_model("instance")

# img_ref is a TPTBox BIDS_FILE pointing at the input scan
img_ref = BIDS_FILE("sub-test_T2w.nii.gz", dataset="/path/to/dataset")

process_img_nii(
img_ref,
model_semantic=semantic,
model_instance=instance,
derivative_name="derivatives_seg",
)
```

See the [Pipeline](modules/pipeline.md) page for more detail on the Python entry points.

## Troubleshooting

- **Import issues**: re-run the install; sometimes not every dependency installs the first time.
- **PyTorch / CUDA issues**: make sure the PyTorch build matches your CUDA version (step 2 above).
63 changes: 63 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# SPINEPS

**SPINEPS** is a framework for out-of-the-box **whole-spine segmentation of MR images**. It segments the
spine in sagittal MR images (T2w, T1w and others) using a two-phase approach to multi-class **semantic**
and **instance** segmentation, and can additionally assign anatomical **vertebra labels** via the
**VERIDAH** labeling model.

[![Paper](https://img.shields.io/badge/Paper-10.1007-blue)](https://link.springer.com/article/10.1007/s00330-024-11155-y)
[![PyPI version](https://badge.fury.io/py/spineps.svg)](https://pypi.python.org/pypi/spineps/)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

![Pipeline process flow](https://github.com/Hendrik-code/spineps/raw/main/spineps/example/figures/pipeline_processflow.png)

## What it does

Given a sagittal MR scan, the pipeline:

1. **Semantically** segments 14 spinal structures (nine vertebra subregions, spinal cord, spinal canal,
intervertebral discs, endplate and sacrum).
2. Derives a per-vertebra **instance** mask from the vertebra subregions.
3. Optionally assigns each instance an anatomical **vertebra label** (C1–L6, sacrum) with VERIDAH.
4. Computes **centroids** (points of interest) for each vertebra, endplate and disc.
5. Renders a **snapshot** visualizing the result.

## Quick links

- [Getting Started](getting-started.md) — installation and first run.
- [Pipeline](modules/pipeline.md) — how the two-phase pipeline is structured.
- [Processing Phases](modules/phases.md) — pre-processing, semantic, instance, labeling and post-processing.
- [Models & Labeling](modules/models.md) — model loading and the VERIDAH labeling model.
- [API Reference](api/pipeline.md) — full auto-generated API documentation.

## Quick start

```bash
# Install
pip install spineps

# Segment a single T2w sagittal scan
spineps sample -i /path/sub-test_T2w.nii.gz -model_semantic t2w -model_instance instance
```

See [Getting Started](getting-started.md) for the full installation guide (including PyTorch setup and
model weights), and the [Pipeline](modules/pipeline.md) page for calling SPINEPS from Python.

## Citation

If you use SPINEPS, please cite:

```bibtex
@article{moller_spinepsautomatic_2024,
title = {{SPINEPS}—automatic whole spine segmentation of T2-weighted {MR} images using a two-phase approach to multi-class semantic and instance segmentation},
doi = {10.1007/s00330-024-11155-y},
journal = {European Radiology},
author = {Möller, Hendrik and Graf, Robert and Schmitt, Joachim and Keinert, Benjamin and Schön, Hanna and Atad, Matan and Sekuboyina, Anjany and Streckenbach, Felix and Kofler, Florian and Kroencke, Thomas and Bette, Stefanie and Willich, Stefan N. and Keil, Thomas and Niendorf, Thoralf and Pischon, Tobias and Endemann, Beate and Menze, Bjoern and Rueckert, Daniel and Kirschke, Jan S.},
date = {2024-10-29},
}
```

## License

SPINEPS is released under the [Apache License 2.0](https://opensource.org/licenses/Apache-2.0).
Copyright 2023 Hendrik Möller.
Loading
Loading