Run module#

In this example we demonstrate how to use AequilibraE’s run module using Sioux Falls example.

References

See also

Several functions, methods, classes and modules are used in this example:

# Imports
from uuid import uuid4
from tempfile import gettempdir
from os.path import join

from aequilibrae.parameters import Parameters
from aequilibrae.utils.create_example import create_example
# Let's create the Sioux Falls example in an arbitrary folder.
folder = join(gettempdir(), uuid4().hex)

project = create_example(folder)

First, let’s check the matrix information using matrix_summary(). This method provides us useful information such as the matrix total, minimum and maximum values in the array, and the number of non-empty pairs in the matrix.

Notice that the matrix summary is presented for each matrix core.

project.run.matrix_summary()
{'demand_omx': {'matrix': {'total': 360600.0, 'min': 0.0, 'max': 4400.0, 'nnz': 528}}, 'demand_mc': {'car': {'total': 271266.6324170904, 'min': 0.0, 'max': 3414.160702028352, 'nnz': 528}, 'motorcycle': {'total': 89819.0708124364, 'min': 0.0, 'max': 1237.9652821904103, 'nnz': 528}, 'trucks': {'total': 90235.57459796841, 'min': 0.0, 'max': 1318.3068496025667, 'nnz': 528}}, 'skims': {'distance_blended': {'total': 6725.294972629576, 'min': 0.0, 'max': 27.000048290421308, 'nnz': 552}, 'time_final': {'total': 13600.90095750823, 'min': 0.0, 'max': 46.66452630996126, 'nnz': 552}}, 'demand_aem': {'matrix': {'total': 360600.0, 'min': 0.0, 'max': 4400.0, 'nnz': 528}}}

If our matrices folder is empty, instead of a nested dictionary of data, AequilibraE run would return an empty dictionary.

Let’s create a graph for mode car.

mode = "c"
network = project.network
network.build_graphs(modes=[mode])
graph = network.graphs[mode]
graph.set_graph("distance")
graph.set_skimming("distance")
graph.set_blocked_centroid_flows(False)

With the method graph_summary(), we can check the total number of links, nodes, and zones, as well as the compact number of links and nodes used for computation. If we had more than one graph, its information would be displayed within the nested dictionary.

project.run.graph_summary()
{'c': {'num_links': 76, 'num_nodes': 24, 'num_zones': 24, 'compact_num_links': 76, 'compact_num_nodes': 24}}

If no graphs have been built, an empty dictionary will be returned.

Let’s add a create_delaunay function to our run/__init__.py file.

This function replicates the example in which we create Delaunay lines.

func_string = """
def create_delaunay(source: str, name: str, computational_view: str, result_name: str, overwrite: bool=False):\n
\tfrom aequilibrae.utils.create_delaunay_network import DelaunayAnalysis\n
\tproject = get_active_project()\n
\tmatrix = project.matrices\n
\tmat = matrix.get_matrix(name)\n
\tmat.computational_view(computational_view)\n
\tda = DelaunayAnalysis(project)\n
\tda.create_network(source, overwrite)\n
\tda.assign_matrix(mat, result_name)\n
"""
with open(join(folder, "run", "__init__.py"), "a") as file:
    file.write("\n")
    file.write(func_string)

Now we add new parameters to our model

p = Parameters(project)
p.parameters["run"]["create_delaunay"] = {}
p.parameters["run"]["create_delaunay"]["source"] = "zones"
p.parameters["run"]["create_delaunay"]["name"] = "demand_omx"
p.parameters["run"]["create_delaunay"]["computational_view"] = "matrix"
p.parameters["run"]["create_delaunay"]["result_name"] = "my_run_module_example"
p.write_back()

And we run the function

project.run.create_delaunay()
delaunay                                          :   0%|          | 0/24 [00:00<?, ?it/s]
Equilibrium Assignment                            :   0%|          | 0/250 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: delaunay          :   0%|          | 1/250 [00:00<00:00, 31300.78it/s]
All-or-Nothing - Traffic Class: delaunay          :   0%|          | 1/250 [00:00<00:00, 6743.25it/s]
All-or-Nothing - Traffic Class: delaunay          :   0%|          | 0/250 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: delaunay - Zones: 0/24:   0%|          | 0/250 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: delaunay - Zones: 10/24:   0%|          | 0/250 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: delaunay - Zones: 20/24:   0%|          | 0/250 [00:00<?, ?it/s]
All-or-Nothing - Traffic Class: delaunay - Zones: 24/24:   0%|          | 0/250 [00:00<?, ?it/s]

Note

To run the create_delaunay function we created above without argument values, we must insert the values as a project parameter. Adding an unused parameter to the parameters.yml file will raise an execution error.

Creating Delaunay lines also creates a results_database.sqlite that contains the result of the all-or-nothing algorithim that generated the output. We can check the existing results in the results_database using the results_summary method.

project.run.results_summary()
table_name procedure procedure_id procedure_report timestamp description year scenario reference_table
0 my_run_module_example Delaunay assignment e9610b1df90843ecba666ead5c3078be "{\"setup\": \"{'Algorithm': 'all-or-nothing',... 2025-07-25 10:28:37.050296 None None links


Let’s check what our Delaunay lines look like!

import sqlite3
import pandas as pd
import geopandas as gpd

Let’s retrieve the results

results = project.results.get_results("my_run_module_example").set_index("link_id")
with project.db_connection as conn:
    links = gpd.read_postgis(
        "SELECT link_id, st_asBinary(geometry) geometry FROM delaunay_network", conn, geom_col="geometry", crs=4326
    )
links.set_index("link_id", inplace=True)
df = links.join(results)
max_vol = df.matrix_tot.max()

And finally plot the data

df.plot(linewidth=5 * df["matrix_tot"] / max_vol, color="blue")
plot run module
<Axes: >
project.close()

Pipeline image credits to Data-pipeline icons created by Vectors Tank - Flaticon

Total running time of the script: (0 minutes 0.692 seconds)

Gallery generated by Sphinx-Gallery