Metadata-Version: 2.4
Name: pytessera
Version: 0.1.0
Summary: Turn whole-slide images (DICOM, SVS, NDPI, OME-TIFF) into training-ready tile datasets
Author: Tomás Bordoy García-Carpintero, Lucas Dyssel
License-Expression: MIT
Project-URL: Repository, https://gitlab.sdu.dk/ouh/pytessera
Project-URL: Documentation, https://gitlab.sdu.dk/ouh/pytessera/-/tree/main/docs/tutorials
Keywords: dicom,whole-slide-image,wsi,digital-pathology,tiling,segmentation,deep-learning
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
Classifier: Topic :: Scientific/Engineering :: Image Recognition
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24
Requires-Dist: scipy>=1.10
Requires-Dist: opencv-python-headless>=4.8
Requires-Dist: scikit-image>=0.22
Requires-Dist: Pillow>=10.0
Requires-Dist: matplotlib>=3.7
Requires-Dist: pydicom>=2.4
Requires-Dist: highdicom>=0.22
Requires-Dist: pylibjpeg[all]>=2.0
Requires-Dist: tqdm>=4.65
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Requires-Dist: psutil>=5.9; extra == "dev"
Provides-Extra: ml
Requires-Dist: torch>=2.1; extra == "ml"
Requires-Dist: torchvision>=0.16; extra == "ml"
Provides-Extra: tiff
Requires-Dist: tifffile>=2023.9; extra == "tiff"
Requires-Dist: imagecodecs; extra == "tiff"
Requires-Dist: zarr; extra == "tiff"
Provides-Extra: openslide
Requires-Dist: openslide-python>=1.3; extra == "openslide"
Provides-Extra: gpu
Requires-Dist: torch>=2.1; extra == "gpu"
Requires-Dist: torchvision>=0.16; extra == "gpu"
Dynamic: license-file

# PyTessera

**A modular library for turning whole-slide images into training-ready tile datasets for multi-scale models.**

Diagnostic interpretation of whole-slide images (WSIs) relies on integrating cellular
morphology and tissue architecture across multiple magnifications, so AI training datasets
must preserve those spatial relationships. PyTessera builds training-ready tile datasets
from WSIs through modular functions rather than one fixed pipeline. A quadtree tiles only
tissue, or only annotated regions of interest, into `DataTiles`, the shared unit that each
later stage enriches: a tile can carry a multi-resolution context chain for multi-scale
models, or join its neighbours in a patch bag for hierarchical patch-then-region models.
Encoders and classifiers attach feature embeddings and tissue-type labels through simple
hooks, so users bring their own models, while a class-balanced sampler draws a balanced
subset from the same catalog for a standardized data representation.

