ngio 0.2.0a2__py3-none-any.whl → 0.5.0b4__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 (106) hide show
  1. ngio/__init__.py +40 -12
  2. ngio/common/__init__.py +16 -32
  3. ngio/common/_dimensions.py +270 -48
  4. ngio/common/_masking_roi.py +153 -0
  5. ngio/common/_pyramid.py +267 -73
  6. ngio/common/_roi.py +290 -66
  7. ngio/common/_synt_images_utils.py +101 -0
  8. ngio/common/_zoom.py +54 -22
  9. ngio/experimental/__init__.py +5 -0
  10. ngio/experimental/iterators/__init__.py +15 -0
  11. ngio/experimental/iterators/_abstract_iterator.py +390 -0
  12. ngio/experimental/iterators/_feature.py +189 -0
  13. ngio/experimental/iterators/_image_processing.py +130 -0
  14. ngio/experimental/iterators/_mappers.py +48 -0
  15. ngio/experimental/iterators/_rois_utils.py +126 -0
  16. ngio/experimental/iterators/_segmentation.py +235 -0
  17. ngio/hcs/__init__.py +17 -58
  18. ngio/hcs/_plate.py +1354 -0
  19. ngio/images/__init__.py +30 -9
  20. ngio/images/_abstract_image.py +968 -0
  21. ngio/images/_create_synt_container.py +132 -0
  22. ngio/images/_create_utils.py +423 -0
  23. ngio/images/_image.py +926 -0
  24. ngio/images/_label.py +417 -0
  25. ngio/images/_masked_image.py +531 -0
  26. ngio/images/_ome_zarr_container.py +1235 -0
  27. ngio/images/_table_ops.py +471 -0
  28. ngio/io_pipes/__init__.py +75 -0
  29. ngio/io_pipes/_io_pipes.py +361 -0
  30. ngio/io_pipes/_io_pipes_masked.py +488 -0
  31. ngio/io_pipes/_io_pipes_roi.py +146 -0
  32. ngio/io_pipes/_io_pipes_types.py +56 -0
  33. ngio/io_pipes/_match_shape.py +377 -0
  34. ngio/io_pipes/_ops_axes.py +344 -0
  35. ngio/io_pipes/_ops_slices.py +411 -0
  36. ngio/io_pipes/_ops_slices_utils.py +199 -0
  37. ngio/io_pipes/_ops_transforms.py +104 -0
  38. ngio/io_pipes/_zoom_transform.py +180 -0
  39. ngio/ome_zarr_meta/__init__.py +39 -15
  40. ngio/ome_zarr_meta/_meta_handlers.py +490 -96
  41. ngio/ome_zarr_meta/ngio_specs/__init__.py +24 -10
  42. ngio/ome_zarr_meta/ngio_specs/_axes.py +268 -234
  43. ngio/ome_zarr_meta/ngio_specs/_channels.py +125 -41
  44. ngio/ome_zarr_meta/ngio_specs/_dataset.py +42 -87
  45. ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +536 -2
  46. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +202 -198
  47. ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +72 -34
  48. ngio/ome_zarr_meta/v04/__init__.py +21 -5
  49. ngio/ome_zarr_meta/v04/_custom_models.py +18 -0
  50. ngio/ome_zarr_meta/v04/{_v04_spec_utils.py → _v04_spec.py} +151 -90
  51. ngio/ome_zarr_meta/v05/__init__.py +27 -0
  52. ngio/ome_zarr_meta/v05/_custom_models.py +18 -0
  53. ngio/ome_zarr_meta/v05/_v05_spec.py +511 -0
  54. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/mask.png +0 -0
  55. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
  56. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/raw.jpg +0 -0
  57. ngio/resources/__init__.py +55 -0
  58. ngio/resources/resource_model.py +36 -0
  59. ngio/tables/__init__.py +20 -4
  60. ngio/tables/_abstract_table.py +270 -0
  61. ngio/tables/_tables_container.py +449 -0
  62. ngio/tables/backends/__init__.py +50 -1
  63. ngio/tables/backends/_abstract_backend.py +200 -31
  64. ngio/tables/backends/_anndata.py +139 -0
  65. ngio/tables/backends/_anndata_utils.py +10 -114
  66. ngio/tables/backends/_csv.py +19 -0
  67. ngio/tables/backends/_json.py +92 -0
  68. ngio/tables/backends/_parquet.py +19 -0
  69. ngio/tables/backends/_py_arrow_backends.py +222 -0
  70. ngio/tables/backends/_table_backends.py +162 -38
  71. ngio/tables/backends/_utils.py +608 -0
  72. ngio/tables/v1/__init__.py +19 -4
  73. ngio/tables/v1/_condition_table.py +71 -0
  74. ngio/tables/v1/_feature_table.py +79 -115
  75. ngio/tables/v1/_generic_table.py +21 -90
  76. ngio/tables/v1/_roi_table.py +486 -137
  77. ngio/transforms/__init__.py +5 -0
  78. ngio/transforms/_zoom.py +19 -0
  79. ngio/utils/__init__.py +16 -14
  80. ngio/utils/_cache.py +48 -0
  81. ngio/utils/_datasets.py +121 -13
  82. ngio/utils/_fractal_fsspec_store.py +42 -0
  83. ngio/utils/_zarr_utils.py +374 -218
  84. ngio-0.5.0b4.dist-info/METADATA +147 -0
  85. ngio-0.5.0b4.dist-info/RECORD +88 -0
  86. {ngio-0.2.0a2.dist-info → ngio-0.5.0b4.dist-info}/WHEEL +1 -1
  87. ngio/common/_array_pipe.py +0 -160
  88. ngio/common/_axes_transforms.py +0 -63
  89. ngio/common/_common_types.py +0 -5
  90. ngio/common/_slicer.py +0 -97
  91. ngio/images/abstract_image.py +0 -240
  92. ngio/images/create.py +0 -251
  93. ngio/images/image.py +0 -389
  94. ngio/images/label.py +0 -236
  95. ngio/images/omezarr_container.py +0 -535
  96. ngio/ome_zarr_meta/_generic_handlers.py +0 -320
  97. ngio/ome_zarr_meta/v04/_meta_handlers.py +0 -54
  98. ngio/tables/_validators.py +0 -192
  99. ngio/tables/backends/_anndata_v1.py +0 -75
  100. ngio/tables/backends/_json_v1.py +0 -56
  101. ngio/tables/tables_container.py +0 -300
  102. ngio/tables/v1/_masking_roi_table.py +0 -175
  103. ngio/utils/_logger.py +0 -29
  104. ngio-0.2.0a2.dist-info/METADATA +0 -95
  105. ngio-0.2.0a2.dist-info/RECORD +0 -53
  106. {ngio-0.2.0a2.dist-info → ngio-0.5.0b4.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,531 @@
1
+ """A module for handling label images in OME-NGFF files."""
2
+
3
+ from collections.abc import Sequence
4
+ from typing import Literal
5
+
6
+ import dask.array as da
7
+ import numpy as np
8
+
9
+ from ngio.images._image import (
10
+ ChannelSlicingInputType,
11
+ Image,
12
+ SlicingInputType,
13
+ add_channel_selection_to_slicing_dict,
14
+ )
15
+ from ngio.images._label import Label
16
+ from ngio.io_pipes import (
17
+ DaskGetterMasked,
18
+ DaskSetterMasked,
19
+ NumpyGetterMasked,
20
+ NumpySetterMasked,
21
+ TransformProtocol,
22
+ )
23
+ from ngio.ome_zarr_meta import ImageMetaHandler, LabelMetaHandler
24
+ from ngio.tables import MaskingRoiTable
25
+ from ngio.utils import (
26
+ ZarrGroupHandler,
27
+ )
28
+
29
+
30
+ class MaskedImage(Image):
31
+ """Placeholder class for a label."""
32
+
33
+ def __init__(
34
+ self,
35
+ group_handler: ZarrGroupHandler,
36
+ path: str,
37
+ meta_handler: ImageMetaHandler | None,
38
+ label: Label,
39
+ masking_roi_table: MaskingRoiTable,
40
+ ) -> None:
41
+ """Initialize the Image at a single level.
42
+
43
+ Args:
44
+ group_handler: The Zarr group handler.
45
+ path: The path to the image in the ome_zarr file.
46
+ meta_handler: The image metadata handler.
47
+ label: The label image.
48
+ masking_roi_table: The masking ROI table.
49
+
50
+ """
51
+ super().__init__(
52
+ group_handler=group_handler, path=path, meta_handler=meta_handler
53
+ )
54
+ self._label = label
55
+ self._masking_roi_table = masking_roi_table
56
+
57
+ def __repr__(self) -> str:
58
+ """Return a string representation of the object."""
59
+ label_name = self._label.meta.name
60
+ if label_name is None:
61
+ label_name = self._masking_roi_table.reference_label
62
+ return f"MaskedImage(path={self.path}, {self.dimensions}, {label_name})"
63
+
64
+ def get_roi_as_numpy( # type: ignore (this ignore the method override issue)
65
+ self,
66
+ label: int,
67
+ channel_selection: ChannelSlicingInputType | None = None,
68
+ zoom_factor: float = 1.0,
69
+ axes_order: Sequence[str] | None = None,
70
+ transforms: Sequence[TransformProtocol] | None = None,
71
+ **slicing_kwargs: slice | int | Sequence[int],
72
+ ) -> np.ndarray:
73
+ """Return the array for a given ROI."""
74
+ roi = self._masking_roi_table.get_label(label)
75
+ roi = roi.zoom(zoom_factor)
76
+ return super().get_roi_as_numpy(
77
+ roi=roi,
78
+ channel_selection=channel_selection,
79
+ axes_order=axes_order,
80
+ transforms=transforms,
81
+ **slicing_kwargs,
82
+ )
83
+
84
+ def get_roi_as_dask( # type: ignore (this ignore the method override issue)
85
+ self,
86
+ label: int,
87
+ channel_selection: ChannelSlicingInputType | None = None,
88
+ zoom_factor: float = 1.0,
89
+ axes_order: Sequence[str] | None = None,
90
+ transforms: Sequence[TransformProtocol] | None = None,
91
+ **slicing_kwargs: slice | int | Sequence[int],
92
+ ) -> da.Array:
93
+ """Return the array for a given ROI as a Dask array."""
94
+ roi = self._masking_roi_table.get_label(label)
95
+ roi = roi.zoom(zoom_factor)
96
+ return super().get_roi_as_dask(
97
+ roi=roi,
98
+ channel_selection=channel_selection,
99
+ axes_order=axes_order,
100
+ transforms=transforms,
101
+ **slicing_kwargs,
102
+ )
103
+
104
+ def get_roi( # type: ignore (this ignore the method override issue)
105
+ self,
106
+ label: int,
107
+ zoom_factor: float = 1.0,
108
+ channel_selection: ChannelSlicingInputType | None = None,
109
+ axes_order: Sequence[str] | None = None,
110
+ transforms: Sequence[TransformProtocol] | None = None,
111
+ mode: Literal["numpy", "dask"] = "numpy",
112
+ **slicing_kwargs: slice | int | Sequence[int],
113
+ ) -> np.ndarray | da.Array:
114
+ """Return the array for a given ROI."""
115
+ roi = self._masking_roi_table.get_label(label)
116
+ roi = roi.zoom(zoom_factor)
117
+ return super().get_roi(
118
+ roi=roi,
119
+ channel_selection=channel_selection,
120
+ axes_order=axes_order,
121
+ transforms=transforms,
122
+ mode=mode,
123
+ **slicing_kwargs,
124
+ )
125
+
126
+ def set_roi( # type: ignore (this ignore the method override issue)
127
+ self,
128
+ label: int,
129
+ patch: np.ndarray | da.Array,
130
+ zoom_factor: float = 1.0,
131
+ channel_selection: ChannelSlicingInputType | None = None,
132
+ axes_order: Sequence[str] | None = None,
133
+ transforms: Sequence[TransformProtocol] | None = None,
134
+ **slicing_kwargs: slice | int | Sequence[int],
135
+ ) -> None:
136
+ """Set the array for a given ROI."""
137
+ roi = self._masking_roi_table.get_label(label)
138
+ roi = roi.zoom(zoom_factor)
139
+ return super().set_roi(
140
+ roi=roi,
141
+ patch=patch,
142
+ channel_selection=channel_selection,
143
+ axes_order=axes_order,
144
+ transforms=transforms,
145
+ **slicing_kwargs,
146
+ )
147
+
148
+ def get_roi_masked_as_numpy(
149
+ self,
150
+ label: int,
151
+ channel_selection: ChannelSlicingInputType | None = None,
152
+ zoom_factor: float = 1.0,
153
+ axes_order: Sequence[str] | None = None,
154
+ transforms: Sequence[TransformProtocol] | None = None,
155
+ allow_rescaling: bool = True,
156
+ **slicing_kwargs: SlicingInputType,
157
+ ) -> np.ndarray:
158
+ """Return the masked array for a given label as a NumPy array."""
159
+ slicing_kwargs = add_channel_selection_to_slicing_dict(
160
+ image=self, channel_selection=channel_selection, slicing_dict=slicing_kwargs
161
+ )
162
+
163
+ roi = self._masking_roi_table.get_label(label)
164
+ roi = roi.zoom(zoom_factor)
165
+ masked_getter = NumpyGetterMasked(
166
+ roi=roi,
167
+ zarr_array=self.zarr_array,
168
+ label_zarr_array=self._label.zarr_array,
169
+ dimensions=self.dimensions,
170
+ label_dimensions=self._label.dimensions,
171
+ axes_order=axes_order,
172
+ transforms=transforms,
173
+ slicing_dict=slicing_kwargs,
174
+ allow_rescaling=allow_rescaling,
175
+ )
176
+ return masked_getter()
177
+
178
+ def get_roi_masked_as_dask(
179
+ self,
180
+ label: int,
181
+ channel_selection: ChannelSlicingInputType | None = None,
182
+ zoom_factor: float = 1.0,
183
+ axes_order: Sequence[str] | None = None,
184
+ transforms: Sequence[TransformProtocol] | None = None,
185
+ allow_rescaling: bool = True,
186
+ **slicing_kwargs: SlicingInputType,
187
+ ) -> da.Array:
188
+ """Return the masked array for a given label as a Dask array."""
189
+ slicing_kwargs = add_channel_selection_to_slicing_dict(
190
+ image=self, channel_selection=channel_selection, slicing_dict=slicing_kwargs
191
+ )
192
+
193
+ roi = self._masking_roi_table.get_label(label)
194
+ roi = roi.zoom(zoom_factor)
195
+ masked_getter = DaskGetterMasked(
196
+ roi=roi,
197
+ zarr_array=self.zarr_array,
198
+ label_zarr_array=self._label.zarr_array,
199
+ dimensions=self.dimensions,
200
+ label_dimensions=self._label.dimensions,
201
+ axes_order=axes_order,
202
+ transforms=transforms,
203
+ slicing_dict=slicing_kwargs,
204
+ allow_rescaling=allow_rescaling,
205
+ )
206
+ return masked_getter()
207
+
208
+ def get_roi_masked(
209
+ self,
210
+ label: int,
211
+ channel_selection: ChannelSlicingInputType | None = None,
212
+ zoom_factor: float = 1.0,
213
+ axes_order: Sequence[str] | None = None,
214
+ transforms: Sequence[TransformProtocol] | None = None,
215
+ mode: Literal["numpy", "dask"] = "numpy",
216
+ allow_rescaling: bool = True,
217
+ **slicing_kwargs: SlicingInputType,
218
+ ) -> np.ndarray | da.Array:
219
+ """Return the masked array for a given label."""
220
+ if mode == "numpy":
221
+ return self.get_roi_masked_as_numpy(
222
+ label=label,
223
+ channel_selection=channel_selection,
224
+ zoom_factor=zoom_factor,
225
+ axes_order=axes_order,
226
+ transforms=transforms,
227
+ allow_rescaling=allow_rescaling,
228
+ **slicing_kwargs,
229
+ )
230
+
231
+ elif mode == "dask":
232
+ return self.get_roi_masked_as_dask(
233
+ label=label,
234
+ channel_selection=channel_selection,
235
+ zoom_factor=zoom_factor,
236
+ axes_order=axes_order,
237
+ transforms=transforms,
238
+ allow_rescaling=allow_rescaling,
239
+ **slicing_kwargs,
240
+ )
241
+ else:
242
+ raise ValueError(f"Unknown mode: {mode}")
243
+
244
+ def set_roi_masked(
245
+ self,
246
+ label: int,
247
+ patch: np.ndarray | da.Array,
248
+ channel_selection: ChannelSlicingInputType | None = None,
249
+ axes_order: Sequence[str] | None = None,
250
+ zoom_factor: float = 1.0,
251
+ transforms: Sequence[TransformProtocol] | None = None,
252
+ allow_rescaling: bool = True,
253
+ **slicing_kwargs: SlicingInputType,
254
+ ) -> None:
255
+ """Set the masked array for a given label."""
256
+ slicing_kwargs = add_channel_selection_to_slicing_dict(
257
+ image=self, channel_selection=channel_selection, slicing_dict=slicing_kwargs
258
+ )
259
+
260
+ roi = self._masking_roi_table.get_label(label)
261
+ roi = roi.zoom(zoom_factor)
262
+ if isinstance(patch, da.Array):
263
+ path_setter = DaskSetterMasked(
264
+ roi=roi,
265
+ zarr_array=self.zarr_array,
266
+ label_zarr_array=self._label.zarr_array,
267
+ dimensions=self.dimensions,
268
+ label_dimensions=self._label.dimensions,
269
+ axes_order=axes_order,
270
+ transforms=transforms,
271
+ slicing_dict=slicing_kwargs,
272
+ allow_rescaling=allow_rescaling,
273
+ )
274
+ path_setter(patch)
275
+ elif isinstance(patch, np.ndarray):
276
+ path_setter = NumpySetterMasked(
277
+ roi=roi,
278
+ zarr_array=self.zarr_array,
279
+ label_zarr_array=self._label.zarr_array,
280
+ dimensions=self.dimensions,
281
+ label_dimensions=self._label.dimensions,
282
+ axes_order=axes_order,
283
+ transforms=transforms,
284
+ slicing_dict=slicing_kwargs,
285
+ allow_rescaling=allow_rescaling,
286
+ )
287
+ path_setter(patch)
288
+ else:
289
+ raise TypeError(
290
+ f"Unsupported patch type: {type(patch)}. "
291
+ "Expected numpy.ndarray or dask.array.Array."
292
+ )
293
+
294
+
295
+ class MaskedLabel(Label):
296
+ """Placeholder class for a label."""
297
+
298
+ def __init__(
299
+ self,
300
+ group_handler: ZarrGroupHandler,
301
+ path: str,
302
+ meta_handler: LabelMetaHandler | None,
303
+ label: Label,
304
+ masking_roi_table: MaskingRoiTable,
305
+ ) -> None:
306
+ """Initialize the Image at a single level.
307
+
308
+ Args:
309
+ group_handler: The Zarr group handler.
310
+ path: The path to the image in the ome_zarr file.
311
+ meta_handler: The image metadata handler.
312
+ label: The label image.
313
+ masking_roi_table: The masking ROI table.
314
+
315
+ """
316
+ super().__init__(
317
+ group_handler=group_handler, path=path, meta_handler=meta_handler
318
+ )
319
+ self._label = label
320
+ self._masking_roi_table = masking_roi_table
321
+
322
+ def __repr__(self) -> str:
323
+ """Return a string representation of the object."""
324
+ label_name = self._label.meta.name
325
+ if label_name is None:
326
+ label_name = self._masking_roi_table.reference_label
327
+ return f"MaskedLabel(path={self.path}, {self.dimensions}, {label_name})"
328
+
329
+ def get_roi_as_numpy(
330
+ self,
331
+ label: int,
332
+ zoom_factor: float = 1.0,
333
+ axes_order: Sequence[str] | None = None,
334
+ transforms: Sequence[TransformProtocol] | None = None,
335
+ **slicing_kwargs: slice | int | Sequence[int],
336
+ ) -> np.ndarray:
337
+ """Return the ROI as a NumPy array."""
338
+ roi = self._masking_roi_table.get_label(label)
339
+ roi = roi.zoom(zoom_factor)
340
+ return super().get_roi_as_numpy(
341
+ roi=roi,
342
+ axes_order=axes_order,
343
+ transforms=transforms,
344
+ **slicing_kwargs,
345
+ )
346
+
347
+ def get_roi_as_dask(
348
+ self,
349
+ label: int,
350
+ zoom_factor: float = 1.0,
351
+ axes_order: Sequence[str] | None = None,
352
+ transforms: Sequence[TransformProtocol] | None = None,
353
+ **slicing_kwargs: slice | int | Sequence[int],
354
+ ) -> da.Array:
355
+ """Return the ROI as a Dask array."""
356
+ roi = self._masking_roi_table.get_label(label)
357
+ roi = roi.zoom(zoom_factor)
358
+ return super().get_roi_as_dask(
359
+ roi=roi,
360
+ axes_order=axes_order,
361
+ transforms=transforms,
362
+ **slicing_kwargs,
363
+ )
364
+
365
+ def get_roi(
366
+ self,
367
+ label: int,
368
+ zoom_factor: float = 1.0,
369
+ axes_order: Sequence[str] | None = None,
370
+ mode: Literal["numpy", "dask"] = "numpy",
371
+ transforms: Sequence[TransformProtocol] | None = None,
372
+ **slicing_kwargs: slice | int | Sequence[int],
373
+ ) -> np.ndarray | da.Array:
374
+ """Return the array for a given ROI."""
375
+ roi = self._masking_roi_table.get_label(label)
376
+ roi = roi.zoom(zoom_factor)
377
+ return super().get_roi(
378
+ roi=roi,
379
+ axes_order=axes_order,
380
+ mode=mode,
381
+ transforms=transforms,
382
+ **slicing_kwargs,
383
+ )
384
+
385
+ def set_roi(
386
+ self,
387
+ label: int,
388
+ patch: np.ndarray | da.Array,
389
+ zoom_factor: float = 1.0,
390
+ axes_order: Sequence[str] | None = None,
391
+ transforms: Sequence[TransformProtocol] | None = None,
392
+ **slicing_kwargs: slice | int | Sequence[int],
393
+ ) -> None:
394
+ """Set the array for a given ROI."""
395
+ roi = self._masking_roi_table.get_label(label)
396
+ roi = roi.zoom(zoom_factor)
397
+ return super().set_roi(
398
+ roi=roi,
399
+ patch=patch,
400
+ axes_order=axes_order,
401
+ transforms=transforms,
402
+ **slicing_kwargs,
403
+ )
404
+
405
+ def get_roi_masked_as_numpy(
406
+ self,
407
+ label: int,
408
+ zoom_factor: float = 1.0,
409
+ axes_order: Sequence[str] | None = None,
410
+ transforms: Sequence[TransformProtocol] | None = None,
411
+ allow_rescaling: bool = True,
412
+ **slicing_kwargs: SlicingInputType,
413
+ ) -> np.ndarray:
414
+ """Return the masked array for a given label as a NumPy array."""
415
+ roi = self._masking_roi_table.get_label(label)
416
+ roi = roi.zoom(zoom_factor)
417
+ masked_getter = NumpyGetterMasked(
418
+ roi=roi,
419
+ zarr_array=self.zarr_array,
420
+ label_zarr_array=self._label.zarr_array,
421
+ dimensions=self.dimensions,
422
+ label_dimensions=self._label.dimensions,
423
+ axes_order=axes_order,
424
+ transforms=transforms,
425
+ slicing_dict=slicing_kwargs,
426
+ allow_rescaling=allow_rescaling,
427
+ )
428
+ return masked_getter()
429
+
430
+ def get_roi_masked_as_dask(
431
+ self,
432
+ label: int,
433
+ zoom_factor: float = 1.0,
434
+ axes_order: Sequence[str] | None = None,
435
+ transforms: Sequence[TransformProtocol] | None = None,
436
+ allow_rescaling: bool = True,
437
+ **slicing_kwargs: SlicingInputType,
438
+ ) -> da.Array:
439
+ """Return the masked array for a given label as a Dask array."""
440
+ roi = self._masking_roi_table.get_label(label)
441
+ roi = roi.zoom(zoom_factor)
442
+ masked_getter = DaskGetterMasked(
443
+ roi=roi,
444
+ zarr_array=self.zarr_array,
445
+ label_zarr_array=self._label.zarr_array,
446
+ dimensions=self.dimensions,
447
+ label_dimensions=self._label.dimensions,
448
+ axes_order=axes_order,
449
+ transforms=transforms,
450
+ slicing_dict=slicing_kwargs,
451
+ allow_rescaling=allow_rescaling,
452
+ )
453
+ return masked_getter()
454
+
455
+ def get_roi_masked(
456
+ self,
457
+ label: int,
458
+ zoom_factor: float = 1.0,
459
+ axes_order: Sequence[str] | None = None,
460
+ mode: Literal["numpy", "dask"] = "numpy",
461
+ transforms: Sequence[TransformProtocol] | None = None,
462
+ allow_rescaling: bool = True,
463
+ **slicing_kwargs: SlicingInputType,
464
+ ) -> np.ndarray | da.Array:
465
+ """Return the masked array for a given label."""
466
+ if mode == "numpy":
467
+ return self.get_roi_masked_as_numpy(
468
+ label=label,
469
+ zoom_factor=zoom_factor,
470
+ axes_order=axes_order,
471
+ transforms=transforms,
472
+ allow_rescaling=allow_rescaling,
473
+ **slicing_kwargs,
474
+ )
475
+
476
+ elif mode == "dask":
477
+ return self.get_roi_masked_as_dask(
478
+ label=label,
479
+ zoom_factor=zoom_factor,
480
+ axes_order=axes_order,
481
+ transforms=transforms,
482
+ allow_rescaling=allow_rescaling,
483
+ **slicing_kwargs,
484
+ )
485
+ else:
486
+ raise ValueError(f"Unknown mode: {mode}")
487
+
488
+ def set_roi_masked(
489
+ self,
490
+ label: int,
491
+ patch: np.ndarray | da.Array,
492
+ axes_order: Sequence[str] | None = None,
493
+ zoom_factor: float = 1.0,
494
+ transforms: Sequence[TransformProtocol] | None = None,
495
+ allow_rescaling: bool = True,
496
+ **slicing_kwargs: SlicingInputType,
497
+ ) -> None:
498
+ """Set the masked array for a given label."""
499
+ roi = self._masking_roi_table.get_label(label)
500
+ roi = roi.zoom(zoom_factor)
501
+ if isinstance(patch, da.Array):
502
+ path_setter = DaskSetterMasked(
503
+ roi=roi,
504
+ zarr_array=self.zarr_array,
505
+ label_zarr_array=self._label.zarr_array,
506
+ dimensions=self.dimensions,
507
+ label_dimensions=self._label.dimensions,
508
+ axes_order=axes_order,
509
+ transforms=transforms,
510
+ slicing_dict=slicing_kwargs,
511
+ allow_rescaling=allow_rescaling,
512
+ )
513
+ path_setter(patch)
514
+ elif isinstance(patch, np.ndarray):
515
+ path_setter = NumpySetterMasked(
516
+ roi=roi,
517
+ zarr_array=self.zarr_array,
518
+ label_zarr_array=self._label.zarr_array,
519
+ dimensions=self.dimensions,
520
+ label_dimensions=self._label.dimensions,
521
+ axes_order=axes_order,
522
+ transforms=transforms,
523
+ slicing_dict=slicing_kwargs,
524
+ allow_rescaling=allow_rescaling,
525
+ )
526
+ path_setter(patch)
527
+ else:
528
+ raise TypeError(
529
+ f"Unsupported patch type: {type(patch)}. "
530
+ "Expected numpy.ndarray or dask.array.Array."
531
+ )