domains / science / wsi-tile-extraction / histolab
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.
| Repository | Path |
|---|---|
| K-Dense-AI/scientific-agent-skills | skills/histolab/SKILL.md |
| foryourhealth111-pixel/Vibe-Skills | bundled/skills/histolab/SKILL.md |
| aipoch/medical-research-skills | scientific-skills/Data Analysis/histolab/SKILL.md |
| FreedomIntelligence/OpenClaw-Medical-Skills | skills/histolab/SKILL.md |
| Role | Repository | Path |
|---|---|---|
| peer | K-Dense-AI/scientific-agent-skills | skills/histolab/SKILL.md |
| peer | foryourhealth111-pixel/Vibe-Skills | bundled/skills/histolab/SKILL.md |
| peer | aipoch/medical-research-skills | scientific-skills/Data Analysis/histolab/SKILL.md |
| peer | FreedomIntelligence/OpenClaw-Medical-Skills | skills/histolab/SKILL.md |
---
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.