ngio 0.5.0b6__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 (88) hide show
  1. ngio/__init__.py +69 -0
  2. ngio/common/__init__.py +28 -0
  3. ngio/common/_dimensions.py +335 -0
  4. ngio/common/_masking_roi.py +153 -0
  5. ngio/common/_pyramid.py +408 -0
  6. ngio/common/_roi.py +315 -0
  7. ngio/common/_synt_images_utils.py +101 -0
  8. ngio/common/_zoom.py +188 -0
  9. ngio/experimental/__init__.py +5 -0
  10. ngio/experimental/iterators/__init__.py +15 -0
  11. ngio/experimental/iterators/_abstract_iterator.py +390 -0
  12. ngio/experimental/iterators/_feature.py +189 -0
  13. ngio/experimental/iterators/_image_processing.py +130 -0
  14. ngio/experimental/iterators/_mappers.py +48 -0
  15. ngio/experimental/iterators/_rois_utils.py +126 -0
  16. ngio/experimental/iterators/_segmentation.py +235 -0
  17. ngio/hcs/__init__.py +19 -0
  18. ngio/hcs/_plate.py +1354 -0
  19. ngio/images/__init__.py +44 -0
  20. ngio/images/_abstract_image.py +967 -0
  21. ngio/images/_create_synt_container.py +132 -0
  22. ngio/images/_create_utils.py +423 -0
  23. ngio/images/_image.py +926 -0
  24. ngio/images/_label.py +411 -0
  25. ngio/images/_masked_image.py +531 -0
  26. ngio/images/_ome_zarr_container.py +1237 -0
  27. ngio/images/_table_ops.py +471 -0
  28. ngio/io_pipes/__init__.py +75 -0
  29. ngio/io_pipes/_io_pipes.py +361 -0
  30. ngio/io_pipes/_io_pipes_masked.py +488 -0
  31. ngio/io_pipes/_io_pipes_roi.py +146 -0
  32. ngio/io_pipes/_io_pipes_types.py +56 -0
  33. ngio/io_pipes/_match_shape.py +377 -0
  34. ngio/io_pipes/_ops_axes.py +344 -0
  35. ngio/io_pipes/_ops_slices.py +411 -0
  36. ngio/io_pipes/_ops_slices_utils.py +199 -0
  37. ngio/io_pipes/_ops_transforms.py +104 -0
  38. ngio/io_pipes/_zoom_transform.py +180 -0
  39. ngio/ome_zarr_meta/__init__.py +65 -0
  40. ngio/ome_zarr_meta/_meta_handlers.py +536 -0
  41. ngio/ome_zarr_meta/ngio_specs/__init__.py +77 -0
  42. ngio/ome_zarr_meta/ngio_specs/_axes.py +515 -0
  43. ngio/ome_zarr_meta/ngio_specs/_channels.py +462 -0
  44. ngio/ome_zarr_meta/ngio_specs/_dataset.py +89 -0
  45. ngio/ome_zarr_meta/ngio_specs/_ngio_hcs.py +539 -0
  46. ngio/ome_zarr_meta/ngio_specs/_ngio_image.py +438 -0
  47. ngio/ome_zarr_meta/ngio_specs/_pixel_size.py +122 -0
  48. ngio/ome_zarr_meta/v04/__init__.py +27 -0
  49. ngio/ome_zarr_meta/v04/_custom_models.py +18 -0
  50. ngio/ome_zarr_meta/v04/_v04_spec.py +473 -0
  51. ngio/ome_zarr_meta/v05/__init__.py +27 -0
  52. ngio/ome_zarr_meta/v05/_custom_models.py +18 -0
  53. ngio/ome_zarr_meta/v05/_v05_spec.py +511 -0
  54. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/mask.png +0 -0
  55. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/nuclei.png +0 -0
  56. ngio/resources/20200812-CardiomyocyteDifferentiation14-Cycle1_B03/raw.jpg +0 -0
  57. ngio/resources/__init__.py +55 -0
  58. ngio/resources/resource_model.py +36 -0
  59. ngio/tables/__init__.py +43 -0
  60. ngio/tables/_abstract_table.py +270 -0
  61. ngio/tables/_tables_container.py +449 -0
  62. ngio/tables/backends/__init__.py +57 -0
  63. ngio/tables/backends/_abstract_backend.py +240 -0
  64. ngio/tables/backends/_anndata.py +139 -0
  65. ngio/tables/backends/_anndata_utils.py +90 -0
  66. ngio/tables/backends/_csv.py +19 -0
  67. ngio/tables/backends/_json.py +92 -0
  68. ngio/tables/backends/_parquet.py +19 -0
  69. ngio/tables/backends/_py_arrow_backends.py +222 -0
  70. ngio/tables/backends/_table_backends.py +226 -0
  71. ngio/tables/backends/_utils.py +608 -0
  72. ngio/tables/v1/__init__.py +23 -0
  73. ngio/tables/v1/_condition_table.py +71 -0
  74. ngio/tables/v1/_feature_table.py +125 -0
  75. ngio/tables/v1/_generic_table.py +49 -0
  76. ngio/tables/v1/_roi_table.py +575 -0
  77. ngio/transforms/__init__.py +5 -0
  78. ngio/transforms/_zoom.py +19 -0
  79. ngio/utils/__init__.py +45 -0
  80. ngio/utils/_cache.py +48 -0
  81. ngio/utils/_datasets.py +165 -0
  82. ngio/utils/_errors.py +37 -0
  83. ngio/utils/_fractal_fsspec_store.py +42 -0
  84. ngio/utils/_zarr_utils.py +534 -0
  85. ngio-0.5.0b6.dist-info/METADATA +148 -0
  86. ngio-0.5.0b6.dist-info/RECORD +88 -0
  87. ngio-0.5.0b6.dist-info/WHEEL +4 -0
  88. ngio-0.5.0b6.dist-info/licenses/LICENSE +28 -0
