From 249222abc3ad5ab506b6257bb777f54f0a86a6b9 Mon Sep 17 00:00:00 2001 From: William Moore Date: Mon, 17 Jan 2022 16:36:24 +0000 Subject: [PATCH 1/5] Always read channel_axis, even when sizeC==1 --- napari_ome_zarr/_reader.py | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/napari_ome_zarr/_reader.py b/napari_ome_zarr/_reader.py index 73e0602..e335c68 100644 --- a/napari_ome_zarr/_reader.py +++ b/napari_ome_zarr/_reader.py @@ -11,7 +11,6 @@ import numpy as np from vispy.color import Colormap -from ome_zarr.data import CHANNEL_DIMENSION from ome_zarr.io import parse_url from ome_zarr.reader import Label, Node, Reader from ome_zarr.types import LayerData, PathLike, ReaderFunction @@ -95,27 +94,25 @@ def f(*args: Any, **kwargs: Any) -> List[LayerData]: LOGGER.debug(f"skipping non-data {node}") else: LOGGER.debug(f"transforming {node}") - shape = data[0].shape layer_type: str = "image" + channel_axis = None + try: + ch_types = [axis["type"] for axis in node.metadata["axes"]] + if "channel" in ch_types: + channel_axis = ch_types.index("channel") + except: + LOGGER.error("Error reading axes: Please update ome-zarr") + if node.load(Label): layer_type = "labels" for x in METADATA_KEYS: if x in node.metadata: metadata[x] = node.metadata[x] - if "axes" in node.metadata and "c" in node.metadata["axes"]: - c_index = node.metadata["axes"].index("c") - data = [np.squeeze(level, axis=c_index) for level in node.data] + if channel_axis is not None: + data = [np.squeeze(level, axis=channel_axis) for level in node.data] else: - channel_axis = None - if "axes" in node.metadata: - # version 0.3 or greater. NB: is 'axes' optional? - if "c" in node.metadata["axes"]: - channel_axis = node.metadata["axes"].index("c") - elif shape[CHANNEL_DIMENSION] > 1: - # versions of ome-zarr-py before v0.3 support - channel_axis = CHANNEL_DIMENSION - + LOGGER.debug("napari-ome-zarr: node.metadata: %s" % node.metadata) # Handle the removal of vispy requirement from ome-zarr-py cms = node.metadata.get("colormap", []) for idx, cm in enumerate(cms): From dad9ea92fbb59223dddb99915e782a19b5de1028 Mon Sep 17 00:00:00 2001 From: William Moore Date: Wed, 19 Jan 2022 11:28:46 +0000 Subject: [PATCH 2/5] Apply scale info to metadata --- napari_ome_zarr/_reader.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/napari_ome_zarr/_reader.py b/napari_ome_zarr/_reader.py index e335c68..76d8c62 100644 --- a/napari_ome_zarr/_reader.py +++ b/napari_ome_zarr/_reader.py @@ -87,6 +87,8 @@ def transform(nodes: Iterator[Node]) -> Optional[ReaderFunction]: def f(*args: Any, **kwargs: Any) -> List[LayerData]: results: List[LayerData] = list() + image_scale_values = None + for node in nodes: data: List[Any] = node.data metadata: Dict[str, Any] = {} @@ -104,6 +106,36 @@ def f(*args: Any, **kwargs: Any) -> List[LayerData]: except: LOGGER.error("Error reading axes: Please update ome-zarr") + """ + e.g. transformation is {"axisIndices": [1, 2, 3], "scale": [0.2, 0.06, 0.06]} + Get a list of these for each level in data. Just use first? + """ + if "transformations" in node.metadata: + level_0_transforms = node.metadata["transformations"][0] + for transf in level_0_transforms: + if "scale" in transf and "axisIndices" in transf: + axis_indices = transf["axisIndices"] + scale = transf["scale"] + scale_by_axis = {} + for axis, scale_val in zip(axis_indices, scale): + scale_by_axis[axis] = scale_val + # for each dimension of the data (not including channels), we want + # scale value, or 1 if not found + scale_values = [] + for dim in range(len(data[0].shape)): + if dim != channel_axis: + scale_values.append(scale_by_axis.get(dim, -1)) + if len(scale_values) > 0: + # cache scale to apply to other layers with no scale + if image_scale_values is None: + image_scale_values = scale_values + metadata["scale"] = tuple(scale_values) + elif image_scale_values is not None: + # If layer has no scale info, apply existing image_scale_values + # e.g. labels layer should be scaled to match the image + metadata["scale"] = tuple(image_scale_values) + + if node.load(Label): layer_type = "labels" for x in METADATA_KEYS: From d393b58beb9f6f96d3632f0a983c0dadce5a442c Mon Sep 17 00:00:00 2001 From: William Moore Date: Wed, 19 Jan 2022 11:41:46 +0000 Subject: [PATCH 3/5] Move scale handling to transform_scale() --- napari_ome_zarr/_reader.py | 58 ++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/napari_ome_zarr/_reader.py b/napari_ome_zarr/_reader.py index 76d8c62..71e535f 100644 --- a/napari_ome_zarr/_reader.py +++ b/napari_ome_zarr/_reader.py @@ -83,12 +83,34 @@ def transform_properties(props=None): return properties +def transform_scale(node_metadata, metadata, channel_axis, shape): + """ + e.g. transformation is {"axisIndices": [1, 2, 3], "scale": [0.2, 0.06, 0.06]} + Get a list of these for each level in data. Just use first? + """ + if "transformations" in node_metadata: + level_0_transforms = node_metadata["transformations"][0] + for transf in level_0_transforms: + if "scale" in transf and "axisIndices" in transf: + axis_indices = transf["axisIndices"] + scale = transf["scale"] + scale_by_axis = {} + for axis, scale_val in zip(axis_indices, scale): + scale_by_axis[axis] = scale_val + # for each dimension of the data (not including channels), we want + # scale value, or 1 if not found + scale_values = [] + for dim in range(len(shape)): + if dim != channel_axis: + scale_values.append(scale_by_axis.get(dim, 1)) + if len(scale_values) > 0: + metadata["scale"] = tuple(scale_values) + + def transform(nodes: Iterator[Node]) -> Optional[ReaderFunction]: def f(*args: Any, **kwargs: Any) -> List[LayerData]: results: List[LayerData] = list() - image_scale_values = None - for node in nodes: data: List[Any] = node.data metadata: Dict[str, Any] = {} @@ -106,35 +128,11 @@ def f(*args: Any, **kwargs: Any) -> List[LayerData]: except: LOGGER.error("Error reading axes: Please update ome-zarr") - """ - e.g. transformation is {"axisIndices": [1, 2, 3], "scale": [0.2, 0.06, 0.06]} - Get a list of these for each level in data. Just use first? - """ - if "transformations" in node.metadata: - level_0_transforms = node.metadata["transformations"][0] - for transf in level_0_transforms: - if "scale" in transf and "axisIndices" in transf: - axis_indices = transf["axisIndices"] - scale = transf["scale"] - scale_by_axis = {} - for axis, scale_val in zip(axis_indices, scale): - scale_by_axis[axis] = scale_val - # for each dimension of the data (not including channels), we want - # scale value, or 1 if not found - scale_values = [] - for dim in range(len(data[0].shape)): - if dim != channel_axis: - scale_values.append(scale_by_axis.get(dim, -1)) - if len(scale_values) > 0: - # cache scale to apply to other layers with no scale - if image_scale_values is None: - image_scale_values = scale_values - metadata["scale"] = tuple(scale_values) - elif image_scale_values is not None: - # If layer has no scale info, apply existing image_scale_values + transform_scale(node.metadata, metadata, channel_axis, data[0].shape) + # If layer has no scale info, try apply scale from first layer + if "scale" not in metadata and len(results) and "scale" in results[0][1]: # e.g. labels layer should be scaled to match the image - metadata["scale"] = tuple(image_scale_values) - + metadata["scale"] = results[0][1]["scale"] if node.load(Label): layer_type = "labels" From dc4f0bd83d03df870b568977589883037fa95cb1 Mon Sep 17 00:00:00 2001 From: William Moore Date: Wed, 19 Jan 2022 16:30:26 +0000 Subject: [PATCH 4/5] require ome-zarr==0.3a1 --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 80a1471..32378d6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -34,7 +34,7 @@ setup_requires = setuptools_scm # add your package requirements here install_requires = napari-plugin-engine>=0.1.4 - ome-zarr>=0.2.0 + ome-zarr==0.3a1 numpy From b3abf9218e507c560a7410de669b1e008c6c0d7d Mon Sep 17 00:00:00 2001 From: William Moore Date: Tue, 25 Jan 2022 23:19:57 +0000 Subject: [PATCH 5/5] fixes for PR #31 --- napari_ome_zarr/_reader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/napari_ome_zarr/_reader.py b/napari_ome_zarr/_reader.py index f5830a5..14f9191 100644 --- a/napari_ome_zarr/_reader.py +++ b/napari_ome_zarr/_reader.py @@ -127,6 +127,7 @@ def f(*args: Any, **kwargs: Any) -> List[LayerData]: channel_axis = ch_types.index("channel") except: LOGGER.error("Error reading axes: Please update ome-zarr") + raise transform_scale(node.metadata, metadata, channel_axis, data[0].shape) # If layer has no scale info, try apply scale from first layer @@ -142,7 +143,7 @@ def f(*args: Any, **kwargs: Any) -> List[LayerData]: if channel_axis is not None: data = [np.squeeze(level, axis=channel_axis) for level in node.data] else: - LOGGER.debug("napari-ome-zarr: node.metadata: %s" % node.metadata) + LOGGER.debug("node.metadata: %s" % node.metadata) # Handle the removal of vispy requirement from ome-zarr-py cms = node.metadata.get("colormap", []) for idx, cm in enumerate(cms):