| Crates.io | tp-lib-py |
| lib.rs | tp-lib-py |
| version | 0.0.1 |
| created_at | 2026-01-08 15:10:15.133492+00 |
| updated_at | 2026-01-08 15:10:15.133492+00 |
| description | Python bindings for tp-lib-core GNSS projection library |
| homepage | |
| repository | https://github.com/Matdata-eu/tp-lib |
| max_upload_size | |
| id | 2030422 |
| size | 155,264 |
Status: โ Production Ready - All 66 Tasks Complete
Train positioning library for processing GNSS data by projecting positions onto railway track netelements (track axis centerlines). Developed for Infrabel infrastructure management.
tp-lib/ # Rust workspace root
โโโ tp-core/ # Core Rust library
โ โโโ src/
โ โ โโโ models/ # Data models (GnssPosition, Netelement, ProjectedPosition)
โ โ โโโ projection/ # Projection algorithms (geom, spatial indexing)
โ โ โโโ io/ # Input/output (CSV, GeoJSON, Arrow)
โ โ โโโ crs/ # Coordinate reference system transformations
โ โ โโโ temporal/ # Timezone handling utilities
โ โ โโโ errors.rs # Error types
โ โโโ tests/
โ โ โโโ unit/ # Unit tests
โ โ โโโ integration/ # Integration tests
โ โโโ benches/ # Performance benchmarks
โโโ tp-cli/ # Command-line interface
โโโ tp-py/ # Python bindings (PyO3)
# Clone repository
git clone https://github.com/infrabel/tp-lib
cd tp-lib
# Build all crates
cargo build --workspace
# Run tests
cargo test --workspace
# Run benchmarks
cargo bench --workspace
Use Docker to run the CLI without installing Rust:
# Build production image
docker build -t tp-lib:latest .
# Run with mounted data directory
docker run --rm -v $(pwd)/data:/data tp-lib:latest \
--gnss-file /data/gnss.csv \
--crs EPSG:4326 \
--network-file /data/network.geojson \
--output-format csv > output.csv
# Or use docker-compose
docker-compose up tp-cli
Run the complete test suite including CRS transformation tests:
# Using docker-compose (recommended)
docker-compose run --rm test
# Or build and run test image directly
docker build -f Dockerfile.test -t tp-lib-test .
docker run --rm tp-lib-test
# Run specific tests
docker-compose run --rm test cargo test test_identity_transform
# Run only CRS transformation tests
docker-compose run --rm test cargo test crs_transform
# Interactive shell for debugging
docker run --rm -it tp-lib-test bash
Why Docker for tests?
Dockerfile.test in GitHub Actions or other CI systems# CLI usage - CSV input/output
tp-cli --gnss-file train_positions.csv \
--gnss-crs EPSG:4326 \
--network-file railway_network.geojson \
--output-format csv > projected.csv
# GeoJSON output with custom warning threshold
tp-cli --gnss-file positions.csv \
--gnss-crs EPSG:4326 \
--network-file network.geojson \
--output-format json \
--warning-threshold 100.0 > projected.geojson
# Custom CSV column names
tp-cli --gnss-file data.csv \
--gnss-crs EPSG:4326 \
--network-file network.geojson \
--lat-col lat --lon-col lon --time-col timestamp
use tp_lib_core::{parse_gnss_csv, parse_network_geojson, RailwayNetwork};
use tp_lib_core::{project_gnss, ProjectionConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load railway network from GeoJSON
let netelements = parse_network_geojson("network.geojson")?;
let network = RailwayNetwork::new(netelements)?;
// Load GNSS positions from CSV
let positions = parse_gnss_csv(
"gnss.csv",
"EPSG:4326",
"latitude",
"longitude",
"timestamp"
)?;
// Project onto network with default config (50m warning threshold)
let config = ProjectionConfig::default();
let projected = project_gnss(&positions, &network, &config)?;
// Use results
for pos in projected {
println!(
"Position at {}m on netelement {} (accuracy: {:.2}m)",
pos.measure_meters,
pos.netelement_id,
pos.projection_distance_meters
);
}
Ok(())
}
Result: Fully functional CLI and library with 28 passing tests
GNSS CSV:
latitude,longitude,timestamp,altitude,hdop
50.8503,4.3517,2025-12-09T14:30:00+01:00,100.0,2.0
--gnss-crs flag--lat-col, --lon-col, --time-colRailway Network GeoJSON:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { "id": "NE001", "crs": "EPSG:4326" },
"geometry": {
"type": "LineString",
"coordinates": [
[4.35, 50.85],
[4.36, 50.86]
]
}
}
]
}
id property per netelementcrs property with EPSG code"Large projection distance" warnings:**
Indicates GNSS position is far from nearest track (> threshold). Possible causes:
Adjust threshold with --warning-threshold flag or investigate data quality.
"No Python 3.x interpreter found" build error:
Building with default features requires Python for PyO3 bindings. Disable with:
cargo build --no-default-features
Or install Python 3.12+ and ensure it's in your PATH.
TP-Lib uses proj4rs, a pure Rust implementation of PROJ.4, for coordinate reference system transformations. This eliminates system dependencies and enables cross-platform compatibility.
Key Features:
crs-definitions crate for EPSG code lookupSupported Transformations:
TP-Lib has been tested with Belgian railway coordinate systems:
Usage:
use tp_lib_core::crs::CrsTransformer;
use geo::Point;
// Create transformer (EPSG codes or PROJ strings)
let transformer = CrsTransformer::new(
"EPSG:4326".to_string(),
"EPSG:31370".to_string()
)?;
// Transform point (automatic degree/radian conversion)
let wgs84_point = Point::new(4.3517, 50.8503);
let lambert_point = transformer.transform(wgs84_point)?;
Technical Details:
Limitations:
Online: https://matdata-eu.github.io/tp-lib/
The documentation is automatically built and deployed on every push to main. It includes:
Build locally:
# Generate documentation for all workspace crates
cargo doc --no-deps --workspace
# Open in browser (on Windows)
start target/doc/index.html
# Open in browser (on Linux/macOS)
open target/doc/index.html # macOS
xdg-open target/doc/index.html # Linux
This project uses automated workflows for continuous integration and deployment:
See CI/CD Workflows Documentation for details on:
This project follows the TP-Lib Constitution v1.1.0 principles:
This project follows strict TDD workflow:
See CONTRIBUTING.md for guidelines.
Apache License 2.0 - See LICENSE for details
TP-Lib Contributors - GitHub Issues