Skip to main content

IduEdu

Code style: black PyPI version Tests and Coverage Coverage License Docs GitHub

IduEdu logo banner

IduEdu is an open-source Python toolkit for building and analyzing multimodal city networks from OpenStreetMap and local GTFS Schedule data. It downloads OSM data via Overpass, reads GTFS feeds, builds drive, walk, public-transport and intermodal networks, and stores them as UrbanGraph objects backed by GeoDataFrame node and edge tables.

Benchmark snapshot

The benchmark below isolates city-scale pedestrian graph construction, comparing IduEdu's tabular UrbanGraph representation with OSMnx's widely used NetworkX-backed workflow on the same area of interest for each city. Both simplification modes are shown because simplify changes the trade-off between graph-construction time and the size of the resulting graph.

Pedestrian graph construction benchmark

Across these repeated B1 runs, IduEdu built pedestrian graphs in about 6.6-10.0x less time without simplification and 3.9-6.7x less time with simplification enabled. The resulting geospatial graph object had a 10-12x lower deterministic representation-size estimate. Edge-row counts are shown as a representation detail: UrbanGraph can keep bidirectional walking edges as one row with a direction flag, while NetworkX-style directed multigraphs store separate directed edge rows.

Full protocol notes, limitations and raw-result links are in the benchmark documentation.

Documentation

Full documentation is published at https://iduclub.github.io/IduEdu/. Migrating from the old NetworkX-first API? See the UrbanGraph migration guide. Runnable examples are available for graph construction, UrbanGraph basics, object projection, and shortest paths. GTFS feeds are covered in the GTFS guide and the GTFS example, public-transport speeds and waits in the transport registry guide, and every setting in the configuration guide.

Features

  • Store graph topology, geometry, CRS and edge weights in UrbanGraph, a GeoDataFrame-native graph model.
  • Build drive and walk graphs from OpenStreetMap with local metric projection and optional simplification.
  • Build static public-transport graphs directly from OSM relations for bus, trolleybus, tram, subway, monorail and share taxi, with trains available through DEFAULT_REGISTRY_W_TRAIN.
  • Build static public-transport graphs from local GTFS Schedule directories or ZIP archives, using timetable headways for boarding weights and shapes or straight-line fallbacks for route geometry. Several feeds of one city can be merged with merge_gtfs_feeds.
  • Reconstruct shortest routes as ordered nodes and edge geometries for mapping.
  • Combine pedestrian and public-transport layers into one intermodal graph by projecting stops, platforms and station access points onto the walking network.
  • Compute shortest paths and OD matrices with Numba-backed CSR routines, cutoff thresholds and adaptive graph reversal for unbalanced origin-destination sets.
  • Work with connected, weakly connected and strongly connected UrbanGraph components.
  • Convert to and from NetworkX through optional compatibility utilities.
  • Snap geometries to graph nodes with nearest_nodes and validate custom graph edits.
  • Store graphs as .urbangraph archives with parquet tables and metadata.
  • Cache Overpass responses and query historical OSM snapshots.

Installation

pip install iduedu

IduEdu supports Python 3.11 through 3.14. The core package uses the standard geospatial stack including GeoPandas, Shapely, PyProj, NumPy, Pandas and SciPy. NetworkX utilities are optional compatibility helpers.

Use pip install "iduedu[io]" to enable .urbangraph parquet archive read/write helpers.

Use pip install "iduedu[pbf]" to build the same OSM graphs offline from local .osm.pbf extracts (for example Geofabrik downloads) instead of the Overpass API; see the configuration guide.

Quickstart

Build an intermodal graph

from iduedu import get_intermodal_graph

graph = get_intermodal_graph(
    osm_id=1114252,  # for example, Saint Petersburg's Vasileostrovsky District
    pt_kwargs={"transport_types": ["bus", "tram", "subway"]},
)

print(graph.nodes_gdf.head())
print(graph.edges_gdf.head())

