API Reference
traj_dist_rs
traj-dist-rs: High-performance trajectory distance & similarity measures in Rust with Python bindings.
This package provides efficient implementations of various trajectory distance and similarity algorithms including SSPD, DTW, Hausdorff, LCSS, EDR, ERP, and Discret Frechet.
Trajectory similarity is often measured via trajectory distances such as DTW, LCSS, EDR, ERP, Hausdorff, and Fréchet. These algorithms are widely used for trajectory similarity search, clustering, and pattern mining.
All algorithms support both Euclidean (Cartesian) and Spherical (Haversine) distance calculations. The underlying algorithms are implemented in Rust for optimal performance, with Python bindings generated using PyO3.
Use Cases: - Trajectory similarity search and retrieval - Nearest neighbor queries on trajectory databases - Trajectory clustering and classification - Mobility data analysis and GPS trace processing - Route pattern mining - Anomaly detection in movement data
Examples:
>>> import traj_dist_rs
>>>
>>> # Define two trajectories as lists of [longitude, latitude] pairs
>>> t1 = [[0.0, 0.0], [1.0, 1.0]]
>>> t2 = [[0.0, 1.0], [1.0, 0.0]]
>>>
>>> # Calculate SSPD distance using Euclidean distance
>>> distance = traj_dist_rs.sspd(t1, t2, "euclidean")
>>> print(f"SSPD distance: {distance}")
>>>
>>> # Convert to similarity score
>>> similarity = 1.0 / (1.0 + distance)
>>> print(f"SSPD similarity: {similarity}")
>>>
>>> # Calculate DTW distance using Spherical distance (for geographic coordinates)
>>> distance = traj_dist_rs.dtw(t1, t2, "spherical")
>>> print(f"DTW distance: {distance}")
DpResult
Python wrapper for the Rust DpResult struct
This class wraps the Rust DpResult and provides Python-friendly access to the distance and optional matrix.
distance
property
Get the distance value
matrix
property
Get the matrix (or None if not computed)
Returns a numpy array if use_full_matrix was True, otherwise None
Metric
A metric configuration object for distance calculations.
This class encapsulates the distance algorithm, its parameters, and the underlying point-to-point distance type (e.g., Euclidean or Spherical).
Do not instantiate this class directly. Use the provided static factory
methods instead (e.g., Metric.sspd(), Metric.lcss(...)).
discret_frechet(type_d='euclidean')
staticmethod
Discrete Frechet Distance.
dtw(type_d='euclidean')
staticmethod
Dynamic Time Warping.
edr(eps, type_d='euclidean')
staticmethod
Edit Distance on Real sequence.
erp(g, type_d='euclidean')
staticmethod
Edit distance with Real Penalty.
hausdorff(type_d='euclidean')
staticmethod
Hausdorff Distance.
lcss(eps, type_d='euclidean')
staticmethod
Longest Common Subsequence.
sspd(type_d='euclidean')
staticmethod
Symmetric Segment-Path Distance.
cdist(trajectories_a, trajectories_b, metric, parallel=True)
builtin
Compute distances between two trajectory collections
This function computes the distances between all pairs of trajectories from two collections. The result is a full distance matrix (2D array) with shape (n_a, n_b).
When to Use cdist vs pdist
- Use
cdistwhen: - Computing distances between two different trajectory collections
- Your distance metric is asymmetric (distance(A, B) != distance(B, A))
-
You need the full distance matrix for both directions
-
Use
pdistwhen: - Computing distances within a single trajectory collection
- Your distance metric is symmetric (distance(A, B) == distance(B, A))
- You want to save memory by using the compressed distance matrix format
Arguments
trajectories_a- First collection of trajectories, where each trajectory is a 2D numpy array or list of [x, y] pairstrajectories_b- Second collection of trajectoriesmetric- Metric configuration object (e.g.,Metric.sspd(),Metric.lcss(eps=5.0))parallel- Whether to use parallel processing (default: True)
Returns
distances- 2D numpy array with shape (len(trajectories_a), len(trajectories_b))
Output Format
For n_a trajectories in the first collection and n_b trajectories in the second,
the result is a 2D array with shape (n_a, n_b). The distance at index [i, j]
represents the distance from trajectories_a[i] to trajectories_b[j].
Examples
import traj_dist_rs
import numpy as np
# Create metric configuration
metric = traj_dist_rs.Metric.sspd(type_d="euclidean")
# Using numpy arrays (zero-copy)
trajectories_a = [
np.array([[0.0, 0.0], [1.0, 1.0]]),
np.array([[0.0, 1.0], [1.0, 0.0]])
]
trajectories_b = [
np.array([[0.5, 0.5], [1.5, 1.5]]),
np.array([[0.5, 1.5], [1.5, 0.5]])
]
distances = traj_dist_rs.cdist(trajectories_a, trajectories_b, metric=metric)
print(distances.shape) # (2, 2)
# Using lists (will be copied)
trajectories_a = [
[[0.0, 0.0], [1.0, 1.0]],
[[0.0, 1.0], [1.0, 0.0]]
]
trajectories_b = [
[[0.5, 0.5], [1.5, 1.5]],
[[0.5, 1.5], [1.5, 0.5]]
]
distances = traj_dist_rs.cdist(trajectories_a, trajectories_b, metric=metric)
# Using ERP with gap point parameter
metric_erp = traj_dist_rs.Metric.erp(g=[0.0, 1.0], type_d="euclidean")
distances = traj_dist_rs.cdist(trajectories_a, trajectories_b, metric=metric_erp)
discret_frechet(t1, t2, dist_type, use_full_matrix=False)
builtin
Compute the Discret Frechet distance between two trajectories
The discret Frechet distance is a measure of similarity between two curves that takes into account the location and ordering of the points along the curves.
Arguments
t1- First trajectory (list of [longitude, latitude] pairs)t2- Second trajectory (list of [longitude, latitude] pairs)dist_type- Distance type: "euclidean" (only Euclidean is supported for Discret Frechet)use_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: Discret Frechet distance as f64matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
t1 = [[0.0, 0.0], [1.0, 1.0]]
t2 = [[0.0, 1.0], [1.0, 0.0]]
result = traj_dist_rs.discret_frechet(t1, t2, "euclidean")
print(result.distance) # Distance value
print(result.matrix) # None
result = traj_dist_rs.discret_frechet(t1, t2, "euclidean", True)
print(result.matrix) # numpy array
discret_frechet_with_matrix(distance_matrix, use_full_matrix=False)
builtin
Compute the Discret Frechet distance using a precomputed distance matrix
This function allows you to use a precomputed distance matrix instead of computing distances between trajectory points on the fly.
Arguments
distance_matrix- A 2D numpy array wherematrix[i][j]is the distance between point i of trajectory 1 and point j of trajectory 2use_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: Discret Frechet distance as f64matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
import numpy as np
dist_matrix = np.array([
[1.0, 1.0],
[1.0, 1.0],
])
# Without matrix
result = traj_dist_rs.discret_frechet_with_matrix(dist_matrix)
print(result.distance) # Distance value
print(result.matrix) # None
# With matrix
result = traj_dist_rs.discret_frechet_with_matrix(dist_matrix, use_full_matrix=True)
print(result.matrix) # numpy array
dtw(t1, t2, dist_type, use_full_matrix=False)
builtin
Compute the DTW (Dynamic Time Warping) distance between two trajectories
Arguments
t1- First trajectory (list of [longitude, latitude] pairs)t2- Second trajectory (list of [longitude, latitude] pairs)dist_type- Distance type: "euclidean" or "spherical"use_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: DTW distance as f64matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
t1 = [[0.0, 0.0], [1.0, 1.0]]
t2 = [[0.0, 1.0], [1.0, 0.0]]
# Without matrix
result = traj_dist_rs.dtw(t1, t2, "euclidean")
print(result.distance) # Distance value
print(result.matrix) # None
# With matrix
result = traj_dist_rs.dtw(t1, t2, "euclidean", True)
print(result.distance) # Distance value
print(result.matrix) # numpy array
dtw_with_matrix(distance_matrix, use_full_matrix=False)
builtin
Compute the DTW (Dynamic Time Warping) distance using a precomputed distance matrix
This function allows you to use a precomputed distance matrix instead of computing distances between trajectory points on the fly. This can be useful when: - You need to compute multiple distance measures on the same trajectory pair - You want to reuse the same distance matrix across different computations - You have custom distance calculations that don't fit the standard distance types
Arguments
distance_matrix- A 2D numpy array wherematrix[i][j]is the distance between point i of trajectory 1 and point j of trajectory 2use_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: DTW distance as f64matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
import numpy as np
t1 = [[0.0, 0.0], [1.0, 1.0]]
t2 = [[0.0, 1.0], [1.0, 0.0]]
# Precompute distance matrix
dist_matrix = np.array([
[1.0, 1.0], # distance from t1[0] to t2[0], t2[1]
[1.0, 1.0], # distance from t1[1] to t2[0], t2[1]
])
# Without matrix
result = traj_dist_rs.dtw_with_matrix(dist_matrix)
print(result.distance) # Distance value
print(result.matrix) # None
# With matrix
result = traj_dist_rs.dtw_with_matrix(dist_matrix, True)
print(result.distance) # Distance value
print(result.matrix) # numpy array
edr(t1, t2, dist_type, eps, use_full_matrix=False)
builtin
Compute the EDR (Edit Distance on Real sequence) distance between two trajectories
EDR is a distance measure for trajectories that allows for gaps in the matching.
It uses a threshold eps to determine if two points match.
The distance is normalized by the maximum length of the two trajectories.
Arguments
t1- First trajectory (list of [longitude, latitude] pairs)t2- Second trajectory (list of [longitude, latitude] pairs)dist_type- Distance type: "euclidean" or "spherical"eps- Epsilon threshold for matching pointsuse_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: EDR distance as f64 (normalized to [0, 1])matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
t1 = [[0.0, 0.0], [1.0, 1.0]]
t2 = [[0.0, 1.0], [1.0, 0.0]]
result = traj_dist_rs.edr(t1, t2, "euclidean", eps=0.5)
print(result.distance) # Distance value
print(result.matrix) # None
result = traj_dist_rs.edr(t1, t2, "euclidean", eps=0.5, use_full_matrix=True)
print(result.matrix) # numpy array
edr_with_matrix(distance_matrix, eps, use_full_matrix=False)
builtin
Compute the EDR (Edit Distance on Real sequence) distance using a precomputed distance matrix
This function allows you to use a precomputed distance matrix instead of computing distances between trajectory points on the fly.
Arguments
distance_matrix- A 2D numpy array wherematrix[i][j]is the distance between point i of trajectory 1 and point j of trajectory 2eps- Epsilon threshold for matching pointsuse_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: EDR distance as f64 (normalized to [0, 1])matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
import numpy as np
dist_matrix = np.array([
[1.0, 1.0],
[1.0, 1.0],
])
# Without matrix
result = traj_dist_rs.edr_with_matrix(dist_matrix, eps=0.5)
print(result.distance) # Distance value
print(result.matrix) # None
# With matrix
result = traj_dist_rs.edr_with_matrix(dist_matrix, eps=0.5, use_full_matrix=True)
print(result.matrix) # numpy array
erp_compat_traj_dist(t1, t2, dist_type, g, use_full_matrix=False)
builtin
Compute the ERP (Edit distance with Real Penalty) distance between two trajectories
This is the traj-dist compatible implementation that matches the (buggy) implementation in traj-dist. This version should be used when compatibility with traj-dist is required.
ERP is a distance measure for trajectories that uses a gap point g as a penalty
for insertions and deletions. The distance is computed using dynamic programming.
Note: This implementation has a bug in the DP matrix initialization where it uses the total sum of distances to g instead of cumulative sums. This matches the bug in traj-dist's Python implementation.
Arguments
t1- First trajectory (list of [longitude, latitude] pairs)t2- Second trajectory (list of [longitude, latitude] pairs)dist_type- Distance type: "euclidean" or "spherical"g- Gap point for penalty (list of [longitude, latitude] or None for centroid)use_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: ERP distance as f64matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
t1 = [[0.0, 0.0], [1.0, 1.0]]
t2 = [[0.0, 1.0], [1.0, 0.0]]
result = traj_dist_rs.erp_compat_traj_dist(t1, t2, "euclidean", g=[0.0, 0.0])
print(result.distance) # Distance value
print(result.matrix) # None
result = traj_dist_rs.erp_compat_traj_dist(t1, t2, "euclidean", g=[0.0, 0.0], use_full_matrix=True)
print(result.matrix) # numpy array
erp_compat_traj_dist_with_matrix(distance_matrix, seq0_gap_dists, seq1_gap_dists, use_full_matrix=False)
builtin
Compute the ERP (Edit distance with Real Penalty) distance using a precomputed distance matrix
This is the traj-dist compatible implementation that matches the (buggy) implementation in traj-dist. This version should be used when compatibility with traj-dist is required.
This function allows you to use a precomputed distance matrix and extra distance arrays instead of computing distances on the fly.
Arguments
distance_matrix- A 2D numpy array wherematrix[i][j]is the distance between point i of trajectory 1 and point j of trajectory 2seq0_gap_dists- A 1D numpy array whereseq0_gap_dists[i]is the distance between point i of trajectory 1 and the gap point gseq1_gap_dists- A 1D numpy array whereseq1_gap_dists[j]is the distance between point j of trajectory 2 and the gap point guse_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: ERP distance as f64matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
import numpy as np
dist_matrix = np.array([
[1.0, 1.0],
[1.0, 1.0],
])
seq0_gap_dists = np.array([1.0, 1.0])
seq1_gap_dists = np.array([1.0, 1.0])
# Without matrix
result = traj_dist_rs.erp_compat_traj_dist_with_matrix(dist_matrix, seq0_gap_dists, seq1_gap_dists)
print(result.distance) # Distance value
print(result.matrix) # None
# With matrix
result = traj_dist_rs.erp_compat_traj_dist_with_matrix(dist_matrix, seq0_gap_dists, seq1_gap_dists, use_full_matrix=True)
print(result.matrix) # numpy array
erp_standard(t1, t2, dist_type, g, use_full_matrix=False)
builtin
Compute the ERP (Edit distance with Real Penalty) distance between two trajectories
This is the standard ERP implementation with correct cumulative initialization. This version should be used for new applications where correctness is more important than compatibility with traj-dist.
ERP is a distance measure for trajectories that uses a gap point g as a penalty
for insertions and deletions. The distance is computed using dynamic programming.
Note: This implementation correctly accumulates distances by index in the DP matrix initialization, unlike the buggy implementation in traj-dist.
Arguments
t1- First trajectory (list of [longitude, latitude] pairs)t2- Second trajectory (list of [longitude, latitude] pairs)dist_type- Distance type: "euclidean" or "spherical"g- Gap point for penalty (list of [longitude, latitude] or None for centroid)use_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: ERP distance as f64matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
t1 = [[0.0, 0.0], [1.0, 1.0]]
t2 = [[0.0, 1.0], [1.0, 0.0]]
result = traj_dist_rs.erp_standard(t1, t2, "euclidean", g=[0.0, 0.0])
print(result.distance) # Distance value
print(result.matrix) # None
result = traj_dist_rs.erp_standard(t1, t2, "euclidean", g=[0.0, 0.0], use_full_matrix=True)
print(result.matrix) # numpy array
erp_standard_with_matrix(distance_matrix, seq0_gap_dists, seq1_gap_dists, use_full_matrix=False)
builtin
Compute the ERP (Edit distance with Real Penalty) distance using a precomputed distance matrix
This is the standard ERP implementation with correct cumulative initialization. This version should be used for new applications where correctness is more important than compatibility with traj-dist.
This function allows you to use a precomputed distance matrix and extra distance arrays instead of computing distances on the fly.
Arguments
distance_matrix- A 2D numpy array wherematrix[i][j]is the distance between point i of trajectory 1 and point j of trajectory 2seq0_gap_dists- A 1D numpy array whereseq0_gap_dists[i]is the distance between point i of trajectory 1 and the gap point gseq1_gap_dists- A 1D numpy array whereseq1_gap_dists[j]is the distance between point j of trajectory 2 and the gap point guse_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: ERP distance as f64matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
import numpy as np
dist_matrix = np.array([
[1.0, 1.0],
[1.0, 1.0],
])
seq0_gap_dists = np.array([1.0, 1.0])
seq1_gap_dists = np.array([1.0, 1.0])
# Without matrix
result = traj_dist_rs.erp_standard_with_matrix(dist_matrix, seq0_gap_dists, seq1_gap_dists)
print(result.distance) # Distance value
print(result.matrix) # None
# With matrix
result = traj_dist_rs.erp_standard_with_matrix(dist_matrix, seq0_gap_dists, seq1_gap_dists, use_full_matrix=True)
print(result.matrix) # numpy array
hausdorff(t1, t2, dist_type)
builtin
Compute the Hausdorff distance between two trajectories
Arguments
t1- First trajectory (list of [longitude, latitude] pairs)t2- Second trajectory (list of [longitude, latitude] pairs)dist_type- Distance type: "euclidean" or "spherical"
Returns
- Hausdorff distance as f64
Examples
lcss(t1, t2, dist_type, eps, use_full_matrix=False)
builtin
Compute the LCSS (Longest Common Subsequence) distance between two trajectories
The LCSS distance is calculated as 1 - (length of longest common subsequence) / min(len(t0), len(t1)) where two points are considered matching if their distance is less than eps.
Arguments
t1- First trajectory (list of [longitude, latitude] pairs)t2- Second trajectory (list of [longitude, latitude] pairs)dist_type- Distance type: "euclidean" or "spherical"eps- Epsilon threshold for matching pointsuse_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: LCSS distance as f64matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
t1 = [[0.0, 0.0], [1.0, 1.0]]
t2 = [[0.0, 1.0], [1.0, 0.0]]
result = traj_dist_rs.lcss(t1, t2, "euclidean", eps=0.5)
print(result.distance) # Distance value
print(result.matrix) # None
result = traj_dist_rs.lcss(t1, t2, "euclidean", eps=0.5, use_full_matrix=True)
print(result.matrix) # numpy array
lcss_with_matrix(distance_matrix, eps, use_full_matrix=False)
builtin
Compute the LCSS (Longest Common Subsequence) distance using a precomputed distance matrix
This function allows you to use a precomputed distance matrix instead of computing distances between trajectory points on the fly.
Arguments
distance_matrix- A 2D numpy array wherematrix[i][j]is the distance between point i of trajectory 1 and point j of trajectory 2eps- Epsilon threshold for matching pointsuse_full_matrix- If true, compute and return the full DP matrix; if false (default), return None for the matrix to save space
Returns
- A
DpResultobject with two properties: distance: LCSS distance as f64matrix: numpy array of shape (n0+1, n1+1) if use_full_matrix=True, else None
Examples
import traj_dist_rs
import numpy as np
dist_matrix = np.array([
[1.0, 1.0],
[1.0, 1.0],
])
# Without matrix
result = traj_dist_rs.lcss_with_matrix(dist_matrix, eps=0.5)
print(result.distance) # Distance value
print(result.matrix) # None
# With matrix
result = traj_dist_rs.lcss_with_matrix(dist_matrix, eps=0.5, use_full_matrix=True)
print(result.matrix) # numpy array
pdist(trajectories, metric, parallel=True)
builtin
Compute pairwise distances between trajectories
This function computes the distances between all unique pairs of trajectories in the input list. The result is a compressed distance matrix (1D array) containing distances for all pairs (i, j) where i < j.
Symmetry Assumption
This function assumes that the distance metric is symmetric, i.e.,
distance(A, B) == distance(B, A). All standard distance algorithms
in traj-dist-rs (SSPD, DTW, Hausdorff, LCSS, EDR, ERP, Discret Frechet)
satisfy this property.
Important: If your distance metric is asymmetric, use cdist instead
to compute the full distance matrix. Using pdist with asymmetric distances
will only compute half of the distances and may produce incorrect results.
Arguments
trajectories- List of trajectories, where each trajectory is a 2D numpy array or list of [x, y] pairsmetric- Metric configuration object (e.g.,Metric.sspd(),Metric.lcss(eps=5.0))parallel- Whether to use parallel processing (default: True)
Returns
distances- 1D numpy array containing distances for all unique pairs
Output Format
For n trajectories, the result is a 1D array of length n * (n - 1) / 2.
The distances are ordered as d(0,1), d(0,2), ..., d(0,n-1), d(1,2), d(1,3), ..., d(n-2,n-1).
Examples
import traj_dist_rs
import numpy as np
# Create metric configuration
metric = traj_dist_rs.Metric.sspd(type_d="euclidean")
# Using numpy arrays (zero-copy)
trajectories = [
np.array([[0.0, 0.0], [1.0, 1.0]]),
np.array([[0.0, 1.0], [1.0, 0.0]]),
np.array([[0.5, 0.5], [1.5, 1.5]])
]
distances = traj_dist_rs.pdist(trajectories, metric=metric)
# Using lists (will be copied)
trajectories = [
[[0.0, 0.0], [1.0, 1.0]],
[[0.0, 1.0], [1.0, 0.0]],
[[0.5, 0.5], [1.5, 1.5]]
]
distances = traj_dist_rs.pdist(trajectories, metric=metric)
# Using LCSS with epsilon parameter
metric_lcss = traj_dist_rs.Metric.lcss(eps=5.0, type_d="euclidean")
distances = traj_dist_rs.pdist(trajectories, metric=metric_lcss)
sspd(t1, t2, dist_type)
builtin
Compute the SSPD distance between two trajectories
Arguments
t1- First trajectory (list of [longitude, latitude] pairs)t2- Second trajectory (list of [longitude, latitude] pairs)dist_type- Distance type: "euclidean" or "spherical"
Returns
- SSPD distance as f64