44"""
55
66
7- import logging
87import warnings
9- from importlib .metadata import version
10- from typing import Any , Dict , Iterator , List , Optional
118
12- import numpy as np
139from .ome_zarr_reader import read_ome_zarr
14- # from ome_zarr.io import parse_url
15- from ome_zarr .reader import Label , Node , Reader
16- from ome_zarr .types import LayerData , PathLike , ReaderFunction
17- from vispy .color import Colormap
1810
19- LOGGER = logging .getLogger ("napari_ome_zarr.reader" )
20-
21- METADATA_KEYS = ("name" , "visible" , "contrast_limits" , "colormap" , "metadata" )
22-
23- # major and minor versions as int
24- napari_version = tuple (map (int , list (version ("napari" ).split ("." )[:2 ])))
25-
26-
27- def napari_get_reader (path : PathLike ) -> Optional [ReaderFunction ]:
11+ def napari_get_reader (path ):
2812 """Returns a reader for supported paths that include IDR ID.
2913
3014 - URL of the form: https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.1/ID.zarr/
@@ -34,153 +18,3 @@ def napari_get_reader(path: PathLike) -> Optional[ReaderFunction]:
3418 warnings .warn ("more than one path is not currently supported" )
3519 path = path [0 ]
3620 return read_ome_zarr (path )
37- # zarr = parse_url(path)
38- # if zarr:
39- # reader = Reader(zarr)
40- # return transform(reader())
41- # # Ignoring this path
42- # return None
43-
44-
45- def transform_properties (
46- props : Optional [Dict [str , Dict ]] = None
47- ) -> Optional [Dict [str , List ]]:
48- """
49- Transform properties
50-
51- Transform a dict of {label_id : {key: value, key2: value2}}
52- with a key for every LABEL
53- into a dict of a key for every VALUE, with a list of values for each
54- .. code::
55-
56- {
57- "index": [1381342, 1381343...]
58- "omero:roiId": [1381342, 1381343...],
59- "omero:shapeId": [1682567, 1682567...]
60- }
61-
62- """
63- if props is None :
64- return None
65-
66- properties : Dict [str , List ] = {}
67-
68- # First, create lists for all existing keys...
69- for label_id , props_dict in props .items ():
70- for key in props_dict .keys ():
71- properties [key ] = []
72-
73- keys = list (properties .keys ())
74-
75- properties ["index" ] = []
76- for label_id , props_dict in props .items ():
77- properties ["index" ].append (label_id )
78- # ...in case some objects don't have all the keys
79- for key in keys :
80- properties [key ].append (props_dict .get (key , None ))
81- return properties
82-
83-
84- def transform_scale (
85- node_metadata : Dict , metadata : Dict , channel_axis : Optional [int ]
86- ) -> None :
87- """
88- e.g. transformation is {"scale": [0.2, 0.06, 0.06]}
89- Get a list of these for each level in data. Just use first?
90- """
91- if "coordinateTransformations" in node_metadata :
92- level_0_transforms = node_metadata ["coordinateTransformations" ][0 ]
93- for transf in level_0_transforms :
94- if "scale" in transf :
95- scale = transf ["scale" ]
96- if channel_axis is not None :
97- scale .pop (channel_axis )
98- metadata ["scale" ] = tuple (scale )
99- if "translation" in transf :
100- translate = transf ["translation" ]
101- if channel_axis is not None :
102- translate .pop (channel_axis )
103- metadata ["translate" ] = tuple (translate )
104-
105-
106- def transform (nodes : Iterator [Node ]) -> Optional [ReaderFunction ]:
107- def f (* args : Any , ** kwargs : Any ) -> List [LayerData ]:
108- results : List [LayerData ] = list ()
109-
110- for node in nodes :
111- data : List [Any ] = node .data
112- metadata : Dict [str , Any ] = {}
113- if data is None or len (data ) < 1 :
114- LOGGER .debug ("skipping non-data %s" , node )
115- else :
116- LOGGER .debug ("transforming %s" , node )
117- LOGGER .debug ("node.metadata: %s" , node .metadata )
118-
119- layer_type : str = "image"
120- channel_axis = None
121- try :
122- ch_types = [axis ["type" ] for axis in node .metadata ["axes" ]]
123- if "channel" in ch_types :
124- channel_axis = ch_types .index ("channel" )
125- except Exception :
126- LOGGER .error ("Error reading axes: Please update ome-zarr" )
127- raise
128-
129- transform_scale (node .metadata , metadata , channel_axis )
130-
131- if node .load (Label ):
132- layer_type = "labels"
133- for x in METADATA_KEYS :
134- if x in node .metadata :
135- metadata [x ] = node .metadata [x ]
136- elif x == "colormap" and node .metadata ["color" ]:
137- # key changed 'color' -> 'colormap' in napari 0.5
138- if napari_version >= (0 , 5 ):
139- metadata ["colormap" ] = node .metadata ["color" ]
140- else :
141- metadata ["color" ] = node .metadata ["color" ]
142- if channel_axis is not None :
143- data = [
144- np .squeeze (level , axis = channel_axis ) for level in node .data
145- ]
146- else :
147- # Handle the removal of vispy requirement from ome-zarr-py
148- cms = node .metadata .get ("colormap" , [])
149- for idx , cm in enumerate (cms ):
150- if not isinstance (cm , Colormap ):
151- cms [idx ] = Colormap (cm )
152-
153- if channel_axis is not None :
154- # multi-channel; Copy known metadata values
155- metadata ["channel_axis" ] = channel_axis
156- for x in METADATA_KEYS :
157- if x in node .metadata :
158- metadata [x ] = node .metadata [x ]
159- # overwrite 'name' if we have 'channel_names'
160- if "channel_names" in node .metadata :
161- metadata ["name" ] = node .metadata ["channel_names" ]
162- else :
163- # single channel image, so metadata just needs
164- # single items (not lists)
165- for x in METADATA_KEYS :
166- if x in node .metadata :
167- try :
168- metadata [x ] = node .metadata [x ][0 ]
169- except Exception :
170- pass
171- # overwrite 'name' if we have 'channel_names'
172- if "channel_names" in node .metadata :
173- if len (node .metadata ["channel_names" ]) > 0 :
174- metadata ["name" ] = node .metadata ["channel_names" ][0 ]
175-
176- properties = transform_properties (node .metadata .get ("properties" ))
177- if properties is not None :
178- metadata ["properties" ] = properties
179-
180- rv : LayerData = (data , metadata , layer_type )
181- LOGGER .debug ("Transformed: %s" , rv )
182- results .append (rv )
183-
184- return results
185-
186- return f
0 commit comments