Skip to content

brainhops.io.images.zarr

Readers and writers for Zarr and OME-Zarr images.

Classes

ZarrImage

ZarrImage(node: ZarrNode | None = None)

Bases: ZarrParserWriter, WritableFileBasedImage, SingleScaleImage

An image that is encoded by a plain Zarr array.

A plain Zarr array carries no world geometry, so the image is read with an identity geometry unless a voxel-to-world transformation is supplied through the transformation argument. An OME-Zarr pyramid, whose group carries a multiscale geometry, is read by OmeZarrImage instead.

The array is held as a handle and its data is read on first access, so opening the image does not read the array.

Attributes

PREFIXES class-attribute
PREFIXES: tuple[str, ...] = ()

Filename prefixes required by this parser, e.g. ("y_", "iy_").

An empty tuple means "no constraint". A parser that constrains the prefix is more specific than one that does not, and wins ties.

Declaring EXTENSIONS and PREFIXES separately states the cross-product implicitly, which is how these conventions actually work: SPM's four names are {y_, iy_} x {.nii, .nii.gz}.

PRIORITY class-attribute
PRIORITY: int = 10

Kind precedence, used only to break ties that confidence could not.

A NIfTI file is legitimately both an image and a set of affines, so when nothing else separates them the image wins. Scoring sniffers (e.g. NIfTI intent codes) normally decide well before this matters.

shape property
shape: tuple[int, ...]

The shape of the image data.

ndim property
ndim: int

The number of dimensions of the image data.

dtype property
dtype: dtype

The data type of the image data.

grid property

The Cartesian field that defines the sampling grid of the image.

This is the grid of the image's geometry.

transformation property writable
transformation: Transformation

The preferred transformation.

It is always the last transformation in the list.

Assigning a transformation appends it as the new preferred transformation. Assigning an integer or a string selects an existing transformation by position or by output-space name and moves it to the end. Assigning a transformation that is already in the list moves it to the end instead of adding a copy.

A transformation is recognized as already present by identity (transformations compare by identity): a distinct transformation with the same parameters is appended as a new preferred transformation.

geometry property
geometry: Geometry

A transformation that is the composition of the preferred voxel-to-world transformation and the cartesian field corresponding to the image's shape.

This transformation can be used to reslice any image onto the same grid as this image.

Methods:

