Skip to content

Commit

Permalink
Merge pull request #300 from aeisenbarth/field-of-view-paths
Browse files Browse the repository at this point in the history
Avoid hard-coded field-of-view path "0"
  • Loading branch information
will-moore authored Sep 29, 2023
2 parents 652cd8b + 1b4601d commit ea18dd4
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 12 deletions.
11 changes: 6 additions & 5 deletions ome_zarr/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,8 @@ def get_field(tile_name: str, level: int) -> np.ndarray:
"""tile_name is 'row,col'"""
row, col = (int(n) for n in tile_name.split(","))
field_index = (column_count * row) + col
path = f"{field_index}/{level}"
image_path = image_paths[field_index]
path = f"{image_path}/{level}"
LOGGER.debug("LOADING tile... %s", path)
try:
data = self.zarr.load(path)
Expand Down Expand Up @@ -486,7 +487,6 @@ def get_pyramid_lazy(self, node: Node) -> None:
LOGGER.info("plate_data: %s", self.plate_data)
self.rows = self.plate_data.get("rows")
self.columns = self.plate_data.get("columns")
self.first_field = "0"
self.row_names = [row["name"] for row in self.rows]
self.col_names = [col["name"] for col in self.columns]

Expand All @@ -502,6 +502,7 @@ def get_pyramid_lazy(self, node: Node) -> None:
well_spec: Optional[Well] = well_node.first(Well)
if well_spec is None:
raise Exception("Could not find first well")
self.first_field_path = well_spec.well_data["images"][0]["path"]
self.numpy_type = well_spec.numpy_type

LOGGER.debug("img_pyramid_shapes: %s", well_spec.img_pyramid_shapes)
Expand All @@ -528,7 +529,7 @@ def get_numpy_type(self, image_node: Node) -> np.dtype:
def get_tile_path(self, level: int, row: int, col: int) -> str:
return (
f"{self.row_names[row]}/"
f"{self.col_names[col]}/{self.first_field}/{level}"
f"{self.col_names[col]}/{self.first_field_path}/{level}"
)

def get_stitched_grid(self, level: int, tile_shape: tuple) -> da.core.Array:
Expand Down Expand Up @@ -568,7 +569,7 @@ def get_tile_path(self, level: int, row: int, col: int) -> str: # pragma: no co
"""251.zarr/A/1/0/labels/0/3/"""
path = (
f"{self.row_names[row]}/{self.col_names[col]}/"
f"{self.first_field}/labels/0/{level}"
f"{self.first_field_path}/labels/0/{level}"
)
return path

Expand All @@ -590,7 +591,7 @@ def get_pyramid_lazy(self, node: Node) -> None: # pragma: no cover
properties: Dict[int, Dict[str, Any]] = {}
for row in self.row_names:
for col in self.col_names:
path = f"{row}/{col}/{self.first_field}/labels/0/.zattrs"
path = f"{row}/{col}/{self.first_field_path}/labels/0/.zattrs"
labels_json = self.zarr.get_json(path).get("image-label", {})
# NB: assume that 'label_val' is unique across all images
props_list = labels_json.get("properties", [])
Expand Down
25 changes: 18 additions & 7 deletions tests/test_reader.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import numpy as np
import pytest
import zarr
from numpy import zeros
from numpy import ones, zeros

from ome_zarr.data import create_zarr
from ome_zarr.io import parse_url
Expand Down Expand Up @@ -75,7 +76,8 @@ def test_minimal_plate(self):
# assert len(nodes[1].specs) == 1
# assert isinstance(nodes[1].specs[0], PlateLabels)

def test_multiwells_plate(self):
@pytest.mark.parametrize("field_paths", [["0", "1", "2"], ["img1", "img2", "img3"]])
def test_multiwells_plate(self, field_paths):
row_names = ["A", "B", "C"]
col_names = ["1", "2", "3", "4"]
well_paths = ["A/1", "A/2", "A/4", "B/2", "B/3", "C/1", "C/3", "C/4"]
Expand All @@ -84,16 +86,25 @@ def test_multiwells_plate(self):
row, col = wp.split("/")
row_group = self.root.require_group(row)
well = row_group.require_group(col)
write_well_metadata(well, ["0", "1", "2"])
for field in range(3):
write_well_metadata(well, field_paths)
for field in field_paths:
image = well.require_group(str(field))
write_image(zeros((1, 1, 1, 256, 256)), image)
write_image(ones((1, 1, 1, 256, 256)), image)

reader = Reader(parse_url(str(self.path)))
nodes = list(reader())
# currently reading plate labels disabled. Only 1 node
assert len(nodes) == 1
assert len(nodes[0].specs) == 1
assert isinstance(nodes[0].specs[0], Plate)
plate_node = nodes[0]
assert len(plate_node.specs) == 1
assert isinstance(plate_node.specs[0], Plate)
# Get the plate node's array. It should be fused from the first field of all
# well arrays (which in this test are non-zero), with zero values for wells
# that failed to load (not expected) or the surplus area not filled by a well.
expected_num_pixels = (
len(well_paths) * len(field_paths[:1]) * np.prod((1, 1, 1, 256, 256))
)
pyramid_0 = plate_node.data[0]
assert np.asarray(pyramid_0).sum() == expected_num_pixels
# assert len(nodes[1].specs) == 1
# assert isinstance(nodes[1].specs[0], PlateLabels)

0 comments on commit ea18dd4

Please sign in to comment.