Skip to content

OME-NGFF (OME-Zarr)

Convenience

open_ome_zarr

open_ome_zarr(
    store_path: StorePath,
    layout: Literal["auto", "fov", "hcs", "tiled", "bf2raw"] = "auto",
    mode: Literal["r", "r+", "a", "w", "w-"] = "r",
    channel_names: list[str] | None = None,
    axes: list[AxisMeta] | None = None,
    version: Literal["0.4", "0.5"] = "0.5",
    disable_path_checking: bool = False,
    implementation: str | None = None,
    implementation_config: ImplementationConfig | None = None,
    **kwargs,
) -> Plate | Position | TiledPosition | Bioformats2RawSeries

Convenience method to open OME-Zarr stores.

Parameters:

  • store_path (StorePath) –

    Path or store-like object to open. Accepts str, Path, zarr Store, StorePath, or FSMap.

  • layout (Literal['auto', 'fov', 'hcs', 'tiled', 'bf2raw'], default: 'auto' ) –

    NGFF store layout: "auto" will infer layout from existing metadata (cannot be used for creation); "fov" opens a single position/FOV node; "hcs" opens the high-content-screening multi-fov hierarchy; "tiled" opens a "fov" layout with tiled image array (cannot be automatically inferred since this not NGFF-specified); by default "auto"

  • mode (Literal['r', 'r+', 'a', 'w', 'w-'], default: 'r' ) –

    Persistence mode: 'r' means read only (must exist); 'r+' means read/write (must exist); 'a' means read/write (create if doesn't exist); 'w' means create (overwrite if exists); 'w-' means create (fail if exists), by default "r".

  • channel_names (list[str], default: None ) –

    Channel names used to create a new data store, ignored for existing stores, by default None

  • axes (list[AxisMeta], default: None ) –

    OME axes metadata, by default None:

    [AxisMeta(name='T', type='time', unit='second'),
     AxisMeta(name='C', type='channel', unit=None),
     AxisMeta(name='Z', type='space', unit='micrometer'),
     AxisMeta(name='Y', type='space', unit='micrometer'),
     AxisMeta(name='X', type='space', unit='micrometer')]
    
  • version (Literal['0.4', '0.5'], default: '0.5' ) –

    OME-NGFF version, by default "0.5".

  • disable_path_checking (bool, default: False ) –

    Whether to allow overwriting a path that does not contain '.zarr', by default False

    Warning

    This can lead to severe data loss if the input path is not checked carefully.

  • implementation (str, default: None ) –

    Name of the zarr implementation to use (e.g. "zarrs-python", "zarr-python", "tensorstore"), by default None (uses the default implementation, "zarrs-python"). "zarrs-python" uses the zarrs (Rust) codec pipeline; "zarr-python" uses the pure-Python codec pipeline.

  • implementation_config (ImplementationConfig, default: None ) –

    Configuration for the chosen implementation (e.g. ZarrConfig, TensorStoreConfig), by default None

  • kwargs (dict, default: {} ) –

    Keyword arguments to underlying NGFF node constructor, by default None

Returns:

NGFF Nodes

NGFFNode

NGFFNode(
    group: Group,
    parse_meta: bool = True,
    channel_names: list[str] | None = None,
    axes: list[AxisMeta] | None = None,
    version: Literal["0.4", "0.5"] = "0.5",
    overwriting_creation: bool = False,
    impl: ZarrImplementation | None = None,
)

A node (group level in Zarr) in an NGFF dataset.

channel_names cached property

channel_names

Channel names. Subclasses override for lazy resolution.

axes cached property

axes

Axes metadata. Lazily resolves to defaults if not set.

zgroup property

zgroup

Corresponding Zarr group of the node.

zattrs property

zattrs

Zarr attributes of the node.

Assignments will modify the metadata file.

maybe_wrapped_ome_attrs property

maybe_wrapped_ome_attrs

Container of OME metadata attributes.

version property

version: Literal['0.4', '0.5']

NGFF version

__delitem__

__delitem__(key)

Delete a child without cleaning up metadata.

Warning

This does not clean up metadata.

group_keys

group_keys()

Sorted list of keys to all the child zgroups (if any).

Returns:

  • list[str] –

array_keys

array_keys()

Sorted list of keys to all the child zarrays (if any).

Returns:

  • list[str] –

is_root

is_root()

Whether this node is the root node

Returns:

  • bool –

is_leaf

is_leaf()

Wheter this node is a leaf node,

meaning that no child Zarr group is present. Usually a position/fov node for NGFF-HCS if True.

Returns:

  • bool –

print_tree

print_tree(level: int | None = None)

Print hierarchy of the node to stdout.

Parameters:

  • level (int, default: None ) –

    Maximum depth to show, by default None

get_channel_index

get_channel_index(name: str) -> int

Get the index of a given channel in the channel list.

Parameters:

  • name (str) –

    Name of the channel.

Returns:

  • int –

    Index of the channel.

dump_meta

dump_meta()

Dumps metadata JSON to the .zattrs file.

close

close()

Close Zarr store.

Position

Position(
    group: Group,
    parse_meta: bool = True,
    channel_names: list[str] | None = None,
    axes: list[AxisMeta] | None = None,
    version: Literal["0.4", "0.5"] = "0.5",
    overwriting_creation: bool = False,
    impl: ZarrImplementation | None = None,
)

Bases: MultiscaleNode

The Zarr group level directly containing multiscale image arrays.

Parameters:

  • group (Group) –

    Zarr heirarchy group object

  • parse_meta (bool, default: True ) –

    Whether to parse NGFF metadata in .zattrs, by default True

  • channel_names (list[str], default: None ) –

    List of channel names, by default None

  • axes (list[AxisMeta], default: None ) –

    List of axes (ngff_meta.AxisMeta, up to 5D), by default None

  • overwriting_creation (bool, default: False ) –

    Whether to overwrite or error upon creating an existing child item, by default False

Attributes:

  • version (Literal['0.4', '0.5']) –

    OME-NGFF specification version

  • zgroup (Group) –

    Root Zarr group holding arrays

  • zattr (Attributes) –

    Zarr attributes of the group

  • channel_names (list[str]) –

    Name of the channels

  • axes (list[AxisMeta]) –

    Axes metadata

channel_names cached property

channel_names

Channel names. Subclasses override for lazy resolution.

axes cached property

axes

Axes metadata. Lazily resolves to defaults if not set.

zgroup property

zgroup

Corresponding Zarr group of the node.

zattrs property

zattrs

Zarr attributes of the node.

Assignments will modify the metadata file.

maybe_wrapped_ome_attrs property

maybe_wrapped_ome_attrs

Container of OME metadata attributes.

version property

version: Literal['0.4', '0.5']

NGFF version

scale property

scale: list[float]

Helper function for scale transform metadata of

highest resolution scale.

axis_names property

axis_names: list[str]

Helper function for axis names of the highest resolution scale.

Returns lowercase axis names.

data property

data

Warning

This property does NOT aim to retrieve all the arrays. And it may also fail to retrieve any data if arrays exist but are not named conventionally.

Alias for an array named '0' in the position, which is usually the raw data (or the finest resolution in a pyramid).

Returns:

Raises:

  • KeyError –

    If no array is named '0'.

Notes

Do not depend on this in non-interactive code! The name is hard-coded and is not guaranteed by the OME-NGFF specification.

labels_group property

labels_group: Group | None

Access the labels subgroup if it exists.

label_axes property

label_axes: list[AxisMeta]

Axes for labels: the image's axes (TCZYX); a label's channel axis has length 1.

has_labels property

has_labels: bool

Check if this position has any labels.

__delitem__

__delitem__(key)

Delete a child without cleaning up metadata.

Warning

This does not clean up metadata.

group_keys

group_keys()

Sorted list of keys to all the child zgroups (if any).

Returns:

  • list[str] –

array_keys

array_keys()

Sorted list of keys to all the child zarrays (if any).

Returns:

  • list[str] –

is_root

is_root()

Whether this node is the root node

Returns:

  • bool –

is_leaf

is_leaf()

Wheter this node is a leaf node,

meaning that no child Zarr group is present. Usually a position/fov node for NGFF-HCS if True.

Returns:

  • bool –

print_tree

print_tree(level: int | None = None)

Print hierarchy of the node to stdout.

Parameters:

  • level (int, default: None ) –

    Maximum depth to show, by default None

get_channel_index

get_channel_index(name: str) -> int

Get the index of a given channel in the channel list.

Parameters:

  • name (str) –

    Name of the channel.

Returns:

  • int –

    Index of the channel.

close

close()

Close Zarr store.

initialize_pyramid

initialize_pyramid(levels: int, dims: set[str] | None = None, shards: ShardsLike = None) -> None

Initializes the pyramid arrays with a down scaling of 2 per level.

Decimals shapes are rounded up to ceiling. Scales metadata are also updated.

Every level keeps the level-0 chunk shape, clamped to the level's shape, so a viewer reads the same-sized tiles at every zoom. Shards are sized per level from shards: by default the coarser levels keep the nominal (uncompressed) byte size of the level-0 shard, which the sizer fills spatially first and then along time, so shard files stay about the same size down the pyramid instead of shrinking eightfold per level.

Parameters:

  • levels (int) –

    Number of pyramid levels. If 1, nothing happens.

  • dims (set[str] | None, default: None ) –

    Axis names to downsample (e.g. {"y", "x"} for YX-only). Must be a subset of the dataset's axis names. Defaults to {"z", "y", "x"}, must be lowercase.

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry of every downsampled level, in the forms :func:iohub.core.sharding.resolve_shards accepts (an explicit shape, "XY"/"XYZ", or a size target such as "1GB"). Defaults to None: a size target equal to the level-0 shard's nominal byte size when level 0 is sharded, else no sharding.

compute_pyramid

compute_pyramid(
    levels: int | None = None,
    method: str = "mean",
    dims: set[str] | None = None,
    shards: ShardsLike = None,
    resume: bool = False,
    resume_token: str = "",
    num_workers: int = 1,
) -> None

Compute pyramid by downsampling from source level.

Creates pyramid structure if none exists. Uses cascade downsampling where each level is derived from the previous level to prevent aliasing artifacts and chunk boundary issues.

Each level is written one shard-aligned region at a time, and on a store that can be tracked (zarr-python backend, Zarr v3, local filesystem) every region is a resumable unit, like the writes of iohub.ngff.utils.process_single_position: its files are cleared before it is written, so a shard torn by an interruption is replaced rather than merged into, and a marker beside the store records it once its shards are synced. With resume=True the regions a previous run recorded under the same resume_token are skipped.

Parameters:

  • levels (int, default: None ) –

    Number of pyramid levels. If None, uses existing pyramid structure.

  • method (str, default: 'mean' ) –

    Downsampling method: "mean", "median", "mode", "min", "max", "stride". By default "mean".

  • dims (set[str] | None, default: None ) –

    Axis names to downsample (e.g. {"y", "x"} for YX-only). Forwarded to initialize_pyramid when creating the pyramid structure. Defaults to {"z", "y", "x"}.

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry of the new levels, forwarded to initialize_pyramid when creating the pyramid structure. Defaults to None: the level-0 shard's byte size as a size target.

  • resume (bool, default: False ) –

    Skip the regions an earlier run finished (recorded under resume_token) instead of recomputing every level. By default False: everything is recomputed, markers are still written.

  • resume_token (str, default: '' ) –

    Fingerprint of what determines the pyramid (method, levels, the source data's revision), mixed into the markers' identity so a changed request recomputes rather than skips.

  • num_workers (int, default: 1 ) –

    Threads that downsample each region, one sub-block per thread: a region splits along the axes that are not downsampled (e.g. one (t, c) volume per sub-block), which also bounds the source data held in memory to a few sub-blocks. Ignored by the TensorStore implementation, which uses its own thread pool. By default 1.

Raises:

  • ValueError –

    If level 0 array doesn't exist, pyramid structure is invalid, or if a pyramid already exists with a different number of levels.

Examples:

>>> # Create and compute pyramid with 4 levels
>>> pos.compute_pyramid(levels=4, method="mean")
>>> # Recompute existing pyramid structure
>>> pos.compute_pyramid(method="median")
>>> # Change pyramid levels (must delete first)
>>> pos.delete_pyramid()
>>> pos.compute_pyramid(levels=3, method="mean")

pyramid_dims

pyramid_dims() -> set[str] | None

Axis names the existing pyramid downsamples, or None without a pyramid.

Read from the scale transforms: an axis whose scale doubles from one level to the next is downsampled. Use it to give a label image the same levels as the image it annotates, e.g. label.compute_pyramid(levels, dims=position.pyramid_dims()).

Raises:

  • ValueError –

    If the levels do not all downsample the same axes (e.g. YX at level 1 and ZYX at level 2), or scale by a factor other than 2 between levels, schedules initialize_pyramid cannot reproduce.

delete_pyramid

delete_pyramid() -> None

Delete all dataset pyramid levels except the base (level 0) array.

Use this before calling compute_pyramid() with different levels on a position that already has a pyramid structure.

This method removes both the zarr arrays and updates the OME-NGFF multiscales metadata to reflect the deletion.

get_axis_index

get_axis_index(axis_name: str) -> int

Get the index of a given axis.

Parameters:

  • axis_name (str) –

    Name of the axis. Case insensitive.

Returns:

  • int –

    Index of the axis.

get_effective_scale

get_effective_scale(image: str | Literal['*']) -> list[float]

Get the effective coordinate scale metadata

for one image array or the whole FOV.

Parameters:

  • image (str | Literal['*']) –

    Name of one image array (e.g. "0") to query, or "*" for the whole FOV

Returns:

  • list[float] –

    A list of floats representing the total scale for the image or FOV for each axis.

dump_meta

dump_meta()

Dumps metadata JSON to the .zattrs file.

__getitem__

__getitem__(key: int | str) -> ImageArray

Get an image array member of the position.

E.g. Raw-coordinates image, a multi-scale level, or labels

Parameters:

  • key (int | str) –

    Name or path to the image array. Integer key is converted to string (name).

Returns:

  • ImageArray –

    Container object for image stored as a zarr array (up to 5D)

__setitem__

__setitem__(key, value: NDArray)

Write an up-to-5D image with default settings.

images

images() -> Generator[tuple[str, ImageArray]]

Returns a generator that iterate over the name and value

of all the image arrays in the group.

Yields:

  • tuple[str, ImageArray] –

    Name and image array object.

create_image

create_image(
    name: str,
    data: NDArray,
    chunks: tuple[int, ...] | None = None,
    shards: ShardsLike = None,
    shards_ratio: tuple[int, ...] | None = None,
    transform: list[TransformationMeta] | None = None,
    check_shape: bool = True,
)

Create a new image array in the position.

Parameters:

  • name (str) –

    Name key of the new image.

  • data (NDArray) –

    Image data.

  • chunks (tuple[int, ...], default: None ) –

    Chunk size, by default None. ZYX stack size will be used if not specified.

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry, by default None (no sharding). See :meth:create_zeros for the accepted forms.

  • shards_ratio (tuple[int, ...], default: None ) –

    Deprecated per-axis multiplier over chunks. Use shards.

  • transform (list[TransformationMeta], default: None ) –

    List of coordinate transformations, by default None. Should be specified for a non-native resolution level.

  • check_shape (bool, default: True ) –

    Whether to check if image shape matches dataset axes, by default True

Returns:

  • ImageArray –

    Container object for image stored as a zarr array (up to 5D)

create_zeros

create_zeros(
    name: str,
    shape: tuple[int, ...],
    dtype: DTypeLike,
    chunks: tuple[int, ...] | None = None,
    shards: ShardsLike = None,
    shards_ratio: tuple[int, ...] | None = None,
    transform: list[TransformationMeta] | None = None,
    check_shape: bool = True,
)

Create a new zero-filled image array in the position.

Under default zarr-python settings of lazy writing, this will not write the array values, but only create a .zarray file. This is useful for writing larger-than-RAM images and/or writing from multiprocesses in chunks.

Parameters:

  • name (str) –

    Name key of the new image.

  • shape (tuple[int, ...]) –

    Image shape.

  • dtype (DTypeLike) –

    Data type.

  • chunks (tuple[int, ...], default: None ) –

    Chunk size, by default None. ZYX stack size will be used if not specified.

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry, by default None (no sharding). Only supported for OME-Zarr v0.5 (Zarr v3). One of:

    • an explicit TCZYX shard shape in array elements, rounded up to whole chunks (shards=(2, 1, 96, 1792, 1280));
    • a spatial extent, "XY" for one shard per plane or "XYZ" for one shard per volume;
    • a target file size such as "2GB" or "512MiB": the largest chunk-aligned shard whose nominal (uncompressed) size fits under the target. X grows first, then Y, then Z, then time, so a torn shard costs a spatial region before it costs timepoints. The channel axis is never grown, because writers address single channels.
  • shards_ratio (tuple[int, ...], default: None ) –

    Deprecated per-axis multiplier over chunks (shards = chunks * shards_ratio), by default None. Use shards instead; passing both raises ValueError.

  • transform (list[TransformationMeta], default: None ) –

    List of coordinate transformations, by default None. Should be specified for a non-native resolution level.

  • check_shape (bool, default: True ) –

    Whether to check if image shape matches dataset axes, by default True

Returns:

  • ImageArray –

    Container object for a zero-filled image as a lazy zarr array

append_channel

append_channel(chan_name: str, resize_arrays: bool = True)

Append a channel to the end of the channel list.

Parameters:

  • chan_name (str) –

    Name of the new channel

  • resize_arrays (bool, default: True ) –

    Whether to resize all the image arrays for the new channel, by default True

rename_channel

rename_channel(old: str, new: str)

Rename a channel in the channel list.

Parameters:

  • old (str) –

    Current name of the channel

  • new (str) –

    New name of the channel

update_channel

update_channel(chan_name: str, target: str, data: ArrayLike)

Update a channel slice of the target image array with new data.

The incoming data shape needs to be the same as the target array except for the non-existent channel dimension. For example a TCZYX array of shape (2, 3, 4, 1024, 2048) can be updated with data of shape (2, 4, 1024, 2048)

Parameters:

  • chan_name (str) –

    Channel name

  • target (str) –

    Name of the image array to update

  • data (ArrayLike) –

    New data array to write

Notes

This method is a syntactical variation of assigning values to the slice with the = operator, and users are encouraged to use array indexing directly.

get_effective_translation

get_effective_translation(image: str | Literal['*']) -> TransformationMeta

Get the effective coordinate translation metadata

for one image array or the whole FOV.

Parameters:

  • image (str | Literal['*']) –

    Name of one image array (e.g. "0") to query, or "*" for the whole FOV

Returns:

  • list[float] –

    A list of floats representing the total translation for the image or FOV for each axis.

set_transform

set_transform(image: str | Literal['*'], transform: list[TransformationMeta])

Set the coordinate transformations metadata

for one image array or the whole FOV.

Parameters:

  • image (str | Literal['*']) –

    Name of one image array (e.g. "0") to transform, or "*" for the whole FOV

  • transform (list[TransformationMeta]) –

    List of transformations to apply (TransformationMeta)

set_scale

set_scale(image: str | Literal['*'], axis_name: str, new_scale: float)

Set the scale for a named axis.

Either one image array or the whole FOV.

Parameters:

  • image (str | Literal['*']) –

    Name of one image array (e.g. "0") to transform, or "*" for the whole FOV

  • axis_name (str) –

    Name of the axis to set.

  • new_scale (float) –

    Value of the new scale.

label_shape

label_shape(path: str = '0') -> tuple[int, ...]

The shape of a label of this image's level path: the image's, with one channel.

label_matches_pyramid

label_matches_pyramid(label: PositionLabel) -> bool

Whether label has the image's levels: same paths, shapes (with one channel) and scales.

A label scaffolded before the image's pyramid existed, or with other dims, may carry the right number of levels with the wrong geometry; iohub compute-pyramid uses this to rebuild such levels.

create_labels_group

create_labels_group()

Create the labels subgroup if it doesn't exist.

labels

labels() -> Generator[tuple[str, PositionLabel], None, None]

Returns a generator that iterates over the name and value

of all the label images in the position.

Yields:

label_names

label_names() -> list[str]

List all available label names in this position.

Returns:

  • list[str] –

    List of label names (group keys in the labels group)

get_label

get_label(name: str) -> PositionLabel

Get a multiscale label image by name.

Parameters:

  • name (str) –

    Name of the label image

Returns:

  • PositionLabel –

    Container object for the multiscale label image

Raises:

  • KeyError –

    If the label does not exist

create_label

create_label(
    name: str,
    data: NDArray,
    colors: dict[int, list[int]] | None = None,
    properties: list[dict[str, Any]] | None = None,
    chunks: tuple[int, ...] | None = None,
    shards: ShardsLike = None,
    shards_ratio: tuple[int, ...] | None = None,
    pyramid_levels: int = 1,
) -> PositionLabel

Create a new multiscale label image in this position.

This creates an NGFF-compliant multiscale label image.

Parameters:

  • name (str) –

    Name for the new label image

  • data (NDArray) –

    Label data as integer array with the image's axes and one channel, e.g. (T, 1, Z, Y, X) for a TCZYX image

  • colors (dict[int, list[int]], default: None ) –

    Color mapping for label values {label_value: [r, g, b, a]} Values should be integers 0-255

  • properties (list[dict[str, Any]], default: None ) –

    Properties for each label value, must include "label-value" field

  • chunks (tuple[int, ...], default: None ) –

    Chunk size for the zarr arrays

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry, by default None (no sharding). See :meth:create_zeros for the accepted forms.

  • shards_ratio (tuple[int, ...], default: None ) –

    Deprecated per-axis multiplier over chunks. Use shards.

  • pyramid_levels (int, default: 1 ) –

    Number of pyramid levels to create, by default 1

Returns:

Raises:

  • TypeError –

    If the label data is not an NDArray array

  • ValueError –

    If the label data is not an integer dtype

Examples:

Create a cell segmentation label with colors and pyramid levels:

>>> import numpy as np
>>> from iohub.ngff.nodes import open_ome_zarr
>>>
>>> # Create segmentation mask (T, 1, Z, Y, X): the image's axes, one channel
>>> segmentation = np.zeros((1, 1, 3, 256, 256), dtype=np.uint16)
>>> segmentation[0, 0, :, 50:100, 50:100] = 1  # Cell 1
>>> segmentation[0, 0, :, 150:200, 150:200] = 2  # Cell 2
>>>
>>> # Define colors for visualization (RGBA integers 0-255)
>>> colors = {
...     1: [255, 0, 0, 255],  # Red for cell 1
...     2: [0, 255, 0, 255],  # Green for cell 2
... }
>>>
>>> # Define properties for each label value
>>> properties = [
...     {"label-value": 1, "type": "cell", "area": 2500},
...     {"label-value": 2, "type": "cell", "area": 2500},
... ]
>>>
>>> with open_ome_zarr("dataset.zarr", mode="r+") as position:
...     # Create multiscale label image (3 pyramid levels)
...     cells = position.create_label(
...         name="cells",
...         data=segmentation,
...         colors=colors,
...         properties=properties,
...         pyramid_levels=3,
...     )
...
...     # Access different resolution levels
...     high_res = cells["0"]  # Highest resolution
...     medium_res = cells["1"]  # 2x downscaled
...     low_res = cells["2"]  # 4x downscaled
...
...     # Iterate over all labels
...     for name, label in position.labels():
...         print(f"Label: {name}, Levels: {label.array_keys()}")
...         # Or use the highest resolution level with `.data`
...         high_res_labels = label.data
Notes

Label data MUST be integer data types per NGFF specification: uint8, int8, uint16, int16, uint32, int32, uint64, and int64 are supported.

create_label_zeros

create_label_zeros(
    name: str,
    shape: tuple[int, ...],
    dtype: DTypeLike = np.uint32,
    chunks: tuple[int, ...] | None = None,
    shards: ShardsLike = None,
    shards_ratio: tuple[int, ...] | None = None,
    transform: list[TransformationMeta] | None = None,
    colors: dict[int, list[int]] | None = None,
    properties: list[dict[str, Any]] | None = None,
    level: str = "0",
) -> PositionLabel

Create a new zero-filled multiscale label image in this position.

Parallel to create_zeros for images: only the array metadata is written, so the label can be filled later (e.g. chunk by chunk from several processes) with position.get_label(name)["0"][...] = data.

Parameters:

  • name (str) –

    Name for the new label image

  • shape (tuple[int, ...]) –

    Shape of the first level: the image's axes with one channel, e.g. (T, 1, Z, Y, X) (see :meth:label_shape)

  • dtype (DTypeLike, default: uint32 ) –

    Integer data type of the label, by default np.uint32

  • chunks (tuple[int, ...], default: None ) –

    Chunk size, by default None (one ZYX volume per chunk)

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry: an explicit TCZYX shape, an extent keyword such as "XYZ", or a size target such as "1GB"; see :func:iohub.core.sharding.resolve_shards. By default None (no sharding)

  • shards_ratio (tuple[int, ...], default: None ) –

    Deprecated multiplier over chunks; use shards

  • transform (list[TransformationMeta], default: None ) –

    Coordinate transformations of level "0", by default None (unit scale). Should match the image's transforms.

  • colors (dict[int, list[int]], default: None ) –

    Color mapping for label values {label_value: [r, g, b, a]}

  • properties (list[dict[str, Any]], default: None ) –

    Properties for each label value, must include "label-value" field

  • level (str, default: '0' ) –

    Path of the first level, by default "0". Further levels can be added on the returned label with create_zeros.

Returns:

Raises:

  • ValueError –

    If the dtype is not an integer type, or the shape is not the image's axes with one channel

set_contrast_limits

set_contrast_limits(channel_name: str, window: WindowDict)

Set the contrast limits for a channel.

Parameters:

  • channel_name (str) –

    Name of the channel to set

  • window (WindowDict) –

    Contrast limit (min, max, start, end)

to_xarray

to_xarray() -> xr.DataArray

Export full Position data as a labeled xarray.DataArray (tczyx).

The DataArray is backed by a dask array (lazy, no data loaded until .values or .compute() is called).

Coordinate units follow CF conventions: each coordinate carries its own attrs["units"] (e.g. xa.coords["z"].attrs["units"] == "micrometer"). xa.attrs is reserved for value-level metadata (e.g. xa.attrs["units"] = "nanometer" for ret).

Returns:

  • DataArray –

    5D labeled array with coordinates derived from channel names and physical scales/units.

write_xarray

write_xarray(data_array: DataArray, image: str = '0') -> None

Write an xarray.DataArray into this Position.

Supports writing a subset of channels and/or timepoints. The image array is created on first call; subsequent calls write into the existing array at the correct indices.

Scales, translations, axis units, and DataArray attrs are set from the first write and updated on subsequent writes.

Parameters:

  • data_array (DataArray) –

    5D labeled array with tczyx dimensions. The "c" coordinate must be a subset of this Position's channel names. "t" coordinates are mapped to time indices via the scale and translation.

  • image (str, default: '0' ) –

    Name of the image array to write to, by default "0".

PositionLabel

PositionLabel(
    group,
    parse_meta: bool = True,
    axes: list[AxisMeta] | None = None,
    version: Literal["0.4", "0.5"] = "0.5",
    colors: dict[int, list[int]] | None = None,
    properties: list[dict[str, Any]] | None = None,
    overwriting_creation: bool = False,
    impl: ZarrImplementation | None = None,
)

Bases: MultiscaleNode

Multiscale label image group containing LabelsArray pyramid levels.

This class manages label images according to NGFF specification where each label image MUST implement the multiscales specification with the same number of scale levels as the original image. A label has the axes of the image it annotates; its channel axis has length 1.

Parameters:

  • group (Group) –

    Zarr hierarchy group object for the label image

  • parse_meta (bool, default: True ) –

    Whether to parse NGFF metadata in .zattrs, by default True

  • axes (list[AxisMeta], default: None ) –

    List of axes (TCZYX, the image's), by default None

  • version (Literal['0.4', '0.5'], default: '0.5' ) –

    OME-NGFF specification version

  • colors (dict[int, list[int]], default: None ) –

    Color mapping for label values, by default None

  • properties (list[dict[str, Any]], default: None ) –

    Properties for label values, by default None

  • overwriting_creation (bool, default: False ) –

    Whether to overwrite existing arrays, by default False

Attributes:

  • version (Literal['0.4', '0.5']) –

    OME-NGFF specification version

  • zgroup (Group) –

    Zarr group holding label arrays

  • zattr (Attributes) –

    Zarr attributes of the group

  • axes (list[AxisMeta]) –

    Axes metadata (TCZYX, the image's)

data property

data: LabelsArray

Alias for the highest-resolution label array ('0').

channel_names cached property

channel_names

Channel names. Subclasses override for lazy resolution.

zgroup property

zgroup

Corresponding Zarr group of the node.

zattrs property

zattrs

Zarr attributes of the node.

Assignments will modify the metadata file.

maybe_wrapped_ome_attrs property

maybe_wrapped_ome_attrs

Container of OME metadata attributes.

version property

version: Literal['0.4', '0.5']

NGFF version

scale property

scale: list[float]

Helper function for scale transform metadata of

highest resolution scale.

axis_names property

axis_names: list[str]

Helper function for axis names of the highest resolution scale.

Returns lowercase axis names.

dump_meta

dump_meta()

Dump metadata to zarr.json file.

compute_pyramid

compute_pyramid(
    levels: int | None = None,
    method: str = "max",
    dims: set[str] | None = None,
    shards: ShardsLike = None,
    resume: bool = False,
    resume_token: str = "",
    num_workers: int = 1,
) -> None

Compute the label pyramid with a method that never invents a label id.

Same as MultiscaleNode.compute_pyramid, but method defaults to "max" and must be one of LABEL_PYRAMID_METHODS (max, min, stride, mode), which pick a value present in the window: mean and median would turn a window of 0s and 8s into a 4 that exists nowhere at level 0.

Pass dims=position.pyramid_dims() to match an image pyramid that already exists (Position.create_label and the iohub compute-pyramid command do).

create_label

create_label(
    level: str,
    data: NDArray,
    chunks: tuple[int, ...] | None = None,
    shards: ShardsLike = None,
    shards_ratio: tuple[int, ...] | None = None,
    transform: list[TransformationMeta] | None = None,
) -> LabelsArray

Create a label array at a specific resolution level.

Parallel to Position.create_image for creating label arrays at specific multiscale resolution levels.

Parameters:

  • level (str) –

    Resolution level name (e.g., "0", "1", "2")

  • data (NDArray) –

    Label data (integer array, TCZYX with one channel)

  • chunks (tuple[int, ...], default: None ) –

    Chunk size, by default None

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry, by default None (no sharding). See :meth:Position.create_zeros for the accepted forms.

  • shards_ratio (tuple[int, ...], default: None ) –

    Deprecated per-axis multiplier over chunks. Use shards.

  • transform (list[TransformationMeta], default: None ) –

    Coordinate transformations for this level, by default None

Returns:

  • LabelsArray –

    Created label array

create_zeros

create_zeros(
    level: str,
    shape: tuple[int, ...],
    dtype: DTypeLike,
    chunks: tuple[int, ...] | None = None,
    shards: ShardsLike = None,
    shards_ratio: tuple[int, ...] | None = None,
    transform: list[TransformationMeta] | None = None,
) -> LabelsArray

Create a zero-filled label array at a specific resolution level.

Parameters:

  • level (str) –

    Resolution level name

  • shape (tuple[int, ...]) –

    Array shape (TCZYX with one channel, e.g. (T, 1, Z, Y, X))

  • dtype (DTypeLike) –

    Integer data type for labels

  • chunks (tuple[int, ...], default: None ) –

    Chunk size, by default None

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry, by default None (no sharding). See :meth:Position.create_zeros for the accepted forms.

  • shards_ratio (tuple[int, ...], default: None ) –

    Deprecated per-axis multiplier over chunks. Use shards.

  • transform (list[TransformationMeta], default: None ) –

    Coordinate transformations, by default None

Returns:

  • LabelsArray –

    Zero-filled label array

Raises:

  • ValueError –

    If the dtype is not an integer type, the shape does not have one entry per axis, or the channel axis is longer than 1.

__delitem__

__delitem__(key)

Delete a child without cleaning up metadata.

Warning

This does not clean up metadata.

group_keys

group_keys()

Sorted list of keys to all the child zgroups (if any).

Returns:

  • list[str] –

array_keys

array_keys()

Sorted list of keys to all the child zarrays (if any).

Returns:

  • list[str] –

is_root

is_root()

Whether this node is the root node

Returns:

  • bool –

is_leaf

is_leaf()

Wheter this node is a leaf node,

meaning that no child Zarr group is present. Usually a position/fov node for NGFF-HCS if True.

Returns:

  • bool –

print_tree

print_tree(level: int | None = None)

Print hierarchy of the node to stdout.

Parameters:

  • level (int, default: None ) –

    Maximum depth to show, by default None

get_channel_index

get_channel_index(name: str) -> int

Get the index of a given channel in the channel list.

Parameters:

  • name (str) –

    Name of the channel.

Returns:

  • int –

    Index of the channel.

close

close()

Close Zarr store.

initialize_pyramid

initialize_pyramid(levels: int, dims: set[str] | None = None, shards: ShardsLike = None) -> None

Initializes the pyramid arrays with a down scaling of 2 per level.

Decimals shapes are rounded up to ceiling. Scales metadata are also updated.

Every level keeps the level-0 chunk shape, clamped to the level's shape, so a viewer reads the same-sized tiles at every zoom. Shards are sized per level from shards: by default the coarser levels keep the nominal (uncompressed) byte size of the level-0 shard, which the sizer fills spatially first and then along time, so shard files stay about the same size down the pyramid instead of shrinking eightfold per level.

Parameters:

  • levels (int) –

    Number of pyramid levels. If 1, nothing happens.

  • dims (set[str] | None, default: None ) –

    Axis names to downsample (e.g. {"y", "x"} for YX-only). Must be a subset of the dataset's axis names. Defaults to {"z", "y", "x"}, must be lowercase.

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry of every downsampled level, in the forms :func:iohub.core.sharding.resolve_shards accepts (an explicit shape, "XY"/"XYZ", or a size target such as "1GB"). Defaults to None: a size target equal to the level-0 shard's nominal byte size when level 0 is sharded, else no sharding.

pyramid_dims

pyramid_dims() -> set[str] | None

Axis names the existing pyramid downsamples, or None without a pyramid.

Read from the scale transforms: an axis whose scale doubles from one level to the next is downsampled. Use it to give a label image the same levels as the image it annotates, e.g. label.compute_pyramid(levels, dims=position.pyramid_dims()).

Raises:

  • ValueError –

    If the levels do not all downsample the same axes (e.g. YX at level 1 and ZYX at level 2), or scale by a factor other than 2 between levels, schedules initialize_pyramid cannot reproduce.

delete_pyramid

delete_pyramid() -> None

Delete all dataset pyramid levels except the base (level 0) array.

Use this before calling compute_pyramid() with different levels on a position that already has a pyramid structure.

This method removes both the zarr arrays and updates the OME-NGFF multiscales metadata to reflect the deletion.

get_axis_index

get_axis_index(axis_name: str) -> int

Get the index of a given axis.

Parameters:

  • axis_name (str) –

    Name of the axis. Case insensitive.

Returns:

  • int –

    Index of the axis.

get_effective_scale

get_effective_scale(image: str | Literal['*']) -> list[float]

Get the effective coordinate scale metadata

for one image array or the whole FOV.

Parameters:

  • image (str | Literal['*']) –

    Name of one image array (e.g. "0") to query, or "*" for the whole FOV

Returns:

  • list[float] –

    A list of floats representing the total scale for the image or FOV for each axis.

MultiscaleNode

MultiscaleNode(
    group: Group,
    parse_meta: bool = True,
    channel_names: list[str] | None = None,
    axes: list[AxisMeta] | None = None,
    version: Literal["0.4", "0.5"] = "0.5",
    overwriting_creation: bool = False,
    impl: ZarrImplementation | None = None,
)

Bases: NGFFNode

A group holding one multiscale image: the pyramid levels and their transforms.

Shared by Position (TCZYX images) and PositionLabel (TCZYX label images with one channel): both are ome.multiscales groups whose level "0" is the full-resolution array and whose further levels are 2x downsampled per level. The pyramid methods here only need metadata.multiscales[0], data, create_zeros and item access, which both subclasses provide.

scale property

scale: list[float]

Helper function for scale transform metadata of

highest resolution scale.

axis_names property

axis_names: list[str]

Helper function for axis names of the highest resolution scale.

Returns lowercase axis names.

channel_names cached property

channel_names

Channel names. Subclasses override for lazy resolution.

axes cached property

axes

Axes metadata. Lazily resolves to defaults if not set.

zgroup property

zgroup

Corresponding Zarr group of the node.

zattrs property

zattrs

Zarr attributes of the node.

Assignments will modify the metadata file.

maybe_wrapped_ome_attrs property

maybe_wrapped_ome_attrs

Container of OME metadata attributes.

version property

version: Literal['0.4', '0.5']

NGFF version

initialize_pyramid

initialize_pyramid(levels: int, dims: set[str] | None = None, shards: ShardsLike = None) -> None

Initializes the pyramid arrays with a down scaling of 2 per level.

Decimals shapes are rounded up to ceiling. Scales metadata are also updated.

Every level keeps the level-0 chunk shape, clamped to the level's shape, so a viewer reads the same-sized tiles at every zoom. Shards are sized per level from shards: by default the coarser levels keep the nominal (uncompressed) byte size of the level-0 shard, which the sizer fills spatially first and then along time, so shard files stay about the same size down the pyramid instead of shrinking eightfold per level.

Parameters:

  • levels (int) –

    Number of pyramid levels. If 1, nothing happens.

  • dims (set[str] | None, default: None ) –

    Axis names to downsample (e.g. {"y", "x"} for YX-only). Must be a subset of the dataset's axis names. Defaults to {"z", "y", "x"}, must be lowercase.

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry of every downsampled level, in the forms :func:iohub.core.sharding.resolve_shards accepts (an explicit shape, "XY"/"XYZ", or a size target such as "1GB"). Defaults to None: a size target equal to the level-0 shard's nominal byte size when level 0 is sharded, else no sharding.

compute_pyramid

compute_pyramid(
    levels: int | None = None,
    method: str = "mean",
    dims: set[str] | None = None,
    shards: ShardsLike = None,
    resume: bool = False,
    resume_token: str = "",
    num_workers: int = 1,
) -> None

Compute pyramid by downsampling from source level.

Creates pyramid structure if none exists. Uses cascade downsampling where each level is derived from the previous level to prevent aliasing artifacts and chunk boundary issues.

Each level is written one shard-aligned region at a time, and on a store that can be tracked (zarr-python backend, Zarr v3, local filesystem) every region is a resumable unit, like the writes of iohub.ngff.utils.process_single_position: its files are cleared before it is written, so a shard torn by an interruption is replaced rather than merged into, and a marker beside the store records it once its shards are synced. With resume=True the regions a previous run recorded under the same resume_token are skipped.

Parameters:

  • levels (int, default: None ) –

    Number of pyramid levels. If None, uses existing pyramid structure.

  • method (str, default: 'mean' ) –

    Downsampling method: "mean", "median", "mode", "min", "max", "stride". By default "mean".

  • dims (set[str] | None, default: None ) –

    Axis names to downsample (e.g. {"y", "x"} for YX-only). Forwarded to initialize_pyramid when creating the pyramid structure. Defaults to {"z", "y", "x"}.

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry of the new levels, forwarded to initialize_pyramid when creating the pyramid structure. Defaults to None: the level-0 shard's byte size as a size target.

  • resume (bool, default: False ) –

    Skip the regions an earlier run finished (recorded under resume_token) instead of recomputing every level. By default False: everything is recomputed, markers are still written.

  • resume_token (str, default: '' ) –

    Fingerprint of what determines the pyramid (method, levels, the source data's revision), mixed into the markers' identity so a changed request recomputes rather than skips.

  • num_workers (int, default: 1 ) –

    Threads that downsample each region, one sub-block per thread: a region splits along the axes that are not downsampled (e.g. one (t, c) volume per sub-block), which also bounds the source data held in memory to a few sub-blocks. Ignored by the TensorStore implementation, which uses its own thread pool. By default 1.

Raises:

  • ValueError –

    If level 0 array doesn't exist, pyramid structure is invalid, or if a pyramid already exists with a different number of levels.

Examples:

>>> # Create and compute pyramid with 4 levels
>>> pos.compute_pyramid(levels=4, method="mean")
>>> # Recompute existing pyramid structure
>>> pos.compute_pyramid(method="median")
>>> # Change pyramid levels (must delete first)
>>> pos.delete_pyramid()
>>> pos.compute_pyramid(levels=3, method="mean")

pyramid_dims

pyramid_dims() -> set[str] | None

Axis names the existing pyramid downsamples, or None without a pyramid.

Read from the scale transforms: an axis whose scale doubles from one level to the next is downsampled. Use it to give a label image the same levels as the image it annotates, e.g. label.compute_pyramid(levels, dims=position.pyramid_dims()).

Raises:

  • ValueError –

    If the levels do not all downsample the same axes (e.g. YX at level 1 and ZYX at level 2), or scale by a factor other than 2 between levels, schedules initialize_pyramid cannot reproduce.

delete_pyramid

delete_pyramid() -> None

Delete all dataset pyramid levels except the base (level 0) array.

Use this before calling compute_pyramid() with different levels on a position that already has a pyramid structure.

This method removes both the zarr arrays and updates the OME-NGFF multiscales metadata to reflect the deletion.

get_axis_index

get_axis_index(axis_name: str) -> int

Get the index of a given axis.

Parameters:

  • axis_name (str) –

    Name of the axis. Case insensitive.

Returns:

  • int –

    Index of the axis.

get_effective_scale

get_effective_scale(image: str | Literal['*']) -> list[float]

Get the effective coordinate scale metadata

for one image array or the whole FOV.

Parameters:

  • image (str | Literal['*']) –

    Name of one image array (e.g. "0") to query, or "*" for the whole FOV

Returns:

  • list[float] –

    A list of floats representing the total scale for the image or FOV for each axis.

__delitem__

__delitem__(key)

Delete a child without cleaning up metadata.

Warning

This does not clean up metadata.

group_keys

group_keys()

Sorted list of keys to all the child zgroups (if any).

Returns:

  • list[str] –

array_keys

array_keys()

Sorted list of keys to all the child zarrays (if any).

Returns:

  • list[str] –

is_root

is_root()

Whether this node is the root node

Returns:

  • bool –

is_leaf

is_leaf()

Wheter this node is a leaf node,

meaning that no child Zarr group is present. Usually a position/fov node for NGFF-HCS if True.

Returns:

  • bool –

print_tree

print_tree(level: int | None = None)

Print hierarchy of the node to stdout.

Parameters:

  • level (int, default: None ) –

    Maximum depth to show, by default None

get_channel_index

get_channel_index(name: str) -> int

Get the index of a given channel in the channel list.

Parameters:

  • name (str) –

    Name of the channel.

Returns:

  • int –

    Index of the channel.

dump_meta

dump_meta()

Dumps metadata JSON to the .zattrs file.

close

close()

Close Zarr store.

TiledPosition

TiledPosition(
    group: Group,
    parse_meta: bool = True,
    channel_names: list[str] | None = None,
    axes: list[AxisMeta] | None = None,
    version: Literal["0.4", "0.5"] = "0.5",
    overwriting_creation: bool = False,
    impl: ZarrImplementation | None = None,
)

Bases: Position

Variant of the NGFF position node

with convenience methods to create and access tiled arrays. Other parameters and attributes are the same as Position.

channel_names cached property

channel_names

Channel names. Subclasses override for lazy resolution.

axes cached property

axes

Axes metadata. Lazily resolves to defaults if not set.

zgroup property

zgroup

Corresponding Zarr group of the node.

zattrs property

zattrs

Zarr attributes of the node.

Assignments will modify the metadata file.

maybe_wrapped_ome_attrs property

maybe_wrapped_ome_attrs

Container of OME metadata attributes.

version property

version: Literal['0.4', '0.5']

NGFF version

scale property

scale: list[float]

Helper function for scale transform metadata of

highest resolution scale.

axis_names property

axis_names: list[str]

Helper function for axis names of the highest resolution scale.

Returns lowercase axis names.

data property

data

Warning

This property does NOT aim to retrieve all the arrays. And it may also fail to retrieve any data if arrays exist but are not named conventionally.

Alias for an array named '0' in the position, which is usually the raw data (or the finest resolution in a pyramid).

Returns:

Raises:

  • KeyError –

    If no array is named '0'.

Notes

Do not depend on this in non-interactive code! The name is hard-coded and is not guaranteed by the OME-NGFF specification.

labels_group property

labels_group: Group | None

Access the labels subgroup if it exists.

label_axes property

label_axes: list[AxisMeta]

Axes for labels: the image's axes (TCZYX); a label's channel axis has length 1.

has_labels property

has_labels: bool

Check if this position has any labels.

__getitem__

__getitem__(key: int | str) -> ImageArray

Get an image array member of the position.

E.g. Raw-coordinates image, a multi-scale level, or labels

Parameters:

  • key (int | str) –

    Name or path to the image array. Integer key is converted to string (name).

Returns:

  • ImageArray –

    Container object for image stored as a zarr array (up to 5D)

__setitem__

__setitem__(key, value: NDArray)

Write an up-to-5D image with default settings.

__delitem__

__delitem__(key)

Delete a child without cleaning up metadata.

Warning

This does not clean up metadata.

group_keys

group_keys()

Sorted list of keys to all the child zgroups (if any).

Returns:

  • list[str] –

array_keys

array_keys()

Sorted list of keys to all the child zarrays (if any).

Returns:

  • list[str] –

is_root

is_root()

Whether this node is the root node

Returns:

  • bool –

is_leaf

is_leaf()

Wheter this node is a leaf node,

meaning that no child Zarr group is present. Usually a position/fov node for NGFF-HCS if True.

Returns:

  • bool –

print_tree

print_tree(level: int | None = None)

Print hierarchy of the node to stdout.

Parameters:

  • level (int, default: None ) –

    Maximum depth to show, by default None

get_channel_index

get_channel_index(name: str) -> int

Get the index of a given channel in the channel list.

Parameters:

  • name (str) –

    Name of the channel.

Returns:

  • int –

    Index of the channel.

dump_meta

dump_meta()

Dumps metadata JSON to the .zattrs file.

close

close()

Close Zarr store.

initialize_pyramid

initialize_pyramid(levels: int, dims: set[str] | None = None, shards: ShardsLike = None) -> None

Initializes the pyramid arrays with a down scaling of 2 per level.

Decimals shapes are rounded up to ceiling. Scales metadata are also updated.

Every level keeps the level-0 chunk shape, clamped to the level's shape, so a viewer reads the same-sized tiles at every zoom. Shards are sized per level from shards: by default the coarser levels keep the nominal (uncompressed) byte size of the level-0 shard, which the sizer fills spatially first and then along time, so shard files stay about the same size down the pyramid instead of shrinking eightfold per level.

Parameters:

  • levels (int) –

    Number of pyramid levels. If 1, nothing happens.

  • dims (set[str] | None, default: None ) –

    Axis names to downsample (e.g. {"y", "x"} for YX-only). Must be a subset of the dataset's axis names. Defaults to {"z", "y", "x"}, must be lowercase.

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry of every downsampled level, in the forms :func:iohub.core.sharding.resolve_shards accepts (an explicit shape, "XY"/"XYZ", or a size target such as "1GB"). Defaults to None: a size target equal to the level-0 shard's nominal byte size when level 0 is sharded, else no sharding.

compute_pyramid

compute_pyramid(
    levels: int | None = None,
    method: str = "mean",
    dims: set[str] | None = None,
    shards: ShardsLike = None,
    resume: bool = False,
    resume_token: str = "",
    num_workers: int = 1,
) -> None

Compute pyramid by downsampling from source level.

Creates pyramid structure if none exists. Uses cascade downsampling where each level is derived from the previous level to prevent aliasing artifacts and chunk boundary issues.

Each level is written one shard-aligned region at a time, and on a store that can be tracked (zarr-python backend, Zarr v3, local filesystem) every region is a resumable unit, like the writes of iohub.ngff.utils.process_single_position: its files are cleared before it is written, so a shard torn by an interruption is replaced rather than merged into, and a marker beside the store records it once its shards are synced. With resume=True the regions a previous run recorded under the same resume_token are skipped.

Parameters:

  • levels (int, default: None ) –

    Number of pyramid levels. If None, uses existing pyramid structure.

  • method (str, default: 'mean' ) –

    Downsampling method: "mean", "median", "mode", "min", "max", "stride". By default "mean".

  • dims (set[str] | None, default: None ) –

    Axis names to downsample (e.g. {"y", "x"} for YX-only). Forwarded to initialize_pyramid when creating the pyramid structure. Defaults to {"z", "y", "x"}.

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry of the new levels, forwarded to initialize_pyramid when creating the pyramid structure. Defaults to None: the level-0 shard's byte size as a size target.

  • resume (bool, default: False ) –

    Skip the regions an earlier run finished (recorded under resume_token) instead of recomputing every level. By default False: everything is recomputed, markers are still written.

  • resume_token (str, default: '' ) –

    Fingerprint of what determines the pyramid (method, levels, the source data's revision), mixed into the markers' identity so a changed request recomputes rather than skips.

  • num_workers (int, default: 1 ) –

    Threads that downsample each region, one sub-block per thread: a region splits along the axes that are not downsampled (e.g. one (t, c) volume per sub-block), which also bounds the source data held in memory to a few sub-blocks. Ignored by the TensorStore implementation, which uses its own thread pool. By default 1.

Raises:

  • ValueError –

    If level 0 array doesn't exist, pyramid structure is invalid, or if a pyramid already exists with a different number of levels.

Examples:

>>> # Create and compute pyramid with 4 levels
>>> pos.compute_pyramid(levels=4, method="mean")
>>> # Recompute existing pyramid structure
>>> pos.compute_pyramid(method="median")
>>> # Change pyramid levels (must delete first)
>>> pos.delete_pyramid()
>>> pos.compute_pyramid(levels=3, method="mean")

pyramid_dims

pyramid_dims() -> set[str] | None

Axis names the existing pyramid downsamples, or None without a pyramid.

Read from the scale transforms: an axis whose scale doubles from one level to the next is downsampled. Use it to give a label image the same levels as the image it annotates, e.g. label.compute_pyramid(levels, dims=position.pyramid_dims()).

Raises:

  • ValueError –

    If the levels do not all downsample the same axes (e.g. YX at level 1 and ZYX at level 2), or scale by a factor other than 2 between levels, schedules initialize_pyramid cannot reproduce.

delete_pyramid

delete_pyramid() -> None

Delete all dataset pyramid levels except the base (level 0) array.

Use this before calling compute_pyramid() with different levels on a position that already has a pyramid structure.

This method removes both the zarr arrays and updates the OME-NGFF multiscales metadata to reflect the deletion.

get_axis_index

get_axis_index(axis_name: str) -> int

Get the index of a given axis.

Parameters:

  • axis_name (str) –

    Name of the axis. Case insensitive.

Returns:

  • int –

    Index of the axis.

get_effective_scale

get_effective_scale(image: str | Literal['*']) -> list[float]

Get the effective coordinate scale metadata

for one image array or the whole FOV.

Parameters:

  • image (str | Literal['*']) –

    Name of one image array (e.g. "0") to query, or "*" for the whole FOV

Returns:

  • list[float] –

    A list of floats representing the total scale for the image or FOV for each axis.

images

images() -> Generator[tuple[str, ImageArray]]

Returns a generator that iterate over the name and value

of all the image arrays in the group.

Yields:

  • tuple[str, ImageArray] –

    Name and image array object.

create_image

create_image(
    name: str,
    data: NDArray,
    chunks: tuple[int, ...] | None = None,
    shards: ShardsLike = None,
    shards_ratio: tuple[int, ...] | None = None,
    transform: list[TransformationMeta] | None = None,
    check_shape: bool = True,
)

Create a new image array in the position.

Parameters:

  • name (str) –

    Name key of the new image.

  • data (NDArray) –

    Image data.

  • chunks (tuple[int, ...], default: None ) –

    Chunk size, by default None. ZYX stack size will be used if not specified.

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry, by default None (no sharding). See :meth:create_zeros for the accepted forms.

  • shards_ratio (tuple[int, ...], default: None ) –

    Deprecated per-axis multiplier over chunks. Use shards.

  • transform (list[TransformationMeta], default: None ) –

    List of coordinate transformations, by default None. Should be specified for a non-native resolution level.

  • check_shape (bool, default: True ) –

    Whether to check if image shape matches dataset axes, by default True

Returns:

  • ImageArray –

    Container object for image stored as a zarr array (up to 5D)

create_zeros

create_zeros(
    name: str,
    shape: tuple[int, ...],
    dtype: DTypeLike,
    chunks: tuple[int, ...] | None = None,
    shards: ShardsLike = None,
    shards_ratio: tuple[int, ...] | None = None,
    transform: list[TransformationMeta] | None = None,
    check_shape: bool = True,
)

Create a new zero-filled image array in the position.

Under default zarr-python settings of lazy writing, this will not write the array values, but only create a .zarray file. This is useful for writing larger-than-RAM images and/or writing from multiprocesses in chunks.

Parameters:

  • name (str) –

    Name key of the new image.

  • shape (tuple[int, ...]) –

    Image shape.

  • dtype (DTypeLike) –

    Data type.

  • chunks (tuple[int, ...], default: None ) –

    Chunk size, by default None. ZYX stack size will be used if not specified.

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry, by default None (no sharding). Only supported for OME-Zarr v0.5 (Zarr v3). One of:

    • an explicit TCZYX shard shape in array elements, rounded up to whole chunks (shards=(2, 1, 96, 1792, 1280));
    • a spatial extent, "XY" for one shard per plane or "XYZ" for one shard per volume;
    • a target file size such as "2GB" or "512MiB": the largest chunk-aligned shard whose nominal (uncompressed) size fits under the target. X grows first, then Y, then Z, then time, so a torn shard costs a spatial region before it costs timepoints. The channel axis is never grown, because writers address single channels.
  • shards_ratio (tuple[int, ...], default: None ) –

    Deprecated per-axis multiplier over chunks (shards = chunks * shards_ratio), by default None. Use shards instead; passing both raises ValueError.

  • transform (list[TransformationMeta], default: None ) –

    List of coordinate transformations, by default None. Should be specified for a non-native resolution level.

  • check_shape (bool, default: True ) –

    Whether to check if image shape matches dataset axes, by default True

Returns:

  • ImageArray –

    Container object for a zero-filled image as a lazy zarr array

append_channel

append_channel(chan_name: str, resize_arrays: bool = True)

Append a channel to the end of the channel list.

Parameters:

  • chan_name (str) –

    Name of the new channel

  • resize_arrays (bool, default: True ) –

    Whether to resize all the image arrays for the new channel, by default True

rename_channel

rename_channel(old: str, new: str)

Rename a channel in the channel list.

Parameters:

  • old (str) –

    Current name of the channel

  • new (str) –

    New name of the channel

update_channel

update_channel(chan_name: str, target: str, data: ArrayLike)

Update a channel slice of the target image array with new data.

The incoming data shape needs to be the same as the target array except for the non-existent channel dimension. For example a TCZYX array of shape (2, 3, 4, 1024, 2048) can be updated with data of shape (2, 4, 1024, 2048)

Parameters:

  • chan_name (str) –

    Channel name

  • target (str) –

    Name of the image array to update

  • data (ArrayLike) –

    New data array to write

Notes

This method is a syntactical variation of assigning values to the slice with the = operator, and users are encouraged to use array indexing directly.

get_effective_translation

get_effective_translation(image: str | Literal['*']) -> TransformationMeta

Get the effective coordinate translation metadata

for one image array or the whole FOV.

Parameters:

  • image (str | Literal['*']) –

    Name of one image array (e.g. "0") to query, or "*" for the whole FOV

Returns:

  • list[float] –

    A list of floats representing the total translation for the image or FOV for each axis.

set_transform

set_transform(image: str | Literal['*'], transform: list[TransformationMeta])

Set the coordinate transformations metadata

for one image array or the whole FOV.

Parameters:

  • image (str | Literal['*']) –

    Name of one image array (e.g. "0") to transform, or "*" for the whole FOV

  • transform (list[TransformationMeta]) –

    List of transformations to apply (TransformationMeta)

set_scale

set_scale(image: str | Literal['*'], axis_name: str, new_scale: float)

Set the scale for a named axis.

Either one image array or the whole FOV.

Parameters:

  • image (str | Literal['*']) –

    Name of one image array (e.g. "0") to transform, or "*" for the whole FOV

  • axis_name (str) –

    Name of the axis to set.

  • new_scale (float) –

    Value of the new scale.

label_shape

label_shape(path: str = '0') -> tuple[int, ...]

The shape of a label of this image's level path: the image's, with one channel.

label_matches_pyramid

label_matches_pyramid(label: PositionLabel) -> bool

Whether label has the image's levels: same paths, shapes (with one channel) and scales.

A label scaffolded before the image's pyramid existed, or with other dims, may carry the right number of levels with the wrong geometry; iohub compute-pyramid uses this to rebuild such levels.

create_labels_group

create_labels_group()

Create the labels subgroup if it doesn't exist.

labels

labels() -> Generator[tuple[str, PositionLabel], None, None]

Returns a generator that iterates over the name and value

of all the label images in the position.

Yields:

label_names

label_names() -> list[str]

List all available label names in this position.

Returns:

  • list[str] –

    List of label names (group keys in the labels group)

get_label

get_label(name: str) -> PositionLabel

Get a multiscale label image by name.

Parameters:

  • name (str) –

    Name of the label image

Returns:

  • PositionLabel –

    Container object for the multiscale label image

Raises:

  • KeyError –

    If the label does not exist

create_label

create_label(
    name: str,
    data: NDArray,
    colors: dict[int, list[int]] | None = None,
    properties: list[dict[str, Any]] | None = None,
    chunks: tuple[int, ...] | None = None,
    shards: ShardsLike = None,
    shards_ratio: tuple[int, ...] | None = None,
    pyramid_levels: int = 1,
) -> PositionLabel

Create a new multiscale label image in this position.

This creates an NGFF-compliant multiscale label image.

Parameters:

  • name (str) –

    Name for the new label image

  • data (NDArray) –

    Label data as integer array with the image's axes and one channel, e.g. (T, 1, Z, Y, X) for a TCZYX image

  • colors (dict[int, list[int]], default: None ) –

    Color mapping for label values {label_value: [r, g, b, a]} Values should be integers 0-255

  • properties (list[dict[str, Any]], default: None ) –

    Properties for each label value, must include "label-value" field

  • chunks (tuple[int, ...], default: None ) –

    Chunk size for the zarr arrays

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry, by default None (no sharding). See :meth:create_zeros for the accepted forms.

  • shards_ratio (tuple[int, ...], default: None ) –

    Deprecated per-axis multiplier over chunks. Use shards.

  • pyramid_levels (int, default: 1 ) –

    Number of pyramid levels to create, by default 1

Returns:

Raises:

  • TypeError –

    If the label data is not an NDArray array

  • ValueError –

    If the label data is not an integer dtype

Examples:

Create a cell segmentation label with colors and pyramid levels:

>>> import numpy as np
>>> from iohub.ngff.nodes import open_ome_zarr
>>>
>>> # Create segmentation mask (T, 1, Z, Y, X): the image's axes, one channel
>>> segmentation = np.zeros((1, 1, 3, 256, 256), dtype=np.uint16)
>>> segmentation[0, 0, :, 50:100, 50:100] = 1  # Cell 1
>>> segmentation[0, 0, :, 150:200, 150:200] = 2  # Cell 2
>>>
>>> # Define colors for visualization (RGBA integers 0-255)
>>> colors = {
...     1: [255, 0, 0, 255],  # Red for cell 1
...     2: [0, 255, 0, 255],  # Green for cell 2
... }
>>>
>>> # Define properties for each label value
>>> properties = [
...     {"label-value": 1, "type": "cell", "area": 2500},
...     {"label-value": 2, "type": "cell", "area": 2500},
... ]
>>>
>>> with open_ome_zarr("dataset.zarr", mode="r+") as position:
...     # Create multiscale label image (3 pyramid levels)
...     cells = position.create_label(
...         name="cells",
...         data=segmentation,
...         colors=colors,
...         properties=properties,
...         pyramid_levels=3,
...     )
...
...     # Access different resolution levels
...     high_res = cells["0"]  # Highest resolution
...     medium_res = cells["1"]  # 2x downscaled
...     low_res = cells["2"]  # 4x downscaled
...
...     # Iterate over all labels
...     for name, label in position.labels():
...         print(f"Label: {name}, Levels: {label.array_keys()}")
...         # Or use the highest resolution level with `.data`
...         high_res_labels = label.data
Notes

Label data MUST be integer data types per NGFF specification: uint8, int8, uint16, int16, uint32, int32, uint64, and int64 are supported.

create_label_zeros

create_label_zeros(
    name: str,
    shape: tuple[int, ...],
    dtype: DTypeLike = np.uint32,
    chunks: tuple[int, ...] | None = None,
    shards: ShardsLike = None,
    shards_ratio: tuple[int, ...] | None = None,
    transform: list[TransformationMeta] | None = None,
    colors: dict[int, list[int]] | None = None,
    properties: list[dict[str, Any]] | None = None,
    level: str = "0",
) -> PositionLabel

Create a new zero-filled multiscale label image in this position.

Parallel to create_zeros for images: only the array metadata is written, so the label can be filled later (e.g. chunk by chunk from several processes) with position.get_label(name)["0"][...] = data.

Parameters:

  • name (str) –

    Name for the new label image

  • shape (tuple[int, ...]) –

    Shape of the first level: the image's axes with one channel, e.g. (T, 1, Z, Y, X) (see :meth:label_shape)

  • dtype (DTypeLike, default: uint32 ) –

    Integer data type of the label, by default np.uint32

  • chunks (tuple[int, ...], default: None ) –

    Chunk size, by default None (one ZYX volume per chunk)

  • shards (tuple[int, ...] or str, default: None ) –

    Shard geometry: an explicit TCZYX shape, an extent keyword such as "XYZ", or a size target such as "1GB"; see :func:iohub.core.sharding.resolve_shards. By default None (no sharding)

  • shards_ratio (tuple[int, ...], default: None ) –

    Deprecated multiplier over chunks; use shards

  • transform (list[TransformationMeta], default: None ) –

    Coordinate transformations of level "0", by default None (unit scale). Should match the image's transforms.

  • colors (dict[int, list[int]], default: None ) –

    Color mapping for label values {label_value: [r, g, b, a]}

  • properties (list[dict[str, Any]], default: None ) –

    Properties for each label value, must include "label-value" field

  • level (str, default: '0' ) –

    Path of the first level, by default "0". Further levels can be added on the returned label with create_zeros.

Returns:

Raises:

  • ValueError –

    If the dtype is not an integer type, or the shape is not the image's axes with one channel

set_contrast_limits

set_contrast_limits(channel_name: str, window: WindowDict)

Set the contrast limits for a channel.

Parameters:

  • channel_name (str) –

    Name of the channel to set

  • window (WindowDict) –

    Contrast limit (min, max, start, end)

to_xarray

to_xarray() -> xr.DataArray

Export full Position data as a labeled xarray.DataArray (tczyx).

The DataArray is backed by a dask array (lazy, no data loaded until .values or .compute() is called).

Coordinate units follow CF conventions: each coordinate carries its own attrs["units"] (e.g. xa.coords["z"].attrs["units"] == "micrometer"). xa.attrs is reserved for value-level metadata (e.g. xa.attrs["units"] = "nanometer" for ret).

Returns:

  • DataArray –

    5D labeled array with coordinates derived from channel names and physical scales/units.

write_xarray

write_xarray(data_array: DataArray, image: str = '0') -> None

Write an xarray.DataArray into this Position.

Supports writing a subset of channels and/or timepoints. The image array is created on first call; subsequent calls write into the existing array at the correct indices.

Scales, translations, axis units, and DataArray attrs are set from the first write and updated on subsequent writes.

Parameters:

  • data_array (DataArray) –

    5D labeled array with tczyx dimensions. The "c" coordinate must be a subset of this Position's channel names. "t" coordinates are mapped to time indices via the scale and translation.

  • image (str, default: '0' ) –

    Name of the image array to write to, by default "0".

make_tiles

make_tiles(
    name: str,
    grid_shape: tuple[int, int],
    tile_shape: tuple[int, ...],
    dtype: DTypeLike,
    transform: list[TransformationMeta] | None = None,
    chunk_dims: int = 2,
)

Make a tiled image array filled with zeros.

Chunk size is inferred from tile shape.

Parameters:

  • name (str) –

    Name of the array.

  • grid_shape (tuple[int, int]) –

    2-tuple of the tiling grid shape (rows, columns).

  • tile_shape (tuple[int, ...]) –

    Shape of each tile (up to 5D).

  • dtype (DTypeLike) –

    Data type in NumPy convention

  • transform (list[TransformationMeta], default: None ) –

    List of coordinate transformations, by default None. Should be specified for a non-native resolution level.

  • chunk_dims (int, default: 2 ) –

    Non-singleton dimensions of the chunksize, by default 2 (chunk by 2D (y, x) tile size).

Returns:

  • TiledImageArray –

Plate

Plate(
    group: Group,
    parse_meta: bool = True,
    channel_names: list[str] | None = None,
    axes: list[AxisMeta] | None = None,
    name: str | None = None,
    acquisitions: list[AcquisitionMeta] | None = None,
    version: Literal["0.4", "0.5"] = "0.5",
    overwriting_creation: bool = False,
    impl: ZarrImplementation | None = None,
)

Bases: NGFFNode

zgroup property

zgroup

Corresponding Zarr group of the node.

zattrs property

zattrs

Zarr attributes of the node.

Assignments will modify the metadata file.

maybe_wrapped_ome_attrs property

maybe_wrapped_ome_attrs

Container of OME metadata attributes.

version property

version: Literal['0.4', '0.5']

NGFF version

__delitem__

__delitem__(key)

Delete a child without cleaning up metadata.

Warning

This does not clean up metadata.

group_keys

group_keys()

Sorted list of keys to all the child zgroups (if any).

Returns:

  • list[str] –

array_keys

array_keys()

Sorted list of keys to all the child zarrays (if any).

Returns:

  • list[str] –

is_root

is_root()

Whether this node is the root node

Returns:

  • bool –

is_leaf

is_leaf()

Wheter this node is a leaf node,

meaning that no child Zarr group is present. Usually a position/fov node for NGFF-HCS if True.

Returns:

  • bool –

print_tree

print_tree(level: int | None = None)

Print hierarchy of the node to stdout.

Parameters:

  • level (int, default: None ) –

    Maximum depth to show, by default None

get_channel_index

get_channel_index(name: str) -> int

Get the index of a given channel in the channel list.

Parameters:

  • name (str) –

    Name of the channel.

Returns:

  • int –

    Index of the channel.

close

close()

Close Zarr store.

from_positions classmethod

from_positions(store_path: str | Path, positions: dict[str, Position]) -> Plate

Create a new HCS store from existing OME-Zarr stores

by copying images and metadata from a dictionary of positions.

Warning

This assumes the FOVs have the same channel names and axes, and does not check for consistent shapes or chunk sizes.

Parameters:

  • store_path (str | Path) –

    Path of the new store

  • positions (dict[str, Position]) –

    Dictionary where keys are destination path names ('row/column/fov') and values are Position objects.

Returns:

  • Plate –

    New plate with copied data

Examples:

Combine an HCS-layout store and an FOV-layout store:

>>> from iohub.ngff import open_ome_zarr, Plate
>>> with open_ome_zarr("hcs.zarr") as old_plate:
>>>     fovs = dict(old_plate.positions())
>>> with open_ome_zarr("fov.zarr") as old_position:
>>>     fovs["Z/1/0"] = old_position
>>> new_plate = Plate.from_positions("combined.zarr", fovs)

dump_meta

dump_meta(field_count: bool = False)

Dumps metadata JSON to the .zattrs file.

Parameters:

  • field_count (bool, default: False ) –

    Whether to count all the FOV/positions and populate the metadata field 'plate.field_count'; this operation can be expensive if there are many positions, by default False

create_well

create_well(row_name: str, col_name: str, row_index: int | None = None, col_index: int | None = None)

Creates a new well group in the plate.

The new well will have empty group metadata, which will not be created until a position is written.

Parameters:

  • row_name (str) –

    Name key of the row

  • col_name (str) –

    Name key of the column

  • row_index (int, default: None ) –

    Index of the row, will be set by the sequence of creation if not provided, by default None

  • col_index (int, default: None ) –

    Index of the column, will be set by the sequence of creation if not provided, by default None

Returns:

  • Well –

    Well node object

create_positions

create_positions(positions: list[PositionSpec]) -> list[Position]

Creates multiple position groups in the plate efficiently.

This is a vectorized version of create_position that creates multiple positions in a single call. Wells are created as needed and metadata is written in batches for better performance.

Parameters:

  • positions (list[PositionSpec]) –

    List of position specifications. Each tuple can have 3-6 elements:

    • 3 elements: (row_name, col_name, pos_name)
    • 4 elements: (row_name, col_name, pos_name, row_index)
    • 5 elements: (row_name, col_name, pos_name, row_index, col_index)
    • 6 elements: (row_name, col_name, pos_name, row_index, col_index, acq_index)

    Where:

    • row_name (str): Name key of the row
    • col_name (str): Name key of the column
    • pos_name (str): Name key of the position
    • row_index (int | None): Index of the row (auto-assigned if None or omitted)
    • col_index (int | None): Index of the column (auto-assigned if None or omitted)
    • acq_index (int): Index of the acquisition (defaults to 0 if omitted)

Returns:

  • list[Position] –

    List of created Position node objects

See Also

create_position : Create a single position group

Examples:

Create multiple positions with automatic row/column indexing:

>>> plate.create_positions(
...     [
...         ("A", "1", "0"),
...         ("A", "1", "1"),
...         ("A", "2", "0"),
...     ]
... )

Create positions with explicit row/column indices:

>>> plate.create_positions(
...     [
...         ("B", "3", "0", 1, 2),  # row_index=1, col_index=2
...         ("B", "3", "1", 1, 2),  # same well indices
...     ]
... )

Create positions with specific acquisition indices:

>>> plate.create_positions(
...     [
...         ("B", "3", "0", 1, 2, 0),  # acquisition 0
...         ("B", "3", "1", 1, 2, 1),  # acquisition 1
...     ]
... )

create_position

create_position(
    row_name: str,
    col_name: str,
    pos_name: str,
    row_index: int | None = None,
    col_index: int | None = None,
    acq_index: int = 0,
)

Creates a new position group in the plate.

The new position will have empty group metadata, which will not be created until an image is written.

Parameters:

  • row_name (str) –

    Name key of the row

  • col_name (str) –

    Name key of the column

  • row_index (int, default: None ) –

    Index of the row, will be set by the sequence of creation if not provided, by default None

  • col_index (int, default: None ) –

    Index of the column, will be set by the sequence of creation if not provided, by default None

  • acq_index (int, default: 0 ) –

    Index of the acquisition, by default 0

Returns:

rows

rows() -> Generator[tuple[str, Row], None, None]

Returns a generator that iterate over the name and value

of all the rows in the plate.

Yields:

  • tuple[str, Row] –

    Name and row object.

wells

wells() -> Generator[tuple[str, Well], None, None]

Returns a generator that iterate over the path and value

of all the wells (along rows, columns) in the plate.

Yields:

  • [str, Well] –

    Path and well object.

positions

positions() -> Generator[tuple[str, Position], None, None]

Returns a generator that iterate over the path and value

of all the positions (along rows, columns, and wells) in the plate.

Yields:

  • [str, Position] –

    Path and position object.

rename_well

rename_well(old: str, new: str)

Rename a well.

Parameters:

  • old (str) –

    Old name of well, e.g. "A/1"

  • new (str) –

    New name of well, e.g. "B/2"

ImageArray

ImageArray(handle: Any, impl: ZarrImplementation, dim_names: tuple[str, ...] | None = None)

Bases: NGFFArray

Container object for image stored as a zarr array (up to 5D: TCZYX)

nbytes property

nbytes: int

Total number of bytes for the uncompressed array.

metadata property

metadata

Delegate to native handle's metadata (if available).

path property

path: str

Path of the underlying array (if available).

native property

native

Raw implementation handle (zarr.Array, TensorStore, etc.).

from_handle classmethod

from_handle(handle: Any, impl: ZarrImplementation, dim_names: tuple[str, ...] | None = None) -> Self

Construct from an implementation-native handle.

resize

resize(new_shape: tuple[int, ...]) -> None

Resize the array in-place.

append

append(data: ndarray, axis: int = 0) -> tuple[int, ...]

Append data along axis. Returns the new shape.

numpy

numpy() -> NDArray

Return the whole array as an in-RAM NumPy array.

dask_array

dask_array()

Return as a dask array (delegates to implementation).

write_from_dask

write_from_dask(dask_array) -> None

Write a dask array into this array's store.

downsample_into

downsample_into(target: NGFFArray, factors: list[int], method: str = 'mean') -> None

Downsample this array into a target array.