NonOverlapping#
- class deeptrack.features.NonOverlapping(feature: Feature, min_distance: float = 1, max_attempts: int = 5, max_iters: int = 100, **kwargs: dict[str, Any])#
Bases:
FeatureEnsure volumes are placed non-overlapping in a 3D space.
This feature ensures that a list of 3D volumes are positioned such that their non-zero voxels do not overlap. If volumes overlap, their positions are resampled until they are non-overlapping. If the maximum number of attempts is exceeded, the feature regenerates the list of volumes and raises a warning if non-overlapping placement cannot be achieved.
Note: min_distance refers to the distance between the edges of volumes, not their centers. Due to the way volumes are calculated, slight rounding errors may affect the final distance.
This feature is incompatible with non-volumetric scatterers such as MieScatterers.
Parameters#
- feature: Feature
The feature that generates the list of volumes to place non-overlapping.
- min_distance: float, optional
The minimum distance between volumes in pixels. Defaults to 1. It can be negative to allow for partial overlap.
- max_attempts: int, optional
The maximum number of attempts to place volumes without overlap. Defaults to 5.
- max_iters: int, optional
- The maximum number of resamplings. If this number is exceeded, a
new list of volumes is generated. Defaults to 100.
Attributes#
- __distributed__: bool
Indicates whether this feature distributes computation across inputs. Always False for NonOverlapping.
Methods#
- get(_: Any, min_distance: float, max_attempts: int, **kwargs: dict[str, Any]) -> list[np.ndarray]
Generate a list of non-overlapping 3D volumes.
- _check_non_overlapping(list_of_volumes: list[np.ndarray]) -> bool
Check if all volumes in the list are non-overlapping.
- _check_bounding_cubes_non_overlapping(bounding_cube_1: list[int], bounding_cube_2: list[int], min_distance: float) -> bool
Check if two bounding cubes are non-overlapping.
- _get_overlapping_cube(bounding_cube_1: list[int], bounding_cube_2: list[int]) -> list[int]
Get the overlapping cube between two bounding cubes.
- _get_overlapping_volume(volume: np.ndarray, bounding_cube: tuple[float, float, float, float, float, float], overlapping_cube: tuple[float, float, float, float, float, float]) -> np.ndarray
Get the overlapping volume between a volume and a bounding cube.
- _check_volumes_non_overlapping(volume_1: np.ndarray, volume_2: np.ndarray, min_distance: float) -> bool
Check if two volumes are non-overlapping.
- _resample_volume_position(volume: np.ndarray | Image) -> Image
Resample the position of a volume to avoid overlap.
Notes#
This feature performs bounding cube checks first to quickly reject obvious overlaps before voxel-level checks.
If the bounding cubes overlap, precise voxel-based checks are performed.
Examples#
>>> import deeptrack as dt >>> import numpy as np >>> import matplotlib.pyplot as plt
Define an ellipse scatterer with randomly positioned objects: >>> scatterer = dt.Ellipse( >>> radius= 13 * dt.units.pixels, >>> position=lambda: np.random.uniform(5, 115, size=2)* dt.units.pixels, >>> )
Create multiple scatterers: >>> scatterers = (scatterer ^ 8)
Define the optics and create the image with possible overlap: >>> optics = dt.Fluorescence() >>> im_with_overlap = optics(scatterers) >>> im_with_overlap.store_properties() >>> im_with_overlap_resolved = image_with_overlap()
Gather position from image: >>> pos_with_overlap = np.array( >>> im_with_overlap_resolved.get_property( >>> “position”, >>> get_one=False >>> ) >>> )
Enforce non-overlapping and create the image without overlap: >>> non_overlapping_scatterers = dt.NonOverlapping(scatterers, min_distance=4) >>> im_without_overlap = optics(non_overlapping_scatterers) >>> im_without_overlap.store_properties() >>> im_without_overlap_resolved = im_without_overlap()
Gather position from image: >>> pos_without_overlap = np.array( >>> im_without_overlap_resolved.get_property( >>> “position”, >>> get_one=False >>> ) >>> )
Create a figure with two subplots to visualize the difference: >>> fig, axes = plt.subplots(1, 2, figsize=(10, 5))
>>> axes[0].imshow(im_with_overlap_resolved, cmap="gray") >>> axes[0].scatter(pos_with_overlap[:,1],pos_with_overlap[:,0]) >>> axes[0].set_title("Overlapping Objects") >>> axes[0].axis("off") >>> axes[1].imshow(im_without_overlap_resolved, cmap="gray") >>> axes[1].scatter(pos_without_overlap[:,1],pos_without_overlap[:,0]) >>> axes[1].set_title("Non-Overlapping Objects") >>> axes[1].axis("off") >>> plt.tight_layout() >>> plt.show()
Define function to calculate minimum distance: >>> def calculate_min_distance(positions): >>> distances = [ >>> np.linalg.norm(positions[i] - positions[j]) >>> for i in range(len(positions)) >>> for j in range(i + 1, len(positions)) >>> ] >>> return min(distances)
Print minimum distances with and without overlap: >>> print(calculate_min_distance(pos_with_overlap)) 10.768742383382174 >>> print(calculate_min_distance(pos_without_overlap)) 30.82531120942446
Methods Summary
get(_, min_distance, max_attempts, ...)Generates a list of non-overlapping 3D volumes within a defined field of view (FOV).
Methods Documentation
- get(_: Any, min_distance: float, max_attempts: int, max_iters: int, **kwargs: dict[str, Any]) list[ndarray]#
Generates a list of non-overlapping 3D volumes within a defined field of view (FOV).
This method iteratively attempts to place volumes while ensuring they maintain at least min_distance separation. If non-overlapping placement is not achieved within max_attempts, a warning is issued, and the best available configuration is returned.
Parameters#
- _: Any
Placeholder parameter, typically for an input image.
- min_distance: float
The minimum required separation distance between volumes, in pixels.
- max_attempts: int
The maximum number of attempts to generate a valid non-overlapping configuration.
- max_iters: int
The maximum number of resampling iterations per attempt.
- **kwargs: dict[str, Any]
Additional parameters that may be used by subclasses.
Returns#
- list[np.ndarray]
A list of 3D volumes represented as NumPy arrays. If non-overlapping placement is unsuccessful, the best available configuration is returned.
Warns#
- UserWarning
If non-overlapping placement is not achieved within max_attempts, suggesting parameter adjustments such as increasing the FOV or reducing min_distance.
Notes#
The placement process prioritizes bounding cube checks for efficiency.
If bounding cubes overlap, voxel-based overlap checks are performed.