ngio 0.4.0a2__py3-none-any.whl → 0.4.0a4__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 +223 -64
- ngio/common/_pyramid.py +42 -23
- ngio/common/_roi.py +94 -418
- ngio/common/_zoom.py +32 -7
- ngio/experimental/iterators/_abstract_iterator.py +2 -2
- ngio/experimental/iterators/_feature.py +10 -15
- ngio/experimental/iterators/_image_processing.py +18 -28
- ngio/experimental/iterators/_rois_utils.py +6 -6
- ngio/experimental/iterators/_segmentation.py +38 -54
- ngio/images/_abstract_image.py +136 -94
- ngio/images/_create.py +16 -0
- ngio/images/_create_synt_container.py +10 -0
- ngio/images/_image.py +33 -9
- ngio/images/_label.py +24 -3
- ngio/images/_masked_image.py +60 -81
- ngio/images/_ome_zarr_container.py +34 -1
- ngio/io_pipes/__init__.py +49 -0
- ngio/io_pipes/_io_pipes.py +286 -0
- ngio/io_pipes/_io_pipes_masked.py +481 -0
- ngio/io_pipes/_io_pipes_roi.py +143 -0
- ngio/io_pipes/_io_pipes_utils.py +299 -0
- ngio/io_pipes/_match_shape.py +376 -0
- ngio/io_pipes/_ops_axes.py +146 -0
- ngio/io_pipes/_ops_slices.py +218 -0
- ngio/io_pipes/_ops_transforms.py +104 -0
- ngio/io_pipes/_zoom_transform.py +175 -0
- ngio/ome_zarr_meta/__init__.py +6 -2
- ngio/ome_zarr_meta/ngio_specs/__init__.py +6 -4
- ngio/ome_zarr_meta/ngio_specs/_axes.py +182 -70
- 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/tables/v1/_roi_table.py +11 -3
- ngio/{common/transforms → transforms}/__init__.py +1 -1
- ngio/transforms/_zoom.py +19 -0
- ngio/utils/_zarr_utils.py +5 -1
- {ngio-0.4.0a2.dist-info → ngio-0.4.0a4.dist-info}/METADATA +1 -1
- ngio-0.4.0a4.dist-info/RECORD +83 -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.0a2.dist-info/RECORD +0 -76
- {ngio-0.4.0a2.dist-info → ngio-0.4.0a4.dist-info}/WHEEL +0 -0
- {ngio-0.4.0a2.dist-info → ngio-0.4.0a4.dist-info}/licenses/LICENSE +0 -0
ngio/common/_zoom.py
CHANGED
|
@@ -7,6 +7,19 @@ from scipy.ndimage import zoom as scipy_zoom
|
|
|
7
7
|
|
|
8
8
|
from ngio.utils import NgioValueError
|
|
9
9
|
|
|
10
|
+
InterpolationOrder = Literal["nearest", "linear", "cubic"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def order_to_int(order: InterpolationOrder | Literal[0, 1, 2]) -> Literal[0, 1, 2]:
|
|
14
|
+
if order == "nearest" or order == 0:
|
|
15
|
+
return 0
|
|
16
|
+
elif order == "linear" or order == 1:
|
|
17
|
+
return 1
|
|
18
|
+
elif order == "cubic" or order == 2:
|
|
19
|
+
return 2
|
|
20
|
+
else:
|
|
21
|
+
raise NgioValueError(f"Invalid order: {order}")
|
|
22
|
+
|
|
10
23
|
|
|
11
24
|
def _stacked_zoom(x, zoom_y, zoom_x, order=1, mode="grid-constant", grid_mode=True):
|
|
12
25
|
*rest, yshape, xshape = x.shape
|
|
@@ -32,6 +45,10 @@ def fast_zoom(x, zoom, order=1, mode="grid-constant", grid_mode=True, auto_stack
|
|
|
32
45
|
it stacks the first dimensions to call zoom only on the last two.
|
|
33
46
|
"""
|
|
34
47
|
mask = np.isclose(x.shape, 1)
|
|
48
|
+
# Always keep the last two dimensions
|
|
49
|
+
# To avoid issues with singleton x or y dimensions
|
|
50
|
+
mask[-1] = False
|
|
51
|
+
mask[-2] = False
|
|
35
52
|
zoom = np.array(zoom)
|
|
36
53
|
singletons = tuple(np.where(mask)[0])
|
|
37
54
|
xs = np.squeeze(x, axis=singletons)
|
|
@@ -71,7 +88,7 @@ def _zoom_inputs_check(
|
|
|
71
88
|
_target_shape = target_shape
|
|
72
89
|
else:
|
|
73
90
|
_scale = np.array(scale)
|
|
74
|
-
_target_shape = tuple(np.array(source_array.shape) * scale)
|
|
91
|
+
_target_shape = tuple(map(int, np.round(np.array(source_array.shape) * scale)))
|
|
75
92
|
|
|
76
93
|
if len(_scale) != source_array.ndim:
|
|
77
94
|
raise NgioValueError(
|
|
@@ -86,7 +103,7 @@ def dask_zoom(
|
|
|
86
103
|
source_array: da.Array,
|
|
87
104
|
scale: tuple[float | int, ...] | None = None,
|
|
88
105
|
target_shape: tuple[int, ...] | None = None,
|
|
89
|
-
order:
|
|
106
|
+
order: InterpolationOrder = "linear",
|
|
90
107
|
) -> da.Array:
|
|
91
108
|
"""Dask implementation of zooming an array.
|
|
92
109
|
|
|
@@ -96,7 +113,8 @@ def dask_zoom(
|
|
|
96
113
|
source_array (da.Array): The source array to zoom.
|
|
97
114
|
scale (tuple[int, ...] | None): The scale factor to zoom by.
|
|
98
115
|
target_shape (tuple[int, ...], None): The target shape to zoom to.
|
|
99
|
-
order (Literal[
|
|
116
|
+
order (Literal["nearest", "linear", "cubic"]): The order of interpolation.
|
|
117
|
+
Defaults to "linear".
|
|
100
118
|
|
|
101
119
|
Returns:
|
|
102
120
|
da.Array: The zoomed array.
|
|
@@ -105,7 +123,6 @@ def dask_zoom(
|
|
|
105
123
|
# https://github.com/ome/ome-zarr-py/blob/master/ome_zarr/dask_utils.py
|
|
106
124
|
# The module was contributed by Andreas Eisenbarth @aeisenbarth
|
|
107
125
|
# See https://github.com/toloudis/ome-zarr-py/pull/
|
|
108
|
-
|
|
109
126
|
_scale, _target_shape = _zoom_inputs_check(
|
|
110
127
|
source_array=source_array, scale=scale, target_shape=target_shape
|
|
111
128
|
)
|
|
@@ -120,7 +137,11 @@ def dask_zoom(
|
|
|
120
137
|
block_output_shape = tuple(np.ceil(better_source_chunks * _scale).astype(int))
|
|
121
138
|
|
|
122
139
|
zoom_wrapper = partial(
|
|
123
|
-
fast_zoom,
|
|
140
|
+
fast_zoom,
|
|
141
|
+
zoom=_scale,
|
|
142
|
+
order=order_to_int(order),
|
|
143
|
+
mode="grid-constant",
|
|
144
|
+
grid_mode=True,
|
|
124
145
|
)
|
|
125
146
|
|
|
126
147
|
out_array = da.map_blocks(
|
|
@@ -137,7 +158,7 @@ def numpy_zoom(
|
|
|
137
158
|
source_array: np.ndarray,
|
|
138
159
|
scale: tuple[int | float, ...] | None = None,
|
|
139
160
|
target_shape: tuple[int, ...] | None = None,
|
|
140
|
-
order:
|
|
161
|
+
order: InterpolationOrder = "linear",
|
|
141
162
|
) -> np.ndarray:
|
|
142
163
|
"""Numpy implementation of zooming an array.
|
|
143
164
|
|
|
@@ -157,7 +178,11 @@ def numpy_zoom(
|
|
|
157
178
|
)
|
|
158
179
|
|
|
159
180
|
out_array = fast_zoom(
|
|
160
|
-
source_array,
|
|
181
|
+
source_array,
|
|
182
|
+
zoom=_scale,
|
|
183
|
+
order=order_to_int(order),
|
|
184
|
+
mode="grid-constant",
|
|
185
|
+
grid_mode=True,
|
|
161
186
|
)
|
|
162
187
|
assert isinstance(out_array, np.ndarray)
|
|
163
188
|
return out_array
|
|
@@ -156,7 +156,7 @@ class AbstractIteratorBuilder(ABC):
|
|
|
156
156
|
def map_as_numpy(self, func: Callable) -> None:
|
|
157
157
|
"""Apply a transformation function to the ROI pixels."""
|
|
158
158
|
for roi in self.rois:
|
|
159
|
-
data = self.build_numpy_getter(roi)
|
|
159
|
+
data = self.build_numpy_getter(roi)()
|
|
160
160
|
data = func(data)
|
|
161
161
|
self.build_numpy_setter(roi)
|
|
162
162
|
self.post_consolidate()
|
|
@@ -164,7 +164,7 @@ class AbstractIteratorBuilder(ABC):
|
|
|
164
164
|
def map_as_dask(self, func: Callable) -> None:
|
|
165
165
|
"""Apply a transformation function to the ROI pixels."""
|
|
166
166
|
for roi in self.rois:
|
|
167
|
-
data = self.build_dask_getter(roi)
|
|
167
|
+
data = self.build_dask_getter(roi)()
|
|
168
168
|
data = func(data)
|
|
169
169
|
self.build_dask_setter(roi)
|
|
170
170
|
self.post_consolidate()
|
|
@@ -3,18 +3,14 @@ from collections.abc import Callable, Generator, Sequence
|
|
|
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_numpy_getter,
|
|
11
|
-
)
|
|
6
|
+
from ngio.common import Roi
|
|
12
7
|
from ngio.experimental.iterators._abstract_iterator import AbstractIteratorBuilder
|
|
13
8
|
from ngio.images import Image, Label
|
|
14
9
|
from ngio.images._image import (
|
|
15
10
|
ChannelSlicingInputType,
|
|
16
11
|
add_channel_selection_to_slicing_dict,
|
|
17
12
|
)
|
|
13
|
+
from ngio.io_pipes import DaskRoiGetter, NumpyRoiGetter, TransformProtocol
|
|
18
14
|
|
|
19
15
|
|
|
20
16
|
class FeatureExtractorIterator(AbstractIteratorBuilder):
|
|
@@ -47,7 +43,7 @@ class FeatureExtractorIterator(AbstractIteratorBuilder):
|
|
|
47
43
|
self._input = input_image
|
|
48
44
|
self._input_label = input_label
|
|
49
45
|
self._ref_image = input_image
|
|
50
|
-
self._rois = input_image.build_image_roi_table().rois()
|
|
46
|
+
self._rois = input_image.build_image_roi_table(name=None).rois()
|
|
51
47
|
|
|
52
48
|
# Set iteration parameters
|
|
53
49
|
self._input_slicing_kwargs = add_channel_selection_to_slicing_dict(
|
|
@@ -58,6 +54,9 @@ class FeatureExtractorIterator(AbstractIteratorBuilder):
|
|
|
58
54
|
self._input_transforms = input_transforms
|
|
59
55
|
self._label_transforms = label_transforms
|
|
60
56
|
|
|
57
|
+
self._input.require_axes_match(self._input_label)
|
|
58
|
+
self._input.require_can_be_rescaled(self._input_label)
|
|
59
|
+
|
|
61
60
|
def get_init_kwargs(self) -> dict:
|
|
62
61
|
"""Return the initialization arguments for the iterator."""
|
|
63
62
|
return {
|
|
@@ -70,21 +69,19 @@ class FeatureExtractorIterator(AbstractIteratorBuilder):
|
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
def build_numpy_getter(self, roi: Roi):
|
|
73
|
-
data_getter =
|
|
72
|
+
data_getter = NumpyRoiGetter(
|
|
74
73
|
zarr_array=self._input.zarr_array,
|
|
75
74
|
dimensions=self._input.dimensions,
|
|
76
75
|
axes_order=self._axes_order,
|
|
77
76
|
transforms=self._input_transforms,
|
|
78
|
-
pixel_size=self._input.pixel_size,
|
|
79
77
|
roi=roi,
|
|
80
78
|
slicing_dict=self._input_slicing_kwargs,
|
|
81
79
|
)
|
|
82
|
-
label_getter =
|
|
80
|
+
label_getter = NumpyRoiGetter(
|
|
83
81
|
zarr_array=self._input_label.zarr_array,
|
|
84
82
|
dimensions=self._input_label.dimensions,
|
|
85
83
|
axes_order=self._axes_order,
|
|
86
84
|
transforms=self._label_transforms,
|
|
87
|
-
pixel_size=self._input_label.pixel_size,
|
|
88
85
|
roi=roi,
|
|
89
86
|
remove_channel_selection=True,
|
|
90
87
|
)
|
|
@@ -94,21 +91,19 @@ class FeatureExtractorIterator(AbstractIteratorBuilder):
|
|
|
94
91
|
return None
|
|
95
92
|
|
|
96
93
|
def build_dask_getter(self, roi: Roi):
|
|
97
|
-
data_getter =
|
|
94
|
+
data_getter = DaskRoiGetter(
|
|
98
95
|
zarr_array=self._input.zarr_array,
|
|
99
96
|
dimensions=self._input.dimensions,
|
|
100
97
|
axes_order=self._axes_order,
|
|
101
98
|
transforms=self._input_transforms,
|
|
102
|
-
pixel_size=self._input.pixel_size,
|
|
103
99
|
roi=roi,
|
|
104
100
|
slicing_dict=self._input_slicing_kwargs,
|
|
105
101
|
)
|
|
106
|
-
label_getter =
|
|
102
|
+
label_getter = DaskRoiGetter(
|
|
107
103
|
zarr_array=self._input_label.zarr_array,
|
|
108
104
|
dimensions=self._input_label.dimensions,
|
|
109
105
|
axes_order=self._axes_order,
|
|
110
106
|
transforms=self._label_transforms,
|
|
111
|
-
pixel_size=self._input_label.pixel_size,
|
|
112
107
|
roi=roi,
|
|
113
108
|
remove_channel_selection=True,
|
|
114
109
|
)
|
|
@@ -3,21 +3,20 @@ from collections.abc import Callable, Generator, Sequence
|
|
|
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_numpy_getter,
|
|
12
|
-
build_roi_numpy_setter,
|
|
13
|
-
)
|
|
6
|
+
from ngio.common import Roi
|
|
14
7
|
from ngio.experimental.iterators._abstract_iterator import AbstractIteratorBuilder
|
|
15
8
|
from ngio.images import Image
|
|
16
9
|
from ngio.images._image import (
|
|
17
10
|
ChannelSlicingInputType,
|
|
18
11
|
add_channel_selection_to_slicing_dict,
|
|
19
12
|
)
|
|
20
|
-
from ngio.
|
|
13
|
+
from ngio.io_pipes import (
|
|
14
|
+
DaskRoiGetter,
|
|
15
|
+
DaskRoiSetter,
|
|
16
|
+
NumpyRoiGetter,
|
|
17
|
+
NumpyRoiSetter,
|
|
18
|
+
TransformProtocol,
|
|
19
|
+
)
|
|
21
20
|
|
|
22
21
|
|
|
23
22
|
class ImageProcessingIterator(AbstractIteratorBuilder):
|
|
@@ -53,7 +52,7 @@ class ImageProcessingIterator(AbstractIteratorBuilder):
|
|
|
53
52
|
self._input = input_image
|
|
54
53
|
self._output = output_image
|
|
55
54
|
self._ref_image = input_image
|
|
56
|
-
self._rois = input_image.build_image_roi_table().rois()
|
|
55
|
+
self._rois = input_image.build_image_roi_table(name=None).rois()
|
|
57
56
|
|
|
58
57
|
# Set iteration parameters
|
|
59
58
|
self._input_slicing_kwargs = add_channel_selection_to_slicing_dict(
|
|
@@ -72,12 +71,7 @@ class ImageProcessingIterator(AbstractIteratorBuilder):
|
|
|
72
71
|
self._input_transforms = input_transforms
|
|
73
72
|
self._output_transforms = output_transforms
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
if not self._input.dimensions.is_compatible_with(self._output.dimensions):
|
|
77
|
-
raise NgioValidationError(
|
|
78
|
-
"Input image and output label have incompatible dimensions. "
|
|
79
|
-
f"Input: {self._input.dimensions}, Output: {self._output.dimensions}."
|
|
80
|
-
)
|
|
74
|
+
self._input.require_dimensions_match(self._output, allow_singleton=True)
|
|
81
75
|
|
|
82
76
|
def get_init_kwargs(self) -> dict:
|
|
83
77
|
"""Return the initialization arguments for the iterator."""
|
|
@@ -92,46 +86,42 @@ class ImageProcessingIterator(AbstractIteratorBuilder):
|
|
|
92
86
|
}
|
|
93
87
|
|
|
94
88
|
def build_numpy_getter(self, roi: Roi):
|
|
95
|
-
return
|
|
89
|
+
return NumpyRoiGetter(
|
|
96
90
|
zarr_array=self._input.zarr_array,
|
|
97
91
|
dimensions=self._input.dimensions,
|
|
92
|
+
roi=roi,
|
|
98
93
|
axes_order=self._axes_order,
|
|
99
94
|
transforms=self._input_transforms,
|
|
100
|
-
pixel_size=self._input.pixel_size,
|
|
101
|
-
roi=roi,
|
|
102
95
|
slicing_dict=self._input_slicing_kwargs,
|
|
103
96
|
)
|
|
104
97
|
|
|
105
98
|
def build_numpy_setter(self, roi: Roi):
|
|
106
|
-
return
|
|
99
|
+
return NumpyRoiSetter(
|
|
107
100
|
zarr_array=self._output.zarr_array,
|
|
108
101
|
dimensions=self._output.dimensions,
|
|
102
|
+
roi=roi,
|
|
109
103
|
axes_order=self._axes_order,
|
|
110
104
|
transforms=self._output_transforms,
|
|
111
|
-
pixel_size=self._output.pixel_size,
|
|
112
|
-
roi=roi,
|
|
113
105
|
slicing_dict=self._output_slicing_kwargs,
|
|
114
106
|
)
|
|
115
107
|
|
|
116
108
|
def build_dask_getter(self, roi: Roi):
|
|
117
|
-
return
|
|
109
|
+
return DaskRoiGetter(
|
|
118
110
|
zarr_array=self._input.zarr_array,
|
|
119
111
|
dimensions=self._input.dimensions,
|
|
112
|
+
roi=roi,
|
|
120
113
|
axes_order=self._axes_order,
|
|
121
114
|
transforms=self._input_transforms,
|
|
122
|
-
pixel_size=self._input.pixel_size,
|
|
123
|
-
roi=roi,
|
|
124
115
|
slicing_dict=self._input_slicing_kwargs,
|
|
125
116
|
)
|
|
126
117
|
|
|
127
118
|
def build_dask_setter(self, roi: Roi):
|
|
128
|
-
return
|
|
119
|
+
return DaskRoiSetter(
|
|
129
120
|
zarr_array=self._output.zarr_array,
|
|
130
121
|
dimensions=self._output.dimensions,
|
|
122
|
+
roi=roi,
|
|
131
123
|
axes_order=self._axes_order,
|
|
132
124
|
transforms=self._output_transforms,
|
|
133
|
-
pixel_size=self._output.pixel_size,
|
|
134
|
-
roi=roi,
|
|
135
125
|
slicing_dict=self._output_slicing_kwargs,
|
|
136
126
|
)
|
|
137
127
|
|
|
@@ -24,7 +24,7 @@ def grid(
|
|
|
24
24
|
stride_y: int | None = None,
|
|
25
25
|
stride_z: int | None = None,
|
|
26
26
|
stride_t: int | None = None,
|
|
27
|
-
base_name: str =
|
|
27
|
+
base_name: str | None = None,
|
|
28
28
|
) -> list[Roi]:
|
|
29
29
|
"""This method is a placeholder for creating a regular grid of ROIs."""
|
|
30
30
|
t_dim = ref_image.dimensions.get("t", default=1)
|
|
@@ -49,7 +49,7 @@ def grid(
|
|
|
49
49
|
for y in range(0, y_dim, stride_y):
|
|
50
50
|
for x in range(0, x_dim, stride_x):
|
|
51
51
|
roi = RoiPixels(
|
|
52
|
-
name=
|
|
52
|
+
name=base_name,
|
|
53
53
|
x=x,
|
|
54
54
|
y=y,
|
|
55
55
|
z=z,
|
|
@@ -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
|
|
@@ -3,18 +3,7 @@ from collections.abc import Callable, Generator, Sequence
|
|
|
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,7 +11,19 @@ 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
|
+
DataGetter,
|
|
20
|
+
DataSetter,
|
|
21
|
+
NumpyGetterMasked,
|
|
22
|
+
NumpyRoiGetter,
|
|
23
|
+
NumpyRoiSetter,
|
|
24
|
+
NumpySetterMasked,
|
|
25
|
+
TransformProtocol,
|
|
26
|
+
)
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
class SegmentationIterator(AbstractIteratorBuilder):
|
|
@@ -55,7 +56,7 @@ class SegmentationIterator(AbstractIteratorBuilder):
|
|
|
55
56
|
self._input = input_image
|
|
56
57
|
self._output = output_label
|
|
57
58
|
self._ref_image = input_image
|
|
58
|
-
self._rois = input_image.build_image_roi_table().rois()
|
|
59
|
+
self._rois = input_image.build_image_roi_table(name=None).rois()
|
|
59
60
|
|
|
60
61
|
# Set iteration parameters
|
|
61
62
|
self._input_slicing_kwargs = add_channel_selection_to_slicing_dict(
|
|
@@ -66,12 +67,7 @@ class SegmentationIterator(AbstractIteratorBuilder):
|
|
|
66
67
|
self._input_transforms = input_transforms
|
|
67
68
|
self._output_transforms = output_transforms
|
|
68
69
|
|
|
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
|
-
)
|
|
70
|
+
self._input.require_dimensions_match(self._output, allow_singleton=False)
|
|
75
71
|
|
|
76
72
|
def get_init_kwargs(self) -> dict:
|
|
77
73
|
"""Return the initialization arguments for the iterator."""
|
|
@@ -84,47 +80,43 @@ class SegmentationIterator(AbstractIteratorBuilder):
|
|
|
84
80
|
"output_transforms": self._output_transforms,
|
|
85
81
|
}
|
|
86
82
|
|
|
87
|
-
def build_numpy_getter(self, roi: Roi):
|
|
88
|
-
return
|
|
83
|
+
def build_numpy_getter(self, roi: Roi) -> DataGetter[np.ndarray]:
|
|
84
|
+
return NumpyRoiGetter(
|
|
89
85
|
zarr_array=self._input.zarr_array,
|
|
90
86
|
dimensions=self._input.dimensions,
|
|
87
|
+
roi=roi,
|
|
91
88
|
axes_order=self._axes_order,
|
|
92
89
|
transforms=self._input_transforms,
|
|
93
|
-
pixel_size=self._input.pixel_size,
|
|
94
|
-
roi=roi,
|
|
95
90
|
slicing_dict=self._input_slicing_kwargs,
|
|
96
91
|
)
|
|
97
92
|
|
|
98
|
-
def build_numpy_setter(self, roi: Roi):
|
|
99
|
-
return
|
|
93
|
+
def build_numpy_setter(self, roi: Roi) -> DataSetter[np.ndarray]:
|
|
94
|
+
return NumpyRoiSetter(
|
|
100
95
|
zarr_array=self._output.zarr_array,
|
|
101
96
|
dimensions=self._output.dimensions,
|
|
97
|
+
roi=roi,
|
|
102
98
|
axes_order=self._axes_order,
|
|
103
99
|
transforms=self._output_transforms,
|
|
104
|
-
pixel_size=self._output.pixel_size,
|
|
105
|
-
roi=roi,
|
|
106
100
|
remove_channel_selection=True,
|
|
107
101
|
)
|
|
108
102
|
|
|
109
|
-
def build_dask_getter(self, roi: Roi):
|
|
110
|
-
return
|
|
103
|
+
def build_dask_getter(self, roi: Roi) -> DataGetter[da.Array]:
|
|
104
|
+
return DaskRoiGetter(
|
|
111
105
|
zarr_array=self._input.zarr_array,
|
|
112
106
|
dimensions=self._input.dimensions,
|
|
107
|
+
roi=roi,
|
|
113
108
|
axes_order=self._axes_order,
|
|
114
109
|
transforms=self._input_transforms,
|
|
115
|
-
pixel_size=self._input.pixel_size,
|
|
116
|
-
roi=roi,
|
|
117
110
|
slicing_dict=self._input_slicing_kwargs,
|
|
118
111
|
)
|
|
119
112
|
|
|
120
|
-
def build_dask_setter(self, roi: Roi):
|
|
121
|
-
return
|
|
113
|
+
def build_dask_setter(self, roi: Roi) -> DataSetter[da.Array]:
|
|
114
|
+
return DaskRoiSetter(
|
|
122
115
|
zarr_array=self._output.zarr_array,
|
|
123
116
|
dimensions=self._output.dimensions,
|
|
117
|
+
roi=roi,
|
|
124
118
|
axes_order=self._axes_order,
|
|
125
119
|
transforms=self._output_transforms,
|
|
126
|
-
pixel_size=self._output.pixel_size,
|
|
127
|
-
roi=roi,
|
|
128
120
|
remove_channel_selection=True,
|
|
129
121
|
)
|
|
130
122
|
|
|
@@ -205,11 +197,11 @@ class MaskedSegmentationIterator(SegmentationIterator):
|
|
|
205
197
|
self._output_transforms = output_transforms
|
|
206
198
|
|
|
207
199
|
# Check compatibility between input and output images
|
|
208
|
-
if not self._input.dimensions.is_compatible_with(self._output.dimensions):
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
200
|
+
# if not self._input.dimensions.is_compatible_with(self._output.dimensions):
|
|
201
|
+
# raise NgioValidationError(
|
|
202
|
+
# "Input image and output label have incompatible dimensions. "
|
|
203
|
+
# f"Input: {self._input.dimensions}, Output: {self._output.dimensions}."
|
|
204
|
+
# )
|
|
213
205
|
|
|
214
206
|
def get_init_kwargs(self) -> dict:
|
|
215
207
|
"""Return the initialization arguments for the iterator."""
|
|
@@ -223,58 +215,50 @@ class MaskedSegmentationIterator(SegmentationIterator):
|
|
|
223
215
|
}
|
|
224
216
|
|
|
225
217
|
def build_numpy_getter(self, roi: Roi):
|
|
226
|
-
return
|
|
227
|
-
roi=roi,
|
|
218
|
+
return NumpyGetterMasked(
|
|
228
219
|
zarr_array=self._input.zarr_array,
|
|
229
220
|
dimensions=self._input.dimensions,
|
|
221
|
+
roi=roi,
|
|
230
222
|
label_zarr_array=self._input._label.zarr_array,
|
|
231
223
|
label_dimensions=self._input._label.dimensions,
|
|
232
|
-
label_pixel_size=self._input._label.pixel_size,
|
|
233
224
|
axes_order=self._axes_order,
|
|
234
225
|
transforms=self._input_transforms,
|
|
235
|
-
pixel_size=self._input.pixel_size,
|
|
236
226
|
slicing_dict=self._input_slicing_kwargs,
|
|
237
227
|
)
|
|
238
228
|
|
|
239
229
|
def build_numpy_setter(self, roi: Roi):
|
|
240
|
-
return
|
|
230
|
+
return NumpySetterMasked(
|
|
241
231
|
roi=roi,
|
|
242
232
|
zarr_array=self._output.zarr_array,
|
|
243
233
|
dimensions=self._output.dimensions,
|
|
244
234
|
label_zarr_array=self._input._label.zarr_array,
|
|
245
235
|
label_dimensions=self._input._label.dimensions,
|
|
246
|
-
label_pixel_size=self._input._label.pixel_size,
|
|
247
236
|
axes_order=self._axes_order,
|
|
248
237
|
transforms=self._output_transforms,
|
|
249
|
-
pixel_size=self._output.pixel_size,
|
|
250
238
|
remove_channel_selection=True,
|
|
251
239
|
)
|
|
252
240
|
|
|
253
241
|
def build_dask_getter(self, roi: Roi):
|
|
254
|
-
return
|
|
242
|
+
return DaskGetterMasked(
|
|
255
243
|
roi=roi,
|
|
256
244
|
zarr_array=self._input.zarr_array,
|
|
257
245
|
dimensions=self._input.dimensions,
|
|
258
246
|
label_zarr_array=self._input._label.zarr_array,
|
|
259
247
|
label_dimensions=self._input._label.dimensions,
|
|
260
|
-
label_pixel_size=self._input._label.pixel_size,
|
|
261
248
|
axes_order=self._axes_order,
|
|
262
249
|
transforms=self._input_transforms,
|
|
263
|
-
pixel_size=self._input.pixel_size,
|
|
264
250
|
slicing_dict=self._input_slicing_kwargs,
|
|
265
251
|
)
|
|
266
252
|
|
|
267
253
|
def build_dask_setter(self, roi: Roi):
|
|
268
|
-
return
|
|
254
|
+
return DaskSetterMasked(
|
|
269
255
|
roi=roi,
|
|
270
256
|
zarr_array=self._output.zarr_array,
|
|
271
257
|
dimensions=self._output.dimensions,
|
|
272
258
|
label_zarr_array=self._input._label.zarr_array,
|
|
273
259
|
label_dimensions=self._input._label.dimensions,
|
|
274
|
-
label_pixel_size=self._input._label.pixel_size,
|
|
275
260
|
axes_order=self._axes_order,
|
|
276
261
|
transforms=self._output_transforms,
|
|
277
|
-
pixel_size=self._output.pixel_size,
|
|
278
262
|
remove_channel_selection=True,
|
|
279
263
|
)
|
|
280
264
|
|