{
"cells": [
{
"cell_type": "markdown",
"id": "title",
"metadata": {},
"source": [
"# Python User Guide\n",
"\n",
"This guide provides comprehensive usage examples for the traj-dist-rs library, a high-performance trajectory distance library implemented in Rust.\n",
"\n",
"## Table of Contents\n",
"\n",
"1. [Installation](#installation)\n",
"2. [Basic Concepts](#basic-concepts)\n",
"3. [Basic Usage](#basic-usage)\n",
"4. [Using Spherical Distance](#using-spherical-distance)\n",
"5. [Algorithms with Parameters](#algorithms-with-parameters)\n",
"6. [Comparing All Algorithms](#comparing-all-algorithms)\n",
"7. [Using DpResult](#using-dpresult)\n",
"8. [Visualizing Trajectories](#visualizing-trajectories)\n",
"9. [Batch Computation](#batch-computation)\n",
"10. [Parallel Processing](#parallel-processing)\n",
" - [pdist parallel](#parallel-processing-with-pdist)\n",
" - [cdist parallel](#parallel-processing-with-cdist)\n",
"11. [Performance Comparison](#performance-comparison)\n",
"12. [Real-World Data Usage](#real-world-data-usage)\n",
"13. [Error Handling](#error-handling)"
]
},
{
"cell_type": "markdown",
"id": "installation",
"metadata": {},
"source": [
"## Installation\n",
"\n",
"Install the package using pip:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "install",
"metadata": {},
"outputs": [],
"source": [
"# Uncomment to install\n",
"# !pip install traj-dist-rs"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "import",
"metadata": {},
"outputs": [],
"source": [
"import traj_dist_rs\n",
"import numpy as np\n",
"\n",
"print(f\"traj_dist_rs version: {traj_dist_rs.__version__}\")"
]
},
{
"cell_type": "markdown",
"id": "concepts",
"metadata": {},
"source": [
"## Basic Concepts\n",
"\n",
"The library provides implementations of several trajectory distance algorithms:\n",
"\n",
"- **SSPD**: Symmetric Segment-Path Distance\n",
"- **DTW**: Dynamic Time Warping\n",
"- **Hausdorff**: Hausdorff Distance\n",
"- **LCSS**: Longest Common Subsequence\n",
"- **EDR**: Edit Distance on Real sequence\n",
"- **ERP**: Edit distance with Real Penalty\n",
"- **Discret Frechet**: Discrete Fréchet Distance\n",
"\n",
"Each algorithm supports both Euclidean (Cartesian) and Spherical (Haversine) distance calculations."
]
},
{
"cell_type": "markdown",
"id": "basic-usage-title",
"metadata": {},
"source": [
"## Basic Usage\n",
"\n",
"Let's start with basic usage of the traj-dist-rs package:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "basic-import",
"metadata": {},
"outputs": [],
"source": [
"import traj_dist_rs\n",
"import numpy as np\n",
"\n",
"# Define two trajectories as lists of [x, y] coordinates\n",
"traj1 = np.array([[0.0, 0.0], [1.0, 1.0], [2.0, 2.0]])\n",
"traj2 = np.array([[0.1, 0.1], [1.1, 1.1], [2.1, 2.1]])\n",
"\n",
"print(\"Trajectory 1:\", traj1)\n",
"print(\"Trajectory 2:\", traj2)"
]
},
{
"cell_type": "markdown",
"id": "basic-dist-desc",
"metadata": {},
"source": [
"Now we can calculate different trajectory distances:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "compute-basic-dists",
"metadata": {},
"outputs": [],
"source": [
"# Calculate different trajectory distances\n",
"sspd_dist = traj_dist_rs.sspd(traj1, traj2, \"euclidean\")\n",
"dtw_dist = traj_dist_rs.dtw(traj1, traj2, \"euclidean\")\n",
"hausdorff_dist = traj_dist_rs.hausdorff(traj1, traj2, \"euclidean\")\n",
"\n",
"print(f\"SSPD distance: {sspd_dist:.6f}\")\n",
"print(f\"DTW distance: {dtw_dist.distance:.6f}\")\n",
"print(f\"Hausdorff distance: {hausdorff_dist:.6f}\")"
]
},