Python interface to OpenSlide for reading whole-slide images used in digital pathology
—
Core functionality for opening, reading, and manipulating whole-slide images. This module provides the primary user interface for working with digital pathology slides, supporting various file formats and providing efficient access to multi-resolution image data.
import openslide
from openslide import OpenSlide, ImageSlide, OpenSlideCache, open_slide
from PIL import Image
from PIL.ImageCms import ImageCmsProfile
from collections.abc import Mapping
import osFunctions and classes for opening different types of slide files with automatic format detection and proper resource management.
def open_slide(filename: str | bytes | os.PathLike[Any]) -> OpenSlide | ImageSlide:
"""
Open a whole-slide or regular image file.
Automatically detects the file format and returns the appropriate slide object.
Returns OpenSlide for whole-slide images, ImageSlide for regular images.
Args:
filename: Path to the image file
Returns:
OpenSlide object for whole-slide images, ImageSlide for regular images
Raises:
OpenSlideError: If there's an error opening the file
"""
class OpenSlide:
"""
Main interface for OpenSlide whole-slide images.
Supports context manager protocol for automatic resource cleanup.
Has latching error semantics - once an error occurs, all operations fail.
"""
def __init__(self, filename: str | bytes | os.PathLike[Any]):
"""
Open a whole-slide image file.
Args:
filename: Path to the whole-slide image file
Raises:
OpenSlideUnsupportedFormatError: If the file format is not supported
OpenSlideError: If there's an error opening the file
"""
@classmethod
def detect_format(cls, filename: str | bytes | os.PathLike[Any]) -> str | None:
"""
Detect the format vendor of a slide file.
Args:
filename: Path to the slide file
Returns:
String describing the format vendor, or None if not recognized
"""
class ImageSlide:
"""
Wrapper for PIL.Image that provides the OpenSlide interface.
Allows regular images to be used with OpenSlide-compatible APIs.
"""
def __init__(self, file: str | bytes | os.PathLike[Any] | Image.Image):
"""
Open an image file or wrap a PIL.Image.
Args:
file: Path to image file or PIL.Image object
"""
@classmethod
def detect_format(cls, filename: str | bytes | os.PathLike[Any]) -> str | None:
"""
Detect the format of an image file.
Args:
filename: Path to the image file
Returns:
PIL format string, or None if not recognized
"""Methods for extracting regions, thumbnails, and associated images from slides.
class AbstractSlide:
"""Base class for all slide objects"""
def read_region(self, location: tuple[int, int], level: int, size: tuple[int, int]) -> Image.Image:
"""
Read a rectangular region from the slide.
Args:
location: (x, y) top-left pixel coordinates in level 0 reference frame
level: Level number to read from (0 is highest resolution)
size: (width, height) size of region to read
Returns:
PIL.Image with RGBA format containing the region data
Raises:
OpenSlideError: If there's an error reading the region
"""
def get_thumbnail(self, size: tuple[int, int]) -> Image.Image:
"""
Generate a thumbnail of the entire slide.
Args:
size: Maximum (width, height) for the thumbnail
Returns:
PIL.Image in RGB format with thumbnail of the slide
"""
def get_best_level_for_downsample(self, downsample: float) -> int:
"""
Get the best level for a given downsample factor.
Args:
downsample: Desired downsample factor
Returns:
Level number that best matches the downsample factor
"""
def close(self) -> None:
"""
Close the slide and free associated resources.
After calling close(), no other operations are valid.
"""Access to slide dimensions, levels, properties, and associated images.
class AbstractSlide:
@property
def dimensions(self) -> tuple[int, int]:
"""
Dimensions of level 0 (highest resolution) as (width, height).
"""
@property
def level_count(self) -> int:
"""
Number of resolution levels in the slide.
"""
@property
def level_dimensions(self) -> tuple[tuple[int, int], ...]:
"""
Dimensions for each level as tuple of (width, height) tuples.
level_dimensions[n] contains dimensions of level n.
"""
@property
def level_downsamples(self) -> tuple[float, ...]:
"""
Downsample factors for each level.
level_downsamples[n] contains the downsample factor of level n
relative to level 0.
"""
@property
def properties(self) -> Mapping[str, str]:
"""
Slide metadata as a mapping of property name to value.
Common properties include vendor, comment, objective power,
microns per pixel, and slide bounds information.
"""
@property
def associated_images(self) -> Mapping[str, Image.Image]:
"""
Associated images as a mapping of image name to PIL.Image.
Common associated images include 'label', 'macro', and 'thumbnail'.
Images are not premultiplied.
"""
@property
def color_profile(self) -> ImageCms.ImageCmsProfile | None:
"""
ICC color profile for the slide, or None if unavailable.
Requires OpenSlide 4.0.0+.
"""Caching functionality for improved performance when reading multiple regions.
class OpenSlideCache:
"""
In-memory tile cache for improved slide reading performance.
Can be shared across multiple OpenSlide objects.
"""
def __init__(self, capacity: int):
"""
Create a tile cache.
Args:
capacity: Cache capacity in bytes
"""
class OpenSlide:
def set_cache(self, cache: OpenSlideCache) -> None:
"""
Use the specified cache for storing decoded slide tiles.
By default, each OpenSlide object has its own cache.
Args:
cache: OpenSlideCache object to use
Raises:
TypeError: If cache is not an OpenSlideCache object
"""import openslide
# Open a slide with automatic format detection
with openslide.open_slide("slide.svs") as slide:
# Get slide information
print(f"Format: {slide.detect_format('slide.svs')}")
print(f"Dimensions: {slide.dimensions}")
print(f"Levels: {slide.level_count}")
# Read a 1000x1000 pixel region from level 0
region = slide.read_region((5000, 5000), 0, (1000, 1000))
region.save("region.png")
# Generate thumbnail
thumb = slide.get_thumbnail((500, 500))
thumb.save("thumbnail.jpg")with openslide.OpenSlide("slide.svs") as slide:
print("Level information:")
for level in range(slide.level_count):
dims = slide.level_dimensions[level]
downsample = slide.level_downsamples[level]
print(f" Level {level}: {dims[0]}x{dims[1]} (downsample: {downsample:.2f}x)")
# Read same region at different resolutions
location = (10000, 10000)
size = (512, 512)
# High resolution (level 0)
high_res = slide.read_region(location, 0, size)
# Lower resolution (level 2)
low_res = slide.read_region(location, 2, size)import openslide
# Create a shared cache
cache = openslide.OpenSlideCache(256 * 1024 * 1024) # 256MB
# Use cache with multiple slides
with openslide.OpenSlide("slide1.svs") as slide1:
slide1.set_cache(cache)
region1 = slide1.read_region((0, 0), 0, (512, 512))
with openslide.OpenSlide("slide2.svs") as slide2:
slide2.set_cache(cache)
region2 = slide2.read_region((0, 0), 0, (512, 512))with openslide.OpenSlide("slide.svs") as slide:
# Access common properties using constants
vendor = slide.properties.get(openslide.PROPERTY_NAME_VENDOR, "Unknown")
objective = slide.properties.get(openslide.PROPERTY_NAME_OBJECTIVE_POWER, "Unknown")
mpp_x = slide.properties.get(openslide.PROPERTY_NAME_MPP_X, "Unknown")
print(f"Vendor: {vendor}")
print(f"Objective: {objective}")
print(f"Microns per pixel (X): {mpp_x}")
# List all available properties
print("All properties:")
for key, value in slide.properties.items():
print(f" {key}: {value}")
# Access associated images
print("Associated images:")
for name, image in slide.associated_images.items():
print(f" {name}: {image.size}")
image.save(f"associated_{name}.png")Install with Tessl CLI
npx tessl i tessl/pypi-openslide-python