.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "_auto_examples/trip_distribution/plot_trip_distribution.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr__auto_examples_trip_distribution_plot_trip_distribution.py: .. _example_usage_distribution: Trip Distribution ================= In this example, we calibrate a Synthetic Gravity Model that same model plus IPF (Fratar/Furness). .. GENERATED FROM PYTHON SOURCE LINES 11-20 .. code-block:: Python # Imports from uuid import uuid4 from tempfile import gettempdir from os.path import join from aequilibrae.utils.create_example import create_example import pandas as pd import numpy as np .. GENERATED FROM PYTHON SOURCE LINES 21-22 We create the example project inside our temp folder .. GENERATED FROM PYTHON SOURCE LINES 22-26 .. code-block:: Python fldr = join(gettempdir(), uuid4().hex) project = create_example(fldr) .. GENERATED FROM PYTHON SOURCE LINES 27-29 We get the demand matrix directly from the project record so let's inspect what we have in the project .. GENERATED FROM PYTHON SOURCE LINES 29-32 .. code-block:: Python proj_matrices = project.matrices print(proj_matrices.list()) .. rst-class:: sphx-glr-script-out .. code-block:: none name file_name ... description status 0 demand_omx demand.omx ... Original data imported to OMX format 1 demand_mc demand_mc.omx ... None 2 skims skims.omx ... Example skim 3 demand_aem demand.aem ... Original data imported to AEM format [4 rows x 8 columns] .. GENERATED FROM PYTHON SOURCE LINES 33-34 We get the demand matrix .. GENERATED FROM PYTHON SOURCE LINES 34-37 .. code-block:: Python demand = proj_matrices.get_matrix("demand_omx") demand.computational_view(["matrix"]) .. GENERATED FROM PYTHON SOURCE LINES 38-39 And the impedance .. GENERATED FROM PYTHON SOURCE LINES 39-42 .. code-block:: Python impedance = proj_matrices.get_matrix("skims") impedance.computational_view(["time_final"]) .. GENERATED FROM PYTHON SOURCE LINES 43-44 Let's have a function to plot the Trip Length Frequency Distribution .. GENERATED FROM PYTHON SOURCE LINES 44-47 .. code-block:: Python from math import log10, floor import matplotlib.pyplot as plt .. GENERATED FROM PYTHON SOURCE LINES 48-67 .. code-block:: Python def plot_tlfd(demand, skim, name): plt.clf() b = floor(log10(skim.shape[0]) * 10) n, bins, patches = plt.hist( np.nan_to_num(skim.flatten(), 0), bins=b, weights=np.nan_to_num(demand.flatten()), density=False, facecolor="g", alpha=0.75, ) plt.xlabel("Trip length") plt.ylabel("Probability") plt.title("Trip-length frequency distribution") plt.savefig(name, format="png") return plt .. GENERATED FROM PYTHON SOURCE LINES 68-70 .. code-block:: Python from aequilibrae.distribution import GravityCalibration .. GENERATED FROM PYTHON SOURCE LINES 71-87 .. code-block:: Python for function in ["power", "expo"]: gc = GravityCalibration(matrix=demand, impedance=impedance, function=function, nan_as_zero=True) gc.calibrate() model = gc.model # We save the model model.save(join(fldr, f"{function}_model.mod")) # We can save an image for the resulting model _ = plot_tlfd(gc.result_matrix.matrix_view, impedance.matrix_view, join(fldr, f"{function}_tfld.png")) # We can save the result of applying the model as well # We can also save the calibration report with open(join(fldr, f"{function}_convergence.log"), "w") as otp: for r in gc.report: otp.write(r + "\n") .. image-sg:: /_auto_examples/trip_distribution/images/sphx_glr_plot_trip_distribution_001.png :alt: Trip-length frequency distribution :srcset: /_auto_examples/trip_distribution/images/sphx_glr_plot_trip_distribution_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none /opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/site-packages/aequilibrae/distribution/gravity_application.py:321: RuntimeWarning: divide by zero encountered in power self.output.matrix_view[i, :] = (np.power(self.impedance.matrix_view[i, :], -self.model.alpha) * p * a)[ /opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/site-packages/aequilibrae/distribution/gravity_application.py:335: RuntimeWarning: invalid value encountered in multiply self.output.matrix_view[:, :] = self.output.matrix_view[:, :] * non_inf .. GENERATED FROM PYTHON SOURCE LINES 88-89 We save a trip length frequency distribution for the demand itself .. GENERATED FROM PYTHON SOURCE LINES 89-92 .. code-block:: Python plt = plot_tlfd(demand.matrix_view, impedance.matrix_view, join(fldr, "demand_tfld.png")) plt.show() .. image-sg:: /_auto_examples/trip_distribution/images/sphx_glr_plot_trip_distribution_002.png :alt: Trip-length frequency distribution :srcset: /_auto_examples/trip_distribution/images/sphx_glr_plot_trip_distribution_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 93-97 Forecast -------- We create a set of *'future'* vectors by applying some models and apply the model for both deterrence functions .. GENERATED FROM PYTHON SOURCE LINES 99-104 .. code-block:: Python from aequilibrae.distribution import Ipf, GravityApplication, SyntheticGravityModel from aequilibrae.matrix import AequilibraeData import numpy as np .. GENERATED FROM PYTHON SOURCE LINES 105-107 .. code-block:: Python zonal_data = pd.read_sql("Select zone_id, population, employment from zones order by zone_id", project.conn) .. GENERATED FROM PYTHON SOURCE LINES 108-109 We compute the vectors from our matrix .. GENERATED FROM PYTHON SOURCE LINES 109-127 .. code-block:: Python args = { "file_path": join(fldr, "synthetic_future_vector.aed"), "entries": demand.zones, "field_names": ["origins", "destinations"], "data_types": [np.float64, np.float64], "memory_mode": True, } vectors = AequilibraeData() vectors.create_empty(**args) vectors.index[:] = zonal_data.zone_id[:] # We apply a trivial regression-based model and balance the vectors vectors.origins[:] = zonal_data.population[:] * 2.32 vectors.destinations[:] = zonal_data.employment[:] * 1.87 vectors.destinations *= vectors.origins.sum() / vectors.destinations.sum() .. GENERATED FROM PYTHON SOURCE LINES 128-129 We simply apply the models to the same impedance matrix now .. GENERATED FROM PYTHON SOURCE LINES 129-150 .. code-block:: Python for function in ["power", "expo"]: model = SyntheticGravityModel() model.load(join(fldr, f"{function}_model.mod")) outmatrix = join(proj_matrices.fldr, f"demand_{function}_model.aem") args = { "impedance": impedance, "rows": vectors, "row_field": "origins", "model": model, "columns": vectors, "column_field": "destinations", "nan_as_zero": True, } gravity = GravityApplication(**args) gravity.apply() # We get the output matrix and save it to OMX too, gravity.save_to_project(name=f"demand_{function}_model_omx", file_name=f"demand_{function}_model.omx") .. GENERATED FROM PYTHON SOURCE LINES 151-152 We update the matrices table/records and verify that the new matrices are indeed there .. GENERATED FROM PYTHON SOURCE LINES 152-155 .. code-block:: Python proj_matrices.update_database() print(proj_matrices.list()) .. rst-class:: sphx-glr-script-out .. code-block:: none name ... status 0 demand_omx ... 1 demand_mc ... 2 skims ... 3 demand_aem ... 4 demand_power_model_omx ... 5 demand_expo_model_omx ... [6 rows x 8 columns] .. GENERATED FROM PYTHON SOURCE LINES 156-157 We now run IPF for the future vectors .. GENERATED FROM PYTHON SOURCE LINES 159-174 .. code-block:: Python args = { "matrix": demand, "rows": vectors, "columns": vectors, "column_field": "destinations", "row_field": "origins", "nan_as_zero": True, } ipf = Ipf(**args) ipf.fit() ipf.save_to_project(name="demand_ipf", file_name="demand_ipf.aem") ipf.save_to_project(name="demand_ipf_omx", file_name="demand_ipf.omx") .. rst-class:: sphx-glr-script-out .. code-block:: none .. GENERATED FROM PYTHON SOURCE LINES 175-177 .. code-block:: Python print(proj_matrices.list()) .. rst-class:: sphx-glr-script-out .. code-block:: none name ... status 0 demand_omx ... 1 demand_mc ... 2 skims ... 3 demand_aem ... 4 demand_power_model_omx ... 5 demand_expo_model_omx ... 6 demand_ipf ... 7 demand_ipf_omx ... [8 rows x 8 columns] .. GENERATED FROM PYTHON SOURCE LINES 178-179 .. code-block:: Python project.close() .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.324 seconds) .. _sphx_glr_download__auto_examples_trip_distribution_plot_trip_distribution.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_trip_distribution.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_trip_distribution.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_trip_distribution.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_