{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n\n# Route Choice set generation\n\nIn this example, we show how to generate route choice sets for estimation of route choice models, using a\na city in La Serena Metropolitan Area in Chile.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        ".. admonition:: References\n\n  * :doc:`../../route_choice`\n\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        ".. seealso::\n    Several functions, methods, classes and modules are used in this example:\n\n    * :func:`aequilibrae.paths.RouteChoice`\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Imports\nfrom uuid import uuid4\nfrom tempfile import gettempdir\nfrom os.path import join\n\nimport folium\nimport numpy as np\nfrom aequilibrae.utils.create_example import create_example"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# We create the example project inside our temp folder\nfldr = join(gettempdir(), uuid4().hex)\n\nproject = create_example(fldr, \"coquimbo\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Model parameters\nLet's select a set of nodes of interest\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "od_pairs_of_interest = [(71645, 79385), (77011, 74089)]\nnodes_of_interest = (71645, 74089, 77011, 79385)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Let's build all graphs\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "project.network.build_graphs()\n# We get warnings that several fields in the project are filled with NaNs.\n# This is true, but we won't use those fields."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We grab the graph for cars\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "graph = project.network.graphs[\"c\"]\n\n# we also see what graphs are available\nproject.network.graphs.keys()\n\ngraph.set_graph(\"distance\")\n\n# We set the nodes of interest as centroids to make sure they are not simplified away when we create the network\ngraph.prepare_graph(np.array(nodes_of_interest))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Route Choice class\nHere we'll construct and use the Route Choice class to generate our route sets\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from aequilibrae.paths import RouteChoice"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "This object construct might take a minute depending on the size of the graph due to the construction of the\ncompressed link to network link mapping that's required. This is a one time operation per graph and is cached.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "rc = RouteChoice(graph)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "It is highly recommended to set either ``max_routes`` or ``max_depth`` to prevent runaway results.\n\nWe'll also set a 5% penalty (``penalty=1.05``), which is likely a little too large, but it creates routes that are \ndistinct enough to make this simple example more interesting.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "rc.set_choice_set_generation(\"bfsle\", max_routes=5, penalty=1.05)\nrc.prepare(od_pairs_of_interest)\nrc.execute(perform_assignment=True)\n\nchoice_set = rc.get_results()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "If we were interested in storing the route choice result, we could also write them to disk using the ``save_path_files`` method.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# rc.save_path_files(path)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "From those path files we could also preform a full assignment or select link analysis by using the ``execute_from_path_files`` method.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# rc.execute_from_path_files(path)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Or if we had externally computed route choice sets, we can use AequilibraEs assignment procedures by loading them with the ``execute_from_pandas` method.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# rc.execute_from_pandas(path_files_df)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Plotting choice sets\n\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Now we will plot the paths we just created for the second OD pair\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# We get the data we will use for the plot: links, nodes and the route choice set\nplot_routes = choice_set[(choice_set[\"origin id\"] == 77011)][\"route set\"].values\n\nlinks = project.network.links.data\n\n# For ease of plot, we create a GeoDataFrame for each route in the choice set\nroute_1 = links[links.link_id.isin(plot_routes[0])]\nroute_2 = links[links.link_id.isin(plot_routes[1])]\nroute_3 = links[links.link_id.isin(plot_routes[2])]\nroute_4 = links[links.link_id.isin(plot_routes[3])]\nroute_5 = links[links.link_id.isin(plot_routes[4])]\n\nnodes = project.network.nodes.data\nnodes = nodes[nodes[\"node_id\"].isin([77011, 74089])]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "map = route_1.explore(color=\"red\", style_kwds={\"weight\": 3}, name=\"route_1\")\nmap = route_2.explore(m=map, color=\"blue\", style_kwds={\"weight\": 3}, name=\"route_2\")\nmap = route_3.explore(m=map, color=\"green\", style_kwds={\"weight\": 3}, name=\"route_3\")\nmap = route_4.explore(m=map, color=\"purple\", style_kwds={\"weight\": 3}, name=\"route_4\")\nmap = route_5.explore(m=map, color=\"orange\", style_kwds={\"weight\": 3}, name=\"route_5\")\n\nmap = nodes.explore(m=map, color=\"black\", style_kwds={\"radius\": 5, \"fillOpacity\": 1.0}, name=\"network_nodes\")\n\nfolium.LayerControl().add_to(map)\nmap"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "project.close()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.10.18"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}