polars-gps-hilbert
⚠️ EXPERIMENTAL SOFTWARE: This plugin is in active development and should not be used in production environments. APIs may change without notice.
A high-performance Polars plugin for GPS trajectory indexing using 3D Hilbert curves. This plugin enables efficient spatial-temporal indexing of GPS data for applications like trajectory analysis, route deviation detection, and spatial queries.
Features
- 3D Hilbert Curve Indexing: Combines latitude, longitude, and timestamp into a single index
- Lazy Evaluation: Supports out-of-core processing for datasets larger than memory
- Automatic Bounds Detection: Automatically computes spatial and temporal bounds or accepts pre-computed values
- High Performance: Written in Rust for maximum performance (10-15M points/second)
- Polars Integration: Seamless integration with Polars' expression API and lazy evaluation
Installation
From Source
# Clone the repository
git clone https://github.com/nullbutt/polars-gps-hilbert.git
cd polars-gps-hilbert
# Install UV (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Build and install the plugin
./build_and_test.sh
Requirements
- Python >= 3.8
- Rust toolchain (for building from source)
- Polars >= 0.20.0
- UV (for Python project management)
Quick Start
import polars as pl
import polars_gps_hilbert as gps
# Load GPS trajectory data
df = pl.read_parquet("gps_data.parquet")
# Add Hilbert index with automatic bounds computation
df = df.with_columns(
gps.hilbert_index("latitude", "longitude", "timestamp").alias("hilbert_idx")
)
# Use for spatial queries
nearby_points = df.sort("hilbert_idx").slice(1000, 100)
Usage Examples
Basic Indexing
import polars as pl
import polars_gps_hilbert as gps
df = pl.DataFrame({
"latitude": [37.7749, 34.0522, 40.7128],
"longitude": [-122.4194, -118.2437, -74.0060],
"timestamp": [1640995200, 1640998800, 1641002400]
})
result = df.with_columns(
gps.hilbert_index("latitude", "longitude", "timestamp").alias("hilbert_idx")
)
With Pre-computed Bounds (Better Performance)
bounds = {
"lat_min": -90.0, "lat_max": 90.0,
"lon_min": -180.0, "lon_max": 180.0,
"ts_min": 1640995200, "ts_max": 1767225600
}
df = df.with_columns(
gps.hilbert_index("latitude", "longitude", "timestamp", bounds=bounds).alias("hilbert_idx")
)
Lazy Evaluation for Large Datasets
# Perfect for datasets larger than memory
lf = pl.scan_parquet("huge_gps_dataset.parquet")
result = lf.with_columns(
gps.hilbert_index("latitude", "longitude", "timestamp").alias("hilbert_idx")
).filter(
pl.col("hilbert_idx") < 1000000
).collect()
Spatial Range Queries
# Sort by Hilbert index for efficient spatial queries
df_sorted = df.sort("hilbert_idx")
# Find nearby points using index ranges
reference_idx = df_sorted["hilbert_idx"][1000]
range_size = 1000000
nearby = df_sorted.filter(
(pl.col("hilbert_idx") >= reference_idx - range_size) &
(pl.col("hilbert_idx") <= reference_idx + range_size)
)
Performance
Benchmarked on Apple M1 MacBook Pro:
- Throughput: 10-15 million points/second
- Memory overhead: 8 bytes per index (21.8% increase)
- Spatial locality: Excellent for nearby GPS points
- Scales linearly: Tested up to 200M points
Dataset Generation
Generate test datasets for benchmarking:
# Generate 1M point test dataset
cd examples
python generate_sample_data.py
# Generate full 200M point dataset (requires significant time/space)
python generate_sample_data.py --full
Test datasets include:
- GPS points across 50+ countries
- 5,000+ unique vehicles
- Realistic trajectory simulation
- Timestamps from 2022-2025
Testing
# Run basic functionality tests
pytest tests/test_basic.py
# Run performance tests
pytest tests/test_performance.py
# Run all tests
pytest tests/
# Run examples
python examples/basic_usage.py
# Benchmark 200M dataset
python examples/benchmark_200M.py
Project Structure
polars-gps-hilbert/
├── src/ # Rust source code
│ ├── lib.rs # Library entry point
│ ├── expressions.rs # Polars expression functions
│ ├── gps_hilbert.rs # Core Hilbert indexing logic
│ └── utils.rs # Utility functions
├── python/ # Python bindings
│ └── polars_gps_hilbert/
│ └── __init__.py # Python API
├── examples/ # Usage examples and benchmarks
│ ├── basic_usage.py # Basic usage examples
│ ├── generate_sample_data.py # Dataset generation
│ └── benchmark_200M.py # Large-scale benchmarks
├── tests/ # Test suite
│ ├── test_basic.py # Basic functionality tests
│ ├── test_performance.py # Performance tests
│ └── test_gps_hilbert.py # Legacy comprehensive tests
└── Cargo.toml # Rust dependencies
Technical Details
- Hilbert Curves: Uses the
lindelcrate for efficient 3D Hilbert curve computation - Precision: Configurable bits per dimension (default: 21 bits, 63 total)
- Bounds: Auto-computed or pre-specified for optimal performance
- Null Handling: Graceful handling of missing GPS coordinates
- Validation: Input validation for GPS coordinate ranges
Use Cases
- Vehicle Trajectory Analysis: Index millions of GPS points for efficient trajectory reconstruction
- Route Deviation Detection: Quickly identify when vehicles deviate from expected routes
- Spatial-Temporal Clustering: Group nearby points in space and time
- Geofencing: Efficient point-in-region queries
- Traffic Pattern Analysis: Analyze movement patterns across time and space
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
License
MIT License - see LICENSE file for details.
Acknowledgments
Metadata
Release files for polars-gps-hilbert 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| polars_gps_hilbert-0.1.1.tar.gz | 44.5 kB | Without provenance | Details for polars_gps_hilbert-0.1.1.tar.gz |
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| polars_gps_hilbert-0.1.1-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details for polars_gps_hilbert-0.1.1-cp39-abi3-win_amd64.whl |
| polars_gps_hilbert-0.1.1-cp39-abi3-manylinux_2_34_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.34+ x86-64 | Details for polars_gps_hilbert-0.1.1-cp39-abi3-manylinux_2_34_x86_64.whl |
| polars_gps_hilbert-0.1.1-cp39-abi3-macosx_11_0_arm64.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64 | Details for polars_gps_hilbert-0.1.1-cp39-abi3-macosx_11_0_arm64.whl |
Total release size: 15.2 MB
Release files / polars_gps_hilbert-0.1.1.tar.gz
| Download URL | polars_gps_hilbert-0.1.1.tar.gz |
|---|---|
| Size | 44.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5e65ea7b42b3405f4671e96594525ac169a9a225ee9012debdfd8312a5ea4551
|
|
BLAKE2b-256 checksum How to use checksums |
f70f94ffe7624d3b0f3f7c83e9e4fb1a70068ece9f35618d50bed86e5a154074
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Release files / polars_gps_hilbert-0.1.1-cp39-abi3-win_amd64.whl
| Download URL | polars_gps_hilbert-0.1.1-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 5.1 MB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
b013b7bd46e014ba2e24c88b69a260b0c1f23911ef674bf9d106d6c5bd9c5818
|
|
BLAKE2b-256 checksum How to use checksums |
57c8d4023525c1e764ce56ea5d8e66b7f7e2bc59473bf074857a7d2d9c14df3d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Release files / polars_gps_hilbert-0.1.1-cp39-abi3-manylinux_2_34_x86_64.whl
| Download URL | polars_gps_hilbert-0.1.1-cp39-abi3-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 5.4 MB |
| Tags | CPython 3.9 Linux glibc 2.34+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
451eb906fb78520168d778148a7f2919bda4144fe766d95cdc90f69f005fbc21
|
|
BLAKE2b-256 checksum How to use checksums |
d2d4d7bee61e62c1937591d670424a191e905c09b190c91afbfd0776d631bb7e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Release files / polars_gps_hilbert-0.1.1-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | polars_gps_hilbert-0.1.1-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 4.6 MB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
408fed747f84506920bd9154048541b7a3aa1b138c9b13ee9247916cb76b8c29
|
|
BLAKE2b-256 checksum How to use checksums |
f9c6e6cc8b7bcb6289994f23e3b72b3caf753651291cf1d18ca197410d6ed42f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.9
|
Security for polars-gps-hilbert 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.