sniff classmethod
sniff(
    file: FileOrContentLike,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> type | None

On a dispatcher, identify which registered format would read file. On a concrete format, score how confident it is that file, in any supported form, is its own.

sniff_content classmethod
sniff_content(
    content: ContentLike,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> type | None

On a dispatcher, identify which registered format would read the content (text or bytes). On a concrete format, score how confident it is that the content is its own.

sniff_text classmethod
sniff_text(
    text: str,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> type | None

On a dispatcher, identify which registered format would read the text. On a concrete format, score how confident it is that the text is its own.

sniff_lines classmethod
sniff_lines(
    lines: Iterable[str],
    error: bool | Type[Exception] = False,
    **kwargs,
) -> type | None

On a dispatcher, identify which registered format would read the lines. On a concrete format, score how confident it is that the lines are its own.

sniff_line classmethod
sniff_line(
    line: str,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> type | None

On a dispatcher, identify which registered format would read the line. On a concrete format, score how confident it is that the line is its own.

load classmethod
load(other: FileOrContentLike, **kwargs) -> Self

On a dispatcher, pick the best-matching registered format and build an instance of it from other. On a concrete format, build an instance of this class from other, in any supported form.

from_spec classmethod
from_spec(spec: SourceSpec, **kwargs) -> Self

Load a structured source specification through this dispatcher.

from_filename classmethod
from_filename(filename: FilenameLike, **kwargs) -> Self

Build an object from a filename.

Parameters:

Name Type Description Default
filename FilenameLike

The filename to parse.

required
**kwargs

Parser-specific options.

{}

Returns:

Type Description
obj

The parsed object.

from_content classmethod
from_content(content: ContentLike, **kwargs) -> Self

On a dispatcher, pick the best-matching registered format and build an instance of it from the content (text or bytes). On a concrete format, build an instance of this class from the content.

from_text classmethod
from_text(text: str, **kwargs) -> Self

On a dispatcher, pick the best-matching registered format and build an instance of it from the text. On a concrete format, build an instance of this class from the text.

from_lines classmethod
from_lines(lines: Iterable[str], **kwargs) -> Self

On a dispatcher, pick the best-matching registered format and build an instance of it from the lines. On a concrete format, build an instance of this class from the lines.

from_line classmethod
from_line(line: str, **kwargs) -> Self

On a dispatcher, pick the best-matching registered format and build an instance of it from the line. On a concrete format, build an instance of this class from the line.

save
save(file: FileLike, **kwargs) -> None

Write the object to a file (path or file-like object).

This is the generic front door to the to_* family. It is named save rather than to because to already means something else on the data models these parsers are mixed into: Transformation.to converts an object to another type. A writer's to was shadowed by it on every writable transformation.

Parameters:

Name Type Description Default
file FileLike

The file to write to.

required
**kwargs

Parser-specific options.

{}
to_filename
to_filename(filename: FilenameLike, **kwargs) -> None

Write the object to a filename.

Parameters:

Name Type Description Default
filename FilenameLike

The filename to write to.

required
**kwargs

Parser-specific options.

{}
to_bytes
to_bytes(**kwargs) -> bytes

Return a binary version of the file.

Parameters:

Name Type Description Default
**kwargs

Parser-specific options.

{}

Returns:

Type Description
bytes

A binary version of the file.

to_text
to_text(**kwargs) -> str

Return a text version of the file.

Parameters:

Name Type Description Default
**kwargs

Parser-specific options.

{}

Returns:

Type Description
str

A text version of the file.

to_lines
to_lines(**kwargs) -> Iterator[str]

Return a text version of the file as an iterable of lines.

Parameters:

Name Type Description Default
**kwargs

Parser-specific options.

{}

Returns:

Type Description
Iterator[str]

An iterable of lines representing the object.

to_line
to_line(**kwargs) -> str

Return a line representing the object.

Parameters:

Name Type Description Default
**kwargs

Parser-specific options.

{}

Returns:

Type Description
str

A line representing the object.

from_dict classmethod
from_dict(other: Mapping, *args, **kwargs) -> Self

Create an instance of the class from a dictionary-like object.

Only keys in the dictionary that match keyword-like fields of this class, or the keywords its constructor takes without storing them (its InitVars, such as the matrix= of an Affine), will be used. Other keys are ignored, but see from_other, which refuses them.

Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.

A key naming a field that this class fixes (a field that cannot be passed to its constructor) is checked instead of used: a dictionary that sets it to anything other than None or the value of this class is refused with a ValueError.

from_instance classmethod
from_instance(other: Any, *args, **kwargs) -> Self

Create an instance from an instance of a similar class.

The data model copies the fields both classes share, by name. A field that a file format declares for its own use -- such as the nibabel image and header of the NIfTI and MGH formats -- is only copied from an object of that same format: from any other object, a field of the same name holds something else (a NIfTI image is no MGH image), so this class's default is kept instead. Saving a NIfTI image to MGH, or the converse, therefore converts the data model only, and the format-specific state is rebuilt by the writer.

from_other classmethod
from_other(other: Any, *args, **kwargs) -> Self

Create an instance from a file, or from anything the data model reads.

A path (str or os.PathLike), an open file, bytes or a structured source (SourceSpec) is read with load: on a dispatcher such as FileBasedImage, the best-matching registered format reads it, and on a concrete format, that format does. Any other value is handed to the data model's own from_other, which reads a mapping field by field, copies an instance of a similar class, and passes anything else to the constructor.

Parameters:

Name Type Description Default
other Any

A file, its content, a mapping, or an instance of a similar class.

required
*args

Constructor arguments. A file is read with keyword options only.

()
**kwargs

Format-specific options when reading a file, and field values otherwise.

{}

Returns:

Type Description
obj

The object that was built.

Raises:

Type Description
TypeError

If positional arguments come with a file to read.

__array__
__array__(dtype: DTypeLike | None = None) -> ndarray

Return the image data as an array.

reslice
reslice(
    geometry: Self
    | Geometry
    | Transformation
    | None = None,
    degree: int = 1,
    bound: str = "reflect",
    coeff: bool = False,
    copy: bool = False,
) -> Self

Apply transformations to current data and return new image.

Parameters:

Name Type Description Default
geometry Image | Geometry | Transformation

Geometry of the output image.

The geometry is a voxel-to-world transformation that defines the grid onto which the image will be resliced.

If it is a Geometry, then it also defines the shape of the output image. Otherwise, the current shape of the image is used.

If it is None, the image is resampled onto its own grid.

None
degree 0..5

The spline degree. 0=nearest, 1=linear, 2=quadratic, etc.

0..5
bound (nearest, reflect, mirror, grid - wrap, wrap)

The boundary condition. If a string, one of: - 'nearest': nearest edge value (a a a a | a b c d | d d d d) - 'reflect': reflect at edge (d c b a | a b c d | d c b a) - 'mirror': mirror at edge (d c b | a b c d | c b a) - 'grid-wrap': wrap around (a b c d | a b c d | a b c d) - 'wrap': wrap around with shift (d b c d | a b c d | b c a b) If a float, the constant value to use beyond the edge.

'nearest'
coeff bool

If True, the input image is assumed to already contain spline coefficients. If False, the input image is prefiltered before interpolation.

False
copy bool

Whether the output data must be a fresh array. As with torch.Tensor.to, when False the output data may share memory with the input data: a reslice that only gathers (a flip, a permutation, or a unit-step slice, such as a reslice onto the image's own grid) can return a view of it. When True the output data never shares memory with the input data. A dask array is never copied: it is immutable, and writing into the output rebinds the output's own graph, never the input's, so the lazy output is returned as is.

False

Returns:

Type Description
Image

The resliced image.

__call__
__call__(transform: Transformation) -> SingleScaleImage

Apply a transformation to the image, but do not compute.

Parameters:

Name Type Description Default
transform Transformation

The transformation to apply.

The output space of this transformation should match (or be compatible with) the output space of the preferred transformation. That is, the new "voxel-to-world" transformation is defined as self.transformation @ transform.inverse().

required

Returns:

Type Description
Image

The updated (not-yet-resliced) image.

__getitem__
__getitem__(
    index: tuple[int | slice | None, ...],
) -> SingleScaleImage

Index into the image data while preserving the geometry of the image.

from_store classmethod
from_store(location: StoreLike, **kwargs) -> Self

Read the object from a store location or an opened store.

location is a path, given as a string or an os.PathLike, or an already-opened abczarr or driver-native store.

from_node classmethod
from_node(
    node: Any,
    transformation: Transformation | None = None,
    **kwargs,
) -> Self

Read the image from an opened Zarr array.

A plain array carries no world geometry, so transformation supplies the voxel-to-world placement to read it with. Without one the image is read with an identity geometry.

A group is refused: it carries no array to read, and reading one as an image would fail later and more obscurely.

OmeZarrImage magic

OmeZarrImage(
    _axes: AxisList[Axis | _Ellipsis] | None = None,
    _ome: Multiscale | None = None,
)

Bases: ZarrParserWriter, WritableFileBasedImage, MultiScaleImage

A multiscale image that is encoded by an OME-Zarr pyramid.

Each resolution level of the pyramid is read as a single-scale image whose voxel-to-world geometry comes from the level's coordinate transformation. The metadata is read through abczarr and normalized so that each level carries one transformation. The levels are ordered from finest to coarsest, and the axes are permuted from the OME storage order into the brainhops order at the boundary. A plain Zarr array, which carries no multiscale geometry, is read by ZarrImage instead.

Every level holds its array handle and reads it on first access, so opening a large pyramid does not read the arrays.

Attributes

PREFIXES class-attribute
PREFIXES: tuple[str, ...] = ()

Filename prefixes required by this parser, e.g. ("y_", "iy_").

An empty tuple means "no constraint". A parser that constrains the prefix is more specific than one that does not, and wins ties.

Declaring EXTENSIONS and PREFIXES separately states the cross-product implicitly, which is how these conventions actually work: SPM's four names are {y_, iy_} x {.nii, .nii.gz}.

PRIORITY class-attribute
PRIORITY: int = 10

Kind precedence, used only to break ties that confidence could not.

A NIfTI file is legitimately both an image and a set of affines, so when nothing else separates them the image wins. Scoring sniffers (e.g. NIfTI intent codes) normally decide well before this matters.

shape property
shape: tuple[int, ...]

The shape of the image data.

ndim property
ndim: int

The number of dimensions of the image data.

dtype property
dtype: dtype

The data type of the image data.

grid property

The Cartesian field that defines the sampling grid of the image.

This is the grid of the image's geometry.

data property
data: ArrayProtocol

The data of the highest-resolution level of the pyramid.

nscales property
nscales: int

Return the number of scales in the multi-resolution pyramid.

scales property

Yield all levels as single-resolution images.

transformation property writable
transformation: Transformation

The preferred transformation.

It is always the last transformation in the list.

Assigning a transformation appends it as the new preferred transformation. Assigning an integer or a string selects an existing transformation by position or by output-space name and moves it to the end. Assigning a transformation that is already in the list moves it to the end instead of adding a copy.

A transformation is recognized as already present by identity (transformations compare by identity): a distinct transformation with the same parameters is appended as a new preferred transformation.

geometry property
geometry: Geometry

The geometry of the highest-resolution image in the pyramid.

A transformation that is the composition of the preferred voxel-to-world transformation and the cartesian field corresponding to the image's shape.

This transformation can be used to reslice any image onto the same grid as this image.

axes property
axes: AxisList[Axis | _Ellipsis] | None

The axes a from-scratch pyramid is stored under, or None.

bagof stores the axes argument under _axes but generates no reader for it, so the reader is spelled out here.

Methods:

sniff classmethod
sniff(
    file: FileOrContentLike,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> type | None

On a dispatcher, identify which registered format would read file. On a concrete format, score how confident it is that file, in any supported form, is its own.

sniff_content classmethod
sniff_content(
    content: ContentLike,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> type | None

On a dispatcher, identify which registered format would read the content (text or bytes). On a concrete format, score how confident it is that the content is its own.

sniff_text classmethod
sniff_text(
    text: str,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> type | None

On a dispatcher, identify which registered format would read the text. On a concrete format, score how confident it is that the text is its own.

sniff_lines classmethod
sniff_lines(
    lines: Iterable[str],
    error: bool | Type[Exception] = False,
    **kwargs,
) -> type | None

On a dispatcher, identify which registered format would read the lines. On a concrete format, score how confident it is that the lines are its own.

sniff_line classmethod
sniff_line(
    line: str,
    error: bool | Type[Exception] = False,
    **kwargs,
) -> type | None

On a dispatcher, identify which registered format would read the line. On a concrete format, score how confident it is that the line is its own.

load classmethod
load(other: FileOrContentLike, **kwargs) -> Self

On a dispatcher, pick the best-matching registered format and build an instance of it from other. On a concrete format, build an instance of this class from other, in any supported form.

from_spec classmethod
from_spec(spec: SourceSpec, **kwargs) -> Self

Load a structured source specification through this dispatcher.

from_filename classmethod
from_filename(filename: FilenameLike, **kwargs) -> Self

Build an object from a filename.

Parameters:

Name Type Description Default
filename FilenameLike

The filename to parse.

required
**kwargs

Parser-specific options.

{}

Returns:

Type Description
obj

The parsed object.

from_content classmethod
from_content(content: ContentLike, **kwargs) -> Self

On a dispatcher, pick the best-matching registered format and build an instance of it from the content (text or bytes). On a concrete format, build an instance of this class from the content.

from_text classmethod
from_text(text: str, **kwargs) -> Self

On a dispatcher, pick the best-matching registered format and build an instance of it from the text. On a concrete format, build an instance of this class from the text.

from_lines classmethod
from_lines(lines: Iterable[str], **kwargs) -> Self

On a dispatcher, pick the best-matching registered format and build an instance of it from the lines. On a concrete format, build an instance of this class from the lines.

from_line classmethod
from_line(line: str, **kwargs) -> Self

On a dispatcher, pick the best-matching registered format and build an instance of it from the line. On a concrete format, build an instance of this class from the line.

save
save(file: FileLike, **kwargs) -> None

Write the object to a file (path or file-like object).

This is the generic front door to the to_* family. It is named save rather than to because to already means something else on the data models these parsers are mixed into: Transformation.to converts an object to another type. A writer's to was shadowed by it on every writable transformation.

Parameters:

Name Type Description Default
file FileLike

The file to write to.

required
**kwargs

Parser-specific options.

{}
to_filename
to_filename(filename: FilenameLike, **kwargs) -> None

Write the object to a filename.

Parameters:

Name Type Description Default
filename FilenameLike

The filename to write to.

required
**kwargs

Parser-specific options.

{}
to_bytes
to_bytes(**kwargs) -> bytes

Return a binary version of the file.

Parameters:

Name Type Description Default
**kwargs

Parser-specific options.

{}

Returns:

Type Description
bytes

A binary version of the file.

to_text
to_text(**kwargs) -> str

Return a text version of the file.

Parameters:

Name Type Description Default
**kwargs

Parser-specific options.

{}

Returns:

Type Description
str

A text version of the file.

to_lines
to_lines(**kwargs) -> Iterator[str]

Return a text version of the file as an iterable of lines.

Parameters:

Name Type Description Default
**kwargs

Parser-specific options.

{}

Returns:

Type Description
Iterator[str]

An iterable of lines representing the object.

to_line
to_line(**kwargs) -> str

Return a line representing the object.

Parameters:

Name Type Description Default
**kwargs

Parser-specific options.

{}

Returns:

Type Description
str

A line representing the object.

from_dict classmethod
from_dict(other: Mapping, *args, **kwargs) -> Self

Create an instance of the class from a dictionary-like object.

Only keys in the dictionary that match keyword-like fields of this class, or the keywords its constructor takes without storing them (its InitVars, such as the matrix= of an Affine), will be used. Other keys are ignored, but see from_other, which refuses them.

Additional positional and/or keyword arguments can be provided, and will take precedence over the values in the dictionary.

A key naming a field that this class fixes (a field that cannot be passed to its constructor) is checked instead of used: a dictionary that sets it to anything other than None or the value of this class is refused with a ValueError.

from_instance classmethod
from_instance(other: Any, *args, **kwargs) -> Self

Create an instance from an instance of a similar class.

The data model copies the fields both classes share, by name. A field that a file format declares for its own use -- such as the nibabel image and header of the NIfTI and MGH formats -- is only copied from an object of that same format: from any other object, a field of the same name holds something else (a NIfTI image is no MGH image), so this class's default is kept instead. Saving a NIfTI image to MGH, or the converse, therefore converts the data model only, and the format-specific state is rebuilt by the writer.

from_other classmethod
from_other(other: Any, *args, **kwargs) -> Self

Create an instance from a file, or from anything the data model reads.

A path (str or os.PathLike), an open file, bytes or a structured source (SourceSpec) is read with load: on a dispatcher such as FileBasedImage, the best-matching registered format reads it, and on a concrete format, that format does. Any other value is handed to the data model's own from_other, which reads a mapping field by field, copies an instance of a similar class, and passes anything else to the constructor.

Parameters:

Name Type Description Default
other Any

A file, its content, a mapping, or an instance of a similar class.

required
*args

Constructor arguments. A file is read with keyword options only.

()
**kwargs

Format-specific options when reading a file, and field values otherwise.

{}

Returns:

Type Description
obj

The object that was built.

Raises:

Type Description
TypeError

If positional arguments come with a file to read.

__array__
__array__(dtype: DTypeLike | None = None) -> ndarray

Return the image data as an array.

to_singlescale
to_singlescale(index: int = 0) -> SingleScaleImage

Return one of the levels as a single-resolution image.

reslice
reslice(
    geometry: Image
    | Geometry
    | Transformation
    | None = None,
    degree: int = 1,
    bound: str = "reflect",
    coeff: bool = False,
    copy: bool = False,
) -> Self

Apply transformations to current data and return new image

Parameters:

Name Type Description Default
geometry Image | Geometry | Transformation

Geometry of the highest-resolution level of the output image.

The geometry is a voxel-to-world transformation that defines the grid onto which the image will be resliced.

If it is a Geometry, then it also defines the shape of the output image. Otherwise, the current shape of the image is used.

If it is None, the image is resampled onto its own grid.

None
intrinsic Geometry | Transformation | None

An optional transformation that defines the intrinsic geometry of the highest-resolution image in the output pyramid. If provided, it is used to compute the geometry of each level in the output pyramid. If not provided, this function returns a single-scale image instead.

required
degree 0..5

The spline degree. 0=nearest, 1=linear, 2=quadratic, etc.

0..5
bound (nearest, reflect, mirror, grid - wrap, wrap)

The boundary condition. If a string, one of: - 'nearest': nearest edge value (a a a a | a b c d | d d d d) - 'reflect': reflect at edge (d c b a | a b c d | d c b a) - 'mirror': mirror at edge (d c b | a b c d | c b a) - 'grid-wrap': wrap around (a b c d | a b c d | a b c d) - 'wrap': wrap around with shift (d b c d | a b c d | b c a b) If a float, the constant value to use beyond the edge.

'nearest'
coeff bool

If True, the input image is assumed to already contain spline coefficients. If False, the input image is prefiltered before interpolation.

False
copy bool

Whether the output data must be a fresh array. As with torch.Tensor.to, when False the output data may share memory with the input data: a reslice that only gathers (a flip, a permutation, or a unit-step slice, such as a reslice onto the image's own grid) can return a view of it. When True the output data never shares memory with the input data. A dask array is never copied: it is immutable, and writing into the output rebinds the output's own graph, never the input's, so the lazy output is returned as is.

False

Returns:

Type Description
SingleScaleImage

The resliced image.

__call__
__call__(transform: Transformation) -> Self

Apply a transformation to the multi-scale image.

Parameters:

Name Type Description Default
transform Transformation

The transformation to apply.

The output space of this transformation should match (or be compatible with) the output space of the preferred transformation. That is, the new "intrinsic-to-world" transformation is defined as self.transformation @ transform.inverse().

required

Returns:

Type Description
MultiScaleImage

The transformed image.

from_store classmethod
from_store(location: StoreLike, **kwargs) -> Self

Read the object from a store location or an opened store.

location is a path, given as a string or an os.PathLike, or an already-opened abczarr or driver-native store.

from_node classmethod
from_node(node: Any, **kwargs) -> Self

Read the pyramid from an opened Zarr group.

The multiscale metadata is parsed here, so a group whose metadata cannot be read as a pyramid is refused at open rather than on first access. The levels themselves stay unread: each holds its array handle and reads it when its data is asked for.

to_node
to_node(
    node: Any,
    chunks: Any = None,
    version: str | None = None,
    **kwargs,
) -> None

Write the pyramid into an opened Zarr group, and return it.

to_store
to_store(
    location: StoreLike,
    chunks: Any = None,
    version: str | None = None,
    **kwargs,
) -> None

Write the pyramid to a store location, or into an opened store.

An opened group is written into as it stands. A location names a store that does not exist yet, so the group is created there first.

OmeImageError

Bases: ParserContentError

Raised when an OME-Zarr image group cannot be read.

A group with no multiscale metadata, or one whose metadata abczarr cannot parse into a valid pyramid, is refused with this error.