Back to Claude Scientific Skills

Image loading, formats, levels, and coordinates

skills/pathml/references/image_loading.md

2.55.09.6 KB
Original Source

Image loading, formats, levels, and coordinates

This reference targets the PyPI-stable PathML 3.0.5 API. All sources were checked on 2026-07-23 against the v3.0.5 tag and stable ReadTheDocs build.

Start with a local, de-identified file

Never infer authorization from the fact that a file is readable. Whole-slide images and DICOM objects can carry identifiers in pixels, labels, filenames, and metadata. Keep the original on approved storage, use a pseudonymous working name, and do not print arbitrary metadata. The bundled inspector emits only an allowlist of technical fields:

bash
python scripts/slide_manifest.py inspect \
  --slide data/pseudonymous_slide.svs \
  --root .

It rejects URLs and symlinks. PathML itself accepts paths more broadly, so validate before constructing a slide object.

Stable slide classes

python
from pathml.core import (
    CODEXSlide,
    HESlide,
    IHCSlide,
    MultiparametricSlide,
    SlideData,
    SlideDataset,
    VectraSlide,
    types,
)

Convenience classes pass a stable SlideType:

  • HESlide(...)types.HE
  • IHCSlide(...)types.IHC
  • MultiparametricSlide(...)types.IF, Bio-Formats by default
  • VectraSlide(...)types.Vectra, Bio-Formats by default
  • CODEXSlide(...)types.CODEX, Bio-Formats by default

The generic constructor is:

python
slide = SlideData(
    "data/pseudonymous_slide.svs",
    name="slide-001",
    backend="openslide",
    slide_type=types.HE,
)

SlideData.from_slide(), read_region(), level_dimensions, and level_downsamples are not stable SlideData APIs. Use the constructor, extract_region(), shape, and backend-specific objects where necessary.

For a local cohort, instantiate slides first:

python
from pathlib import Path
from pathml.core import HESlide, SlideDataset

root = Path("data/slides")
paths = sorted(root.glob("*.svs"))
slides = [HESlide(path, backend="openslide", name=path.stem) for path in paths]
dataset = SlideDataset(slides)

Do not recursively accept arbitrary user-controlled paths. Validate a manifest, freeze the patient split, and then build this list.

Backends and file types

OpenSlide

Use backend="openslide" for common brightfield pyramid formats. Stable PathML lists:

.svs, .tif, .tiff, .bif, .ndpi, .vms, .vmu, .scn, .mrxs, and .svslide.

The complete capability depends on the installed OpenSlide build and the vendor subtype, not only the suffix. Some generic TIFFs are not valid WSIs, and some files with a supported suffix use unsupported compression.

Native OpenSlide is required. Official PathML guidance uses openslide-tools on Debian/Ubuntu, Homebrew openslide on macOS, and vcpkg or official prebuilt binaries on Windows.

Bio-Formats

Use backend="bioformats" for multidimensional microscopy, OME-TIFF, QPTIFF, and formats OpenSlide cannot read. Bio-Formats supports a large catalogue (the upstream examples describe 160+ formats), including .ome.tif, .ome.tiff, .qptiff, .czi, .vsi, .zvi, and many laboratory formats.

This backend requires Java, python-bioformats, and python-javabridge. It starts a JVM and stable source configures a large maximum heap, so isolate and resource-limit untrusted images. Java has an approximately 2 GB array limit in the backend. A listed extension is not proof that every variant loads.

Bio-Formats returns five-dimensional arrays in PathML order:

(i, j, z, channel, time) = (row, column, z, c, t).

Even singleton z and time dimensions are retained until a transform such as CollapseRunsCODEX or CollapseRunsVectra changes the layout.

DICOM

Use backend="dicom" for .dcm or .dicom. Stable PathML treats DICOM frames as tiles. DICOM metadata is especially likely to contain PHI; de-identify with an approved DICOM process before PathML, preserve required UIDs consistently, and never dump the full dataset to logs.

h5path

.h5 and .h5path inputs are inferred as PathML's processed HDF5 format:

python
from pathml.core import SlideData

processed = SlideData("derived/slide-001.h5path")

There is no stable from_hdf5() constructor. See data_management.md.

Backend inference versus explicit selection

If backend=None, PathML infers a backend from the suffix. Prefer an explicit backend in reproducible work:

python
from pathml.core import HESlide

slide = HESlide("data/slide-001.svs", backend="openslide")

