ngio 0.1.6__py3-none-any.whl → 0.2.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.
- ngio/__init__.py +33 -5
- ngio/common/__init__.py +54 -0
- ngio/common/_array_pipe.py +265 -0
- ngio/common/_axes_transforms.py +64 -0
- ngio/common/_common_types.py +5 -0
- ngio/common/_dimensions.py +120 -0
- ngio/common/_masking_roi.py +158 -0
- ngio/common/_pyramid.py +228 -0
- ngio/common/_roi.py +165 -0
- ngio/common/_slicer.py +96 -0
- ngio/{pipes/_zoom_utils.py → common/_zoom.py} +7 -81
- ngio/hcs/__init__.py +5 -0
- ngio/hcs/plate.py +448 -0
- ngio/images/__init__.py +23 -0
- ngio/images/abstract_image.py +349 -0
- ngio/images/create.py +270 -0
- ngio/images/image.py +453 -0
- ngio/images/label.py +285 -0
- ngio/images/masked_image.py +273 -0
- ngio/images/ome_zarr_container.py +738 -0
- ngio/ome_zarr_meta/__init__.py +47 -0
- ngio/ome_zarr_meta/_meta_handlers.py +791 -0
- ngio/ome_zarr_meta/ngio_specs/__init__.py +71 -0
- ngio/ome_zarr_meta/ngio_specs/_axes.py +481 -0
- ngio/ome_zarr_meta/ngio_specs/_channels.py +389 -0
- ngio/ome_zarr_meta/ngio_specs/_dataset.py +134 -0
- ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +377 -0
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +489 -0
- ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +116 -0
- ngio/ome_zarr_meta/v04/__init__.py +23 -0
- ngio/ome_zarr_meta/v04/_v04_spec_utils.py +485 -0
- ngio/tables/__init__.py +24 -6
- ngio/tables/_validators.py +190 -0
- ngio/tables/backends/__init__.py +8 -0
- ngio/tables/backends/_abstract_backend.py +71 -0
- ngio/tables/backends/_anndata_utils.py +198 -0
- ngio/tables/backends/_anndata_v1.py +76 -0
- ngio/tables/backends/_json_v1.py +56 -0
- ngio/tables/backends/_table_backends.py +102 -0
- ngio/tables/tables_container.py +310 -0
- ngio/tables/v1/__init__.py +5 -5
- ngio/tables/v1/_feature_table.py +182 -0
- ngio/tables/v1/_generic_table.py +160 -179
- ngio/tables/v1/_roi_table.py +366 -0
- ngio/utils/__init__.py +26 -10
- ngio/utils/_datasets.py +53 -0
- ngio/utils/_errors.py +10 -4
- ngio/utils/_fractal_fsspec_store.py +13 -0
- ngio/utils/_logger.py +3 -1
- ngio/utils/_zarr_utils.py +401 -0
- {ngio-0.1.6.dist-info → ngio-0.2.0.dist-info}/METADATA +30 -43
- ngio-0.2.0.dist-info/RECORD +54 -0
- ngio/core/__init__.py +0 -7
- ngio/core/dimensions.py +0 -122
- ngio/core/image_handler.py +0 -228
- ngio/core/image_like_handler.py +0 -549
- ngio/core/label_handler.py +0 -410
- ngio/core/ngff_image.py +0 -387
- ngio/core/roi.py +0 -92
- ngio/core/utils.py +0 -287
- ngio/io/__init__.py +0 -19
- ngio/io/_zarr.py +0 -88
- ngio/io/_zarr_array_utils.py +0 -0
- ngio/io/_zarr_group_utils.py +0 -60
- ngio/iterators/__init__.py +0 -1
- ngio/ngff_meta/__init__.py +0 -27
- ngio/ngff_meta/fractal_image_meta.py +0 -1267
- ngio/ngff_meta/meta_handler.py +0 -92
- ngio/ngff_meta/utils.py +0 -235
- ngio/ngff_meta/v04/__init__.py +0 -6
- ngio/ngff_meta/v04/specs.py +0 -158
- ngio/ngff_meta/v04/zarr_utils.py +0 -376
- ngio/pipes/__init__.py +0 -7
- ngio/pipes/_slicer_transforms.py +0 -176
- ngio/pipes/_transforms.py +0 -33
- ngio/pipes/data_pipe.py +0 -52
- ngio/tables/_ad_reader.py +0 -80
- ngio/tables/_utils.py +0 -301
- ngio/tables/tables_group.py +0 -252
- ngio/tables/v1/feature_tables.py +0 -182
- ngio/tables/v1/masking_roi_tables.py +0 -243
- ngio/tables/v1/roi_tables.py +0 -285
- ngio/utils/_common_types.py +0 -5
- ngio/utils/_pydantic_utils.py +0 -52
- ngio-0.1.6.dist-info/RECORD +0 -44
- {ngio-0.1.6.dist-info → ngio-0.2.0.dist-info}/WHEEL +0 -0
- {ngio-0.1.6.dist-info → ngio-0.2.0.dist-info}/licenses/LICENSE +0 -0
ngio/images/label.py
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"""A module for handling label images in OME-NGFF files."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Collection
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
from ngio.common import compute_masking_roi
|
|
7
|
+
from ngio.images.abstract_image import AbstractImage, consolidate_image
|
|
8
|
+
from ngio.images.create import _create_empty_label
|
|
9
|
+
from ngio.images.image import Image
|
|
10
|
+
from ngio.ome_zarr_meta import (
|
|
11
|
+
LabelMetaHandler,
|
|
12
|
+
NgioLabelMeta,
|
|
13
|
+
PixelSize,
|
|
14
|
+
find_label_meta_handler,
|
|
15
|
+
)
|
|
16
|
+
from ngio.tables import MaskingRoiTable
|
|
17
|
+
from ngio.utils import (
|
|
18
|
+
NgioValidationError,
|
|
19
|
+
NgioValueError,
|
|
20
|
+
StoreOrGroup,
|
|
21
|
+
ZarrGroupHandler,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Label(AbstractImage[LabelMetaHandler]):
|
|
26
|
+
"""Placeholder class for a label."""
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
group_handler: ZarrGroupHandler,
|
|
31
|
+
path: str,
|
|
32
|
+
meta_handler: LabelMetaHandler | None,
|
|
33
|
+
) -> None:
|
|
34
|
+
"""Initialize the Image at a single level.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
group_handler: The Zarr group handler.
|
|
38
|
+
path: The path to the image in the ome_zarr file.
|
|
39
|
+
meta_handler: The image metadata handler.
|
|
40
|
+
|
|
41
|
+
"""
|
|
42
|
+
if meta_handler is None:
|
|
43
|
+
meta_handler = find_label_meta_handler(group_handler)
|
|
44
|
+
super().__init__(
|
|
45
|
+
group_handler=group_handler, path=path, meta_handler=meta_handler
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def __repr__(self) -> str:
|
|
49
|
+
"""Return the string representation of the label."""
|
|
50
|
+
return f"Label(path={self.path}, {self.dimensions})"
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def meta(self) -> NgioLabelMeta:
|
|
54
|
+
"""Return the metadata."""
|
|
55
|
+
return self._meta_handler.meta
|
|
56
|
+
|
|
57
|
+
def build_masking_roi_table(self) -> MaskingRoiTable:
|
|
58
|
+
"""Compute the masking ROI table."""
|
|
59
|
+
return build_masking_roi_table(self)
|
|
60
|
+
|
|
61
|
+
def consolidate(
|
|
62
|
+
self,
|
|
63
|
+
mode: Literal["dask", "numpy", "coarsen"] = "dask",
|
|
64
|
+
) -> None:
|
|
65
|
+
"""Consolidate the label on disk."""
|
|
66
|
+
consolidate_image(self, mode=mode, order=0)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class LabelsContainer:
|
|
70
|
+
"""A class to handle the /labels group in an OME-NGFF file."""
|
|
71
|
+
|
|
72
|
+
def __init__(self, group_handler: ZarrGroupHandler) -> None:
|
|
73
|
+
"""Initialize the LabelGroupHandler."""
|
|
74
|
+
self._group_handler = group_handler
|
|
75
|
+
|
|
76
|
+
# Validate the group
|
|
77
|
+
# Either contains a labels attribute or is empty
|
|
78
|
+
attrs = self._group_handler.load_attrs()
|
|
79
|
+
if len(attrs) == 0:
|
|
80
|
+
# It's an empty group
|
|
81
|
+
pass
|
|
82
|
+
elif "labels" in attrs and isinstance(attrs["labels"], list):
|
|
83
|
+
# It's a valid group
|
|
84
|
+
pass
|
|
85
|
+
else:
|
|
86
|
+
raise NgioValidationError(
|
|
87
|
+
f"Invalid /labels group. "
|
|
88
|
+
f"Expected a single labels attribute with a list of label names. "
|
|
89
|
+
f"Found: {attrs}"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def list(self) -> list[str]:
|
|
93
|
+
"""Create the /labels group if it doesn't exist."""
|
|
94
|
+
attrs = self._group_handler.load_attrs()
|
|
95
|
+
return attrs.get("labels", [])
|
|
96
|
+
|
|
97
|
+
def get(
|
|
98
|
+
self,
|
|
99
|
+
name: str,
|
|
100
|
+
path: str | None = None,
|
|
101
|
+
pixel_size: PixelSize | None = None,
|
|
102
|
+
strict: bool = False,
|
|
103
|
+
) -> Label:
|
|
104
|
+
"""Get a label from the group.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
name (str): The name of the label.
|
|
108
|
+
path (str | None): The path to the image in the ome_zarr file.
|
|
109
|
+
pixel_size (PixelSize | None): The pixel size of the image.
|
|
110
|
+
strict (bool): Only used if the pixel size is provided. If True, the
|
|
111
|
+
pixel size must match the image pixel size exactly. If False, the
|
|
112
|
+
closest pixel size level will be returned.
|
|
113
|
+
|
|
114
|
+
"""
|
|
115
|
+
group_handler = self._group_handler.derive_handler(name)
|
|
116
|
+
label_meta_handler = find_label_meta_handler(group_handler)
|
|
117
|
+
path = label_meta_handler.meta.get_dataset(
|
|
118
|
+
path=path, pixel_size=pixel_size, strict=strict
|
|
119
|
+
).path
|
|
120
|
+
return Label(group_handler, path, label_meta_handler)
|
|
121
|
+
|
|
122
|
+
def derive(
|
|
123
|
+
self,
|
|
124
|
+
name: str,
|
|
125
|
+
ref_image: Image,
|
|
126
|
+
shape: Collection[int] | None = None,
|
|
127
|
+
pixel_size: PixelSize | None = None,
|
|
128
|
+
axes_names: Collection[str] | None = None,
|
|
129
|
+
chunks: Collection[int] | None = None,
|
|
130
|
+
dtype: str | None = None,
|
|
131
|
+
overwrite: bool = False,
|
|
132
|
+
) -> "Label":
|
|
133
|
+
"""Create an empty OME-Zarr label from a reference image.
|
|
134
|
+
|
|
135
|
+
And add the label to the /labels group.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
store (StoreOrGroup): The Zarr store or group to create the image in.
|
|
139
|
+
ref_image (Image): The reference image.
|
|
140
|
+
name (str): The name of the new image.
|
|
141
|
+
shape (Collection[int] | None): The shape of the new image.
|
|
142
|
+
pixel_size (PixelSize | None): The pixel size of the new image.
|
|
143
|
+
axes_names (Collection[str] | None): The axes names of the new image.
|
|
144
|
+
For labels, the channel axis is not allowed.
|
|
145
|
+
chunks (Collection[int] | None): The chunk shape of the new image.
|
|
146
|
+
dtype (str | None): The data type of the new image.
|
|
147
|
+
overwrite (bool): Whether to overwrite an existing image.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Label: The new label.
|
|
151
|
+
|
|
152
|
+
"""
|
|
153
|
+
existing_labels = self.list()
|
|
154
|
+
if name in existing_labels and not overwrite:
|
|
155
|
+
raise NgioValueError(
|
|
156
|
+
f"Table '{name}' already exists in the group. "
|
|
157
|
+
"Use overwrite=True to replace it."
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
label_group = self._group_handler.get_group(name, create_mode=True)
|
|
161
|
+
|
|
162
|
+
_derive_label(
|
|
163
|
+
store=label_group,
|
|
164
|
+
ref_image=ref_image,
|
|
165
|
+
name=name,
|
|
166
|
+
shape=shape,
|
|
167
|
+
pixel_size=pixel_size,
|
|
168
|
+
axes_names=axes_names,
|
|
169
|
+
chunks=chunks,
|
|
170
|
+
dtype=dtype,
|
|
171
|
+
overwrite=overwrite,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
if name not in existing_labels:
|
|
175
|
+
existing_labels.append(name)
|
|
176
|
+
self._group_handler.write_attrs({"labels": existing_labels})
|
|
177
|
+
|
|
178
|
+
return self.get(name)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _derive_label(
|
|
182
|
+
store: StoreOrGroup,
|
|
183
|
+
ref_image: Image,
|
|
184
|
+
name: str,
|
|
185
|
+
shape: Collection[int] | None = None,
|
|
186
|
+
pixel_size: PixelSize | None = None,
|
|
187
|
+
axes_names: Collection[str] | None = None,
|
|
188
|
+
chunks: Collection[int] | None = None,
|
|
189
|
+
dtype: str | None = None,
|
|
190
|
+
overwrite: bool = False,
|
|
191
|
+
) -> None:
|
|
192
|
+
"""Create an empty OME-Zarr label from a reference image.
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
store (StoreOrGroup): The Zarr store or group to create the image in.
|
|
196
|
+
ref_image (Image): The reference image.
|
|
197
|
+
name (str): The name of the new image.
|
|
198
|
+
shape (Collection[int] | None): The shape of the new image.
|
|
199
|
+
pixel_size (PixelSize | None): The pixel size of the new image.
|
|
200
|
+
axes_names (Collection[str] | None): The axes names of the new image.
|
|
201
|
+
For labels, the channel axis is not allowed.
|
|
202
|
+
chunks (Collection[int] | None): The chunk shape of the new image.
|
|
203
|
+
dtype (str | None): The data type of the new image.
|
|
204
|
+
overwrite (bool): Whether to overwrite an existing image.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
None
|
|
208
|
+
|
|
209
|
+
"""
|
|
210
|
+
ref_meta = ref_image.meta
|
|
211
|
+
|
|
212
|
+
if shape is None:
|
|
213
|
+
shape = ref_image.shape
|
|
214
|
+
|
|
215
|
+
if pixel_size is None:
|
|
216
|
+
pixel_size = ref_image.pixel_size
|
|
217
|
+
|
|
218
|
+
if axes_names is None:
|
|
219
|
+
axes_names = ref_meta.axes_mapper.on_disk_axes_names
|
|
220
|
+
c_axis = ref_meta.axes_mapper.get_index("c")
|
|
221
|
+
else:
|
|
222
|
+
if "c" in axes_names:
|
|
223
|
+
raise NgioValidationError(
|
|
224
|
+
"Labels cannot have a channel axis. "
|
|
225
|
+
"Please remove the channel axis from the axes names."
|
|
226
|
+
)
|
|
227
|
+
c_axis = None
|
|
228
|
+
|
|
229
|
+
if len(axes_names) != len(shape):
|
|
230
|
+
raise NgioValidationError(
|
|
231
|
+
"The axes names of the new image does not match the reference image."
|
|
232
|
+
f"Got {axes_names} for shape {shape}."
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
if chunks is None:
|
|
236
|
+
chunks = ref_image.chunks
|
|
237
|
+
|
|
238
|
+
if len(chunks) != len(shape):
|
|
239
|
+
raise NgioValidationError(
|
|
240
|
+
"The chunks of the new image does not match the reference image."
|
|
241
|
+
f"Got {chunks} for shape {shape}."
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
if dtype is None:
|
|
245
|
+
dtype = ref_image.dtype
|
|
246
|
+
|
|
247
|
+
if c_axis is not None:
|
|
248
|
+
# remove channel if present
|
|
249
|
+
shape = list(shape)
|
|
250
|
+
shape = shape[:c_axis] + shape[c_axis + 1 :]
|
|
251
|
+
chunks = list(chunks)
|
|
252
|
+
chunks = chunks[:c_axis] + chunks[c_axis + 1 :]
|
|
253
|
+
axes_names = list(axes_names)
|
|
254
|
+
axes_names = axes_names[:c_axis] + axes_names[c_axis + 1 :]
|
|
255
|
+
|
|
256
|
+
_ = _create_empty_label(
|
|
257
|
+
store=store,
|
|
258
|
+
shape=shape,
|
|
259
|
+
pixelsize=ref_image.pixel_size.x,
|
|
260
|
+
z_spacing=ref_image.pixel_size.z,
|
|
261
|
+
time_spacing=ref_image.pixel_size.t,
|
|
262
|
+
levels=ref_meta.levels,
|
|
263
|
+
yx_scaling_factor=ref_meta.yx_scaling(),
|
|
264
|
+
z_scaling_factor=ref_meta.z_scaling(),
|
|
265
|
+
time_unit=ref_image.pixel_size.time_unit,
|
|
266
|
+
space_unit=ref_image.pixel_size.space_unit,
|
|
267
|
+
axes_names=axes_names,
|
|
268
|
+
chunks=chunks,
|
|
269
|
+
dtype=dtype,
|
|
270
|
+
overwrite=overwrite,
|
|
271
|
+
version=ref_meta.version,
|
|
272
|
+
name=name,
|
|
273
|
+
)
|
|
274
|
+
return None
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def build_masking_roi_table(label: Label) -> MaskingRoiTable:
|
|
278
|
+
"""Compute the masking ROI table for a label."""
|
|
279
|
+
if label.dimensions.is_time_series:
|
|
280
|
+
raise NgioValueError("Time series labels are not supported.")
|
|
281
|
+
|
|
282
|
+
array = label.get_array(axes_order=["z", "y", "x"], mode="dask")
|
|
283
|
+
|
|
284
|
+
rois = compute_masking_roi(array, label.pixel_size)
|
|
285
|
+
return MaskingRoiTable(rois, reference_label=label.meta.name)
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"""A module for handling label images in OME-NGFF files."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Collection, Iterable
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
from ngio.common import ArrayLike, get_masked_pipe, roi_to_slice_kwargs, set_masked_pipe
|
|
7
|
+
from ngio.images.image import Image
|
|
8
|
+
from ngio.images.label import Label
|
|
9
|
+
from ngio.ome_zarr_meta import ImageMetaHandler, LabelMetaHandler
|
|
10
|
+
from ngio.tables import MaskingRoiTable
|
|
11
|
+
from ngio.utils import (
|
|
12
|
+
ZarrGroupHandler,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MaskedImage(Image):
|
|
17
|
+
"""Placeholder class for a label."""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
group_handler: ZarrGroupHandler,
|
|
22
|
+
path: str,
|
|
23
|
+
meta_handler: ImageMetaHandler | None,
|
|
24
|
+
label: Label,
|
|
25
|
+
masking_roi_table: MaskingRoiTable,
|
|
26
|
+
) -> None:
|
|
27
|
+
"""Initialize the Image at a single level.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
group_handler: The Zarr group handler.
|
|
31
|
+
path: The path to the image in the ome_zarr file.
|
|
32
|
+
meta_handler: The image metadata handler.
|
|
33
|
+
label: The label image.
|
|
34
|
+
masking_roi_table: The masking ROI table.
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
super().__init__(
|
|
38
|
+
group_handler=group_handler, path=path, meta_handler=meta_handler
|
|
39
|
+
)
|
|
40
|
+
self._label = label
|
|
41
|
+
self._masking_roi_table = masking_roi_table
|
|
42
|
+
|
|
43
|
+
def __repr__(self) -> str:
|
|
44
|
+
"""Return a string representation of the object."""
|
|
45
|
+
label_name = self._label.meta.name
|
|
46
|
+
if label_name is None:
|
|
47
|
+
label_name = self._masking_roi_table.reference_label
|
|
48
|
+
return f"MaskedImage(path={self.path}, {self.dimensions}, {label_name})"
|
|
49
|
+
|
|
50
|
+
def get_roi(
|
|
51
|
+
self,
|
|
52
|
+
label: int,
|
|
53
|
+
zoom_factor: float = 1.0,
|
|
54
|
+
axes_order: Collection[str] | None = None,
|
|
55
|
+
mode: Literal["numpy", "dask", "delayed"] = "numpy",
|
|
56
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
57
|
+
) -> ArrayLike:
|
|
58
|
+
"""Return the array for a given ROI."""
|
|
59
|
+
roi = self._masking_roi_table.get(label)
|
|
60
|
+
roi = roi.zoom(zoom_factor)
|
|
61
|
+
return super().get_roi(
|
|
62
|
+
roi=roi, axes_order=axes_order, mode=mode, **slice_kwargs
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def set_roi(
|
|
66
|
+
self,
|
|
67
|
+
label: int,
|
|
68
|
+
patch: ArrayLike,
|
|
69
|
+
zoom_factor: float = 1.0,
|
|
70
|
+
axes_order: Collection[str] | None = None,
|
|
71
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
72
|
+
) -> None:
|
|
73
|
+
"""Set the array for a given ROI."""
|
|
74
|
+
roi = self._masking_roi_table.get(label)
|
|
75
|
+
roi = roi.zoom(zoom_factor)
|
|
76
|
+
return super().set_roi(
|
|
77
|
+
roi=roi, patch=patch, axes_order=axes_order, **slice_kwargs
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def get_roi_masked(
|
|
81
|
+
self,
|
|
82
|
+
label: int,
|
|
83
|
+
axes_order: Collection[str] | None = None,
|
|
84
|
+
mode: Literal["numpy", "dask", "delayed"] = "numpy",
|
|
85
|
+
zoom_factor: float = 1.0,
|
|
86
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
87
|
+
) -> ArrayLike:
|
|
88
|
+
"""Return the masked array for a given label."""
|
|
89
|
+
return get_masked_roi_pipe(
|
|
90
|
+
image=self,
|
|
91
|
+
label=label,
|
|
92
|
+
axes_order=axes_order,
|
|
93
|
+
mode=mode,
|
|
94
|
+
zoom_factor=zoom_factor,
|
|
95
|
+
**slice_kwargs,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def set_roi_masked(
|
|
99
|
+
self,
|
|
100
|
+
label: int,
|
|
101
|
+
patch: ArrayLike,
|
|
102
|
+
axes_order: Collection[str] | None = None,
|
|
103
|
+
zoom_factor: float = 1.0,
|
|
104
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
105
|
+
) -> None:
|
|
106
|
+
"""Set the masked array for a given label."""
|
|
107
|
+
return set_masked_roi_pipe(
|
|
108
|
+
image=self,
|
|
109
|
+
label=label,
|
|
110
|
+
patch=patch,
|
|
111
|
+
axes_order=axes_order,
|
|
112
|
+
zoom_factor=zoom_factor,
|
|
113
|
+
**slice_kwargs,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class MaskedLabel(Label):
|
|
118
|
+
"""Placeholder class for a label."""
|
|
119
|
+
|
|
120
|
+
def __init__(
|
|
121
|
+
self,
|
|
122
|
+
group_handler: ZarrGroupHandler,
|
|
123
|
+
path: str,
|
|
124
|
+
meta_handler: LabelMetaHandler | None,
|
|
125
|
+
label: Label,
|
|
126
|
+
masking_roi_table: MaskingRoiTable,
|
|
127
|
+
) -> None:
|
|
128
|
+
"""Initialize the Image at a single level.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
group_handler: The Zarr group handler.
|
|
132
|
+
path: The path to the image in the ome_zarr file.
|
|
133
|
+
meta_handler: The image metadata handler.
|
|
134
|
+
label: The label image.
|
|
135
|
+
masking_roi_table: The masking ROI table.
|
|
136
|
+
|
|
137
|
+
"""
|
|
138
|
+
super().__init__(
|
|
139
|
+
group_handler=group_handler, path=path, meta_handler=meta_handler
|
|
140
|
+
)
|
|
141
|
+
self._label = label
|
|
142
|
+
self._masking_roi_table = masking_roi_table
|
|
143
|
+
|
|
144
|
+
def __repr__(self) -> str:
|
|
145
|
+
"""Return a string representation of the object."""
|
|
146
|
+
label_name = self._label.meta.name
|
|
147
|
+
if label_name is None:
|
|
148
|
+
label_name = self._masking_roi_table.reference_label
|
|
149
|
+
return f"MaskedLabel(path={self.path}, {self.dimensions}, {label_name})"
|
|
150
|
+
|
|
151
|
+
def get_roi(
|
|
152
|
+
self,
|
|
153
|
+
label: int,
|
|
154
|
+
zoom_factor: float = 1.0,
|
|
155
|
+
axes_order: Collection[str] | None = None,
|
|
156
|
+
mode: Literal["numpy", "dask", "delayed"] = "numpy",
|
|
157
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
158
|
+
) -> ArrayLike:
|
|
159
|
+
"""Return the array for a given ROI."""
|
|
160
|
+
roi = self._masking_roi_table.get(label)
|
|
161
|
+
roi = roi.zoom(zoom_factor)
|
|
162
|
+
return super().get_roi(
|
|
163
|
+
roi=roi, axes_order=axes_order, mode=mode, **slice_kwargs
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
def set_roi(
|
|
167
|
+
self,
|
|
168
|
+
label: int,
|
|
169
|
+
patch: ArrayLike,
|
|
170
|
+
zoom_factor: float = 1.0,
|
|
171
|
+
axes_order: Collection[str] | None = None,
|
|
172
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
173
|
+
) -> None:
|
|
174
|
+
"""Set the array for a given ROI."""
|
|
175
|
+
roi = self._masking_roi_table.get(label)
|
|
176
|
+
roi = roi.zoom(zoom_factor)
|
|
177
|
+
return super().set_roi(
|
|
178
|
+
roi=roi, patch=patch, axes_order=axes_order, **slice_kwargs
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
def get_roi_masked(
|
|
182
|
+
self,
|
|
183
|
+
label: int,
|
|
184
|
+
axes_order: Collection[str] | None = None,
|
|
185
|
+
mode: Literal["numpy", "dask", "delayed"] = "numpy",
|
|
186
|
+
zoom_factor: float = 1.0,
|
|
187
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
188
|
+
) -> ArrayLike:
|
|
189
|
+
"""Return the masked array for a given label."""
|
|
190
|
+
return get_masked_roi_pipe(
|
|
191
|
+
image=self,
|
|
192
|
+
label=label,
|
|
193
|
+
axes_order=axes_order,
|
|
194
|
+
mode=mode,
|
|
195
|
+
zoom_factor=zoom_factor,
|
|
196
|
+
**slice_kwargs,
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
def set_roi_masked(
|
|
200
|
+
self,
|
|
201
|
+
label: int,
|
|
202
|
+
patch: ArrayLike,
|
|
203
|
+
axes_order: Collection[str] | None = None,
|
|
204
|
+
zoom_factor: float = 1.0,
|
|
205
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
206
|
+
) -> None:
|
|
207
|
+
"""Set the masked array for a given label."""
|
|
208
|
+
return set_masked_roi_pipe(
|
|
209
|
+
image=self,
|
|
210
|
+
label=label,
|
|
211
|
+
patch=patch,
|
|
212
|
+
axes_order=axes_order,
|
|
213
|
+
zoom_factor=zoom_factor,
|
|
214
|
+
**slice_kwargs,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def get_masked_roi_pipe(
|
|
219
|
+
image: MaskedImage | MaskedLabel,
|
|
220
|
+
label: int,
|
|
221
|
+
axes_order: Collection[str] | None = None,
|
|
222
|
+
mode: Literal["numpy", "dask", "delayed"] = "numpy",
|
|
223
|
+
zoom_factor: float = 1.0,
|
|
224
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
225
|
+
) -> ArrayLike:
|
|
226
|
+
"""Return the masked array for a given label."""
|
|
227
|
+
roi = image._masking_roi_table.get(label)
|
|
228
|
+
roi = roi.zoom(zoom_factor)
|
|
229
|
+
slice_kwargs = roi_to_slice_kwargs(
|
|
230
|
+
roi=roi,
|
|
231
|
+
pixel_size=image.pixel_size,
|
|
232
|
+
dimensions=image.dimensions,
|
|
233
|
+
**slice_kwargs,
|
|
234
|
+
)
|
|
235
|
+
return get_masked_pipe(
|
|
236
|
+
array=image.zarr_array,
|
|
237
|
+
label_array=image._label.zarr_array,
|
|
238
|
+
label=label,
|
|
239
|
+
dimensions_array=image.dimensions,
|
|
240
|
+
dimensions_label=image._label.dimensions,
|
|
241
|
+
axes_order=axes_order,
|
|
242
|
+
mode=mode,
|
|
243
|
+
**slice_kwargs,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def set_masked_roi_pipe(
|
|
248
|
+
image: MaskedImage | MaskedLabel,
|
|
249
|
+
label: int,
|
|
250
|
+
patch: ArrayLike,
|
|
251
|
+
axes_order: Collection[str] | None = None,
|
|
252
|
+
zoom_factor: float = 1.0,
|
|
253
|
+
**slice_kwargs: slice | int | Iterable[int],
|
|
254
|
+
) -> None:
|
|
255
|
+
"""Set the masked array for a given label."""
|
|
256
|
+
roi = image._masking_roi_table.get(label)
|
|
257
|
+
roi = roi.zoom(zoom_factor)
|
|
258
|
+
slice_kwargs = roi_to_slice_kwargs(
|
|
259
|
+
roi=roi,
|
|
260
|
+
pixel_size=image.pixel_size,
|
|
261
|
+
dimensions=image.dimensions,
|
|
262
|
+
**slice_kwargs,
|
|
263
|
+
)
|
|
264
|
+
return set_masked_pipe(
|
|
265
|
+
array=image.zarr_array,
|
|
266
|
+
label_array=image._label.zarr_array,
|
|
267
|
+
label=label,
|
|
268
|
+
patch=patch,
|
|
269
|
+
dimensions_array=image.dimensions,
|
|
270
|
+
dimensions_label=image._label.dimensions,
|
|
271
|
+
axes_order=axes_order,
|
|
272
|
+
**slice_kwargs,
|
|
273
|
+
)
|