Graph builders return UrbanGraph. Nodes are stored in graph.nodes_gdf; edges are stored in graph.edges_gdf and include u, v, geometry, length_meter and time_min.

OSM-based boarding waits are mode-specific defaults stored in TransportRegistry. GTFS boarding waits are derived from the selected feed schedule instead.

Build a public-transport graph from GTFS

from iduedu import get_gtfs_public_transport_graph

pt_graph = get_gtfs_public_transport_graph(
    "feed.zip",
    service_date="2026-08-04",
    start_time="07:00:00",
    end_time="10:00:00",
)

The source can be a GTFS directory, a ZIP archive, or a list of feeds to merge. See the GTFS guide for schedule aggregation, geometry fallbacks, single-departure handling and intermodal joining.

Compute an OD matrix

from iduedu import od_matrix

nodes = graph.nodes_gdf.index.to_list()

matrix = od_matrix(
    graph,
    origins_nodes=nodes[:5],
    destination_nodes=nodes[5:15],
    weight="time_min",
    cutoff=30,
)

print(matrix)

Use weight="time_min" for travel time in minutes or weight="length_meter" for distance in meters. Pairs without a path, or outside cutoff, are returned as inf; threshold remains a compatible alias.

To calculate distances and routes together, use output="both". Lazy storage reconstructs individual routes without rerunning Dijkstra:

result = graph.od_matrix(
    origins_nodes=nodes[:5],
    destination_nodes=nodes[5:15],
    cutoff=30,  # inclusive; threshold remains a compatible alias
    output="both",
    path_storage="lazy",
)
distances = result.distances
path = result.get_path(nodes[0], nodes[5])  # node list, or None when unreachable
paths = result.paths  # materialize and cache all requested routes

Use output="paths" for routes alone, mode="pairwise" to match inputs by position, and iter_od_matrix to process origin rows in blocks. The general single_source_dijkstra, multi_source_dijkstra (nearest source), and dijkstra_parallel (independent source rows) helpers also support selecting distances, paths, or both. See the routing API for shapes, lazy storage, and memory limits.

Reconstruct a route

from iduedu import path_to_edges

paths = graph.single_source_dijkstra(
    nodes[0], target_nodes=[nodes[-1]], weight="time_min", output="paths",
)
path = paths.loc[nodes[-1]]
route = path_to_edges(graph, path or [])

print(route[["type", "length_meter", "time_min"]])

Path results contain node ids in travel order, or None when the destination cannot be reached. path_to_edges turns them into the traversed edges with their geometry, type and travel time, ready to plot. The specialised single_source_dijkstra_path helper remains available and returns [] for an unreachable target.

Work with graph components

from iduedu import largest_component, subgraph_by_nodes

component_nodes = largest_component(graph)
main_graph = subgraph_by_nodes(graph, component_nodes)

Public API

Common entry points are available directly from iduedu:

  • Builders: get_drive_graph, get_walk_graph, get_public_transport_graph, get_gtfs_public_transport_graph, get_intermodal_graph, join_pt_walk_graph, get_4326_boundary.
  • GTFS: merge_gtfs_feeds; read_gtfs_feed, validate_gtfs_feed and GTFSFeed live in iduedu.gtfs.
  • Transport modes: TransportSpec, TransportRegistry, DEFAULT_REGISTRY, DEFAULT_REGISTRY_W_TRAIN.
  • Graph model: UrbanGraph, UrbanGraphChanges.
  • Editing and transforms: clip_urban_graph, join_urban_graphs, project_objects2urban_graph, apply_urban_graph_changes, subgraph_by_nodes, relabel_urban_graph, simplify_multiedges, to_directed, to_undirected.
  • Graph utilities: nearest_nodes, validate_graph, UrbanGraph.nearest_nodes, UrbanGraph.validate.
  • Graph IO: read_urban_graph, write_urban_graph, UrbanGraph.read, UrbanGraph.write.
  • Components: connected_components, weakly_connected_components, strongly_connected_components, largest_component.
  • Shortest paths and matrices: single_source_dijkstra, multi_source_dijkstra, dijkstra_parallel, ShortestPathResult, iter_od_matrix, single_source_dijkstra_path, multi_source_dijkstra_path, path_to_edges, single_source_dijkstra_path_length, multi_source_dijkstra_path_length, multi_source_dijkstra_nearest_source, dijkstra_path_length_parallel, od_matrix.
  • Optional NetworkX helpers (install networkx separately): urban_graph2nx_graph, nx_graph2urban_graph, graph2gdf, gdf2graph, read_gml, write_gml, clip_nx_graph, reproject_graph.

Configuration

IduEdu reads its settings from the global config object, and most of them also from environment variables. Use it to point requests at another Overpass instance, pace them, cache responses, query a historical OSM snapshot, choose the OSM tags kept on edges, or set up logging:

from iduedu import config

config.set_overpass_url("https://overpass-api.de/api/interpreter")
config.set_rate_limit(min_interval=2.0, max_retries=5)
config.set_overpass_cache(cache_dir=".iduedu_cache", enabled=True)
config.set_overpass_date(date="2020-01-01")  # query OSM as it stood on this date
config.configure_logging(level="INFO")

See the configuration guide for every setting and its environment variable.

Development

This project uses uv.

uv sync --all-groups

Useful commands:

make test           # fast tests, no network
make test-network   # Overpass/network tests
make test-all       # all tests
make coverage       # terminal coverage for fast tests
make coverage-xml   # CI coverage, includes network tests
make format-check
make lint
make docs

See CONTRIBUTING.md for the full development, testing, Conventional Commits and release workflow.

Releases

Releases are automated from Conventional Commit messages on the official IDUclub/IduEdu main branch using python-semantic-release. Do not bump versions or create tags manually. The single source of truth for the package version is iduedu/_version.py; pyproject.toml reads it dynamically at build time.

Contacts

Acknowledgments

Реализовано при финансовой поддержке Фонда поддержки проектов Национальной технологической инициативы в рамках реализации "дорожной карты" развития высокотехнологичного направления "Искусственный интеллект" на период до 2030 года (Договор № 70-2021-00187)

This research is financially supported by the Foundation for National Technology Initiative's Projects Support as a part of the roadmap implementation for the development of the high-tech field of Artificial Intelligence for the period up to 2030 (agreement 70-2021-00187)


License

IduEdu is distributed under the BSD 3-Clause License. See LICENSE.txt for details.


Citing IduEdu

If you use IduEdu in research, please cite it. Citation metadata is kept in CITATION.cff; on GitHub, Cite this repository in the repository sidebar copies it as APA or BibTeX. Publications describing IduEdu will be listed below.

Publications

Coming soon...

Metadata

Release files for iduedu 2.3.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 iduedu 2.3.0
File Size Uploaded Provenance
iduedu-2.3.0.tar.gz 132.2 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for iduedu 2.3.0
File Interpreter ABI Platform
iduedu-2.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 284.7 kB

Release files / iduedu-2.3.0.tar.gz

Download URL iduedu-2.3.0.tar.gz
Size 132.2 kB
Tags Source
SHA-256 checksum
How to use checksums
98681fbd6a0b4f5e87a0e1ec2ddb1584e444d8b0c6821a133a176d531eca1e8b
BLAKE2b-256 checksum
How to use checksums
ab59623129648c6cb469fe2a1979455de0cbfdf4d53e064af720f3f84e7fd77e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Release files / iduedu-2.3.0-py3-none-any.whl

Download URL iduedu-2.3.0-py3-none-any.whl
Size 152.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5b20c57f50a1d639f2a306e0a50ecde2f6b3dd547b13f530c3fdb33fbf383601
BLAKE2b-256 checksum
How to use checksums
657ed86a8b6a081901a7ae79f61c0547e163d8bc95649bbd38bc18e090bacb6e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Security for iduedu 2.3.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for iduedu-2.3.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

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.

Release history Release notifications | RSS feed

This release

2.3.0 This release

2 release files Full provenance

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