
{
"cell_type": "markdown",
"id": "spherical-title",
"metadata": {},
"source": [
"## Using Spherical Distance\n",
"\n",
"For geographic coordinates (latitude/longitude), use spherical distance:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "spherical-data",
"metadata": {},
"outputs": [],
"source": [
"import traj_dist_rs\n",
"import numpy as np\n",
"\n",
"# Geographic coordinates as [latitude, longitude]\n",
"geo_traj1 = np.array([[40.7128, -74.0060], [40.7589, -73.9851], [40.7831, -73.9712]]) # NYC trajectory\n",
"geo_traj2 = np.array([[40.7228, -74.0160], [40.7689, -73.9951], [40.7931, -73.9812]]) # Similar NYC trajectory\n",
"\n",
"print(\"Geographic Trajectory 1 (NYC):\", geo_traj1)\n",
"print(\"Geographic Trajectory 2 (Similar to NYC):\", geo_traj2)"
]
},
{
"cell_type": "markdown",
"id": "spherical-calc-desc",
"metadata": {},
"source": [
"Calculate distances using spherical distance (Haversine formula):"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "spherical-dists",
"metadata": {},
"outputs": [],
"source": [
"# Calculate distances using spherical distance (Haversine formula)\n",
"sspd_dist = traj_dist_rs.sspd(geo_traj1, geo_traj2, \"spherical\")\n",
"dtw_dist = traj_dist_rs.dtw(geo_traj1, geo_traj2, \"spherical\")\n",
"\n",
"print(f\"SSPD spherical distance: {sspd_dist:.2f} meters\")\n",
"print(f\"DTW spherical distance: {dtw_dist.distance:.2f} meters\")"
]
},
{
"cell_type": "markdown",
"id": "params-title",
"metadata": {},
"source": [
"## Algorithms with Parameters\n",
"\n",
"Some algorithms require additional parameters:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "params-data",
"metadata": {},
"outputs": [],
"source": [
"import traj_dist_rs\n",
"import numpy as np\n",
"\n",
"traj1 = np.array([[0.0, 0.0], [1.0, 1.0], [2.0, 2.0], [3.0, 3.0]])\n",
"traj2 = np.array([[0.5, 0.5], [1.5, 1.5], [2.5, 2.5], [3.5, 3.5]])\n",
"\n",
"print(\"Using trajectories with parameters:\")\n",
"print(\"Trajectory 1:\", traj1)\n",
"print(\"Trajectory 2:\", traj2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "params-compute",
"metadata": {},
"outputs": [],
"source": [
"# LCSS with epsilon parameter - threshold for point matching\n",
"lcss_dist = traj_dist_rs.lcss(traj1, traj2, \"euclidean\", 1.0)\n",
"\n",
"# EDR with epsilon parameter - threshold for point matching\n",
"edr_dist = traj_dist_rs.edr(traj1, traj2, \"euclidean\", 1.0)\n",
"\n",
"# ERP with gap point - reference point for penalties\n",
"erp_dist = traj_dist_rs.erp_compat_traj_dist(traj1, traj2, \"euclidean\", [0.0, 0.0])\n",
"\n",
"print(f\"LCSS distance (eps=1.0): {lcss_dist.distance:.6f}\")\n",
"print(f\"EDR distance (eps=1.0): {edr_dist.distance:.6f}\")\n",
"print(f\"ERP distance (g=[0,0]): {erp_dist.distance:.6f}\")"
]
},