Analysis pipeline for multiplex immunofluorescence whole slide images (OME-TIFF). Performs tissue detection, cell segmentation, feature extraction, marker thresholding, cell phenotyping, and cell count reporting.
| Step | Script | Input | Output |
|---|---|---|---|
| 1. Tissue detection | 01_tissue_detection.py |
OME-TIFF image | Tissue mask + area |
| 2. Cell segmentation | 01_segmentation.py |
OME-TIFF image | Cell label mask |
| 3. Feature extraction | 02_feature_extraction.py |
Image + cell labels | MFI per cell (parquet + anndata) |
| 4. Thresholding | 03_threshold_explorer.ipynb |
Anndata + image | Marker thresholds → YAML |
| 5. Phenotyping | 04_phenotyping.py |
Anndata + YAML plans | Phenotyped anndata |
| 6. Report | 05_report.py |
Phenotyped anndata + tissue area | Cell count CSV |
Dependencies come in two tiers:
- Baseline — everything except cell segmentation: tissue detection, feature extraction, threshold exploration, phenotyping, and reporting. Runs on CPU with the bundled sample data. No GPU or PyTorch required.
- Segmentation (step 2, InstanSeg) — an opt-in extra that requires PyTorch. PyTorch is installed separately because the correct build depends on your hardware (CPU, or a specific CUDA version). See Cell segmentation below.
Examples below use uv (recommended — installs from
the pinned uv.lock for reproducible environments). Equivalent pip commands are
shown where they differ.
# With uv (reproducible, uses uv.lock)
uv sync --extra dev
# Or with pip
python3.12 -m venv .venv
source .venv/bin/activate
pip install ".[dev]"This is all you need for the tutorials and for steps 1, 3, 4, 5, and 6.
Segmentation needs the segmentation extra and PyTorch. Install PyTorch
first (with the build that matches your hardware), then the extra.
⚠️ PyTorch version and your GPU:torch >= 2.6dropped support for NVIDIA V100 (compute capability 7.0). On V100, pintorch <= 2.5.x. Check your CUDA driver withnvidia-smi | grep "CUDA Version".
On a GPU machine:
| GPU | CUDA driver | Install PyTorch with |
|---|---|---|
| V100 | 12.x | pip install torch==2.5.1 --index-url https://download.pytorch.org/whl/cu124 |
| A100 | 12.x | pip install torch==2.5.1 --index-url https://download.pytorch.org/whl/cu124 |
| A100/H100 | 12.6+ | pip install torch==2.6.0 --index-url https://download.pytorch.org/whl/cu126 |
On a CPU-only machine (segmentation works but is slow — fine for small tiles):
pip install torch==2.5.1 --index-url https://download.pytorch.org/whl/cpuFor other configurations, see pytorch.org/get-started/locally.
Then install the segmentation extra:
# With uv
uv sync --extra dev --extra segmentation
# Or with pip (into the same environment where you installed torch)
pip install ".[dev,segmentation]"uv + PyTorch note:
uv sync --extra segmentationresolvestorchfrom the default index, which may not match your GPU/CUDA (and may pick a version that breaks on V100). After syncing, reinstall the correct build into the uv environment, e.g.:uv pip install torch==2.5.1 --index-url https://download.pytorch.org/whl/cu124Alternatively, configure a PyTorch index in
pyproject.tomlfor fully reproducible GPU installs.
Verify the segmentation stack is importable:
python -c "import torch; print('CUDA available:', torch.cuda.is_available())"CUDA available: True means the GPU is detected; False means segmentation will
run on CPU.
Interactive Jupyter notebooks walk through each pipeline step with the bundled sample data (512×512 tile, 7 channels). No GPU required.
| Tutorial | Description |
|---|---|
tutorials/01_tissue_detection.ipynb |
Generate tissue mask, visualize, inspect area |
tutorials/02_cell_segmentation.ipynb |
Visualize cell labels (GPU cell commented out) |
tutorials/03_feature_extraction.ipynb |
Extract MFI, compare raw vs background-corrected |
tutorials/04_phenotyping.ipynb |
Inspect YAML plans, run gating, plot spatial distribution |
tutorials/05_report.ipynb |
Generate and inspect cell count report |
Each step can be run via CLI arguments or a TOML config file:
cp config.toml.example config.toml # copy and edit for your data
# Step 1: Tissue detection
python 01_tissue_detection.py --config config.toml
# Step 2: Cell segmentation (requires GPU)
python 01_segmentation.py --config config.toml
# Step 3: Feature extraction
python 02_feature_extraction.py --config config.toml
# Step 4: Threshold exploration (interactive notebook)
jupyter notebook 03_threshold_explorer.ipynb
# Step 5: Phenotyping
python 04_phenotyping.py --config config.toml
# Step 6: Report
python 05_report.py --config config.tomlOr run each step with CLI arguments directly:
# Tissue detection
python 01_tissue_detection.py --image_fullpath data/sample_IF_image.ome.tiff --output_dir data
# Cell segmentation
python 01_segmentation.py --image_fullpath data/sample_IF_image.ome.tiff --output_dir data
# Feature extraction
python 02_feature_extraction.py \
--image_fullpath data/sample_IF_image.ome.tiff \
--label_fullpath data/cell_segmentation/sample_IF_image_celllabels.ome.tiff \
--af_channel AF --output_dir data
# Phenotyping
python 04_phenotyping.py \
--anndata_fullpath data/anndata/sample_IF_image.h5ad \
--yamls ph_bcell=data/phenotyping/phenotyping_bcell.yml \
ph_plasma=data/phenotyping/phenotyping_plasma.yml
# Report
python 05_report.py \
--anndata_fullpath data/phenotyping/sample_IF_image_phenotyped.h5ad \
--tissue_area_fullpath data/tissue_mask/sample_IF_image_tissue_area.parquetSee config.toml.example for all available parameters.
The baseline install (uv sync --extra dev) covers all non-segmentation tests:
# All tests except segmentation (80 tests, no GPU/PyTorch needed)
pytest tests/ --ignore=tests/test_segmentation.py -v
# Tutorial notebook execution tests
pytest tests/test_tutorials.py -vSegmentation tests require the segmentation extra + PyTorch (see
Installation) and a real image. The model-running
tests skip automatically when those dependencies are absent:
# Segmentation tests (requires segmentation extra + PyTorch, GPU recommended)
pytest tests/test_segmentation.py -v \
--image_fullpath '/path/to/image.ome.tiff'See docs/tests/ for detailed test documentation per step.
├── 01_tissue_detection.py # Tissue mask generation
├── 01_segmentation.py # Cell segmentation (InstanSeg)
├── 02_feature_extraction.py # Per-cell MFI extraction
├── 03_threshold_explorer.ipynb # Interactive threshold tuning
├── 04_phenotyping.py # Hierarchical gating from YAML plans
├── 05_report.py # Cell count and density report
├── lib_sp.py # Shared helper library
├── config.toml.example # Example TOML config
├── pyproject.toml # Dependencies and project metadata
│
├── data/ # Bundled sample data
│ ├── sample_IF_image.ome.tiff # 512x512 tile (7 channels)
│ ├── tissue_mask/ # Tissue mask + area
│ ├── cell_segmentation/ # Cell label mask
│ ├── cell_features/ # Raw + BG-corrected MFI parquets
│ ├── anndata/ # Anndata .h5ad files
│ ├── phenotyping/ # YAML plans + phenotyped anndata
│ └── reports/ # Cell count CSV reports
│
├── tutorials/ # Step-by-step tutorial notebooks
├── tests/ # Pytest suite (80+ tests)
├── docs/tests/ # Test documentation
└── src_original/ # Original reference scripts
OME-TIFF image
|
|---> 01_tissue_detection.py ---> tissue mask + area (parquet)
| |
|---> 01_segmentation.py ---> cell labels |
| | |
+---> 02_feature_extraction.py ---> anndata (.h5ad)
|
03_threshold_explorer.ipynb |
| |
v |
YAML plans (thresholds) |
| |
+---> 04_phenotyping.py ---> phenotyped anndata
|
v
05_report.py <--- tissue area
|
v
report CSV (counts + densities)