Note
Go to the end to download the full example code.
Analyzing traffic convergence#
On this example we show how to use analyze traffic convergence for different segments of the results
Imports#
import sqlite3
from pathlib import Path
import geopandas as gpd
from polaris.analyze.path_metrics import PathMetrics
from polaris.network.data.data_table_cache import DataTableCache
from polaris.network.network import Network
from polaris.runs.scenario_compression import ScenarioCompression
from polaris.runs.scenario_utils import get_last_iteration
from polaris.utils.database.db_utils import read_and_close
Data Sources#
Open the demand database for analysis sphinx_gallery_thumbnail_path = ‘../../examples/result_analysis/map_plot_convergence_analysis.png’
project_dir = Path("/tmp/Bloomington")
iteration_folder = get_last_iteration(project_dir)
demand_db = ScenarioCompression.maybe_extract(Path(iteration_folder) / "Bloomington-Demand.sqlite")
supply_db = ScenarioCompression.maybe_extract(Path(iteration_folder) / "Bloomington-Supply.sqlite")
dem_conn = sqlite3.connect(demand_db)
net = Network()
net.open(supply_db)
Data retrieval#
tm = PathMetrics(supply_file=supply_db, demand_file=demand_db)
with read_and_close(supply_db, spatial=True) as conn:
zones = DataTableCache(supply_db).plotting_layer("Zone", conn)
links = DataTableCache(supply_db).plotting_layer("Link", conn)
traces = tm.data
traces = traces[traces.tmode.isin([0, 9, 17, 18, 19, 20])]
traces.head()
Plotting aggregate results#
import matplotlib.pyplot as plt
def chart_metric(df, metric: str, axis=None):
data = df.rename(columns={"mend": "Trip end minute"})
data = data.groupby([metric, "Trip end minute"]).sum()[["absolute_gap"]].reset_index()
pvt = data.pivot_table(index="Trip end minute", values="absolute_gap", columns=metric, fill_value=0)
for c in data[metric].unique():
pvt[c] = pvt[c].cumsum()
if axis is None:
pvt.plot.area()
plt.title("Cummulative absolute gap")
plt.show()
else:
pvt.plot.area(ax=axis)
We can plot many figures together#
fig, axis = plt.subplots(2, 2)
chart_metric(traces, "value_Switch_Cause", axis[0, 0])
chart_metric(traces, "value_Number_of_Switches", axis[0, 1])
chart_metric(traces, "has_artificial_trip", axis[1, 0])
chart_metric(traces, "tmode", axis[1, 1])
# Combine all the operations and display
plt.tight_layout()
plt.show()
![plot convergence analysis](../../_images/sphx_glr_plot_convergence_analysis_001.png)
Or one at a time#
chart_metric(traces, "value_Switch_Cause")
![Cummulative absolute gap](../../_images/sphx_glr_plot_convergence_analysis_002.png)
Totals per zone and link#
zlayer = gpd.GeoDataFrame(zones, geometry=gpd.GeoSeries.from_wkt(zones.geo, crs=4326)).reset_index()
llayer = gpd.GeoDataFrame(links, geometry=gpd.GeoSeries.from_wkt(links.geo, crs=4326)).reset_index()
gdf = llayer.sjoin_nearest(zlayer, how="inner")[["link", "zone"]]
gap_per_zone = (
traces.merge(gdf, left_on="value_link", right_on="link").groupby(["zone"]).sum()[["absolute_gap"]].reset_index()
)
plot_zone_layer = zlayer.merge(gap_per_zone, on="zone").drop(columns=["geo"])
gap_per_link = traces.groupby(["value_link"]).sum()[["absolute_gap"]].reset_index()
plot_link_layer = llayer.merge(gap_per_link, left_on="link", right_on="value_link", how="left").drop(columns=["geo"])
map_center = (zlayer.geometry.centroid.x.mean(), zlayer.geometry.centroid.y.mean())
/usr/local/lib/python3.11/site-packages/geopandas/array.py:403: UserWarning: Geometry is in a geographic CRS. Results from 'sjoin_nearest' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.
warnings.warn(
/builds/polaris/code/polarislib/docs/examples/result_analysis/plot_convergence_analysis.py:120: UserWarning: Geometry is in a geographic CRS. Results from 'centroid' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.
map_center = (zlayer.geometry.centroid.x.mean(), zlayer.geometry.centroid.y.mean())
Cummulative charts#
import seaborn as sns
import matplotlib.pyplot as plt
cumm_links = gap_per_link.sort_values(by=["absolute_gap"], ascending=False).reset_index(drop=True)
cumm_links = cumm_links.assign(cummulative_relative_gap=cumm_links.absolute_gap.cumsum())
cumm_links.cummulative_relative_gap /= cumm_links.cummulative_relative_gap.max()
sns.lineplot(data=cumm_links["cummulative_relative_gap"])
plt.xlabel("link count")
![plot convergence analysis](../../_images/sphx_glr_plot_convergence_analysis_003.png)
Text(0.5, 23.52222222222222, 'link count')
And map them#
print(
"REFERENCE: And below we map links and zones according to gaps. The maps should look like this, "
"but will need formatting"
)
REFERENCE: And below we map links and zones according to gaps. The maps should look like this, but will need formatting
map_zone_config = {
"version": "v1",
"config": {
"visState": {
"filters": [],
"layers": [
{
"id": "z0w117",
"type": "geojson",
"config": {
"dataId": "Total gaps",
"label": "Total gaps",
"color": [34, 63, 154],
"highlightColor": [252, 242, 26, 255],
"columns": {"geojson": "geometry"},
"isVisible": True,
"visConfig": {
"opacity": 0.8,
"strokeOpacity": 0.8,
"thickness": 0.1,
"strokeColor": [221, 212, 205],
"colorRange": {
"name": "Uber Viz Diverging 1.5",
"type": "diverging",
"category": "Uber",
"colors": ["#00939C", "#5DBABF", "#BAE1E2", "#F8C0AA", "#DD7755", "#C22E00"],
},
"strokeColorRange": {
"name": "Global Warming",
"type": "sequential",
"category": "Uber",
"colors": ["#5A1846", "#900C3F", "#C70039", "#E3611C", "#F1920E", "#FFC300"],
},
"radius": 10,
"sizeRange": [0, 10],
"radiusRange": [0, 50],
"heightRange": [0, 500],
"elevationScale": 27.8,
"enableElevationZoomFactor": True,
"stroked": True,
"filled": True,
"enable3d": True,
"wireframe": False,
},
"hidden": False,
"textLabel": [
{
"field": None,
"color": [255, 255, 255],
"size": 18,
"offset": [0, 0],
"anchor": "start",
"alignment": "center",
}
],
},
"visualChannels": {
"colorField": {"name": "absolute_gap", "type": "integer"},
"colorScale": "quantile",
"strokeColorField": None,
"strokeColorScale": "quantile",
"sizeField": None,
"sizeScale": "linear",
"heightField": {"name": "relative_gap", "type": "real"},
"heightScale": "linear",
"radiusField": None,
"radiusScale": "linear",
},
}
],
"interactionConfig": {
"tooltip": {
"fieldsToShow": {
"Total gaps": [
{"name": "zone", "format": None},
{"name": "absolute_gap", "format": None},
{"name": "relative_gap", "format": ".1%"},
]
},
"compareMode": False,
"compareType": "absolute",
"enabled": True,
},
"brush": {"size": 0.5, "enabled": False},
"geocoder": {"enabled": False},
"coordinate": {"enabled": False},
},
"layerBlending": "normal",
"splitMaps": [],
"animationConfig": {"currentTime": None, "speed": 1},
},
"mapState": {
"bearing": 24,
"dragRotate": True,
"latitude": map_center[1],
"longitude": map_center[0],
"pitch": 50,
"zoom": 9.096117833833905,
"isSplit": False,
},
"mapStyle": {
"styleType": "muted",
"topLayerGroups": {},
"visibleLayerGroups": {
"label": True,
"road": False,
"border": False,
"building": True,
"water": True,
"land": True,
"3d building": False,
},
"threeDBuildingColor": [224.4071295378559, 224.4071295378559, 224.4071295378559],
"mapStyles": {},
},
},
}
from keplergl import KeplerGl
map1 = KeplerGl(height=900, data={"Total gaps": plot_zone_layer}, config=map_zone_config)
map1
User Guide: https://docs.kepler.gl/docs/keplergl-jupyter
KeplerGl(config={'version': 'v1', 'config': {'visState': {'filters': [], 'layers': [{'id': 'z0w117', 'type': 'geojson', 'config': {'dataId': 'Total gaps', 'label': 'Total gaps', 'color': [34, 63, 154], 'highlightColor': [252, 242, 26, 255], 'columns': {'geojson': 'geometry'}, 'isVisible': True, 'visConfig': {'opacity': 0.8, 'strokeOpacity': 0.8, 'thickness': 0.1, 'strokeColor': [221, 212, 205], 'colorRange': {'name': 'Uber Viz Diverging 1.5', 'type': 'diverging', 'category': 'Uber', 'colors': ['#00939C', '#5DBABF', '#BAE1E2', '#F8C0AA', '#DD7755', '#C22E00']}, 'strokeColorRange': {'name': 'Global Warming', 'type': 'sequential', 'category': 'Uber', 'colors': ['#5A1846', '#900C3F', '#C70039', '#E3611C', '#F1920E', '#FFC300']}, 'radius': 10, 'sizeRange': [0, 10], 'radiusRange': [0, 50], 'heightRange': [0, 500], 'elevationScale': 27.8, 'enableElevationZoomFactor': True, 'stroked': True, 'filled': True, 'enable3d': True, 'wireframe': False}, 'hidden': False, 'textLabel': [{'field': None, 'color': [255, 255, 255], 'size': 18, 'offset': [0, 0], 'anchor': 'start', 'alignment': 'center'}]}, 'visualChannels': {'colorField': {'name': 'absolute_gap', 'type': 'integer'}, 'colorScale': 'quantile', 'strokeColorField': None, 'strokeColorScale': 'quantile', 'sizeField': None, 'sizeScale': 'linear', 'heightField': {'name': 'relative_gap', 'type': 'real'}, 'heightScale': 'linear', 'radiusField': None, 'radiusScale': 'linear'}}], 'interactionConfig': {'tooltip': {'fieldsToShow': {'Total gaps': [{'name': 'zone', 'format': None}, {'name': 'absolute_gap', 'format': None}, {'name': 'relative_gap', 'format': '.1%'}]}, 'compareMode': False, 'compareType': 'absolute', 'enabled': True}, 'brush': {'size': 0.5, 'enabled': False}, 'geocoder': {'enabled': False}, 'coordinate': {'enabled': False}}, 'layerBlending': 'normal', 'splitMaps': [], 'animationConfig': {'currentTime': None, 'speed': 1}}, 'mapState': {'bearing': 24, 'dragRotate': True, 'latitude': 40.49083374959828, 'longitude': -88.97889575473327, 'pitch': 50, 'zoom': 9.096117833833905, 'isSplit': False}, 'mapStyle': {'styleType': 'muted', 'topLayerGroups': {}, 'visibleLayerGroups': {'label': True, 'road': False, 'border': False, 'building': True, 'water': True, 'land': True, '3d building': False}, 'threeDBuildingColor': [224.4071295378559, 224.4071295378559, 224.4071295378559], 'mapStyles': {}}}}, data={'Total gaps': zone ... absolute_gap
0 11 ... 991.0
1 22 ... 134.0
2 25 ... 158.0
3 27 ... 751.0
4 28 ... 338.0
.. ... ... ...
179 287 ... 2516.0
180 292 ... 3464.0
181 293 ... 3445.0
182 296 ... 389.0
183 297 ... 1065.0
[184 rows x 32 columns]}, height=900)
link_config = {
"version": "v1",
"config": {
"visState": {
"filters": [],
"layers": [
{
"id": "xiykhj",
"type": "geojson",
"config": {
"dataId": "Total gaps",
"label": "Total gaps",
"color": [248, 149, 112],
"highlightColor": [252, 242, 26, 255],
"columns": {"geojson": "geometry"},
"isVisible": True,
"visConfig": {
"opacity": 0.8,
"strokeOpacity": 1,
"thickness": 0.5,
"strokeColor": None,
"colorRange": {
"name": "Global Warming",
"type": "sequential",
"category": "Uber",
"colors": ["#5A1846", "#900C3F", "#C70039", "#E3611C", "#F1920E", "#FFC300"],
},
"strokeColorRange": {
"name": "Uber Viz Diverging 3.5",
"type": "diverging",
"category": "Uber",
"colors": [
"#00939C",
"#2FA7AE",
"#5DBABF",
"#8CCED1",
"#BAE1E2",
"#F8C0AA",
"#EB9C80",
"#DD7755",
"#D0532B",
"#C22E00",
],
},
"radius": 10,
"sizeRange": [0.2, 20],
"radiusRange": [0, 50],
"heightRange": [0, 500],
"elevationScale": 5,
"enableElevationZoomFactor": True,
"stroked": True,
"filled": False,
"enable3d": False,
"wireframe": False,
},
"hidden": False,
"textLabel": [
{
"field": None,
"color": [255, 255, 255],
"size": 18,
"offset": [0, 0],
"anchor": "start",
"alignment": "center",
}
],
},
"visualChannels": {
"colorField": None,
"colorScale": "quantile",
"strokeColorField": {"name": "absolute_gap", "type": "integer"},
"strokeColorScale": "quantile",
"sizeField": {"name": "absolute_gap", "type": "integer"},
"sizeScale": "linear",
"heightField": None,
"heightScale": "linear",
"radiusField": None,
"radiusScale": "linear",
},
}
],
"interactionConfig": {
"tooltip": {
"fieldsToShow": {
"Total gaps": [{"name": "link", "format": None}, {"name": "absolute_gap", "format": None}]
},
"compareMode": False,
"compareType": "absolute",
"enabled": True,
},
"brush": {"size": 0.5, "enabled": False},
"geocoder": {"enabled": False},
"coordinate": {"enabled": False},
},
"layerBlending": "normal",
"splitMaps": [],
"animationConfig": {"currentTime": None, "speed": 1},
},
"mapState": {
"bearing": 0,
"dragRotate": False,
"latitude": map_center[1],
"longitude": map_center[0],
"pitch": 0,
"zoom": 8.42575627208353,
"isSplit": False,
},
"mapStyle": {
"styleType": "muted",
"topLayerGroups": {},
"visibleLayerGroups": {
"label": False,
"road": False,
"border": False,
"building": True,
"water": True,
"land": True,
"3d building": False,
},
"threeDBuildingColor": [224.4071295378559, 224.4071295378559, 224.4071295378559],
"mapStyles": {},
},
},
}
from keplergl import KeplerGl
map2 = KeplerGl(height=900, data={"Total gaps": plot_link_layer}, config=link_config)
map2
User Guide: https://docs.kepler.gl/docs/keplergl-jupyter
KeplerGl(config={'version': 'v1', 'config': {'visState': {'filters': [], 'layers': [{'id': 'xiykhj', 'type': 'geojson', 'config': {'dataId': 'Total gaps', 'label': 'Total gaps', 'color': [248, 149, 112], 'highlightColor': [252, 242, 26, 255], 'columns': {'geojson': 'geometry'}, 'isVisible': True, 'visConfig': {'opacity': 0.8, 'strokeOpacity': 1, 'thickness': 0.5, 'strokeColor': None, 'colorRange': {'name': 'Global Warming', 'type': 'sequential', 'category': 'Uber', 'colors': ['#5A1846', '#900C3F', '#C70039', '#E3611C', '#F1920E', '#FFC300']}, 'strokeColorRange': {'name': 'Uber Viz Diverging 3.5', 'type': 'diverging', 'category': 'Uber', 'colors': ['#00939C', '#2FA7AE', '#5DBABF', '#8CCED1', '#BAE1E2', '#F8C0AA', '#EB9C80', '#DD7755', '#D0532B', '#C22E00']}, 'radius': 10, 'sizeRange': [0.2, 20], 'radiusRange': [0, 50], 'heightRange': [0, 500], 'elevationScale': 5, 'enableElevationZoomFactor': True, 'stroked': True, 'filled': False, 'enable3d': False, 'wireframe': False}, 'hidden': False, 'textLabel': [{'field': None, 'color': [255, 255, 255], 'size': 18, 'offset': [0, 0], 'anchor': 'start', 'alignment': 'center'}]}, 'visualChannels': {'colorField': None, 'colorScale': 'quantile', 'strokeColorField': {'name': 'absolute_gap', 'type': 'integer'}, 'strokeColorScale': 'quantile', 'sizeField': {'name': 'absolute_gap', 'type': 'integer'}, 'sizeScale': 'linear', 'heightField': None, 'heightScale': 'linear', 'radiusField': None, 'radiusScale': 'linear'}}], 'interactionConfig': {'tooltip': {'fieldsToShow': {'Total gaps': [{'name': 'link', 'format': None}, {'name': 'absolute_gap', 'format': None}]}, 'compareMode': False, 'compareType': 'absolute', 'enabled': True}, 'brush': {'size': 0.5, 'enabled': False}, 'geocoder': {'enabled': False}, 'coordinate': {'enabled': False}}, 'layerBlending': 'normal', 'splitMaps': [], 'animationConfig': {'currentTime': None, 'speed': 1}}, 'mapState': {'bearing': 0, 'dragRotate': False, 'latitude': 40.49083374959828, 'longitude': -88.97889575473327, 'pitch': 0, 'zoom': 8.42575627208353, 'isSplit': False}, 'mapStyle': {'styleType': 'muted', 'topLayerGroups': {}, 'visibleLayerGroups': {'label': False, 'road': False, 'border': False, 'building': True, 'water': True, 'land': True, '3d building': False}, 'threeDBuildingColor': [224.4071295378559, 224.4071295378559, 224.4071295378559], 'mapStyles': {}}}}, data={'Total gaps': link name ... value_link absolute_gap
0 4 Landmark Drive ... 4.0 24.0
1 6 Landmark Drive ... 6.0 32.0
2 10 Mecherle Drive ... NaN NaN
3 11 Mecherle Drive ... NaN NaN
4 12 Mecherle Drive ... 12.0 1.0
... ... ... ... ... ...
4522 5993 Brigham School Road ... 5993.0 13.0
4523 5994 South Main Street ... 5994.0 68.0
4524 5995 South Main Street ... 5995.0 59.0
4525 5996 South Main Street ... 5996.0 56.0
4526 5997 South Main Street ... 5997.0 15.0
[4527 rows x 23 columns]}, height=900)
Closes project
net.close()
Total running time of the script: (0 minutes 2.157 seconds)