ngio 0.4.0a3__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.
Files changed (50) hide show
  1. ngio/__init__.py +1 -2
  2. ngio/common/__init__.py +2 -51
  3. ngio/common/_dimensions.py +223 -64
  4. ngio/common/_pyramid.py +42 -23
  5. ngio/common/_roi.py +47 -411
  6. ngio/common/_zoom.py +32 -7
  7. ngio/experimental/iterators/_abstract_iterator.py +2 -2
  8. ngio/experimental/iterators/_feature.py +9 -14
  9. ngio/experimental/iterators/_image_processing.py +17 -27
  10. ngio/experimental/iterators/_rois_utils.py +4 -4
  11. ngio/experimental/iterators/_segmentation.py +37 -53
  12. ngio/images/_abstract_image.py +135 -93
  13. ngio/images/_create.py +16 -0
  14. ngio/images/_create_synt_container.py +10 -0
  15. ngio/images/_image.py +33 -9
  16. ngio/images/_label.py +24 -3
  17. ngio/images/_masked_image.py +60 -81
  18. ngio/images/_ome_zarr_container.py +33 -0
  19. ngio/io_pipes/__init__.py +49 -0
  20. ngio/io_pipes/_io_pipes.py +286 -0
  21. ngio/io_pipes/_io_pipes_masked.py +481 -0
  22. ngio/io_pipes/_io_pipes_roi.py +143 -0
  23. ngio/io_pipes/_io_pipes_utils.py +299 -0
  24. ngio/io_pipes/_match_shape.py +376 -0
  25. ngio/io_pipes/_ops_axes.py +146 -0
  26. ngio/io_pipes/_ops_slices.py +218 -0
  27. ngio/io_pipes/_ops_transforms.py +104 -0
  28. ngio/io_pipes/_zoom_transform.py +175 -0
  29. ngio/ome_zarr_meta/__init__.py +6 -2
  30. ngio/ome_zarr_meta/ngio_specs/__init__.py +6 -4
  31. ngio/ome_zarr_meta/ngio_specs/_axes.py +182 -70
  32. ngio/ome_zarr_meta/ngio_specs/_dataset.py +47 -121
  33. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +30 -22
  34. ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +17 -1
  35. ngio/ome_zarr_meta/v04/_v04_spec_utils.py +33 -30
  36. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
  37. ngio/resources/__init__.py +1 -0
  38. ngio/resources/resource_model.py +1 -0
  39. ngio/{common/transforms → transforms}/__init__.py +1 -1
  40. ngio/transforms/_zoom.py +19 -0
  41. ngio/utils/_zarr_utils.py +5 -1
  42. {ngio-0.4.0a3.dist-info → ngio-0.4.0a4.dist-info}/METADATA +1 -1
  43. ngio-0.4.0a4.dist-info/RECORD +83 -0
  44. ngio/common/_array_io_pipes.py +0 -554
  45. ngio/common/_array_io_utils.py +0 -508
  46. ngio/common/transforms/_label.py +0 -12
  47. ngio/common/transforms/_zoom.py +0 -109
  48. ngio-0.4.0a3.dist-info/RECORD +0 -76
  49. {ngio-0.4.0a3.dist-info → ngio-0.4.0a4.dist-info}/WHEEL +0 -0
  50. {ngio-0.4.0a3.dist-info → ngio-0.4.0a4.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,286 @@
1
+ from abc import ABC, abstractmethod
2
+ from collections.abc import Sequence
3
+ from typing import Generic, TypeVar
4
+
5
+ import numpy as np
6
+ import zarr
7
+ from dask.array import Array as DaskArray
8
+
9
+ from ngio.common import Dimensions
10
+ from ngio.io_pipes._io_pipes_utils import SlicingInputType, setup_io_pipe
11
+ from ngio.io_pipes._ops_axes import (
12
+ get_as_dask_axes_ops,
13
+ get_as_numpy_axes_ops,
14
+ set_as_dask_axes_ops,
15
+ set_as_numpy_axes_ops,
16
+ )
17
+ from ngio.io_pipes._ops_slices import (
18
+ SlicingOps,
19
+ get_slice_as_dask,
20
+ get_slice_as_numpy,
21
+ set_slice_as_dask,
22
+ set_slice_as_numpy,
23
+ )
24
+ from ngio.io_pipes._ops_transforms import (
25
+ TransformProtocol,
26
+ get_as_dask_transform,
27
+ get_as_numpy_transform,
28
+ set_as_dask_transform,
29
+ set_as_numpy_transform,
30
+ )
31
+ from ngio.ome_zarr_meta.ngio_specs._axes import AxesOps
32
+
33
+ ##############################################################
34
+ #
35
+ # "From Disk" Pipes
36
+ #
37
+ ##############################################################
38
+
39
+ ArrayType = TypeVar("ArrayType", np.ndarray, DaskArray)
40
+
41
+
42
+ class DataGetter(ABC, Generic[ArrayType]):
43
+ def __init__(
44
+ self,
45
+ zarr_array: zarr.Array,
46
+ slicing_ops: SlicingOps,
47
+ axes_ops: AxesOps,
48
+ transforms: Sequence[TransformProtocol] | None = None,
49
+ ) -> None:
50
+ self._zarr_array = zarr_array
51
+ self._slicing_ops = slicing_ops
52
+ self._axes_ops = axes_ops
53
+ self._transforms = transforms
54
+
55
+ @property
56
+ def zarr_array(self) -> zarr.Array:
57
+ return self._zarr_array
58
+
59
+ @property
60
+ def slicing_ops(self) -> SlicingOps:
61
+ return self._slicing_ops
62
+
63
+ @property
64
+ def axes_ops(self) -> AxesOps:
65
+ return self._axes_ops
66
+
67
+ @property
68
+ def in_memory_axes(self) -> tuple[str, ...]:
69
+ return self._axes_ops.in_memory_axes
70
+
71
+ @property
72
+ def transforms(self) -> Sequence[TransformProtocol] | None:
73
+ return self._transforms
74
+
75
+ def __call__(self) -> ArrayType:
76
+ return self.get()
77
+
78
+ @abstractmethod
79
+ def get(self) -> ArrayType:
80
+ pass
81
+
82
+
83
+ class DataSetter(ABC, Generic[ArrayType]):
84
+ def __init__(
85
+ self,
86
+ zarr_array: zarr.Array,
87
+ slicing_ops: SlicingOps,
88
+ axes_ops: AxesOps,
89
+ transforms: Sequence[TransformProtocol] | None = None,
90
+ ) -> None:
91
+ self._zarr_array = zarr_array
92
+ self._slicing_ops = slicing_ops
93
+ self._axes_ops = axes_ops
94
+ self._transforms = transforms
95
+
96
+ @property
97
+ def zarr_array(self) -> zarr.Array:
98
+ return self._zarr_array
99
+
100
+ @property
101
+ def slicing_ops(self) -> SlicingOps:
102
+ return self._slicing_ops
103
+
104
+ @property
105
+ def axes_ops(self) -> AxesOps:
106
+ return self._axes_ops
107
+
108
+ @property
109
+ def in_memory_axes(self) -> tuple[str, ...]:
110
+ return self._axes_ops.in_memory_axes
111
+
112
+ @property
113
+ def transforms(self) -> Sequence[TransformProtocol] | None:
114
+ return self._transforms
115
+
116
+ def __call__(self, patch: ArrayType) -> None:
117
+ return self.set(patch)
118
+
119
+ @abstractmethod
120
+ def set(self, patch: ArrayType) -> None:
121
+ pass
122
+
123
+
124
+ class NumpyGetter(DataGetter[np.ndarray]):
125
+ def __init__(
126
+ self,
127
+ zarr_array: zarr.Array,
128
+ dimensions: Dimensions,
129
+ axes_order: Sequence[str] | None = None,
130
+ transforms: Sequence[TransformProtocol] | None = None,
131
+ slicing_dict: dict[str, SlicingInputType] | None = None,
132
+ remove_channel_selection: bool = False,
133
+ ) -> None:
134
+ """Build a pipe to get a numpy or dask array from a zarr array."""
135
+ slicing_ops, axes_ops = setup_io_pipe(
136
+ dimensions=dimensions,
137
+ slicing_dict=slicing_dict,
138
+ axes_order=axes_order,
139
+ remove_channel_selection=remove_channel_selection,
140
+ )
141
+ super().__init__(
142
+ zarr_array=zarr_array,
143
+ slicing_ops=slicing_ops,
144
+ axes_ops=axes_ops,
145
+ transforms=transforms,
146
+ )
147
+
148
+ def get(self) -> np.ndarray:
149
+ array = get_slice_as_numpy(self._zarr_array, slicing_ops=self._slicing_ops)
150
+ array = get_as_numpy_axes_ops(array, axes_ops=self._axes_ops)
151
+ array = get_as_numpy_transform(
152
+ array,
153
+ slicing_ops=self._slicing_ops,
154
+ axes_ops=self._axes_ops,
155
+ transforms=self._transforms,
156
+ )
157
+ return array
158
+
159
+
160
+ class DaskGetter(DataGetter[DaskArray]):
161
+ def __init__(
162
+ self,
163
+ zarr_array: zarr.Array,
164
+ dimensions: Dimensions,
165
+ axes_order: Sequence[str] | None = None,
166
+ transforms: Sequence[TransformProtocol] | None = None,
167
+ slicing_dict: dict[str, SlicingInputType] | None = None,
168
+ remove_channel_selection: bool = False,
169
+ ) -> None:
170
+ """Build a pipe to get a numpy or dask array from a zarr array."""
171
+ slicing_ops, axes_ops = setup_io_pipe(
172
+ dimensions=dimensions,
173
+ slicing_dict=slicing_dict,
174
+ axes_order=axes_order,
175
+ remove_channel_selection=remove_channel_selection,
176
+ )
177
+ super().__init__(
178
+ zarr_array=zarr_array,
179
+ slicing_ops=slicing_ops,
180
+ axes_ops=axes_ops,
181
+ transforms=transforms,
182
+ )
183
+
184
+ def get(self) -> DaskArray:
185
+ array = get_slice_as_dask(self._zarr_array, slicing_ops=self._slicing_ops)
186
+ array = get_as_dask_axes_ops(array, axes_ops=self._axes_ops)
187
+ array = get_as_dask_transform(
188
+ array,
189
+ slicing_ops=self._slicing_ops,
190
+ axes_ops=self._axes_ops,
191
+ transforms=self._transforms,
192
+ )
193
+ return array
194
+
195
+
196
+ ##############################################################
197
+ #
198
+ # "To Disk" Pipes
199
+ #
200
+ ##############################################################
201
+
202
+
203
+ class NumpySetter(DataSetter[np.ndarray]):
204
+ def __init__(
205
+ self,
206
+ zarr_array: zarr.Array,
207
+ dimensions: Dimensions,
208
+ axes_order: Sequence[str] | None = None,
209
+ transforms: Sequence[TransformProtocol] | None = None,
210
+ slicing_dict: dict[str, SlicingInputType] | None = None,
211
+ remove_channel_selection: bool = False,
212
+ ) -> None:
213
+ """Build a pipe to get a numpy or dask array from a zarr array."""
214
+ slicing_ops, axes_ops = setup_io_pipe(
215
+ dimensions=dimensions,
216
+ slicing_dict=slicing_dict,
217
+ axes_order=axes_order,
218
+ remove_channel_selection=remove_channel_selection,
219
+ )
220
+ super().__init__(
221
+ zarr_array=zarr_array,
222
+ slicing_ops=slicing_ops,
223
+ axes_ops=axes_ops,
224
+ transforms=transforms,
225
+ )
226
+
227
+ def set(self, patch: np.ndarray) -> None:
228
+ """Get a numpy array from the zarr array with ops."""
229
+ patch = set_as_numpy_transform(
230
+ array=patch,
231
+ slicing_ops=self._slicing_ops,
232
+ axes_ops=self._axes_ops,
233
+ transforms=self._transforms,
234
+ )
235
+ patch = set_as_numpy_axes_ops(
236
+ array=patch,
237
+ axes_ops=self._axes_ops,
238
+ )
239
+ set_slice_as_numpy(
240
+ zarr_array=self._zarr_array,
241
+ patch=patch,
242
+ slicing_ops=self._slicing_ops,
243
+ )
244
+
245
+
246
+ class DaskSetter(DataSetter[DaskArray]):
247
+ def __init__(
248
+ self,
249
+ zarr_array: zarr.Array,
250
+ dimensions: Dimensions,
251
+ axes_order: Sequence[str] | None = None,
252
+ transforms: Sequence[TransformProtocol] | None = None,
253
+ slicing_dict: dict[str, SlicingInputType] | None = None,
254
+ remove_channel_selection: bool = False,
255
+ ) -> None:
256
+ """Build a pipe to get a numpy or dask array from a zarr array."""
257
+ slicing_ops, axes_ops = setup_io_pipe(
258
+ dimensions=dimensions,
259
+ slicing_dict=slicing_dict,
260
+ axes_order=axes_order,
261
+ remove_channel_selection=remove_channel_selection,
262
+ )
263
+ super().__init__(
264
+ zarr_array=zarr_array,
265
+ slicing_ops=slicing_ops,
266
+ axes_ops=axes_ops,
267
+ transforms=transforms,
268
+ )
269
+
270
+ def set(self, patch: DaskArray) -> None:
271
+ """Get a dask array from the zarr array with ops."""
272
+ patch = set_as_dask_transform(
273
+ array=patch,
274
+ slicing_ops=self._slicing_ops,
275
+ axes_ops=self._axes_ops,
276
+ transforms=self._transforms,
277
+ )
278
+ patch = set_as_dask_axes_ops(
279
+ array=patch,
280
+ axes_ops=self._axes_ops,
281
+ )
282
+ set_slice_as_dask(
283
+ zarr_array=self._zarr_array,
284
+ patch=patch,
285
+ slicing_ops=self._slicing_ops,
286
+ )