
{
"cell_type": "markdown",
"id": "compare-all-title",
"metadata": {},
"source": [
"## Comparing All Available Algorithms\n",
"\n",
"Let's compare all available algorithms on the same trajectories:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "compare-all-data",
"metadata": {},
"outputs": [],
"source": [
"# Create sample trajectories\n",
"traj1 = [[0.0, 0.0], [1.0, 1.0], [2.0, 2.0]]\n",
"traj2 = [[0.0, 1.0], [1.0, 0.0], [2.0, 1.0]]\n",
"\n",
"print(\"Comparing All Algorithms:\")\n",
"print(\"Trajectory 1:\", traj1)\n",
"print(\"Trajectory 2:\", traj2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "compare-all-compute",
"metadata": {},
"outputs": [],
"source": [
"# Calculate all available distances\n",
"distances = {}\n",
"\n",
"# Standard algorithms without parameters\n",
"distances['SSPD'] = traj_dist_rs.sspd(traj1, traj2, \"euclidean\")\n",
"distances['DTW'] = traj_dist_rs.dtw(traj1, traj2, \"euclidean\")\n",
"distances['Hausdorff'] = traj_dist_rs.hausdorff(traj1, traj2, \"euclidean\")\n",
"distances['Discret Frechet'] = traj_dist_rs.discret_frechet(traj1, traj2, \"euclidean\")\n",
"\n",
"# Algorithms with parameters\n",
"distances['LCSS'] = traj_dist_rs.lcss(traj1, traj2, \"euclidean\", 2.0)\n",
"distances['EDR'] = traj_dist_rs.edr(traj1, traj2, \"euclidean\", 2.0)\n",
"distances['ERP (compat)'] = traj_dist_rs.erp_compat_traj_dist(traj1, traj2, \"euclidean\", [0.0, 0.0])\n",
"distances['ERP (standard)'] = traj_dist_rs.erp_standard(traj1, traj2, \"euclidean\", [0.0, 0.0])\n",
"\n",
"# Print results\n",
"for algorithm, distance in distances.items():\n",
" print(f\"{algorithm}: {distance if isinstance(distance, float) else distance.distance:.6f}\")"
]
},
{
"cell_type": "markdown",
"id": "dpresult-title",
"metadata": {},
"source": [
"## Using DpResult (Distance with Optional Matrix)\n",
"\n",
"Some algorithms return a `DpResult` object that contains both the distance value and optionally the alignment matrix:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dpresult-demo",
"metadata": {},
"outputs": [],
"source": [
"import traj_dist_rs\n",
"import numpy as np\n",
"\n",
"traj1 = np.array([[0.0, 0.0], [1.0, 1.0], [2.0, 2.0]])\n",
"traj2 = np.array([[0.1, 0.1], [1.1, 1.1], [2.1, 2.1]])\n",
"\n",
"# DTW with full matrix\n",
"result = traj_dist_rs.dtw(traj1, traj2, \"euclidean\", use_full_matrix=True)\n",
"print(f\"DTW distance: {result.distance}\")\n",
"print(f\"Matrix shape: {result.matrix.shape if result.matrix is not None else 'None'}\")\n",
"\n",
"# DTW without matrix (faster)\n",
"result_no_matrix = traj_dist_rs.dtw(traj1, traj2, \"euclidean\", use_full_matrix=False)\n",
"print(f\"DTW distance (no matrix): {result_no_matrix.distance}\")"
]
},
{
"cell_type": "markdown",
"id": "viz-title",
"metadata": {},
"source": [
"## Visualizing Trajectories and Distances\n",
"\n",
"Let's visualize the trajectories and compare algorithm results:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "viz-demo",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"# Create trajectories for visualization\n",
"traj1 = [[0.0, 0.0], [1.0, 1.0], [2.0, 2.0], [3.0, 3.0]]\n",
"traj2 = [[0.0, 1.0], [1.0, 0.0], [2.0, 3.0], [3.0, 2.0]]\n",
"\n",
"# Calculate distances\n",
"sspd_dist = traj_dist_rs.sspd(traj1, traj2, \"euclidean\")\n",
"dtw_dist = traj_dist_rs.dtw(traj1, traj2, \"euclidean\")\n",
"hausdorff_dist = traj_dist_rs.hausdorff(traj1, traj2, \"euclidean\")\n",
"\n",
"# Plot trajectories\n",
"plt.figure(figsize=(10, 6))\n",
"traj1_x, traj1_y = zip(*traj1)\n",
"traj2_x, traj2_y = zip(*traj2)\n",
"\n",
"plt.plot(traj1_x, traj1_y, 'b-o', label='Trajectory 1', linewidth=2, markersize=8)\n",
"plt.plot(traj2_x, traj2_y, 'r-s', label='Trajectory 2', linewidth=2, markersize=8)\n",
"\n",
"plt.title(f'Trajectory Comparison\\nSSPD: {sspd_dist:.3f}, DTW: {dtw_dist.distance:.3f}, Hausdorff: {hausdorff_dist:.3f}')\n",
"plt.xlabel('X coordinate')\n",
"plt.ylabel('Y coordinate')\n",
"plt.legend()\n",
"plt.grid(True, linestyle='--', alpha=0.6)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "pdist-title",
"metadata": {},
"source": [
"## Batch Computation with pdist\n",
"\n",
"Compute pairwise distances between multiple trajectories:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "pdist-demo",
"metadata": {},
"outputs": [],
"source": [
"import traj_dist_rs\n",
"import numpy as np\n",
"\n",
"# List of trajectories\n",
"trajectories = [\n",
" np.array([[0.0, 0.0], [1.0, 1.0]]),\n",
" np.array([[0.1, 0.1], [1.1, 1.1]]),\n",
" np.array([[0.2, 0.2], [1.2, 1.2]]),\n",
" np.array([[0.3, 0.3], [1.3, 1.3]]),\n",
"]\n",
"\n",
"print(f\"Number of trajectories: {len(trajectories)}\")\n",
"\n",
"# Create metric configuration using Metric class\n",
"metric = traj_dist_rs.Metric.sspd(type_d=\"euclidean\")\n",
"\n",
"# Compute pairwise distances (compressed format)\n",
"distances = traj_dist_rs.pdist(trajectories, metric=metric)\n",
"print(f\"Number of pairwise distances: {len(distances)}\")\n",
"print(f\"Distances: {distances}\")"
]
},
{
"cell_type": "markdown",
"id": "cdist-title",
"metadata": {},
"source": [
"## Batch Computation with cdist\n",
"\n",
"Compute cross-distance matrix between two trajectory collections:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cdist-demo",
"metadata": {},
"outputs": [],
"source": [
"import traj_dist_rs\n",
"import numpy as np\n",
"\n",
"# Two collections of trajectories\n",
"trajectories_a = [\n",
" np.array([[0.0, 0.0], [1.0, 1.0]]),\n",
" np.array([[0.1, 0.1], [1.1, 1.1]]),\n",
"]\n",
"\n",
"trajectories_b = [\n",
" np.array([[0.2, 0.2], [1.2, 1.2]]),\n",
" np.array([[0.3, 0.3], [1.3, 1.3]]),\n",
" np.array([[0.4, 0.4], [1.4, 1.4]]),\n",
"]\n",
"\n",
"print(f\"Collection A: {len(trajectories_a)} trajectories\")\n",
"print(f\"Collection B: {len(trajectories_b)} trajectories\")\n",
"\n",
"# Create metric configuration\n",
"metric = traj_dist_rs.Metric.dtw(type_d=\"euclidean\")\n",
"\n",
"# Compute cross-distance matrix\n",
"distance_matrix = traj_dist_rs.cdist(trajectories_a, trajectories_b, metric=metric)\n",
"print(f\"Distance matrix shape: {distance_matrix.shape}\")\n",
"print(f\"Distance matrix:\\n{distance_matrix}\")"
]
},
{
"cell_type": "markdown",
"id": "parallel-title",
"metadata": {},
"source": [
"## Parallel Processing with pdist\n",
"\n",
"Use parallel processing for faster batch computation:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "parallel-demo",
"metadata": {},
"outputs": [],
"source": [
"import traj_dist_rs\n",
"import numpy as np\n",
"import time\n",
"\n",
"# Create a larger dataset\n",
"trajectories = [np.random.rand(100, 2) for _ in range(50)]\n",
"print(f\"Number of trajectories: {len(trajectories)}\")\n",
"\n",
"# Create metric configuration\n",
"metric = traj_dist_rs.Metric.sspd(type_d=\"euclidean\")\n",
"\n",
"# Sequential computation\n",
"start = time.time()\n",
"distances_seq = traj_dist_rs.pdist(trajectories, metric=metric, parallel=False)\n",
"seq_time = time.time() - start\n",
"\n",
"# Parallel computation\n",
"start = time.time()\n",
"distances_par = traj_dist_rs.pdist(trajectories, metric=metric, parallel=True)\n",
"par_time = time.time() - start\n",
"\n",
"print(f\"Sequential time: {seq_time:.3f}s\")\n",
"print(f\"Parallel time: {par_time:.3f}s\")\n",
"print(f\"Speedup: {seq_time/par_time:.2f}x\")\n",
"print(f\"Results match: {distances_seq.shape == distances_par.shape}\")"
]
},
{
"cell_type": "markdown",
"id": "cdist-parallel-title",
"metadata": {},
"source": [
"## Parallel Processing with cdist\n",
"\n",
"Use parallel processing with cdist for cross-distance matrix computation:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cdist-parallel-demo",
"metadata": {},
"outputs": [],
"source": [
"import traj_dist_rs\n",
"import numpy as np\n",
"import time\n",
"\n",
"# Create two larger trajectory collections\n",
"trajectories_a = [np.random.rand(100, 2) for _ in range(30)]\n",
"trajectories_b = [np.random.rand(100, 2) for _ in range(30)]\n",
"\n",
"print(f\"Collection A: {len(trajectories_a)} trajectories\")\n",
"print(f\"Collection B: {len(trajectories_b)} trajectories\")\n",
"\n",
"# Create metric configuration\n",
"metric = traj_dist_rs.Metric.dtw(type_d=\"euclidean\")\n",
"\n",
"# Sequential computation\n",
"start = time.time()\n",
"matrix_seq = traj_dist_rs.cdist(trajectories_a, trajectories_b, metric=metric, parallel=False)\n",
"seq_time = time.time() - start\n",
"\n",
"# Parallel computation\n",
"start = time.time()\n",
"matrix_par = traj_dist_rs.cdist(trajectories_a, trajectories_b, metric=metric, parallel=True)\n",
"par_time = time.time() - start\n",
"\n",
"print(f\"Sequential time: {seq_time:.3f}s\")\n",
"print(f\"Parallel time: {par_time:.3f}s\")\n",
"print(f\"Speedup: {seq_time/par_time:.2f}x\")\n",
"print(f\"Results match: {np.allclose(matrix_seq, matrix_par)}\")\n",
"print(f\"Matrix shape: {matrix_par.shape}\")"
]
},
{
"cell_type": "markdown",
"id": "metric-api-title",
"metadata": {},
"source": [
"## Using Metric API with Different Algorithms\n",
"\n",
"The Metric class provides type-safe configuration for all algorithms:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "metric-api-demo",
"metadata": {},
"outputs": [],
"source": [
"import traj_dist_rs\n",
"import numpy as np\n",
"\n",
"traj1 = np.array([[0.0, 0.0], [1.0, 1.0], [2.0, 2.0]])\n",
"traj2 = np.array([[0.1, 0.1], [1.1, 1.1], [2.1, 2.1]])\n",
"\n",
"# Create metrics for different algorithms\n",
"metric_sspd = traj_dist_rs.Metric.sspd(type_d=\"euclidean\")\n",
"metric_dtw = traj_dist_rs.Metric.dtw(type_d=\"euclidean\")\n",
"metric_hausdorff = traj_dist_rs.Metric.hausdorff(type_d=\"euclidean\")\n",
"metric_discret_frechet = traj_dist_rs.Metric.discret_frechet(type_d=\"euclidean\")\n",
"\n",
"# Algorithms with parameters\n",
"metric_lcss = traj_dist_rs.Metric.lcss(eps=0.5, type_d=\"euclidean\")\n",
"metric_edr = traj_dist_rs.Metric.edr(eps=0.5, type_d=\"euclidean\")\n",
"metric_erp = traj_dist_rs.Metric.erp(g=[0.0, 0.0], type_d=\"euclidean\")\n",
"\n",
"# Use metrics with batch computation\n",
"trajectories = [traj1, traj2]\n",
"distances_sspd = traj_dist_rs.pdist(trajectories, metric=metric_sspd)\n",
"distances_dtw = traj_dist_rs.pdist(trajectories, metric=metric_dtw)\n",
"distances_lcss = traj_dist_rs.pdist(trajectories, metric=metric_lcss)\n",
"\n",
"print(f\"SSPD distance: {distances_sspd[0]:.4f}\")\n",
"print(f\"DTW distance: {distances_dtw[0]:.4f}\")\n",
"print(f\"LCSS distance: {distances_lcss[0]:.4f}\")"
]
},
{
"cell_type": "markdown",
"id": "joblib-title",
"metadata": {},
"source": [
"## Parallel Processing with joblib\n",
"\n",
"Use joblib for parallel computation with custom functions:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "joblib-demo",
"metadata": {},
"outputs": [],
"source": [
"import traj_dist_rs\n",
"import numpy as np\n",
"from joblib import Parallel, delayed\n",
"\n",
"def compute_dtw_distance(traj1, traj2):\n",
" \"\"\"Compute DTW distance between two trajectories.\"\"\"\n",
" result = traj_dist_rs.dtw(traj1, traj2, \"euclidean\", use_full_matrix=False)\n",
" return result.distance\n",
"\n",
"# Create a set of trajectories\n",
"trajectories = [np.random.rand(50, 2) for _ in range(20)]\n",
"print(f\"Number of trajectories: {len(trajectories)}\")\n",
"\n",
"# Compute pairwise distances in parallel\n",
"results = Parallel(n_jobs=-1)(\n",
" delayed(compute_dtw_distance)(t1, t2)\n",
" for i, t1 in enumerate(trajectories)\n",
" for j, t2 in enumerate(trajectories)\n",
" if i < j # Only compute unique pairs\n",
")\n",
"\n",
"print(f\"Computed {len(results)} pairwise distances\")\n",
"print(f\"Sample distances: {results[:5]}\")"
]
},
{
"cell_type": "markdown",
"id": "perf-title",
"metadata": {},
"source": [
"## Performance Comparison\n",
"\n",
"Let's compare the performance of different algorithms:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "perf-demo",
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"\n",
"# Create longer trajectories for performance testing\n",
"def create_random_trajectory(length, max_coord=10.0):\n",
" return [[np.random.uniform(0, max_coord), np.random.uniform(0, max_coord)] \n",
" for _ in range(length)]\n",
"\n",
"# Create test trajectories\n",
"traj_short = create_random_trajectory(10)\n",
"traj_medium = create_random_trajectory(50)\n",
"\n",
"print(\"Performance Comparison (short trajectory - 10 points):\")\n",
"algorithms = [\n",
" ('SSPD', lambda t1, t2: traj_dist_rs.sspd(t1, t2, \"euclidean\")),\n",
" ('DTW', lambda t1, t2: traj_dist_rs.dtw(t1, t2, \"euclidean\")),\n",
" ('Hausdorff', lambda t1, t2: traj_dist_rs.hausdorff(t1, t2, \"euclidean\")),\n",
" ('Discret Frechet', lambda t1, t2: traj_dist_rs.discret_frechet(t1, t2, \"euclidean\")),\n",
"]\n",
"\n",
"for name, func in algorithms:\n",
" start_time = time.time()\n",
" result = func(traj_short, traj_short)\n",
" end_time = time.time()\n",
" print(f\"{name}: {end_time - start_time:.6f}s, distance: {result if isinstance(result, float) else result.distance:.6f}\")"
]
},
{
"cell_type": "markdown",
"id": "realworld-title",
"metadata": {},
"source": [
"## Real-World Data Usage\n",
"\n",
"Here's an example of how to use the library with real-world trajectory data:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "realworld-demo",
"metadata": {},
"outputs": [],
"source": [
"# Example with GPS-like data\n",
"def create_gps_trajectory(start_lat, start_lon, num_points, lat_variation=0.01, lon_variation=0.01):\n",
" \"\"\"Create a GPS-like trajectory with some variation\"\"\"\n",
" trajectory = []\n",
" for i in range(num_points):\n",
" lat = start_lat + i * 0.001 + np.random.uniform(-lat_variation, lat_variation)\n",
" lon = start_lon + i * 0.001 + np.random.uniform(-lon_variation, lon_variation)\n",
" trajectory.append([lat, lon])\n",
" return trajectory\n",
"\n",
"# Create two similar GPS trajectories\n",
"gps_traj1 = create_gps_trajectory(40.7128, -74.0060, 20) # NYC-like\n",
"gps_traj2 = create_gps_trajectory(40.7130, -74.0062, 20) # Similar, slightly different start\n",
"\n",
"print(f\"GPS Trajectory 1 (first 3 points): {gps_traj1[:3]}\")\n",
"print(f\"GPS Trajectory 2 (first 3 points): {gps_traj2[:3]}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "realworld-calc",
"metadata": {},
"outputs": [],
"source": [
"# Calculate distances using spherical distance for GPS coordinates\n",
"sspd_dist = traj_dist_rs.sspd(gps_traj1, gps_traj2, \"spherical\")\n",
"dtw_dist = traj_dist_rs.dtw(gps_traj1, gps_traj2, \"spherical\")\n",
"hausdorff_dist = traj_dist_rs.hausdorff(gps_traj1, gps_traj2, \"spherical\")\n",
"\n",
"print(f\"SSPD spherical distance: {sspd_dist:.2f} meters\")\n",
"print(f\"DTW spherical distance: {dtw_dist.distance:.2f} meters\")\n",
"print(f\"Hausdorff spherical distance: {hausdorff_dist:.2f} meters\")"
]
},
{
"cell_type": "markdown",
"id": "error-title",
"metadata": {},
"source": [
"## Error Handling\n",
"\n",
"The library provides appropriate error handling:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "error-demo",
"metadata": {},
"outputs": [],
"source": [
"# Example of error handling\n",
"try:\n",
" # This will raise an error - invalid distance type\n",
" invalid_dist = traj_dist_rs.sspd([[0, 0], [1, 1]], [[1, 1], [2, 2]], \"invalid_type\")\n",
"except ValueError as e:\n",
" print(f\"Caught expected error: {e}\")\n",
"\n",
"try:\n",
" # This will raise an error - invalid trajectory format\n",
" invalid_dist = traj_dist_rs.sspd([[0, 0, 0], [1, 1]], [[0, 0], [1, 1]], \"euclidean\")\n",
"except Exception as e:\n",
" print(f\"Caught expected error: {e}\")"
]
},
{
"cell_type": "markdown",
"id": "summary",
"metadata": {},
"source": [
"## Summary\n",
"\n",
"This guide covered:\n",
"\n",
"1. Basic installation and import\n",
"2. Different trajectory distance algorithms\n",
"3. Euclidean vs. Spherical distance calculations\n",
"4. Algorithms with parameters (LCSS, EDR, ERP)\n",
"5. Comparing all available algorithms\n",
"6. Visualizing trajectories and distances\n",
"7. Batch computation with pdist and cdist\n",
"8. Parallel processing with Rayon and joblib\n",
"9. Performance considerations\n",
"10. Real-world GPS data usage\n",
"11. Error handling\n",
"\n",
"The `traj-dist-rs` library provides high-performance trajectory distance calculations with both Python and Rust APIs, making it suitable for a wide range of trajectory analysis applications.\n",
"\n",
"For more information on each algorithm, refer to the API documentation."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "traj-dist-rs",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.17"
}
},
"nbformat": 4,
"nbformat_minor": 5
}