Reasons to be explicit:

  • .tif can mean a brightfield pyramid, OME-TIFF, or a plain raster.
  • Bio-Formats is broader but slower and starts Java.
  • Backend metadata and pyramid interpretation differ.
  • A file renamed to a recognized suffix is not thereby valid.

Shape, regions, and tile generation

slide.shape returns (height, width) for the backend's default level.

python
height, width = slide.shape

region = slide.extract_region(
    location=(2_000, 3_000),  # (i, j) = (row, column)
    size=(512, 768),          # (height, width)
    level=1,
)

tiles = slide.generate_tiles(
    shape=(512, 512),
    stride=(256, 256),
    pad=False,
    level=1,
)

generate_tiles() is lazy. Do not materialize all tiles just to count them. Use the bounded planner first:

bash
python scripts/plan_pipeline.py \
  --width 100000 --height 80000 \
  --tile-size 512 --stride 256 \
  --level-downsample 4

SlideData.run() uses different parameter names: tile_size, tile_stride, tile_pad, and level.

Coordinate convention

PathML's Tile.coords is the top-left (i, j):

  • i: row / vertical / image y
  • j: column / horizontal / image x
  • origin: top-left pixel (0, 0)
  • units: pixels at the selected pyramid level

For OpenSlide, stable PathML multiplies (i, j) by that level's downsample and swaps the order before calling OpenSlide's level-0 (x, y) API. Therefore:

text
row_level0 = i_level * downsample_level
col_level0 = j_level * downsample_level
y_um = row_level0 * mpp_y
x_um = col_level0 * mpp_x

Use scanner-provided level-0 MPP when reliable. Do not silently derive MPP from objective power. Record:

  • coordinate convention (ij or xy)
  • pyramid level and exact downsample
  • whether MPP is measured, metadata-derived, or unavailable
  • tile height/width, stride, and padding

QuantifyMIF later writes obsm["spatial"] in (x, y) order, so a conversion is required when joining it to Tile.coords.

Pyramid levels

For OpenSlide, level 0 is highest resolution. Later levels are downsampled, but the factors are slide-specific; do not assume 4x, 16x, or a particular magnification sequence.

Backend-level inspection:

python
level_count = slide.slide.level_count
level0_shape = slide.slide.get_image_shape(level=0)  # (height, width)

# OpenSlide-specific internals, not a backend-neutral PathML contract:
downsamples = tuple(slide.slide.slide.level_downsamples)
dimensions_xy = tuple(slide.slide.slide.level_dimensions)

Guard backend-specific access and record it as such. Bio-Formats maps image series to levels; those series are not necessarily an optical pyramid.

Tile count and edge behavior

For one dimension D, tile extent T, and stride S, pad=False yields:

text
0                         if D < T
floor((D - T) / S) + 1    otherwise

With pad=True, stable PathML follows its backend implementation, which is not identical to a generic ceil(D / S) rule for every overlapping configuration. Use the bundled planner and verify a small synthetic case. Padded pixels are zero, which can bias tissue/stain/QC transforms.

Important stable limitation: SlideData.generate_tiles() does not slice slide-level masks into padded tiles. Do not combine a slide-level mask with pad=True without an explicit, tested padding policy.

Technical metadata without PHI leakage

PathML 3.0.5 has no backend-neutral slide.metadata mapping. Technical metadata is backend-specific:

  • OpenSlide properties are under the wrapped OpenSlide object.
  • Bio-Formats stores OME-XML in its backend metadata.
  • DICOM contains a full clinical metadata model.

Default to a strict allowlist such as:

  • dimensions and level count
  • level downsamples
  • MPP X/Y
  • objective power
  • scanner vendor/model
  • pixel dtype, channels, Z, and time dimensions

Do not emit patient name/ID, accession, dates, institution, free text, UIDs, or file paths. Even technical fields can be identifying in a small cohort; minimize what is retained.

Loading/QC checklist

Before large-scale processing:

  1. Validate suffix, regular-file status, symlinks, size, and manifest uniqueness.
  2. Confirm backend and native dependencies with a non-sensitive test slide.
  3. Read a thumbnail or a few bounded regions, not the full level-0 image.
  4. Confirm color/channel order, dtype, level count, dimensions, and MPP.
  5. Check orientation, blank areas, focus, folds, pen, bubbles, coverslip edges, clipping, and scanner artifacts.
  6. Confirm tile coordinates by overlaying a few sampled tiles on a thumbnail.
  7. Record failures instead of silently dropping slides.

Sources, accessed 2026-07-23