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()
x y timestamp gps_fix_id vehicle_unique_id geometry
0 166.942502 -0.546496 2018-05-09 18:13:56 1 2 POINT (166.9425 -0.5465)
1 166.943424 -0.546774 2018-05-09 18:14:05 2 2 POINT (166.94342 -0.54677)
2 166.943201 -0.547001 2018-05-09 18:14:08 3 2 POINT (166.9432 -0.547)
3 166.940958 -0.549704 2018-05-09 18:14:39 4 2 POINT (166.94096 -0.5497)
4 166.940674 -0.550305 2018-05-09 18:14:45 5 2 POINT (166.94067 -0.5503)


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
project.conn.execute("Update Nodes set is_centroid=1 where node_id = 1")
mmatcher = MapMatcher.from_aequilibrae(project, "c")

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:   4%|▍         | 4/100 [00:00<00:02, 39.07it/s]
building trips:   9%|▉         | 9/100 [00:00<00:02, 44.04it/s]
building trips:  14%|█▍        | 14/100 [00:00<00:01, 45.58it/s]
building trips:  19%|█▉        | 19/100 [00:00<00:01, 44.74it/s]
building trips:  24%|██▍       | 24/100 [00:00<00:01, 44.28it/s]
building trips:  29%|██▉       | 29/100 [00:00<00:01, 44.42it/s]
building trips:  34%|███▍      | 34/100 [00:00<00:01, 43.69it/s]
building trips:  39%|███▉      | 39/100 [00:00<00:01, 42.84it/s]
building trips:  44%|████▍     | 44/100 [00:01<00:01, 42.48it/s]
building trips:  49%|████▉     | 49/100 [00:01<00:01, 42.11it/s]
building trips:  54%|█████▍    | 54/100 [00:01<00:01, 41.71it/s]
building trips:  59%|█████▉    | 59/100 [00:01<00:00, 42.09it/s]
building trips:  64%|██████▍   | 64/100 [00:01<00:00, 42.34it/s]
building trips:  69%|██████▉   | 69/100 [00:01<00:00, 43.64it/s]
building trips:  74%|███████▍  | 74/100 [00:01<00:00, 42.94it/s]
building trips:  79%|███████▉  | 79/100 [00:01<00:00, 42.87it/s]
building trips:  84%|████████▍ | 84/100 [00:01<00:00, 42.43it/s]
building trips:  89%|████████▉ | 89/100 [00:02<00:00, 41.67it/s]
building trips:  94%|█████████▍| 94/100 [00:02<00:00, 42.73it/s]
building trips:  99%|█████████▉| 99/100 [00:02<00:00, 41.51it/s]
building trips: 100%|██████████| 100/100 [00:02<00:00, 42.63it/s]

