ngio 0.3.5__py3-none-any.whl → 0.4.0a1__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 +6 -0
- ngio/common/__init__.py +50 -48
- ngio/common/_array_io_pipes.py +549 -0
- ngio/common/_array_io_utils.py +508 -0
- ngio/common/_dimensions.py +63 -27
- ngio/common/_masking_roi.py +38 -10
- ngio/common/_pyramid.py +9 -7
- ngio/common/_roi.py +571 -72
- ngio/common/_synt_images_utils.py +101 -0
- ngio/common/_zoom.py +17 -12
- ngio/common/transforms/__init__.py +5 -0
- ngio/common/transforms/_label.py +12 -0
- ngio/common/transforms/_zoom.py +109 -0
- ngio/experimental/__init__.py +5 -0
- ngio/experimental/iterators/__init__.py +17 -0
- ngio/experimental/iterators/_abstract_iterator.py +170 -0
- ngio/experimental/iterators/_feature.py +151 -0
- ngio/experimental/iterators/_image_processing.py +169 -0
- ngio/experimental/iterators/_rois_utils.py +127 -0
- ngio/experimental/iterators/_segmentation.py +278 -0
- ngio/hcs/_plate.py +41 -36
- ngio/images/__init__.py +22 -1
- ngio/images/_abstract_image.py +247 -117
- ngio/images/_create.py +15 -15
- ngio/images/_create_synt_container.py +128 -0
- ngio/images/_image.py +425 -62
- ngio/images/_label.py +33 -30
- ngio/images/_masked_image.py +396 -122
- ngio/images/_ome_zarr_container.py +203 -66
- ngio/{common → images}/_table_ops.py +41 -41
- ngio/ome_zarr_meta/ngio_specs/__init__.py +2 -8
- ngio/ome_zarr_meta/ngio_specs/_axes.py +151 -128
- ngio/ome_zarr_meta/ngio_specs/_channels.py +55 -18
- ngio/ome_zarr_meta/ngio_specs/_dataset.py +7 -7
- ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +3 -3
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +11 -68
- ngio/ome_zarr_meta/v04/_v04_spec_utils.py +1 -1
- ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/mask.png +0 -0
- ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
- ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/raw.jpg +0 -0
- ngio/resources/__init__.py +54 -0
- ngio/resources/resource_model.py +35 -0
- ngio/tables/backends/_abstract_backend.py +5 -6
- ngio/tables/backends/_anndata.py +1 -1
- ngio/tables/backends/_anndata_utils.py +3 -3
- ngio/tables/backends/_non_zarr_backends.py +1 -1
- ngio/tables/backends/_table_backends.py +0 -1
- ngio/tables/backends/_utils.py +3 -3
- ngio/tables/v1/_roi_table.py +156 -69
- ngio/utils/__init__.py +2 -3
- ngio/utils/_logger.py +19 -0
- ngio/utils/_zarr_utils.py +1 -5
- {ngio-0.3.5.dist-info → ngio-0.4.0a1.dist-info}/METADATA +3 -1
- ngio-0.4.0a1.dist-info/RECORD +76 -0
- ngio/common/_array_pipe.py +0 -288
- ngio/common/_axes_transforms.py +0 -64
- ngio/common/_common_types.py +0 -5
- ngio/common/_slicer.py +0 -96
- ngio-0.3.5.dist-info/RECORD +0 -61
- {ngio-0.3.5.dist-info → ngio-0.4.0a1.dist-info}/WHEEL +0 -0
- {ngio-0.3.5.dist-info → ngio-0.4.0a1.dist-info}/licenses/LICENSE +0 -0
ngio/common/_roi.py
CHANGED
|
@@ -4,21 +4,38 @@ These are the interfaces bwteen the ROI tables / masking ROI tables and
|
|
|
4
4
|
the ImageLikeHandler.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from collections.abc import
|
|
7
|
+
from collections.abc import Callable, Sequence
|
|
8
|
+
from typing import Generic, TypeVar
|
|
9
|
+
from warnings import warn
|
|
8
10
|
|
|
11
|
+
import dask.array as da
|
|
9
12
|
import numpy as np
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
import zarr
|
|
14
|
+
from pydantic import BaseModel, ConfigDict
|
|
15
|
+
|
|
16
|
+
from ngio.common._array_io_pipes import (
|
|
17
|
+
build_dask_getter,
|
|
18
|
+
build_dask_setter,
|
|
19
|
+
build_masked_dask_getter,
|
|
20
|
+
build_masked_dask_setter,
|
|
21
|
+
build_masked_numpy_getter,
|
|
22
|
+
build_masked_numpy_setter,
|
|
23
|
+
build_numpy_getter,
|
|
24
|
+
build_numpy_setter,
|
|
25
|
+
)
|
|
26
|
+
from ngio.common._array_io_utils import SlicingInputType, TransformProtocol
|
|
12
27
|
from ngio.common._dimensions import Dimensions
|
|
13
28
|
from ngio.ome_zarr_meta.ngio_specs import DefaultSpaceUnit, PixelSize, SpaceUnits
|
|
14
29
|
from ngio.utils import NgioValueError
|
|
15
30
|
|
|
16
31
|
|
|
17
|
-
def _to_raster(value: float, pixel_size: float, max_shape: int) -> int:
|
|
32
|
+
def _to_raster(value: float, pixel_size: float, max_shape: int | None) -> int:
|
|
18
33
|
"""Convert to raster coordinates."""
|
|
19
34
|
round_value = int(np.round(value / pixel_size))
|
|
20
35
|
# Ensure the value is within the image shape boundaries
|
|
21
|
-
|
|
36
|
+
if max_shape is not None:
|
|
37
|
+
return max(0, min(round_value, max_shape))
|
|
38
|
+
return round_value
|
|
22
39
|
|
|
23
40
|
|
|
24
41
|
def _to_world(value: int, pixel_size: float) -> float:
|
|
@@ -26,40 +43,197 @@ def _to_world(value: int, pixel_size: float) -> float:
|
|
|
26
43
|
return value * pixel_size
|
|
27
44
|
|
|
28
45
|
|
|
29
|
-
|
|
30
|
-
|
|
46
|
+
T = TypeVar("T", int, float)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class GenericRoi(BaseModel, Generic[T]):
|
|
50
|
+
"""A generic Region of Interest (ROI) model."""
|
|
31
51
|
|
|
32
52
|
name: str
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
53
|
+
x: T
|
|
54
|
+
y: T
|
|
55
|
+
z: T | None = None
|
|
56
|
+
t: T | None = None
|
|
57
|
+
x_length: T
|
|
58
|
+
y_length: T
|
|
59
|
+
z_length: T | None = None
|
|
60
|
+
t_length: T | None = None
|
|
61
|
+
label: int | None = None
|
|
62
|
+
unit: SpaceUnits | str | None = None
|
|
40
63
|
|
|
41
64
|
model_config = ConfigDict(extra="allow")
|
|
42
65
|
|
|
43
|
-
def
|
|
44
|
-
|
|
66
|
+
def intersection(self, other: "GenericRoi[T]") -> "GenericRoi[T] | None":
|
|
67
|
+
"""Calculate the intersection of this ROI with another ROI."""
|
|
68
|
+
return roi_intersection(self, other)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _1d_intersection(
|
|
72
|
+
a: T | None, a_length: T | None, b: T | None, b_length: T | None
|
|
73
|
+
) -> tuple[T | None, T | None]:
|
|
74
|
+
"""Calculate the intersection of two 1D intervals."""
|
|
75
|
+
if a is None:
|
|
76
|
+
if b is not None and b_length is not None:
|
|
77
|
+
return b, b_length
|
|
78
|
+
return None, None
|
|
79
|
+
if b is None:
|
|
80
|
+
if a is not None and a_length is not None:
|
|
81
|
+
return a, a_length
|
|
82
|
+
return None, None
|
|
83
|
+
|
|
84
|
+
assert (
|
|
85
|
+
a is not None
|
|
86
|
+
and a_length is not None
|
|
87
|
+
and b is not None
|
|
88
|
+
and b_length is not None
|
|
89
|
+
)
|
|
90
|
+
start = max(a, b)
|
|
91
|
+
end = min(a + a_length, b + b_length)
|
|
92
|
+
length = end - start
|
|
93
|
+
|
|
94
|
+
if length <= 0:
|
|
95
|
+
return None, None
|
|
96
|
+
|
|
97
|
+
return start, length
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def roi_intersection(
|
|
101
|
+
ref_roi: GenericRoi[T], other_roi: GenericRoi[T]
|
|
102
|
+
) -> GenericRoi[T] | None:
|
|
103
|
+
"""Calculate the intersection of two ROIs."""
|
|
104
|
+
if (
|
|
105
|
+
ref_roi.unit is not None
|
|
106
|
+
and other_roi.unit is not None
|
|
107
|
+
and ref_roi.unit != other_roi.unit
|
|
108
|
+
):
|
|
109
|
+
raise NgioValueError(
|
|
110
|
+
"Cannot calculate intersection of ROIs with different units."
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
x, x_length = _1d_intersection(
|
|
114
|
+
ref_roi.x, ref_roi.x_length, other_roi.x, other_roi.x_length
|
|
115
|
+
)
|
|
116
|
+
assert x is not None and x_length is not None
|
|
117
|
+
|
|
118
|
+
y, y_length = _1d_intersection(
|
|
119
|
+
ref_roi.y, ref_roi.y_length, other_roi.y, other_roi.y_length
|
|
120
|
+
)
|
|
121
|
+
assert y is not None and y_length is not None
|
|
122
|
+
|
|
123
|
+
z, z_length = _1d_intersection(
|
|
124
|
+
ref_roi.z, ref_roi.z_length, other_roi.z, other_roi.z_length
|
|
125
|
+
)
|
|
126
|
+
t, t_length = _1d_intersection(
|
|
127
|
+
ref_roi.t, ref_roi.t_length, other_roi.t, other_roi.t_length
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
if (
|
|
131
|
+
x_length <= 0
|
|
132
|
+
or y_length <= 0
|
|
133
|
+
or (z_length is not None and z_length <= 0)
|
|
134
|
+
or (t_length is not None and t_length <= 0)
|
|
135
|
+
):
|
|
136
|
+
# No intersection
|
|
137
|
+
return None
|
|
138
|
+
|
|
139
|
+
# Find label
|
|
140
|
+
if ref_roi.label is not None and other_roi.label is not None:
|
|
141
|
+
if ref_roi.label != other_roi.label:
|
|
142
|
+
raise NgioValueError(
|
|
143
|
+
"Cannot calculate intersection of ROIs with different labels."
|
|
144
|
+
)
|
|
145
|
+
label = ref_roi.label or other_roi.label
|
|
146
|
+
|
|
147
|
+
cls_ref = ref_roi.__class__
|
|
148
|
+
return cls_ref(
|
|
149
|
+
name=f"[{ref_roi.name}_x_{other_roi.name}]",
|
|
150
|
+
x=x,
|
|
151
|
+
y=y,
|
|
152
|
+
z=z,
|
|
153
|
+
t=t,
|
|
154
|
+
x_length=x_length,
|
|
155
|
+
y_length=y_length,
|
|
156
|
+
z_length=z_length,
|
|
157
|
+
t_length=t_length,
|
|
158
|
+
unit=ref_roi.unit,
|
|
159
|
+
label=label,
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class Roi(GenericRoi[float]):
|
|
164
|
+
x: float = 0.0
|
|
165
|
+
y: float = 0.0
|
|
166
|
+
unit: SpaceUnits | str | None = DefaultSpaceUnit
|
|
167
|
+
|
|
168
|
+
def to_roi_pixels(
|
|
169
|
+
self, pixel_size: PixelSize, dimensions: Dimensions | None = None
|
|
45
170
|
) -> "RoiPixels":
|
|
46
171
|
"""Convert to raster coordinates."""
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
172
|
+
if dimensions is None:
|
|
173
|
+
# No check for dimensions
|
|
174
|
+
dim_x, dim_y, dim_z, dim_t = None, None, None, None
|
|
175
|
+
else:
|
|
176
|
+
dim_x, dim_y, dim_z, dim_t = (
|
|
177
|
+
dimensions.get("x"),
|
|
178
|
+
dimensions.get("y"),
|
|
179
|
+
dimensions.get("z"),
|
|
180
|
+
dimensions.get("t"),
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
x = _to_raster(self.x, pixel_size.x, dim_x)
|
|
184
|
+
x_length = _to_raster(self.x_length, pixel_size.x, dim_x)
|
|
185
|
+
y = _to_raster(self.y, pixel_size.y, dim_y)
|
|
186
|
+
y_length = _to_raster(self.y_length, pixel_size.y, dim_y)
|
|
187
|
+
|
|
188
|
+
if self.z is None:
|
|
189
|
+
z = None
|
|
190
|
+
else:
|
|
191
|
+
z = _to_raster(self.z, pixel_size.z, dim_z)
|
|
192
|
+
|
|
193
|
+
if self.z_length is None:
|
|
194
|
+
z_length = None
|
|
195
|
+
else:
|
|
196
|
+
z_length = _to_raster(self.z_length, pixel_size.z, dim_z)
|
|
51
197
|
|
|
198
|
+
if self.t is None:
|
|
199
|
+
t = None
|
|
200
|
+
else:
|
|
201
|
+
t = _to_raster(self.t, pixel_size.t, dim_t)
|
|
202
|
+
|
|
203
|
+
if self.t_length is None:
|
|
204
|
+
t_length = None
|
|
205
|
+
else:
|
|
206
|
+
t_length = _to_raster(self.t_length, pixel_size.t, dim_t)
|
|
207
|
+
|
|
208
|
+
extra_dict = self.model_extra if self.model_extra else {}
|
|
52
209
|
return RoiPixels(
|
|
53
210
|
name=self.name,
|
|
54
|
-
x=
|
|
55
|
-
y=
|
|
56
|
-
z=
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
211
|
+
x=x,
|
|
212
|
+
y=y,
|
|
213
|
+
z=z,
|
|
214
|
+
t=t,
|
|
215
|
+
x_length=x_length,
|
|
216
|
+
y_length=y_length,
|
|
217
|
+
z_length=z_length,
|
|
218
|
+
t_length=t_length,
|
|
219
|
+
label=self.label,
|
|
220
|
+
unit=self.unit,
|
|
221
|
+
**extra_dict,
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
def to_pixel_roi(
|
|
225
|
+
self, pixel_size: PixelSize, dimensions: Dimensions | None = None
|
|
226
|
+
) -> "RoiPixels":
|
|
227
|
+
"""Convert to raster coordinates."""
|
|
228
|
+
warn(
|
|
229
|
+
"to_pixel_roi is deprecated and will be removed in a future release. "
|
|
230
|
+
"Use to_roi_pixels instead.",
|
|
231
|
+
DeprecationWarning,
|
|
232
|
+
stacklevel=2,
|
|
61
233
|
)
|
|
62
234
|
|
|
235
|
+
return self.to_roi_pixels(pixel_size=pixel_size, dimensions=dimensions)
|
|
236
|
+
|
|
63
237
|
def zoom(self, zoom_factor: float = 1) -> "Roi":
|
|
64
238
|
"""Zoom the ROI by a factor.
|
|
65
239
|
|
|
@@ -72,38 +246,72 @@ class Roi(BaseModel):
|
|
|
72
246
|
return zoom_roi(self, zoom_factor)
|
|
73
247
|
|
|
74
248
|
|
|
75
|
-
class RoiPixels(
|
|
76
|
-
"""Region of interest (ROI)
|
|
249
|
+
class RoiPixels(GenericRoi[int]):
|
|
250
|
+
"""Region of interest (ROI) in pixel coordinates."""
|
|
77
251
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
z: int
|
|
82
|
-
x_length: int
|
|
83
|
-
y_length: int
|
|
84
|
-
z_length: int
|
|
85
|
-
model_config = ConfigDict(extra="allow")
|
|
252
|
+
x: int = 0
|
|
253
|
+
y: int = 0
|
|
254
|
+
unit: SpaceUnits | str | None = None
|
|
86
255
|
|
|
87
|
-
def to_roi(self, pixel_size: PixelSize) -> Roi:
|
|
88
|
-
"""Convert to
|
|
256
|
+
def to_roi(self, pixel_size: PixelSize) -> "Roi":
|
|
257
|
+
"""Convert to raster coordinates."""
|
|
258
|
+
x = _to_world(self.x, pixel_size.x)
|
|
259
|
+
x_length = _to_world(self.x_length, pixel_size.x)
|
|
260
|
+
y = _to_world(self.y, pixel_size.y)
|
|
261
|
+
y_length = _to_world(self.y_length, pixel_size.y)
|
|
262
|
+
|
|
263
|
+
if self.z is None:
|
|
264
|
+
z = None
|
|
265
|
+
else:
|
|
266
|
+
z = _to_world(self.z, pixel_size.z)
|
|
267
|
+
|
|
268
|
+
if self.z_length is None:
|
|
269
|
+
z_length = None
|
|
270
|
+
else:
|
|
271
|
+
z_length = _to_world(self.z_length, pixel_size.z)
|
|
272
|
+
|
|
273
|
+
if self.t is None:
|
|
274
|
+
t = None
|
|
275
|
+
else:
|
|
276
|
+
t = _to_world(self.t, pixel_size.t)
|
|
277
|
+
|
|
278
|
+
if self.t_length is None:
|
|
279
|
+
t_length = None
|
|
280
|
+
else:
|
|
281
|
+
t_length = _to_world(self.t_length, pixel_size.t)
|
|
282
|
+
|
|
283
|
+
extra_dict = self.model_extra if self.model_extra else {}
|
|
89
284
|
return Roi(
|
|
90
285
|
name=self.name,
|
|
91
|
-
x=
|
|
92
|
-
y=
|
|
93
|
-
z=
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
286
|
+
x=x,
|
|
287
|
+
y=y,
|
|
288
|
+
z=z,
|
|
289
|
+
t=t,
|
|
290
|
+
x_length=x_length,
|
|
291
|
+
y_length=y_length,
|
|
292
|
+
z_length=z_length,
|
|
293
|
+
t_length=t_length,
|
|
294
|
+
label=self.label,
|
|
295
|
+
unit=self.unit,
|
|
296
|
+
**extra_dict,
|
|
99
297
|
)
|
|
100
298
|
|
|
101
|
-
def
|
|
102
|
-
|
|
299
|
+
def to_slicing_dict(self) -> dict[str, SlicingInputType]:
|
|
300
|
+
x_slice = slice(self.x, self.x + self.x_length)
|
|
301
|
+
y_slice = slice(self.y, self.y + self.y_length)
|
|
302
|
+
if self.z is not None and self.z_length is not None:
|
|
303
|
+
z_slice = slice(self.z, self.z + self.z_length)
|
|
304
|
+
else:
|
|
305
|
+
z_slice = slice(None)
|
|
306
|
+
if self.t is not None and self.t_length is not None:
|
|
307
|
+
t_slice = slice(self.t, self.t + self.t_length)
|
|
308
|
+
else:
|
|
309
|
+
t_slice = slice(None)
|
|
103
310
|
return {
|
|
104
|
-
"x":
|
|
105
|
-
"y":
|
|
106
|
-
"z":
|
|
311
|
+
"x": x_slice,
|
|
312
|
+
"y": y_slice,
|
|
313
|
+
"z": z_slice,
|
|
314
|
+
"t": t_slice,
|
|
107
315
|
}
|
|
108
316
|
|
|
109
317
|
|
|
@@ -134,34 +342,325 @@ def zoom_roi(roi: Roi, zoom_factor: float = 1) -> Roi:
|
|
|
134
342
|
x=new_x,
|
|
135
343
|
y=new_y,
|
|
136
344
|
z=roi.z,
|
|
345
|
+
t=roi.t,
|
|
137
346
|
x_length=roi.x_length + diff_x,
|
|
138
347
|
y_length=roi.y_length + diff_y,
|
|
139
348
|
z_length=roi.z_length,
|
|
349
|
+
t_length=roi.t_length,
|
|
350
|
+
label=roi.label,
|
|
140
351
|
unit=roi.unit,
|
|
141
352
|
)
|
|
142
|
-
|
|
143
353
|
return new_roi
|
|
144
354
|
|
|
145
355
|
|
|
146
|
-
def
|
|
147
|
-
roi: Roi,
|
|
148
|
-
pixel_size: PixelSize,
|
|
356
|
+
def roi_to_slicing_dict(
|
|
357
|
+
roi: Roi | RoiPixels,
|
|
149
358
|
dimensions: Dimensions,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if not dimensions.has_axis(axis_name="z"):
|
|
158
|
-
raster_roi.pop("z")
|
|
159
|
-
|
|
160
|
-
for key in slice_kwargs.keys():
|
|
161
|
-
if key in raster_roi:
|
|
359
|
+
pixel_size: PixelSize | None = None,
|
|
360
|
+
slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
361
|
+
) -> dict[str, SlicingInputType]:
|
|
362
|
+
"""Convert a ROI to a slicing dictionary."""
|
|
363
|
+
if isinstance(roi, Roi):
|
|
364
|
+
if pixel_size is None:
|
|
162
365
|
raise NgioValueError(
|
|
163
|
-
|
|
164
|
-
"Ambiguous which one to use: "
|
|
165
|
-
f"{key}={slice_kwargs[key]} or roi_{key}={raster_roi[key]}"
|
|
366
|
+
"pixel_size must be provided when converting a Roi to slice_kwargs."
|
|
166
367
|
)
|
|
167
|
-
|
|
368
|
+
roi = roi.to_roi_pixels(pixel_size=pixel_size, dimensions=dimensions)
|
|
369
|
+
|
|
370
|
+
roi_slicing_dict = roi.to_slicing_dict()
|
|
371
|
+
if slicing_dict is None:
|
|
372
|
+
return roi_slicing_dict
|
|
373
|
+
|
|
374
|
+
# Additional slice kwargs can be provided
|
|
375
|
+
# and will override the ones from the ROI
|
|
376
|
+
roi_slicing_dict.update(slicing_dict)
|
|
377
|
+
return roi_slicing_dict
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def build_roi_numpy_getter(
|
|
381
|
+
zarr_array: zarr.Array,
|
|
382
|
+
dimensions: Dimensions,
|
|
383
|
+
roi: Roi | RoiPixels,
|
|
384
|
+
pixel_size: PixelSize | None = None,
|
|
385
|
+
axes_order: Sequence[str] | None = None,
|
|
386
|
+
transforms: Sequence[TransformProtocol] | None = None,
|
|
387
|
+
slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
388
|
+
remove_channel_selection: bool = False,
|
|
389
|
+
) -> Callable[[], np.ndarray]:
|
|
390
|
+
"""Prepare slice kwargs for setting an array."""
|
|
391
|
+
input_slice_kwargs = roi_to_slicing_dict(
|
|
392
|
+
roi=roi,
|
|
393
|
+
dimensions=dimensions,
|
|
394
|
+
pixel_size=pixel_size,
|
|
395
|
+
slicing_dict=slicing_dict,
|
|
396
|
+
)
|
|
397
|
+
return build_numpy_getter(
|
|
398
|
+
zarr_array=zarr_array,
|
|
399
|
+
dimensions=dimensions,
|
|
400
|
+
axes_order=axes_order,
|
|
401
|
+
transforms=transforms,
|
|
402
|
+
slicing_dict=input_slice_kwargs,
|
|
403
|
+
remove_channel_selection=remove_channel_selection,
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def build_roi_numpy_setter(
|
|
408
|
+
zarr_array: zarr.Array,
|
|
409
|
+
dimensions: Dimensions,
|
|
410
|
+
roi: Roi | RoiPixels,
|
|
411
|
+
pixel_size: PixelSize | None = None,
|
|
412
|
+
axes_order: Sequence[str] | None = None,
|
|
413
|
+
transforms: Sequence[TransformProtocol] | None = None,
|
|
414
|
+
slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
415
|
+
) -> Callable[[np.ndarray], None]:
|
|
416
|
+
"""Prepare slice kwargs for setting an array."""
|
|
417
|
+
input_slice_kwargs = roi_to_slicing_dict(
|
|
418
|
+
roi=roi,
|
|
419
|
+
dimensions=dimensions,
|
|
420
|
+
pixel_size=pixel_size,
|
|
421
|
+
slicing_dict=slicing_dict,
|
|
422
|
+
)
|
|
423
|
+
return build_numpy_setter(
|
|
424
|
+
zarr_array=zarr_array,
|
|
425
|
+
dimensions=dimensions,
|
|
426
|
+
axes_order=axes_order,
|
|
427
|
+
transforms=transforms,
|
|
428
|
+
slicing_dict=input_slice_kwargs,
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
def build_roi_dask_getter(
|
|
433
|
+
zarr_array: zarr.Array,
|
|
434
|
+
dimensions: Dimensions,
|
|
435
|
+
roi: Roi | RoiPixels,
|
|
436
|
+
pixel_size: PixelSize | None = None,
|
|
437
|
+
axes_order: Sequence[str] | None = None,
|
|
438
|
+
transforms: Sequence[TransformProtocol] | None = None,
|
|
439
|
+
slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
440
|
+
remove_channel_selection: bool = False,
|
|
441
|
+
) -> Callable[[], da.Array]:
|
|
442
|
+
"""Prepare slice kwargs for getting an array."""
|
|
443
|
+
input_slice_kwargs = roi_to_slicing_dict(
|
|
444
|
+
roi=roi,
|
|
445
|
+
dimensions=dimensions,
|
|
446
|
+
pixel_size=pixel_size,
|
|
447
|
+
slicing_dict=slicing_dict,
|
|
448
|
+
)
|
|
449
|
+
return build_dask_getter(
|
|
450
|
+
zarr_array=zarr_array,
|
|
451
|
+
dimensions=dimensions,
|
|
452
|
+
axes_order=axes_order,
|
|
453
|
+
transforms=transforms,
|
|
454
|
+
slicing_dict=input_slice_kwargs,
|
|
455
|
+
remove_channel_selection=remove_channel_selection,
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
def build_roi_dask_setter(
|
|
460
|
+
zarr_array: zarr.Array,
|
|
461
|
+
dimensions: Dimensions,
|
|
462
|
+
roi: Roi | RoiPixels,
|
|
463
|
+
pixel_size: PixelSize | None = None,
|
|
464
|
+
axes_order: Sequence[str] | None = None,
|
|
465
|
+
transforms: Sequence[TransformProtocol] | None = None,
|
|
466
|
+
slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
467
|
+
) -> Callable[[da.Array], None]:
|
|
468
|
+
"""Prepare slice kwargs for setting an array."""
|
|
469
|
+
input_slice_kwargs = roi_to_slicing_dict(
|
|
470
|
+
roi=roi,
|
|
471
|
+
dimensions=dimensions,
|
|
472
|
+
pixel_size=pixel_size,
|
|
473
|
+
slicing_dict=slicing_dict,
|
|
474
|
+
)
|
|
475
|
+
return build_dask_setter(
|
|
476
|
+
zarr_array=zarr_array,
|
|
477
|
+
dimensions=dimensions,
|
|
478
|
+
axes_order=axes_order,
|
|
479
|
+
transforms=transforms,
|
|
480
|
+
slicing_dict=input_slice_kwargs,
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
################################################################
|
|
485
|
+
#
|
|
486
|
+
# Masked ROIs array pipes
|
|
487
|
+
#
|
|
488
|
+
################################################################
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def build_roi_masked_numpy_getter(
|
|
492
|
+
*,
|
|
493
|
+
roi: Roi | RoiPixels,
|
|
494
|
+
zarr_array: zarr.Array,
|
|
495
|
+
dimensions: Dimensions,
|
|
496
|
+
pixel_size: PixelSize | None = None,
|
|
497
|
+
label_zarr_array: zarr.Array,
|
|
498
|
+
label_dimensions: Dimensions,
|
|
499
|
+
label_pixel_size: PixelSize | None = None,
|
|
500
|
+
axes_order: Sequence[str] | None = None,
|
|
501
|
+
transforms: Sequence[TransformProtocol] | None = None,
|
|
502
|
+
label_transforms: Sequence[TransformProtocol] | None = None,
|
|
503
|
+
slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
504
|
+
label_slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
505
|
+
fill_value: int | float = 0,
|
|
506
|
+
allow_scaling: bool = True,
|
|
507
|
+
) -> Callable[[], np.ndarray]:
|
|
508
|
+
"""Prepare slice kwargs for getting a masked array."""
|
|
509
|
+
input_slice_kwargs = roi_to_slicing_dict(
|
|
510
|
+
roi=roi,
|
|
511
|
+
dimensions=dimensions,
|
|
512
|
+
pixel_size=pixel_size,
|
|
513
|
+
slicing_dict=slicing_dict,
|
|
514
|
+
)
|
|
515
|
+
label_slice_kwargs = roi_to_slicing_dict(
|
|
516
|
+
roi=roi,
|
|
517
|
+
dimensions=label_dimensions,
|
|
518
|
+
pixel_size=label_pixel_size,
|
|
519
|
+
slicing_dict=label_slicing_dict,
|
|
520
|
+
)
|
|
521
|
+
return build_masked_numpy_getter(
|
|
522
|
+
zarr_array=zarr_array,
|
|
523
|
+
dimensions=dimensions,
|
|
524
|
+
label_zarr_array=label_zarr_array,
|
|
525
|
+
label_dimensions=label_dimensions,
|
|
526
|
+
label_id=roi.label,
|
|
527
|
+
axes_order=axes_order,
|
|
528
|
+
transforms=transforms,
|
|
529
|
+
label_transforms=label_transforms,
|
|
530
|
+
slicing_dict=input_slice_kwargs,
|
|
531
|
+
label_slicing_dict=label_slice_kwargs,
|
|
532
|
+
fill_value=fill_value,
|
|
533
|
+
allow_scaling=allow_scaling,
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
def build_roi_masked_numpy_setter(
|
|
538
|
+
*,
|
|
539
|
+
roi: Roi | RoiPixels,
|
|
540
|
+
zarr_array: zarr.Array,
|
|
541
|
+
dimensions: Dimensions,
|
|
542
|
+
pixel_size: PixelSize | None = None,
|
|
543
|
+
label_zarr_array: zarr.Array,
|
|
544
|
+
label_dimensions: Dimensions,
|
|
545
|
+
label_pixel_size: PixelSize | None = None,
|
|
546
|
+
axes_order: Sequence[str] | None = None,
|
|
547
|
+
transforms: Sequence[TransformProtocol] | None = None,
|
|
548
|
+
label_transforms: Sequence[TransformProtocol] | None = None,
|
|
549
|
+
slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
550
|
+
label_slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
551
|
+
allow_scaling: bool = True,
|
|
552
|
+
) -> Callable[[np.ndarray], None]:
|
|
553
|
+
"""Prepare slice kwargs for setting a masked array."""
|
|
554
|
+
input_slice_kwargs = roi_to_slicing_dict(
|
|
555
|
+
roi=roi,
|
|
556
|
+
dimensions=dimensions,
|
|
557
|
+
pixel_size=pixel_size,
|
|
558
|
+
slicing_dict=slicing_dict,
|
|
559
|
+
)
|
|
560
|
+
label_slice_kwargs = roi_to_slicing_dict(
|
|
561
|
+
roi=roi,
|
|
562
|
+
dimensions=label_dimensions,
|
|
563
|
+
pixel_size=label_pixel_size,
|
|
564
|
+
slicing_dict=label_slicing_dict,
|
|
565
|
+
)
|
|
566
|
+
return build_masked_numpy_setter(
|
|
567
|
+
zarr_array=zarr_array,
|
|
568
|
+
dimensions=dimensions,
|
|
569
|
+
label_zarr_array=label_zarr_array,
|
|
570
|
+
label_dimensions=label_dimensions,
|
|
571
|
+
label_id=roi.label,
|
|
572
|
+
axes_order=axes_order,
|
|
573
|
+
transforms=transforms,
|
|
574
|
+
label_transforms=label_transforms,
|
|
575
|
+
slicing_dict=input_slice_kwargs,
|
|
576
|
+
label_slicing_dict=label_slice_kwargs,
|
|
577
|
+
allow_scaling=allow_scaling,
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
def build_roi_masked_dask_getter(
|
|
582
|
+
*,
|
|
583
|
+
roi: Roi | RoiPixels,
|
|
584
|
+
zarr_array: zarr.Array,
|
|
585
|
+
dimensions: Dimensions,
|
|
586
|
+
pixel_size: PixelSize | None = None,
|
|
587
|
+
label_zarr_array: zarr.Array,
|
|
588
|
+
label_dimensions: Dimensions,
|
|
589
|
+
label_pixel_size: PixelSize | None = None,
|
|
590
|
+
axes_order: Sequence[str] | None = None,
|
|
591
|
+
transforms: Sequence[TransformProtocol] | None = None,
|
|
592
|
+
label_transforms: Sequence[TransformProtocol] | None = None,
|
|
593
|
+
slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
594
|
+
label_slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
595
|
+
allow_scaling: bool = True,
|
|
596
|
+
) -> Callable[[], da.Array]:
|
|
597
|
+
"""Prepare slice kwargs for getting a masked array."""
|
|
598
|
+
input_slice_kwargs = roi_to_slicing_dict(
|
|
599
|
+
roi=roi,
|
|
600
|
+
dimensions=dimensions,
|
|
601
|
+
pixel_size=pixel_size,
|
|
602
|
+
slicing_dict=slicing_dict,
|
|
603
|
+
)
|
|
604
|
+
label_slice_kwargs = roi_to_slicing_dict(
|
|
605
|
+
roi=roi,
|
|
606
|
+
dimensions=label_dimensions,
|
|
607
|
+
pixel_size=label_pixel_size,
|
|
608
|
+
slicing_dict=label_slicing_dict,
|
|
609
|
+
)
|
|
610
|
+
return build_masked_dask_getter(
|
|
611
|
+
zarr_array=zarr_array,
|
|
612
|
+
dimensions=dimensions,
|
|
613
|
+
label_zarr_array=label_zarr_array,
|
|
614
|
+
label_dimensions=label_dimensions,
|
|
615
|
+
label_id=roi.label,
|
|
616
|
+
axes_order=axes_order,
|
|
617
|
+
transforms=transforms,
|
|
618
|
+
label_transforms=label_transforms,
|
|
619
|
+
slicing_dict=input_slice_kwargs,
|
|
620
|
+
label_slicing_dict=label_slice_kwargs,
|
|
621
|
+
allow_scaling=allow_scaling,
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
def build_roi_masked_dask_setter(
|
|
626
|
+
*,
|
|
627
|
+
roi: Roi | RoiPixels,
|
|
628
|
+
zarr_array: zarr.Array,
|
|
629
|
+
dimensions: Dimensions,
|
|
630
|
+
pixel_size: PixelSize | None = None,
|
|
631
|
+
label_zarr_array: zarr.Array,
|
|
632
|
+
label_dimensions: Dimensions,
|
|
633
|
+
label_pixel_size: PixelSize | None = None,
|
|
634
|
+
axes_order: Sequence[str] | None = None,
|
|
635
|
+
transforms: Sequence[TransformProtocol] | None = None,
|
|
636
|
+
label_transforms: Sequence[TransformProtocol] | None = None,
|
|
637
|
+
slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
638
|
+
label_slicing_dict: dict[str, SlicingInputType] | None = None,
|
|
639
|
+
allow_scaling: bool = True,
|
|
640
|
+
) -> Callable[[da.Array], None]:
|
|
641
|
+
"""Prepare slice kwargs for setting a masked array."""
|
|
642
|
+
input_slice_kwargs = roi_to_slicing_dict(
|
|
643
|
+
roi=roi,
|
|
644
|
+
dimensions=dimensions,
|
|
645
|
+
pixel_size=pixel_size,
|
|
646
|
+
slicing_dict=slicing_dict,
|
|
647
|
+
)
|
|
648
|
+
label_slice_kwargs = roi_to_slicing_dict(
|
|
649
|
+
roi=roi,
|
|
650
|
+
dimensions=label_dimensions,
|
|
651
|
+
pixel_size=label_pixel_size,
|
|
652
|
+
slicing_dict=label_slicing_dict,
|
|
653
|
+
)
|
|
654
|
+
return build_masked_dask_setter(
|
|
655
|
+
zarr_array=zarr_array,
|
|
656
|
+
dimensions=dimensions,
|
|
657
|
+
label_zarr_array=label_zarr_array,
|
|
658
|
+
label_dimensions=label_dimensions,
|
|
659
|
+
label_id=roi.label,
|
|
660
|
+
axes_order=axes_order,
|
|
661
|
+
transforms=transforms,
|
|
662
|
+
label_transforms=label_transforms,
|
|
663
|
+
slicing_dict=input_slice_kwargs,
|
|
664
|
+
label_slicing_dict=label_slice_kwargs,
|
|
665
|
+
allow_scaling=allow_scaling,
|
|
666
|
+
)
|