Note
Go to the end to download the full example code.
Matching with an AequilibraE Model#
import uuid
from os.path import join
from tempfile import gettempdir
from aequilibrae.utils.create_example import create_example
from mapmatcher import MapMatcher
from mapmatcher.examples import nauru_data
nauru_gps = nauru_data()
# Let's see if the data has all the fields we need
nauru_gps.head()
Since it does not, let’s fix it
nauru_gps.rename(columns={"x": "longitude", "y": "latitude", "vehicle_unique_id": "trace_id"}, inplace=True)
We get our AequilibraE model for Nauru and create the map-mather from this model We also need to provide the transportation mode we want to consider for the map-matching
project = create_example(join(gettempdir(), uuid.uuid4().hex), "nauru")
# We need to have at least one centroid connector to the model due to a bug in AequilibraE 0.9.5
with project.db_connection as conn:
conn.execute("Update Nodes set is_centroid=1 where node_id = 1")
mmatcher = MapMatcher.from_aequilibrae(project, "c")
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/aequilibrae/paths/graph.py:248: UserWarning: Found centroids not present in the graph!
[1]
warnings.warn("Found centroids not present in the graph!\n" + str(centroids[~present_centroids]))
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/aequilibrae/paths/graph.py:248: UserWarning: Found centroids not present in the graph!
[1]
warnings.warn("Found centroids not present in the graph!\n" + str(centroids[~present_centroids]))
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/aequilibrae/paths/graph.py:248: UserWarning: Found centroids not present in the graph!
[1]
warnings.warn("Found centroids not present in the graph!\n" + str(centroids[~present_centroids]))
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/aequilibrae/paths/graph.py:248: UserWarning: Found centroids not present in the graph!
[1]
warnings.warn("Found centroids not present in the graph!\n" + str(centroids[~present_centroids]))
let’s add the GPS data to the map-matcher and run it!
mmatcher.load_gps_traces(nauru_gps)
mmatcher.map_match(parallel_threads=1)
building trips: 0%| | 0/100 [00:00<?, ?it/s]
building trips: 5%|▌ | 5/100 [00:00<00:02, 41.43it/s]
building trips: 11%|█ | 11/100 [00:00<00:01, 47.33it/s]
building trips: 16%|█▌ | 16/100 [00:00<00:01, 47.36it/s]
building trips: 22%|██▏ | 22/100 [00:00<00:01, 48.19it/s]
building trips: 27%|██▋ | 27/100 [00:00<00:01, 47.96it/s]
building trips: 32%|███▏ | 32/100 [00:00<00:01, 45.72it/s]
building trips: 37%|███▋ | 37/100 [00:00<00:01, 46.15it/s]
building trips: 42%|████▏ | 42/100 [00:00<00:01, 45.95it/s]
building trips: 47%|████▋ | 47/100 [00:01<00:01, 45.67it/s]
building trips: 52%|█████▏ | 52/100 [00:01<00:01, 44.34it/s]
building trips: 57%|█████▋ | 57/100 [00:01<00:00, 44.19it/s]
building trips: 62%|██████▏ | 62/100 [00:01<00:00, 45.20it/s]
building trips: 68%|██████▊ | 68/100 [00:01<00:00, 46.29it/s]
building trips: 73%|███████▎ | 73/100 [00:01<00:00, 46.70it/s]
building trips: 78%|███████▊ | 78/100 [00:01<00:00, 45.86it/s]
building trips: 83%|████████▎ | 83/100 [00:01<00:00, 45.94it/s]
building trips: 88%|████████▊ | 88/100 [00:01<00:00, 44.67it/s]
building trips: 93%|█████████▎| 93/100 [00:02<00:00, 44.93it/s]
building trips: 98%|█████████▊| 98/100 [00:02<00:00, 44.61it/s]
building trips: 100%|██████████| 100/100 [00:02<00:00, 45.51it/s]
Map matching trips: 0%| | 0/100 [00:00<?, ?it/s]
Map matching trips: 6%|▌ | 6/100 [00:00<00:04, 19.22it/s]
Map matching trips: 11%|█ | 11/100 [00:00<00:04, 18.93it/s]
Map matching trips: 13%|█▎ | 13/100 [00:00<00:06, 13.24it/s]
Map matching trips: 15%|█▌ | 15/100 [00:01<00:07, 11.11it/s]
Map matching trips: 18%|█▊ | 18/100 [00:01<00:08, 9.93it/s]
Map matching trips: 20%|██ | 20/100 [00:01<00:10, 7.28it/s]
Map matching trips: 25%|██▌ | 25/100 [00:02<00:08, 8.60it/s]
Map matching trips: 33%|███▎ | 33/100 [00:02<00:05, 12.12it/s]
Map matching trips: 36%|███▌ | 36/100 [00:03<00:06, 9.69it/s]
Map matching trips: 39%|███▉ | 39/100 [00:03<00:06, 9.94it/s]
Map matching trips: 42%|████▏ | 42/100 [00:04<00:06, 9.24it/s]
Map matching trips: 45%|████▌ | 45/100 [00:04<00:06, 8.16it/s]
Map matching trips: 53%|█████▎ | 53/100 [00:04<00:03, 12.02it/s]
Map matching trips: 62%|██████▏ | 62/100 [00:05<00:02, 14.87it/s]
Map matching trips: 64%|██████▍ | 64/100 [00:05<00:02, 13.73it/s]
Map matching trips: 66%|██████▌ | 66/100 [00:06<00:03, 10.18it/s]
Map matching trips: 69%|██████▉ | 69/100 [00:06<00:03, 9.66it/s]
Map matching trips: 70%|███████ | 70/100 [00:06<00:04, 7.26it/s]
Map matching trips: 73%|███████▎ | 73/100 [00:07<00:03, 7.51it/s]
Map matching trips: 76%|███████▌ | 76/100 [00:07<00:03, 7.59it/s]
Map matching trips: 79%|███████▉ | 79/100 [00:07<00:02, 8.33it/s]
Map matching trips: 80%|████████ | 80/100 [00:08<00:02, 7.20it/s]
Map matching trips: 93%|█████████▎| 93/100 [00:08<00:00, 15.15it/s]
Map matching trips: 95%|█████████▌| 95/100 [00:08<00:00, 12.91it/s]
Map matching trips: 100%|██████████| 100/100 [00:08<00:00, 11.23it/s]
for trip in mmatcher.trips:
if trip.success:
break
import folium
import geopandas as gpd
import numpy as np
Create a geometry list from the GeoDataFrame
trace = trip.trace.to_crs(4326)
geo_df_list = [[point.xy[1][0], point.xy[0][0], ts] for point, ts in zip(trace.geometry, trace.timestamp)]
result_layer = folium.FeatureGroup("Map-match result")
trace_layer = folium.FeatureGroup("GPS traces")
# Iterate through list and add a marker for each GPS ping.
i = 0
for lat, lng, ts in geo_df_list:
trace_layer.add_child(
folium.CircleMarker(
location=[lat, lng],
radius=1,
fill=True, # Set fill to True
color="black",
tooltip=str(ts),
fill_opacity=1.0,
)
)
gdf = gpd.GeoDataFrame({"d": [1]}, geometry=[trip.path_shape], crs=3857).to_crs(4326).explode(ignore_index=True)
for _, rec in gdf.iterrows():
coords = rec.geometry.xy
coordinates = [[y, x] for x, y in zip(coords[0], coords[1])]
folium.PolyLine(coordinates, weight=5, color="red").add_to(result_layer)
map = folium.Map(location=[np.mean(coords[1]), np.mean(coords[0])], tiles="OpenStreetMap", zoom_start=15)
result_layer.add_to(map)
trace_layer.add_to(map)
folium.LayerControl(position="bottomright").add_to(map)
map
trip.result
Total running time of the script: (0 minutes 11.729 seconds)