Skip to content

Iterators API Reference

ImageProcessingIterator

ngio.experimental.iterators.ImageProcessingIterator

ImageProcessingIterator(
    input_image: Image,
    output_image: Image,
    input_channel_selection: ChannelSlicingInputType = None,
    output_channel_selection: ChannelSlicingInputType = None,
    axes_order: Sequence[str] | None = None,
    input_transforms: Sequence[TransformProtocol]
    | None = None,
    output_transforms: Sequence[TransformProtocol]
    | None = None,
)

Bases: AbstractIteratorBuilder[ndarray, Array]

Base class for iterators over ROIs.

Initialize the iterator with a ROI table and input/output images.

Parameters:

  • input_image (Image) –

    The input image to be used as input for the segmentation.

  • output_image (Image) –

    The image where the ROIs will be written.

  • input_channel_selection (ChannelSlicingInputType, default: None ) –

    Optional selection of channels to use for the input image.

  • output_channel_selection (ChannelSlicingInputType, default: None ) –

    Optional selection of channels to use for the output image.

  • axes_order (Sequence[str] | None, default: None ) –

    Optional axes order for the segmentation.

  • input_transforms (Sequence[TransformProtocol] | None, default: None ) –

    Optional transforms to apply to the input image.

  • output_transforms (Sequence[TransformProtocol] | None, default: None ) –

    Optional transforms to apply to the output label.

Source code in ngio/experimental/iterators/_image_processing.py
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
def __init__(
    self,
    input_image: Image,
    output_image: Image,
    input_channel_selection: ChannelSlicingInputType = None,
    output_channel_selection: ChannelSlicingInputType = None,
    axes_order: Sequence[str] | None = None,
    input_transforms: Sequence[TransformProtocol] | None = None,
    output_transforms: Sequence[TransformProtocol] | None = None,
) -> None:
    """Initialize the iterator with a ROI table and input/output images.

    Args:
        input_image (Image): The input image to be used as input for the
            segmentation.
        output_image (Image): The image where the ROIs will be written.
        input_channel_selection (ChannelSlicingInputType): Optional
            selection of channels to use for the input image.
        output_channel_selection (ChannelSlicingInputType): Optional
            selection of channels to use for the output image.
        axes_order (Sequence[str] | None): Optional axes order for the
            segmentation.
        input_transforms (Sequence[TransformProtocol] | None): Optional
            transforms to apply to the input image.
        output_transforms (Sequence[TransformProtocol] | None): Optional
            transforms to apply to the output label.
    """
    self._input = input_image
    self._output = output_image
    self._ref_image = input_image
    self._rois = input_image.build_image_roi_table(name=None).rois()

    # Set iteration parameters
    self._input_slicing_kwargs = add_channel_selection_to_slicing_dict(
        image=self._input,
        channel_selection=input_channel_selection,
        slicing_dict={},
    )
    self._output_slicing_kwargs = add_channel_selection_to_slicing_dict(
        image=self._output,
        channel_selection=output_channel_selection,
        slicing_dict={},
    )
    self._input_channel_selection = input_channel_selection
    self._output_channel_selection = output_channel_selection
    self._axes_order = axes_order
    self._input_transforms = input_transforms
    self._output_transforms = output_transforms

    self._input.require_dimensions_match(self._output, allow_singleton=True)

rois property

rois: list[Roi]

Get the list of ROIs for the iterator.

ref_image property

ref_image: AbstractImage

Get the reference image for the iterator.

grid

grid(
    size_x: int | None = None,
    size_y: int | None = None,
    size_z: int | None = None,
    size_t: int | None = None,
    stride_x: int | None = None,
    stride_y: int | None = None,
    stride_z: int | None = None,
    stride_t: int | None = None,
    base_name: str = "",
) -> Self

Create a grid of ROIs based on the input image dimensions.

Source code in ngio/experimental/iterators/_abstract_iterator.py
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
def grid(
    self,
    size_x: int | None = None,
    size_y: int | None = None,
    size_z: int | None = None,
    size_t: int | None = None,
    stride_x: int | None = None,
    stride_y: int | None = None,
    stride_z: int | None = None,
    stride_t: int | None = None,
    base_name: str = "",
) -> Self:
    """Create a grid of ROIs based on the input image dimensions."""
    rois = grid(
        rois=self.rois,
        ref_image=self.ref_image,
        size_x=size_x,
        size_y=size_y,
        size_z=size_z,
        size_t=size_t,
        stride_x=stride_x,
        stride_y=stride_y,
        stride_z=stride_z,
        stride_t=stride_t,
        base_name=base_name,
    )
    return self._new_from_rois(rois)

by_yx

by_yx() -> Self

Return a new iterator that iterates over ROIs by YX coordinates.

Source code in ngio/experimental/iterators/_abstract_iterator.py
91
92
93
94
def by_yx(self) -> Self:
    """Return a new iterator that iterates over ROIs by YX coordinates."""
    rois = by_yx(self.rois, self.ref_image)
    return self._new_from_rois(rois)

by_zyx

by_zyx(strict: bool = True) -> Self

Return a new iterator that iterates over ROIs by ZYX coordinates.

Parameters:

  • strict (bool, default: True ) –

    If True, only iterate over ZYX if a Z axis is present and not of size 1.

Source code in ngio/experimental/iterators/_abstract_iterator.py
 96
 97
 98
 99
100
101
102
103
104
105
def by_zyx(self, strict: bool = True) -> Self:
    """Return a new iterator that iterates over ROIs by ZYX coordinates.

    Args:
        strict (bool): If True, only iterate over ZYX if a Z axis
            is present and not of size 1.

    """
    rois = by_zyx(self.rois, self.ref_image, strict=strict)
    return self._new_from_rois(rois)

by_chunks

by_chunks(overlap_xy: int = 0, overlap_z: int = 0) -> Self

Return a new iterator that iterates over ROIs by chunks.

Parameters:

  • overlap_xy (int, default: 0 ) –

    Overlap in XY dimensions.

  • overlap_z (int, default: 0 ) –

    Overlap in Z dimension.

Returns:

  • SegmentationIterator ( Self ) –

    A new iterator with chunked ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
def by_chunks(self, overlap_xy: int = 0, overlap_z: int = 0) -> Self:
    """Return a new iterator that iterates over ROIs by chunks.

    Args:
        overlap_xy (int): Overlap in XY dimensions.
        overlap_z (int): Overlap in Z dimension.

    Returns:
        SegmentationIterator: A new iterator with chunked ROIs.
    """
    rois = by_chunks(
        self.rois, self.ref_image, overlap_xy=overlap_xy, overlap_z=overlap_z
    )
    return self._new_from_rois(rois)

product

product(other: list[Roi] | GenericRoiTable) -> Self

Cartesian product of the current ROIs with an arbitrary list of ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
122
123
124
125
126
127
def product(self, other: list[Roi] | GenericRoiTable) -> Self:
    """Cartesian product of the current ROIs with an arbitrary list of ROIs."""
    if isinstance(other, GenericRoiTable):
        other = other.rois()
    rois = rois_product(self.rois, other)
    return self._new_from_rois(rois)

iter

iter(
    lazy: Literal[True],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[
        DataGetterProtocol[NumpyPipeType],
        DataSetterProtocol[NumpyPipeType],
    ]
]
iter(
    lazy: Literal[True],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DataGetterProtocol[NumpyPipeType]]
iter(
    lazy: Literal[True],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[
        DataGetterProtocol[DaskPipeType],
        DataSetterProtocol[DaskPipeType],
    ]
]
iter(
    lazy: Literal[True],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DataGetterProtocol[DaskPipeType]]
