Skip to content

Commit

Permalink
Check scales are ordered (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
dstansby authored Dec 12, 2024
1 parent a6bb702 commit ac854b7
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 2 deletions.
26 changes: 24 additions & 2 deletions src/ome_zarr_models/v04/multiscales.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from ome_zarr_models.v04.coordinate_transformations import (
ScaleTransform,
TranslationTransform,
VectorScale,
VectorTransform,
_build_transforms,
_ndim,
Expand Down Expand Up @@ -188,7 +189,26 @@ def build(
)


Datasets = Sequence[Dataset]
def _ensure_ordered_scales(datasets: list[Dataset]) -> list[Dataset]:
"""
Make sure datasets are ordered from highests resolution to smallest.
"""
scale_transforms = [d.coordinateTransformations[0] for d in datasets]
# Only handle scales given in metadata, not in files
scale_vector_transforms = [
t for t in scale_transforms if isinstance(t, VectorScale)
]
scales = [s.scale for s in scale_vector_transforms]
for i in range(len(scales) - 1):
s1, s2 = scales[i], scales[i + 1]
is_ordered = all(s1[j] <= s2[j] for j in range(len(s1)))
if not is_ordered:
raise ValueError(
f"Dataset {i} has a lower resolution (scales = {s1}) "
f"than dataset {i+1} (scales = {s2})."
)

return datasets


class Multiscale(Base):
Expand All @@ -202,7 +222,9 @@ class Multiscale(Base):
AfterValidator(_ensure_unique_axis_names),
AfterValidator(_ensure_axis_types),
]
datasets: Datasets = Field(..., min_length=1)
datasets: Annotated[tuple[Dataset, ...], AfterValidator(_ensure_ordered_scales)] = (
Field(..., min_length=1)
)
version: Literal["0.4"] | None = None
coordinateTransformations: ValidTransform | None = None
metadata: JsonValue = None
Expand Down
33 changes: 33 additions & 0 deletions tests/v04/test_multiscales.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,39 @@ def test_validate_axes_dset_transforms() -> None:
)


def test_ordred_multiscales() -> None:
"""
> The "path"s MUST be ordered from largest (i.e. highest resolution) to smallest.
"""
axes = (
Axis(name="c", type="channel", unit=None),
Axis(name="z", type="space", unit="meter"),
Axis(name="x", type="space", unit="meter"),
Axis(name="y", type="space", unit="meter"),
)
datasets = (
Dataset(
path="0",
coordinateTransformations=(VectorScale(type="scale", scale=(2, 2, 2, 2)),),
),
Dataset(
path="1",
coordinateTransformations=(VectorScale(type="scale", scale=(2, 2, 1, 2)),),
),
)
with pytest.raises(
ValidationError,
match=re.escape(
"Dataset 0 has a lower resolution (scales = [2.0, 2.0, 2.0, 2.0]) "
"than dataset 1 (scales = [2.0, 2.0, 1.0, 2.0])"
),
):
Multiscale(
axes=axes,
datasets=datasets,
)


@pytest.mark.skip
def test_multiscale_group_datasets_exist(
default_multiscale: Multiscale,
Expand Down

0 comments on commit ac854b7

Please sign in to comment.