Skip to main content

OSM_graph

Quickly generate isochrones for Python and Rust!

This library provides a set of tools for generating isochrones and reverse isochrones from geographic coordinates. It leverages OpenStreetMap data to construct road networks and calculate areas accessible within specified time limits. The library is designed for both Rust and Python, offering high performance and easy integration into data science workflows.

Isochrones

Features

  • Graph Construction: Parses OpenStreetMap data to construct a directed graph representing the road network.
  • Graph Simplification: Topologically simplifies the graph by collapsing linear chains and deduplicating parallel edges, reducing node/edge count by ~89% for faster downstream computation.
  • Spatial Indexing: R-tree spatial index for O(log n) nearest-node lookups, built once and reused for all queries.
  • Isochrone Calculation: Generates isochrones using a single Dijkstra traversal, with hull computation parallelized across time limits.
  • Routing: A* point-to-point routing returning a GeoJSON LineString with distance, total duration, and cumulative travel times at each waypoint.
  • Geocoding: Place-name to coordinate lookup via Nominatim.
  • Concave and Convex Hulls: Supports convex, fast-concave, and concave hull types for isochrone shapes.
  • Caching: Three-level cache (disk XML → in-memory XML → in-memory graph) so repeated queries for the same area skip the network entirely, persisting across process restarts.
  • Python Integration: Python bindings for all core functionality — isochrones, routing, geocoding, and cache management.
  • GeoJSON Output: All results returned as GeoJSON strings for easy integration with mapping tools and data science workflows.

Installation

To use the library in Rust, add it to your Cargo.toml:

[dependencies]
osm-graph = "0.2.0"

For Python:

pip install pysochrone

Or build from source with Rust and maturin installed:

maturin develop

Usage

Python

Isochrones

import pysochrone

isochrones = pysochrone.calc_isochrones(
    48.137144,                           # lat
    11.575399,                           # lon
    [300, 600, 900, 1200, 1500, 1800],  # time limits in seconds
    "Drive",                             # Drive | DriveService | Walk | Bike | All | AllPrivate
    "Concave",                           # Convex | FastConcave | Concave
    max_dist=10_000,                     # optional bounding box radius in metres
    retain_all=False,                    # False = simplified graph (default)
)
# Returns a list of GeoJSON geometry strings, one per time limit

Routing

route = pysochrone.calc_route(
    48.137144, 11.575399,   # origin lat, lon
    48.154560, 11.530840,   # destination lat, lon
    "Drive",
)
# Returns a GeoJSON Feature (LineString) with properties:
#   distance_m          – total distance in metres
#   duration_s          – total travel time in seconds
#   cumulative_times_s  – travel time at each waypoint (parallel to coordinates)

Geocoding

lat, lon = pysochrone.geocode("Marienplatz, Munich, Germany")

Points of interest

# Pass any isochrone string from calc_isochrones
pois = pysochrone.fetch_pois(isochrones[0])
# Returns a GeoJSON FeatureCollection; each feature carries raw OSM tags as properties

Cache management

pysochrone.cache_dir()    # path to the on-disk XML cache
pysochrone.clear_cache()  # clear both in-memory and disk caches

Rust

use osm_graph::isochrone::{calculate_isochrones_from_point, HullType};
use osm_graph::overpass::NetworkType;

#[tokio::main]
async fn main() {
    let (isochrones, _graph) = calculate_isochrones_from_point(
        48.137144,
        11.575399,
        Some(10_000.0),                                        // max_dist in metres; None = auto
        vec![300.0, 600.0, 900.0, 1_200.0, 1_500.0, 1_800.0],
        NetworkType::Drive,
        HullType::Concave,
        false,                                                 // false = simplified (faster)
    )
    .await
    .unwrap();
}

Performance

Benchmarks run on Munich road network, cached data only (no network I/O), Intel Core i7-11370H. Compared against osmnx using a pre-enriched graph and a single Dijkstra pass — the fairest apples-to-apples comparison. To reproduce: python benchmarks/comparison.py

Radius Nodes Edges pysochrone osmnx Speedup
5,000m 6,251 15,356 0.030s 0.190s 6.3×
10,000m 16,183 41,601 0.064s 0.365s 5.7×
20,000m 32,501 82,385 0.092s 0.455s 4.9×

The ~5–6× gap reflects compiled Rust and petgraph's flat adjacency list vs pure-Python NetworkX. osmnx is a full-featured geospatial analysis library rather than a purpose-built isochrone engine — this comparison isolates the core Dijkstra computation to show what you gain from a compiled, cache-aware implementation.

pysochrone's caching model means graph construction and edge enrichment are one-time costs paid on the first query for an area. Subsequent queries reuse the in-memory graph directly, so the numbers above represent steady-state performance for repeated queries over the same region.

Performance comparison

Roadmap

  • Testing and benchmarks.
  • Customizable Speed Limits: Allow users to specify custom speed limits for different road types.
  • Support for Pedestrian and Bicycle Networks: Expand the graph construction to support pedestrian and bicycle network types.
  • Topological simplification of osm graphs for more efficient downstream analytics.
  • Additional Roadnetwork analytics.
  • Routing engine.
  • Advanced Caching Strategies: Implement more sophisticated caching mechanisms for dynamic query parameters.
  • Interactive Visualization Tools: Develop a set of tools for interactive visualization of isochrones in web applications.
  • API Integration: Provide integration options with third-party APIs for enhanced data accuracy and features.
  • Optimization and Parallel Computing: Further optimize the graph algorithms and explore parallel computing options for large-scale data.

Contributing

Contributions are welcome! Please submit pull requests, open issues for discussion, and suggest new features or improvements.

License

This library is licensed under MIT License.

Metadata

Release files for pysochrone 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pysochrone 0.2.0
File Size Uploaded
pysochrone-0.2.0.tar.gz 53.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pysochrone 0.2.0
File Interpreter ABI Platform
pysochrone-0.2.0-cp310-none-win_amd64.whl CPython 3.10 none Windows x86-64 Details

Total release size: 1.7 MB

Release files / pysochrone-0.2.0.tar.gz

Download URL pysochrone-0.2.0.tar.gz
Size 53.2 kB
Tags Source
SHA-256 checksum
How to use checksums
17169a4b282b393886a34672d51d1614079cc055c3772bb23682d65839b3df84
BLAKE2b-256 checksum
How to use checksums
8daa4794ce9b4b27378fee73796e3eae2d763106ec5b75a5b0a575b65bf429e5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.5

Release files / pysochrone-0.2.0-cp310-none-win_amd64.whl

Download URL pysochrone-0.2.0-cp310-none-win_amd64.whl
Size 1.6 MB
Tags CPython 3.10 Windows x86-64
SHA-256 checksum
How to use checksums
34f4c6abd79220b9c34b871b76ad925e72e2481de3de9129fbd4dc78959f5eda
BLAKE2b-256 checksum
How to use checksums
d8e838775703e38588c8715a3cc611174a78ba2ad28306960b568afcbe5374cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.5

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page