def extract_patches_sequential(
arr: np.ndarray,
patch_size: Union[list[int], tuple[int, ...]],
target: Optional[np.ndarray] = None,
) -> tuple[np.ndarray, Optional[np.ndarray]]:
"""
Generate patches from an array in a sequential manner.
Array dimensions should be SC(Z)YX, where S and C can be singleton dimensions. The
patches are generated sequentially and cover the whole array.
Parameters
----------
arr : np.ndarray
Input image array.
patch_size : tuple[int]
Patch sizes in each dimension.
target : Optional[np.ndarray], optional
Target array, by default None.
Returns
-------
tuple[np.ndarray, Optional[np.ndarray]]
Patches.
"""
is_3d_patch = len(patch_size) == 3
# Patches sanity check
validate_patch_dimensions(arr, patch_size, is_3d_patch)
# Update patch size to encompass S and C dimensions
patch_size = [1, arr.shape[1], *patch_size]
# Compute overlap
overlaps = _compute_overlap(arr_shape=arr.shape, patch_sizes=patch_size)
# Create view window and overlaps
window_steps = _compute_patch_steps(patch_sizes=patch_size, overlaps=overlaps)
output_shape = [
-1,
] + patch_size[1:]
# Generate a view of the input array containing pre-calculated number of patches
# in each dimension with overlap.
# Resulting array is resized to (n_patches, C, Z, Y, X) or (n_patches, C, Y, X)
patches = _compute_patch_views(
arr,
window_shape=patch_size,
step=window_steps,
output_shape=output_shape,
target=target,
)
if target is not None:
# target was concatenated to patches in _compute_reshaped_view
return (
patches[:, 0, ...],
patches[:, 1, ...],
) # TODO in _compute_reshaped_view?
else:
return patches, None