ngff_zarr.tiff_to_ngff_image

Convert TIFF files to OME-NGFF.

This module provides functions to convert TIFF files (including multi-series OME-TIFF files) to NgffImage objects for further processing into OME-Zarr format.

When reading OME-TIFF files, physical size metadata (PhysicalSizeX/Y/Z and their units) is extracted and used to set the scale and axes_units of the resulting NgffImage.

Requires the tifffile package: pip install tifffile

Module Contents

Classes

_TiffStructuralErrorHandler

Collect ERROR-level messages emitted by tifffile while reading a file.

Functions

_normalize_unit

Convert an OME unit string to an NGFF-compatible unit name.

_map_tiff_axes_to_ngff

Map TIFF axes to NGFF-compatible dimensions, flattening channel-like dims.

_reshape_tiff_for_channels

Reshape TIFF data array to match NGFF dimensions.

_extract_ome_pixel_metadata

Extract scale and units from OME-XML metadata for a specific series.

_extract_ome_channel_names

Extract channel names from OME-XML metadata for a specific series.

_ome_color_int_to_hex

Convert an OME-XML Channel Color integer to a 6-digit hex string.

_extract_ome_channel_colors

Extract channel colors from OME-XML metadata for a specific series.

_channels_to_hex_colors

Convert a list of OME Channel elements to hex color strings.

_sanitize_series_name

Sanitize a series name to prevent path traversal attacks.

_build_multiscales_from_pyramid

Build a NgffMultiscales object from a pyramidal TIFF’s existing pyramid levels.

_summarize_tiff_error_messages

Deduplicate and truncate captured tifffile error messages for display.

tiff_file_to_ngff_images

Convert a TIFF file to a list of (name, NgffImage) or (name, NgffMultiscales) pairs.

_tiff_open_error

Build an actionable error for a TIFF that cannot be opened or enumerated.

_read_tiff_series

Read the requested series from a TIFF file (see tiff_file_to_ngff_images).

Data

API

ngff_zarr.tiff_to_ngff_image.TIFF_AXIS_TO_NGFF: dict[str, str | None]

None

ngff_zarr.tiff_to_ngff_image.TIFF_CHANNEL_AXES

None

ngff_zarr.tiff_to_ngff_image.SPATIAL_DIMS

None

ngff_zarr.tiff_to_ngff_image.OME_UNIT_TO_NGFF: dict[str, str]

None

ngff_zarr.tiff_to_ngff_image._normalize_unit(ome_unit: str | None) str | None

Convert an OME unit string to an NGFF-compatible unit name.

Parameters

ome_unit : str or None The unit string from OME-XML metadata.

Returns

str or None The NGFF-compatible unit name, or None if not recognized.

ngff_zarr.tiff_to_ngff_image._map_tiff_axes_to_ngff(
tiff_axes: str,
tiff_shape: tuple[int, ...],
) tuple[tuple[str, ...], tuple[int, ...], list[int], list[int]]

Map TIFF axes to NGFF-compatible dimensions, flattening channel-like dims.

Parameters

tiff_axes : str TIFF axis string (e.g., ‘ZYXS’, ‘TCYX’). tiff_shape : Tuple[int, …] Shape corresponding to the axes.

Returns

ngff_dims : Tuple[str, …] NGFF-compatible dimension names. ngff_shape : Tuple[int, …] Shape after processing (may flatten channel dims). channel_indices : List[int] Indices of channel-like dimensions in original axes. dropped_indices : List[int] Indices of dropped (unsupported) dimensions in original axes.

Warns

UserWarning If unsupported axes are encountered and dropped.

ngff_zarr.tiff_to_ngff_image._reshape_tiff_for_channels(
data: dask.array.Array,
tiff_axes: str,
tiff_shape: tuple[int, ...],
ngff_dims: tuple[str, ...],
ngff_shape: tuple[int, ...],
channel_indices: list[int],
dropped_indices: list[int],
) dask.array.Array

Reshape TIFF data array to match NGFF dimensions.

Handles:

  • Dropping unsupported dimensions (takes first slice)

  • Flattening multiple channel-like dimensions (C, S) into single ‘c’

  • Moving/reordering dimensions as needed

Parameters

data : da.Array Input dask array with original TIFF shape. tiff_axes : str Original TIFF axis string. tiff_shape : Tuple[int, …] Original shape. ngff_dims : Tuple[str, …] Target NGFF dimension names. ngff_shape : Tuple[int, …] Target shape. channel_indices : List[int] Indices of channel dimensions in original data. dropped_indices : List[int] Indices of dimensions to drop.

Returns

da.Array Reshaped array matching ngff_shape.

