Skip to content

Commit dd97acb

Browse files
authored
Allow HCS objects without existing well groups (#214)
* Allow HCS objects without existing well groups * Fix row/col indexing * Fix well group gettingb * Add a breaking changelog entry
1 parent 982900c commit dd97acb

File tree

4 files changed

+69
-7
lines changed

4 files changed

+69
-7
lines changed

docs/changelog.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Changelog
22

3+
## 0.1.10
4+
5+
### Bug fixes
6+
7+
- Creating a `HCS` group with well paths that do not point to existing well Zarr groups
8+
no longer errors.
9+
10+
### Breaking changes
11+
12+
- `HCS.well_groups` will now only return well groups that exist, instead of erroring out if a well group is defined in the HCS metadata but does not exist as a Zarr group.
13+
314
## 0.1.9
415

516
### Bug fixes

src/ome_zarr_models/common/well.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,9 @@ class WellAttrs(BaseAttrs):
88
"""
99

1010
well: WellMeta
11+
12+
13+
class WellGroupNotFoundError(RuntimeError):
14+
"""
15+
Raised if a well Zarr group is not found.
16+
"""

src/ome_zarr_models/v04/hcs.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pydantic import model_validator
55

66
from ome_zarr_models.base import BaseAttrs
7+
from ome_zarr_models.common.well import WellGroupNotFoundError
78
from ome_zarr_models.v04.base import BaseGroupv04
89
from ome_zarr_models.v04.plate import Plate
910
from ome_zarr_models.v04.well import Well
@@ -60,9 +61,18 @@ def n_wells(self) -> int:
6061
def well_groups(self) -> Generator[Well, None, None]:
6162
"""
6263
Well groups within this HCS group.
64+
65+
Notes
66+
-----
67+
Only well groups that exist are returned. This can be less than the number
68+
of wells defined in the HCS metadata if some of the well Zarr groups don't
69+
exist.
6370
"""
6471
for i in range(self.n_wells):
65-
yield self.get_well_group(i)
72+
try:
73+
yield self.get_well_group(i)
74+
except WellGroupNotFoundError:
75+
continue
6676

6777
def get_well_group(self, i: int) -> Well:
6878
"""
@@ -72,12 +82,25 @@ def get_well_group(self, i: int) -> Well:
7282
----------
7383
i :
7484
Index of well group.
85+
86+
Raises
87+
------
88+
WellGroupNotFoundError :
89+
If no Zarr group is found at the well path.
7590
"""
7691
well = self.attributes.plate.wells[i]
7792
well_path = well.path
7893
well_path_parts = well_path.split("/")
79-
group = self
80-
for part in well_path_parts:
81-
group = group.members[part]
82-
94+
if len(well_path_parts) != 2:
95+
raise RuntimeError(f"Well path '{well_path_parts}' does not have two parts")
96+
row, col = well_path_parts
97+
if row not in self.members:
98+
raise WellGroupNotFoundError(
99+
f"Row '{row}' not found in group members: {self.members}"
100+
)
101+
if col not in self.members[row].members:
102+
raise WellGroupNotFoundError(
103+
f"Column '{col}' not found in row group members: {self.members[row]}"
104+
)
105+
group = self.members[row].members[col]
83106
return Well(attributes=group.attributes, members=group.members)

tests/v04/test_hcs.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
def test_example_hcs() -> None:
1616
group = zarr.open(Path(__file__).parent / "data" / "hcs_example.ome.zarr", mode="r")
17-
hcs = HCS.from_zarr(group)
17+
hcs: HCS = HCS.from_zarr(group)
1818
assert hcs.attributes == HCSAttrs(
1919
plate=Plate(
2020
acquisitions=[
@@ -38,7 +38,7 @@ def test_example_hcs() -> None:
3838

3939
well_groups = list(hcs.well_groups)
4040
assert len(well_groups) == 1
41-
well_group = well_groups[0]
41+
well_group = hcs.get_well_group(0)
4242
assert well_group.attributes.well == WellMeta(
4343
images=[WellImage(path="0", acquisition=None)], version="0.4"
4444
)
@@ -108,3 +108,25 @@ def test_example_hcs() -> None:
108108
version="0.4",
109109
),
110110
)
111+
112+
113+
def test_non_existent_wells() -> None:
114+
"""
115+
Make sure it's possible to create a HCS that has well paths that don't exist
116+
as Zarr groups.
117+
118+
The relevant part of the OME-Zarr specification (https://ngff.openmicroscopy.org/0.4/index.html#plate-md)
119+
does not specify explicitly that the Zarr groups have to exist.
120+
"""
121+
HCS(
122+
attributes={
123+
"plate": {
124+
"acquisitions": [{"id": 1}, {"id": 2}, {"id": 3}],
125+
"columns": [{"name": "1"}],
126+
"field_count": 10,
127+
"rows": [{"name": "A"}],
128+
"version": "0.4",
129+
"wells": [{"columnIndex": 0, "path": "A/1", "rowIndex": 0}],
130+
}
131+
}
132+
)

0 commit comments

Comments
 (0)