ngio 0.4.8__py3-none-any.whl → 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. ngio/__init__.py +5 -2
  2. ngio/common/__init__.py +11 -6
  3. ngio/common/_masking_roi.py +34 -54
  4. ngio/common/_pyramid.py +322 -75
  5. ngio/common/_roi.py +258 -330
  6. ngio/experimental/iterators/_feature.py +3 -3
  7. ngio/experimental/iterators/_rois_utils.py +10 -11
  8. ngio/hcs/_plate.py +192 -136
  9. ngio/images/_abstract_image.py +539 -35
  10. ngio/images/_create_synt_container.py +45 -47
  11. ngio/images/_create_utils.py +406 -0
  12. ngio/images/_image.py +524 -248
  13. ngio/images/_label.py +257 -180
  14. ngio/images/_masked_image.py +2 -2
  15. ngio/images/_ome_zarr_container.py +658 -255
  16. ngio/io_pipes/_io_pipes.py +9 -9
  17. ngio/io_pipes/_io_pipes_masked.py +7 -7
  18. ngio/io_pipes/_io_pipes_roi.py +6 -6
  19. ngio/io_pipes/_io_pipes_types.py +3 -3
  20. ngio/io_pipes/_match_shape.py +6 -8
  21. ngio/io_pipes/_ops_slices_utils.py +8 -5
  22. ngio/ome_zarr_meta/__init__.py +29 -18
  23. ngio/ome_zarr_meta/_meta_handlers.py +402 -689
  24. ngio/ome_zarr_meta/ngio_specs/__init__.py +4 -0
  25. ngio/ome_zarr_meta/ngio_specs/_axes.py +152 -51
  26. ngio/ome_zarr_meta/ngio_specs/_dataset.py +13 -22
  27. ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +129 -91
  28. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +69 -69
  29. ngio/ome_zarr_meta/v04/__init__.py +5 -1
  30. ngio/ome_zarr_meta/v04/{_v04_spec_utils.py → _v04_spec.py} +55 -86
  31. ngio/ome_zarr_meta/v05/__init__.py +27 -0
  32. ngio/ome_zarr_meta/v05/_custom_models.py +18 -0
  33. ngio/ome_zarr_meta/v05/_v05_spec.py +495 -0
  34. ngio/resources/__init__.py +1 -1
  35. ngio/resources/resource_model.py +1 -1
  36. ngio/tables/_tables_container.py +82 -24
  37. ngio/tables/backends/_abstract_backend.py +7 -0
  38. ngio/tables/backends/_anndata.py +60 -7
  39. ngio/tables/backends/_anndata_utils.py +2 -4
  40. ngio/tables/backends/_csv.py +3 -19
  41. ngio/tables/backends/_json.py +10 -13
  42. ngio/tables/backends/_parquet.py +3 -31
  43. ngio/tables/backends/_py_arrow_backends.py +222 -0
  44. ngio/tables/backends/_utils.py +1 -1
  45. ngio/tables/v1/_roi_table.py +41 -24
  46. ngio/utils/__init__.py +8 -12
  47. ngio/utils/_cache.py +48 -0
  48. ngio/utils/_zarr_utils.py +354 -236
  49. {ngio-0.4.8.dist-info → ngio-0.5.0.dist-info}/METADATA +12 -5
  50. ngio-0.5.0.dist-info/RECORD +88 -0
  51. ngio/images/_create.py +0 -276
  52. ngio/tables/backends/_non_zarr_backends.py +0 -196
  53. ngio/utils/_logger.py +0 -50
  54. ngio-0.4.8.dist-info/RECORD +0 -85
  55. {ngio-0.4.8.dist-info → ngio-0.5.0.dist-info}/WHEEL +0 -0
  56. {ngio-0.4.8.dist-info → ngio-0.5.0.dist-info}/licenses/LICENSE +0 -0
ngio/images/_label.py CHANGED
@@ -1,26 +1,26 @@
1
1
  """A module for handling label images in OME-NGFF files."""
2
2
 
3
- from collections.abc import Sequence
4
- from typing import Literal
3
+ from collections.abc import Mapping, Sequence
4
+ from typing import Any, Literal
5
5
 
6
- from zarr.types import DIMENSION_SEPARATOR
6
+ from zarr.core.array import CompressorLike
7
7
 
8
8
  from ngio.common import compute_masking_roi
9
- from ngio.images._abstract_image import AbstractImage
10
- from ngio.images._create import create_empty_label_container
9
+ from ngio.common._pyramid import ChunksLike, ShardsLike
10
+ from ngio.images._abstract_image import AbstractImage, abstract_derive
11
11
  from ngio.images._image import Image
12
12
  from ngio.ome_zarr_meta import (
13
13
  LabelMetaHandler,
14
+ LabelsGroupMetaHandler,
14
15
  NgioLabelMeta,
16
+ NgioLabelsGroupMeta,
15
17
  PixelSize,
16
- find_label_meta_handler,
18
+ update_ngio_labels_group_meta,
17
19
  )
18
20
  from ngio.ome_zarr_meta.ngio_specs import (
19
- DefaultSpaceUnit,
20
- DefaultTimeUnit,
21
- SpaceUnits,
22
- TimeUnits,
21
+ NgffVersions,
23
22
  )
23
+ from ngio.ome_zarr_meta.ngio_specs._axes import AxesSetup
24
24
  from ngio.tables import MaskingRoiTable
25
25
  from ngio.utils import (
26
26
  NgioValidationError,
@@ -30,7 +30,7 @@ from ngio.utils import (
30
30
  )
31
31
 
32
32
 
33
- class Label(AbstractImage[LabelMetaHandler]):
33
+ class Label(AbstractImage):
34
34
  """Placeholder class for a label."""
35
35
 
36
36
  get_as_numpy = AbstractImage._get_as_numpy
@@ -46,7 +46,7 @@ class Label(AbstractImage[LabelMetaHandler]):
46
46
  self,
47
47
  group_handler: ZarrGroupHandler,
48
48
  path: str,
49
- meta_handler: LabelMetaHandler | None,
49
+ meta_handler: LabelMetaHandler,
50
50
  ) -> None:
51
51
  """Initialize the Image at a single level.
52
52
 
@@ -56,8 +56,6 @@ class Label(AbstractImage[LabelMetaHandler]):
56
56
  meta_handler: The image metadata handler.
57
57
 
58
58
  """
59
- if meta_handler is None:
60
- meta_handler = find_label_meta_handler(group_handler)
61
59
  super().__init__(
62
60
  group_handler=group_handler, path=path, meta_handler=meta_handler
63
61
  )
@@ -66,29 +64,24 @@ class Label(AbstractImage[LabelMetaHandler]):
66
64
  """Return the string representation of the label."""
67
65
  return f"Label(path={self.path}, {self.dimensions})"
68
66
 
67
+ @property
68
+ def meta_handler(self) -> LabelMetaHandler:
69
+ """Return the metadata handler."""
70
+ assert isinstance(self._meta_handler, LabelMetaHandler)
71
+ return self._meta_handler
72
+
69
73
  @property
70
74
  def meta(self) -> NgioLabelMeta:
71
75
  """Return the metadata."""
72
- return self._meta_handler.meta
73
-
74
- def set_axes_unit(
75
- self,
76
- space_unit: SpaceUnits = DefaultSpaceUnit,
77
- time_unit: TimeUnits = DefaultTimeUnit,
78
- ) -> None:
79
- """Set the axes unit of the image.
80
-
81
- Args:
82
- space_unit (SpaceUnits): The space unit of the image.
83
- time_unit (TimeUnits): The time unit of the image.
84
- """
85
- meta = self.meta
86
- meta = meta.to_units(space_unit=space_unit, time_unit=time_unit)
87
- self._meta_handler.write_meta(meta)
76
+ meta = self.meta_handler.get_meta()
77
+ assert isinstance(meta, NgioLabelMeta)
78
+ return meta
88
79
 
89
- def build_masking_roi_table(self) -> MaskingRoiTable:
80
+ def build_masking_roi_table(
81
+ self, axes_order: Sequence[str] | None = None
82
+ ) -> MaskingRoiTable:
90
83
  """Compute the masking ROI table."""
91
- return build_masking_roi_table(self)
84
+ return build_masking_roi_table(self, axes_order=axes_order)
92
85
 
93
86
  def consolidate(
94
87
  self,
@@ -104,30 +97,46 @@ class Label(AbstractImage[LabelMetaHandler]):
104
97
  class LabelsContainer:
105
98
  """A class to handle the /labels group in an OME-NGFF file."""
106
99
 
107
- def __init__(self, group_handler: ZarrGroupHandler) -> None:
100
+ def __init__(
101
+ self,
102
+ group_handler: ZarrGroupHandler,
103
+ axes_setup: AxesSetup | None = None,
104
+ ngff_version: NgffVersions | None = None,
105
+ ) -> None:
108
106
  """Initialize the LabelGroupHandler."""
109
107
  self._group_handler = group_handler
110
-
111
- # Validate the group
112
- # Either contains a labels attribute or is empty
113
- attrs = self._group_handler.load_attrs()
114
- if len(attrs) == 0:
115
- # It's an empty group
116
- pass
117
- elif "labels" in attrs and isinstance(attrs["labels"], list):
118
- # It's a valid group
119
- pass
120
- else:
121
- raise NgioValidationError(
122
- f"Invalid /labels group. "
123
- f"Expected a single labels attribute with a list of label names. "
124
- f"Found: {attrs}"
108
+ self._axes_setup = axes_setup or AxesSetup()
109
+ # If the group is empty, initialize the metadata
110
+ try:
111
+ self._meta_handler = LabelsGroupMetaHandler(group_handler)
112
+ except NgioValidationError:
113
+ if ngff_version is None:
114
+ raise NgioValueError(
115
+ "The /labels group is missing metadata. "
116
+ "Please provide the ngff_version to initialize it."
117
+ ) from None
118
+ meta = NgioLabelsGroupMeta(labels=[], version=ngff_version)
119
+ update_ngio_labels_group_meta(
120
+ group_handler=group_handler,
121
+ ngio_meta=meta,
125
122
  )
123
+ self._group_handler = self._group_handler.reopen_handler()
124
+ self._meta_handler = LabelsGroupMetaHandler(group_handler)
125
+
126
+ @property
127
+ def meta(self) -> NgioLabelsGroupMeta:
128
+ """Return the metadata."""
129
+ meta = self._meta_handler.get_meta()
130
+ return meta
131
+
132
+ @property
133
+ def axes_setup(self) -> AxesSetup:
134
+ """Return the axes setup."""
135
+ return self._axes_setup
126
136
 
127
137
  def list(self) -> list[str]:
128
- """Create the /labels group if it doesn't exist."""
129
- attrs = self._group_handler.load_attrs()
130
- return attrs.get("labels", [])
138
+ """Return the list of label names in the group."""
139
+ return self.meta.labels
131
140
 
132
141
  def get(
133
142
  self,
@@ -153,49 +162,107 @@ class LabelsContainer:
153
162
  f"Available labels: {self.list()}"
154
163
  )
155
164
 
156
- group_handler = self._group_handler.derive_handler(name)
157
- label_meta_handler = find_label_meta_handler(group_handler)
158
- path = label_meta_handler.meta.get_dataset(
159
- path=path, pixel_size=pixel_size, strict=strict
160
- ).path
161
- return Label(group_handler, path, label_meta_handler)
165
+ group_handler = self._group_handler.get_handler(name)
166
+ label_meta_handler = LabelMetaHandler(group_handler, axes_setup=self.axes_setup)
167
+ path = (
168
+ label_meta_handler.get_meta()
169
+ .get_dataset(path=path, pixel_size=pixel_size, strict=strict)
170
+ .path
171
+ )
172
+ return Label(
173
+ group_handler=group_handler,
174
+ path=path,
175
+ meta_handler=label_meta_handler,
176
+ )
177
+
178
+ def delete(self, name: str, missing_ok: bool = False) -> None:
179
+ """Delete a label from the group.
180
+
181
+ Args:
182
+ name (str): The name of the label to delete.
183
+ missing_ok (bool): If True, do not raise an error if the label does not
184
+ exist.
185
+
186
+ """
187
+ existing_labels = self.list()
188
+ if name not in existing_labels:
189
+ if missing_ok:
190
+ return
191
+ raise NgioValueError(
192
+ f"Label '{name}' not found in the Labels group. "
193
+ f"Available labels: {existing_labels}"
194
+ )
195
+
196
+ self._group_handler.delete_group(name)
197
+ existing_labels.remove(name)
198
+ update_meta = NgioLabelsGroupMeta(
199
+ labels=existing_labels, version=self.meta.version
200
+ )
201
+ self._meta_handler.update_meta(update_meta)
162
202
 
163
203
  def derive(
164
204
  self,
165
205
  name: str,
166
206
  ref_image: Image | Label,
207
+ # Metadata parameters
167
208
  shape: Sequence[int] | None = None,
168
- pixel_size: PixelSize | None = None,
169
- axes_names: Sequence[str] | None = None,
170
- chunks: Sequence[int] | None = None,
171
- dtype: str = "uint32",
172
- dimension_separator: DIMENSION_SEPARATOR | None = None,
173
- compressor=None,
209
+ pixelsize: float | tuple[float, float] | None = None,
210
+ z_spacing: float | None = None,
211
+ time_spacing: float | None = None,
212
+ translation: Sequence[float] | None = None,
213
+ channels_policy: Literal["same", "squeeze", "singleton"] | int = "squeeze",
214
+ ngff_version: NgffVersions | None = None,
215
+ # Zarr Array parameters
216
+ chunks: ChunksLike | None = None,
217
+ shards: ShardsLike | None = None,
218
+ dtype: str | None = None,
219
+ dimension_separator: Literal[".", "/"] | None = None,
220
+ compressors: CompressorLike | None = None,
221
+ extra_array_kwargs: Mapping[str, Any] | None = None,
174
222
  overwrite: bool = False,
223
+ # Deprecated arguments
224
+ labels: Sequence[str] | None = None,
225
+ pixel_size: PixelSize | None = None,
175
226
  ) -> "Label":
176
- """Create an empty OME-Zarr label from a reference image.
227
+ """Create an empty OME-Zarr label from an existing image or label.
177
228
 
178
- And add the label to the /labels group.
229
+ If a kwarg is not provided, the value from the reference image will be used.
179
230
 
180
231
  Args:
181
- store (StoreOrGroup): The Zarr store or group to create the image in.
182
- ref_image (Image | Label): A reference image that will be used to create
183
- the new image.
184
- name (str): The name of the new image.
185
- shape (Sequence[int] | None): The shape of the new image.
186
- pixel_size (PixelSize | None): The pixel size of the new image.
187
- axes_names (Sequence[str] | None): The axes names of the new image.
188
- For labels, the channel axis is not allowed.
189
- chunks (Sequence[int] | None): The chunk shape of the new image.
190
- dtype (str): The data type of the new label.
191
- dimension_separator (DIMENSION_SEPARATOR | None): The separator to use for
192
- dimensions. If None it will use the same as the reference image.
193
- compressor: The compressor to use. If None it will use
194
- the same as the reference image.
195
- overwrite (bool): Whether to overwrite an existing image.
232
+ name (str): The name of the new label.
233
+ ref_image (Image | Label): The reference image to derive the new label from.
234
+ shape (Sequence[int] | None): The shape of the new label.
235
+ pixelsize (float | tuple[float, float] | None): The pixel size of the new
236
+ label.
237
+ z_spacing (float | None): The z spacing of the new label.
238
+ time_spacing (float | None): The time spacing of the new label.
239
+ translation (Sequence[float] | None): The translation for each axis
240
+ at the highest resolution level. Defaults to None.
241
+ channels_policy (Literal["squeeze", "same", "singleton"] | int):
242
+ Possible policies:
243
+ - If "squeeze", the channels axis will be removed (no matter its size).
244
+ - If "same", the channels axis will be kept as is (if it exists).
245
+ - If "singleton", the channels axis will be set to size 1.
246
+ - If an integer is provided, the channels axis will be changed to have
247
+ that size.
248
+ ngff_version (NgffVersions | None): The NGFF version to use.
249
+ chunks (ChunksLike | None): The chunk shape of the new label.
250
+ shards (ShardsLike | None): The shard shape of the new label.
251
+ dtype (str | None): The data type of the new label.
252
+ dimension_separator (Literal[".", "/"] | None): The separator to use for
253
+ dimensions.
254
+ compressors (CompressorLike | None): The compressors to use.
255
+ extra_array_kwargs (Mapping[str, Any] | None): Extra arguments to pass to
256
+ the zarr array creation.
257
+ overwrite (bool): Whether to overwrite an existing label.
258
+ labels (Sequence[str] | None): Deprecated. This argument is deprecated,
259
+ please use channels_meta instead.
260
+ pixel_size (PixelSize | None): Deprecated. The pixel size of the new label.
261
+ This argument is deprecated, please use pixelsize, z_spacing,
262
+ and time_spacing instead.
196
263
 
197
264
  Returns:
198
- Label: The new label.
265
+ Label: The new derived label.
199
266
 
200
267
  """
201
268
  existing_labels = self.list()
@@ -206,137 +273,147 @@ class LabelsContainer:
206
273
  )
207
274
 
208
275
  label_group = self._group_handler.get_group(name, create_mode=True)
209
-
210
276
  derive_label(
211
- store=label_group,
212
277
  ref_image=ref_image,
213
- name=name,
278
+ store=label_group,
214
279
  shape=shape,
215
- pixel_size=pixel_size,
216
- axes_names=axes_names,
280
+ pixelsize=pixelsize,
281
+ z_spacing=z_spacing,
282
+ time_spacing=time_spacing,
283
+ name=name,
284
+ translation=translation,
285
+ channels_policy=channels_policy,
286
+ ngff_version=ngff_version,
217
287
  chunks=chunks,
288
+ shards=shards,
218
289
  dtype=dtype,
219
290
  dimension_separator=dimension_separator,
220
- compressor=compressor,
291
+ compressors=compressors,
292
+ extra_array_kwargs=extra_array_kwargs,
221
293
  overwrite=overwrite,
294
+ labels=labels,
295
+ pixel_size=pixel_size,
222
296
  )
223
297
 
224
298
  if name not in existing_labels:
225
299
  existing_labels.append(name)
226
- self._group_handler.write_attrs({"labels": existing_labels})
227
300
 
301
+ update_meta = NgioLabelsGroupMeta(
302
+ labels=existing_labels, version=self.meta.version
303
+ )
304
+ self._meta_handler.update_meta(update_meta)
228
305
  return self.get(name)
229
306
 
230
307
 
231
308
  def derive_label(
309
+ *,
232
310
  store: StoreOrGroup,
233
311
  ref_image: Image | Label,
234
- name: str,
312
+ # Metadata parameters
235
313
  shape: Sequence[int] | None = None,
236
- pixel_size: PixelSize | None = None,
237
- axes_names: Sequence[str] | None = None,
238
- chunks: Sequence[int] | None = None,
239
- dimension_separator: DIMENSION_SEPARATOR | None = None,
240
- compressor=None,
241
- dtype: str = "uint32",
314
+ pixelsize: float | tuple[float, float] | None = None,
315
+ z_spacing: float | None = None,
316
+ time_spacing: float | None = None,
317
+ name: str | None = None,
318
+ translation: Sequence[float] | None = None,
319
+ channels_policy: Literal["same", "squeeze", "singleton"] | int = "squeeze",
320
+ ngff_version: NgffVersions | None = None,
321
+ # Zarr Array parameters
322
+ chunks: ChunksLike | None = None,
323
+ shards: ShardsLike | None = None,
324
+ dtype: str | None = None,
325
+ dimension_separator: Literal[".", "/"] | None = None,
326
+ compressors: CompressorLike | None = None,
327
+ extra_array_kwargs: Mapping[str, Any] | None = None,
242
328
  overwrite: bool = False,
243
- ) -> None:
244
- """Create an empty OME-Zarr label from a reference image.
329
+ # Deprecated arguments
330
+ labels: Sequence[str] | None = None,
331
+ pixel_size: PixelSize | None = None,
332
+ ) -> tuple[ZarrGroupHandler, AxesSetup]:
333
+ """Derive a new OME-Zarr label from an existing image or label.
334
+
335
+ If a kwarg is not provided, the value from the reference image will be used.
245
336
 
246
337
  Args:
247
- store (StoreOrGroup): The Zarr store or group to create the image in.
248
- ref_image (Image | Label): A reference image that will be used to
249
- create the new image.
250
- name (str): The name of the new image.
251
- shape (Sequence[int] | None): The shape of the new image.
252
- pixel_size (PixelSize | None): The pixel size of the new image.
253
- axes_names (Sequence[str] | None): The axes names of the new image.
254
- For labels, the channel axis is not allowed.
255
- chunks (Sequence[int] | None): The chunk shape of the new image.
256
- dtype (str): The data type of the new label.
257
- dimension_separator (DIMENSION_SEPARATOR | None): The separator to use for
258
- dimensions. If None it will use the same as the reference image.
259
- compressor: The compressor to use. If None it will use
260
- the same as the reference image.
261
- overwrite (bool): Whether to overwrite an existing image.
338
+ store (StoreOrGroup): The Zarr store or group to create the label in.
339
+ ref_image (Image | Label): The reference image to derive the new label from.
340
+ shape (Sequence[int] | None): The shape of the new label.
341
+ pixelsize (float | tuple[float, float] | None): The pixel size of the new label.
342
+ z_spacing (float | None): The z spacing of the new label.
343
+ time_spacing (float | None): The time spacing of the new label.
344
+ name (str | None): The name of the new label.
345
+ translation (Sequence[float] | None): The translation for each axis
346
+ at the highest resolution level. Defaults to None.
347
+ channels_policy (Literal["squeeze", "same", "singleton"] | int): Possible
348
+ policies:
349
+ - If "squeeze", the channels axis will be removed (no matter its size).
350
+ - If "same", the channels axis will be kept as is (if it exists).
351
+ - If "singleton", the channels axis will be set to size 1.
352
+ - If an integer is provided, the channels axis will be changed to have that
353
+ size.
354
+ ngff_version (NgffVersions | None): The NGFF version to use.
355
+ chunks (ChunksLike | None): The chunk shape of the new label.
356
+ shards (ShardsLike | None): The shard shape of the new label.
357
+ dtype (str | None): The data type of the new label.
358
+ dimension_separator (Literal[".", "/"] | None): The separator to use for
359
+ dimensions.
360
+ compressors (CompressorLike | None): The compressors to use.
361
+ extra_array_kwargs (Mapping[str, Any] | None): Extra arguments to pass to
362
+ the zarr array creation.
363
+ overwrite (bool): Whether to overwrite an existing label. Defaults to False.
364
+ labels (Sequence[str] | None): Deprecated. This argument is deprecated,
365
+ please use channels_meta instead.
366
+ pixel_size (PixelSize | None): Deprecated. The pixel size of the new label.
367
+ This argument is deprecated, please use pixelsize, z_spacing,
368
+ and time_spacing instead.
262
369
 
263
370
  Returns:
264
- None
371
+ tuple[ZarrGroupHandler, AxesSetup]: The group handler of the new label
372
+ and the axes setup.
265
373
 
266
374
  """
267
- ref_meta = ref_image.meta
268
-
269
- if shape is None:
270
- shape = ref_image.shape
271
-
272
- if pixel_size is None:
273
- pixel_size = ref_image.pixel_size
274
-
275
- if axes_names is None:
276
- axes_names = ref_meta.axes_handler.axes_names
277
- c_axis = ref_meta.axes_handler.get_index("c")
278
- else:
279
- if "c" in axes_names:
280
- raise NgioValidationError(
281
- "Labels cannot have a channel axis. "
282
- "Please remove the channel axis from the axes names."
283
- )
284
- c_axis = None
285
-
286
- if len(axes_names) != len(shape):
287
- raise NgioValidationError(
288
- "The axes names of the new image does not match the reference image."
289
- f"Got {axes_names} for shape {shape}."
290
- )
291
-
292
- if chunks is None:
293
- chunks = ref_image.chunks
294
-
295
- if len(chunks) != len(shape):
296
- raise NgioValidationError(
297
- "The chunks of the new image does not match the reference image."
298
- f"Got {chunks} for shape {shape}."
299
- )
300
-
301
- if c_axis is not None:
302
- # remove channel if present
303
- shape = list(shape)
304
- shape = shape[:c_axis] + shape[c_axis + 1 :]
305
- chunks = list(chunks)
306
- chunks = chunks[:c_axis] + chunks[c_axis + 1 :]
307
- axes_names = list(axes_names)
308
- axes_names = axes_names[:c_axis] + axes_names[c_axis + 1 :]
309
-
310
- if dimension_separator is None:
311
- dimension_separator = ref_image.zarr_array._dimension_separator # type: ignore
312
- if compressor is None:
313
- compressor = ref_image.zarr_array.compressor # type: ignore
314
-
315
- _ = create_empty_label_container(
375
+ if dtype is None and isinstance(ref_image, Image):
376
+ dtype = "uint32"
377
+ group_handler, axes_setup = abstract_derive(
378
+ ref_image=ref_image,
379
+ meta_type=NgioLabelMeta,
316
380
  store=store,
317
381
  shape=shape,
318
- pixelsize=ref_image.pixel_size.x,
319
- z_spacing=ref_image.pixel_size.z,
320
- time_spacing=ref_image.pixel_size.t,
321
- levels=ref_meta.paths,
322
- yx_scaling_factor=ref_meta.yx_scaling(),
323
- z_scaling_factor=ref_meta.z_scaling(),
324
- time_unit=ref_image.pixel_size.time_unit,
325
- space_unit=ref_image.pixel_size.space_unit,
326
- axes_names=axes_names,
382
+ pixelsize=pixelsize,
383
+ z_spacing=z_spacing,
384
+ time_spacing=time_spacing,
385
+ name=name,
386
+ translation=translation,
387
+ channels_meta=None,
388
+ channels_policy=channels_policy,
389
+ ngff_version=ngff_version,
327
390
  chunks=chunks,
391
+ shards=shards,
328
392
  dtype=dtype,
329
- dimension_separator=dimension_separator, # type: ignore
330
- compressor=compressor, # type: ignore
393
+ dimension_separator=dimension_separator,
394
+ compressors=compressors,
395
+ extra_array_kwargs=extra_array_kwargs,
331
396
  overwrite=overwrite,
332
- version=ref_meta.version,
333
- name=name,
397
+ labels=labels,
398
+ pixel_size=pixel_size,
334
399
  )
335
- return None
400
+ return group_handler, axes_setup
336
401
 
337
402
 
338
- def build_masking_roi_table(label: Label) -> MaskingRoiTable:
339
- """Compute the masking ROI table for a label."""
340
- array = label.get_as_dask(axes_order=["t", "z", "y", "x"])
341
- rois = compute_masking_roi(array, label.pixel_size)
403
+ def build_masking_roi_table(
404
+ label: Label, axes_order: Sequence[str] | None = None
405
+ ) -> MaskingRoiTable:
406
+ """Compute the masking ROI table for a label.
407
+
408
+ Args:
409
+ label: The label to compute the masking ROI table for.
410
+ axes_order: The order of axes for the computation. If None,
411
+ uses the label's default axes order.
412
+
413
+ Returns:
414
+ A MaskingRoiTable containing ROIs for each label in the segmentation.
415
+ """
416
+ axes_order = axes_order or label.axes
417
+ array = label.get_as_dask(axes_order=axes_order)
418
+ rois = compute_masking_roi(array, label.pixel_size, axes_order=axes_order)
342
419
  return MaskingRoiTable(rois, reference_label=label.meta.name)
@@ -34,7 +34,7 @@ class MaskedImage(Image):
34
34
  self,
35
35
  group_handler: ZarrGroupHandler,
36
36
  path: str,
37
- meta_handler: ImageMetaHandler | None,
37
+ meta_handler: ImageMetaHandler,
38
38
  label: Label,
39
39
  masking_roi_table: MaskingRoiTable,
40
40
  ) -> None:
@@ -299,7 +299,7 @@ class MaskedLabel(Label):
299
299
  self,
300
300
  group_handler: ZarrGroupHandler,
301
301
  path: str,
302
- meta_handler: LabelMetaHandler | None,
302
+ meta_handler: LabelMetaHandler,
303
303
  label: Label,
304
304
  masking_roi_table: MaskingRoiTable,
305
305
  ) -> None: