domains / science / wsi-tile-extraction / histolab

histolab

Skill card

combined

The K-Dense-AI copy is the most rigorous and contains critical, non-obvious constraints (pinned version 0.7.0, Python 3.10, native OpenSlide installation, macOS DYLD path, and the correct API usage where extraction_mask is passed to extract/locate_tiles rather than the constructor). The other three copies (Vibe-Skills, aipoch, OpenClaw) are near-identical, less rigorous mirrors that use a simplified, potentially incorrect API call (tiler.locate_tiles(slide, n_tiles=20)) and omit the environment setup. Because the K-Dense copy has material steps the others lack, and the others disagree on the API usage, crowning one would hide the alternative (simpler) approach, so combine is appropriate.

Repositories

RepositoryPath
K-Dense-AI/scientific-agent-skillsskills/histolab/SKILL.md
foryourhealth111-pixel/Vibe-Skillsbundled/skills/histolab/SKILL.md
aipoch/medical-research-skillsscientific-skills/Data Analysis/histolab/SKILL.md
FreedomIntelligence/OpenClaw-Medical-Skillsskills/histolab/SKILL.md

Other copies

RoleRepositoryPath
peerK-Dense-AI/scientific-agent-skillsskills/histolab/SKILL.md
peerforyourhealth111-pixel/Vibe-Skillsbundled/skills/histolab/SKILL.md
peeraipoch/medical-research-skillsscientific-skills/Data Analysis/histolab/SKILL.md
peerFreedomIntelligence/OpenClaw-Medical-Skillsskills/histolab/SKILL.md

Combined skill

---
name: histolab
description: Extracts and preprocesses whole-slide histology image tiles with Histolab. Use for WSI inspection, tissue masks, random/grid/score-based tile extraction, H&E stain normalization, and tile dataset preparation.
license: Apache-2.0 license
metadata:
  version: "1.5"
  skill-author: K-Dense Inc.
---

# Histolab

## When to use

Use Histolab to inspect WSI metadata, identify tissue, extract image tiles, and standardize H&E staining. Its masks and scores are image-processing heuristics; they do not diagnose cancer, count individual cells, or establish image quality.

## Installation

Histolab 0.7.0 requires Python <3.12, NumPy <=1.24.4, scikit-image <0.19.4, SciPy <1.10.1, Pillow <11, and openslide-python 1.3.1. Keep this stack isolated from modern scientific environments. Windows is not supported.

Install native OpenSlide for your system, then create a dedicated environment (Python 3.10 was tested):

```bash
uv venv --python 3.10 .venv-histolab
uv pip install --python .venv-histolab/bin/python 'histolab==0.7.0' pooch matplotlib
.venv-histolab/bin/python -c 'import openslide; print(openslide.__library_version__)'
```

On macOS with Homebrew, `brew install openslide` installs the native library. If the older Python binding cannot find it, launch Python with the library path set:

```bash
env DYLD_FALLBACK_LIBRARY_PATH="$(brew --prefix openslide)/lib" .venv-histolab/bin/python -c 'import openslide; print(openslide.__library_version__)'
```

## Workflow

1. Inspect `slide.dimensions`, `slide.levels` (a list), and `slide.level_dimensions(level)` (a method). Check both MPP axes in metadata.
2. Select physical field of view and pixel resolution; level numbers are not interchangeable across scanners. Preserve level-0 coordinate bounds.
3. Choose `TissueMask` for all tissue sections or `BiggestTissueBoxMask` for the largest section's bounding box. Inspect the mask at its actual resolution.
4. Configure a tiler and preview with the **same mask** passed to extraction. Preview methods return a Pillow image; save or display that return value.
5. Extract into a distinct per-slide/per-strategy directory. Count saved files, inspect representative tiles, and retain parameters, source IDs and QC flags.
6. Split datasets by patient before training/validation/test tile assignment. Fit stain normalization targets on training data only and validate on held-out scanners. A seed reproduces sampling; it does not prevent patient leakage.

## Quick start

```python
from pathlib import Path
from histolab.slide import Slide
from histolab.masks import TissueMask
from histolab.tiler import RandomTiler

output = Path("output/random_tiles")
output.mkdir(parents=True, exist_ok=True)
slide = Slide("slide.svs", processed_path=output)
mask = TissueMask()
slide.locate_mask(mask).save(output / "mask_preview.png")

tiler = RandomTiler(
    tile_size=(512, 512), n_tiles=100, level=0, seed=42,
    check_tissue=True, tissue_percent=80.0, prefix="random_",
)
tiler.locate_tiles(slide, extraction_mask=mask).save(output / "tile_preview.png")
tiler.extract(slide, extraction_mask=mask)
print("[OK] Saved tiles:", len(list(output.glob("random_tile_*.png"))))
```

`extraction_mask` belongs to `extract()` and `locate_tiles()`, not to the tiler constructor. `locate_tiles()` has no `n_tiles` argument.

## Choose a strategy

| Tiler | Selection | Important limitation |
| --- | --- | --- |
| `RandomTiler` | Seeded sampling, at most `n_tiles`, up to `max_iter` attempts | May overlap, repeat, or miss rare structures |
| `GridTiler` | Grid within the extraction mask | Boundary tiles and tissue checks can leave gaps |
| `ScoreTiler` | Scores all eligible grid candidates; saves top `n_tiles` | Lower output count does not avoid scoring all candidates |

For grids, stride in each axis is tile size minus `pixel_overlap`; positive values must be smaller than both tile dimensions. Negative overlap leaves gaps. `ScoreTiler(n_tiles=0)` saves all eligible ranked tiles.

Nuclei and cellularity scores estimate stain-derived area fractions. They are not calibrated tumor probabilities or blur/focus scores. Score reports contain exactly `filename,score,scaled_score`; record coordinate bounds and physical resolution separately. Equal raw scores can make `scaled_score` undefined in 0.7.0, so inspect raw scores and finiteness before plotting or comparing them.

## Troubleshooting and scientific checks

- **No/few tiles:** inspect mask and output counts, dimensions, level, and `max_iter`. Lowering `tissue_percent` relaxes QC; validate the added tiles.
- **Missing sections:** the default biggest-region box excludes other sections. Pass `TissueMask` to include all sections.

## Conflicts

- K-Dense-AI/scientific-agent-skills specifies a pinned installation (histolab==0.7.0, Python 3.10, native OpenSlide) and correct API usage (extraction_mask passed to extract/locate_tiles), while foryourhealth111-pixel/Vibe-Skills, aipoch/medical-research-skills, and FreedomIntelligence/OpenClaw-Medical-Skills use a simplified install (uv pip install histolab) and an incorrect API call (tiler.locate_tiles(slide, n_tiles=20)).
- K-Dense-AI/scientific-agent-skills includes a detailed workflow with patient-level dataset splitting and stain normalization validation, which the other copies omit.