Computational pathology toolkit: tiling, feature extraction, and annotation for whole-slide images using foundation models
8
stars
733
commits
Python
primary language
Aug 21, 2026
updated
This is a fork of Faisal Mahmood's CLAM repository (GPL v3 license), with a handful of modifications:
Supported systems:
Mussel reads whole-slide images via tiffslide (backed by tifffile). The following formats are supported:
| Extension | Format | Scanner / Vendor | Tiffslide support |
|---|---|---|---|
.svs | Aperio SVS | Leica (Aperio) | ✅ Full |
.scn | Leica SCN | Leica | ✅ Full |
.tif / .tiff | TIFF, BigTIFF, OME-TIFF | Generic / various | ✅ Full |
.ndpi | Hamamatsu NDPI | Hamamatsu | ⚠️ Partial — see notes |
.bif | Ventana BIF | Roche (Ventana) | ⚠️ Partial — see notes |
.mrxs | MIRAX | 3DHISTECH | ⚠️ Generic TIFF — see notes |
.vms / .vmu | Hamamatsu VMS / VMU | Hamamatsu | ⚠️ Generic TIFF — see notes |
.qptiff | PerkinElmer / Akoya QPTIFF | PerkinElmer / Akoya | ⚠️ Generic TIFF — see notes |
.czi | Carl Zeiss CZI | Zeiss | ⚠️ Generic TIFF — see notes |
Format support notes:
tiffslide.mpp-x.tiff.XResolution / tiff.ResolutionUnit).
Most Hamamatsu scanners embed resolution in TIFF tags, so this works in practice.
If MPP is wrong or missing, use seg_config.slide_mpp_override.seg_config.slide_mpp_override if MPP is not found automatically..mrxs
file must be accompanied by its sidecar directory (same name, no extension) in the same
location; moving only the .mrxs file will cause a read error.MPP (microns per pixel) retrieval — Mussel reads MPP from slide metadata using the following fallback chain:
slide_mpp_override CLI parameter — if provided, used directly; all metadata reading is skippedtiffslide.mpp-x — standard property populated by tiffslide for all supported formatsaperio.MPP / openslide.mpp-x — legacy vendor property namestiff.XResolution + tiff.ResolutionUnit — raw TIFF resolution tags converted to µm/px;
tiffslide exposes these for partially-supported formats (NDPI, BIF, MRXS, QPTIFF, CZI)
even when it cannot normalize them to tiffslide.mpp-xaperio.AppMag, openslide.objective-power,
and tiffslide.objective-power; computes MPP as 10.0 / magnificationWhen slides lack MPP metadata and the default 0.5 µm/px doesn't match the actual scanner resolution, pass the known value explicitly:
tessellate slide_path=slide.svs seg_config.slide_mpp_override=1.0 ...
tessellate_extract_features slide_path=slide.svs seg_config.slide_mpp_override=0.25 ...
export_tiles slide_path=slide.svs slide_mpp_override=0.5 ...
curl -LsSf https://astral.sh/uv/install.sh | sh
Model inference may require either PyTorch or TensorFlow, depending on which foundation models you wish to use. Because it can be challenging to satisfy the dependencies for both of those at the same time, you need to choose whether to install the module for PyTorch or for TensorFlow.
In addition, you can choose to install Mussel with or without GPU support. GPUs are necessary to run model inference for feature extraction or for generating class embeddings, but other operations can just run on cpus. (Technically, model inference can just run on cpus, as well, but it's very slow.)
Install PyTorch support first, then models are downloaded automatically on first use:
uv sync --extra torch-gpu # GPU (CUDA) — recommended
uv sync --extra torch-cpu # CPU only (Mac or CPU-only Linux)
PyTorch is required for the following patch encoders:
And the following slide encoders (aggregate patch features into a single slide embedding):
| Model | model_type | Patch encoder | Access | HuggingFace |
|---|---|---|---|---|
| Prov-GigaPath | GIGAPATH_SLIDE | GIGAPATH | 🔒 gated | prov-gigapath/prov-gigapath |
| TITAN | TITAN_SLIDE | CONCH1_5 | 🔒 gated | MahmoodLab/TITAN |
| PRISM | PRISM_SLIDE | VIRCHOW | 🔒 gated | paige-ai/Prism |
| FEATHER | FEATHER_SLIDE | CONCH1_5 | 🔒 gated | MahmoodLab/abmil.base.conch_v15.pc108-24k |
| MADELEINE | MADELEINE_SLIDE | CLIP | 🔒 gated | MahmoodLab/madeleine |
| CHIEF | CHIEF_SLIDE | CTRANSPATH | ⬇ access req. | hms-dbmi/CHIEF |
🔒 Gated models require signing an access agreement on the HuggingFace model page and setting your token:
export HF_TOKEN=hf_...
⬇ Models requiring access request are downloaded automatically once access is granted:
| Model | Request access | Notes |
|---|---|---|
CHIEF (CHIEF_SLIDE) | Google Drive folder | Request via hms-dbmi/CHIEF; gdown downloads automatically on first use |
TransPath (CTRANSPATH) and CHIEF (CHIEF_SLIDE) are downloaded automatically via gdown on first use (cached in the HuggingFace hub cache directory).
GenBio-PathFM (GENBIO_PATHFM) downloads its model architecture code from GitHub on first use and caches it at ~/.cache/mussel/genbio_pathfm/. The model weights are downloaded from HuggingFace (requires a token with access to genbio-ai/genbio-pathfm).
OpenMidnight (OPENMIDNIGHT) uses the DINOv2 ViT-G/14 architecture from the facebookresearch/dinov2 torch.hub repository. On first use, Mussel downloads the repository code and caches it at ~/.cache/torch/hub/facebookresearch_dinov2_main/. The model weights are downloaded from HuggingFace (requires a token with access to SophontAI/OpenMidnight).
TensorFlow is required for GooglePath only:
| Model | model_type | Access | HuggingFace |
|---|---|---|---|
| GooglePath | GOOGLEPATH | 🔒 gated | google/path-foundation |
uv sync --extra tensorflow-gpu # GPU (CUDA)
uv sync --extra tensorflow-cpu # CPU only (e.g. Mac)
seg_model="neural")Mussel includes built-in neural tissue segmentation using a DeepLabV3-ResNet50 model (2-class: tissue vs background) trained on histopathology slides as part of the HEST project at the Mahmood Lab, Harvard Medical School.
Pre-trained weights are hosted at MahmoodLab/hest-tissue-seg on HuggingFace and are downloaded automatically on first use (no account or token required). The model operates at 1 µm/px; Mussel handles resampling automatically.
Reference: Chan et al., "A Pathology Foundation Model for Cancer Diagnosis and Prognosis Prediction", Nature 2025. [paper] [GitHub] [HuggingFace model card]
No extra packages are required — it works with any torch-gpu or torch-cpu install:
uv sync --extra torch-gpu
Then pass seg_config.seg_model=neural to tessellate or
tessellate_extract_features. A CUDA GPU is recommended for practical
performance but CPU inference is supported.
Neural runtime controls are available under neural_config.* (weights path,
device, batch size, confidence threshold, and max_inference_tiles) for
tessellate, tessellate_extract_features, and filter_tessellate. An explicit
neural device takes precedence over the workflow's use_gpu setting; auto
uses that setting. Use
seg_config.max_tiles with seg_config.max_tiles_strategy and
seg_config.max_tiles_seed to cap and reproducibly sample the final output tiles.
For stain classification, use seg_config=stain. This speed-oriented preset
uses bounded neural validation, keeps up to 32 tiles with at least 75% tissue,
checks at most 256 candidates, and honors neural_config.max_inference_tiles as
an additional inference budget. It avoids full-slide neural inference; when
fewer than 32 candidates qualify or the inference budget is reached, it returns
the qualifying tiles without relaxing the tissue cutoff.
uv run <command...> are automatically executed in the project environment.uv by executingsource .venv/bin/activate
uv pip or conda to install
one of Mussel[torch-gpu], Mussel[tensorflow-gpu], Mussel[torch-cpu], or Mussel[tensorflow-cpu]
into that environment. (Here, Mussel would be replaced with the path to the Mussel
repo you've checked out.)(The example commands in README-commands.md all expect you to have a activated python environment, so that uv run isn't necessary.)
uv sync --extra <extra-deps> to install this project and its dependencies into the project's virtual environment,
where is one of torch-gpu, tensorflow-gpu, torch-cpu, or tensorflow-cpuuv sync --extra <extra-deps> after making any changes to the requirements.uv sync --extra torch-gpu
Mussel can process slides stored on the cloud or remote object stores via the tiffslide and fsspec packages. In order to properly configure mussel for this use case ensure that you:
uv sync --extra remote~/.aws/credentials)fsspec defined in your configuration in ~/.config/fsspec/ directory (e.g. you have a ~/.config/fsspec/s3.json file with the profile set to the profile defined in ~/.aws/credentials and all required client_kwargs are specified)Make sure that the dev dependencies are installed. (They should be installed by default.)
uv run pytest tests
To install this module into an existing Python environment, activate that environment and install mussel and its extra dependencies with the command, (for example)
uv pip install .[torch-gpu]
Mussel provides a set of CLI tools for tiling whole-slide images, working with tiled slides, and generating feature embeddings with pathology foundation models. The tools currently available from Mussel are,
tessellate - tiling and foreground detection of whole-slide imagestessellate_extract_features - combined tiling + feature extraction pipeline; supports batch processing from a directoryextract_features - extract features from whole slide images (WSI) using a foundation model.create_class_embeddings - generate tissue-type embeddings for classifying tilesannotate - annotate tiles with tissue-typescache_tiles - save tile information in an efficient form for trainingexport_tiles - export tiles as individual .png files using an HDF5 tile-coordinate manifest.filter_features - filter features using a classifier modelmerge_annotation_features - merge tile features with annotations from a BMP file.linear_probe_benchmark - benchmark a linear probe classifier on features extracted from a slidesave_model - download and save a foundation model locallyconvert - convert whole-slide images to pyramidal TIFF format (single file or batch)These are described, with examples, in the accompanying document, README-commands.md
For running Mussel at scale on a compute cluster, see mussel-nf — a Nextflow pipeline that wraps the Mussel CLI tools and handles job scheduling, parallelism, and output management across large slide cohorts.
Mussel supports building Docker containers with flash-attn 2.0 for accelerated attention in the CONCH1.5 patch encoder and the Prov-GigaPath slide encoder. Flash attention provides ~30-50% speedup on patch encoding (~20% overall TITAN pipeline improvement).
Building the flash-attn container:
# Build Docker image with flash-attn backend
make docker-build BACKEND=fastattn
# Or manually:
docker build --build-arg BACKEND=fastattn -t mussel:fastattn .
# Convert to Apptainer SIF for HPC deployment
make sif
# Or manually:
apptainer build --force mussel-fastattn.sif docker-daemon://mussel:fastattn
Key details:
[fastattn] extra in pyproject.toml installs:
SDPBackend.EFFICIENT_ATTENTION (Phase 1 optimization); flash-attn accelerates CONCH1.5 patch encoding and GigaPath slide encodingUsing with mussel-nf:
Copy the SIF to your mussel-nf repo and use the apptainer_fastattn profile:
cp mussel-fastattn.sif /path/to/mussel-nf/
cd /path/to/mussel-nf
nextflow run main.nf -profile cluster,slurm,apptainer_fastattn ...
The profile automatically uses the flash-attn container for FEATURIZE tasks.
This code is made available under the GPLv3 License and is available for non-commercial academic purposes. Forked from CLAM, © Mahmood Lab.
Please cite the original CLAM paper:
Lu, M.Y., Williamson, D.F.K., Chen, T.Y. et al. Data-efficient and weakly supervised computational pathology on whole-slide images. Nat Biomed Eng 5, 555–570 (2021). https://doi.org/10.1038/s41551-020-00682-w
@article{lu2021data,
title={Data-efficient and weakly supervised computational pathology on whole-slide images},
author={Lu, Ming Y and Williamson, Drew FK and Chen, Tiffany Y and Chen, Richard J and Barbieri, Matteo and Mahmood, Faisal},
journal={Nature Biomedical Engineering},
volume={5},
number={6},
pages={555--570},
year={2021},
publisher={Nature Publishing Group}
}
Python
97.4%
Shell
1.3%
Makefile
1.1%
Computational pathology toolkit: tiling, feature extraction, and annotation for whole-slide images using foundation models
8
stars
733
commits
Python
primary language
Aug 21, 2026
updated
This is a fork of Faisal Mahmood's CLAM repository (GPL v3 license), with a handful of modifications:
Supported systems:
Mussel reads whole-slide images via tiffslide (backed by tifffile). The following formats are supported:
| Extension | Format | Scanner / Vendor | Tiffslide support |
|---|---|---|---|
.svs | Aperio SVS | Leica (Aperio) | ✅ Full |
.scn | Leica SCN | Leica | ✅ Full |
.tif / .tiff | TIFF, BigTIFF, OME-TIFF | Generic / various | ✅ Full |
.ndpi | Hamamatsu NDPI | Hamamatsu | ⚠️ Partial — see notes |
.bif | Ventana BIF | Roche (Ventana) | ⚠️ Partial — see notes |
.mrxs | MIRAX | 3DHISTECH | ⚠️ Generic TIFF — see notes |
.vms / .vmu | Hamamatsu VMS / VMU | Hamamatsu | ⚠️ Generic TIFF — see notes |
.qptiff | PerkinElmer / Akoya QPTIFF | PerkinElmer / Akoya | ⚠️ Generic TIFF — see notes |
.czi | Carl Zeiss CZI | Zeiss | ⚠️ Generic TIFF — see notes |
Format support notes:
tiffslide.mpp-x.tiff.XResolution / tiff.ResolutionUnit).
Most Hamamatsu scanners embed resolution in TIFF tags, so this works in practice.
If MPP is wrong or missing, use seg_config.slide_mpp_override.seg_config.slide_mpp_override if MPP is not found automatically..mrxs
file must be accompanied by its sidecar directory (same name, no extension) in the same
location; moving only the .mrxs file will cause a read error.MPP (microns per pixel) retrieval — Mussel reads MPP from slide metadata using the following fallback chain:
slide_mpp_override CLI parameter — if provided, used directly; all metadata reading is skippedtiffslide.mpp-x — standard property populated by tiffslide for all supported formatsaperio.MPP / openslide.mpp-x — legacy vendor property namestiff.XResolution + tiff.ResolutionUnit — raw TIFF resolution tags converted to µm/px;
tiffslide exposes these for partially-supported formats (NDPI, BIF, MRXS, QPTIFF, CZI)
even when it cannot normalize them to tiffslide.mpp-xaperio.AppMag, openslide.objective-power,
and tiffslide.objective-power; computes MPP as 10.0 / magnificationWhen slides lack MPP metadata and the default 0.5 µm/px doesn't match the actual scanner resolution, pass the known value explicitly:
tessellate slide_path=slide.svs seg_config.slide_mpp_override=1.0 ...
tessellate_extract_features slide_path=slide.svs seg_config.slide_mpp_override=0.25 ...
export_tiles slide_path=slide.svs slide_mpp_override=0.5 ...
curl -LsSf https://astral.sh/uv/install.sh | sh
Model inference may require either PyTorch or TensorFlow, depending on which foundation models you wish to use. Because it can be challenging to satisfy the dependencies for both of those at the same time, you need to choose whether to install the module for PyTorch or for TensorFlow.
In addition, you can choose to install Mussel with or without GPU support. GPUs are necessary to run model inference for feature extraction or for generating class embeddings, but other operations can just run on cpus. (Technically, model inference can just run on cpus, as well, but it's very slow.)
Install PyTorch support first, then models are downloaded automatically on first use:
uv sync --extra torch-gpu # GPU (CUDA) — recommended
uv sync --extra torch-cpu # CPU only (Mac or CPU-only Linux)
PyTorch is required for the following patch encoders:
And the following slide encoders (aggregate patch features into a single slide embedding):
| Model | model_type | Patch encoder | Access | HuggingFace |
|---|---|---|---|---|
| Prov-GigaPath | GIGAPATH_SLIDE | GIGAPATH | 🔒 gated | prov-gigapath/prov-gigapath |
| TITAN | TITAN_SLIDE | CONCH1_5 | 🔒 gated | MahmoodLab/TITAN |
| PRISM | PRISM_SLIDE | VIRCHOW | 🔒 gated | paige-ai/Prism |
| FEATHER | FEATHER_SLIDE | CONCH1_5 | 🔒 gated | MahmoodLab/abmil.base.conch_v15.pc108-24k |
| MADELEINE | MADELEINE_SLIDE | CLIP | 🔒 gated | MahmoodLab/madeleine |
| CHIEF | CHIEF_SLIDE | CTRANSPATH | ⬇ access req. | hms-dbmi/CHIEF |
🔒 Gated models require signing an access agreement on the HuggingFace model page and setting your token:
export HF_TOKEN=hf_...
⬇ Models requiring access request are downloaded automatically once access is granted:
| Model | Request access | Notes |
|---|---|---|
CHIEF (CHIEF_SLIDE) | Google Drive folder | Request via hms-dbmi/CHIEF; gdown downloads automatically on first use |
TransPath (CTRANSPATH) and CHIEF (CHIEF_SLIDE) are downloaded automatically via gdown on first use (cached in the HuggingFace hub cache directory).
GenBio-PathFM (GENBIO_PATHFM) downloads its model architecture code from GitHub on first use and caches it at ~/.cache/mussel/genbio_pathfm/. The model weights are downloaded from HuggingFace (requires a token with access to genbio-ai/genbio-pathfm).
OpenMidnight (OPENMIDNIGHT) uses the DINOv2 ViT-G/14 architecture from the facebookresearch/dinov2 torch.hub repository. On first use, Mussel downloads the repository code and caches it at ~/.cache/torch/hub/facebookresearch_dinov2_main/. The model weights are downloaded from HuggingFace (requires a token with access to SophontAI/OpenMidnight).
TensorFlow is required for GooglePath only:
| Model | model_type | Access | HuggingFace |
|---|---|---|---|
| GooglePath | GOOGLEPATH | 🔒 gated | google/path-foundation |
uv sync --extra tensorflow-gpu # GPU (CUDA)
uv sync --extra tensorflow-cpu # CPU only (e.g. Mac)
seg_model="neural")Mussel includes built-in neural tissue segmentation using a DeepLabV3-ResNet50 model (2-class: tissue vs background) trained on histopathology slides as part of the HEST project at the Mahmood Lab, Harvard Medical School.
Pre-trained weights are hosted at MahmoodLab/hest-tissue-seg on HuggingFace and are downloaded automatically on first use (no account or token required). The model operates at 1 µm/px; Mussel handles resampling automatically.
Reference: Chan et al., "A Pathology Foundation Model for Cancer Diagnosis and Prognosis Prediction", Nature 2025. [paper] [GitHub] [HuggingFace model card]
No extra packages are required — it works with any torch-gpu or torch-cpu install:
uv sync --extra torch-gpu
Then pass seg_config.seg_model=neural to tessellate or
tessellate_extract_features. A CUDA GPU is recommended for practical
performance but CPU inference is supported.
Neural runtime controls are available under neural_config.* (weights path,
device, batch size, confidence threshold, and max_inference_tiles) for
tessellate, tessellate_extract_features, and filter_tessellate. An explicit
neural device takes precedence over the workflow's use_gpu setting; auto
uses that setting. Use
seg_config.max_tiles with seg_config.max_tiles_strategy and
seg_config.max_tiles_seed to cap and reproducibly sample the final output tiles.
For stain classification, use seg_config=stain. This speed-oriented preset
uses bounded neural validation, keeps up to 32 tiles with at least 75% tissue,
checks at most 256 candidates, and honors neural_config.max_inference_tiles as
an additional inference budget. It avoids full-slide neural inference; when
fewer than 32 candidates qualify or the inference budget is reached, it returns
the qualifying tiles without relaxing the tissue cutoff.
uv run <command...> are automatically executed in the project environment.uv by executingsource .venv/bin/activate
uv pip or conda to install
one of Mussel[torch-gpu], Mussel[tensorflow-gpu], Mussel[torch-cpu], or Mussel[tensorflow-cpu]
into that environment. (Here, Mussel would be replaced with the path to the Mussel
repo you've checked out.)(The example commands in README-commands.md all expect you to have a activated python environment, so that uv run isn't necessary.)
uv sync --extra <extra-deps> to install this project and its dependencies into the project's virtual environment,
where is one of torch-gpu, tensorflow-gpu, torch-cpu, or tensorflow-cpuuv sync --extra <extra-deps> after making any changes to the requirements.uv sync --extra torch-gpu
Mussel can process slides stored on the cloud or remote object stores via the tiffslide and fsspec packages. In order to properly configure mussel for this use case ensure that you:
uv sync --extra remote~/.aws/credentials)fsspec defined in your configuration in ~/.config/fsspec/ directory (e.g. you have a ~/.config/fsspec/s3.json file with the profile set to the profile defined in ~/.aws/credentials and all required client_kwargs are specified)Make sure that the dev dependencies are installed. (They should be installed by default.)
uv run pytest tests
To install this module into an existing Python environment, activate that environment and install mussel and its extra dependencies with the command, (for example)
uv pip install .[torch-gpu]
Mussel provides a set of CLI tools for tiling whole-slide images, working with tiled slides, and generating feature embeddings with pathology foundation models. The tools currently available from Mussel are,
tessellate - tiling and foreground detection of whole-slide imagestessellate_extract_features - combined tiling + feature extraction pipeline; supports batch processing from a directoryextract_features - extract features from whole slide images (WSI) using a foundation model.create_class_embeddings - generate tissue-type embeddings for classifying tilesannotate - annotate tiles with tissue-typescache_tiles - save tile information in an efficient form for trainingexport_tiles - export tiles as individual .png files using an HDF5 tile-coordinate manifest.filter_features - filter features using a classifier modelmerge_annotation_features - merge tile features with annotations from a BMP file.linear_probe_benchmark - benchmark a linear probe classifier on features extracted from a slidesave_model - download and save a foundation model locallyconvert - convert whole-slide images to pyramidal TIFF format (single file or batch)These are described, with examples, in the accompanying document, README-commands.md
For running Mussel at scale on a compute cluster, see mussel-nf — a Nextflow pipeline that wraps the Mussel CLI tools and handles job scheduling, parallelism, and output management across large slide cohorts.
Mussel supports building Docker containers with flash-attn 2.0 for accelerated attention in the CONCH1.5 patch encoder and the Prov-GigaPath slide encoder. Flash attention provides ~30-50% speedup on patch encoding (~20% overall TITAN pipeline improvement).
Building the flash-attn container:
# Build Docker image with flash-attn backend
make docker-build BACKEND=fastattn
# Or manually:
docker build --build-arg BACKEND=fastattn -t mussel:fastattn .
# Convert to Apptainer SIF for HPC deployment
make sif
# Or manually:
apptainer build --force mussel-fastattn.sif docker-daemon://mussel:fastattn
Key details:
[fastattn] extra in pyproject.toml installs:
SDPBackend.EFFICIENT_ATTENTION (Phase 1 optimization); flash-attn accelerates CONCH1.5 patch encoding and GigaPath slide encodingUsing with mussel-nf:
Copy the SIF to your mussel-nf repo and use the apptainer_fastattn profile:
cp mussel-fastattn.sif /path/to/mussel-nf/
cd /path/to/mussel-nf
nextflow run main.nf -profile cluster,slurm,apptainer_fastattn ...
The profile automatically uses the flash-attn container for FEATURIZE tasks.
This code is made available under the GPLv3 License and is available for non-commercial academic purposes. Forked from CLAM, © Mahmood Lab.
Please cite the original CLAM paper:
Lu, M.Y., Williamson, D.F.K., Chen, T.Y. et al. Data-efficient and weakly supervised computational pathology on whole-slide images. Nat Biomed Eng 5, 555–570 (2021). https://doi.org/10.1038/s41551-020-00682-w
@article{lu2021data,
title={Data-efficient and weakly supervised computational pathology on whole-slide images},
author={Lu, Ming Y and Williamson, Drew FK and Chen, Tiffany Y and Chen, Richard J and Barbieri, Matteo and Mahmood, Faisal},
journal={Nature Biomedical Engineering},
volume={5},
number={6},
pages={555--570},
year={2021},
publisher={Nature Publishing Group}
}
Python
97.4%
Shell
1.3%
Makefile
1.1%