Skip to content

Commit

Permalink
raise a keyerror when multiscales metadata is missing from attributes (
Browse files Browse the repository at this point in the history
  • Loading branch information
d-v-b authored Jun 19, 2024
1 parent 2332e56 commit ee1fcef
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 9 deletions.
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import zarr
url = "https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.4/idr0062A/6001240.zarr"

# open the Zarr group
zgroup = zarr.open(url)
zgroup = zarr.open(url, mode='r')

# group_model is a `GroupSpec`, i.e. a Pydantic model of a Zarr group
group_model = Group.from_zarr(zgroup)
Expand Down Expand Up @@ -113,7 +113,7 @@ print(multi_meta)
arrays = [zgroup[d.path] for d in multi_meta[0].datasets]
print(arrays)
"""
[<zarr.core.Array '/0' (2, 236, 275, 271) uint16>, <zarr.core.Array '/1' (2, 236, 137, 135) uint16>, <zarr.core.Array '/2' (2, 236, 68, 67) uint16>]
[<zarr.core.Array '/0' (2, 236, 275, 271) uint16 read-only>, <zarr.core.Array '/1' (2, 236, 137, 135) uint16 read-only>, <zarr.core.Array '/2' (2, 236, 68, 67) uint16 read-only>]
"""
```

Expand Down
12 changes: 12 additions & 0 deletions src/pydantic_ome_ngff/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from collections import Counter
from typing import TYPE_CHECKING, Protocol, runtime_checkable
from zarr.storage import BaseStore

import numpy as np

Expand Down Expand Up @@ -38,3 +39,14 @@ def listify_numpy(data: Any) -> Any:
if isinstance(data, np.ndarray):
return data.tolist()
return data


def get_path(store: BaseStore) -> str:
"""
Get a path from a zarr store
"""
if hasattr(store, "path"):
return store.path

else:
return ""
14 changes: 9 additions & 5 deletions src/pydantic_ome_ngff/v04/multiscale.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
ArrayLike,
ChunkedArrayLike,
duplicates,
get_path,
)
from pydantic_ome_ngff.v04.axis import Axis, AxisType
from pydantic_ome_ngff.v04.base import version
Expand Down Expand Up @@ -296,16 +297,17 @@ def from_zarr(cls, node: zarr.Group) -> Group:
A model of the Zarr group.
"""
# on unlistable storage backends, the members of this group will be {}
guess = GroupSpec.from_zarr(node)
guess = GroupSpec.from_zarr(node, depth=0)

try:
multi_meta_maybe = guess.attributes["multiscales"]
except KeyError as e:
store_path = get_path(node.store)
msg = (
"Failed to find mandatory `multiscales` key in the attributes of the Zarr group at "
f"{node.store}://{node.path}."
f"{node.store}://{store_path}://{node.path}."
)
raise ValueError(msg) from e
raise KeyError(msg) from e

multi_meta = GroupAttrs(multiscales=multi_meta_maybe)
members_tree_flat = {}
Expand All @@ -331,7 +333,7 @@ def from_zarr(cls, node: zarr.Group) -> Group:
members_normalized = GroupSpec.from_flat(members_tree_flat)

guess_inferred_members = guess.model_copy(
update={"members": {**guess.members, **members_normalized.members}}
update={"members": members_normalized.members}
)
return cls(**guess_inferred_members.model_dump())

Expand All @@ -347,7 +349,9 @@ def from_arrays(
name: str | None = None,
type: str | None = None,
metadata: dict[str, Any] | None = None,
chunks: tuple[int, ...] | tuple[tuple[int, ...]] | Literal["auto"] = "auto",
chunks: tuple[int, ...]
| tuple[tuple[int, ...], ...]
| Literal["auto"] = "auto",
compressor: Codec = DEFAULT_COMPRESSOR,
fill_value: Any = 0,
order: Literal["C", "F", "auto"] = "auto",
Expand Down
9 changes: 7 additions & 2 deletions tests/v04/test_multiscales.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ def test_from_arrays(
axes = all_axes[:ndim]
else:
axes = tuple([*all_axes[4:], *all_axes[:3]])

chunks_arg: tuple[tuple[int, ...], ...] | tuple[int, ...] | Literal["auto"]
if chunks == "auto":
chunks_arg = chunks
chunks_expected = (
Expand Down Expand Up @@ -441,7 +441,12 @@ def test_from_zarr_missing_metadata(
)
group_model = GroupSpec()
group = group_model.to_zarr(store, path="test")
with pytest.raises(ValueError):
store_path = store.path if hasattr(store, "path") else ""
match = (
"Failed to find mandatory `multiscales` key in the attributes of the Zarr group at "
f"{store}://{store_path}://{group.path}."
)
with pytest.raises(KeyError, match=match):
Group.from_zarr(group)


Expand Down

0 comments on commit ee1fcef

Please sign in to comment.