![PyTessera graphical abstract](https://gitlab.sdu.dk/ouh/pytessera/-/raw/main/docs/assets/Graphical%20Abstract%20-%20PyTessera.png)

## Features

- **Adaptive quadtree tiling**: background is pruned as the tree descends, so tiles follow
  the tissue, and the whole layout is built as a pixel-free skeleton before anything is read.
- **Aligned multi-zoom context**: every tile can carry a multi-resolution context chain,
  and neighbouring tiles regroup into patch bags, both off the same tiling.
- **Bring your own models**: encoders and classifiers attach through hooks; PyTessera
  bundles and validates none of them.
- **Class-balanced datasets**: draw a materialised balanced subset or an exact per-class
  epoch, over either the annotation-derived category or a hooked tissue-type label.
- **Pure Python** (≥3.11), with a native DICOM  reader in the core. PyTorch (`pytessera[ml]`) and the SVS/NDPI/OME-TIFF readers
  (`pytessera[tiff]`) are optional extras, so `import pytessera` never pulls PyTorch.
- **Format-agnostic**: a native Sectra DICOM backend, plus Aperio **SVS**, Hamamatsu
  **NDPI** and OME-TIFF through `tifffile` + `zarr`.

## Install

The core is a light, pure-Python install; the slide readers and the PyTorch loading stack
are optional extras you add only when your workflow needs them.

```bash
pip install pytessera                 # core: tissue segmentation, quadtree tiling, DICOM
pip install "pytessera[tiff]"         # + Aperio SVS / Hamamatsu NDPI / OME-TIFF readers
pip install "pytessera[ml]"           # + PyTorch loading stack (TileDataset, samplers)
pip install "pytessera[tiff,ml]"      # both extras at once (what the tutorials use)
```

## From the command line

The same builders run as a `pytessera` command, so a cohort can be tiled from a shell script
or a cluster job and the catalog handed to Python later with `load_datatile_dict`:

```bash
pytessera build --slides cohort/*.svs --magnification 20 --save cohort.npz   # tissue-driven
pytessera build-annotations --slides cohort/*.tif --labels Tumor --save tumour.npz
pytessera build -h                                                           # every flag
```

Slides can be files of any supported format, or DICOM case folders (`--data-root DIR --cases ID...`).
The command stops at the catalog; embeddings, labels and balancing are Python calls.

## Tutorials

**Start here:** **[Train a tumour segmentation model on a cohort](https://gitlab.sdu.dk/ouh/pytessera/-/blob/main/docs/tutorials/07_end_to_end_training.ipynb)**
takes ten annotated CAMELYON16 slides to a trained model, scores it on held-out slides, and
paints a prediction map over an unseen CAMELYON17 slide. PyTessera calls do the data side, the
scoring and the map; only the model and the training loop are plain PyTorch.

The other notebooks in [`docs/tutorials/`](https://gitlab.sdu.dk/ouh/pytessera/-/tree/main/docs/tutorials) take one idea each:

1. **[Slide-level MIL on patch bags](https://gitlab.sdu.dk/ouh/pytessera/-/blob/main/docs/tutorials/01_walkthrough.ipynb)** — group tiles into patch bags, encode them with a foundation model, and feed the bags to an attention-MIL model.
2. **[Tissue mask hook](https://gitlab.sdu.dk/ouh/pytessera/-/blob/main/docs/tutorials/02_tissue_mask_hook.ipynb)** — swap in your own tissue segmentation via the `mask_fn` hook.
3. **[Embeddings](https://gitlab.sdu.dk/ouh/pytessera/-/blob/main/docs/tutorials/03_embeddings.ipynb)** — leaf, chain, and merged tile embeddings, plus a classifier hook.
4. **[Patch bags](https://gitlab.sdu.dk/ouh/pytessera/-/blob/main/docs/tutorials/04_patch_bags_hipt.ipynb)** — group tiles into HIPT-style region grids and encode each into a vector.
5. **[ROI-balanced tiling](https://gitlab.sdu.dk/ouh/pytessera/-/blob/main/docs/tutorials/05_roi_balanced.ipynb)** — label tiles from real ASAP annotations and balance classes before materialising pixels.
6. **[Label-balanced skeleton](https://gitlab.sdu.dk/ouh/pytessera/-/blob/main/docs/tutorials/06_label_balanced_skeleton.ipynb)** — enrich with pixels, then drop them and keep only the labelled, embedded skeleton.
7. **[End-to-end training](https://gitlab.sdu.dk/ouh/pytessera/-/blob/main/docs/tutorials/07_end_to_end_training.ipynb)** — the cohort training tutorial above.

## Acknowledgements

We thank all paper authors for their contributions: Tomás Bordoy García-Carpintero, Lucas A. D. T. Dyssel, Isabell Seyfried
If PyTessera is useful in your work, please cite it; see [`CITATION.cff`](https://gitlab.sdu.dk/ouh/pytessera/-/blob/main/CITATION.cff). 

## Contact

Tomás Bordoy García-Carpintero and Lucas A. D. T. Dyssel (equal contribution),
University of Southern Denmark & Odense University Hospital.
Corresponding author: [tobor@imada.sdu.dk](mailto:tobor@imada.sdu.dk). Issues and questions
are welcome on the [GitLab repository](https://gitlab.sdu.dk/ouh/pytessera).
