Object Analysis
Functions for analyzing and manipulating objects in binary arrays.
- objscale.label_structures(array: ndarray[tuple[int, ...], dtype[_ScalarType_co]], structure: ndarray[tuple[int, ...], dtype[_ScalarType_co]] = array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]), wrap: str | None = 'both') tuple[ndarray[tuple[int, ...], dtype[_ScalarType_co]] | None, ndarray[tuple[int, ...], dtype[_ScalarType_co]] | None, int][source]
Label connected components in a binary array.
Wrapper on
scipy.ndimage.labelwith NaN handling and optional periodic boundary merging.- Parameters:
array (np.ndarray) – 2-D binary array (0s, 1s, and optionally NaN).
structure (np.ndarray, default=4-connectivity cross) – Connectivity kernel passed to
scipy.ndimage.label.wrap (str or None, default='both') – Periodic boundary handling: -
'both': merge labels across left-right and top-bottom edges. -'sides': merge labels across left-right edges only. -None: no periodic merging.
- Returns:
labelled_array (np.ndarray or None) – Float32 array where each unique positive value is a connected component label. Pixels that were NaN in the input are 0.
Noneif no structures exist.nan_mask (np.ndarray or None) – Boolean array indicating NaN locations in the input.
Noneif no structures exist.n_labels (int) – Number of connected components found (0 if none).
- objscale.get_structure_props(array: ndarray[tuple[int, ...], dtype[_ScalarType_co]], x_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]], y_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]], structure: ndarray[tuple[int, ...], dtype[_ScalarType_co]] = array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]), print_none: bool = False) tuple[ndarray[tuple[int, ...], dtype[_ScalarType_co]], ndarray[tuple[int, ...], dtype[_ScalarType_co]], ndarray[tuple[int, ...], dtype[_ScalarType_co]], ndarray[tuple[int, ...], dtype[_ScalarType_co]]][source]
Calculate properties of structures in a binary array.
Assumes toroidal (periodic) boundary conditions. For non-periodic domains, pad edges with 0 or np.nan before calling. Any perimeter between structure and nan is not counted.
- Parameters:
array (np.ndarray) – Binary array of structures: 2-d array, padded with 0’s or np.nan’s.
x_sizes (np.ndarray) – Sizes of pixels in horizontal direction, same shape as array.
y_sizes (np.ndarray) – Sizes of pixels in vertical direction, same shape as array.
structure (np.ndarray, default=np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) – Defines connectivity.
print_none (bool, default=False) – Print message if no structures found.
- Returns:
perimeter (np.ndarray) – 1-D array, each element the perimeter of an individual structure.
area (np.ndarray) – 1-D array, each element the area of an individual structure.
height (np.ndarray) – 1-D array, each element the height of an individual structure.
width (np.ndarray) – 1-D array, each element the width of an individual structure.
- Raises:
ValueError – If array, x_sizes, and y_sizes are not the same shape. If x or y sizes are nan where array is not nan.
Notes
If x_sizes or y_sizes are not uniform, the width will be the sum of the average pixel widths of the pixels in the column and in the object. Similarly, the height will be the sum of the average pixel heights of the pixels in the row and in the object.
For better performance when only a subset of properties is needed, use the individual functions: get_structure_areas, get_structure_perimeters, get_structure_height_width.
- objscale.get_structure_areas(labelled_array: ndarray[tuple[int, ...], dtype[_ScalarType_co]], nan_mask: ndarray[tuple[int, ...], dtype[_ScalarType_co]], n_labels: int, x_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]], y_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]]) ndarray[tuple[int, ...], dtype[_ScalarType_co]][source]
Calculate areas of labelled structures.
- Parameters:
labelled_array (np.ndarray) – Labelled array from
label_structures().nan_mask (np.ndarray) – Boolean NaN mask from
label_structures().n_labels (int) – Number of labels from
label_structures().x_sizes (np.ndarray) – Pixel sizes in horizontal direction, same shape as labelled_array.
y_sizes (np.ndarray) – Pixel sizes in vertical direction, same shape as labelled_array.
- Returns:
areas – 1-D array of shape
(n_labels,)whereareas[i]is the area of labeli + 1. Guarantees index alignment with otherget_structure_*functions called on the same labelled array.- Return type:
np.ndarray
- objscale.get_structure_perimeters(labelled_array: ndarray[tuple[int, ...], dtype[_ScalarType_co]], nan_mask: ndarray[tuple[int, ...], dtype[_ScalarType_co]], n_labels: int, x_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]], y_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]]) ndarray[tuple[int, ...], dtype[_ScalarType_co]][source]
Calculate perimeters of labelled structures.
Perimeter between a structure and NaN is not counted.
- Parameters:
labelled_array (np.ndarray) – Labelled array from
label_structures().nan_mask (np.ndarray) – Boolean NaN mask from
label_structures().n_labels (int) – Number of labels from
label_structures().x_sizes (np.ndarray) – Pixel sizes in horizontal direction, same shape as labelled_array.
y_sizes (np.ndarray) – Pixel sizes in vertical direction, same shape as labelled_array.
- Returns:
perimeters – 1-D array of shape
(n_labels,)whereperimeters[i]is the perimeter of labeli + 1. Guarantees index alignment with otherget_structure_*functions called on the same labelled array.- Return type:
np.ndarray
- objscale.get_structure_height_width(labelled_array: ndarray[tuple[int, ...], dtype[_ScalarType_co]], nan_mask: ndarray[tuple[int, ...], dtype[_ScalarType_co]], n_labels: int, x_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]], y_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]]) tuple[ndarray[tuple[int, ...], dtype[_ScalarType_co]], ndarray[tuple[int, ...], dtype[_ScalarType_co]]][source]
Calculate heights and widths of labelled structures as bounding-box extents.
The height of a structure is the physical extent spanned by its bounding-box rows; the width is the physical extent spanned by its bounding-box columns. For structures that span a periodic boundary (when
labelled_arraywas produced withwrap='both'or'sides'), the smallest wrap-aware extent is used.- Parameters:
labelled_array (np.ndarray) – Labelled array from
label_structures().nan_mask (np.ndarray) – Boolean NaN mask from
label_structures(). Currently unused; kept for signature compatibility with the otherget_structure_*functions.n_labels (int) – Number of labels from
label_structures().x_sizes (np.ndarray) – Pixel sizes in horizontal direction, same shape as labelled_array.
y_sizes (np.ndarray) – Pixel sizes in vertical direction, same shape as labelled_array.
- Returns:
heights (np.ndarray) – 1-D array of shape
(n_labels,)whereheights[i]is the height of labeli + 1.widths (np.ndarray) – 1-D array of shape
(n_labels,)wherewidths[i]is the width of labeli + 1.
Notes
Widths are well-defined only when
x_sizesis constant within each column (x_sizes[:, j]does not vary for anyj); heights are well-defined only wheny_sizesis constant within each row. If either invariant is violated, aUserWarningis emitted and a per-row / per-column nanmean is used as the canonical pixel size.
- objscale.get_every_boundary_perimeter(array: ndarray[tuple[int, ...], dtype[_ScalarType_co]], x_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]], y_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]], return_nlevels: bool = False) list | tuple[list, int][source]
Return perimeters of each boundary between 0s and 1s.
Each individual boundary between 0s and 1s in the array is treated as a unique perimeter. For example, a donut of 1s gives 2 values: one for the inner circle and one for the outer circle.
- Parameters:
array (np.ndarray) – 2-D binary array containing only 0s and 1s.
x_sizes (np.ndarray) – Sizes of pixels in horizontal direction, same shape as array.
y_sizes (np.ndarray) – Sizes of pixels in vertical direction, same shape as array.
return_nlevels (bool, default=False) – If True, also return the number of nesting levels processed.
- Returns:
perimeters (list) – List of perimeter values for each boundary.
nlevels (int, optional) – Number of nesting levels. Only returned if return_nlevels=True.
- Raises:
ValueError – If more than 100 nesting levels are found (likely infinite loop).
- objscale.total_perimeter(array, x_sizes, y_sizes)[source]
Calculate the total perimeter of a binary array.
Given a binary array, calculate the total perimeter. Only counts perimeter along edges between 1 and 0. Assumes periodic boundary conditions; for other boundary conditions, pad inputs with 0s or nans.
- Parameters:
array (np.ndarray) – Binary array (0s and 1s).
x_sizes (np.ndarray) – Pixel sizes in x direction.
y_sizes (np.ndarray) – Pixel sizes in y direction.
- Returns:
Total perimeter length.
- Return type:
float
- Raises:
ValueError – If x_sizes or y_sizes is nan where array is 1.
- objscale.total_number(array: ndarray[tuple[int, ...], dtype[_ScalarType_co]], structure: ndarray[tuple[int, ...], dtype[_ScalarType_co]] = array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) int[source]
Count the number of connected objects in an array.
Given a 2-D array with 0’s, nans, and 1’s, calculate number of objects of connected 1’s where connectivity is defined by structure.
- Parameters:
array (np.ndarray) – 2-D array with 0s, 1s, and optionally nans.
structure (np.ndarray, default=np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) – Connectivity structure.
- Returns:
Number of connected objects.
- Return type:
int
- objscale.isolate_nth_largest_structure(binary_array: ndarray[tuple[int, ...], dtype[_ScalarType_co]], n: int = 1, structure: ndarray[tuple[int, ...], dtype[_ScalarType_co]] = array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) ndarray[tuple[int, ...], dtype[bool]][source]
Isolate the Nth largest connected structure in a binary array.
- Parameters:
binary_array (np.ndarray) – Binary input array.
n (int, default=1) – Which structure to return, ranked by pixel count (1 = largest).
structure (np.ndarray, default=np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) – Connectivity structure.
- Returns:
Boolean array with only the Nth largest structure set to True.
- Return type:
np.ndarray
- Raises:
ValueError – If
binary_arraycontains no structures ornexceeds the number of structures.
- objscale.remove_structures_touching_border_nan(array: ndarray[tuple[int, ...], dtype[_ScalarType_co]]) ndarray[tuple[int, ...], dtype[_ScalarType_co]][source]
Remove structures that touch the NaN border of an array.
- Parameters:
array (np.ndarray) – 2-D array consisting of 0s, 1s, and np.nan. All values at the array edge should be np.nan.
- Returns:
2-D array consisting of 0s, 1s, and np.nan with any structure in contact with the nan values around the outer edge of the good data removed. Contact is defined using adjacent connectivity (4-connectivity).
- Return type:
np.ndarray
- Raises:
ValueError – If array is not 2-dimensional.
- objscale.remove_structure_holes(array: ndarray[tuple[int, ...], dtype[_ScalarType_co]], periodic: bool | str = False) ndarray[tuple[int, ...], dtype[_ScalarType_co]][source]
Fill in all holes in all structures within the array.
Sets any value of 0 that is not connected to the largest connected structure of 0s (the background) to 1. Assumes the largest contiguous area of 0s is the background.
- Parameters:
array (np.ndarray) – 2D array with values either 0, 1, or np.nan.
periodic (bool or str, default=False) – Boundary condition handling. Options: - False: Holes connected to the edge are filled (as if padded with 1s). - ‘sides’: Periodic boundary on left/right edges. - ‘both’: Periodic boundary on all edges.
- Returns:
Array with all structure holes filled.
- Return type:
np.ndarray
- Raises:
ValueError – If array is not a numpy array or contains values other than 0, 1, or np.nan.
- objscale.clear_border_adjacent(array: ndarray[tuple[int, ...], dtype[_ScalarType_co]], structure: ndarray[tuple[int, ...], dtype[_ScalarType_co]] = array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) ndarray[tuple[int, ...], dtype[bool]][source]
Remove connected regions that touch the array border.
Similar to skimage.segmentation.clear_border but allows custom connectivity structure.
- Parameters:
array (np.ndarray) – 2-D array consisting of 0s and 1s.
structure (np.ndarray, default=np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])) – Defines connectivity for determining connected regions.
- Returns:
2-D boolean array with border-touching structures removed.
- Return type:
np.ndarray
Examples
For a structure of
np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]]):[[0,0,0,0], [0,1,1,0], [0,0,0,1], [0,0,0,0]]-> keeps middle structure[[0,0,0,0], [0,1,1,0], [0,0,1,1], [0,0,0,0]]-> removes all (connected to border)[[0,0,0,0], [0,1,0,0], [1,0,0,0], [0,0,0,0]]-> keeps middle structure
- objscale.label_size(array: ndarray[tuple[int, ...], dtype[_ScalarType_co]], variable: str = 'area', wrap: str | None = 'both', x_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]] | None = None, y_sizes: ndarray[tuple[int, ...], dtype[_ScalarType_co]] | None = None) ndarray[tuple[int, ...], dtype[_ScalarType_co]][source]
Label structures with their size values.
Creates a labelled array where each structure is labelled with its size (area, summed perimeter, width, or height) instead of a unique identifier.
- Parameters:
array (np.ndarray) – Binary array of structures: 2-d array, padded with 0’s or np.nan’s.
variable (str, default='area') – Which variable to use for ‘size’. Options:
'area','summed perimeter','width','height'.'perimeter'is accepted but deprecated.wrap (str or None, default='both') – Boundary wrapping options: None, ‘sides’, ‘both’. If ‘sides’, connect structures that span the left/right edge. If ‘both’, connect structures that span all edges.
x_sizes (np.ndarray, optional) – Pixel sizes in x direction. If None, assume all sizes are 1.
y_sizes (np.ndarray, optional) – Pixel sizes in y direction. If None, assume all sizes are 1.
- Returns:
Array where structures are labelled with their size value and background is 0.
- Return type:
np.ndarray
- Raises:
ValueError – If variable or wrap is not a supported value.
Notes
If x_sizes or y_sizes are not uniform, the width will be the sum of the average pixel widths of the pixels in the column and in the object. Similarly, the height will be the sum of the average pixel heights of the pixels in the row and in the object.