Map matching trips:   0%|          | 0/100 [00:00<?, ?it/s]
Map matching trips:   6%|▌         | 6/100 [00:00<00:05, 17.98it/s]
Map matching trips:  11%|█         | 11/100 [00:00<00:05, 17.56it/s]
Map matching trips:  13%|█▎        | 13/100 [00:00<00:07, 12.37it/s]
Map matching trips:  15%|█▌        | 15/100 [00:01<00:08, 10.48it/s]
Map matching trips:  18%|█▊        | 18/100 [00:01<00:08,  9.30it/s]
Map matching trips:  19%|█▉        | 19/100 [00:01<00:10,  8.09it/s]
Map matching trips:  20%|██        | 20/100 [00:02<00:13,  5.99it/s]
Map matching trips:  25%|██▌       | 25/100 [00:02<00:09,  7.55it/s]
Map matching trips:  33%|███▎      | 33/100 [00:03<00:06, 11.12it/s]
Map matching trips:  36%|███▌      | 36/100 [00:03<00:07,  8.66it/s]
Map matching trips:  39%|███▉      | 39/100 [00:04<00:06,  8.96it/s]
Map matching trips:  42%|████▏     | 42/100 [00:04<00:06,  8.38it/s]
Map matching trips:  45%|████▌     | 45/100 [00:05<00:07,  7.40it/s]
Map matching trips:  53%|█████▎    | 53/100 [00:05<00:04, 11.05it/s]
Map matching trips:  62%|██████▏   | 62/100 [00:05<00:02, 13.69it/s]
Map matching trips:  64%|██████▍   | 64/100 [00:06<00:02, 12.69it/s]
Map matching trips:  66%|██████▌   | 66/100 [00:06<00:03,  9.19it/s]
Map matching trips:  69%|██████▉   | 69/100 [00:07<00:03,  8.86it/s]
Map matching trips:  70%|███████   | 70/100 [00:07<00:04,  6.63it/s]
Map matching trips:  73%|███████▎  | 73/100 [00:07<00:03,  6.80it/s]
Map matching trips:  76%|███████▌  | 76/100 [00:08<00:03,  6.77it/s]
Map matching trips:  79%|███████▉  | 79/100 [00:08<00:02,  7.49it/s]
Map matching trips:  80%|████████  | 80/100 [00:08<00:03,  6.47it/s]
Map matching trips:  93%|█████████▎| 93/100 [00:09<00:00, 13.34it/s]
Map matching trips:  95%|█████████▌| 95/100 [00:09<00:00, 11.51it/s]
Map matching trips: 100%|██████████| 100/100 [00:09<00:00, 10.15it/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
Make this Notebook Trusted to load map: File -> Trust Notebook


trip.result
links direction milepost geometry
0 1228 -1 1124.584887 LINESTRING (166.92574 -0.51213, 166.92589 -0.5...
1 910 1 1175.350264 LINESTRING (166.92574 -0.51213, 166.92542 -0.5...
2 911 1 1194.939370 LINESTRING (166.92542 -0.51246, 166.9253 -0.51...
3 912 1 1201.665519 LINESTRING (166.9253 -0.51258, 166.92488 -0.51...
4 1240 1 1208.386598 LINESTRING (166.92488 -0.51302, 166.92511 -0.5...
5 1240 -1 1215.107678 LINESTRING (166.92488 -0.51302, 166.92511 -0.5...
6 913 1 1276.267386 LINESTRING (166.92488 -0.51302, 166.92451 -0.5...
7 914 1 1290.152053 LINESTRING (166.92451 -0.51343, 166.92443 -0.5...
8 915 1 1292.893482 LINESTRING (166.92443 -0.51353, 166.92426 -0.5...
9 916 1 1344.025141 LINESTRING (166.92426 -0.5137, 166.92394 -0.51...
10 917 1 1416.300787 LINESTRING (166.92394 -0.51404, 166.9235 -0.51...
11 918 1 1423.168806 LINESTRING (166.9235 -0.51452, 166.92308 -0.51...
12 919 1 1437.002929 LINESTRING (166.92308 -0.51497, 166.92299 -0.5...
13 920 1 1452.636599 LINESTRING (166.92299 -0.51507, 166.9229 -0.51...
14 921 1 1488.030956 LINESTRING (166.9229 -0.51517, 166.92268 -0.51...
15 922 1 1523.208037 LINESTRING (166.92268 -0.51541, 166.9225 -0.51...
16 923 1 1568.370584 LINESTRING (166.9225 -0.51567, 166.92231 -0.51...
17 924 1 1599.011011 LINESTRING (166.92231 -0.51603, 166.92218 -0.5...
18 925 1 1601.218148 LINESTRING (166.92218 -0.51627, 166.92206 -0.5...
19 926 1 1638.344782 LINESTRING (166.92206 -0.51643, 166.92183 -0.5...
20 927 1 1671.654432 LINESTRING (166.92183 -0.51667, 166.9216 -0.51...
21 1116 -1 1682.671559 LINESTRING (166.92088 -0.51726, 166.92091 -0.5...
22 1226 -1 1693.861510 LINESTRING (166.9206 -0.51753, 166.92047 -0.51...
23 931 1 1706.166402 LINESTRING (166.9206 -0.51753, 166.9205 -0.51758)
24 932 1 1755.165865 LINESTRING (166.9205 -0.51758, 166.92014 -0.51...
25 933 1 1768.063688 LINESTRING (166.92014 -0.51784, 166.91926 -0.5...
26 934 1 1775.853776 LINESTRING (166.91926 -0.51859, 166.91878 -0.5...
27 935 1 1779.828479 LINESTRING (166.91878 -0.5191, 166.91854 -0.51...
28 936 1 1800.035146 LINESTRING (166.91854 -0.51937, 166.91842 -0.5...
29 937 1 1820.835860 LINESTRING (166.91842 -0.5195, 166.91828 -0.51...
30 938 1 1828.613960 LINESTRING (166.91828 -0.51963, 166.9177 -0.52...
31 939 1 1906.245998 LINESTRING (166.9177 -0.52003, 166.91715 -0.52...
32 940 1 1964.071072 LINESTRING (166.91715 -0.52046, 166.91675 -0.5...
33 941 1 2047.465681 LINESTRING (166.91675 -0.5208, 166.91617 -0.52...
34 942 1 2054.335952 LINESTRING (166.91617 -0.52127, 166.9157 -0.52...
35 943 1 2061.268315 LINESTRING (166.9157 -0.52167, 166.91565 -0.52...
36 944 1 2116.540548 LINESTRING (166.91565 -0.52171, 166.91527 -0.5...
37 945 1 2144.694510 LINESTRING (166.91527 -0.52203, 166.91507 -0.5...
38 946 1 2172.066185 LINESTRING (166.91507 -0.52219, 166.9149 -0.52...
39 947 1 2199.383492 LINESTRING (166.9149 -0.52237, 166.91476 -0.52...
40 948 1 2202.123860 LINESTRING (166.91476 -0.52257, 166.91464 -0.5...
41 949 1 2205.246512 LINESTRING (166.91464 -0.52279, 166.91454 -0.5...
42 950 1 2236.437781 LINESTRING (166.91454 -0.52305, 166.91443 -0.5...
43 951 1 2239.368459 LINESTRING (166.91443 -0.52331, 166.91438 -0.5...


Total running time of the script: (0 minutes 12.636 seconds)

Gallery generated by Sphinx-Gallery