iter(
    lazy: Literal[False],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[NumpyPipeType, DataSetterProtocol[NumpyPipeType]]
]
iter(
    lazy: Literal[False],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[NumpyPipeType]
iter(
    lazy: Literal[False],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[DaskPipeType, DataSetterProtocol[DaskPipeType]]
]
iter(
    lazy: Literal[False],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DaskPipeType]
iter(
    lazy: bool = False,
    data_mode: Literal["numpy", "dask"] = "dask",
    iterator_mode: Literal[
        "readwrite", "readonly"
    ] = "readwrite",
) -> Generator

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
def iter(
    self,
    lazy: bool = False,
    data_mode: Literal["numpy", "dask"] = "dask",
    iterator_mode: Literal["readwrite", "readonly"] = "readwrite",
) -> Generator:
    """Create an iterator over the pixels of the ROIs."""
    if data_mode == "numpy":
        getters = self._numpy_getters_generator()
        setters = self._numpy_setters_generator()
    elif data_mode == "dask":
        getters = self._dask_getters_generator()
        setters = self._dask_setters_generator()
    else:
        raise NgioValueError(f"Invalid mode: {data_mode}")

    if iterator_mode == "readonly":
        if lazy:
            return getters
        else:
            return (getter() for getter in getters)
    if lazy:
        return self._read_and_write_generator(getters, setters)
    else:
        gen = self._read_and_write_generator(getters, setters)
        return ((getter(), setter) for getter, setter in gen)

iter_as_numpy

iter_as_numpy()

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
291
292
293
294
295
def iter_as_numpy(
    self,
):
    """Create an iterator over the pixels of the ROIs."""
    return self.iter(lazy=False, data_mode="numpy", iterator_mode="readwrite")

iter_as_dask

iter_as_dask()

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
297
298
299
300
301
def iter_as_dask(
    self,
):
    """Create an iterator over the pixels of the ROIs."""
    return self.iter(lazy=False, data_mode="dask", iterator_mode="readwrite")

map_as_numpy

map_as_numpy(
    func: Callable[[NumpyPipeType], NumpyPipeType],
    mapper: MapperProtocol[NumpyPipeType] | None = None,
) -> None

Apply a transformation function to the ROI pixels.

Source code in ngio/experimental/iterators/_abstract_iterator.py
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
def map_as_numpy(
    self,
    func: Callable[[NumpyPipeType], NumpyPipeType],
    mapper: MapperProtocol[NumpyPipeType] | None = None,
) -> None:
    """Apply a transformation function to the ROI pixels."""
    if mapper is None:
        _mapper = BasicMapper[NumpyPipeType]()
    else:
        _mapper = mapper

    _mapper(
        func=func,
        getters=self._numpy_getters_generator(),
        setters=self._numpy_setters_generator(),
    )
    self.post_consolidate()

map_as_dask

map_as_dask(
    func: Callable[[DaskPipeType], DaskPipeType],
    mapper: MapperProtocol[DaskPipeType] | None = None,
) -> None

Apply a transformation function to the ROI pixels.

Source code in ngio/experimental/iterators/_abstract_iterator.py
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
def map_as_dask(
    self,
    func: Callable[[DaskPipeType], DaskPipeType],
    mapper: MapperProtocol[DaskPipeType] | None = None,
) -> None:
    """Apply a transformation function to the ROI pixels."""
    if mapper is None:
        _mapper = BasicMapper[DaskPipeType]()
    else:
        _mapper = mapper

    _mapper(
        func=func,
        getters=self._dask_getters_generator(),
        setters=self._dask_setters_generator(),
    )
    self.post_consolidate()

check_if_regions_overlap

check_if_regions_overlap() -> bool

Check if any of the ROIs overlap logically.

If two ROIs cover the same pixel, they are considered to overlap. This does not consider chunking or other storage details.

Returns:

  • bool ( bool ) –

    True if any ROIs overlap. False otherwise.

Source code in ngio/experimental/iterators/_abstract_iterator.py
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
def check_if_regions_overlap(self) -> bool:
    """Check if any of the ROIs overlap logically.

    If two ROIs cover the same pixel, they are considered to overlap.
    This does not consider chunking or other storage details.

    Returns:
        bool: True if any ROIs overlap. False otherwise.
    """
    if len(self.rois) < 2:
        # Less than 2 ROIs cannot overlap
        return False

    slicing_tuples = (
        g.slicing_ops.normalized_slicing_tuple
        for g in self._numpy_getters_generator()
    )
    x = check_if_regions_overlap(slicing_tuples)
    return x

require_no_regions_overlap

require_no_regions_overlap() -> None

Ensure that the Iterator's ROIs do not overlap.

Source code in ngio/experimental/iterators/_abstract_iterator.py
359
360
361
362
def require_no_regions_overlap(self) -> None:
    """Ensure that the Iterator's ROIs do not overlap."""
    if self.check_if_regions_overlap():
        raise NgioValueError("Some rois overlap.")

check_if_chunks_overlap

check_if_chunks_overlap() -> bool

Check if any of the ROIs overlap in terms of chunks.

If two ROIs cover the same chunk, they are considered to overlap in chunks. This does not consider pixel-level overlaps.

Returns:

  • bool ( bool ) –

    True if any ROIs overlap in chunks, False otherwise.

Source code in ngio/experimental/iterators/_abstract_iterator.py
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
def check_if_chunks_overlap(self) -> bool:
    """Check if any of the ROIs overlap in terms of chunks.

    If two ROIs cover the same chunk, they are considered to overlap in chunks.
    This does not consider pixel-level overlaps.

    Returns:
        bool: True if any ROIs overlap in chunks, False otherwise.
    """
    from ngio.io_pipes._ops_slices_utils import check_if_chunks_overlap

    if len(self.rois) < 2:
        # Less than 2 ROIs cannot overlap
        return False

    slicing_tuples = (
        g.slicing_ops.normalized_slicing_tuple
        for g in self._numpy_getters_generator()
    )
    shape = self.ref_image.shape
    chunks = self.ref_image.chunks
    return check_if_chunks_overlap(slicing_tuples, shape, chunks)

require_no_chunks_overlap

require_no_chunks_overlap() -> None

Ensure that the ROIs do not overlap in terms of chunks.

Source code in ngio/experimental/iterators/_abstract_iterator.py
387
388
389
390
def require_no_chunks_overlap(self) -> None:
    """Ensure that the ROIs do not overlap in terms of chunks."""
    if self.check_if_chunks_overlap():
        raise NgioValueError("Some rois overlap in chunks.")

get_init_kwargs

get_init_kwargs() -> dict

Return the initialization arguments for the iterator.

Source code in ngio/experimental/iterators/_image_processing.py
77
78
79
80
81
82
83
84
85
86
87
def get_init_kwargs(self) -> dict:
    """Return the initialization arguments for the iterator."""
    return {
        "input_image": self._input,
        "output_image": self._output,
        "input_channel_selection": self._input_channel_selection,
        "output_channel_selection": self._output_channel_selection,
        "axes_order": self._axes_order,
        "input_transforms": self._input_transforms,
        "output_transforms": self._output_transforms,
    }

build_numpy_getter

build_numpy_getter(roi: Roi) -> DataGetterProtocol[ndarray]
Source code in ngio/experimental/iterators/_image_processing.py
89
90
91
92
93
94
95
96
97
def build_numpy_getter(self, roi: Roi) -> DataGetterProtocol[np.ndarray]:
    return NumpyRoiGetter(
        zarr_array=self._input.zarr_array,
        dimensions=self._input.dimensions,
        roi=roi,
        axes_order=self._axes_order,
        transforms=self._input_transforms,
        slicing_dict=self._input_slicing_kwargs,
    )

build_numpy_setter

build_numpy_setter(roi: Roi) -> DataSetterProtocol[ndarray]
Source code in ngio/experimental/iterators/_image_processing.py
 99
100
101
102
103
104
105
106
107
def build_numpy_setter(self, roi: Roi) -> DataSetterProtocol[np.ndarray]:
    return NumpyRoiSetter(
        zarr_array=self._output.zarr_array,
        dimensions=self._output.dimensions,
        roi=roi,
        axes_order=self._axes_order,
        transforms=self._output_transforms,
        slicing_dict=self._output_slicing_kwargs,
    )

build_dask_getter

build_dask_getter(roi: Roi) -> DataGetterProtocol[Array]
Source code in ngio/experimental/iterators/_image_processing.py
109
110
111
112
113
114
115
116
117
def build_dask_getter(self, roi: Roi) -> DataGetterProtocol[da.Array]:
    return DaskRoiGetter(
        zarr_array=self._input.zarr_array,
        dimensions=self._input.dimensions,
        roi=roi,
        axes_order=self._axes_order,
        transforms=self._input_transforms,
        slicing_dict=self._input_slicing_kwargs,
    )

build_dask_setter

build_dask_setter(roi: Roi) -> DataSetterProtocol[Array]
Source code in ngio/experimental/iterators/_image_processing.py
119
120
121
122
123
124
125
126
127
def build_dask_setter(self, roi: Roi) -> DataSetterProtocol[da.Array]:
    return DaskRoiSetter(
        zarr_array=self._output.zarr_array,
        dimensions=self._output.dimensions,
        roi=roi,
        axes_order=self._axes_order,
        transforms=self._output_transforms,
        slicing_dict=self._output_slicing_kwargs,
    )

post_consolidate

post_consolidate()
Source code in ngio/experimental/iterators/_image_processing.py
129
130
def post_consolidate(self):
    self._output.consolidate()

SegmentationIterator

ngio.experimental.iterators.SegmentationIterator

SegmentationIterator(
    input_image: Image,
    output_label: Label,
    channel_selection: ChannelSlicingInputType = None,
    axes_order: Sequence[str] | None = None,
    input_transforms: Sequence[TransformProtocol]
    | None = None,
    output_transforms: Sequence[TransformProtocol]
    | None = None,
)

Bases: AbstractIteratorBuilder[ndarray, Array]

Base class for iterators over ROIs.

Initialize the iterator with a ROI table and input/output images.

Parameters:

  • input_image (Image) –

    The input image to be used as input for the segmentation.

  • output_label (Label) –

    The label image where the ROIs will be written.

  • channel_selection (ChannelSlicingInputType, default: None ) –

    Optional selection of channels to use for the segmentation.

  • axes_order (Sequence[str] | None, default: None ) –

    Optional axes order for the segmentation.

  • input_transforms (Sequence[TransformProtocol] | None, default: None ) –

    Optional transforms to apply to the input image.

  • output_transforms (Sequence[TransformProtocol] | None, default: None ) –

    Optional transforms to apply to the output label.

Source code in ngio/experimental/iterators/_segmentation.py
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
def __init__(
    self,
    input_image: Image,
    output_label: Label,
    channel_selection: ChannelSlicingInputType = None,
    axes_order: Sequence[str] | None = None,
    input_transforms: Sequence[TransformProtocol] | None = None,
    output_transforms: Sequence[TransformProtocol] | None = None,
) -> None:
    """Initialize the iterator with a ROI table and input/output images.

    Args:
        input_image (Image): The input image to be used as input for the
            segmentation.
        output_label (Label): The label image where the ROIs will be written.
        channel_selection (ChannelSlicingInputType): Optional
            selection of channels to use for the segmentation.
        axes_order (Sequence[str] | None): Optional axes order for the
            segmentation.
        input_transforms (Sequence[TransformProtocol] | None): Optional
            transforms to apply to the input image.
        output_transforms (Sequence[TransformProtocol] | None): Optional
            transforms to apply to the output label.
    """
    self._input = input_image
    self._output = output_label
    self._ref_image = input_image
    self._rois = input_image.build_image_roi_table(name=None).rois()

    # Set iteration parameters
    self._input_slicing_kwargs = add_channel_selection_to_slicing_dict(
        image=self._input, channel_selection=channel_selection, slicing_dict={}
    )
    self._channel_selection = channel_selection
    self._axes_order = axes_order
    self._input_transforms = input_transforms
    self._output_transforms = output_transforms

    self._input.require_dimensions_match(self._output, allow_singleton=False)

rois property

rois: list[Roi]

Get the list of ROIs for the iterator.

ref_image property

ref_image: AbstractImage

Get the reference image for the iterator.

grid

grid(
    size_x: int | None = None,
    size_y: int | None = None,
    size_z: int | None = None,
    size_t: int | None = None,
    stride_x: int | None = None,
    stride_y: int | None = None,
    stride_z: int | None = None,
    stride_t: int | None = None,
    base_name: str = "",
) -> Self

Create a grid of ROIs based on the input image dimensions.

Source code in ngio/experimental/iterators/_abstract_iterator.py
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
def grid(
    self,
    size_x: int | None = None,
    size_y: int | None = None,
    size_z: int | None = None,
    size_t: int | None = None,
    stride_x: int | None = None,
    stride_y: int | None = None,
    stride_z: int | None = None,
    stride_t: int | None = None,
    base_name: str = "",
) -> Self:
    """Create a grid of ROIs based on the input image dimensions."""
    rois = grid(
        rois=self.rois,
        ref_image=self.ref_image,
        size_x=size_x,
        size_y=size_y,
        size_z=size_z,
        size_t=size_t,
        stride_x=stride_x,
        stride_y=stride_y,
        stride_z=stride_z,
        stride_t=stride_t,
        base_name=base_name,
    )
    return self._new_from_rois(rois)

by_yx

by_yx() -> Self

Return a new iterator that iterates over ROIs by YX coordinates.

Source code in ngio/experimental/iterators/_abstract_iterator.py
91
92
93
94
def by_yx(self) -> Self:
    """Return a new iterator that iterates over ROIs by YX coordinates."""
    rois = by_yx(self.rois, self.ref_image)
    return self._new_from_rois(rois)

by_zyx

by_zyx(strict: bool = True) -> Self

Return a new iterator that iterates over ROIs by ZYX coordinates.

Parameters:

  • strict (bool, default: True ) –

    If True, only iterate over ZYX if a Z axis is present and not of size 1.

Source code in ngio/experimental/iterators/_abstract_iterator.py
 96
 97
 98
 99
100
101
102
103
104
105
def by_zyx(self, strict: bool = True) -> Self:
    """Return a new iterator that iterates over ROIs by ZYX coordinates.

    Args:
        strict (bool): If True, only iterate over ZYX if a Z axis
            is present and not of size 1.

    """
    rois = by_zyx(self.rois, self.ref_image, strict=strict)
    return self._new_from_rois(rois)

by_chunks

by_chunks(overlap_xy: int = 0, overlap_z: int = 0) -> Self

Return a new iterator that iterates over ROIs by chunks.

Parameters:

  • overlap_xy (int, default: 0 ) –

    Overlap in XY dimensions.

  • overlap_z (int, default: 0 ) –

    Overlap in Z dimension.

Returns:

  • SegmentationIterator ( Self ) –

    A new iterator with chunked ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
def by_chunks(self, overlap_xy: int = 0, overlap_z: int = 0) -> Self:
    """Return a new iterator that iterates over ROIs by chunks.

    Args:
        overlap_xy (int): Overlap in XY dimensions.
        overlap_z (int): Overlap in Z dimension.

    Returns:
        SegmentationIterator: A new iterator with chunked ROIs.
    """
    rois = by_chunks(
        self.rois, self.ref_image, overlap_xy=overlap_xy, overlap_z=overlap_z
    )
    return self._new_from_rois(rois)

product

product(other: list[Roi] | GenericRoiTable) -> Self

Cartesian product of the current ROIs with an arbitrary list of ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
122
123
124
125
126
127
def product(self, other: list[Roi] | GenericRoiTable) -> Self:
    """Cartesian product of the current ROIs with an arbitrary list of ROIs."""
    if isinstance(other, GenericRoiTable):
        other = other.rois()
    rois = rois_product(self.rois, other)
    return self._new_from_rois(rois)

iter

iter(
    lazy: Literal[True],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[
        DataGetterProtocol[NumpyPipeType],
        DataSetterProtocol[NumpyPipeType],
    ]
]
iter(
    lazy: Literal[True],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DataGetterProtocol[NumpyPipeType]]
iter(
    lazy: Literal[True],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[
        DataGetterProtocol[DaskPipeType],
        DataSetterProtocol[DaskPipeType],
    ]
]
iter(
    lazy: Literal[True],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DataGetterProtocol[DaskPipeType]]
iter(
    lazy: Literal[False],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[NumpyPipeType, DataSetterProtocol[NumpyPipeType]]
]
iter(
    lazy: Literal[False],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[NumpyPipeType]
iter(
    lazy: Literal[False],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[DaskPipeType, DataSetterProtocol[DaskPipeType]]
]
iter(
    lazy: Literal[False],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DaskPipeType]
iter(
    lazy: bool = False,
    data_mode: Literal["numpy", "dask"] = "dask",
    iterator_mode: Literal[
        "readwrite", "readonly"
    ] = "readwrite",
) -> Generator

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
def iter(
    self,
    lazy: bool = False,
    data_mode: Literal["numpy", "dask"] = "dask",
    iterator_mode: Literal["readwrite", "readonly"] = "readwrite",
) -> Generator:
    """Create an iterator over the pixels of the ROIs."""
    if data_mode == "numpy":
        getters = self._numpy_getters_generator()
        setters = self._numpy_setters_generator()
    elif data_mode == "dask":
        getters = self._dask_getters_generator()
        setters = self._dask_setters_generator()
    else:
        raise NgioValueError(f"Invalid mode: {data_mode}")

    if iterator_mode == "readonly":
        if lazy:
            return getters
        else:
            return (getter() for getter in getters)
    if lazy:
        return self._read_and_write_generator(getters, setters)
    else:
        gen = self._read_and_write_generator(getters, setters)
        return ((getter(), setter) for getter, setter in gen)

iter_as_numpy

iter_as_numpy()

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
291
292
293
294
295
def iter_as_numpy(
    self,
):
    """Create an iterator over the pixels of the ROIs."""
    return self.iter(lazy=False, data_mode="numpy", iterator_mode="readwrite")

iter_as_dask

iter_as_dask()

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
297
298
299
300
301
def iter_as_dask(
    self,
):
    """Create an iterator over the pixels of the ROIs."""
    return self.iter(lazy=False, data_mode="dask", iterator_mode="readwrite")

map_as_numpy

map_as_numpy(
    func: Callable[[NumpyPipeType], NumpyPipeType],
    mapper: MapperProtocol[NumpyPipeType] | None = None,
) -> None

Apply a transformation function to the ROI pixels.

Source code in ngio/experimental/iterators/_abstract_iterator.py
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
def map_as_numpy(
    self,
    func: Callable[[NumpyPipeType], NumpyPipeType],
    mapper: MapperProtocol[NumpyPipeType] | None = None,
) -> None:
    """Apply a transformation function to the ROI pixels."""
    if mapper is None:
        _mapper = BasicMapper[NumpyPipeType]()
    else:
        _mapper = mapper

    _mapper(
        func=func,
        getters=self._numpy_getters_generator(),
        setters=self._numpy_setters_generator(),
    )
    self.post_consolidate()

map_as_dask

map_as_dask(
    func: Callable[[DaskPipeType], DaskPipeType],
    mapper: MapperProtocol[DaskPipeType] | None = None,
) -> None

Apply a transformation function to the ROI pixels.

Source code in ngio/experimental/iterators/_abstract_iterator.py
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
def map_as_dask(
    self,
    func: Callable[[DaskPipeType], DaskPipeType],
    mapper: MapperProtocol[DaskPipeType] | None = None,
) -> None:
    """Apply a transformation function to the ROI pixels."""
    if mapper is None:
        _mapper = BasicMapper[DaskPipeType]()
    else:
        _mapper = mapper

    _mapper(
        func=func,
        getters=self._dask_getters_generator(),
        setters=self._dask_setters_generator(),
    )
    self.post_consolidate()

check_if_regions_overlap

check_if_regions_overlap() -> bool

Check if any of the ROIs overlap logically.

If two ROIs cover the same pixel, they are considered to overlap. This does not consider chunking or other storage details.

Returns:

  • bool ( bool ) –

    True if any ROIs overlap. False otherwise.

Source code in ngio/experimental/iterators/_abstract_iterator.py
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
def check_if_regions_overlap(self) -> bool:
    """Check if any of the ROIs overlap logically.

    If two ROIs cover the same pixel, they are considered to overlap.
    This does not consider chunking or other storage details.

    Returns:
        bool: True if any ROIs overlap. False otherwise.
    """
    if len(self.rois) < 2:
        # Less than 2 ROIs cannot overlap
        return False

    slicing_tuples = (
        g.slicing_ops.normalized_slicing_tuple
        for g in self._numpy_getters_generator()
    )
    x = check_if_regions_overlap(slicing_tuples)
    return x

require_no_regions_overlap

require_no_regions_overlap() -> None

Ensure that the Iterator's ROIs do not overlap.

Source code in ngio/experimental/iterators/_abstract_iterator.py
359
360
361
362
def require_no_regions_overlap(self) -> None:
    """Ensure that the Iterator's ROIs do not overlap."""
    if self.check_if_regions_overlap():
        raise NgioValueError("Some rois overlap.")

check_if_chunks_overlap

check_if_chunks_overlap() -> bool

Check if any of the ROIs overlap in terms of chunks.

If two ROIs cover the same chunk, they are considered to overlap in chunks. This does not consider pixel-level overlaps.

Returns:

  • bool ( bool ) –

    True if any ROIs overlap in chunks, False otherwise.

Source code in ngio/experimental/iterators/_abstract_iterator.py
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
def check_if_chunks_overlap(self) -> bool:
    """Check if any of the ROIs overlap in terms of chunks.

    If two ROIs cover the same chunk, they are considered to overlap in chunks.
    This does not consider pixel-level overlaps.

    Returns:
        bool: True if any ROIs overlap in chunks, False otherwise.
    """
    from ngio.io_pipes._ops_slices_utils import check_if_chunks_overlap

    if len(self.rois) < 2:
        # Less than 2 ROIs cannot overlap
        return False

    slicing_tuples = (
        g.slicing_ops.normalized_slicing_tuple
        for g in self._numpy_getters_generator()
    )
    shape = self.ref_image.shape
    chunks = self.ref_image.chunks
    return check_if_chunks_overlap(slicing_tuples, shape, chunks)

require_no_chunks_overlap

require_no_chunks_overlap() -> None

Ensure that the ROIs do not overlap in terms of chunks.

Source code in ngio/experimental/iterators/_abstract_iterator.py
387
388
389
390
def require_no_chunks_overlap(self) -> None:
    """Ensure that the ROIs do not overlap in terms of chunks."""
    if self.check_if_chunks_overlap():
        raise NgioValueError("Some rois overlap in chunks.")

get_init_kwargs

get_init_kwargs() -> dict

Return the initialization arguments for the iterator.

Source code in ngio/experimental/iterators/_segmentation.py
71
72
73
74
75
76
77
78
79
80
def get_init_kwargs(self) -> dict:
    """Return the initialization arguments for the iterator."""
    return {
        "input_image": self._input,
        "output_label": self._output,
        "channel_selection": self._channel_selection,
        "axes_order": self._axes_order,
        "input_transforms": self._input_transforms,
        "output_transforms": self._output_transforms,
    }

build_numpy_getter

build_numpy_getter(roi: Roi) -> DataGetterProtocol[ndarray]
Source code in ngio/experimental/iterators/_segmentation.py
82
83
84
85
86
87
88
89
90
def build_numpy_getter(self, roi: Roi) -> DataGetterProtocol[np.ndarray]:
    return NumpyRoiGetter(
        zarr_array=self._input.zarr_array,
        dimensions=self._input.dimensions,
        roi=roi,
        axes_order=self._axes_order,
        transforms=self._input_transforms,
        slicing_dict=self._input_slicing_kwargs,
    )

build_numpy_setter

build_numpy_setter(roi: Roi) -> DataSetterProtocol[ndarray]
Source code in ngio/experimental/iterators/_segmentation.py
 92
 93
 94
 95
 96
 97
 98
 99
100
def build_numpy_setter(self, roi: Roi) -> DataSetterProtocol[np.ndarray]:
    return NumpyRoiSetter(
        zarr_array=self._output.zarr_array,
        dimensions=self._output.dimensions,
        roi=roi,
        axes_order=self._axes_order,
        transforms=self._output_transforms,
        remove_channel_selection=True,
    )

build_dask_getter

build_dask_getter(roi: Roi) -> DataGetterProtocol[Array]
Source code in ngio/experimental/iterators/_segmentation.py
102
103
104
105
106
107
108
109
110
def build_dask_getter(self, roi: Roi) -> DataGetterProtocol[da.Array]:
    return DaskRoiGetter(
        zarr_array=self._input.zarr_array,
        dimensions=self._input.dimensions,
        roi=roi,
        axes_order=self._axes_order,
        transforms=self._input_transforms,
        slicing_dict=self._input_slicing_kwargs,
    )

build_dask_setter

build_dask_setter(roi: Roi) -> DataSetterProtocol[Array]
Source code in ngio/experimental/iterators/_segmentation.py
112
113
114
115
116
117
118
119
120
def build_dask_setter(self, roi: Roi) -> DataSetterProtocol[da.Array]:
    return DaskRoiSetter(
        zarr_array=self._output.zarr_array,
        dimensions=self._output.dimensions,
        roi=roi,
        axes_order=self._axes_order,
        transforms=self._output_transforms,
        remove_channel_selection=True,
    )

post_consolidate

post_consolidate()
Source code in ngio/experimental/iterators/_segmentation.py
122
123
def post_consolidate(self):
    self._output.consolidate()

MaskedSegmentationIterator

ngio.experimental.iterators.MaskedSegmentationIterator

MaskedSegmentationIterator(
    input_image: MaskedImage,
    output_label: Label,
    channel_selection: ChannelSlicingInputType = None,
    axes_order: Sequence[str] | None = None,
    input_transforms: Sequence[TransformProtocol]
    | None = None,
    output_transforms: Sequence[TransformProtocol]
    | None = None,
)

Bases: SegmentationIterator

Base class for iterators over ROIs.

Initialize the iterator with a ROI table and input/output images.

Parameters:

  • input_image (MaskedImage) –

    The input image to be used as input for the segmentation.

  • output_label (Label) –

    The label image where the ROIs will be written.

  • channel_selection (ChannelSlicingInputType, default: None ) –

    Optional selection of channels to use for the segmentation.

  • axes_order (Sequence[str] | None, default: None ) –

    Optional axes order for the segmentation.

  • input_transforms (Sequence[TransformProtocol] | None, default: None ) –

    Optional transforms to apply to the input image.

  • output_transforms (Sequence[TransformProtocol] | None, default: None ) –

    Optional transforms to apply to the output label.

Source code in ngio/experimental/iterators/_segmentation.py
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
def __init__(
    self,
    input_image: MaskedImage,
    output_label: Label,
    channel_selection: ChannelSlicingInputType = None,
    axes_order: Sequence[str] | None = None,
    input_transforms: Sequence[TransformProtocol] | None = None,
    output_transforms: Sequence[TransformProtocol] | None = None,
) -> None:
    """Initialize the iterator with a ROI table and input/output images.

    Args:
        input_image (MaskedImage): The input image to be used as input for the
            segmentation.
        output_label (Label): The label image where the ROIs will be written.
        channel_selection (ChannelSlicingInputType): Optional
            selection of channels to use for the segmentation.
        axes_order (Sequence[str] | None): Optional axes order for the
            segmentation.
        input_transforms (Sequence[TransformProtocol] | None): Optional
            transforms to apply to the input image.
        output_transforms (Sequence[TransformProtocol] | None): Optional
            transforms to apply to the output label.
    """
    self._input = input_image
    self._output = output_label

    self._ref_image = input_image
    self._set_rois(input_image._masking_roi_table.rois())

    # Set iteration parameters
    self._input_slicing_kwargs = add_channel_selection_to_slicing_dict(
        image=self._input, channel_selection=channel_selection, slicing_dict={}
    )
    self._channel_selection = channel_selection
    self._axes_order = axes_order
    self._input_transforms = input_transforms
    self._output_transforms = output_transforms

rois property

rois: list[Roi]

Get the list of ROIs for the iterator.

ref_image property

ref_image: AbstractImage

Get the reference image for the iterator.

grid

grid(
    size_x: int | None = None,
    size_y: int | None = None,
    size_z: int | None = None,
    size_t: int | None = None,
    stride_x: int | None = None,
    stride_y: int | None = None,
    stride_z: int | None = None,
    stride_t: int | None = None,
    base_name: str = "",
) -> Self

Create a grid of ROIs based on the input image dimensions.

Source code in ngio/experimental/iterators/_abstract_iterator.py
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
def grid(
    self,
    size_x: int | None = None,
    size_y: int | None = None,
    size_z: int | None = None,
    size_t: int | None = None,
    stride_x: int | None = None,
    stride_y: int | None = None,
    stride_z: int | None = None,
    stride_t: int | None = None,
    base_name: str = "",
) -> Self:
    """Create a grid of ROIs based on the input image dimensions."""
    rois = grid(
        rois=self.rois,
        ref_image=self.ref_image,
        size_x=size_x,
        size_y=size_y,
        size_z=size_z,
        size_t=size_t,
        stride_x=stride_x,
        stride_y=stride_y,
        stride_z=stride_z,
        stride_t=stride_t,
        base_name=base_name,
    )
    return self._new_from_rois(rois)

by_yx

by_yx() -> Self

Return a new iterator that iterates over ROIs by YX coordinates.

Source code in ngio/experimental/iterators/_abstract_iterator.py
91
92
93
94
def by_yx(self) -> Self:
    """Return a new iterator that iterates over ROIs by YX coordinates."""
    rois = by_yx(self.rois, self.ref_image)
    return self._new_from_rois(rois)

by_zyx

by_zyx(strict: bool = True) -> Self

Return a new iterator that iterates over ROIs by ZYX coordinates.

Parameters:

  • strict (bool, default: True ) –

    If True, only iterate over ZYX if a Z axis is present and not of size 1.

Source code in ngio/experimental/iterators/_abstract_iterator.py
 96
 97
 98
 99
100
101
102
103
104
105
def by_zyx(self, strict: bool = True) -> Self:
    """Return a new iterator that iterates over ROIs by ZYX coordinates.

    Args:
        strict (bool): If True, only iterate over ZYX if a Z axis
            is present and not of size 1.

    """
    rois = by_zyx(self.rois, self.ref_image, strict=strict)
    return self._new_from_rois(rois)

by_chunks

by_chunks(overlap_xy: int = 0, overlap_z: int = 0) -> Self

Return a new iterator that iterates over ROIs by chunks.

Parameters:

  • overlap_xy (int, default: 0 ) –

    Overlap in XY dimensions.

  • overlap_z (int, default: 0 ) –

    Overlap in Z dimension.

Returns:

  • SegmentationIterator ( Self ) –

    A new iterator with chunked ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
def by_chunks(self, overlap_xy: int = 0, overlap_z: int = 0) -> Self:
    """Return a new iterator that iterates over ROIs by chunks.

    Args:
        overlap_xy (int): Overlap in XY dimensions.
        overlap_z (int): Overlap in Z dimension.

    Returns:
        SegmentationIterator: A new iterator with chunked ROIs.
    """
    rois = by_chunks(
        self.rois, self.ref_image, overlap_xy=overlap_xy, overlap_z=overlap_z
    )
    return self._new_from_rois(rois)

product

product(other: list[Roi] | GenericRoiTable) -> Self

Cartesian product of the current ROIs with an arbitrary list of ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
122
123
124
125
126
127
def product(self, other: list[Roi] | GenericRoiTable) -> Self:
    """Cartesian product of the current ROIs with an arbitrary list of ROIs."""
    if isinstance(other, GenericRoiTable):
        other = other.rois()
    rois = rois_product(self.rois, other)
    return self._new_from_rois(rois)

iter

iter(
    lazy: Literal[True],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[
        DataGetterProtocol[NumpyPipeType],
        DataSetterProtocol[NumpyPipeType],
    ]
]
iter(
    lazy: Literal[True],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DataGetterProtocol[NumpyPipeType]]
iter(
    lazy: Literal[True],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[
        DataGetterProtocol[DaskPipeType],
        DataSetterProtocol[DaskPipeType],
    ]
]
iter(
    lazy: Literal[True],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DataGetterProtocol[DaskPipeType]]
iter(
    lazy: Literal[False],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[NumpyPipeType, DataSetterProtocol[NumpyPipeType]]
]
iter(
    lazy: Literal[False],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[NumpyPipeType]
iter(
    lazy: Literal[False],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[DaskPipeType, DataSetterProtocol[DaskPipeType]]
]
iter(
    lazy: Literal[False],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DaskPipeType]
iter(
    lazy: bool = False,
    data_mode: Literal["numpy", "dask"] = "dask",
    iterator_mode: Literal[
        "readwrite", "readonly"
    ] = "readwrite",
) -> Generator

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
def iter(
    self,
    lazy: bool = False,
    data_mode: Literal["numpy", "dask"] = "dask",
    iterator_mode: Literal["readwrite", "readonly"] = "readwrite",
) -> Generator:
    """Create an iterator over the pixels of the ROIs."""
    if data_mode == "numpy":
        getters = self._numpy_getters_generator()
        setters = self._numpy_setters_generator()
    elif data_mode == "dask":
        getters = self._dask_getters_generator()
        setters = self._dask_setters_generator()
    else:
        raise NgioValueError(f"Invalid mode: {data_mode}")

    if iterator_mode == "readonly":
        if lazy:
            return getters
        else:
            return (getter() for getter in getters)
    if lazy:
        return self._read_and_write_generator(getters, setters)
    else:
        gen = self._read_and_write_generator(getters, setters)
        return ((getter(), setter) for getter, setter in gen)

iter_as_numpy

iter_as_numpy()

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
291
292
293
294
295
def iter_as_numpy(
    self,
):
    """Create an iterator over the pixels of the ROIs."""
    return self.iter(lazy=False, data_mode="numpy", iterator_mode="readwrite")

iter_as_dask

iter_as_dask()

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
297
298
299
300
301
def iter_as_dask(
    self,
):
    """Create an iterator over the pixels of the ROIs."""
    return self.iter(lazy=False, data_mode="dask", iterator_mode="readwrite")

map_as_numpy

map_as_numpy(
    func: Callable[[NumpyPipeType], NumpyPipeType],
    mapper: MapperProtocol[NumpyPipeType] | None = None,
) -> None

Apply a transformation function to the ROI pixels.

Source code in ngio/experimental/iterators/_abstract_iterator.py
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
def map_as_numpy(
    self,
    func: Callable[[NumpyPipeType], NumpyPipeType],
    mapper: MapperProtocol[NumpyPipeType] | None = None,
) -> None:
    """Apply a transformation function to the ROI pixels."""
    if mapper is None:
        _mapper = BasicMapper[NumpyPipeType]()
    else:
        _mapper = mapper

    _mapper(
        func=func,
        getters=self._numpy_getters_generator(),
        setters=self._numpy_setters_generator(),
    )
    self.post_consolidate()

map_as_dask

map_as_dask(
    func: Callable[[DaskPipeType], DaskPipeType],
    mapper: MapperProtocol[DaskPipeType] | None = None,
) -> None

Apply a transformation function to the ROI pixels.

Source code in ngio/experimental/iterators/_abstract_iterator.py
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
def map_as_dask(
    self,
    func: Callable[[DaskPipeType], DaskPipeType],
    mapper: MapperProtocol[DaskPipeType] | None = None,
) -> None:
    """Apply a transformation function to the ROI pixels."""
    if mapper is None:
        _mapper = BasicMapper[DaskPipeType]()
    else:
        _mapper = mapper

    _mapper(
        func=func,
        getters=self._dask_getters_generator(),
        setters=self._dask_setters_generator(),
    )
    self.post_consolidate()

check_if_regions_overlap

check_if_regions_overlap() -> bool

Check if any of the ROIs overlap logically.

If two ROIs cover the same pixel, they are considered to overlap. This does not consider chunking or other storage details.

Returns:

  • bool ( bool ) –

    True if any ROIs overlap. False otherwise.

Source code in ngio/experimental/iterators/_abstract_iterator.py
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
def check_if_regions_overlap(self) -> bool:
    """Check if any of the ROIs overlap logically.

    If two ROIs cover the same pixel, they are considered to overlap.
    This does not consider chunking or other storage details.

    Returns:
        bool: True if any ROIs overlap. False otherwise.
    """
    if len(self.rois) < 2:
        # Less than 2 ROIs cannot overlap
        return False

    slicing_tuples = (
        g.slicing_ops.normalized_slicing_tuple
        for g in self._numpy_getters_generator()
    )
    x = check_if_regions_overlap(slicing_tuples)
    return x

require_no_regions_overlap

require_no_regions_overlap() -> None

Ensure that the Iterator's ROIs do not overlap.

Source code in ngio/experimental/iterators/_abstract_iterator.py
359
360
361
362
def require_no_regions_overlap(self) -> None:
    """Ensure that the Iterator's ROIs do not overlap."""
    if self.check_if_regions_overlap():
        raise NgioValueError("Some rois overlap.")

check_if_chunks_overlap

check_if_chunks_overlap() -> bool

Check if any of the ROIs overlap in terms of chunks.

If two ROIs cover the same chunk, they are considered to overlap in chunks. This does not consider pixel-level overlaps.

Returns:

  • bool ( bool ) –

    True if any ROIs overlap in chunks, False otherwise.

Source code in ngio/experimental/iterators/_abstract_iterator.py
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
def check_if_chunks_overlap(self) -> bool:
    """Check if any of the ROIs overlap in terms of chunks.

    If two ROIs cover the same chunk, they are considered to overlap in chunks.
    This does not consider pixel-level overlaps.

    Returns:
        bool: True if any ROIs overlap in chunks, False otherwise.
    """
    from ngio.io_pipes._ops_slices_utils import check_if_chunks_overlap

    if len(self.rois) < 2:
        # Less than 2 ROIs cannot overlap
        return False

    slicing_tuples = (
        g.slicing_ops.normalized_slicing_tuple
        for g in self._numpy_getters_generator()
    )
    shape = self.ref_image.shape
    chunks = self.ref_image.chunks
    return check_if_chunks_overlap(slicing_tuples, shape, chunks)

require_no_chunks_overlap

require_no_chunks_overlap() -> None

Ensure that the ROIs do not overlap in terms of chunks.

Source code in ngio/experimental/iterators/_abstract_iterator.py
387
388
389
390
def require_no_chunks_overlap(self) -> None:
    """Ensure that the ROIs do not overlap in terms of chunks."""
    if self.check_if_chunks_overlap():
        raise NgioValueError("Some rois overlap in chunks.")

get_init_kwargs

get_init_kwargs() -> dict

Return the initialization arguments for the iterator.

Source code in ngio/experimental/iterators/_segmentation.py
175
176
177
178
179
180
181
182
183
184
def get_init_kwargs(self) -> dict:
    """Return the initialization arguments for the iterator."""
    return {
        "input_image": self._input,
        "output_label": self._output,
        "channel_selection": self._channel_selection,
        "axes_order": self._axes_order,
        "input_transforms": self._input_transforms,
        "output_transforms": self._output_transforms,
    }

build_numpy_getter

build_numpy_getter(roi: Roi)
Source code in ngio/experimental/iterators/_segmentation.py
186
187
188
189
190
191
192
193
194
195
196
def build_numpy_getter(self, roi: Roi):
    return NumpyGetterMasked(
        zarr_array=self._input.zarr_array,
        dimensions=self._input.dimensions,
        roi=roi,
        label_zarr_array=self._input._label.zarr_array,
        label_dimensions=self._input._label.dimensions,
        axes_order=self._axes_order,
        transforms=self._input_transforms,
        slicing_dict=self._input_slicing_kwargs,
    )

build_numpy_setter

build_numpy_setter(roi: Roi)
Source code in ngio/experimental/iterators/_segmentation.py
198
199
200
201
202
203
204
205
206
207
208
def build_numpy_setter(self, roi: Roi):
    return NumpySetterMasked(
        roi=roi,
        zarr_array=self._output.zarr_array,
        dimensions=self._output.dimensions,
        label_zarr_array=self._input._label.zarr_array,
        label_dimensions=self._input._label.dimensions,
        axes_order=self._axes_order,
        transforms=self._output_transforms,
        remove_channel_selection=True,
    )

build_dask_getter

build_dask_getter(roi: Roi)
Source code in ngio/experimental/iterators/_segmentation.py
210
211
212
213
214
215
216
217
218
219
220
def build_dask_getter(self, roi: Roi):
    return DaskGetterMasked(
        roi=roi,
        zarr_array=self._input.zarr_array,
        dimensions=self._input.dimensions,
        label_zarr_array=self._input._label.zarr_array,
        label_dimensions=self._input._label.dimensions,
        axes_order=self._axes_order,
        transforms=self._input_transforms,
        slicing_dict=self._input_slicing_kwargs,
    )

build_dask_setter

build_dask_setter(roi: Roi)
Source code in ngio/experimental/iterators/_segmentation.py
222
223
224
225
226
227
228
229
230
231
232
def build_dask_setter(self, roi: Roi):
    return DaskSetterMasked(
        roi=roi,
        zarr_array=self._output.zarr_array,
        dimensions=self._output.dimensions,
        label_zarr_array=self._input._label.zarr_array,
        label_dimensions=self._input._label.dimensions,
        axes_order=self._axes_order,
        transforms=self._output_transforms,
        remove_channel_selection=True,
    )

post_consolidate

post_consolidate()
Source code in ngio/experimental/iterators/_segmentation.py
234
235
def post_consolidate(self):
    self._output.consolidate()

FeatureExtractorIterator

ngio.experimental.iterators.FeatureExtractorIterator

FeatureExtractorIterator(
    input_image: Image,
    input_label: Label,
    channel_selection: ChannelSlicingInputType = None,
    axes_order: Sequence[str] | None = None,
    input_transforms: Sequence[TransformProtocol]
    | None = None,
    label_transforms: Sequence[TransformProtocol]
    | None = None,
)

Bases: AbstractIteratorBuilder[NumpyPipeType, DaskPipeType]

Base class for iterators over ROIs.

Initialize the iterator with a ROI table and input/output images.

Parameters:

  • input_image (Image) –

    The input image to be used as input for the segmentation.

  • input_label (Label) –

    The input label with the segmentation masks.

  • channel_selection (ChannelSlicingInputType, default: None ) –

    Optional selection of channels to use for the segmentation.

  • axes_order (Sequence[str] | None, default: None ) –

    Optional axes order for the segmentation.

  • input_transforms (Sequence[TransformProtocol] | None, default: None ) –

    Optional transforms to apply to the input image.

  • label_transforms (Sequence[TransformProtocol] | None, default: None ) –

    Optional transforms to apply to the output label.

Source code in ngio/experimental/iterators/_feature.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
def __init__(
    self,
    input_image: Image,
    input_label: Label,
    channel_selection: ChannelSlicingInputType = None,
    axes_order: Sequence[str] | None = None,
    input_transforms: Sequence[TransformProtocol] | None = None,
    label_transforms: Sequence[TransformProtocol] | None = None,
) -> None:
    """Initialize the iterator with a ROI table and input/output images.

    Args:
        input_image (Image): The input image to be used as input for the
            segmentation.
        input_label (Label): The input label with the segmentation masks.
        channel_selection (ChannelSlicingInputType): Optional
            selection of channels to use for the segmentation.
        axes_order (Sequence[str] | None): Optional axes order for the
            segmentation.
        input_transforms (Sequence[TransformProtocol] | None): Optional
            transforms to apply to the input image.
        label_transforms (Sequence[TransformProtocol] | None): Optional
            transforms to apply to the output label.
    """
    self._input = input_image
    self._input_label = input_label
    self._ref_image = input_image
    self._rois = input_image.build_image_roi_table(name=None).rois()

    # Set iteration parameters
    self._input_slicing_kwargs = add_channel_selection_to_slicing_dict(
        image=self._input, channel_selection=channel_selection, slicing_dict={}
    )
    self._channel_selection = channel_selection
    self._axes_order = axes_order
    self._input_transforms = input_transforms
    self._label_transforms = label_transforms

    self._input.require_axes_match(self._input_label)
    self._input.require_rescalable(self._input_label)

rois property

rois: list[Roi]

Get the list of ROIs for the iterator.

ref_image property

ref_image: AbstractImage

Get the reference image for the iterator.

grid

grid(
    size_x: int | None = None,
    size_y: int | None = None,
    size_z: int | None = None,
    size_t: int | None = None,
    stride_x: int | None = None,
    stride_y: int | None = None,
    stride_z: int | None = None,
    stride_t: int | None = None,
    base_name: str = "",
) -> Self

Create a grid of ROIs based on the input image dimensions.

Source code in ngio/experimental/iterators/_abstract_iterator.py
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
def grid(
    self,
    size_x: int | None = None,
    size_y: int | None = None,
    size_z: int | None = None,
    size_t: int | None = None,
    stride_x: int | None = None,
    stride_y: int | None = None,
    stride_z: int | None = None,
    stride_t: int | None = None,
    base_name: str = "",
) -> Self:
    """Create a grid of ROIs based on the input image dimensions."""
    rois = grid(
        rois=self.rois,
        ref_image=self.ref_image,
        size_x=size_x,
        size_y=size_y,
        size_z=size_z,
        size_t=size_t,
        stride_x=stride_x,
        stride_y=stride_y,
        stride_z=stride_z,
        stride_t=stride_t,
        base_name=base_name,
    )
    return self._new_from_rois(rois)

by_yx

by_yx() -> Self

Return a new iterator that iterates over ROIs by YX coordinates.

Source code in ngio/experimental/iterators/_abstract_iterator.py
91
92
93
94
def by_yx(self) -> Self:
    """Return a new iterator that iterates over ROIs by YX coordinates."""
    rois = by_yx(self.rois, self.ref_image)
    return self._new_from_rois(rois)

by_zyx

by_zyx(strict: bool = True) -> Self

Return a new iterator that iterates over ROIs by ZYX coordinates.

Parameters:

  • strict (bool, default: True ) –

    If True, only iterate over ZYX if a Z axis is present and not of size 1.

Source code in ngio/experimental/iterators/_abstract_iterator.py
 96
 97
 98
 99
100
101
102
103
104
105
def by_zyx(self, strict: bool = True) -> Self:
    """Return a new iterator that iterates over ROIs by ZYX coordinates.

    Args:
        strict (bool): If True, only iterate over ZYX if a Z axis
            is present and not of size 1.

    """
    rois = by_zyx(self.rois, self.ref_image, strict=strict)
    return self._new_from_rois(rois)

by_chunks

by_chunks(overlap_xy: int = 0, overlap_z: int = 0) -> Self

Return a new iterator that iterates over ROIs by chunks.

Parameters:

  • overlap_xy (int, default: 0 ) –

    Overlap in XY dimensions.

  • overlap_z (int, default: 0 ) –

    Overlap in Z dimension.

Returns:

  • SegmentationIterator ( Self ) –

    A new iterator with chunked ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
def by_chunks(self, overlap_xy: int = 0, overlap_z: int = 0) -> Self:
    """Return a new iterator that iterates over ROIs by chunks.

    Args:
        overlap_xy (int): Overlap in XY dimensions.
        overlap_z (int): Overlap in Z dimension.

    Returns:
        SegmentationIterator: A new iterator with chunked ROIs.
    """
    rois = by_chunks(
        self.rois, self.ref_image, overlap_xy=overlap_xy, overlap_z=overlap_z
    )
    return self._new_from_rois(rois)

product

product(other: list[Roi] | GenericRoiTable) -> Self

Cartesian product of the current ROIs with an arbitrary list of ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
122
123
124
125
126
127
def product(self, other: list[Roi] | GenericRoiTable) -> Self:
    """Cartesian product of the current ROIs with an arbitrary list of ROIs."""
    if isinstance(other, GenericRoiTable):
        other = other.rois()
    rois = rois_product(self.rois, other)
    return self._new_from_rois(rois)

iter

iter(
    lazy: Literal[True],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[
        DataGetterProtocol[NumpyPipeType],
        DataSetterProtocol[NumpyPipeType],
    ]
]
iter(
    lazy: Literal[True],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DataGetterProtocol[NumpyPipeType]]
iter(
    lazy: Literal[True],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[
        DataGetterProtocol[DaskPipeType],
        DataSetterProtocol[DaskPipeType],
    ]
]
iter(
    lazy: Literal[True],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DataGetterProtocol[DaskPipeType]]
iter(
    lazy: Literal[False],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[NumpyPipeType, DataSetterProtocol[NumpyPipeType]]
]
iter(
    lazy: Literal[False],
    data_mode: Literal["numpy"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[NumpyPipeType]
iter(
    lazy: Literal[False],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readwrite"],
) -> Generator[
    tuple[DaskPipeType, DataSetterProtocol[DaskPipeType]]
]
iter(
    lazy: Literal[False],
    data_mode: Literal["dask"],
    iterator_mode: Literal["readonly"] = ...,
) -> Generator[DaskPipeType]
iter(
    lazy: bool = False,
    data_mode: Literal["numpy", "dask"] = "dask",
    iterator_mode: Literal[
        "readwrite", "readonly"
    ] = "readwrite",
) -> Generator

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_abstract_iterator.py
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
def iter(
    self,
    lazy: bool = False,
    data_mode: Literal["numpy", "dask"] = "dask",
    iterator_mode: Literal["readwrite", "readonly"] = "readwrite",
) -> Generator:
    """Create an iterator over the pixels of the ROIs."""
    if data_mode == "numpy":
        getters = self._numpy_getters_generator()
        setters = self._numpy_setters_generator()
    elif data_mode == "dask":
        getters = self._dask_getters_generator()
        setters = self._dask_setters_generator()
    else:
        raise NgioValueError(f"Invalid mode: {data_mode}")

    if iterator_mode == "readonly":
        if lazy:
            return getters
        else:
            return (getter() for getter in getters)
    if lazy:
        return self._read_and_write_generator(getters, setters)
    else:
        gen = self._read_and_write_generator(getters, setters)
        return ((getter(), setter) for getter, setter in gen)

map_as_numpy

map_as_numpy(
    func: Callable[[NumpyPipeType], NumpyPipeType],
    mapper: MapperProtocol[NumpyPipeType] | None = None,
) -> None

Apply a transformation function to the ROI pixels.

Source code in ngio/experimental/iterators/_abstract_iterator.py
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
def map_as_numpy(
    self,
    func: Callable[[NumpyPipeType], NumpyPipeType],
    mapper: MapperProtocol[NumpyPipeType] | None = None,
) -> None:
    """Apply a transformation function to the ROI pixels."""
    if mapper is None:
        _mapper = BasicMapper[NumpyPipeType]()
    else:
        _mapper = mapper

    _mapper(
        func=func,
        getters=self._numpy_getters_generator(),
        setters=self._numpy_setters_generator(),
    )
    self.post_consolidate()

map_as_dask

map_as_dask(
    func: Callable[[DaskPipeType], DaskPipeType],
    mapper: MapperProtocol[DaskPipeType] | None = None,
) -> None

Apply a transformation function to the ROI pixels.

Source code in ngio/experimental/iterators/_abstract_iterator.py
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
def map_as_dask(
    self,
    func: Callable[[DaskPipeType], DaskPipeType],
    mapper: MapperProtocol[DaskPipeType] | None = None,
) -> None:
    """Apply a transformation function to the ROI pixels."""
    if mapper is None:
        _mapper = BasicMapper[DaskPipeType]()
    else:
        _mapper = mapper

    _mapper(
        func=func,
        getters=self._dask_getters_generator(),
        setters=self._dask_setters_generator(),
    )
    self.post_consolidate()

check_if_regions_overlap

check_if_regions_overlap() -> bool

Check if any of the ROIs overlap logically.

If two ROIs cover the same pixel, they are considered to overlap. This does not consider chunking or other storage details.

Returns:

  • bool ( bool ) –

    True if any ROIs overlap. False otherwise.

Source code in ngio/experimental/iterators/_abstract_iterator.py
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
def check_if_regions_overlap(self) -> bool:
    """Check if any of the ROIs overlap logically.

    If two ROIs cover the same pixel, they are considered to overlap.
    This does not consider chunking or other storage details.

    Returns:
        bool: True if any ROIs overlap. False otherwise.
    """
    if len(self.rois) < 2:
        # Less than 2 ROIs cannot overlap
        return False

    slicing_tuples = (
        g.slicing_ops.normalized_slicing_tuple
        for g in self._numpy_getters_generator()
    )
    x = check_if_regions_overlap(slicing_tuples)
    return x

require_no_regions_overlap

require_no_regions_overlap() -> None

Ensure that the Iterator's ROIs do not overlap.

Source code in ngio/experimental/iterators/_abstract_iterator.py
359
360
361
362
def require_no_regions_overlap(self) -> None:
    """Ensure that the Iterator's ROIs do not overlap."""
    if self.check_if_regions_overlap():
        raise NgioValueError("Some rois overlap.")

check_if_chunks_overlap

check_if_chunks_overlap() -> bool

Check if any of the ROIs overlap in terms of chunks.

If two ROIs cover the same chunk, they are considered to overlap in chunks. This does not consider pixel-level overlaps.

Returns:

  • bool ( bool ) –

    True if any ROIs overlap in chunks, False otherwise.

Source code in ngio/experimental/iterators/_abstract_iterator.py
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
def check_if_chunks_overlap(self) -> bool:
    """Check if any of the ROIs overlap in terms of chunks.

    If two ROIs cover the same chunk, they are considered to overlap in chunks.
    This does not consider pixel-level overlaps.

    Returns:
        bool: True if any ROIs overlap in chunks, False otherwise.
    """
    from ngio.io_pipes._ops_slices_utils import check_if_chunks_overlap

    if len(self.rois) < 2:
        # Less than 2 ROIs cannot overlap
        return False

    slicing_tuples = (
        g.slicing_ops.normalized_slicing_tuple
        for g in self._numpy_getters_generator()
    )
    shape = self.ref_image.shape
    chunks = self.ref_image.chunks
    return check_if_chunks_overlap(slicing_tuples, shape, chunks)

require_no_chunks_overlap

require_no_chunks_overlap() -> None

Ensure that the ROIs do not overlap in terms of chunks.

Source code in ngio/experimental/iterators/_abstract_iterator.py
387
388
389
390
def require_no_chunks_overlap(self) -> None:
    """Ensure that the ROIs do not overlap in terms of chunks."""
    if self.check_if_chunks_overlap():
        raise NgioValueError("Some rois overlap in chunks.")

get_init_kwargs

get_init_kwargs() -> dict

Return the initialization arguments for the iterator.

Source code in ngio/experimental/iterators/_feature.py
125
126
127
128
129
130
131
132
133
134
def get_init_kwargs(self) -> dict:
    """Return the initialization arguments for the iterator."""
    return {
        "input_image": self._input,
        "input_label": self._input_label,
        "channel_selection": self._channel_selection,
        "axes_order": self._axes_order,
        "input_transforms": self._input_transforms,
        "label_transforms": self._label_transforms,
    }

build_numpy_getter

build_numpy_getter(roi: Roi) -> NumpyFeatureGetter
Source code in ngio/experimental/iterators/_feature.py
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
def build_numpy_getter(self, roi: Roi) -> NumpyFeatureGetter:
    data_getter = NumpyRoiGetter(
        zarr_array=self._input.zarr_array,
        dimensions=self._input.dimensions,
        axes_order=self._axes_order,
        transforms=self._input_transforms,
        roi=roi,
        slicing_dict=self._input_slicing_kwargs,
    )
    label_getter = NumpyRoiGetter(
        zarr_array=self._input_label.zarr_array,
        dimensions=self._input_label.dimensions,
        axes_order=self._axes_order,
        transforms=self._label_transforms,
        roi=roi,
        remove_channel_selection=True,
    )
    return NumpyFeatureGetter(data_getter, label_getter)

build_dask_getter

build_dask_getter(roi: Roi) -> DaskFeatureGetter
Source code in ngio/experimental/iterators/_feature.py
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
def build_dask_getter(self, roi: Roi) -> DaskFeatureGetter:
    data_getter = DaskRoiGetter(
        zarr_array=self._input.zarr_array,
        dimensions=self._input.dimensions,
        axes_order=self._axes_order,
        transforms=self._input_transforms,
        roi=roi,
        slicing_dict=self._input_slicing_kwargs,
    )
    label_getter = DaskRoiGetter(
        zarr_array=self._input_label.zarr_array,
        dimensions=self._input_label.dimensions,
        axes_order=self._axes_order,
        transforms=self._label_transforms,
        roi=roi,
        remove_channel_selection=True,
    )
    return DaskFeatureGetter(data_getter, label_getter)

build_numpy_setter

build_numpy_setter(roi: Roi) -> None
Source code in ngio/experimental/iterators/_feature.py
174
175
def build_numpy_setter(self, roi: Roi) -> None:
    return None

build_dask_setter

build_dask_setter(roi: Roi) -> None
Source code in ngio/experimental/iterators/_feature.py
177
178
def build_dask_setter(self, roi: Roi) -> None:
    return None

post_consolidate

post_consolidate()
Source code in ngio/experimental/iterators/_feature.py
180
181
def post_consolidate(self):
    pass

iter_as_numpy

iter_as_numpy()

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_feature.py
183
184
185
def iter_as_numpy(self):  # type: ignore[override]
    """Create an iterator over the pixels of the ROIs."""
    return self.iter(lazy=False, data_mode="numpy", iterator_mode="readonly")

iter_as_dask

iter_as_dask()

Create an iterator over the pixels of the ROIs.

Source code in ngio/experimental/iterators/_feature.py
187
188
189
def iter_as_dask(self):  # type: ignore[override]
    """Create an iterator over the pixels of the ROIs."""
    return self.iter(lazy=False, data_mode="dask", iterator_mode="readonly")