# traffic-flow
A Python module for macroscopic transport modelling; forecasting future traffic flows after major infrastructure projects.
Installation:
```bash
pip install traffic-flow
```
or:
```bash
pip install git+https://github.com/petervanya/traffic-flow.git
```
## Overview
### Key features
- A minimal, open-source and Pythonic alternative to closed-source products such as PTV Visum, Aimsum or Cube
- An implementation of the [three-step transport model](https://www.transitwiki.org/TransitWiki/index.php/Four-step_travel_model)
- Simple input structure in excel: nodes (zones and crossroads), links (road sections and connectors to zones) and link types (road types)
- Only one transport system available at the moment (eg passenger vehicles), more to be added in the future (work in progress)
On top of the features contained in closed-source products, this package enables a data-driven parameter optimisation (a simplified machine-learning) based on measured traffic flows.
### A quick overview of macroscopic transport modelling
Prior to modelling, one must create a network of road sections (links) and zones (nodes) with attributes representing the composition of the population. (NB: This step cannot be currently done with this package, we advise to use one of GIS packages or standard modelling products such as PTV Visum.)
Standard four-step modelling:
1. Trip generation: decide the demand stratum representing eg people daily travelling to work between zones
2. Trip distribution: compute the travel distance between the zones and distribute the generated trips
3. Mode choice: decide between private and public transport (not available here yet)
4. Assignment: assign the trips between the zones to the road network
On the output, there are traffic flows (eg 20000 vehicles/24h on a specific highway section), which can be compared with measured flows.
Then, a new link representing a new highway section can be added to the network and we can get a prediction for the traffic flow on the link with travel times. This can then serve as input for the cost-benefit analysis to estimate if the new section is worth building.
### Technical details
Multiple graph libraries (backends) exploited to represent the road network:
- [Igraph](https://igraph.org/python/), high-performance with C++ backend (default)
- [NetworkX](https://networkx.org/), purely Pythonic, lower performance
Both directed (default) and undirected networks are available.
## Inputs
The network is represented by three tables (dataframes):
* nodes (zones, crossroads and other point features)
* links (road sections or connectors to zones)
* link types (types of roads specified by their capacities and speeds)
In the simulation, these tables are read into a graph structure, which is then used to compute the shortest paths between zones and perform network assignment.
Each table has a set of columns that must be present:
- nodes: `[id, is_zone, name, pop]` (`pop` represents the population as a basic demand stratum)
- links: `[id, node_from, node_to, type, length]` (ideally also include `count` for traffic flows)
- link types: `[type, type_name, v0, qmax, a, b]`
To better appreciate the logic of the input tables, please download one of the sample inputs (see below).
## Example
### Sample inputs
Several sample networks are available:
* Network 1: minimal setting, 4 zones, 8 links
* Network 2: larger area, 12 zones, 42 links
Loading an example network:
```python
from traffic_flow.sample_networks import load_network_2
df_nodes, df_link_types, df_links = load_network_2()
```
### Reading inputs from PTV Visum
Alternatively, it is possible to load the shapefiles exported from PTV Visum.
Assuming the modelling project is stored in `project-path`, the following shapefiles are required:
- `project-path/myproject_node.SHP`
- `project-path/myproject_zone_centropid.SHP`
- `project-path/myproject_link.SHP`
- `project-path/myproject_connector.SHP`
```python
from traffic_flow.utils import read_inputs_shapefile
basepath = 'project-path'
basename = 'myproject'
df_nodes, df_link_types, df_links = read_inputs_shapefile(basepath, basename)
```
### Simulation
```python
from traffic_flow import MTM # macroscopic transport model
# initialise the object
model = MTM()
# read the input network data
model.read_data(df_nodes, df_link_types, df_links)
# trip generation, create a demand stratum
# 'pop' is a zone attribute containing population
model.generate("stratum-1", "pop", "pop", 0.5)
# calculate skim (resistance) matrices for distance and time
model.compute_skims()
# trip distribution of demand stratum 'stratum-1' using the gravity model
# distribute the trips exponentially with decay parameter -0.02
# disutility defined as time 'tcur' computed above as a skim matrix
model.distribute("stratum-1", "tcur", "exp", -0.02)
# assign vehicle flows to network edges (ie road sections) based on real travel time:
model.assign("tcur")
```
As a result of assignment, the `model.df_links` attribute obtains the `q` column with modelled traffic flows.
## Data-driven optimisation of model parameters
As an extra vital feature, which is absent in standard transport modelling software, `traffic-flow` enables tuning the generation and distribution parameters in order to minimise error between predicted and measured traffic flows. This is where machine learning meets transport modelling to leverage the use of cheap data (automatic traffic flow counts) to bypass expensive travel surveys and expert time required for model calibration.
The modelling pipeline now changes as follows:
```python
from traffic_flow import MTM
model = MTM()
model.read_data(df_nodes, df_link_types, df_links)
model.generate("stratum-1", "pop", "pop", 0.5) # parameter
model.compute_skims()
model.distribute("stratum-1", "tcur", "exp", -0.02) # parameter
# optimise using 10 iterations
model.optimise(n_iter=10)
```
Get the results:
```python
>>> print(model.opt_params)
```
| | attr_param | dist_param |
|:----------|-------------:|-------------:|
| stratum-1 | 0.699951 | -0.0581738 |
After optimisation, trip generation changed to 0.7 and the distribution exponent to -0.06 respectively.
The objective function is the [GEH function](https://en.wikipedia.org/wiki/GEH_statistic).
Currently [dual annealing](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.dual_annealing.html)
is the only available global optimisation method, others can be added upon request.
## Contributions
- Katarína Šimková, University of Glasgow/Vrije Universiteit Brussel
- Patrik Turzák, World Bank
Started as a side project on a summer internship at the Ministry of Finance of Slovakia.
To contribute, please fork the repo, make *reasonable* changes (ideally contact me at `peter.vanya~gmail` before) and create a pull request.
Raw data
{
"_id": null,
"home_page": "https://github.com/petervanya/traffic-flow",
"name": "traffic-flow",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": "",
"keywords": "traffic flow modelling forecast optimisation transport",
"author": "Peter Vanya",
"author_email": "peter.vanya@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/34/aa/594bc82c76b23e402835fa226fa34a0a489384bde68e8f960074aa160c0e/traffic-flow-0.2.4.tar.gz",
"platform": null,
"description": "# traffic-flow\n\nA Python module for macroscopic transport modelling; forecasting future traffic flows after major infrastructure projects.\n\nInstallation:\n```bash\npip install traffic-flow\n```\nor:\n```bash\npip install git+https://github.com/petervanya/traffic-flow.git\n```\n\n## Overview\n\n### Key features\n- A minimal, open-source and Pythonic alternative to closed-source products such as PTV Visum, Aimsum or Cube\n- An implementation of the [three-step transport model](https://www.transitwiki.org/TransitWiki/index.php/Four-step_travel_model)\n- Simple input structure in excel: nodes (zones and crossroads), links (road sections and connectors to zones) and link types (road types)\n- Only one transport system available at the moment (eg passenger vehicles), more to be added in the future (work in progress)\n\nOn top of the features contained in closed-source products, this package enables a data-driven parameter optimisation (a simplified machine-learning) based on measured traffic flows.\n\n### A quick overview of macroscopic transport modelling\nPrior to modelling, one must create a network of road sections (links) and zones (nodes) with attributes representing the composition of the population. (NB: This step cannot be currently done with this package, we advise to use one of GIS packages or standard modelling products such as PTV Visum.)\n\nStandard four-step modelling:\n1. Trip generation: decide the demand stratum representing eg people daily travelling to work between zones\n2. Trip distribution: compute the travel distance between the zones and distribute the generated trips\n3. Mode choice: decide between private and public transport (not available here yet)\n4. Assignment: assign the trips between the zones to the road network\n\nOn the output, there are traffic flows (eg 20000 vehicles/24h on a specific highway section), which can be compared with measured flows.\n\nThen, a new link representing a new highway section can be added to the network and we can get a prediction for the traffic flow on the link with travel times. This can then serve as input for the cost-benefit analysis to estimate if the new section is worth building.\n\n### Technical details\nMultiple graph libraries (backends) exploited to represent the road network:\n- [Igraph](https://igraph.org/python/), high-performance with C++ backend (default)\n- [NetworkX](https://networkx.org/), purely Pythonic, lower performance\n\nBoth directed (default) and undirected networks are available.\n\n\n## Inputs\nThe network is represented by three tables (dataframes):\n* nodes (zones, crossroads and other point features)\n* links (road sections or connectors to zones)\n* link types (types of roads specified by their capacities and speeds)\n\nIn the simulation, these tables are read into a graph structure, which is then used to compute the shortest paths between zones and perform network assignment.\n\nEach table has a set of columns that must be present:\n- nodes: `[id, is_zone, name, pop]` (`pop` represents the population as a basic demand stratum)\n- links: `[id, node_from, node_to, type, length]` (ideally also include `count` for traffic flows)\n- link types: `[type, type_name, v0, qmax, a, b]`\n\nTo better appreciate the logic of the input tables, please download one of the sample inputs (see below).\n\n\n## Example\n\n### Sample inputs\nSeveral sample networks are available:\n* Network 1: minimal setting, 4 zones, 8 links\n* Network 2: larger area, 12 zones, 42 links\n\nLoading an example network:\n```python\nfrom traffic_flow.sample_networks import load_network_2\n\ndf_nodes, df_link_types, df_links = load_network_2()\n```\n\n### Reading inputs from PTV Visum\nAlternatively, it is possible to load the shapefiles exported from PTV Visum.\nAssuming the modelling project is stored in `project-path`, the following shapefiles are required:\n- `project-path/myproject_node.SHP`\n- `project-path/myproject_zone_centropid.SHP`\n- `project-path/myproject_link.SHP`\n- `project-path/myproject_connector.SHP`\n\n```python\nfrom traffic_flow.utils import read_inputs_shapefile\n\nbasepath = 'project-path'\nbasename = 'myproject'\ndf_nodes, df_link_types, df_links = read_inputs_shapefile(basepath, basename)\n```\n\n### Simulation\n```python\nfrom traffic_flow import MTM # macroscopic transport model\n\n# initialise the object\nmodel = MTM()\n\n# read the input network data\nmodel.read_data(df_nodes, df_link_types, df_links)\n\n# trip generation, create a demand stratum\n# 'pop' is a zone attribute containing population\nmodel.generate(\"stratum-1\", \"pop\", \"pop\", 0.5)\n\n# calculate skim (resistance) matrices for distance and time\nmodel.compute_skims()\n\n# trip distribution of demand stratum 'stratum-1' using the gravity model\n# distribute the trips exponentially with decay parameter -0.02 \n# disutility defined as time 'tcur' computed above as a skim matrix\nmodel.distribute(\"stratum-1\", \"tcur\", \"exp\", -0.02)\n\n# assign vehicle flows to network edges (ie road sections) based on real travel time:\nmodel.assign(\"tcur\")\n```\n\nAs a result of assignment, the `model.df_links` attribute obtains the `q` column with modelled traffic flows.\n\n\n## Data-driven optimisation of model parameters\nAs an extra vital feature, which is absent in standard transport modelling software, `traffic-flow` enables tuning the generation and distribution parameters in order to minimise error between predicted and measured traffic flows. This is where machine learning meets transport modelling to leverage the use of cheap data (automatic traffic flow counts) to bypass expensive travel surveys and expert time required for model calibration.\n\nThe modelling pipeline now changes as follows:\n```python\nfrom traffic_flow import MTM\n\nmodel = MTM()\nmodel.read_data(df_nodes, df_link_types, df_links)\nmodel.generate(\"stratum-1\", \"pop\", \"pop\", 0.5) # parameter\nmodel.compute_skims()\nmodel.distribute(\"stratum-1\", \"tcur\", \"exp\", -0.02) # parameter\n\n# optimise using 10 iterations\nmodel.optimise(n_iter=10)\n```\n\nGet the results:\n```python\n>>> print(model.opt_params)\n```\n| | attr_param | dist_param |\n|:----------|-------------:|-------------:|\n| stratum-1 | 0.699951 | -0.0581738 |\n\nAfter optimisation, trip generation changed to 0.7 and the distribution exponent to -0.06 respectively.\n\nThe objective function is the [GEH function](https://en.wikipedia.org/wiki/GEH_statistic).\n\nCurrently [dual annealing](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.dual_annealing.html)\nis the only available global optimisation method, others can be added upon request.\n\n\n## Contributions\n- Katar\u00edna \u0160imkov\u00e1, University of Glasgow/Vrije Universiteit Brussel\n- Patrik Turz\u00e1k, World Bank\n\nStarted as a side project on a summer internship at the Ministry of Finance of Slovakia.\n\nTo contribute, please fork the repo, make *reasonable* changes (ideally contact me at `peter.vanya~gmail` before) and create a pull request.\n",
"bugtrack_url": null,
"license": "GPLv3",
"summary": "Macroscopic transport modelling; forecasting traffic flows on roads",
"version": "0.2.4",
"project_urls": {
"Homepage": "https://github.com/petervanya/traffic-flow"
},
"split_keywords": [
"traffic",
"flow",
"modelling",
"forecast",
"optimisation",
"transport"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d9bc0e158ce0ae09e9d8d2d7f395e5c32b2e92a3e8b09549da947581304478c5",
"md5": "71181867843b1094a86efcae8e8b555b",
"sha256": "6024bbfa5df37e91ea2e595f665eb680011ab796045d1df575b795ba0f4dc6bd"
},
"downloads": -1,
"filename": "traffic_flow-0.2.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "71181867843b1094a86efcae8e8b555b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 91993,
"upload_time": "2023-12-16T22:46:48",
"upload_time_iso_8601": "2023-12-16T22:46:48.573623Z",
"url": "https://files.pythonhosted.org/packages/d9/bc/0e158ce0ae09e9d8d2d7f395e5c32b2e92a3e8b09549da947581304478c5/traffic_flow-0.2.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "34aa594bc82c76b23e402835fa226fa34a0a489384bde68e8f960074aa160c0e",
"md5": "44d862b2434af1ad21b901fca633c194",
"sha256": "ec688f76d435ec5b8d910056ed22503d95f2f9435ee31c34838735835d84a2b2"
},
"downloads": -1,
"filename": "traffic-flow-0.2.4.tar.gz",
"has_sig": false,
"md5_digest": "44d862b2434af1ad21b901fca633c194",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 70510,
"upload_time": "2023-12-16T22:46:51",
"upload_time_iso_8601": "2023-12-16T22:46:51.133584Z",
"url": "https://files.pythonhosted.org/packages/34/aa/594bc82c76b23e402835fa226fa34a0a489384bde68e8f960074aa160c0e/traffic-flow-0.2.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-12-16 22:46:51",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "petervanya",
"github_project": "traffic-flow",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "traffic-flow"
}