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,130 @@
1
+ from collections.abc import Sequence
2
+
3
+ import dask.array as da
4
+ import numpy as np
5
+
6
+ from ngio.common import Roi
7
+ from ngio.experimental.iterators._abstract_iterator import AbstractIteratorBuilder
8
+ from ngio.images import Image
9
+ from ngio.images._image import (
10
+ ChannelSlicingInputType,
11
+ add_channel_selection_to_slicing_dict,
12
+ )
13
+ from ngio.io_pipes import (
14
+ DaskRoiGetter,
15
+ DaskRoiSetter,
16
+ NumpyRoiGetter,
17
+ NumpyRoiSetter,
18
+ TransformProtocol,
19
+ )
20
+ from ngio.io_pipes._io_pipes_types import DataGetterProtocol, DataSetterProtocol
21
+
22
+
23
+ class ImageProcessingIterator(AbstractIteratorBuilder[np.ndarray, da.Array]):
24
+ """Base class for iterators over ROIs."""
25
+
26
+ def __init__(
27
+ self,
28
+ input_image: Image,
29
+ output_image: Image,
30
+ input_channel_selection: ChannelSlicingInputType = None,
31
+ output_channel_selection: ChannelSlicingInputType = None,
32
+ axes_order: Sequence[str] | None = None,
33
+ input_transforms: Sequence[TransformProtocol] | None = None,
34
+ output_transforms: Sequence[TransformProtocol] | None = None,
35
+ ) -> None:
36
+ """Initialize the iterator with a ROI table and input/output images.
37
+
38
+ Args:
39
+ input_image (Image): The input image to be used as input for the
40
+ segmentation.
41
+ output_image (Image): The image where the ROIs will be written.
42
+ input_channel_selection (ChannelSlicingInputType): Optional
43
+ selection of channels to use for the input image.
44
+ output_channel_selection (ChannelSlicingInputType): Optional
45
+ selection of channels to use for the output image.
46
+ axes_order (Sequence[str] | None): Optional axes order for the
47
+ segmentation.
48
+ input_transforms (Sequence[TransformProtocol] | None): Optional
49
+ transforms to apply to the input image.
50
+ output_transforms (Sequence[TransformProtocol] | None): Optional
51
+ transforms to apply to the output label.
52
+ """
53
+ self._input = input_image
54
+ self._output = output_image
55
+ self._ref_image = input_image
56
+ self._rois = input_image.build_image_roi_table(name=None).rois()
57
+
58
+ # Set iteration parameters
59
+ self._input_slicing_kwargs = add_channel_selection_to_slicing_dict(
60
+ image=self._input,
61
+ channel_selection=input_channel_selection,
62
+ slicing_dict={},
63
+ )
64
+ self._output_slicing_kwargs = add_channel_selection_to_slicing_dict(
65
+ image=self._output,
66
+ channel_selection=output_channel_selection,
67
+ slicing_dict={},
68
+ )
69
+ self._input_channel_selection = input_channel_selection
70
+ self._output_channel_selection = output_channel_selection
71
+ self._axes_order = axes_order
72
+ self._input_transforms = input_transforms
73
+ self._output_transforms = output_transforms
74
+
75
+ self._input.require_dimensions_match(self._output, allow_singleton=True)
76
+
77
+ def get_init_kwargs(self) -> dict:
78
+ """Return the initialization arguments for the iterator."""
79
+ return {
80
+ "input_image": self._input,
81
+ "output_image": self._output,
82
+ "input_channel_selection": self._input_channel_selection,
83
+ "output_channel_selection": self._output_channel_selection,
84
+ "axes_order": self._axes_order,
85
+ "input_transforms": self._input_transforms,
86
+ "output_transforms": self._output_transforms,
87
+ }
88
+
89
+ def build_numpy_getter(self, roi: Roi) -> DataGetterProtocol[np.ndarray]:
90
+ return NumpyRoiGetter(
91
+ zarr_array=self._input.zarr_array,
92
+ dimensions=self._input.dimensions,
93
+ roi=roi,
94
+ axes_order=self._axes_order,
95
+ transforms=self._input_transforms,
96
+ slicing_dict=self._input_slicing_kwargs,
97
+ )
98
+
99
+ def build_numpy_setter(self, roi: Roi) -> DataSetterProtocol[np.ndarray]:
100
+ return NumpyRoiSetter(
101
+ zarr_array=self._output.zarr_array,
102
+ dimensions=self._output.dimensions,
103
+ roi=roi,
104
+ axes_order=self._axes_order,
105
+ transforms=self._output_transforms,
106
+ slicing_dict=self._output_slicing_kwargs,
107
+ )
108
+
109
+ def build_dask_getter(self, roi: Roi) -> DataGetterProtocol[da.Array]:
110
+ return DaskRoiGetter(
111
+ zarr_array=self._input.zarr_array,
112
+ dimensions=self._input.dimensions,
113
+ roi=roi,
114
+ axes_order=self._axes_order,
115
+ transforms=self._input_transforms,
116
+ slicing_dict=self._input_slicing_kwargs,
117
+ )
118
+
119
+ def build_dask_setter(self, roi: Roi) -> DataSetterProtocol[da.Array]:
120
+ return DaskRoiSetter(
121
+ zarr_array=self._output.zarr_array,
122
+ dimensions=self._output.dimensions,
123
+ roi=roi,
124
+ axes_order=self._axes_order,
125
+ transforms=self._output_transforms,
126
+ slicing_dict=self._output_slicing_kwargs,
127
+ )
128
+
129
+ def post_consolidate(self):
130
+ self._output.consolidate()
@@ -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)
@@ -0,0 +1,126 @@
1
+ from ngio import Roi
2
+ from ngio.images._abstract_image import AbstractImage
3
+
4
+
5
+ def rois_product(rois_a: list[Roi], rois_b: list[Roi]) -> list[Roi]:
6
+ """Compute the product of two sets of ROIs."""
7
+ rois_product = []
8
+ for roi_a in rois_a:
9
+ for roi_b in rois_b:
10
+ intersection = roi_a.intersection(roi_b)
11
+ if intersection:
12
+ rois_product.append(intersection)
13
+ return rois_product
14
+
15
+
16
+ def grid(
17
+ rois: list[Roi],
18
+ ref_image: AbstractImage,
19
+ size_x: int | None = None,
20
+ size_y: int | None = None,
21
+ size_z: int | None = None,
22
+ size_t: int | None = None,
23
+ stride_x: int | None = None,
24
+ stride_y: int | None = None,
25
+ stride_z: int | None = None,
26
+ stride_t: int | None = None,
27
+ base_name: str | None = None,
28
+ ) -> list[Roi]:
29
+ """This method is a placeholder for creating a regular grid of ROIs."""
30
+ t_dim = ref_image.dimensions.get("t", default=1)
31
+ z_dim = ref_image.dimensions.get("z", default=1)
32
+ y_dim = ref_image.dimensions.get("y", default=1)
33
+ x_dim = ref_image.dimensions.get("x", default=1)
34
+
35
+ size_t = size_t if size_t is not None else t_dim
36
+ size_z = size_z if size_z is not None else z_dim
37
+ size_y = size_y if size_y is not None else y_dim
38
+ size_x = size_x if size_x is not None else x_dim
39
+
40
+ stride_t = stride_t if stride_t is not None else size_t
41
+ stride_z = stride_z if stride_z is not None else size_z
42
+ stride_y = stride_y if stride_y is not None else size_y
43
+ stride_x = stride_x if stride_x is not None else size_x
44
+
45
+ # Here we would create a grid of ROIs based on the specified parameters.
46
+ new_rois = []
47
+ for t in range(0, t_dim, stride_t):
48
+ for z in range(0, z_dim, stride_z):
49
+ for y in range(0, y_dim, stride_y):
50
+ for x in range(0, x_dim, stride_x):
51
+ roi = Roi.from_values(
52
+ name=base_name,
53
+ slices={
54
+ "x": (x, size_x),
55
+ "y": (y, size_y),
56
+ "z": (z, size_z),
57
+ "t": (t, size_t),
58
+ },
59
+ space="pixel",
60
+ )
61
+ new_rois.append(roi.to_world(pixel_size=ref_image.pixel_size))
62
+
63
+ return rois_product(rois, new_rois)
64
+
65
+
66
+ def by_yx(rois: list[Roi], ref_image: AbstractImage) -> list[Roi]:
67
+ """Return a new iterator that iterates over ROIs by YX coordinates."""
68
+ return grid(
69
+ rois=rois,
70
+ ref_image=ref_image,
71
+ size_z=1,
72
+ stride_z=1,
73
+ size_t=1,
74
+ stride_t=1,
75
+ )
76
+
77
+
78
+ def by_zyx(rois: list[Roi], ref_image: AbstractImage, strict: bool = True) -> list[Roi]:
79
+ """Return a new iterator that iterates over ROIs by ZYX coordinates."""
80
+ if strict and not ref_image.is_3d:
81
+ raise ValueError(
82
+ "Reference Input image must be 3D to iterate by ZXY coordinates. "
83
+ f"Current dimensions: {ref_image.dimensions}"
84
+ )
85
+ return grid(
86
+ rois=rois,
87
+ ref_image=ref_image,
88
+ size_t=1,
89
+ stride_t=1,
90
+ )
91
+
92
+
93
+ def by_chunks(
94
+ rois: list[Roi],
95
+ ref_image: AbstractImage,
96
+ overlap_xy: int = 0,
97
+ overlap_z: int = 0,
98
+ overlap_t: int = 0,
99
+ ) -> list[Roi]:
100
+ """This method is a placeholder for chunked processing."""
101
+ chunk_size = ref_image.chunks
102
+ t_axis = ref_image.axes_handler.get_index("t")
103
+ z_axis = ref_image.axes_handler.get_index("z")
104
+ y_axis = ref_image.axes_handler.get_index("y")
105
+ x_axis = ref_image.axes_handler.get_index("x")
106
+
107
+ size_x = chunk_size[x_axis] if x_axis is not None else None
108
+ size_y = chunk_size[y_axis] if y_axis is not None else None
109
+ size_z = chunk_size[z_axis] if z_axis is not None else None
110
+ size_t = chunk_size[t_axis] if t_axis is not None else None
111
+ stride_x = size_x - overlap_xy if size_x is not None else None
112
+ stride_y = size_y - overlap_xy if size_y is not None else None
113
+ stride_z = size_z - overlap_z if size_z is not None else None
114
+ stride_t = size_t - overlap_t if size_t is not None else None
115
+ return grid(
116
+ rois=rois,
117
+ ref_image=ref_image,
118
+ size_x=size_x,
119
+ size_y=size_y,
120
+ size_z=size_z,
121
+ size_t=size_t,
122
+ stride_x=stride_x,
123
+ stride_y=stride_y,
124
+ stride_z=stride_z,
125
+ stride_t=stride_t,
126
+ )
@@ -0,0 +1,235 @@
1
+ from collections.abc import Sequence
2
+
3
+ import dask.array as da
4
+ import numpy as np
5
+
6
+ from ngio.common import Roi
7
+ from ngio.experimental.iterators._abstract_iterator import AbstractIteratorBuilder
8
+ from ngio.images import Image, Label
9
+ from ngio.images._image import (
10
+ ChannelSlicingInputType,
11
+ add_channel_selection_to_slicing_dict,
12
+ )
13
+ from ngio.images._masked_image import MaskedImage
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
+
27
+
28
+ class SegmentationIterator(AbstractIteratorBuilder[np.ndarray, da.Array]):
29
+ """Base class for iterators over ROIs."""
30
+
31
+ def __init__(
32
+ self,
33
+ input_image: Image,
34
+ output_label: Label,
35
+ channel_selection: ChannelSlicingInputType = None,
36
+ axes_order: Sequence[str] | None = None,
37
+ input_transforms: Sequence[TransformProtocol] | None = None,
38
+ output_transforms: Sequence[TransformProtocol] | None = None,
39
+ ) -> None:
40
+ """Initialize the iterator with a ROI table and input/output images.
41
+
42
+ Args:
43
+ input_image (Image): The input image to be used as input for the
44
+ segmentation.
45
+ output_label (Label): The label image where the ROIs will be written.
46
+ channel_selection (ChannelSlicingInputType): Optional
47
+ selection of channels to use for the segmentation.
48
+ axes_order (Sequence[str] | None): Optional axes order for the
49
+ segmentation.
50
+ input_transforms (Sequence[TransformProtocol] | None): Optional
51
+ transforms to apply to the input image.
52
+ output_transforms (Sequence[TransformProtocol] | None): Optional
53
+ transforms to apply to the output label.
54
+ """
55
+ self._input = input_image
56
+ self._output = output_label
57
+ self._ref_image = input_image
58
+ self._rois = input_image.build_image_roi_table(name=None).rois()
59
+
60
+ # Set iteration parameters
61
+ self._input_slicing_kwargs = add_channel_selection_to_slicing_dict(
62
+ image=self._input, channel_selection=channel_selection, slicing_dict={}
63
+ )
64
+ self._channel_selection = channel_selection
65
+ self._axes_order = axes_order
66
+ self._input_transforms = input_transforms
67
+ self._output_transforms = output_transforms
68
+
69
+ self._input.require_dimensions_match(self._output, allow_singleton=False)
70
+
71
+ def get_init_kwargs(self) -> dict:
72
+ """Return the initialization arguments for the iterator."""
73
+ return {
74
+ "input_image": self._input,
75
+ "output_label": self._output,
76
+ "channel_selection": self._channel_selection,
77
+ "axes_order": self._axes_order,
78
+ "input_transforms": self._input_transforms,
79
+ "output_transforms": self._output_transforms,
80
+ }
81
+
82
+ def build_numpy_getter(self, roi: Roi) -> DataGetterProtocol[np.ndarray]:
83
+ return NumpyRoiGetter(
84
+ zarr_array=self._input.zarr_array,
85
+ dimensions=self._input.dimensions,
86
+ roi=roi,
87
+ axes_order=self._axes_order,
88
+ transforms=self._input_transforms,
89
+ slicing_dict=self._input_slicing_kwargs,
90
+ )
91
+
92
+ def build_numpy_setter(self, roi: Roi) -> DataSetterProtocol[np.ndarray]:
93
+ return NumpyRoiSetter(
94
+ zarr_array=self._output.zarr_array,
95
+ dimensions=self._output.dimensions,
96
+ roi=roi,
97
+ axes_order=self._axes_order,
98
+ transforms=self._output_transforms,
99
+ remove_channel_selection=True,
100
+ )
101
+
102
+ def build_dask_getter(self, roi: Roi) -> DataGetterProtocol[da.Array]:
103
+ return DaskRoiGetter(
104
+ zarr_array=self._input.zarr_array,
105
+ dimensions=self._input.dimensions,
106
+ roi=roi,
107
+ axes_order=self._axes_order,
108
+ transforms=self._input_transforms,
109
+ slicing_dict=self._input_slicing_kwargs,
110
+ )
111
+
112
+ def build_dask_setter(self, roi: Roi) -> DataSetterProtocol[da.Array]:
113
+ return DaskRoiSetter(
114
+ zarr_array=self._output.zarr_array,
115
+ dimensions=self._output.dimensions,
116
+ roi=roi,
117
+ axes_order=self._axes_order,
118
+ transforms=self._output_transforms,
119
+ remove_channel_selection=True,
120
+ )
121
+
122
+ def post_consolidate(self):
123
+ self._output.consolidate()
124
+
125
+
126
+ class MaskedSegmentationIterator(SegmentationIterator):
127
+ """Base class for iterators over ROIs."""
128
+
129
+ def __init__(
130
+ self,
131
+ input_image: MaskedImage,
132
+ output_label: Label,
133
+ channel_selection: ChannelSlicingInputType = None,
134
+ axes_order: Sequence[str] | None = None,
135
+ input_transforms: Sequence[TransformProtocol] | None = None,
136
+ output_transforms: Sequence[TransformProtocol] | None = None,
137
+ ) -> None:
138
+ """Initialize the iterator with a ROI table and input/output images.
139
+
140
+ Args:
141
+ input_image (MaskedImage): The input image to be used as input for the
142
+ segmentation.
143
+ output_label (Label): The label image where the ROIs will be written.
144
+ channel_selection (ChannelSlicingInputType): Optional
145
+ selection of channels to use for the segmentation.
146
+ axes_order (Sequence[str] | None): Optional axes order for the
147
+ segmentation.
148
+ input_transforms (Sequence[TransformProtocol] | None): Optional
149
+ transforms to apply to the input image.
150
+ output_transforms (Sequence[TransformProtocol] | None): Optional
151
+ transforms to apply to the output label.
152
+ """
153
+ self._input = input_image
154
+ self._output = output_label
155
+
156
+ self._ref_image = input_image
157
+ self._set_rois(input_image._masking_roi_table.rois())
158
+
159
+ # Set iteration parameters
160
+ self._input_slicing_kwargs = add_channel_selection_to_slicing_dict(
161
+ image=self._input, channel_selection=channel_selection, slicing_dict={}
162
+ )
163
+ self._channel_selection = channel_selection
164
+ self._axes_order = axes_order
165
+ self._input_transforms = input_transforms
166
+ self._output_transforms = output_transforms
167
+
168
+ # Check compatibility between input and output images
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
+ # )
174
+
175
+ def get_init_kwargs(self) -> dict:
176
+ """Return the initialization arguments for the iterator."""
177
+ return {
178
+ "input_image": self._input,
179
+ "output_label": self._output,
180
+ "channel_selection": self._channel_selection,
181
+ "axes_order": self._axes_order,
182
+ "input_transforms": self._input_transforms,
183
+ "output_transforms": self._output_transforms,
184
+ }
185
+
186
+ def build_numpy_getter(self, roi: Roi):
187
+ return NumpyGetterMasked(
188
+ zarr_array=self._input.zarr_array,
189
+ dimensions=self._input.dimensions,
190
+ roi=roi,
191
+ label_zarr_array=self._input._label.zarr_array,
192
+ label_dimensions=self._input._label.dimensions,
193
+ axes_order=self._axes_order,
194
+ transforms=self._input_transforms,
195
+ slicing_dict=self._input_slicing_kwargs,
196
+ )
197
+
198
+ def build_numpy_setter(self, roi: Roi):
199
+ return NumpySetterMasked(
200
+ roi=roi,
201
+ zarr_array=self._output.zarr_array,
202
+ dimensions=self._output.dimensions,
203
+ label_zarr_array=self._input._label.zarr_array,
204
+ label_dimensions=self._input._label.dimensions,
205
+ axes_order=self._axes_order,
206
+ transforms=self._output_transforms,
207
+ remove_channel_selection=True,
208
+ )
209
+
210
+ def build_dask_getter(self, roi: Roi):
211
+ return DaskGetterMasked(
212
+ roi=roi,
213
+ zarr_array=self._input.zarr_array,
214
+ dimensions=self._input.dimensions,
215
+ label_zarr_array=self._input._label.zarr_array,
216
+ label_dimensions=self._input._label.dimensions,
217
+ axes_order=self._axes_order,
218
+ transforms=self._input_transforms,
219
+ slicing_dict=self._input_slicing_kwargs,
220
+ )
221
+
222
+ def build_dask_setter(self, roi: Roi):
223
+ return DaskSetterMasked(
224
+ roi=roi,
225
+ zarr_array=self._output.zarr_array,
226
+ dimensions=self._output.dimensions,
227
+ label_zarr_array=self._input._label.zarr_array,
228
+ label_dimensions=self._input._label.dimensions,
229
+ axes_order=self._axes_order,
230
+ transforms=self._output_transforms,
231
+ remove_channel_selection=True,
232
+ )
233
+
234
+ def post_consolidate(self):
235
+ self._output.consolidate()
ngio/hcs/__init__.py ADDED
@@ -0,0 +1,19 @@
1
+ """OME-Zarr HCS objects models."""
2
+
3
+ from ngio.hcs._plate import (
4
+ OmeZarrPlate,
5
+ OmeZarrWell,
6
+ create_empty_plate,
7
+ create_empty_well,
8
+ open_ome_zarr_plate,
9
+ open_ome_zarr_well,
10
+ )
11
+
12
+ __all__ = [
13
+ "OmeZarrPlate",
14
+ "OmeZarrWell",
15
+ "create_empty_plate",
16
+ "create_empty_well",
17
+ "open_ome_zarr_plate",
18
+ "open_ome_zarr_well",
19
+ ]