> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bioptimus.com/llms.txt
> Use this file to discover all available pages before exploring further.

# WSI processing

> Read whole-slide images: pyramid levels, MPP, regions, and thumbnails.

The Bioptimus SDK's `WSI` factory provides uniform access to whole-slide images, automatically selecting the best available backend.

**Supported backends** (auto-selected, in order of preference):

* **cuCIM** — GPU-accelerated reading, used when available.
* **OpenSlide** — CPU fallback, broad format support.

**Supported formats** include `.svs`, `.tiff`, `.tif`, `.ndpi`, `.vms`, `.vsi`, `.scn`, `.mrxs`, and `.jp2` (subject to the active backend).

## Open a slide

```python theme={null}
from bioptimus.io.wsi import WSI, Level, MPP, Magnification, MeasurementUnit

wsi = WSI("/data/wsi/tcga_coad.svs")
print(wsi.level_count)                      # pyramid levels (0 = highest resolution)
print(wsi.level_dimensions(Level(0)))       # base dimensions
print(wsi.mpp)                              # microns per pixel at level 0
```

## Properties

Slides carry rich scanning metadata. Access it through `props`, and inspect the pyramid with `level_dimensions` and `level_downsample`.

```python theme={null}
props = wsi.props
print(props.SCANNER)          # scanning device
print(props.OBJECTIVE_POWER)  # objective magnification (e.g. 40)
print(props.MPP_X, props.MPP_Y)

# Per-level pyramid structure:
for level in range(wsi.level_count):
    dims = wsi.level_dimensions(Level(level))
    ds = wsi.level_downsample(Level(level))
    print(f"Level {level}: {dims.width}x{dims.height} (downsample {ds:.1f}x)")
```

## Bounded vs. unbounded

Scanners capture the whole slide, but tissue occupies only part of it. `bounded=True` returns the tissue area; `bounded=False` returns the full slide.

```python theme={null}
tissue = wsi.dimensions(bounded=True)    # tissue area only
full   = wsi.dimensions(bounded=False)   # entire slide
```

## Read a region

Specify resolution three ways — by pyramid `Level`, by physical `MPP`, or by `Magnification` — and choose pixel or micrometer units.

```python theme={null}
# By pyramid level, size in pixels (Level 2 ≈ 16× downsample), tissue-bounded:
region_px = wsi.read_region(location=(1625, 0), size=(1200, 1200),
                            resolution=Level(2),
                            measurement_unit=MeasurementUnit.PIXELS, bounded=True)

# The same window requested in micrometers (physical units):
region_um = wsi.read_region(location=(1625, 0), size=(599.0, 599.0),
                            resolution=Level(2),
                            measurement_unit=MeasurementUnit.UM, bounded=True)

img = region_px.image       # PIL image
print(region_px.image.size, region_px.resolution)
```

<Frame caption="The same window read by pixel size vs. physical (µm) size at pyramid level 2 on a TCGA-COAD slide — both yield a matching 1200×1200 px crop. Representative example.">
  <img src="https://mintcdn.com/bioptimus-79a2297b/wzVDcCnzT959rZil/images/figures/wsi-read-region.png?fit=max&auto=format&n=wzVDcCnzT959rZil&q=85&s=832ae5d637e13788efa6a53761ba37d3" alt="Region read in pixels versus micrometers, side by side" width="1609" height="790" data-path="images/figures/wsi-read-region.png" />
</Frame>

`MPP ≈ 10 / magnification` (40× ≈ 0.25 MPP, 20× ≈ 0.5 MPP, 10× ≈ 1.0 MPP). Bioptimus embeddings use 0.5 MPP; tissue segmentation uses 8 MPP.

## Thumbnails & associated images

```python theme={null}
thumb = wsi.get_thumbnail(size=(512, 512), bounded=False)  # PIL image
images = wsi.associated_images                             # {'thumbnail','label','macro'}
macro = images["macro"]                                    # slide-level macro photograph
props = wsi.props                                          # scanner, objective, MPP_X/Y, ...
```

<Note>
  `size` is an upper bound: the aspect ratio is preserved, so the longer side is fit to the requested dimension and the shorter side scaled down proportionally. This slide is slightly taller than wide, so requesting `(512, 512)` yields 486×512 px rather than an exact 512×512.
</Note>

<Frame caption="Generated thumbnail (unbounded, 486×512 px) of a TCGA-COAD diagnostic slide (56,640 × 59,636 px at 0.25 µm/pixel, 40× Aperio). Representative example.">
  <img src="https://mintcdn.com/bioptimus-79a2297b/wzVDcCnzT959rZil/images/figures/wsi-thumbnail-coad.png?fit=max&auto=format&n=wzVDcCnzT959rZil&q=85&s=9a2dc65d53ae16739f4d243f4f58d537" alt="Whole-slide image thumbnail" width="458" height="525" data-path="images/figures/wsi-thumbnail-coad.png" />
</Frame>

<Frame caption="Macro associated image — a low-magnification photograph of the whole slide, including the label. Representative example (TCGA-COAD).">
  <img src="https://mintcdn.com/bioptimus-79a2297b/wzVDcCnzT959rZil/images/figures/wsi-macro-associated.png?fit=max&auto=format&n=wzVDcCnzT959rZil&q=85&s=bdd97de04db5deffadf48b68a29d6080" alt="Macro associated image of the whole slide" width="1182" height="454" data-path="images/figures/wsi-macro-associated.png" />
</Frame>

<Tip>
  For inference you don't usually call the reader directly — the [Inference pipeline](/guides/get-started/inference-pipeline) and `SlideInference` handle tiling. Use the reader for QC, custom region extraction, or building your own pipelines.
</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.