ngio 0.4.0a3__py3-none-any.whl → 0.4.0b1__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 +1 -2
- ngio/common/__init__.py +2 -51
- ngio/common/_dimensions.py +253 -74
- ngio/common/_pyramid.py +42 -23
- ngio/common/_roi.py +49 -413
- ngio/common/_zoom.py +32 -7
- ngio/experimental/iterators/__init__.py +0 -2
- ngio/experimental/iterators/_abstract_iterator.py +246 -26
- ngio/experimental/iterators/_feature.py +90 -52
- ngio/experimental/iterators/_image_processing.py +24 -63
- ngio/experimental/iterators/_mappers.py +48 -0
- ngio/experimental/iterators/_rois_utils.py +4 -4
- ngio/experimental/iterators/_segmentation.py +38 -85
- ngio/images/_abstract_image.py +192 -95
- ngio/images/_create.py +16 -0
- ngio/images/_create_synt_container.py +10 -0
- ngio/images/_image.py +35 -9
- ngio/images/_label.py +26 -3
- ngio/images/_masked_image.py +45 -61
- ngio/images/_ome_zarr_container.py +33 -0
- ngio/io_pipes/__init__.py +75 -0
- ngio/io_pipes/_io_pipes.py +361 -0
- ngio/io_pipes/_io_pipes_masked.py +488 -0
- ngio/io_pipes/_io_pipes_roi.py +152 -0
- ngio/io_pipes/_io_pipes_types.py +56 -0
- ngio/io_pipes/_match_shape.py +376 -0
- ngio/io_pipes/_ops_axes.py +344 -0
- ngio/io_pipes/_ops_slices.py +446 -0
- ngio/io_pipes/_ops_slices_utils.py +196 -0
- ngio/io_pipes/_ops_transforms.py +104 -0
- ngio/io_pipes/_zoom_transform.py +175 -0
- ngio/ome_zarr_meta/__init__.py +4 -2
- ngio/ome_zarr_meta/ngio_specs/__init__.py +4 -4
- ngio/ome_zarr_meta/ngio_specs/_axes.py +129 -141
- ngio/ome_zarr_meta/ngio_specs/_dataset.py +47 -121
- ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +30 -22
- ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +17 -1
- ngio/ome_zarr_meta/v04/_v04_spec_utils.py +33 -30
- ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
- ngio/resources/__init__.py +1 -0
- ngio/resources/resource_model.py +1 -0
- ngio/{common/transforms → transforms}/__init__.py +1 -1
- ngio/transforms/_zoom.py +19 -0
- ngio/utils/_datasets.py +5 -0
- ngio/utils/_zarr_utils.py +5 -1
- {ngio-0.4.0a3.dist-info → ngio-0.4.0b1.dist-info}/METADATA +1 -1
- ngio-0.4.0b1.dist-info/RECORD +85 -0
- ngio/common/_array_io_pipes.py +0 -554
- ngio/common/_array_io_utils.py +0 -508
- ngio/common/transforms/_label.py +0 -12
- ngio/common/transforms/_zoom.py +0 -109
- ngio-0.4.0a3.dist-info/RECORD +0 -76
- {ngio-0.4.0a3.dist-info → ngio-0.4.0b1.dist-info}/WHEEL +0 -0
- {ngio-0.4.0a3.dist-info → ngio-0.4.0b1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Mappers for iterators.
|
|
2
|
+
|
|
3
|
+
Mappers are classes that can be passed to the `map` method of iterators to
|
|
4
|
+
transform the items yielded by the iterator.
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from collections.abc import Callable, Iterable
|
|
9
|
+
from typing import Generic, Protocol, TypeVar
|
|
10
|
+
|
|
11
|
+
from ngio.io_pipes._io_pipes_types import DataGetterProtocol, DataSetterProtocol
|
|
12
|
+
from ngio.utils import NgioValueError
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MapperProtocol(Protocol[T]):
|
|
18
|
+
"""Protocol for mappers."""
|
|
19
|
+
|
|
20
|
+
def __call__(
|
|
21
|
+
self,
|
|
22
|
+
func: Callable[[T], T],
|
|
23
|
+
getters: Iterable[DataGetterProtocol[T]],
|
|
24
|
+
setters: Iterable[DataSetterProtocol[T] | None],
|
|
25
|
+
) -> None:
|
|
26
|
+
"""Map an item to another item."""
|
|
27
|
+
...
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class BasicMapper(Generic[T]):
|
|
31
|
+
"""A basic mapper that simply applies a function to the data."""
|
|
32
|
+
|
|
33
|
+
def __call__(
|
|
34
|
+
self,
|
|
35
|
+
func: Callable[[T], T],
|
|
36
|
+
getters: Iterable[DataGetterProtocol[T]],
|
|
37
|
+
setters: Iterable[DataSetterProtocol[T] | None],
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Map an item to another item."""
|
|
40
|
+
for getter, setter in zip(getters, setters, strict=True):
|
|
41
|
+
data = getter()
|
|
42
|
+
data = func(data)
|
|
43
|
+
if setter is None:
|
|
44
|
+
raise NgioValueError(
|
|
45
|
+
"Error in BasicMapper: setter is None, "
|
|
46
|
+
"this iterator is read-only, mapping is not possible."
|
|
47
|
+
)
|
|
48
|
+
setter(data)
|
|
@@ -100,10 +100,10 @@ def by_chunks(
|
|
|
100
100
|
) -> list[Roi]:
|
|
101
101
|
"""This method is a placeholder for chunked processing."""
|
|
102
102
|
chunk_size = ref_image.chunks
|
|
103
|
-
t_axis = ref_image.
|
|
104
|
-
z_axis = ref_image.
|
|
105
|
-
y_axis = ref_image.
|
|
106
|
-
x_axis = ref_image.
|
|
103
|
+
t_axis = ref_image.axes_handler.get_index("t")
|
|
104
|
+
z_axis = ref_image.axes_handler.get_index("z")
|
|
105
|
+
y_axis = ref_image.axes_handler.get_index("y")
|
|
106
|
+
x_axis = ref_image.axes_handler.get_index("x")
|
|
107
107
|
|
|
108
108
|
size_x = chunk_size[x_axis] if x_axis is not None else None
|
|
109
109
|
size_y = chunk_size[y_axis] if y_axis is not None else None
|
|
@@ -1,20 +1,9 @@
|
|
|
1
|
-
from collections.abc import
|
|
1
|
+
from collections.abc import Sequence
|
|
2
2
|
|
|
3
3
|
import dask.array as da
|
|
4
4
|
import numpy as np
|
|
5
5
|
|
|
6
|
-
from ngio.common import
|
|
7
|
-
Roi,
|
|
8
|
-
TransformProtocol,
|
|
9
|
-
build_roi_dask_getter,
|
|
10
|
-
build_roi_dask_setter,
|
|
11
|
-
build_roi_masked_dask_getter,
|
|
12
|
-
build_roi_masked_dask_setter,
|
|
13
|
-
build_roi_masked_numpy_getter,
|
|
14
|
-
build_roi_masked_numpy_setter,
|
|
15
|
-
build_roi_numpy_getter,
|
|
16
|
-
build_roi_numpy_setter,
|
|
17
|
-
)
|
|
6
|
+
from ngio.common import Roi
|
|
18
7
|
from ngio.experimental.iterators._abstract_iterator import AbstractIteratorBuilder
|
|
19
8
|
from ngio.images import Image, Label
|
|
20
9
|
from ngio.images._image import (
|
|
@@ -22,10 +11,21 @@ from ngio.images._image import (
|
|
|
22
11
|
add_channel_selection_to_slicing_dict,
|
|
23
12
|
)
|
|
24
13
|
from ngio.images._masked_image import MaskedImage
|
|
25
|
-
from ngio.
|
|
14
|
+
from ngio.io_pipes import (
|
|
15
|
+
DaskGetterMasked,
|
|
16
|
+
DaskRoiGetter,
|
|
17
|
+
DaskRoiSetter,
|
|
18
|
+
DaskSetterMasked,
|
|
19
|
+
NumpyGetterMasked,
|
|
20
|
+
NumpyRoiGetter,
|
|
21
|
+
NumpyRoiSetter,
|
|
22
|
+
NumpySetterMasked,
|
|
23
|
+
TransformProtocol,
|
|
24
|
+
)
|
|
25
|
+
from ngio.io_pipes._io_pipes_types import DataGetterProtocol, DataSetterProtocol
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
class SegmentationIterator(AbstractIteratorBuilder):
|
|
28
|
+
class SegmentationIterator(AbstractIteratorBuilder[np.ndarray, da.Array]):
|
|
29
29
|
"""Base class for iterators over ROIs."""
|
|
30
30
|
|
|
31
31
|
def __init__(
|
|
@@ -66,12 +66,7 @@ class SegmentationIterator(AbstractIteratorBuilder):
|
|
|
66
66
|
self._input_transforms = input_transforms
|
|
67
67
|
self._output_transforms = output_transforms
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
if not self._input.dimensions.is_compatible_with(self._output.dimensions):
|
|
71
|
-
raise NgioValidationError(
|
|
72
|
-
"Input image and output label have incompatible dimensions. "
|
|
73
|
-
f"Input: {self._input.dimensions}, Output: {self._output.dimensions}."
|
|
74
|
-
)
|
|
69
|
+
self._input.require_dimensions_match(self._output, allow_singleton=False)
|
|
75
70
|
|
|
76
71
|
def get_init_kwargs(self) -> dict:
|
|
77
72
|
"""Return the initialization arguments for the iterator."""
|
|
@@ -84,83 +79,49 @@ class SegmentationIterator(AbstractIteratorBuilder):
|
|
|
84
79
|
"output_transforms": self._output_transforms,
|
|
85
80
|
}
|
|
86
81
|
|
|
87
|
-
def build_numpy_getter(self, roi: Roi):
|
|
88
|
-
return
|
|
82
|
+
def build_numpy_getter(self, roi: Roi) -> DataGetterProtocol[np.ndarray]:
|
|
83
|
+
return NumpyRoiGetter(
|
|
89
84
|
zarr_array=self._input.zarr_array,
|
|
90
85
|
dimensions=self._input.dimensions,
|
|
86
|
+
roi=roi,
|
|
91
87
|
axes_order=self._axes_order,
|
|
92
88
|
transforms=self._input_transforms,
|
|
93
|
-
pixel_size=self._input.pixel_size,
|
|
94
|
-
roi=roi,
|
|
95
89
|
slicing_dict=self._input_slicing_kwargs,
|
|
96
90
|
)
|
|
97
91
|
|
|
98
|
-
def build_numpy_setter(self, roi: Roi):
|
|
99
|
-
return
|
|
92
|
+
def build_numpy_setter(self, roi: Roi) -> DataSetterProtocol[np.ndarray]:
|
|
93
|
+
return NumpyRoiSetter(
|
|
100
94
|
zarr_array=self._output.zarr_array,
|
|
101
95
|
dimensions=self._output.dimensions,
|
|
96
|
+
roi=roi,
|
|
102
97
|
axes_order=self._axes_order,
|
|
103
98
|
transforms=self._output_transforms,
|
|
104
|
-
pixel_size=self._output.pixel_size,
|
|
105
|
-
roi=roi,
|
|
106
99
|
remove_channel_selection=True,
|
|
107
100
|
)
|
|
108
101
|
|
|
109
|
-
def build_dask_getter(self, roi: Roi):
|
|
110
|
-
return
|
|
102
|
+
def build_dask_getter(self, roi: Roi) -> DataGetterProtocol[da.Array]:
|
|
103
|
+
return DaskRoiGetter(
|
|
111
104
|
zarr_array=self._input.zarr_array,
|
|
112
105
|
dimensions=self._input.dimensions,
|
|
106
|
+
roi=roi,
|
|
113
107
|
axes_order=self._axes_order,
|
|
114
108
|
transforms=self._input_transforms,
|
|
115
|
-
pixel_size=self._input.pixel_size,
|
|
116
|
-
roi=roi,
|
|
117
109
|
slicing_dict=self._input_slicing_kwargs,
|
|
118
110
|
)
|
|
119
111
|
|
|
120
|
-
def build_dask_setter(self, roi: Roi):
|
|
121
|
-
return
|
|
112
|
+
def build_dask_setter(self, roi: Roi) -> DataSetterProtocol[da.Array]:
|
|
113
|
+
return DaskRoiSetter(
|
|
122
114
|
zarr_array=self._output.zarr_array,
|
|
123
115
|
dimensions=self._output.dimensions,
|
|
116
|
+
roi=roi,
|
|
124
117
|
axes_order=self._axes_order,
|
|
125
118
|
transforms=self._output_transforms,
|
|
126
|
-
pixel_size=self._output.pixel_size,
|
|
127
|
-
roi=roi,
|
|
128
119
|
remove_channel_selection=True,
|
|
129
120
|
)
|
|
130
121
|
|
|
131
122
|
def post_consolidate(self):
|
|
132
123
|
self._output.consolidate()
|
|
133
124
|
|
|
134
|
-
def iter_as_numpy(
|
|
135
|
-
self,
|
|
136
|
-
) -> Generator[tuple[np.ndarray, Callable[[np.ndarray], None]]]:
|
|
137
|
-
"""Create an iterator over the pixels of the ROIs as Dask arrays.
|
|
138
|
-
|
|
139
|
-
Returns:
|
|
140
|
-
Generator[tuple[da.Array, DaskWriter]]: An iterator the input
|
|
141
|
-
image as Dask arrays and a writer to write the output
|
|
142
|
-
to the label image.
|
|
143
|
-
"""
|
|
144
|
-
return super().iter_as_numpy()
|
|
145
|
-
|
|
146
|
-
def map_as_numpy(self, func: Callable[[np.ndarray], np.ndarray]) -> None:
|
|
147
|
-
"""Apply a transformation function to the ROI pixels."""
|
|
148
|
-
return super().map_as_numpy(func)
|
|
149
|
-
|
|
150
|
-
def iter_as_dask(self) -> Generator[tuple[da.Array, Callable[[da.Array], None]]]:
|
|
151
|
-
"""Create an iterator over the pixels of the ROIs as Dask arrays.
|
|
152
|
-
|
|
153
|
-
Returns:
|
|
154
|
-
Generator[tuple[da.Array, DaskWriter]]: An iterator the input
|
|
155
|
-
image as Dask arrays and a writer to write the output
|
|
156
|
-
to the label image.
|
|
157
|
-
"""
|
|
158
|
-
return super().iter_as_dask()
|
|
159
|
-
|
|
160
|
-
def map_as_dask(self, func: Callable[[da.Array], da.Array]) -> None:
|
|
161
|
-
"""Apply a transformation function to the ROI pixels."""
|
|
162
|
-
return super().map_as_dask(func)
|
|
163
|
-
|
|
164
125
|
|
|
165
126
|
class MaskedSegmentationIterator(SegmentationIterator):
|
|
166
127
|
"""Base class for iterators over ROIs."""
|
|
@@ -205,11 +166,11 @@ class MaskedSegmentationIterator(SegmentationIterator):
|
|
|
205
166
|
self._output_transforms = output_transforms
|
|
206
167
|
|
|
207
168
|
# Check compatibility between input and output images
|
|
208
|
-
if not self._input.dimensions.is_compatible_with(self._output.dimensions):
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
169
|
+
# if not self._input.dimensions.is_compatible_with(self._output.dimensions):
|
|
170
|
+
# raise NgioValidationError(
|
|
171
|
+
# "Input image and output label have incompatible dimensions. "
|
|
172
|
+
# f"Input: {self._input.dimensions}, Output: {self._output.dimensions}."
|
|
173
|
+
# )
|
|
213
174
|
|
|
214
175
|
def get_init_kwargs(self) -> dict:
|
|
215
176
|
"""Return the initialization arguments for the iterator."""
|
|
@@ -223,58 +184,50 @@ class MaskedSegmentationIterator(SegmentationIterator):
|
|
|
223
184
|
}
|
|
224
185
|
|
|
225
186
|
def build_numpy_getter(self, roi: Roi):
|
|
226
|
-
return
|
|
227
|
-
roi=roi,
|
|
187
|
+
return NumpyGetterMasked(
|
|
228
188
|
zarr_array=self._input.zarr_array,
|
|
229
189
|
dimensions=self._input.dimensions,
|
|
190
|
+
roi=roi,
|
|
230
191
|
label_zarr_array=self._input._label.zarr_array,
|
|
231
192
|
label_dimensions=self._input._label.dimensions,
|
|
232
|
-
label_pixel_size=self._input._label.pixel_size,
|
|
233
193
|
axes_order=self._axes_order,
|
|
234
194
|
transforms=self._input_transforms,
|
|
235
|
-
pixel_size=self._input.pixel_size,
|
|
236
195
|
slicing_dict=self._input_slicing_kwargs,
|
|
237
196
|
)
|
|
238
197
|
|
|
239
198
|
def build_numpy_setter(self, roi: Roi):
|
|
240
|
-
return
|
|
199
|
+
return NumpySetterMasked(
|
|
241
200
|
roi=roi,
|
|
242
201
|
zarr_array=self._output.zarr_array,
|
|
243
202
|
dimensions=self._output.dimensions,
|
|
244
203
|
label_zarr_array=self._input._label.zarr_array,
|
|
245
204
|
label_dimensions=self._input._label.dimensions,
|
|
246
|
-
label_pixel_size=self._input._label.pixel_size,
|
|
247
205
|
axes_order=self._axes_order,
|
|
248
206
|
transforms=self._output_transforms,
|
|
249
|
-
pixel_size=self._output.pixel_size,
|
|
250
207
|
remove_channel_selection=True,
|
|
251
208
|
)
|
|
252
209
|
|
|
253
210
|
def build_dask_getter(self, roi: Roi):
|
|
254
|
-
return
|
|
211
|
+
return DaskGetterMasked(
|
|
255
212
|
roi=roi,
|
|
256
213
|
zarr_array=self._input.zarr_array,
|
|
257
214
|
dimensions=self._input.dimensions,
|
|
258
215
|
label_zarr_array=self._input._label.zarr_array,
|
|
259
216
|
label_dimensions=self._input._label.dimensions,
|
|
260
|
-
label_pixel_size=self._input._label.pixel_size,
|
|
261
217
|
axes_order=self._axes_order,
|
|
262
218
|
transforms=self._input_transforms,
|
|
263
|
-
pixel_size=self._input.pixel_size,
|
|
264
219
|
slicing_dict=self._input_slicing_kwargs,
|
|
265
220
|
)
|
|
266
221
|
|
|
267
222
|
def build_dask_setter(self, roi: Roi):
|
|
268
|
-
return
|
|
223
|
+
return DaskSetterMasked(
|
|
269
224
|
roi=roi,
|
|
270
225
|
zarr_array=self._output.zarr_array,
|
|
271
226
|
dimensions=self._output.dimensions,
|
|
272
227
|
label_zarr_array=self._input._label.zarr_array,
|
|
273
228
|
label_dimensions=self._input._label.dimensions,
|
|
274
|
-
label_pixel_size=self._input._label.pixel_size,
|
|
275
229
|
axes_order=self._axes_order,
|
|
276
230
|
transforms=self._output_transforms,
|
|
277
|
-
pixel_size=self._output.pixel_size,
|
|
278
231
|
remove_channel_selection=True,
|
|
279
232
|
)
|
|
280
233
|
|