Skip to main content

High-performance trajectory distance calculations in Rust with Python bindings

Project description

traj-dist-rs

A high-performance Rust implementation of trajectory distance algorithms with Python bindings, offering significant speed improvements over the original traj-dist library.

License: MIT Python Version Rust Version

📖 About

traj-dist-rs is a high-performance trajectory distance calculation library written in Rust, providing both native Rust APIs and Python bindings via PyO3. It is a complete rewrite of the original traj-dist library, focusing on performance optimization and modern language features.

Why traj-dist-rs?

  • 🚀 Performance: ~73x faster than Python implementation and ~2.7x faster than Cython implementation on average
  • 🔒 Safety: Rust's memory safety guarantees eliminate common runtime errors
  • 📦 Cross-platform: Supports Linux, macOS, and Windows with native binaries
  • 🔗 Dual API: Use it from Python or Rust with minimal overhead
  • 🎯 Accuracy: All algorithms verified against original implementation with < 1e-8 error margin

✨ Features

Supported Distance Algorithms

  • SSPD - Symmetric Segment-Path Distance
  • DTW - Dynamic Time Warping (with optional matrix return)
  • Discret Frechet - Discrete Fréchet Distance
  • Hausdorff - Hausdorff Distance
  • LCSS - Longest Common Subsequence
  • EDR - Edit Distance on Real sequence
  • ERP - Edit distance with Real Penalty (standard & traj-dist compatible)

Distance Types

  • Euclidean - 2D Euclidean distance
  • Spherical - Haversine distance for geographic coordinates

Additional Features

  • Matrix return for DP-based algorithms (DTW, LCSS, EDR, ERP, Discret Frechet)
  • Precomputed distance matrix support for efficient batch computations
  • Comprehensive error handling for invalid inputs
  • Full Python type hints for better IDE support

🚀 Quick Start

Python

import traj_dist_rs
import numpy as np

# Define trajectories as list of [x, y] coordinates or numpy arrays
traj1 = [[0.0, 0.0], [1.0, 1.0], [2.0, 2.0]]
traj2 = [[0.1, 0.1], [1.1, 1.1], [2.1, 2.1]]

# Calculate SSPD distance
distance = traj_dist_rs.sspd(traj1, traj2, dist_type="euclidean")
print(f"SSPD distance: {distance}")

# Calculate DTW distance (returns DpResult with distance and optional matrix)
result = traj_dist_rs.dtw(traj1, traj2, dist_type="euclidean", use_full_matrix=False)
print(f"DTW distance: {result.distance}")

# Calculate Hausdorff distance
distance = traj_dist_rs.hausdorff(traj1, traj2, dist_type="spherical")
print(f"Hausdorff distance: {distance}")

Rust

use traj_dist_rs::distance::sspd::sspd;
use traj_dist_rs::distance::dtw::dtw;
use traj_dist_rs::distance::base::TrajectoryCalculator;
use traj_dist_rs::distance::distance_type::DistanceType;

fn main() {
    let traj1 = vec![[0.0, 0.0], [1.0, 1.0], [2.0, 2.0]];
    let traj2 = vec![[0.1, 0.1], [1.1, 1.1], [2.1, 2.1]];

    // Calculate SSPD distance
    let dist = sspd(&traj1, &traj2, DistanceType::Euclidean);
    println!("SSPD distance: {}", dist);

    // Calculate DTW distance
    let calculator = TrajectoryCalculator::new(&traj1, &traj2, DistanceType::Euclidean);
    let result = dtw(&calculator, false);
    println!("DTW distance: {}", result.distance);
}

📦 Installation

From PyPI (Python)

pip install traj-dist-rs

From Source

Prerequisites:

  • Rust 1.70 or later
  • Python 3.10, 3.11, 3.12, or 3.13
  • maturin

Build and install:

# Clone the repository
git clone <repository-url>
cd traj-dist-rs

# Install development dependencies
pip install maturin

# Build and install in development mode
maturin develop

# Or build a release wheel
maturin build --release
pip install target/wheels/*.whl

Rust-only build:

cargo build --release

📊 Performance

Compared to the original traj-dist implementation (based on median values from K=1000 trajectory pairs):

Overall Performance

Implementation Average Speedup
Rust vs Python ~73x faster
Rust vs Cython ~2.7x faster

By Distance Type

Euclidean Distance:

  • Rust vs Python: ~389x faster (range: 187x - 595x)
  • Rust vs Cython: ~10x faster (range: 6x - 16x)

Spherical Distance:

  • Rust vs Python: ~76x faster (range: 41x - 167x)
  • Rust vs Cython: ~2.7x faster (range: 1.6x - 5.2x)

Best Performing Algorithms

Rust vs Cython (Euclidean):

  • SSPD: 16.13x faster
  • Hausdorff: 14.07x faster
  • ERP: 12.03x faster

Rust vs Python (Euclidean):

  • DTW: 595x faster
  • Discret Frechet: 554x faster
  • LCSS: 381x faster

For detailed performance analysis with statistics, see docs/performance.md.

📚 Documentation

🧪 Testing

Python Tests

cd traj-dist-rs
uv sync --dev
pytest py_tests/

Rust Tests

cd traj-dist-rs
cargo test

Integration Tests

Run comprehensive integration tests:

bash scripts/pre_build.sh

🤝 Contributing

We welcome contributions! Please see our contributing guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests and ensure they pass
  5. Format your code (cargo fmt for Rust, black for Python)
  6. Commit your changes (git commit -m 'Add amazing feature')
  7. Push to the branch (git push origin feature/amazing-feature)
  8. Open a Pull Request

Development Workflow

For daily development, use the pre-build script:

bash scripts/pre_build.sh

This script will:

  • Format Rust and Python code
  • Run linting (clippy, ruff)
  • Run all tests (Rust + Python)
  • Generate Python stub files
  • Build Python bindings

🔧 Project Structure

traj-dist-rs/
├── src/
│   ├── distance/       # Distance algorithm implementations
│   ├── binding/        # Python bindings (PyO3)
│   └── lib.rs          # Library entry point
├── tests/              # Rust integration tests
├── py_tests/           # Python integration tests
├── python/             # Python package source
├── docs/               # Documentation
└── scripts/            # Build and utility scripts

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Original traj-dist library for algorithm reference
  • PyO3 for Python bindings
  • The Rust community for excellent tooling and libraries

📮 Support

  • Issues: Report bugs and request features via GitHub Issues
  • Discussions: Join discussions about usage and development
  • Documentation: Check the docs directory for detailed guides

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

traj_dist_rs-1.0.0a1.tar.gz (2.8 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

traj_dist_rs-1.0.0a1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (501.8 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

traj_dist_rs-1.0.0a1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (502.3 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

traj_dist_rs-1.0.0a1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (506.9 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

traj_dist_rs-1.0.0a1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (506.6 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

File details

Details for the file traj_dist_rs-1.0.0a1.tar.gz.

File metadata

  • Download URL: traj_dist_rs-1.0.0a1.tar.gz
  • Upload date:
  • Size: 2.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for traj_dist_rs-1.0.0a1.tar.gz
Algorithm Hash digest
SHA256 5ae686f432e7c69285bc394207b2052fcbf1610ee31a022b5807902d0d7051c4
MD5 258c84404bd89c8217481c0651876e22
BLAKE2b-256 573a1539af6bc8774e8efa223d42dbf53e8ff421d086ed0be2ce9369309cf501

See more details on using hashes here.

File details

Details for the file traj_dist_rs-1.0.0a1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for traj_dist_rs-1.0.0a1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b1230dd1a961b89b65cf6992defa9f84213dc1f34cad7651f900c9e4628f9234
MD5 4e20e58dfb77d37e7414b242dee69df9
BLAKE2b-256 5b0d26ff850dc8846ad6d716b205e526ab8ebc214e092a8f8662c4a334477c5e

See more details on using hashes here.

File details

Details for the file traj_dist_rs-1.0.0a1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for traj_dist_rs-1.0.0a1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ea49def671207742c0d1f550f1b60137387909ae1043bcee5bc8827195e0fd81
MD5 595bf68286b65b1bfdb1687a02492127
BLAKE2b-256 09932d68efb99a7a9511cbf7809099f5ee7c8b973c52e7c0e32dc33cc54b77b8

See more details on using hashes here.

File details

Details for the file traj_dist_rs-1.0.0a1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for traj_dist_rs-1.0.0a1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1485f136aa8f5201fe4941f72a5f901853de34934d814d1ff10e84beb289c9a4
MD5 31229187c7583295fff70b0a40da7cbb
BLAKE2b-256 2dcf9b8c7ea114e24d33b3d73dc86234f3d42f8fea34f5a379cea79b2cd4a377

See more details on using hashes here.

File details

Details for the file traj_dist_rs-1.0.0a1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for traj_dist_rs-1.0.0a1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 51b72c003ac4a215ee4859f6688e0e6b2eb13146cd7c8ac1ff14fad9a4955f3f
MD5 790b73ce9db613733f2123dae85a52be
BLAKE2b-256 90a4c841e15fb3a528bcdfdb13b97ebf87d03eaaf165aa736bb48ec045f63250

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page