ngff_zarr.tiff_to_ngff_image._extract_ome_pixel_metadata(
tif: tifffile.TiffFile,
series_index: int = 0,
) tuple[dict[str, float] | None, dict[str, str] | None]

Extract scale and units from OME-XML metadata for a specific series.

Parameters

tif : tifffile.TiffFile An open TiffFile instance. series_index : int, optional Index of the series to extract metadata for. Default is 0.

Returns

Tuple[Optional[Dict[str, float]], Optional[Dict[str, str]]] A tuple of (scale_dict, units_dict) where: - scale_dict maps dimension names (‘x’, ‘y’, ‘z’) to physical sizes - units_dict maps dimension names to NGFF-compatible unit strings Returns (None, None) if OME metadata is not available or cannot be parsed.

Examples

with tifffile.TiffFile(“sample.ome.tiff”) as tif: … scale, units = _extract_ome_pixel_metadata(tif, series_index=0) … if scale: … print(f”Scale: {scale}”) # {‘x’: 0.5, ‘y’: 0.5, ‘z’: 2.0} … print(f”Units: {units}”) # {‘x’: ‘micrometer’, …}

ngff_zarr.tiff_to_ngff_image._extract_ome_channel_names(
tif: tifffile.TiffFile,
series_index: int = 0,
) list[str] | None

Extract channel names from OME-XML metadata for a specific series.

Parameters

tif : tifffile.TiffFile An open TiffFile instance. series_index : int, optional Index of the series to extract metadata for. Default is 0.

Returns

Optional[List[str]] List of channel names, or None if OME metadata is not available or cannot be parsed. Empty strings are used for channels without names.

Examples

with tifffile.TiffFile(“sample.ome.tiff”) as tif: … channel_names = _extract_ome_channel_names(tif, series_index=0) … if channel_names: … print(f”Channels: {channel_names}”) # [‘DAPI’, ‘GFP’, ‘RFP’]

ngff_zarr.tiff_to_ngff_image._ome_color_int_to_hex(color_int: int) str

Convert an OME-XML Channel Color integer to a 6-digit hex string.

OME-XML stores channel colors as a signed 32-bit integer in ARGB format (big-endian: A is the most-significant byte, B is the least-significant). The alpha byte is ignored; only the R, G, B bytes are used.

Parameters

color_int : int Signed 32-bit integer from the OME-XML Color attribute.

Returns

str 6-digit uppercase hexadecimal string (e.g. “FF0000” for red).

ngff_zarr.tiff_to_ngff_image._extract_ome_channel_colors(
tif: tifffile.TiffFile,
series_index: int = 0,
) list[str] | None

Extract channel colors from OME-XML metadata for a specific series.

Channel colors are stored as signed 32-bit integers in ARGB format (A is the most-significant byte).

Parameters

tif : tifffile.TiffFile An open TiffFile instance. series_index : int, optional Index of the series to extract metadata for. Default is 0.

Returns