@@ -0,0 +1,361 @@
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._dimensions import Dimensions
10
+ from ngio.common._roi import Roi
11
+ from ngio.io_pipes._ops_axes import (
12
+ AxesOps,
13
+ build_axes_ops,
14
+ get_as_dask_axes_ops,
15
+ get_as_numpy_axes_ops,
16
+ set_as_dask_axes_ops,
17
+ set_as_numpy_axes_ops,
18
+ )
19
+ from ngio.io_pipes._ops_slices import (
20
+ SlicingInputType,
21
+ SlicingOps,
22
+ build_slicing_ops,
23
+ get_slice_as_dask,
24
+ get_slice_as_numpy,
25
+ set_slice_as_dask,
26
+ set_slice_as_numpy,
27
+ )
28
+ from ngio.io_pipes._ops_transforms import (
29
+ TransformProtocol,
30
+ get_as_dask_transform,
31
+ get_as_numpy_transform,
32
+ set_as_dask_transform,
33
+ set_as_numpy_transform,
34
+ )
35
+
36
+
37
+ def setup_io_pipe(
38
+ *,
39
+ dimensions: Dimensions,
40
+ slicing_dict: dict[str, SlicingInputType] | None = None,
41
+ axes_order: Sequence[str] | None = None,
42
+ remove_channel_selection: bool = False,
43
+ ) -> tuple[SlicingOps, AxesOps]:
44
+ """Setup the slicing tuple and axes ops for an IO pipe."""
45
+ slicing_ops = build_slicing_ops(
46
+ dimensions=dimensions,
47
+ slicing_dict=slicing_dict,
48
+ remove_channel_selection=remove_channel_selection,
49
+ )
50
+
51
+ axes_ops = build_axes_ops(
52
+ dimensions=dimensions,
53
+ input_axes=slicing_ops.slice_axes,
54
+ axes_order=axes_order,
55
+ )
56
+ return slicing_ops, axes_ops
57
+
58
+
59
+ ##############################################################
60
+ #
61
+ # "From Disk" Pipes
62
+ #
63
+ ##############################################################
64
+
65
+ T = TypeVar("T")
66
+
67
+
68
+ class DataGetter(ABC, Generic[T]):
69
+ def __init__(
70
+ self,
71
+ zarr_array: zarr.Array,
72
+ slicing_ops: SlicingOps,
73
+ axes_ops: AxesOps,
74
+ transforms: Sequence[TransformProtocol] | None = None,
75
+ roi: Roi | None = None,
76
+ ) -> None:
77
+ self._zarr_array = zarr_array
78
+ self._slicing_ops = slicing_ops
79
+ self._axes_ops = axes_ops
80
+ self._transforms = transforms
81
+ self._roi = roi
82
+
83
+ def __repr__(self) -> str:
84
+ name = self.__class__.__name__
85
+ return (
86
+ f"{name}(zarr_array={self._zarr_array}, "
87
+ f"slicing_ops={self._slicing_ops}, "
88
+ f"axes_ops={self._axes_ops}, "
89
+ f"transforms={self._transforms})"
90
+ )
91
+
92
+ @property
93
+ def zarr_array(self) -> zarr.Array:
94
+ return self._zarr_array
95
+
96
+ @property
97
+ def slicing_ops(self) -> SlicingOps:
98
+ return self._slicing_ops
99
+
100
+ @property
101
+ def axes_ops(self) -> AxesOps:
102
+ return self._axes_ops
103
+
104
+ @property
105
+ def transforms(self) -> Sequence[TransformProtocol] | None:
106
+ return self._transforms
107
+
108
+ @property
109
+ def roi(self) -> Roi:
110
+ if self._roi is None:
111
+ name = self.__class__.__name__
112
+ raise ValueError(f"No ROI defined for {name}.")
113
+ return self._roi
114
+
115
+ def __call__(self) -> T:
116
+ return self.get()
117
+
118
+ @abstractmethod
119
+ def get(self) -> T:
120
+ pass
121
+
122
+
123
+ class DataSetter(ABC, Generic[T]):
124
+ def __init__(
125
+ self,
126
+ zarr_array: zarr.Array,
127
+ slicing_ops: SlicingOps,
128
+ axes_ops: AxesOps,
129
+ transforms: Sequence[TransformProtocol] | None = None,
130
+ roi: Roi | None = None,
131
+ ) -> None:
132
+ self._zarr_array = zarr_array
133
+ self._slicing_ops = slicing_ops
134
+ self._axes_ops = axes_ops
135
+ self._transforms = transforms
136
+ self._roi = roi
137
+
138
+ def __repr__(self) -> str:
139
+ name = self.__class__.__name__
140
+ return (
141
+ f"{name}(zarr_array={self._zarr_array}, "
142
+ f"slicing_ops={self._slicing_ops}, "
143
+ f"axes_ops={self._axes_ops}, "
144
+ f"transforms={self._transforms})"
145
+ )
146
+
147
+ @property
148
+ def zarr_array(self) -> zarr.Array:
149
+ return self._zarr_array
150
+
151
+ @property
152
+ def slicing_ops(self) -> SlicingOps:
153
+ return self._slicing_ops
154
+
155
+ @property
156
+ def axes_ops(self) -> AxesOps:
157
+ return self._axes_ops
158
+
159
+ @property
160
+ def transforms(self) -> Sequence[TransformProtocol] | None:
161
+ return self._transforms
162
+
163
+ @property
164
+ def roi(self) -> Roi:
165
+ if self._roi is None:
166
+ name = self.__class__.__name__
167
+ raise ValueError(f"No ROI defined for {name}.")
168
+ return self._roi
169
+
170
+ def __call__(self, patch: T) -> None:
171
+ return self.set(patch)
172
+
173
+ @abstractmethod
174
+ def set(self, patch: T) -> None:
175
+ pass
176
+
177
+
178
+ class NumpyGetter(DataGetter[np.ndarray]):
179
+ def __init__(
180
+ self,
181
+ *,
182
+ zarr_array: zarr.Array,
183
+ dimensions: Dimensions,
184
+ axes_order: Sequence[str] | None = None,
185
+ transforms: Sequence[TransformProtocol] | None = None,
186
+ slicing_dict: dict[str, SlicingInputType] | None = None,
187
+ remove_channel_selection: bool = False,
188
+ roi: Roi | None = None,
189
+ ) -> None:
190
+ """Build a pipe to get a numpy or dask array from a zarr array."""
191
+ slicing_ops, axes_ops = setup_io_pipe(
192
+ dimensions=dimensions,
193
+ slicing_dict=slicing_dict,
194
+ axes_order=axes_order,
195
+ remove_channel_selection=remove_channel_selection,
196
+ )
197
+ super().__init__(
198
+ zarr_array=zarr_array,
199
+ slicing_ops=slicing_ops,
200
+ axes_ops=axes_ops,
201
+ transforms=transforms,
202
+ roi=roi,
203
+ )
204
+
205
+ def get(self) -> np.ndarray:
206
+ """Get a numpy array from the zarr array with ops."""
207
+ array = get_slice_as_numpy(self._zarr_array, slicing_ops=self._slicing_ops)
208
+ array = get_as_numpy_axes_ops(array, axes_ops=self._axes_ops)
209
+ array = get_as_numpy_transform(
210
+ array,
211
+ slicing_ops=self._slicing_ops,
212
+ axes_ops=self._axes_ops,
213
+ transforms=self._transforms,
214
+ )
215
+ return array
216
+
217
+
218
+ class DaskGetter(DataGetter[DaskArray]):
219
+ def __init__(
220
+ self,
221
+ *,
222
+ zarr_array: zarr.Array,
223
+ dimensions: Dimensions,
224
+ axes_order: Sequence[str] | None = None,
225
+ transforms: Sequence[TransformProtocol] | None = None,
226
+ slicing_dict: dict[str, SlicingInputType] | None = None,
227
+ remove_channel_selection: bool = False,
228
+ roi: Roi | None = None,
229
+ ) -> None:
230
+ """Build a pipe to get a numpy or dask array from a zarr array."""
231
+ slicing_ops, axes_ops = setup_io_pipe(
232
+ dimensions=dimensions,
233
+ slicing_dict=slicing_dict,
234
+ axes_order=axes_order,
235
+ remove_channel_selection=remove_channel_selection,
236
+ )
237
+ super().__init__(
238
+ zarr_array=zarr_array,
239
+ slicing_ops=slicing_ops,
240
+ axes_ops=axes_ops,
241
+ transforms=transforms,
242
+ roi=roi,
243
+ )
244
+
245
+ def get(self) -> DaskArray:
246
+ """Get a dask array from the zarr array with ops.
247
+
248
+ The order of operations is:
249
+ * get slice will load the data from the zarr array
250
+ * get axes ops will reorder, squeeze or expand the axes
251
+ * get transform will apply any additional transforms
252
+
253
+ """
254
+ array = get_slice_as_dask(self._zarr_array, slicing_ops=self._slicing_ops)
255
+ array = get_as_dask_axes_ops(array, axes_ops=self._axes_ops)
256
+ array = get_as_dask_transform(
257
+ array,
258
+ slicing_ops=self._slicing_ops,
259
+ axes_ops=self._axes_ops,
260
+ transforms=self._transforms,
261
+ )
262
+ return array
263
+
264
+
265
+ ##############################################################
266
+ #
267
+ # "To Disk" Pipes
268
+ #
269
+ ##############################################################
270
+
271
+
272
+ class NumpySetter(DataSetter[np.ndarray]):
273
+ def __init__(
274
+ self,
275
+ *,
276
+ zarr_array: zarr.Array,
277
+ dimensions: Dimensions,
278
+ axes_order: Sequence[str] | None = None,
279
+ transforms: Sequence[TransformProtocol] | None = None,
280
+ slicing_dict: dict[str, SlicingInputType] | None = None,
281
+ remove_channel_selection: bool = False,
282
+ roi: Roi | None = None,
283
+ ) -> None:
284
+ """Build a pipe to get a numpy or dask array from a zarr array."""
285
+ slicing_ops, axes_ops = setup_io_pipe(
286
+ dimensions=dimensions,
287
+ slicing_dict=slicing_dict,
288
+ axes_order=axes_order,
289
+ remove_channel_selection=remove_channel_selection,
290
+ )
291
+ super().__init__(
292
+ zarr_array=zarr_array,
293
+ slicing_ops=slicing_ops,
294
+ axes_ops=axes_ops,
295
+ transforms=transforms,
296
+ roi=roi,
297
+ )
298
+
299
+ def set(self, patch: np.ndarray) -> None:
300
+ """Get a numpy array from the zarr array with ops."""
301
+ patch = set_as_numpy_transform(
302
+ array=patch,
303
+ slicing_ops=self._slicing_ops,
304
+ axes_ops=self._axes_ops,
305
+ transforms=self._transforms,
306
+ )
307
+ patch = set_as_numpy_axes_ops(
308
+ array=patch,
309
+ axes_ops=self._axes_ops,
310
+ )
311
+ set_slice_as_numpy(
312
+ zarr_array=self._zarr_array,
313
+ patch=patch,
314
+ slicing_ops=self._slicing_ops,
315
+ )
316
+
317
+
318
+ class DaskSetter(DataSetter[DaskArray]):
319
+ def __init__(
320
+ self,
321
+ *,
322
+ zarr_array: zarr.Array,
323
+ dimensions: Dimensions,
324
+ axes_order: Sequence[str] | None = None,
325
+ transforms: Sequence[TransformProtocol] | None = None,
326
+ slicing_dict: dict[str, SlicingInputType] | None = None,
327
+ remove_channel_selection: bool = False,
328
+ roi: Roi | None = None,
329
+ ) -> None:
330
+ """Build a pipe to get a numpy or dask array from a zarr array."""
331
+ slicing_ops, axes_ops = setup_io_pipe(
332
+ dimensions=dimensions,
333
+ slicing_dict=slicing_dict,
334
+ axes_order=axes_order,
335
+ remove_channel_selection=remove_channel_selection,
336
+ )
337
+ super().__init__(
338
+ zarr_array=zarr_array,
339
+ slicing_ops=slicing_ops,
340
+ axes_ops=axes_ops,
341
+ transforms=transforms,
342
+ roi=roi,
343
+ )
344
+
345
+ def set(self, patch: DaskArray) -> None:
346
+ """Get a dask array from the zarr array with ops."""
347
+ patch = set_as_dask_transform(
348
+ array=patch,
349
+ slicing_ops=self._slicing_ops,
350
+ axes_ops=self._axes_ops,
351
+ transforms=self._transforms,
352
+ )
353
+ patch = set_as_dask_axes_ops(
354
+ array=patch,
355
+ axes_ops=self._axes_ops,
356
+ )
357
+ set_slice_as_dask(
358
+ zarr_array=self._zarr_array,
359
+ patch=patch,
360
+ slicing_ops=self._slicing_ops,
361
+ )