Note
Go to the end to download the full example code.
Building a model from GMNS#
In this example we create a model for Marshalltown, Iowa, from GMNS data generated from OSM data.
To create a network file from OSM, you can either use AequilibraE or OSM2GMNS
Imports#
from pathlib import Path
from tempfile import mkdtemp
import pandas as pd
from polaris.network.create.triggers import create_network_triggers, delete_network_triggers
from polaris.network.network import Network
from polaris.utils.database.db_utils import commit_and_close
# Figure out where our polaris directory is (so we can get some test data)
from polaris import __file__ as polaris_dir
polaris_dir = Path(polaris_dir).parent.parent
Creates a new supply file with the chosen SRID sphinx_gallery_thumbnail_path = ‘../../examples/model_building/marshalltown.png’
data_folder = polaris_dir / "tests" / "data" / "docs" / "marshalltown"
srid = 3857
project_dir = mkdtemp(prefix="polaris_marshalltown_from_gmns")
Network.create(Path(project_dir) / "Marshalltown-Supply.sqlite", srid=srid, jumpstart=True)
Opens the newly-created network and import the GMNS network into it
network = Network()
network.open(Path(project_dir) / "Marshalltown-Supply.sqlite")
network.ie.from_gmns(str(data_folder), "epsg:4326")
Unfortunately, Polaris still does not support arbitrary link types due to hard coded parameters in the simulator, so we will have to map them manually.
crosswalk = {
"WALK": "WALKWAY",
"TRANSIT": "BUSWAY",
"RESIDENTIAL": "LOCAL",
"SERVICE": "OTHER",
"SECONDARY": "MINOR",
"CYCLEWAY": "BIKEWAY", # In Polaris, we do not have a type for both bike and walk
"TERTIARY": "COLLECTOR",
"PATH": "WALKWAY",
"UNCLASSIFIED": "OTHER",
"PRIMARY": "MAJOR",
"TRUNK": "PRINCIPAL",
"MOTORWAY": "EXPRESSWAY",
"TRACK": "WALKWAY",
}
with commit_and_close(network.path_to_file, spatial=True) as conn:
for k, v in crosswalk.items():
conn.execute("""UPDATE Link SET "type"=? WHERE "type"=?;""", [v, k])
conn.commit()
conn.execute("DELETE FROM Link_type WHERE link_type=?;", [k])
We also did not did the necessary data imputation into this GMNS network before importing into Polaris, so let’s do it now. Let’s also turn off all triggers while we do that, as it makes it easier to avoid them to complain This adds a free-flow speed of 10 m/s and 1 lane per direction for most links, which is a TERRIBLE data imputation practice, but suffices for the purpose of an example
sqls = [
"""UPDATE Link SET lanes_ab=min(1, lanes_ab) where "type" !='EXPRESSWAY';""",
"""UPDATE Link SET lanes_ba=min(1, lanes_ba) where "type" !='EXPRESSWAY';""",
"""UPDATE Link SET fspd_ab=min(10, fspd_ab) where lanes_ab>0;""",
"""UPDATE Link SET fspd_ba=min(10, fspd_ba) where lanes_ba>0;""",
]
with commit_and_close(network.path_to_file, spatial=True) as conn:
delete_network_triggers(conn)
for sql in sqls:
conn.execute(sql)
conn.commit()
create_network_triggers(conn, srid)
transit = network.transit
transit.purge(False)
feed = transit.new_gtfs(
file_path=data_folder / "marshalltownmunicipaltransit-ia-us.zip",
description="Marshalltown impressive PT system",
agency="MTPT",
)
feed.set_allow_map_match(True)
feed.set_date("2019-10-08") # We should be a pick date very carefully
feed.path_store.threshold = 5000 # Let's assume we are on a machine with little memory
feed.set_do_raw_shapes(True)
transit.fix_connections_table()
We can also set a maximum speed to fix possible GTFS nonsense
max_speeds = pd.read_csv(data_folder / "transit_max_speeds.csv")
feed.set_maximum_speeds(max_speeds)
max_speeds.head()
We do the transit import
feed.doWork()
/usr/local/lib/python3.11/site-packages/geopandas/geodataframe.py:2391: UserWarning: CRS mismatch between the CRS of left geometries and the CRS of right geometries.
Use `to_crs()` to reproject one of the input geometries to match the CRS of the other.
Left CRS: EPSG:3857
Right CRS: None
return geopandas.sjoin(left_df=self, right_df=df, *args, **kwargs) # noqa: B026
/usr/local/lib/python3.11/site-packages/geopandas/geodataframe.py:2391: UserWarning: CRS mismatch between the CRS of left geometries and the CRS of right geometries.
Use `to_crs()` to reproject one of the input geometries to match the CRS of the other.
Left CRS: EPSG:3857
Right CRS: None
return geopandas.sjoin(left_df=self, right_df=df, *args, **kwargs) # noqa: B026
/usr/local/lib/python3.11/site-packages/geopandas/geodataframe.py:2391: UserWarning: CRS mismatch between the CRS of left geometries and the CRS of right geometries.
Use `to_crs()` to reproject one of the input geometries to match the CRS of the other.
Left CRS: EPSG:3857
Right CRS: None
return geopandas.sjoin(left_df=self, right_df=df, *args, **kwargs) # noqa: B026
/usr/local/lib/python3.11/site-packages/geopandas/geodataframe.py:2391: UserWarning: CRS mismatch between the CRS of left geometries and the CRS of right geometries.
Use `to_crs()` to reproject one of the input geometries to match the CRS of the other.
Left CRS: EPSG:3857
Right CRS: None
return geopandas.sjoin(left_df=self, right_df=df, *args, **kwargs) # noqa: B026
/usr/local/lib/python3.11/site-packages/geopandas/geodataframe.py:2391: UserWarning: CRS mismatch between the CRS of left geometries and the CRS of right geometries.
Use `to_crs()` to reproject one of the input geometries to match the CRS of the other.
Left CRS: EPSG:3857
Right CRS: None
return geopandas.sjoin(left_df=self, right_df=df, *args, **kwargs) # noqa: B026
/usr/local/lib/python3.11/site-packages/geopandas/geodataframe.py:2391: UserWarning: CRS mismatch between the CRS of left geometries and the CRS of right geometries.
Use `to_crs()` to reproject one of the input geometries to match the CRS of the other.
Left CRS: EPSG:3857
Right CRS: None
return geopandas.sjoin(left_df=self, right_df=df, *args, **kwargs) # noqa: B026
We create the walk/bike networks for this network
network.active.build()
The network still doesn’t have zones, locations or other things, so we won’t bother about running consistency checks
network.close(clear_issues=False)
Total running time of the script: (0 minutes 22.530 seconds)