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#
from pathlib import Path
import geopandas as gpd
import matplotlib.pyplot as plt
from polaris.analyze.path_metrics import PathMetrics
from polaris.analyze.result_kpis import ResultKPIs
from polaris.network.data.data_table_cache import DataTableCache
from polaris.runs.convergence.convergence_iteration import ConvergenceIteration
from polaris.runs.scenario_compression import ScenarioCompression
from polaris.runs.scenario_utils import get_last_iteration
Data Sources#
Open the demand database for analysis
project_dir = Path("/tmp/Bloomington")
iteration_folder = get_last_iteration(project_dir)
supply_db = ScenarioCompression.maybe_extract(Path(iteration_folder) / "Bloomington-Supply.sqlite")
zones = DataTableCache(supply_db).plotting_layer("Zone")
links = DataTableCache(supply_db).plotting_layer("Link")
Data retrieval#
last_iter = ConvergenceIteration.from_dir(iteration_folder)
kpis = ResultKPIs.from_iteration(last_iter)
Plotting aggregate results#
def chart_metric(df, metric: str, axis=None):
df.plot.area(ax=axis)
axis.set(title=metric)
df = kpis.m_etric_traffic_cumulative_gap()
fig, axis = plt.subplots(2, 2)
all_axis = [axis[0, 0], axis[0, 1], axis[1, 0], axis[1, 1]]
for metric, ax in zip(df.metric.unique(), all_axis):
df_ = df[df.metric == metric]
df_ = df_.dropna(axis=1, how="any").sort_values(by="Trip end minute")
chart_metric(df_, metric, ax)
# Combine all the operations and display
plt.tight_layout()
plt.show()
Totals per zone and link#
pm = PathMetrics(demand_file=last_iter.files.demand_db, h5_file=last_iter.files.result_h5)
traces = pm.data
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="link_id", 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(["link_id"]).sum()[["absolute_gap"]].reset_index()
plot_link_layer = llayer.merge(gap_per_link, left_on="link", right_on="link_id", how="left").drop(columns=["geo"])
map_center = (zlayer.geometry.centroid.x.mean(), zlayer.geometry.centroid.y.mean())
# Fill in any NaN to avoid kepler GL treating it as a string
plot_link_layer.absolute_gap = plot_link_layer.absolute_gap.fillna(0.0)
plot_zone_layer.absolute_gap = plot_zone_layer.absolute_gap.fillna(0.0)
/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:111: 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")
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 ... 437.077
1 22 ... 188.416
2 25 ... 88.863
3 27 ... 368.768
4 28 ... 203.211
.. ... ... ...
179 287 ... 2057.109
180 292 ... 2276.908
181 293 ... 2867.818
182 296 ... 545.642
183 297 ... 1210.687
[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 ... link_id absolute_gap
0 4 Landmark Drive ... 4.0 25.000
1 6 Landmark Drive ... 6.0 23.000
2 10 Mecherle Drive ... NaN 0.000
3 11 Mecherle Drive ... NaN 0.000
4 12 Mecherle Drive ... 12.0 14.933
... ... ... ... ... ...
4522 5993 Brigham School Road ... 5993.0 1.773
4523 5994 South Main Street ... 5994.0 13.264
4524 5995 South Main Street ... 5995.0 8.212
4525 5996 South Main Street ... 5996.0 4.960
4526 5997 South Main Street ... 5997.0 27.237
[4527 rows x 23 columns]}, height=900)
Total running time of the script: (0 minutes 2.254 seconds)