Note
Go to the end to download the full example code.
Import GTFS#
In this example, we import a GTFS feed to our model and perform map matching.
We use data from Coquimbo, a city in La Serena Metropolitan Area in Chile.
See also
Several functions, methods, classes and modules are used in this example:
# Imports
from uuid import uuid4
from os import remove
from os.path import join
from tempfile import gettempdir
import folium
import geopandas as gpd
import pandas as pd
from aequilibrae.project.database_connection import database_connection
from aequilibrae.transit import Transit
from aequilibrae.utils.create_example import create_example
# Let's create an empty project on an arbitrary folder.
fldr = join(gettempdir(), uuid4().hex)
project = create_example(fldr, "coquimbo")
As the Coquimbo example already has a complete GTFS model, we shall remove its public transport database for the sake of this example.
remove(join(fldr, "public_transport.sqlite"))
Let’s import the GTFS feed.
dest_path = join(fldr, "gtfs_coquimbo.zip")
Now we create our Transit object and import the GTFS feed into our model. This will automatically create a new public transport database.
data = Transit(project)
transit = data.new_gtfs_builder(agency="Lisanco", file_path=dest_path)
To load the data, we must choose one date. We’re going to continue with 2016-04-13 but feel free to experiment with any other available dates. Transit class has a function allowing you to check dates for the GTFS feed. It should take approximately 2 minutes to load the data.
transit.load_date("2016-04-13")
# Now we execute the map matching to find the real paths.
# Depending on the GTFS size, this process can be really time-consuming.
# transit.set_allow_map_match(True)
# transit.map_match()
# Finally, we save our GTFS into our model.
transit.save_to_disk()
Loading routes (Step: 1/12) : 0it [00:00, ?it/s]
Loading stops (Step: 2/12) : 0%| | 0/78 [00:00<?, ?it/s]
Loading stop times (Step: 3/12) : 0%| | 0/1007 [00:00<?, ?it/s]
Loading shapes (Step: 4/12) : 0%| | 0/2 [00:00<?, ?it/s]
Loading trips (Step: 5/12) : 0%| | 0/1007 [00:00<?, ?it/s]
Loading trips (Step: 5/12) : 4%|▎ | 37/1007 [00:00<00:02, 364.21it/s]
Loading trips (Step: 5/12) : 7%|▋ | 74/1007 [00:00<00:03, 240.55it/s]
Loading trips (Step: 5/12) : 11%|█ | 110/1007 [00:00<00:03, 281.65it/s]
Loading trips (Step: 5/12) : 14%|█▍ | 146/1007 [00:00<00:02, 305.82it/s]
Loading trips (Step: 5/12) : 18%|█▊ | 181/1007 [00:00<00:02, 318.02it/s]
Loading trips (Step: 5/12) : 22%|██▏ | 217/1007 [00:00<00:02, 329.22it/s]
Loading trips (Step: 5/12) : 25%|██▌ | 253/1007 [00:00<00:02, 337.31it/s]
Loading trips (Step: 5/12) : 29%|██▊ | 289/1007 [00:00<00:02, 342.54it/s]
Loading trips (Step: 5/12) : 32%|███▏ | 325/1007 [00:01<00:01, 346.86it/s]
Loading trips (Step: 5/12) : 36%|███▌ | 361/1007 [00:01<00:01, 348.93it/s]
Loading trips (Step: 5/12) : 39%|███▉ | 397/1007 [00:01<00:01, 350.79it/s]
Loading trips (Step: 5/12) : 43%|████▎ | 433/1007 [00:01<00:01, 352.04it/s]
Loading trips (Step: 5/12) : 47%|████▋ | 469/1007 [00:01<00:01, 353.31it/s]
Loading trips (Step: 5/12) : 50%|█████ | 505/1007 [00:01<00:01, 351.04it/s]
Loading trips (Step: 5/12) : 54%|█████▍ | 542/1007 [00:01<00:01, 356.35it/s]
Loading trips (Step: 5/12) : 57%|█████▋ | 579/1007 [00:01<00:01, 360.35it/s]
Loading trips (Step: 5/12) : 61%|██████ | 616/1007 [00:01<00:01, 363.14it/s]
Loading trips (Step: 5/12) : 65%|██████▍ | 654/1007 [00:01<00:00, 366.03it/s]
Loading trips (Step: 5/12) : 69%|██████▊ | 691/1007 [00:02<00:00, 367.12it/s]
Loading trips (Step: 5/12) : 72%|███████▏ | 729/1007 [00:02<00:00, 368.41it/s]
Loading trips (Step: 5/12) : 76%|███████▌ | 766/1007 [00:02<00:00, 368.42it/s]
Loading trips (Step: 5/12) : 80%|███████▉ | 804/1007 [00:02<00:00, 369.27it/s]
Loading trips (Step: 5/12) : 84%|████████▎ | 841/1007 [00:02<00:00, 280.62it/s]
Loading trips (Step: 5/12) : 87%|████████▋ | 877/1007 [00:02<00:00, 299.47it/s]
Loading trips (Step: 5/12) : 91%|█████████ | 914/1007 [00:02<00:00, 317.48it/s]
Loading trips (Step: 5/12) : 95%|█████████▍| 952/1007 [00:02<00:00, 332.08it/s]
Loading trips (Step: 5/12) : 98%|█████████▊| 990/1007 [00:02<00:00, 342.97it/s]
De-conflicting stop times (Step: 6/12) : 0%| | 0/1 [00:00<?, ?it/s]
Loading fare data (Step: 7/12) : 100%|██████████| 1/1 [00:00<00:00, 1.60it/s]
Loading data for 2016-04-13 (Step: 9/12) - : 0%| | 0/1 [00:00<?, ?it/s]
Saving patterns (Step: 10/12) : 0%| | 0/2 [00:00<?, ?it/s]
Saving trips (Step: 11/12) : 0%| | 0/360 [00:00<?, ?it/s]
Saving links (Step: 11/12) : 0%| | 0/78 [00:00<?, ?it/s]
Saving stops (Step: 12/12) : 0%| | 0/78 [00:00<?, ?it/s]
Saving stops (Step: 12/12) : 8%|▊ | 6/78 [00:00<00:01, 51.67it/s]
Saving stops (Step: 12/12) : 15%|█▌ | 12/78 [00:00<00:01, 46.54it/s]
Saving stops (Step: 12/12) : 22%|██▏ | 17/78 [00:00<00:01, 45.42it/s]
Saving stops (Step: 12/12) : 28%|██▊ | 22/78 [00:00<00:01, 44.51it/s]
Saving stops (Step: 12/12) : 35%|███▍ | 27/78 [00:00<00:01, 43.97it/s]
Saving stops (Step: 12/12) : 41%|████ | 32/78 [00:00<00:01, 43.86it/s]
Saving stops (Step: 12/12) : 47%|████▋ | 37/78 [00:00<00:00, 43.54it/s]
Saving stops (Step: 12/12) : 54%|█████▍ | 42/78 [00:00<00:00, 43.09it/s]
Saving stops (Step: 12/12) : 60%|██████ | 47/78 [00:01<00:00, 43.14it/s]
Saving stops (Step: 12/12) : 67%|██████▋ | 52/78 [00:01<00:00, 42.94it/s]
Saving stops (Step: 12/12) : 73%|███████▎ | 57/78 [00:01<00:00, 42.83it/s]
Saving stops (Step: 12/12) : 79%|███████▉ | 62/78 [00:01<00:00, 42.99it/s]
Saving stops (Step: 12/12) : 86%|████████▌ | 67/78 [00:01<00:00, 42.86it/s]
Saving stops (Step: 12/12) : 92%|█████████▏| 72/78 [00:01<00:00, 42.52it/s]
Saving stops (Step: 12/12) : 99%|█████████▊| 77/78 [00:01<00:00, 42.72it/s]
Now we will plot one of the route’s patterns we just imported
conn = database_connection("transit")
patterns = pd.read_sql("SELECT pattern_id, ST_AsText(geometry) geom FROM routes;", con=conn)
stops = pd.read_sql("""SELECT stop_id, ST_X(geometry) X, ST_Y(geometry) Y FROM stops""", con=conn)
We turn the patterns and stops DataFrames into GeoDataFrames so we can plot them more easily.
patterns = gpd.GeoDataFrame(patterns, geometry=gpd.GeoSeries.from_wkt(patterns["geom"]), crs=4326)
stops = gpd.GeoDataFrame(stops, geometry=gpd.GeoSeries.from_xy(stops["X"], stops["Y"]), crs=4326)
And plot out data!
map = patterns.explore(color=["#146DB3", "#EB9719"], style_kwds={"weight": 4}, name="links")
map = stops.explore(m=map, color="black", style_kwds={"radius": 2, "fillOpacity": 1.0}, name="stops")
folium.LayerControl().add_to(map)
map
project.close()
This project at /tmp/61d84b5da18444d8a7d20fbcdac55988 is already closed
Total running time of the script: (0 minutes 6.867 seconds)