|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
| 3 | +import warnings |
3 | 4 | from collections import Counter |
4 | 5 | from typing import TYPE_CHECKING, Any, Literal, Self |
5 | 6 |
|
|
19 | 20 | ValidTransform, |
20 | 21 | VectorScale, |
21 | 22 | VectorTransform, |
| 23 | + VectorTranslation, |
22 | 24 | _build_transforms, |
23 | 25 | _ndim, |
24 | 26 | ) |
|
27 | 29 | check_ordered_scales, |
28 | 30 | unique_items_validator, |
29 | 31 | ) |
| 32 | +from ome_zarr_models.exceptions import ValidationWarning |
30 | 33 | from ome_zarr_models.v04.axes import Axes |
31 | 34 |
|
32 | 35 | if TYPE_CHECKING: |
@@ -243,23 +246,40 @@ class Transforms(BaseModel): |
243 | 246 | transforms = Transforms(transforms=transforms_obj).transforms |
244 | 247 | check_length(transforms, valid_lengths=[1, 2], variable_name="transforms") |
245 | 248 |
|
246 | | - maybe_scale = transforms[0] |
247 | | - if maybe_scale.type != "scale": |
248 | | - msg = ( |
249 | | - "The first element of `coordinateTransformations` must be a scale " |
250 | | - f"transform. Got {maybe_scale} instead." |
251 | | - ) |
252 | | - raise ValueError(msg) |
253 | | - if len(transforms) == 2: |
254 | | - maybe_trans = transforms[1] |
255 | | - if (maybe_trans.type) != "translation": |
256 | | - msg = ( |
257 | | - "The second element of `coordinateTransformations` must be a " |
258 | | - f"translation transform. Got {maybe_trans} instead." |
| 249 | + transform_types = tuple(t.type for t in transforms) |
| 250 | + if transform_types == ("scale",) or transform_types == ("scale", "translation"): |
| 251 | + return transforms_obj |
| 252 | + elif transform_types == ("translation", "scale"): |
| 253 | + if isinstance(transforms[0], VectorTranslation) and isinstance( |
| 254 | + transforms[1], VectorScale |
| 255 | + ): |
| 256 | + # Can only do the swap if we know the vectors |
| 257 | + warnings.warn( |
| 258 | + "Translation and scale are in the wrong order " |
| 259 | + "(scale should come first). Swapping transforms.", |
| 260 | + ValidationWarning, |
| 261 | + stacklevel=2, |
259 | 262 | ) |
260 | | - raise ValueError(msg) |
| 263 | + new_transforms = ( |
| 264 | + transforms[1], |
| 265 | + VectorTranslation( |
| 266 | + type="translation", |
| 267 | + translation=[ |
| 268 | + t * s |
| 269 | + for t, s in zip( |
| 270 | + transforms[0].translation, |
| 271 | + transforms[1].scale, |
| 272 | + strict=False, |
| 273 | + ) |
| 274 | + ], |
| 275 | + ), |
| 276 | + ) |
| 277 | + return new_transforms |
261 | 278 |
|
262 | | - return transforms_obj |
| 279 | + raise ValueError( |
| 280 | + "Expected a scale or (scale, translation) transform. " |
| 281 | + f"Got {transform_types} instead." |
| 282 | + ) |
263 | 283 |
|
264 | 284 | @field_validator("coordinateTransformations", mode="after") |
265 | 285 | @classmethod |
|
0 commit comments