Containers
Spatial data structures for efficient nearest neighbor queries.
Containers module.
This module provides spatial data structures for efficient nearest neighbor queries, spatial indexing, and tracking containers.
Spatial Index Hierarchy
All spatial index structures inherit from BaseSpatialIndex which defines a common interface for k-nearest neighbor and radius queries:
BaseSpatialIndex (abstract) ├── KDTree - K-dimensional tree (Euclidean space) ├── BallTree - Ball tree variant of KD-tree ├── RTree - Rectangle tree for bounding boxes └── MetricSpatialIndex (abstract)
├── VPTree - Vantage point tree (any metric) └── CoverTree - Cover tree (any metric)
- class pytcl.containers.BaseSpatialIndex(data)[source]
Bases:
ABCAbstract base class for spatial indexing data structures.
All spatial index implementations (KDTree, VPTree, RTree, CoverTree) should inherit from this class and implement the required methods.
This provides a consistent interface for: - Building the index from point data - k-nearest neighbor queries - Range/radius queries - Dimension and size introspection
- Parameters:
data (array_like) – Data points of shape (n_samples, n_features).
- data
The indexed data points.
- Type:
ndarray
- abstractmethod query(X, k=1)[source]
Query the index for k nearest neighbors.
- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
k (int, optional) – Number of nearest neighbors to return. Default is 1.
- Returns:
result – Named tuple with indices and distances of k nearest neighbors for each query point.
- Return type:
- query_ball_point(X, r)[source]
Query the index for all points within radius r.
This is an alias for
query_radius()provided for compatibility with scipy.spatial.KDTree.- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
r (float) – Search radius.
- Returns:
indices – For each query point, a list of indices of data points within distance r.
- Return type:
See also
query_radiusThe underlying implementation.
- class pytcl.containers.MetricSpatialIndex(data, metric=None)[source]
Bases:
BaseSpatialIndexBase class for metric space spatial indices.
Extends BaseSpatialIndex with support for custom distance metrics. Used by VP-trees and Cover trees which can work with any metric.
- Parameters:
data (array_like) – Data points of shape (n_samples, n_features).
metric (callable, optional) – Distance function with signature metric(x, y) -> float. Default is Euclidean distance.
- class pytcl.containers.NeighborResult(indices, distances)[source]
Bases:
NamedTupleUnified result type for spatial index queries.
All spatial index implementations (KDTree, BallTree, VPTree, CoverTree, RTree) return this type from their query methods, ensuring a consistent interface across the library.
- indices
Indices of the k nearest neighbors in the original data array. For k=1, may be 1D. For k>1, shape is (n_queries, k).
- Type:
ndarray of shape (n_queries, k) or (n_queries,)
- distances
Distances to the k nearest neighbors. Same shape as indices.
- Type:
ndarray of shape (n_queries, k) or (n_queries,)
Examples
>>> from pytcl.containers import KDTree >>> import numpy as np >>> points = np.array([[0, 0], [1, 0], [0, 1], [1, 1]]) >>> tree = KDTree(points) >>> result = tree.query([[0.1, 0.1]], k=2) >>> result.indices array([[0, 2]]) >>> result.distances array([[0.14142136, 0.9 ]])
See also
BaseSpatialIndexAbstract base class for spatial indices.
- pytcl.containers.validate_query_input(X, n_features)[source]
Validate and reshape query input.
- Parameters:
X (array_like) – Query points.
n_features (int) – Expected number of features.
- Returns:
X – Validated query array of shape (n_queries, n_features).
- Return type:
ndarray
- Raises:
ValueError – If query has wrong number of features.
- pytcl.containers.SpatialQueryResult
alias of
NeighborResult
- pytcl.containers.NearestNeighborResult
alias of
NeighborResult
- pytcl.containers.VPTreeResult
alias of
NeighborResult
- pytcl.containers.CoverTreeResult
alias of
NeighborResult
- class pytcl.containers.KDNode(point, index, split_dim)[source]
Bases:
objectA node in the k-d tree.
- point
The point stored at this node.
- Type:
ndarray
- point
- index
- split_dim
- class pytcl.containers.KDTree(data, leaf_size=10)[source]
Bases:
BaseSpatialIndexK-D Tree for efficient spatial queries.
A k-d tree recursively partitions space by splitting along different dimensions at each level. This enables O(log n) average-case nearest neighbor queries.
- Parameters:
data (array_like) – Data points of shape (n_samples, n_features).
leaf_size (int, optional) – Maximum number of points in a leaf node. Default 10.
Examples
>>> import numpy as np >>> points = np.array([[0, 0], [1, 0], [0, 1], [1, 1]]) >>> tree = KDTree(points) >>> result = tree.query(np.array([[0.1, 0.1]]), k=2) >>> result.indices array([[0, 1]])
Notes
The tree is balanced by choosing the median point along the split dimension at each level, giving O(n log n) construction time.
Query complexity is O(log n) on average for nearest neighbor search, though worst case is O(n) for highly unbalanced queries.
See also
BaseSpatialIndexAbstract base class defining the spatial index interface.
BallTreeAlternative spatial index using hyperspheres.
- query(X, k=1)[source]
Query the tree for k nearest neighbors.
- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
k (int, optional) – Number of nearest neighbors. Default 1.
- Returns:
result – Indices and distances of k nearest neighbors for each query.
- Return type:
Examples
>>> tree = KDTree(np.array([[0, 0], [1, 1], [2, 2]])) >>> result = tree.query([[0.5, 0.5]], k=2) >>> result.indices array([[0, 1]])
- query_radius(X, r)[source]
Query the tree for all points within radius r.
- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
r (float) – Query radius.
- Returns:
indices – For each query, a list of indices of points within radius r.
- Return type:
list of lists
Examples
>>> tree = KDTree(np.array([[0, 0], [1, 0], [0, 1], [5, 5]])) >>> tree.query_radius([[0, 0]], r=1.5) [[0, 1, 2]]
- class pytcl.containers.BallTree(data, leaf_size=10)[source]
Bases:
BaseSpatialIndexBall Tree for efficient spatial queries.
A ball tree partitions space using hyperspheres (balls), which can be more efficient than k-d trees for high-dimensional data or non-Euclidean metrics.
- Parameters:
data (array_like) – Data points of shape (n_samples, n_features).
leaf_size (int, optional) – Maximum number of points in a leaf node. Default 10.
Examples
>>> import numpy as np >>> points = np.array([[0, 0], [1, 0], [0, 1], [1, 1]]) >>> tree = BallTree(points) >>> result = tree.query(np.array([[0.1, 0.1]]), k=2)
Notes
Ball trees have O(n log n) construction and O(log n) average-case query time. They can outperform k-d trees in high dimensions.
See also
BaseSpatialIndexAbstract base class defining the spatial index interface.
KDTreeAlternative spatial index using axis-aligned splits.
- query(X, k=1)[source]
Query the tree for k nearest neighbors.
- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
k (int, optional) – Number of nearest neighbors. Default 1.
- Returns:
result – Indices and distances of k nearest neighbors.
- Return type:
- class pytcl.containers.BoundingBox(min_coords, max_coords)[source]
Bases:
NamedTupleAxis-aligned bounding box.
- min_coords
Minimum coordinates in each dimension.
- Type:
ndarray
- max_coords
Maximum coordinates in each dimension.
- Type:
ndarray
- pytcl.containers.box_from_points(points)[source]
Create minimum bounding box containing all points.
- class pytcl.containers.RTreeNode(is_leaf=True)[source]
Bases:
objectNode in an R-tree.
- bbox
Bounding box of this node.
- Type:
- is_leaf
- entries: List[Tuple[BoundingBox, int]]
- bbox: BoundingBox | None
- class pytcl.containers.RTreeResult(indices, boxes)[source]
Bases:
NamedTupleResult of R-tree query.
- boxes: List[BoundingBox]
Alias for field number 1
- class pytcl.containers.RTree(max_entries=10, min_entries=None)[source]
Bases:
objectR-tree for spatial indexing of bounding boxes.
An R-tree groups nearby objects and represents them with their minimum bounding rectangle. This allows efficient spatial queries.
Unlike KDTree and BallTree which only index points, RTree can index bounding boxes of arbitrary size. It also supports dynamic insertion.
- Parameters:
Examples
>>> tree = RTree() >>> tree.insert(BoundingBox(np.array([0, 0]), np.array([1, 1])), 0) >>> tree.insert(BoundingBox(np.array([2, 2]), np.array([3, 3])), 1) >>> query_box = BoundingBox(np.array([0.5, 0.5]), np.array([2.5, 2.5])) >>> result = tree.query_intersect(query_box)
Notes
This implementation uses a simplified insertion algorithm. For production use, consider using R*-tree or packed R-tree variants.
See also
- classmethod from_points(data, max_entries=10, min_entries=None)[source]
Create an RTree from point data.
This factory method provides an interface similar to KDTree and BallTree, allowing RTree to be used interchangeably for point queries.
- Parameters:
- Returns:
tree – RTree with all points inserted.
- Return type:
Examples
>>> points = np.array([[0, 0], [1, 0], [0, 1], [1, 1]]) >>> tree = RTree.from_points(points) >>> result = tree.query([[0.1, 0.1]], k=2)
- insert(bbox, data_index=None)[source]
Insert a bounding box into the tree.
- Parameters:
bbox (BoundingBox) – Bounding box to insert.
data_index (int, optional) – Index to associate with this box. If None, uses next available.
- Returns:
index – Index of the inserted entry.
- Return type:
- query(X, k=1)[source]
Query the tree for k nearest neighbors.
This method provides API compatibility with KDTree and BallTree.
- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
k (int, optional) – Number of nearest neighbors. Default 1.
- Returns:
result – Indices and distances of k nearest neighbors for each query.
- Return type:
Examples
>>> tree = RTree.from_points(np.array([[0, 0], [1, 1], [2, 2]])) >>> result = tree.query([[0.5, 0.5]], k=2) >>> result.indices array([[0, 1]])
- query_radius(X, r)[source]
Query the tree for all points within radius r.
This method provides API compatibility with KDTree and BallTree.
- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
r (float) – Query radius.
- Returns:
indices – For each query, a list of indices of points within radius r.
- Return type:
list of lists
Examples
>>> tree = RTree.from_points(np.array([[0, 0], [1, 0], [0, 1], [5, 5]])) >>> tree.query_radius([[0, 0]], r=1.5) [[0, 1, 2]]
- query_ball_point(X, r)[source]
Query the tree for all points within radius r.
This is an alias for
query_radius()provided for compatibility with scipy.spatial.KDTree.- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
r (float) – Search radius.
- Returns:
indices – For each query point, a list of indices of data points within distance r.
- Return type:
See also
query_radiusThe underlying implementation.
- query_intersect(query_bbox)[source]
Find all entries intersecting a query box.
- Parameters:
query_bbox (BoundingBox) – Query bounding box.
- Returns:
result – Indices and boxes of intersecting entries.
- Return type:
- query_contains(query_bbox)[source]
Find all entries contained within a query box.
- Parameters:
query_bbox (BoundingBox) – Query bounding box.
- Returns:
result – Indices and boxes of contained entries.
- Return type:
- query_point(point)[source]
Find all entries containing a point.
- Parameters:
point (array_like) – Query point.
- Returns:
result – Indices and boxes of entries containing the point.
- Return type:
- class pytcl.containers.VPNode(index, radius=0.0)[source]
Bases:
objectNode in a VP-tree.
- index
- radius
- class pytcl.containers.VPTree(data, metric=None)[source]
Bases:
MetricSpatialIndexVantage Point Tree for metric space nearest neighbor search.
A VP-tree recursively partitions space by selecting a vantage point and dividing remaining points into those closer than a threshold (median distance) and those farther.
- Parameters:
data (array_like) – Data points of shape (n_samples, n_features).
metric (callable, optional) – Distance function metric(x, y) -> float. Default is Euclidean distance.
Examples
>>> import numpy as np >>> points = np.random.rand(100, 3) >>> tree = VPTree(points) >>> result = tree.query(points[:5], k=3) >>> result.indices.shape (5, 3)
Notes
VP-trees can use any metric distance function, making them useful for non-Euclidean spaces (e.g., edit distance for strings, geodesic distance on manifolds).
Query complexity is O(log n) on average but can degrade to O(n) for pathological distance distributions.
See also
MetricSpatialIndexAbstract base class for metric-based spatial indices.
CoverTreeAlternative metric space index with theoretical guarantees.
- class pytcl.containers.CoverTreeNode(index, level)[source]
Bases:
objectNode in a Cover tree.
- index
- level
- children: dict[int, List[CoverTreeNode]]
- class pytcl.containers.CoverTree(data, metric=None, base=2.0)[source]
Bases:
MetricSpatialIndexCover Tree for metric space nearest neighbor search.
A cover tree maintains a hierarchy of nested coverings of the data, where points at level i are a subset of points at level i-1 and cover all points within distance 2^i.
- Parameters:
data (array_like) – Data points of shape (n_samples, n_features).
metric (callable, optional) – Distance function metric(x, y) -> float. Default is Euclidean distance.
base (float, optional) – Base for the exponential scale. Default 2.0.
Examples
>>> import numpy as np >>> points = np.random.rand(100, 3) >>> tree = CoverTree(points) >>> result = tree.query(points[:5], k=3)
Notes
Cover trees provide theoretical guarantees based on the expansion constant of the data. For well-distributed data, queries are efficient even in high dimensions.
The implementation uses a simplified version of the original algorithm for clarity.
See also
MetricSpatialIndexAbstract base class for metric-based spatial indices.
VPTreeAlternative metric space index using vantage points.
- root: CoverTreeNode | None
- class pytcl.containers.TrackList(tracks=None)[source]
Bases:
objectCollection of tracks with query and filter capabilities.
Provides: - Filtering by status, time, region - Iteration and indexing - Batch state extraction - Statistics computation
- Parameters:
tracks (Iterable[Track], optional) – Initial tracks to add to the list.
Examples
>>> import numpy as np >>> from pytcl.trackers.multi_target import Track, TrackStatus >>> # Create some tracks >>> t1 = Track(id=0, state=np.array([1, 0, 2, 0]), ... covariance=np.eye(4), status=TrackStatus.CONFIRMED, ... hits=5, misses=0, time=1.0) >>> t2 = Track(id=1, state=np.array([5, 0, 6, 0]), ... covariance=np.eye(4), status=TrackStatus.TENTATIVE, ... hits=2, misses=1, time=1.0) >>> # Create track list >>> tracks = TrackList([t1, t2]) >>> len(tracks) 2 >>> # Filter by status >>> confirmed = tracks.confirmed >>> len(confirmed) 1 >>> # Get positions >>> positions = tracks.positions(indices=(0, 2)) >>> positions.shape (2, 2)
- classmethod from_tracker(tracker)[source]
Create a TrackList from a MultiTargetTracker.
- Parameters:
tracker (MultiTargetTracker) – The tracker to extract tracks from.
- Returns:
A new TrackList containing the tracker’s current tracks.
- Return type:
- filter_by_status(status)[source]
Filter tracks by status.
- Parameters:
status (TrackStatus) – Status to filter by.
- Returns:
New TrackList containing only tracks with the given status.
- Return type:
- filter_by_predicate(predicate)[source]
Filter tracks using a custom predicate.
- Parameters:
predicate (callable) – Function that takes a Track and returns True to include it.
- Returns:
New TrackList containing tracks that pass the predicate.
- Return type:
- states()[source]
Extract all track states as array.
- Returns:
Array of shape (n_tracks, state_dim) containing all states.
- Return type:
ndarray
- covariances()[source]
Extract all track covariances as array.
- Returns:
Array of shape (n_tracks, state_dim, state_dim).
- Return type:
ndarray
- stats()[source]
Compute statistics about the track list.
- Returns:
Statistics about the tracks.
- Return type:
- merge(other)[source]
Merge with another TrackList.
- Parameters:
other (TrackList) – TrackList to merge with.
- Returns:
New TrackList containing tracks from both lists.
- Return type:
Notes
Duplicate track IDs are not handled specially - both tracks will be included. Use get_by_id on the result to access specific tracks.
- class pytcl.containers.TrackQuery(tracks, indices)[source]
Bases:
NamedTupleResult of a track list query.
- class pytcl.containers.TrackListStats(n_tracks, n_confirmed, n_tentative, n_deleted, mean_hits, mean_misses)[source]
Bases:
NamedTupleStatistics about a track list.
- class pytcl.containers.Measurement(value, time, covariance=None, sensor_id=0, id=-1)[source]
Bases:
NamedTupleSingle measurement with metadata.
- value
Measurement vector.
- Type:
ndarray
- covariance
Measurement covariance matrix.
- Type:
ndarray, optional
- class pytcl.containers.MeasurementSet(measurements=None)[source]
Bases:
objectCollection of measurements with time and spatial indexing.
Provides: - Time-windowed queries - Spatial region queries - Sensor filtering - Batch value extraction
- Parameters:
measurements (Iterable[Measurement], optional) – Initial measurements to add.
Examples
>>> import numpy as np >>> # Create measurements >>> m1 = Measurement(value=np.array([1.0, 2.0]), time=0.0, id=0) >>> m2 = Measurement(value=np.array([3.0, 4.0]), time=0.0, id=1) >>> m3 = Measurement(value=np.array([5.0, 6.0]), time=1.0, id=2) >>> # Create measurement set >>> mset = MeasurementSet([m1, m2, m3]) >>> len(mset) 3 >>> # Filter by time >>> at_t0 = mset.at_time(0.0) >>> len(at_t0) 2 >>> # Get values >>> values = mset.values() >>> values.shape (3, 2)
- classmethod from_arrays(values, times, covariances=None, sensor_ids=None)[source]
Create MeasurementSet from arrays.
- Parameters:
values (array_like) – Array of shape (n_meas, meas_dim) containing measurement values.
times (array_like) – Array of length n_meas containing measurement times.
covariances (array_like, optional) – Array of shape (n_meas, meas_dim, meas_dim) containing covariances.
sensor_ids (array_like, optional) – Array of length n_meas containing sensor IDs.
- Returns:
New MeasurementSet containing the measurements.
- Return type:
- __getitem__(idx)[source]
Get measurement by index or slice.
- Parameters:
- Returns:
Single measurement if int, MeasurementSet if slice.
- Return type:
- at_time(time, tolerance=1e-09)[source]
Get measurements at a specific time.
- Parameters:
- Returns:
Measurements at the specified time.
- Return type:
- in_time_window(start, end)[source]
Get measurements in a time window.
- Parameters:
- Returns:
Measurements within the time window.
- Return type:
- in_region(center, radius)[source]
Get measurements within a spatial region.
- Parameters:
center (array_like) – Center point of the region.
radius (float) – Radius of the region.
- Returns:
Measurements within the region.
- Return type:
- by_sensor(sensor_id)[source]
Get measurements from a specific sensor.
- Parameters:
sensor_id (int) – Sensor ID to filter by.
- Returns:
Measurements from the specified sensor.
- Return type:
- nearest_to(point, k=1)[source]
Find k nearest measurements to a point.
- Parameters:
point (array_like) – Query point.
k (int, optional) – Number of nearest neighbors (default: 1).
- Returns:
Query result with measurements and indices.
- Return type:
Notes
This method builds a spatial index on first call if not already built.
- values()[source]
Extract all measurement values as array.
- Returns:
Array of shape (n_meas, meas_dim).
- Return type:
ndarray
- add(measurement)[source]
Add a measurement and return a new MeasurementSet.
- Parameters:
measurement (Measurement) – Measurement to add.
- Returns:
New MeasurementSet with the measurement added.
- Return type:
- add_batch(measurements)[source]
Add multiple measurements and return a new MeasurementSet.
- Parameters:
measurements (Iterable[Measurement]) – Measurements to add.
- Returns:
New MeasurementSet with the measurements added.
- Return type:
- merge(other)[source]
Merge with another MeasurementSet.
- Parameters:
other (MeasurementSet) – MeasurementSet to merge with.
- Returns:
New MeasurementSet containing measurements from both.
- Return type:
- class pytcl.containers.MeasurementQuery(measurements, indices)[source]
Bases:
NamedTupleResult of a measurement set query.
- measurements
List of measurements matching the query.
- Type:
List[Measurement]
- measurements: List[Measurement]
Alias for field number 0
- class pytcl.containers.TrackCluster(id, track_ids, centroid, covariance, time)[source]
Bases:
NamedTupleA cluster of related tracks.
- centroid
Cluster center position.
- Type:
ndarray
- covariance
Cluster spread covariance matrix.
- Type:
ndarray
- class pytcl.containers.ClusterSet(clusters=None)[source]
Bases:
objectCollection of track clusters.
Provides: - Cluster creation from tracks - Cluster queries - Cluster merging/splitting
- Parameters:
clusters (Iterable[TrackCluster], optional) – Initial clusters to add.
Examples
>>> import numpy as np >>> from pytcl.trackers.multi_target import Track, TrackStatus >>> from pytcl.containers.track_list import TrackList >>> # Create some tracks in two groups >>> t1 = Track(id=0, state=np.array([0, 0, 0, 0]), ... covariance=np.eye(4), status=TrackStatus.CONFIRMED, ... hits=5, misses=0, time=1.0) >>> t2 = Track(id=1, state=np.array([1, 0, 1, 0]), ... covariance=np.eye(4), status=TrackStatus.CONFIRMED, ... hits=5, misses=0, time=1.0) >>> t3 = Track(id=2, state=np.array([10, 0, 10, 0]), ... covariance=np.eye(4), status=TrackStatus.CONFIRMED, ... hits=5, misses=0, time=1.0) >>> tracks = TrackList([t1, t2, t3]) >>> # Cluster using DBSCAN >>> clusters = cluster_tracks_dbscan(tracks, eps=5.0, min_samples=2)
- classmethod from_tracks(tracks, method='dbscan', **kwargs)[source]
Create a ClusterSet by clustering tracks.
- Parameters:
- Returns:
New ClusterSet containing the computed clusters.
- Return type:
Examples
>>> clusters = ClusterSet.from_tracks(tracks, method='dbscan', eps=2.0) >>> clusters = ClusterSet.from_tracks(tracks, method='kmeans', n_clusters=3)
- __getitem__(idx)[source]
Get cluster by index or slice.
- Parameters:
- Returns:
Single cluster if int, ClusterSet if slice.
- Return type:
- get_cluster(cluster_id)[source]
Get cluster by ID.
- Parameters:
cluster_id (int) – Cluster ID to find.
- Returns:
The cluster if found, None otherwise.
- Return type:
TrackCluster or None
- get_cluster_for_track(track_id)[source]
Get the cluster containing a specific track.
- Parameters:
track_id (int) – Track ID to find.
- Returns:
The cluster containing the track, or None if not found.
- Return type:
TrackCluster or None
- clusters_in_region(center, radius)[source]
Get clusters with centroids within a spatial region.
- Parameters:
center (array_like) – Center point [x, y].
radius (float) – Radius of the region.
- Returns:
Clusters within the region.
- Return type:
list of TrackCluster
- cluster_stats(cluster_id, tracks=None, state_indices=(0, 2), velocity_indices=(1, 3))[source]
Compute statistics for a cluster.
- Parameters:
cluster_id (int) – ID of the cluster.
tracks (TrackList, optional) – TrackList containing the tracks. Required for velocity coherence.
state_indices (tuple of int, optional) – Indices of x and y in state vector (default: (0, 2)).
velocity_indices (tuple of int, optional) – Indices of vx and vy in state vector (default: (1, 3)).
- Returns:
Statistics for the cluster, or None if cluster not found.
- Return type:
ClusterStats or None
- all_stats(tracks=None, state_indices=(0, 2), velocity_indices=(1, 3))[source]
Compute statistics for all clusters.
- Parameters:
- Returns:
Mapping from cluster ID to ClusterStats.
- Return type:
- add_cluster(cluster)[source]
Add a cluster and return a new ClusterSet.
- Parameters:
cluster (TrackCluster) – Cluster to add.
- Returns:
New ClusterSet with the cluster added.
- Return type:
- remove_cluster(cluster_id)[source]
Remove a cluster by ID and return a new ClusterSet.
- Parameters:
cluster_id (int) – ID of cluster to remove.
- Returns:
New ClusterSet without the specified cluster.
- Return type:
- merge_clusters(id1, id2, new_id=None)[source]
Merge two clusters into one.
- Parameters:
- Returns:
New ClusterSet with merged cluster.
- Return type:
- Raises:
ValueError – If either cluster ID is not found.
- split_cluster(cluster_id, track_ids_1, track_ids_2, new_id_1=None, new_id_2=None, tracks=None, state_indices=(0, 2))[source]
Split a cluster into two.
- Parameters:
cluster_id (int) – ID of cluster to split.
track_ids_1 (Iterable[int]) – Track IDs for first new cluster.
track_ids_2 (Iterable[int]) – Track IDs for second new cluster.
new_id_1 (int, optional) – ID for first new cluster. Defaults to cluster_id.
new_id_2 (int, optional) – ID for second new cluster. Defaults to max(cluster_ids) + 1.
tracks (TrackList, optional) – TrackList for computing centroids. If None, uses existing centroid.
state_indices (tuple of int, optional) – Indices of x and y in state vector (default: (0, 2)).
- Returns:
New ClusterSet with split clusters.
- Return type:
- Raises:
ValueError – If cluster ID is not found.
- class pytcl.containers.ClusterStats(n_tracks, mean_separation, max_separation, velocity_coherence)[source]
Bases:
NamedTupleStatistics for a cluster.
- velocity_coherence
Measure of how aligned velocities are (0-1). 1.0 means perfectly aligned, 0.0 means random directions.
- Type:
- pytcl.containers.cluster_tracks_dbscan(tracks, eps, min_samples=2, state_indices=(0, 2))[source]
Cluster tracks using DBSCAN algorithm.
- Parameters:
- Returns:
Set of track clusters.
- Return type:
- pytcl.containers.cluster_tracks_kmeans(tracks, n_clusters, state_indices=(0, 2), rng=None)[source]
Cluster tracks using K-means algorithm.
- Parameters:
tracks (TrackList) – Tracks to cluster.
n_clusters (int) – Number of clusters to form.
state_indices (tuple of int, optional) – Indices of x and y in state vector (default: (0, 2)).
rng (numpy.random.Generator, optional) – Random number generator for reproducibility.
- Returns:
Set of track clusters.
- Return type:
- pytcl.containers.compute_cluster_centroid(tracks, state_indices=(0, 2))[source]
Compute the centroid of a group of tracks.
- Parameters:
- Returns:
centroid – Centroid position [x, y].
- Return type:
ndarray
Examples
>>> from pytcl.trackers.multi_target import Track >>> import numpy as np >>> # Create sample tracks with [x, vx, y, vy] state vectors >>> track1 = Track(state=np.array([0.0, 1.0, 0.0, 1.0])) >>> track2 = Track(state=np.array([2.0, 1.0, 2.0, 1.0])) >>> track3 = Track(state=np.array([4.0, 1.0, 4.0, 1.0])) >>> tracks = [track1, track2, track3] >>> centroid = compute_cluster_centroid(tracks) >>> centroid array([2., 2.])
See also
compute_cluster_covarianceCompute covariance of track positions.
K-D Tree
K-dimensional tree for spatial queries.
K-D Tree implementation.
A k-dimensional tree (k-d tree) is a space-partitioning data structure for organizing points in k-dimensional space. Useful for efficient nearest neighbor searches in tracking applications.
References
- class pytcl.containers.kd_tree.KDNode(point, index, split_dim)[source]
Bases:
objectA node in the k-d tree.
- point
The point stored at this node.
- Type:
ndarray
- point
- index
- split_dim
- class pytcl.containers.kd_tree.NeighborResult(indices, distances)[source]
Bases:
NamedTupleUnified result type for spatial index queries.
All spatial index implementations (KDTree, BallTree, VPTree, CoverTree, RTree) return this type from their query methods, ensuring a consistent interface across the library.
- indices
Indices of the k nearest neighbors in the original data array. For k=1, may be 1D. For k>1, shape is (n_queries, k).
- Type:
ndarray of shape (n_queries, k) or (n_queries,)
- distances
Distances to the k nearest neighbors. Same shape as indices.
- Type:
ndarray of shape (n_queries, k) or (n_queries,)
Examples
>>> from pytcl.containers import KDTree >>> import numpy as np >>> points = np.array([[0, 0], [1, 0], [0, 1], [1, 1]]) >>> tree = KDTree(points) >>> result = tree.query([[0.1, 0.1]], k=2) >>> result.indices array([[0, 2]]) >>> result.distances array([[0.14142136, 0.9 ]])
See also
BaseSpatialIndexAbstract base class for spatial indices.
- pytcl.containers.kd_tree.NearestNeighborResult
alias of
NeighborResult
- class pytcl.containers.kd_tree.KDTree(data, leaf_size=10)[source]
Bases:
BaseSpatialIndexK-D Tree for efficient spatial queries.
A k-d tree recursively partitions space by splitting along different dimensions at each level. This enables O(log n) average-case nearest neighbor queries.
- Parameters:
data (array_like) – Data points of shape (n_samples, n_features).
leaf_size (int, optional) – Maximum number of points in a leaf node. Default 10.
Examples
>>> import numpy as np >>> points = np.array([[0, 0], [1, 0], [0, 1], [1, 1]]) >>> tree = KDTree(points) >>> result = tree.query(np.array([[0.1, 0.1]]), k=2) >>> result.indices array([[0, 1]])
Notes
The tree is balanced by choosing the median point along the split dimension at each level, giving O(n log n) construction time.
Query complexity is O(log n) on average for nearest neighbor search, though worst case is O(n) for highly unbalanced queries.
See also
BaseSpatialIndexAbstract base class defining the spatial index interface.
BallTreeAlternative spatial index using hyperspheres.
- query(X, k=1)[source]
Query the tree for k nearest neighbors.
- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
k (int, optional) – Number of nearest neighbors. Default 1.
- Returns:
result – Indices and distances of k nearest neighbors for each query.
- Return type:
Examples
>>> tree = KDTree(np.array([[0, 0], [1, 1], [2, 2]])) >>> result = tree.query([[0.5, 0.5]], k=2) >>> result.indices array([[0, 1]])
- query_radius(X, r)[source]
Query the tree for all points within radius r.
- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
r (float) – Query radius.
- Returns:
indices – For each query, a list of indices of points within radius r.
- Return type:
list of lists
Examples
>>> tree = KDTree(np.array([[0, 0], [1, 0], [0, 1], [5, 5]])) >>> tree.query_radius([[0, 0]], r=1.5) [[0, 1, 2]]
- class pytcl.containers.kd_tree.BallTree(data, leaf_size=10)[source]
Bases:
BaseSpatialIndexBall Tree for efficient spatial queries.
A ball tree partitions space using hyperspheres (balls), which can be more efficient than k-d trees for high-dimensional data or non-Euclidean metrics.
- Parameters:
data (array_like) – Data points of shape (n_samples, n_features).
leaf_size (int, optional) – Maximum number of points in a leaf node. Default 10.
Examples
>>> import numpy as np >>> points = np.array([[0, 0], [1, 0], [0, 1], [1, 1]]) >>> tree = BallTree(points) >>> result = tree.query(np.array([[0.1, 0.1]]), k=2)
Notes
Ball trees have O(n log n) construction and O(log n) average-case query time. They can outperform k-d trees in high dimensions.
See also
BaseSpatialIndexAbstract base class defining the spatial index interface.
KDTreeAlternative spatial index using axis-aligned splits.
- query(X, k=1)[source]
Query the tree for k nearest neighbors.
- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
k (int, optional) – Number of nearest neighbors. Default 1.
- Returns:
result – Indices and distances of k nearest neighbors.
- Return type:
Ball Tree
Ball tree for metric space queries.
R-Tree
R-tree for spatial indexing.
R-tree implementation for spatial indexing of bounding boxes.
R-trees are tree data structures used for spatial access methods, i.e., for indexing multi-dimensional information such as geographical coordinates, rectangles, or polygons.
References
A. Guttman, “R-trees: A Dynamic Index Structure for Spatial Searching,” ACM SIGMOD, 1984.
N. Beckmann et al., “The R*-tree: An Efficient and Robust Access Method for Points and Rectangles,” ACM SIGMOD, 1990.
- class pytcl.containers.rtree.NeighborResult(indices, distances)[source]
Bases:
NamedTupleUnified result type for spatial index queries.
All spatial index implementations (KDTree, BallTree, VPTree, CoverTree, RTree) return this type from their query methods, ensuring a consistent interface across the library.
- indices
Indices of the k nearest neighbors in the original data array. For k=1, may be 1D. For k>1, shape is (n_queries, k).
- Type:
ndarray of shape (n_queries, k) or (n_queries,)
- distances
Distances to the k nearest neighbors. Same shape as indices.
- Type:
ndarray of shape (n_queries, k) or (n_queries,)
Examples
>>> from pytcl.containers import KDTree >>> import numpy as np >>> points = np.array([[0, 0], [1, 0], [0, 1], [1, 1]]) >>> tree = KDTree(points) >>> result = tree.query([[0.1, 0.1]], k=2) >>> result.indices array([[0, 2]]) >>> result.distances array([[0.14142136, 0.9 ]])
See also
BaseSpatialIndexAbstract base class for spatial indices.
- pytcl.containers.rtree.SpatialQueryResult
alias of
NeighborResult
- class pytcl.containers.rtree.BoundingBox(min_coords, max_coords)[source]
Bases:
NamedTupleAxis-aligned bounding box.
- min_coords
Minimum coordinates in each dimension.
- Type:
ndarray
- max_coords
Maximum coordinates in each dimension.
- Type:
ndarray
- pytcl.containers.rtree.merge_boxes(boxes)[source]
Compute minimum bounding box containing all boxes.
- pytcl.containers.rtree.box_from_point(point)[source]
Create a zero-volume bounding box from a point.
- pytcl.containers.rtree.box_from_points(points)[source]
Create minimum bounding box containing all points.
- class pytcl.containers.rtree.RTreeNode(is_leaf=True)[source]
Bases:
objectNode in an R-tree.
- bbox
Bounding box of this node.
- Type:
- is_leaf
- entries: List[Tuple[BoundingBox, int]]
- bbox: BoundingBox | None
- class pytcl.containers.rtree.RTreeResult(indices, boxes)[source]
Bases:
NamedTupleResult of R-tree query.
- boxes: List[BoundingBox]
Alias for field number 1
- class pytcl.containers.rtree.RTree(max_entries=10, min_entries=None)[source]
Bases:
objectR-tree for spatial indexing of bounding boxes.
An R-tree groups nearby objects and represents them with their minimum bounding rectangle. This allows efficient spatial queries.
Unlike KDTree and BallTree which only index points, RTree can index bounding boxes of arbitrary size. It also supports dynamic insertion.
- Parameters:
Examples
>>> tree = RTree() >>> tree.insert(BoundingBox(np.array([0, 0]), np.array([1, 1])), 0) >>> tree.insert(BoundingBox(np.array([2, 2]), np.array([3, 3])), 1) >>> query_box = BoundingBox(np.array([0.5, 0.5]), np.array([2.5, 2.5])) >>> result = tree.query_intersect(query_box)
Notes
This implementation uses a simplified insertion algorithm. For production use, consider using R*-tree or packed R-tree variants.
See also
KDTreePoint-based spatial index using axis-aligned splits.
BallTreePoint-based spatial index using hyperspheres.
- classmethod from_points(data, max_entries=10, min_entries=None)[source]
Create an RTree from point data.
This factory method provides an interface similar to KDTree and BallTree, allowing RTree to be used interchangeably for point queries.
- Parameters:
- Returns:
tree – RTree with all points inserted.
- Return type:
Examples
>>> points = np.array([[0, 0], [1, 0], [0, 1], [1, 1]]) >>> tree = RTree.from_points(points) >>> result = tree.query([[0.1, 0.1]], k=2)
- insert(bbox, data_index=None)[source]
Insert a bounding box into the tree.
- Parameters:
bbox (BoundingBox) – Bounding box to insert.
data_index (int, optional) – Index to associate with this box. If None, uses next available.
- Returns:
index – Index of the inserted entry.
- Return type:
- query(X, k=1)[source]
Query the tree for k nearest neighbors.
This method provides API compatibility with KDTree and BallTree.
- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
k (int, optional) – Number of nearest neighbors. Default 1.
- Returns:
result – Indices and distances of k nearest neighbors for each query.
- Return type:
Examples
>>> tree = RTree.from_points(np.array([[0, 0], [1, 1], [2, 2]])) >>> result = tree.query([[0.5, 0.5]], k=2) >>> result.indices array([[0, 1]])
- query_radius(X, r)[source]
Query the tree for all points within radius r.
This method provides API compatibility with KDTree and BallTree.
- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
r (float) – Query radius.
- Returns:
indices – For each query, a list of indices of points within radius r.
- Return type:
list of lists
Examples
>>> tree = RTree.from_points(np.array([[0, 0], [1, 0], [0, 1], [5, 5]])) >>> tree.query_radius([[0, 0]], r=1.5) [[0, 1, 2]]
- query_ball_point(X, r)[source]
Query the tree for all points within radius r.
This is an alias for
query_radius()provided for compatibility with scipy.spatial.KDTree.- Parameters:
X (array_like) – Query points of shape (n_queries, n_features) or (n_features,).
r (float) – Search radius.
- Returns:
indices – For each query point, a list of indices of data points within distance r.
- Return type:
See also
query_radiusThe underlying implementation.
- query_intersect(query_bbox)[source]
Find all entries intersecting a query box.
- Parameters:
query_bbox (BoundingBox) – Query bounding box.
- Returns:
result – Indices and boxes of intersecting entries.
- Return type:
- query_contains(query_bbox)[source]
Find all entries contained within a query box.
- Parameters:
query_bbox (BoundingBox) – Query bounding box.
- Returns:
result – Indices and boxes of contained entries.
- Return type:
- query_point(point)[source]
Find all entries containing a point.
- Parameters:
point (array_like) – Query point.
- Returns:
result – Indices and boxes of entries containing the point.
- Return type:
VP-Tree
Vantage-point tree for metric spaces.
Vantage Point Tree (VP-tree) implementation.
VP-trees are metric trees that partition data based on distance to selected vantage points. They are effective for nearest neighbor search in metric spaces, particularly with high-dimensional data.
References
P. N. Yianilos, “Data structures and algorithms for nearest neighbor search in general metric spaces,” SODA 1993.
- class pytcl.containers.vptree.NeighborResult(indices, distances)[source]
Bases:
NamedTupleUnified result type for spatial index queries.
All spatial index implementations (KDTree, BallTree, VPTree, CoverTree, RTree) return this type from their query methods, ensuring a consistent interface across the library.
- indices
Indices of the k nearest neighbors in the original data array. For k=1, may be 1D. For k>1, shape is (n_queries, k).
- Type:
ndarray of shape (n_queries, k) or (n_queries,)
- distances
Distances to the k nearest neighbors. Same shape as indices.
- Type:
ndarray of shape (n_queries, k) or (n_queries,)
Examples
>>> from pytcl.containers import KDTree >>> import numpy as np >>> points = np.array([[0, 0], [1, 0], [0, 1], [1, 1]]) >>> tree = KDTree(points) >>> result = tree.query([[0.1, 0.1]], k=2) >>> result.indices array([[0, 2]]) >>> result.distances array([[0.14142136, 0.9 ]])
See also
BaseSpatialIndexAbstract base class for spatial indices.
- pytcl.containers.vptree.VPTreeResult
alias of
NeighborResult
- class pytcl.containers.vptree.VPNode(index, radius=0.0)[source]
Bases:
objectNode in a VP-tree.
- index
- radius
- class pytcl.containers.vptree.VPTree(data, metric=None)[source]
Bases:
MetricSpatialIndexVantage Point Tree for metric space nearest neighbor search.
A VP-tree recursively partitions space by selecting a vantage point and dividing remaining points into those closer than a threshold (median distance) and those farther.
- Parameters:
data (array_like) – Data points of shape (n_samples, n_features).
metric (callable, optional) – Distance function metric(x, y) -> float. Default is Euclidean distance.
Examples
>>> import numpy as np >>> points = np.random.rand(100, 3) >>> tree = VPTree(points) >>> result = tree.query(points[:5], k=3) >>> result.indices.shape (5, 3)
Notes
VP-trees can use any metric distance function, making them useful for non-Euclidean spaces (e.g., edit distance for strings, geodesic distance on manifolds).
Query complexity is O(log n) on average but can degrade to O(n) for pathological distance distributions.
See also
MetricSpatialIndexAbstract base class for metric-based spatial indices.
CoverTreeAlternative metric space index with theoretical guarantees.
Cover Tree
Cover tree for approximate nearest neighbors.
Cover Tree implementation for nearest neighbor search.
Cover trees are data structures for nearest neighbor search in metric spaces with a theoretical guarantee of O(c^12 log n) query time, where c is the expansion constant of the data.
References
A. Beygelzimer, S. Kakade, J. Langford, “Cover trees for nearest neighbor,” ICML 2006.
- class pytcl.containers.covertree.NeighborResult(indices, distances)[source]
Bases:
NamedTupleUnified result type for spatial index queries.
All spatial index implementations (KDTree, BallTree, VPTree, CoverTree, RTree) return this type from their query methods, ensuring a consistent interface across the library.
- indices
Indices of the k nearest neighbors in the original data array. For k=1, may be 1D. For k>1, shape is (n_queries, k).
- Type:
ndarray of shape (n_queries, k) or (n_queries,)
- distances
Distances to the k nearest neighbors. Same shape as indices.
- Type:
ndarray of shape (n_queries, k) or (n_queries,)
Examples
>>> from pytcl.containers import KDTree >>> import numpy as np >>> points = np.array([[0, 0], [1, 0], [0, 1], [1, 1]]) >>> tree = KDTree(points) >>> result = tree.query([[0.1, 0.1]], k=2) >>> result.indices array([[0, 2]]) >>> result.distances array([[0.14142136, 0.9 ]])
See also
BaseSpatialIndexAbstract base class for spatial indices.
- pytcl.containers.covertree.CoverTreeResult
alias of
NeighborResult
- class pytcl.containers.covertree.CoverTreeNode(index, level)[source]
Bases:
objectNode in a Cover tree.
- index
- level
- children: dict[int, List[CoverTreeNode]]
- class pytcl.containers.covertree.CoverTree(data, metric=None, base=2.0)[source]
Bases:
MetricSpatialIndexCover Tree for metric space nearest neighbor search.
A cover tree maintains a hierarchy of nested coverings of the data, where points at level i are a subset of points at level i-1 and cover all points within distance 2^i.
- Parameters:
data (array_like) – Data points of shape (n_samples, n_features).
metric (callable, optional) – Distance function metric(x, y) -> float. Default is Euclidean distance.
base (float, optional) – Base for the exponential scale. Default 2.0.
Examples
>>> import numpy as np >>> points = np.random.rand(100, 3) >>> tree = CoverTree(points) >>> result = tree.query(points[:5], k=3)
Notes
Cover trees provide theoretical guarantees based on the expansion constant of the data. For well-distributed data, queries are efficient even in high dimensions.
The implementation uses a simplified version of the original algorithm for clarity.
See also
MetricSpatialIndexAbstract base class for metric-based spatial indices.
VPTreeAlternative metric space index using vantage points.
- root: CoverTreeNode | None