Loading...
Loading...
Generate correct code for whole-slide image (WSI) analysis using TIAToolbox and foundation models (H-optimus-0, UNI, Prov-GigaPath). Triggers on requests involving whole-slide images, WSI, digital pathology, histopathology, SVS/NDPI/pyramidal TIFF, tissue segmentation, patch extraction, stain normalization, H-optimus-0, TIAToolbox, CAMELYON16/17, SlideGraph, MIL aggregation, HoVer-Net, PanNuke, or SageMaker deployment of pathology models. Produces deterministic commands and Python snippets for slide-info inspection, tissue masking, tile extraction at specified mpp, foundation-model feature embedding, slide-level aggregation, and regulated cloud inference.
npx skill4agent add awslabs/hcls-agent-skills digital-pathologyWSIReaderPatchPredictorDeepFeatureExtractorbaselineresolutionunits ∈ {mpp, power, level, baseline}0.5 mpp ≈ 20×0.25 mpp ≈ 40×baseline_mpp / target_mppimport torch
from tiatoolbox.wsicore.wsireader import WSIReader
from tiatoolbox.models.architecture.vanilla import TimmBackbone
from tiatoolbox.models.engine.semantic_segmentor import IOSegmentorConfig
from tiatoolbox.models.engine.patch_predictor import IOPatchPredictorConfig
from tiatoolbox.models import DeepFeatureExtractor
SLIDE = "slide.svs"
OUT = "./out"
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
# 1. Inspect
reader = WSIReader.open(SLIDE)
info = reader.info.as_dict()
print(info["mpp"], info["level_dimensions"])
# 2. Tissue mask (Otsu at low res — do NOT pass as external mask)
mask_reader = reader.tissue_mask(method="otsu", resolution=4, units="mpp")
# 3. Tile + extract H-optimus-0 features @ 0.5 mpp, 224x224
ioconfig = IOPatchPredictorConfig(
input_resolutions=[{"units": "mpp", "resolution": 0.5}],
patch_input_shape=[224, 224],
stride_shape=[224, 224],
)
extractor = DeepFeatureExtractor(
model=TimmBackbone("H-optimus-0", pretrained=True),
batch_size=16,
num_loader_workers=4,
)
output = extractor.run(
images=[SLIDE],
masks=[mask_reader],
patch_mode=False,
ioconfig=ioconfig,
save_dir=OUT,
device=DEVICE,
)
# output[0] -> (positions.npy, features.npy)features.npy--img-input--output-path--resolution--units--batch-size--device cuda# Slide metadata
tiatoolbox slide-info --img-input slide.svs --mode show
# Tissue mask (binary PNG)
tiatoolbox tissue-mask --img-input slide.svs --output-path ./mask --method otsu \
--resolution 1.25 --units power
# Tile classification with built-in ResNet18 on Kather100k
tiatoolbox patch-predictor --img-input slide.svs \
--pretrained-model resnet18-kather100k \
--output-path ./pred --batch-size 32 --device cuda \
--resolution 0.5 --units mpp
# Stain normalization (Reinhard / Macenko / Vahadane)
tiatoolbox stain-norm --img-input tiles/ --method reinhard --output-path ./norm--units baselinefrom tiatoolbox.wsicore.wsireader import WSIReader
reader = WSIReader.open("slide.svs")
reader.info.as_dict() # mpp, levels, vendor
reader.slide_dimensions(resolution=0.5, units="mpp")
tile = reader.read_rect(
location=(10000, 10000), # baseline coords
size=(224, 224),
resolution=0.5, units="mpp",
)
region = reader.read_bounds(
bounds=(0, 0, 4096, 4096),
resolution=2.0, units="mpp",
)
mask = reader.tissue_mask(method="otsu", resolution=4, units="mpp")from tiatoolbox.models import PatchPredictor
from tiatoolbox.models.engine.patch_predictor import IOPatchPredictorConfig
ioconfig = IOPatchPredictorConfig(
input_resolutions=[{"units": "mpp", "resolution": 0.5}],
patch_input_shape=[224, 224],
stride_shape=[224, 224],
)
predictor = PatchPredictor(pretrained_model="resnet18-kather100k", batch_size=32)
out = predictor.run(
images=["slide.svs"], masks=[mask],
patch_mode=False, ioconfig=ioconfig,
save_dir="./pred", device="cuda",
)from tiatoolbox.models import DeepFeatureExtractor
from tiatoolbox.models.architecture.vanilla import TimmBackbone
extractor = DeepFeatureExtractor(
model=TimmBackbone("H-optimus-0", pretrained=True),
batch_size=16, num_loader_workers=4,
)import numpy as np
from tiatoolbox.tools.graph import SlideGraphConstructor
positions = np.load("out/0.position.npy") # (N, 4) x1,y1,x2,y2
features = np.load("out/0.features.npy") # (N, D)
graph = SlideGraphConstructor.build(
positions=positions[:, :2], features=features,
)
# graph -> {"x": features, "edge_index": (2,E), "coords": (N,2)}from tiatoolbox.tools.stainnorm import get_normalizer
norm = get_normalizer("reinhard") # or "macenko", "vahadane"
norm.fit(target_tile) # RGB ndarray HxWx3
normed = norm.transform(source_tile)huggingface-cli loginimport timm, torch
from torchvision import transforms
model = timm.create_model(
"hf-hub:bioptimus/H-optimus-0",
pretrained=True,
init_values=1e-5,
dynamic_img_size=False,
).eval().to("cuda")
preprocess = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(
mean=(0.707223, 0.578729, 0.703617),
std=(0.211883, 0.230117, 0.177517),
),
])
with torch.inference_mode(), torch.autocast("cuda", dtype=torch.float16):
feats = model(preprocess(tile).unsqueeze(0).to("cuda")) # (1, 1536)batch_size=16TimmBackbone("H-optimus-0", pretrained=True)DeepFeatureExtractor| Model | mpp | Patch size |
|---|---|---|
| H-optimus-0 / UNI / Prov-GigaPath | 0.5 | 224×224 |
| HoVer-Net (PanNuke) | 0.25 | 256×256 |
| SlideGraph CNN features | 0.25 | 512×512 |
| Tissue mask (Otsu) | 4 mpp or 1.25× | — |
baseline_mpp / target_mpp.tifnormal/tumor/reference.csvstages.csvimport xml.etree.ElementTree as ET
tree = ET.parse("slide.xml") # ASAP format
for ann in tree.iter("Annotation"):
pts = [(float(c.get("X")), float(c.get("Y")))
for c in ann.iter("Coordinate")] # baseline coordss3fsboto3763104351884.dkr.ecr.<region>.amazonaws.com/pytorch-inference:2.x-gpu-py310openslide-tools libpixman-1-dev libvipstiatoolbox timm huggingface_hub s3fsml.g5.2xlargeml.g5.12xlargeinvocations_timeout=3600max_concurrent_invocations_per_instance=2from sagemaker.async_inference import AsyncInferenceConfig
async_config = AsyncInferenceConfig(
output_path="s3://bucket/async-out/",
max_concurrent_invocations_per_instance=2,
)
predictor = model.deploy(
instance_type="ml.g5.2xlarge", initial_instance_count=1,
async_inference_config=async_config,
)
predictor.predict_async(input_path="s3://bucket/slides/slide.svs")FROM 763104351884.dkr.ecr.us-east-1.amazonaws.com/pytorch-inference:2.3.0-gpu-py310
RUN apt-get update && apt-get install -y openslide-tools libpixman-1-dev libvips \
&& rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir tiatoolbox timm huggingface_hub s3fsapt-get install libpixman-1-devread_rectresolutionreader.info.mppUserWarning: Scale > 1huggingface-cli loginOSError: 401batch_sizevips tiffsave in.tif out.tif --tile --pyramid --compression jpegOpenSlideUnsupportedFormatErrorreader.tissue_mask(...)DimensionMismatchErrorunits="baseline"resolution=1.0patient_idTimmBackbonetiatoolbox>=1.5
timm>=1.0
torch>=2.1
openslide-python
huggingface_hubopenslide-toolslibpixman-1-devlibvips