Optional[List[str]] List of 6-digit hex color strings (without #), or None if OME metadata is not available, cannot be parsed, or no Color attributes are present in the Channel elements.

Examples

with tifffile.TiffFile(“sample.ome.tiff”) as tif: … colors = _extract_ome_channel_colors(tif, series_index=0) … if colors: … print(colors) # [‘FF0000’, ‘00FF00’, ‘0000FF’]

ngff_zarr.tiff_to_ngff_image._channels_to_hex_colors(channels: list) list[str] | None

Convert a list of OME Channel elements to hex color strings.

Returns None if no Channel element has a Color attribute (so callers can fall back to other color selection logic).

ngff_zarr.tiff_to_ngff_image._sanitize_series_name(name: str) str

Sanitize a series name to prevent path traversal attacks.

Removes path separators and parent directory references to ensure the name is safe to use in filesystem paths.

Parameters

name : str Raw series name from TIFF metadata.

Returns

str Sanitized series name safe for use in file paths.

ngff_zarr.tiff_to_ngff_image._SPATIAL_DIMS

None

ngff_zarr.tiff_to_ngff_image._build_multiscales_from_pyramid(
tif: tifffile.TiffFile,
series_idx: int,
tiff_series: tifffile.TiffPageSeries,
ome_scale: dict[str, float] | None,
ome_units: dict[str, str] | None,
ome_channel_names: list[str] | None,
ome_channel_colors: list[str] | None = None,
) ngff_zarr.multiscales.NgffMultiscales

Build a NgffMultiscales object from a pyramidal TIFF’s existing pyramid levels.

Instead of regenerating the pyramid via downsampling, this reuses the resolution levels already stored in the TIFF file.

Parameters

tif : tifffile.TiffFile An open TiffFile instance. series_idx : int Index of the series in the TIFF file. tiff_series : tifffile.TiffPageSeries The TIFF series object (used for axis/shape info). ome_scale : dict or None Physical pixel sizes from OME metadata (e.g., {‘x’: 0.5, ‘y’: 0.5}). ome_units : dict or None Unit strings from OME metadata (e.g., {‘x’: ‘micrometer’}). ome_channel_names : list or None Channel names from OME metadata (e.g., [‘DAPI’, ‘GFP’, ‘RFP’]). ome_channel_colors : list or None Channel colors as 6-digit hex strings (e.g., [‘FF0000’, ‘00FF00’, ‘0000FF’]). When provided, these colors will be stored on every NgffImage in the returned NgffMultiscales so that OMERO computation can use them.

Returns

NgffMultiscales A NgffMultiscales object containing all pyramid levels.

class ngff_zarr.tiff_to_ngff_image._TiffStructuralErrorHandler

Bases: logging.Handler

Collect ERROR-level messages emitted by tifffile while reading a file.

tifffile logs ERROR records such as invalid page offset ... or corrupted tag list ... when a file’s IFD chain is truncated or corrupt. When this happens tifffile silently stops enumerating pages, so the resulting conversion can be missing pyramid levels or whole series (producing an unexpectedly tiny, visually wrong output). Collecting these messages lets us warn the user instead of silently producing an incomplete or incorrect result.

Initialization

Initializes the instance - basically setting the formatter to None and the filter list to empty.

emit(record: logging.LogRecord) None
ngff_zarr.tiff_to_ngff_image._summarize_tiff_error_messages(messages: list[str], limit: int = 5) str

Deduplicate and truncate captured tifffile error messages for display.

Preserves first-seen order, drops duplicates, and appends a ... (N more) note when more than limit distinct messages were collected so a corrupt file with many bad IFDs does not produce an unbounded warning string.

ngff_zarr.tiff_to_ngff_image.tiff_file_to_ngff_images(
tiff_path: str | pathlib.Path,
series: int | str | list[int | str] | None = None,
reuse_existing_pyramids: bool = False,
) list[tuple[str, NgffImage | NgffMultiscales]]

Convert a TIFF file to a list of (name, NgffImage) or (name, NgffMultiscales) pairs.

This function properly handles multi-series TIFF files (including OME-TIFF) and extracts physical size metadata when available.

Parameters

tiff_path : str or Path Path to the TIFF file. series : int, str, or list, optional Series to convert: - None or “all”: Convert all series - int: Convert series at that index - str: Convert series matching regex pattern (use ‘*’ as wildcard) - list: Convert multiple series by index or pattern reuse_existing_pyramids : bool, optional If True and a series has multiple pyramid levels, return a NgffMultiscales object built from the existing levels instead of a single NgffImage. Default is False (always return NgffImage).

Returns

List[Tuple[str, Union[NgffImage, NgffMultiscales]]] List of (series_name, result) tuples. When reuse_existing_pyramids is True and the series is pyramidal, result is a NgffMultiscales. Otherwise it is an NgffImage with: - data: Dask array with lazy loading from the TIFF - dims: Dimension labels (e.g., (‘z’, ‘y’, ‘x’)) - scale: Physical pixel sizes (from OME metadata if available) - translation: Origin offset (defaults to 0.0) - axes_units: Unit strings (from OME metadata if available)

Raises

ImportError If tifffile is not installed. IndexError If a specified series index is out of bounds. ValueError If the series specification is invalid.

Examples

from ngff_zarr import tiff_file_to_ngff_images

Convert all series

images = tiff_file_to_ngff_images(“sample.ome.tiff”)

Convert specific series by index

images = tiff_file_to_ngff_images(“sample.ome.tiff”, series=0)

Convert series matching pattern

images = tiff_file_to_ngff_images(“sample.ome.tiff”, series=”area_1”)

Reuse existing pyramid levels

images = tiff_file_to_ngff_images( … “pyramidal.ome.tiff”, reuse_existing_pyramids=True … )

ngff_zarr.tiff_to_ngff_image._PATH_ACCESS_ERRORS

()

ngff_zarr.tiff_to_ngff_image._tiff_open_error(tiff_path: str | pathlib.Path, error: Exception) OSError

Build an actionable error for a TIFF that cannot be opened or enumerated.

Used for failures both at TiffFile(...) construction and on first .series access, since different tifffile versions detect corruption at different points (see gh-issue-343).

ngff_zarr.tiff_to_ngff_image._read_tiff_series(
tifffile,
tiff_path: str | pathlib.Path,
series: int | str | list[int | str] | None,
reuse_existing_pyramids: bool,
) list[tuple[str, NgffImage | NgffMultiscales]]

Read the requested series from a TIFF file (see tiff_file_to_ngff_images).