Network
Road/rail-network-constrained distance: build a routable graph from Overture Maps transportation data, snap trajectory points to it, and query network (not straight-line) distance via a Rust contraction-hierarchy router.
Build a network
| API | Description | Example |
|---|---|---|
fetch_road_network |
Fetch and build a car-routable graph from Overture road segments. | Trajectory and road network |
build_road_graph |
Load a saved road graph from disk, or fetch it from Overture Maps and save it. | Trajectory and road network |
fetch_rail_network |
Fetch rail segments from Overture Maps and build a bidirectional rail graph. | Rail network |
build_rail_graph |
Load a saved rail graph from disk, or fetch it from Overture Maps and save it. | Rail network |
RoadNetwork |
A road (or rail) network prepared once (contraction hierarchy) and reused for many point-to-point physical-distance queries. | Distances and routes on the network |
RoadNetwork.batch_distances |
Batch route-length (metres) query for (from_node, to_node) pairs. |
Distances and routes on the network |
RoadNetwork.batch_routes |
Batch route-geometry query for (from_node, to_node) pairs. |
Distances and routes on the network |
RoadNetwork.build |
Prepare a contraction hierarchy from a road/rail graph's edges. | Trajectory and road network |
Snap, route and match
| API | Description | Example |
|---|---|---|
snap_locations_to_graph |
Snap each tessellation row to its nearest road/rail graph node. | Snap points to the network |
haversine_m_batch |
Compute distances in metres; prefer fastmob.utils.haversine. |
|
match_trajectory |
Map-match a trajectory with a directed-edge HMM/Viterbi model. | Match a GPS trace to roads |
od_desire_lines |
Aggregate OD-pair flows onto the road/rail graph's edges (desire lines). | Accumulate flows on roads |
Measures along the road network
| API | Description | Example |
|---|---|---|
jump_lengths_road |
Jump lengths (km) measured along the road network. | Road distance versus straight line |
radius_of_gyration_road |
Radius of gyration (km) per user, measured along the road network. | Road distance versus straight line |
fetch_road_network and fetch_rail_network require DuckDB: install it with
pip install duckdb. Snapping uses Fastkit-Mobility's native Rust spatial index and
has no additional Python dependency.
For a worked walk-through (build a network, snap points, compare road and
straight-line distances, accumulate flows, match a GPS trace) see
Road networks: matching, routing and route flows and the concept
page Roads, rails and map matching. Node ids passed to the
distance, route and desire-line functions come from snap_locations_to_graph;
an unsnapped node is -1.
fetch_road_network(min_lon, min_lat, max_lon, max_lat, overture_release)
Fetch and build a car-routable graph from Overture road segments.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_lon
|
float
|
Western edge of the bounding box, in decimal degrees. |
required |
min_lat
|
float
|
Southern edge of the bounding box, in decimal degrees. |
required |
max_lon
|
float
|
Eastern edge of the bounding box, in decimal degrees. |
required |
max_lat
|
float
|
Northern edge of the bounding box, in decimal degrees. |
required |
overture_release
|
str
|
Overture Maps release to read, as listed in the public bucket, for
example |
required |
Returns:
| Type | Description |
|---|---|
nodes_df
|
|
edges_df
|
|
Worked example: Trajectory and road network
build_road_graph(min_lon, min_lat, max_lon, max_lat, overture_release, nodes_output, edges_output)
Load a saved road graph from disk, or fetch it from Overture Maps and save it.
If both nodes_output and edges_output exist they are read (no download); otherwise the network is
fetched with fetch_road_network and written there as Parquet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_lon
|
float
|
Bounding box in degrees (WGS 84). |
required |
min_lat
|
float
|
Bounding box in degrees (WGS 84). |
required |
max_lon
|
float
|
Bounding box in degrees (WGS 84). |
required |
max_lat
|
float
|
Bounding box in degrees (WGS 84). |
required |
overture_release
|
str
|
Overture Maps release id, for example |
required |
nodes_output
|
str
|
Paths of the Parquet files for the graph nodes and edges. |
required |
edges_output
|
str
|
Paths of the Parquet files for the graph nodes and edges. |
required |
Returns:
| Type | Description |
|---|---|
(nodes, edges) : tuple of pyarrow.Table
|
As returned by |
Worked example: Trajectory and road network
fetch_rail_network(min_lon, min_lat, max_lon, max_lat, overture_release, classes=None, speed_kmh_by_class=None, default_speed_kmh=35.0)
Fetch rail segments from Overture Maps and build a bidirectional rail graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_lon
|
float
|
Bounding box in degrees (WGS 84). |
required |
min_lat
|
float
|
Bounding box in degrees (WGS 84). |
required |
max_lon
|
float
|
Bounding box in degrees (WGS 84). |
required |
max_lat
|
float
|
Bounding box in degrees (WGS 84). |
required |
overture_release
|
str
|
Overture Maps release id, for example |
required |
classes
|
list of str
|
Overture rail classes to keep (default: light rail, standard gauge, subway and tram). |
None
|
speed_kmh_by_class
|
dict
|
Speed in km/h for each class, used to compute travel times. |
None
|
default_speed_kmh
|
float
|
Speed for a class not in |
35.0
|
Returns:
| Type | Description |
|---|---|
(nodes, edges) : tuple of pyarrow.Table
|
Same columns as |
Worked example: Rail network
build_rail_graph(min_lon, min_lat, max_lon, max_lat, overture_release, nodes_output, edges_output, classes=None, speed_kmh_by_class=None, default_speed_kmh=35.0)
Load a saved rail graph from disk, or fetch it from Overture Maps and save it.
Arguments are those of fetch_rail_network plus the two output paths. If both files exist they are read
(no download); otherwise the graph is fetched and written there as Parquet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_lon
|
float
|
Bounding box in degrees (WGS 84). |
required |
min_lat
|
float
|
Bounding box in degrees (WGS 84). |
required |
max_lon
|
float
|
Bounding box in degrees (WGS 84). |
required |
max_lat
|
float
|
Bounding box in degrees (WGS 84). |
required |
overture_release
|
str
|
Overture Maps release id, for example |
required |
nodes_output
|
str
|
Paths of the Parquet files for the graph nodes and edges. |
required |
edges_output
|
str
|
Paths of the Parquet files for the graph nodes and edges. |
required |
classes
|
optional
|
As in |
None
|
speed_kmh_by_class
|
optional
|
As in |
None
|
default_speed_kmh
|
optional
|
As in |
35.0
|
Returns:
| Type | Description |
|---|---|
(nodes, edges) : tuple of pyarrow.Table
|
As returned by |
Worked example: Rail network
RoadNetwork
A road (or rail) network prepared once (contraction hierarchy) and reused for many point-to-point physical-distance queries.
Bundles the snap-target nodes together with the routing handle (unlike
a split handle + separate nodes_df pair), since a caller always
needs both to go from raw lat/lng to a routed distance.
batch_distances(from_nodes, to_nodes)
Batch route-length (metres) query for (from_node, to_node) pairs.
The route is the fastest one (minimum travel time at the edge speeds), so the distance is the length of that route, which is not always the shortest possible distance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
from_nodes
|
array-like of int
|
Node indexes ( |
required |
to_nodes
|
array-like of int
|
Node indexes of the destinations, one per origin. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
distances_m |
Array
|
Route length in metres for each pair. |
connected |
Array
|
Boolean array. |
batch_routes(from_nodes, to_nodes, max_waypoints=50)
Batch route-geometry query for (from_node, to_node) pairs.
Returns a flat pyarrow.Table with one row per waypoint: columns
query_id (0-based index into from_nodes/to_nodes), lat,
lng, cum_weight_ds (cumulative travel-time weight from the
route's start), following the same flat-output + boundary convention
used by other variable-rows-per-group measures in this library
(rather than one Python object per query). A query with connected
== False (unsnapped/disconnected) contributes zero rows; join back
on query_id against a connected array from batch_distances
if you need to distinguish "no route" from "route with no
waypoints" (the latter cannot happen: every connected route has at
least its two endpoints).
Waypoints are decimated to at most max_waypoints per query
(always keeping the first and last), so a caller wanting the full,
undecimated node path should pass a large max_waypoints.
build(edges_df, nodes_df)
classmethod
Prepare a contraction hierarchy from a road/rail graph's edges.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
edges_df
|
Columns |
required | |
nodes_df
|
Columns |
required |
Worked example: Distances and routes on the network ยท Trajectory and road network
snap_locations_to_graph(tessellation_df, nodes_df, max_distance_m, lat_col='lat', lng_col='lng')
Snap each tessellation row to its nearest road/rail graph node.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tessellation_df
|
Rows with lat/lng columns to snap. |
required | |
nodes_df
|
Graph nodes with columns |
required | |
max_distance_m
|
float
|
Maximum snap distance; farther rows are reported unsnapped. |
required |
lat_col
|
str
|
Column names on |
'lat'
|
lng_col
|
str
|
Column names on |
'lng'
|
Returns:
| Type | Description |
|---|---|
Int64Array
|
int64 array aligned 1:1 with |
Worked example: Snap points to the network
haversine_m_batch(lat1, lng1, lat2, lng2)
Compute distances in metres; prefer fastmob.utils.haversine.
match_trajectory(traj, *, network, uid_col=None, datetime_col=None, lat_col=None, lng_col=None, candidate_radius_m=75.0, max_candidates=8, gps_sigma_m=20.0, gap_seconds=1800.0, max_transition_speed_kmh=180.0)
Map-match a trajectory with a directed-edge HMM/Viterbi model.
Chooses, for every GPS fix, the most likely road segment given the fix's distance to nearby segments and the route needed to travel between consecutive fixes. Results are Arrow-native and preserve input row order. Independent users are matched concurrently; one user's fixes are matched in sequence, and the sequence restarts after a time gap or an impossible move.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
DataFrame
|
Trajectory table (any eager dataframe) with latitude, longitude and datetime columns, and optionally a user column. |
required |
network
|
RoadNetwork
|
A prepared road network (see |
required |
uid_col
|
str
|
Column name; auto-detected when |
None
|
datetime_col
|
str
|
Column name; auto-detected when |
None
|
lat_col
|
str
|
Column name; auto-detected when |
None
|
lng_col
|
str
|
Column name; auto-detected when |
None
|
candidate_radius_m
|
float
|
Segments within this distance (metres) of a fix are candidates. Default 75. |
75.0
|
max_candidates
|
int
|
Most candidate segments kept per fix, nearest first. Default 8. |
8
|
gps_sigma_m
|
float
|
Assumed standard deviation of the GPS error, in metres: larger values trust the fix less and the route more. Default 20. |
20.0
|
gap_seconds
|
float
|
A time gap longer than this between consecutive fixes starts a new sequence. Default 1800 (30 minutes). |
1800.0
|
max_transition_speed_kmh
|
float
|
A move that would need a higher speed than this between consecutive fixes is not allowed. Default 180. |
180.0
|
Returns:
| Type | Description |
|---|---|
Table
|
The input columns plus |
Worked example: Match a GPS trace to roads
od_desire_lines(road_network, from_nodes, to_nodes, flows)
Aggregate OD-pair flows onto the road/rail graph's edges (desire lines).
The Overture-native analogue of stplanr's overline/overline2:
for each (from_node, to_node, flow) triple, walks the time-optimal
route between the two nodes and adds flow to every edge it crosses,
so many overlapping OD pairs accumulate onto shared road segments
instead of remaining one separate desire line per pair.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
road_network
|
A prepared network (see |
required | |
from_nodes
|
ndarray
|
Node ids per OD pair; a negative value marks an unsnapped origin or destination. |
required |
to_nodes
|
ndarray
|
Node ids per OD pair; a negative value marks an unsnapped origin or destination. |
required |
flows
|
Flow volume (e.g. trip count) per OD pair. |
required |
Returns:
| Type | Description |
|---|---|
(edges_df, dropped_flow)
|
|
Worked example: Accumulate flows on roads
jump_lengths_road(traj, *, network, uid_col=None, lat_col=None, lng_col=None, datetime_col=None, snap_max_distance_m=750.0)
Jump lengths (km) measured along the road network.
As in jump_lengths, a jump is the distance between consecutive fixes of the
same user, ordered by datetime, and zero-length jumps are kept. Here the
distance is the length of the fastest route on network instead of the
straight line, and a jump falls back to the straight-line (Haversine) distance
when a fix is not snapped to the network or the two fixes are not connected.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
Any
|
Trajectory dataframe; any Narwhals-compatible eager backend. |
required |
network
|
RoadNetwork
|
A prepared |
required |
uid_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
lat_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
lng_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
datetime_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
snap_max_distance_m
|
float
|
Maximum distance (metres) to snap a stop to the network; farther stops fall back to Haversine entirely for any jump touching them. |
750.0
|
Returns:
| Type | Description |
|---|---|
ndarray
|
One value per consecutive same-user pair (length: |
Worked example: Road distance versus straight line
radius_of_gyration_road(traj, *, network, uid_col=None, lat_col=None, lng_col=None, snap_max_distance_m=750.0)
Radius of gyration (km) per user, measured along the road network.
The root-mean-square distance from each of a user's fixes to the arithmetic-mean
centroid of their fixes, r_g(u) = sqrt(mean(d(r_i, r_cm)^2)) as in
radius_of_gyration, with d the length of the fastest route on network
instead of the straight line.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
traj
|
Any
|
Trajectory dataframe; any Narwhals-compatible eager backend. |
required |
network
|
RoadNetwork
|
A prepared |
required |
uid_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
lat_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
lng_col
|
str | None
|
Explicit column name overrides; auto-detected when None. |
None
|
snap_max_distance_m
|
float
|
Maximum distance (metres) to snap a stop to the network. |
750.0
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
|
Worked example: Road distance versus straight line