Skip to content

Commit 19bc86e

Browse files
authored
Merge pull request #14 from JaneliaSciComp/fix/multiscale-backwards-compat
Fix/multiscale backwards compat
2 parents 8e0100d + 5b9faae commit 19bc86e

File tree

2 files changed

+173
-1
lines changed

2 files changed

+173
-1
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ dependencies = [
4949
]
5050

5151
[[tool.hatch.envs.test.matrix]]
52-
python = ["3.10", "3.11"]
52+
python = ["3.10", "3.11", "3.12"]
5353

5454
[tool.hatch.envs.test.scripts]
5555
run-coverage = "pytest --cov-config=pyproject.toml --cov=pkg --cov=tests"

src/xarray_ome_ngff/v04/multiscale.py

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from __future__ import annotations
22

33
from typing import TYPE_CHECKING, Literal
4+
from typing_extensions import deprecated
45

56
from pydantic_ome_ngff.v04 import MultiscaleGroup
7+
from pydantic_ome_ngff.v04.multiscale import Group
68

79
from xarray_ome_ngff.array_wrap import (
810
ArrayWrapperSpec,
@@ -389,6 +391,48 @@ def model_multiscale_group(
389391
return group
390392

391393

394+
@deprecated("This function is deprecated. Use `model_multiscale_group instead.`")
395+
def model_group(
396+
*,
397+
arrays: dict[str, DataArray],
398+
transform_precision: int | None = None,
399+
chunks: tuple[int, ...] | tuple[tuple[int, ...]] | Literal["auto"] = "auto",
400+
compressor: Codec | None = DEFAULT_COMPRESSOR,
401+
fill_value: Any = 0,
402+
) -> Group:
403+
"""
404+
Create a model of an OME-NGFF multiscale group from a dict of `xarray.DataArray`.
405+
The dimensions / coordinates of the arrays will be used to infer OME-NGFF axis metadata, as well
406+
as the OME-NGFF coordinate transformation metadata (i.e., scaling and translation).
407+
408+
Parameters
409+
----------
410+
arrays: dict[str, DataArray]
411+
A mapping from strings to `xarray.DataArray`.
412+
transform_precision: int | None, default is None
413+
Whether, and how much, to round the transformations estimated from the coordinates.
414+
The default (`None`) results in no rounding; if `transform_precision` is an int, then
415+
transforms will be rounded to `transform_precision` decimal places using `numpy.round`.
416+
chunks: tuple[int] | tuple[tuple[int, ...]] | Literal["auto"], default = "auto"
417+
The chunks for the arrays in the multiscale group.
418+
If the string "auto" is provided, each array will have chunks set to the zarr-python default
419+
value, which depends on the shape and dtype of the array.
420+
If a single sequence of ints is provided, then this defines the chunks for all arrays.
421+
If a sequence of sequences of ints is provided, then this defines the chunks for each array.
422+
compressor: Codec | None, default = numcodecs.ZStd.
423+
The compressor to use for the arrays. Default is `numcodecs.ZStd`.
424+
fill_value: Any
425+
The fill value for the Zarr arrays.
426+
"""
427+
return model_multiscale_group(
428+
arrays=arrays,
429+
transform_precision=transform_precision,
430+
chunks=chunks,
431+
compressor=compressor,
432+
fill_value=fill_value,
433+
)
434+
435+
392436
def create_multiscale_group(
393437
*,
394438
store: BaseStore,
@@ -440,6 +484,59 @@ def create_multiscale_group(
440484
return model.to_zarr(store, path, overwrite=overwrite)
441485

442486

487+
@deprecated("This function is deprecated. Use `create_multiscale_group` instead.")
488+
def create_group(
489+
*,
490+
store: BaseStore,
491+
path: str,
492+
arrays: dict[str, DataArray],
493+
transform_precision: int | None = None,
494+
chunks: tuple[int, ...] | tuple[tuple[int, ...]] | Literal["auto"] = "auto",
495+
compressor: Codec | None = DEFAULT_COMPRESSOR,
496+
fill_value: Any = 0,
497+
overwrite: bool = False,
498+
) -> zarr.Group:
499+
"""
500+
Create Zarr group that complies with 0.4 of the OME-NGFF multiscale specification from a dict
501+
of `xarray.DataArray`.
502+
503+
Parameters
504+
----------
505+
506+
store: zarr.storage.BaseStore
507+
The storage backend for the Zarr hierarchy.
508+
path: str
509+
The path in the storage backend for the multiscale group.
510+
transform_precision: int | None, default is None
511+
Whether, and how much, to round the transformations estimated from the coordinates.
512+
The default (`None`) results in no rounding; specifying an `int` x will round transforms to
513+
x decimal places using `numpy.round(transform, x)`.
514+
chunks: tuple[int] | tuple[tuple[int, ...]] | Literal["auto"], default = "auto"
515+
The chunks for the arrays in the multiscale group.
516+
If the string "auto" is provided, each array will have chunks set to the zarr-python default
517+
value, which depends on the shape and dtype of the array.
518+
If a single sequence of ints is provided, then this defines the chunks for all arrays.
519+
If a sequence of sequences of ints is provided, then this defines the chunks for each array.
520+
compressor: Codec | None, default = numcodecs.ZStd.
521+
The compressor to use for the arrays. Default is `numcodecs.ZStd`.
522+
fill_value: Any
523+
The fill value for the Zarr arrays.
524+
overwrite: bool, default = False
525+
Whether to overwrite an existing Zarr array or group at `path`. Default is False, which will
526+
result in an exception being raised if a Zarr array or group already exists at `path`.
527+
"""
528+
return create_multiscale_group(
529+
store=store,
530+
path=path,
531+
arrays=arrays,
532+
transform_precision=transform_precision,
533+
chunks=chunks,
534+
compressor=compressor,
535+
fill_value=fill_value,
536+
overwrite=overwrite,
537+
)
538+
539+
443540
def read_multiscale_group(
444541
group: zarr.Group,
445542
*,
@@ -496,6 +593,48 @@ def read_multiscale_group(
496593
return result
497594

498595

596+
@deprecated("This function is deprecated. Use `read_multiscale_group` instead.")
597+
def read_group(
598+
group: zarr.Group,
599+
*,
600+
array_wrapper: (
601+
ZarrArrayWrapper | DaskArrayWrapper | ArrayWrapperSpec
602+
) = ZarrArrayWrapper(),
603+
multiscales_index: int = 0,
604+
) -> dict[str, DataArray]:
605+
"""
606+
Create a dictionary of `xarray.DataArray` from a Zarr group that implements version 0.4 of the
607+
OME-NGFF multiscale image specification.
608+
609+
The keys of the dictionary are the paths to the Zarr arrays. The values of the dictionary are
610+
`xarray.DataArray` objects, one per Zarr array described in the OME-NGFF multiscale metadata,
611+
with dimensions and coordinates that are consistent with the OME-NGFF `Axes` and
612+
`coordinateTransformations` metadata.
613+
614+
Parameters
615+
----------
616+
group: zarr.Group
617+
A handle for the Zarr group that contains the `multiscales` metadata.
618+
array_wrapper: BaseArrayWrapper | ArrayWrapperSpec, default is ZarrArrayWrapper
619+
Either an object that implements `BaseArrayWrapper`, or a dict model of such a subclass,
620+
which will be resolved to an object implementing `BaseArrayWrapper`. This object has a
621+
`wrap` method that takes an instance of `zarr.Array` and returns another array-like object.
622+
This enables wrapping Zarr arrays in a lazy array representation like Dask arrays
623+
(e.g., via `DaskArrayWrapper), which is necessary when working with large Zarr arrays.
624+
multiscales_index: int, default is 0
625+
Version 0.4 of the OME-NGFF multiscales spec states that multiscale
626+
metadata is stored in a JSON array within Zarr group attributes.
627+
This parameter determines which element from that array to use when defining DataArrays.
628+
629+
Returns
630+
-------
631+
dict[str, DataArray]
632+
"""
633+
return read_multiscale_group(
634+
group=group, array_wrapper=array_wrapper, multiscales_index=multiscales_index
635+
)
636+
637+
499638
def read_multiscale_array(
500639
array: zarr.Array,
501640
*,
@@ -566,3 +705,36 @@ def read_multiscale_array(
566705
"Could not find version 0.4 OME-NGFF multiscale metadata in any Zarr groups"
567706
f"ancestral to the array at {array.path}"
568707
)
708+
709+
710+
@deprecated("This function is deprecated. Use `read_multiscale_array` instead.")
711+
def read_array(
712+
array: zarr.Array,
713+
*,
714+
array_wrapper: (
715+
ZarrArrayWrapper | DaskArrayWrapper | ArrayWrapperSpec
716+
) = ZarrArrayWrapper(),
717+
) -> DataArray:
718+
"""
719+
Read a single Zarr array as an `xarray.DataArray`, using version 0.4 OME-NGFF multiscale
720+
metadata.
721+
722+
The information necessary for creating the coordinates of the `DataArray` are not stored
723+
in the attributes of the Zarr array given to this function. Instead, the coordinates must
724+
be inferred by walking up the Zarr hierarchy, group by group, until a Zarr group with attributes
725+
containing OME-NGFF multiscales metadata is found; then that metadata is parsed to determine
726+
whether that metadata references the provided array. Once the correct multiscales metadata is
727+
found, the coordinates can be constructed correctly.
728+
729+
Parameters
730+
----------
731+
array: zarr.Array
732+
A Zarr array that is part of a version 0.4 OME-NGFF multiscale image.
733+
array_wrapper: ZarrArrayWrapper | DaskArrayWrapper | ArrayWrapperSpec, default is ZarrArrayWrapper
734+
The array wrapper class to use when converting the Zarr array to an `xarray.DataArray`.
735+
Returns
736+
-------
737+
xarray.DataArray
738+
"""
739+
740+
return read_multiscale_array(array, array_wrapper=array_wrapper)

0 commit comments

Comments
 (0)