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.metric_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)
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="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())
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")
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"
)
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
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