Skip to content

Commit ac51020

Browse files
committed
ENH: Add omero metadata read support
1 parent fd50719 commit ac51020

File tree

4 files changed

+113
-2
lines changed

4 files changed

+113
-2
lines changed

ngff_zarr/from_ngff_zarr.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@
1616

1717
from .ngff_image import NgffImage
1818
from .to_multiscales import Multiscales
19-
from .v04.zarr_metadata import Axis, Dataset, Scale, Translation
19+
from .v04.zarr_metadata import (
20+
Axis,
21+
Dataset,
22+
Scale,
23+
Translation,
24+
Omero,
25+
OmeroChannel,
26+
OmeroWindow,
27+
)
2028
from .validate import validate as validate_ngff
2129

2230
zarr_version = packaging.version.parse(zarr.__version__)
@@ -145,9 +153,29 @@ def from_ngff_zarr(
145153
Axis(name="y", type="space"),
146154
Axis(name="x", type="space"),
147155
]
156+
148157
coordinateTransformations = None
149158
if "coordinateTransformations" in metadata:
150159
coordinateTransformations = metadata["coordinateTransformations"]
160+
161+
omero = None
162+
if "omero" in root.attrs:
163+
omero_data = root.attrs["omero"]
164+
omero = Omero(
165+
channels=[
166+
OmeroChannel(
167+
color=channel["color"],
168+
window=OmeroWindow(
169+
min=channel["window"]["min"],
170+
max=channel["window"]["max"],
171+
start=channel["window"]["start"],
172+
end=channel["window"]["end"],
173+
),
174+
)
175+
for channel in omero_data["channels"]
176+
]
177+
)
178+
151179
if version == "0.5":
152180
from .v05.zarr_metadata import Metadata
153181

@@ -156,6 +184,7 @@ def from_ngff_zarr(
156184
datasets=datasets,
157185
name=name,
158186
coordinateTransformations=coordinateTransformations,
187+
omero=omero,
159188
)
160189
else:
161190
from .v04.zarr_metadata import Metadata
@@ -166,6 +195,7 @@ def from_ngff_zarr(
166195
name=name,
167196
version=metadata["version"],
168197
coordinateTransformations=coordinateTransformations,
198+
omero=omero,
169199
)
170200

171201
return Multiscales(images, metadata)

ngff_zarr/v04/zarr_metadata.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import List, Optional, Union
33

44
from typing_extensions import Literal
5+
import re
56

67
SupportedDims = Union[
78
Literal["c"], Literal["x"], Literal["y"], Literal["z"], Literal["t"]
@@ -165,10 +166,34 @@ class Dataset:
165166
coordinateTransformations: List[Transform]
166167

167168

169+
@dataclass
170+
class OmeroWindow:
171+
min: float
172+
max: float
173+
start: float
174+
end: float
175+
176+
177+
@dataclass
178+
class OmeroChannel:
179+
color: str
180+
window: OmeroWindow
181+
182+
def validate_color(self):
183+
if not re.fullmatch(r"[0-9A-Fa-f]{6}", self.color):
184+
raise ValueError(f"Invalid color '{self.color}'. Must be 6 hex digits.")
185+
186+
187+
@dataclass
188+
class Omero:
189+
channels: List[OmeroChannel]
190+
191+
168192
@dataclass
169193
class Metadata:
170194
axes: List[Axis]
171195
datasets: List[Dataset]
172196
coordinateTransformations: Optional[List[Transform]]
197+
omero: Optional[Omero] = None
173198
name: str = "image"
174199
version: str = "0.4"

ngff_zarr/v05/zarr_metadata.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
from typing import List, Optional
22
from dataclasses import dataclass
33

4-
from ..v04.zarr_metadata import Axis, Transform, Dataset
4+
from ..v04.zarr_metadata import Axis, Transform, Dataset, Omero
55

66

77
@dataclass
88
class Metadata:
99
axes: List[Axis]
1010
datasets: List[Dataset]
1111
coordinateTransformations: Optional[List[Transform]]
12+
omero: Optional[Omero] = None
1213
name: str = "image"

test/test_omero.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from ngff_zarr import from_ngff_zarr
2+
3+
from ._data import test_data_dir
4+
5+
6+
def test_read_omero(input_images): # noqa: ARG001
7+
dataset_name = "13457537"
8+
store_path = test_data_dir / "input" / f"{dataset_name}.zarr"
9+
multiscales = from_ngff_zarr(store_path, validate=True)
10+
11+
omero = multiscales.metadata.omero
12+
assert omero is not None
13+
assert len(omero.channels) == 6
14+
15+
# Channel 0
16+
assert omero.channels[0].color == "FFFFFF"
17+
assert omero.channels[0].window.min == 0.0
18+
assert omero.channels[0].window.max == 65535.0
19+
assert omero.channels[0].window.start == 0.0
20+
assert omero.channels[0].window.end == 1200.0
21+
22+
# Channel 1
23+
assert omero.channels[1].color == "FFFFFF"
24+
assert omero.channels[1].window.min == 0.0
25+
assert omero.channels[1].window.max == 65535.0
26+
assert omero.channels[1].window.start == 0.0
27+
assert omero.channels[1].window.end == 1200.0
28+
29+
# Channel 2
30+
assert omero.channels[2].color == "FFFFFF"
31+
assert omero.channels[2].window.min == 0.0
32+
assert omero.channels[2].window.max == 65535.0
33+
assert omero.channels[2].window.start == 0.0
34+
assert omero.channels[2].window.end == 1200.0
35+
36+
# Channel 3
37+
assert omero.channels[3].color == "FFFFFF"
38+
assert omero.channels[3].window.min == 0.0
39+
assert omero.channels[3].window.max == 65535.0
40+
assert omero.channels[3].window.start == 0.0
41+
assert omero.channels[3].window.end == 1200.0
42+
43+
# Channel 4
44+
assert omero.channels[4].color == "0000FF"
45+
assert omero.channels[4].window.min == 0.0
46+
assert omero.channels[4].window.max == 65535.0
47+
assert omero.channels[4].window.start == 0.0
48+
assert omero.channels[4].window.end == 5000.0
49+
50+
# Channel 5
51+
assert omero.channels[5].color == "FF0000"
52+
assert omero.channels[5].window.min == 0.0
53+
assert omero.channels[5].window.max == 65535.0
54+
assert omero.channels[5].window.start == 0.0
55+
assert omero.channels[5].window.end == 100.0

0 commit comments

Comments
 (0)