Skip to content

Commit 3628830

Browse files
committed
fix ome metadata reading
This code was merged into iohub, so until a new release is made and we can pin the version we have helper functions stored in ome_tmp
1 parent 5951848 commit 3628830

File tree

2 files changed

+97
-36
lines changed

2 files changed

+97
-36
lines changed

funlib/persistence/arrays/ome_datasets.py

Lines changed: 5 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import logging
2-
from itertools import chain
32
from pathlib import Path
43
from typing import Sequence
54

6-
import numpy as np
75
from iohub.ngff import AxisMeta, TransformationMeta, open_ome_zarr
86
from numpy.typing import DTypeLike
97

108
from funlib.geometry import Coordinate
119

1210
from .array import Array
1311
from .metadata import MetaData, OME_MetaDataFormat
12+
from .ome_tmp import get_effective_scale, get_effective_translation
1413

1514
logger = logging.getLogger(__name__)
1615

@@ -57,45 +56,15 @@ def open_ome_ds(
5756
units = [axis.unit for axis in axes if axis.unit is not None]
5857
types = [axis.type for axis in axes if axis.type is not None]
5958

60-
base_transform = ome_zarr.metadata.multiscales[0].coordinate_transformations
61-
img_transforms = [
62-
ome_zarr.metadata.multiscales[0].datasets[i].coordinate_transformations
63-
for i, dataset_meta in enumerate(ome_zarr.metadata.multiscales[0].datasets)
64-
if dataset_meta.path == name
65-
][0]
66-
67-
scales = [
68-
t.scale for t in chain(base_transform, img_transforms) if t.type == "scale"
69-
]
70-
translations = [
71-
t.translation
72-
for t in chain(base_transform, img_transforms)
73-
if t.type == "translation"
74-
]
75-
assert all(
76-
all(np.isclose(scale, Coordinate(scale))) for scale in scales
77-
), f"funlib.persistence only supports integer scales: {scales}"
78-
assert all(
79-
all(np.isclose(translation, Coordinate(translation)))
80-
for translation in translations
81-
), f"funlib.persistence only supports integer translations: {translations}"
82-
scales = [Coordinate(s) for s in scales]
83-
84-
# apply translations in order to get final scale/transform for this array
85-
base_scale = scales[0] * 0 + 1
86-
base_translation = scales[0] * 0
87-
for t in chain(base_transform, img_transforms):
88-
if t.type == "translation":
89-
base_translation += base_scale * Coordinate(t.translation)
90-
elif t.type == "scale":
91-
base_scale *= Coordinate(t.scale)
59+
scale = get_effective_scale(ome_zarr, name)
60+
offset = get_effective_translation(ome_zarr, name)
9261

9362
dataset = ome_zarr[name]
9463

9564
metadata = OME_MetaDataFormat().parse(
9665
dataset.shape,
97-
offset=list(base_translation),
98-
voxel_size=list(base_scale),
66+
offset=list(offset),
67+
voxel_size=list(scale),
9968
axis_names=axis_names,
10069
units=units,
10170
types=types,

funlib/persistence/arrays/ome_tmp.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
from typing import Literal
2+
3+
import numpy as np
4+
from iohub.ngff import TransformationMeta
5+
6+
7+
def _get_all_transforms(node, image: str | Literal["*"]) -> list[TransformationMeta]:
8+
"""Get all transforms metadata
9+
for one image array or the whole FOV.
10+
11+
Parameters
12+
----------
13+
image : str | Literal["*"]
14+
Name of one image array (e.g. "0") to query,
15+
or "*" for the whole FOV
16+
17+
Returns
18+
-------
19+
list[TransformationMeta]
20+
All transforms applicable to this image or FOV.
21+
"""
22+
transforms: list[TransformationMeta] = (
23+
[t for t in node.metadata.multiscales[0].coordinate_transformations]
24+
if node.metadata.multiscales[0].coordinate_transformations is not None
25+
else []
26+
)
27+
if image != "*" and image in node:
28+
for i, dataset_meta in enumerate(node.metadata.multiscales[0].datasets):
29+
if dataset_meta.path == image:
30+
transforms.extend(
31+
node.metadata.multiscales[0].datasets[i].coordinate_transformations
32+
)
33+
elif image != "*":
34+
raise ValueError(f"Key {image} not recognized.")
35+
return transforms
36+
37+
38+
def get_effective_scale(
39+
node,
40+
image: str | Literal["*"],
41+
) -> list[float]:
42+
"""Get the effective coordinate scale metadata
43+
for one image array or the whole FOV.
44+
45+
Parameters
46+
----------
47+
image : str | Literal["*"]
48+
Name of one image array (e.g. "0") to query,
49+
or "*" for the whole FOV
50+
51+
Returns
52+
-------
53+
list[float]
54+
A list of floats representing the total scale
55+
for the image or FOV for each axis.
56+
"""
57+
transforms = node._get_all_transforms(image)
58+
59+
full_scale = np.ones(len(node.axes), dtype=float)
60+
for transform in transforms:
61+
if transform.type == "scale":
62+
full_scale *= np.array(transform.scale)
63+
64+
return [float(x) for x in full_scale]
65+
66+
67+
def get_effective_translation(
68+
node,
69+
image: str | Literal["*"],
70+
) -> TransformationMeta:
71+
"""Get the effective coordinate translation metadata
72+
for one image array or the whole FOV.
73+
74+
Parameters
75+
----------
76+
image : str | Literal["*"]
77+
Name of one image array (e.g. "0") to query,
78+
or "*" for the whole FOV
79+
80+
Returns
81+
-------
82+
list[float]
83+
A list of floats representing the total translation
84+
for the image or FOV for each axis.
85+
"""
86+
transforms = node._get_all_transforms(image)
87+
full_translation = np.zeros(len(node.axes), dtype=float)
88+
for transform in transforms:
89+
if transform.type == "translation":
90+
full_translation += np.array(transform.translation)
91+
92+
return [float(x) for x in full_translation]

0 commit comments

Comments
 (0)