ranch-network-wrangler 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ranch_network_wrangler-0.0.1/LICENSE +29 -0
- ranch_network_wrangler-0.0.1/PKG-INFO +160 -0
- ranch_network_wrangler-0.0.1/README.md +130 -0
- ranch_network_wrangler-0.0.1/pyproject.toml +70 -0
- ranch_network_wrangler-0.0.1/ranch/__init__.py +34 -0
- ranch_network_wrangler-0.0.1/ranch/logger.py +47 -0
- ranch_network_wrangler-0.0.1/ranch/osm.py +200 -0
- ranch_network_wrangler-0.0.1/ranch/parameters.py +153 -0
- ranch_network_wrangler-0.0.1/ranch/roadway.py +1734 -0
- ranch_network_wrangler-0.0.1/ranch/sharedstreets.py +323 -0
- ranch_network_wrangler-0.0.1/ranch/transit.py +2713 -0
- ranch_network_wrangler-0.0.1/ranch/utils.py +770 -0
- ranch_network_wrangler-0.0.1/ranch_network_wrangler.egg-info/PKG-INFO +160 -0
- ranch_network_wrangler-0.0.1/ranch_network_wrangler.egg-info/SOURCES.txt +20 -0
- ranch_network_wrangler-0.0.1/ranch_network_wrangler.egg-info/dependency_links.txt +1 -0
- ranch_network_wrangler-0.0.1/ranch_network_wrangler.egg-info/requires.txt +11 -0
- ranch_network_wrangler-0.0.1/ranch_network_wrangler.egg-info/top_level.txt +1 -0
- ranch_network_wrangler-0.0.1/setup.cfg +4 -0
- ranch_network_wrangler-0.0.1/tests/test_osmnx.py +24 -0
- ranch_network_wrangler-0.0.1/tests/test_roadway.py +278 -0
- ranch_network_wrangler-0.0.1/tests/test_shst.py +95 -0
- ranch_network_wrangler-0.0.1/tests/test_transit.py +575 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022, WSP | Systems Analysis Group, Metropolitan Transportation Commission (MTC), Metropolitan Council, Miami-Dade TPO, Contra Costa Transportation Authority (CCTA), Alameda County Transportation Commission(ACTC), and Bay Area Rapid Transit (BART)
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ranch-network-wrangler
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A Python package for making travel model networks
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Project-URL: Homepage, https://github.com/network-wrangler/Ranch
|
|
7
|
+
Project-URL: Repository, https://github.com/network-wrangler/Ranch
|
|
8
|
+
Project-URL: Documentation, https://wsp-sag.github.io/Ranch/
|
|
9
|
+
Classifier: Development Status :: 1 - Planning
|
|
10
|
+
Classifier: Natural Language :: English
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
15
|
+
Requires-Python: >=3.7
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: docker
|
|
19
|
+
Requires-Dist: numpy
|
|
20
|
+
Requires-Dist: pandas>1.0
|
|
21
|
+
Requires-Dist: geopandas>=0.8.0
|
|
22
|
+
Requires-Dist: networkx
|
|
23
|
+
Requires-Dist: osmnx
|
|
24
|
+
Requires-Dist: partridge>=1.1
|
|
25
|
+
Requires-Dist: peartree
|
|
26
|
+
Requires-Dist: pyproj
|
|
27
|
+
Requires-Dist: scipy
|
|
28
|
+
Requires-Dist: shapely
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# Ranch
|
|
32
|
+
This is the Python package for building standard roadway and transit networks from scratch. Before becoming `Ranch`, it was also referred to as the `Standard Network Building Pipeline`, which consisted of a series of Python notebooks.
|
|
33
|
+
|
|
34
|
+
It aims to have the following functionality:
|
|
35
|
+
|
|
36
|
+
1. build OSM-based roadway network in standard [`Network Wrangler`](https://github.com/wsp-sag/network_wrangler) format
|
|
37
|
+
2. build GTFS-based transit network in standard [`Network Wrangler`](https://github.com/wsp-sag/network_wrangler) format
|
|
38
|
+
3. build travel model centroid connectors
|
|
39
|
+
|
|
40
|
+
For the latest code developments, check out the `develop` branch.
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
Install the published package with `uv`:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
uv add ranch-network-wrangler
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Or install it with pip:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
python -m pip install ranch-network-wrangler
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The Python import package remains `ranch`.
|
|
57
|
+
|
|
58
|
+
### Requirements
|
|
59
|
+
- Ranch requires user to install [SharedStreets' Node.js implementation](https://github.com/sharedstreets/sharedstreets-js#sharedstreets-nodejs--javascript), using the Docker installation. User will first install Docker on the machine, and then build SharedStreets image using this [Dockerfile](https://github.com/wsp-sag/Ranch/blob/develop/ranch/Dockerfile). See more instruction below.
|
|
60
|
+
|
|
61
|
+
- Ranch uses Python 3.7 and above. Runtime requirements are installed with the package. Development dependencies are managed by uv and can be installed with `uv sync`. Install the documentation dependencies as well with `uv sync --group doc`.
|
|
62
|
+
|
|
63
|
+
The intallation instructions use the [`conda`](https://conda.io/en/latest/) virtual environment manager and some use the ['git'](https://git-scm.com/downloads) version control software.
|
|
64
|
+
|
|
65
|
+
### Ranch Installation from GitHub
|
|
66
|
+
If you are managing multiple python versions, we suggest using [`virtualenv`](https://virtualenv.pypa.io/en/latest/) or [`conda`](https://conda.io/en/latest/) virtual environments. All commands should executed in a conda command prompt, not powershell or the system command prompt. Do not add conda to the system path during installation. This may cause problems with other programs that require python 2.7 to be placed in the system path.
|
|
67
|
+
|
|
68
|
+
Example using a conda environment and using the package manager [pip](https://pip.pypa.io/en/stable/) to install Ranch from the source on GitHub.
|
|
69
|
+
|
|
70
|
+
#### Basic Installation
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
conda config --add channels conda-forge
|
|
74
|
+
conda create python=3.7 rtree geopandas folium osmnx -n <my_ranch_environment>
|
|
75
|
+
conda activate <my_ranch_environment>
|
|
76
|
+
pip install git+https://github.com/wsp-sag/Ranch@master
|
|
77
|
+
```
|
|
78
|
+
Ranch can be installed in several ways depending on the user's needs. The above installation is the simplest method and is appropriate when the user does not anticipate needing to update Ranch. An update will require rebuilding the ranch environment. Installing from clone is slightly more involved and requires the user to have a git manager on their machine, but permits the user to install Ranch with the -e, edit, option so that their Ranch installation can be updated through pulling new commits from the Ranch repo without a full reinstallation.
|
|
79
|
+
|
|
80
|
+
Note: if you wanted to install from a specific tag/version number or branch, replace `@master` with `@<branchname>` or `@tag`
|
|
81
|
+
|
|
82
|
+
#### From Clone (Recommended for project team)
|
|
83
|
+
If you are going to be working on Ranch locally, you might want to clone it to your local machine and install it from the clone. The -e will install it in [editable mode](https://pip.pypa.io/en/stable/reference/pip_install/?highlight=editable#editable-installs).
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
conda config --add channels conda-forge
|
|
87
|
+
conda create python=3.7 rtree geopandas folium osmnx -n <my_ranch_environment>
|
|
88
|
+
conda activate <my_ranch_environment>
|
|
89
|
+
git clone -b develop https://github.com/wsp-sag/Ranch
|
|
90
|
+
cd Ranch
|
|
91
|
+
pip install -e .
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Note: if you are not part of the project team and want to contribute code bxack to the project, please fork before you clone and then add the original repository to your upstream origin list per [these directions on github](https://help.github.com/en/articles/fork-a-repo).
|
|
95
|
+
|
|
96
|
+
### Docker & SharedStreets
|
|
97
|
+
Before running Ranch, user need to install SharedStreets via Docker. The steps are as following:
|
|
98
|
+
|
|
99
|
+
1. Install Docker.
|
|
100
|
+
2. Open command line prompt, change base directory to the Ranch directory
|
|
101
|
+
```bash
|
|
102
|
+
cd path/to/your/ranch/directory/
|
|
103
|
+
```
|
|
104
|
+
3. Build SharedStreets image using this [Dockerfile](https://github.com/wsp-sag/Ranch/blob/develop/ranch/Dockerfile), name the local image as `shst`
|
|
105
|
+
```bash
|
|
106
|
+
cd ranch
|
|
107
|
+
docker build -t shst .
|
|
108
|
+
```
|
|
109
|
+
4. To test if SharedStreets image is built successfully, user can run the following to start a container node
|
|
110
|
+
```bash
|
|
111
|
+
docker run -it --rm -v /path/to/your/local/directory:/usr/node/ shst:latest /bin/bash
|
|
112
|
+
```
|
|
113
|
+
if succeeded, user can see a node being launched
|
|
114
|
+
|
|
115
|
+
## Documentation
|
|
116
|
+
|
|
117
|
+
Documentation is located at [https://wsp-sag.github.io/Ranch/](https://wsp-sag.github.io/Ranch/)
|
|
118
|
+
|
|
119
|
+
Edit the source of the documentation in the `/docs` folder.
|
|
120
|
+
|
|
121
|
+
To build the documentation locally, install its dependencies from the Ranch folder:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
uv sync --group doc
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
To build the documentation, navigate to the `/docs` folder and execute the command: `make html`
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
cd docs
|
|
131
|
+
make html
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Usage
|
|
135
|
+
|
|
136
|
+
To learn basic Ranch functionality, please refer to the following jupyter notebooks in the `/notebooks` directory:
|
|
137
|
+
|
|
138
|
+
- `Ranch-Demo.ipynb`
|
|
139
|
+
|
|
140
|
+
Jupyter notebooks can be started by activating the Ranch conda environment and typing `jupyter notebook`:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
conda activate <my_ranch_environment>
|
|
144
|
+
jupyter notebook
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Troubleshooting
|
|
148
|
+
|
|
149
|
+
**Issue: Conda is unable to install a library or to update to a specific library version**
|
|
150
|
+
Try installing libraries from conda-forge
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
conda install -c conda-forge *library*
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Issue: User does not have permission to install in directories**
|
|
157
|
+
Try running Anaconda Prompt as an administrator.
|
|
158
|
+
|
|
159
|
+
## Client Contact and Relationship
|
|
160
|
+
Before becoming `Ranch`, the `Standard Network Building Pipeline` consisted of a series of python notebooks, which have been implemented to build networks for regions including Minneapolis (Met Council), Bay Area (MTC), and Southeast Florida (SERPM). Those agencies all had different variations of the Standard Network Building Pipeline notebooks due to many reasons, e.g. steps in the pipeline have been getting revised and methods have been evolving, also agencies required different network features. However, the fundamental steps in the process are the same across regions. To standardize the network building process so that the same basic steps can be applied to any region, `Ranch` was created as a Python package that hosts universal network building steps. Our agency partners so far include Met Council, MTC, Miami-Dade TPO, and BART.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Ranch
|
|
2
|
+
This is the Python package for building standard roadway and transit networks from scratch. Before becoming `Ranch`, it was also referred to as the `Standard Network Building Pipeline`, which consisted of a series of Python notebooks.
|
|
3
|
+
|
|
4
|
+
It aims to have the following functionality:
|
|
5
|
+
|
|
6
|
+
1. build OSM-based roadway network in standard [`Network Wrangler`](https://github.com/wsp-sag/network_wrangler) format
|
|
7
|
+
2. build GTFS-based transit network in standard [`Network Wrangler`](https://github.com/wsp-sag/network_wrangler) format
|
|
8
|
+
3. build travel model centroid connectors
|
|
9
|
+
|
|
10
|
+
For the latest code developments, check out the `develop` branch.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
Install the published package with `uv`:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
uv add ranch-network-wrangler
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or install it with pip:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
python -m pip install ranch-network-wrangler
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The Python import package remains `ranch`.
|
|
27
|
+
|
|
28
|
+
### Requirements
|
|
29
|
+
- Ranch requires user to install [SharedStreets' Node.js implementation](https://github.com/sharedstreets/sharedstreets-js#sharedstreets-nodejs--javascript), using the Docker installation. User will first install Docker on the machine, and then build SharedStreets image using this [Dockerfile](https://github.com/wsp-sag/Ranch/blob/develop/ranch/Dockerfile). See more instruction below.
|
|
30
|
+
|
|
31
|
+
- Ranch uses Python 3.7 and above. Runtime requirements are installed with the package. Development dependencies are managed by uv and can be installed with `uv sync`. Install the documentation dependencies as well with `uv sync --group doc`.
|
|
32
|
+
|
|
33
|
+
The intallation instructions use the [`conda`](https://conda.io/en/latest/) virtual environment manager and some use the ['git'](https://git-scm.com/downloads) version control software.
|
|
34
|
+
|
|
35
|
+
### Ranch Installation from GitHub
|
|
36
|
+
If you are managing multiple python versions, we suggest using [`virtualenv`](https://virtualenv.pypa.io/en/latest/) or [`conda`](https://conda.io/en/latest/) virtual environments. All commands should executed in a conda command prompt, not powershell or the system command prompt. Do not add conda to the system path during installation. This may cause problems with other programs that require python 2.7 to be placed in the system path.
|
|
37
|
+
|
|
38
|
+
Example using a conda environment and using the package manager [pip](https://pip.pypa.io/en/stable/) to install Ranch from the source on GitHub.
|
|
39
|
+
|
|
40
|
+
#### Basic Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
conda config --add channels conda-forge
|
|
44
|
+
conda create python=3.7 rtree geopandas folium osmnx -n <my_ranch_environment>
|
|
45
|
+
conda activate <my_ranch_environment>
|
|
46
|
+
pip install git+https://github.com/wsp-sag/Ranch@master
|
|
47
|
+
```
|
|
48
|
+
Ranch can be installed in several ways depending on the user's needs. The above installation is the simplest method and is appropriate when the user does not anticipate needing to update Ranch. An update will require rebuilding the ranch environment. Installing from clone is slightly more involved and requires the user to have a git manager on their machine, but permits the user to install Ranch with the -e, edit, option so that their Ranch installation can be updated through pulling new commits from the Ranch repo without a full reinstallation.
|
|
49
|
+
|
|
50
|
+
Note: if you wanted to install from a specific tag/version number or branch, replace `@master` with `@<branchname>` or `@tag`
|
|
51
|
+
|
|
52
|
+
#### From Clone (Recommended for project team)
|
|
53
|
+
If you are going to be working on Ranch locally, you might want to clone it to your local machine and install it from the clone. The -e will install it in [editable mode](https://pip.pypa.io/en/stable/reference/pip_install/?highlight=editable#editable-installs).
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
conda config --add channels conda-forge
|
|
57
|
+
conda create python=3.7 rtree geopandas folium osmnx -n <my_ranch_environment>
|
|
58
|
+
conda activate <my_ranch_environment>
|
|
59
|
+
git clone -b develop https://github.com/wsp-sag/Ranch
|
|
60
|
+
cd Ranch
|
|
61
|
+
pip install -e .
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Note: if you are not part of the project team and want to contribute code bxack to the project, please fork before you clone and then add the original repository to your upstream origin list per [these directions on github](https://help.github.com/en/articles/fork-a-repo).
|
|
65
|
+
|
|
66
|
+
### Docker & SharedStreets
|
|
67
|
+
Before running Ranch, user need to install SharedStreets via Docker. The steps are as following:
|
|
68
|
+
|
|
69
|
+
1. Install Docker.
|
|
70
|
+
2. Open command line prompt, change base directory to the Ranch directory
|
|
71
|
+
```bash
|
|
72
|
+
cd path/to/your/ranch/directory/
|
|
73
|
+
```
|
|
74
|
+
3. Build SharedStreets image using this [Dockerfile](https://github.com/wsp-sag/Ranch/blob/develop/ranch/Dockerfile), name the local image as `shst`
|
|
75
|
+
```bash
|
|
76
|
+
cd ranch
|
|
77
|
+
docker build -t shst .
|
|
78
|
+
```
|
|
79
|
+
4. To test if SharedStreets image is built successfully, user can run the following to start a container node
|
|
80
|
+
```bash
|
|
81
|
+
docker run -it --rm -v /path/to/your/local/directory:/usr/node/ shst:latest /bin/bash
|
|
82
|
+
```
|
|
83
|
+
if succeeded, user can see a node being launched
|
|
84
|
+
|
|
85
|
+
## Documentation
|
|
86
|
+
|
|
87
|
+
Documentation is located at [https://wsp-sag.github.io/Ranch/](https://wsp-sag.github.io/Ranch/)
|
|
88
|
+
|
|
89
|
+
Edit the source of the documentation in the `/docs` folder.
|
|
90
|
+
|
|
91
|
+
To build the documentation locally, install its dependencies from the Ranch folder:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
uv sync --group doc
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
To build the documentation, navigate to the `/docs` folder and execute the command: `make html`
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
cd docs
|
|
101
|
+
make html
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Usage
|
|
105
|
+
|
|
106
|
+
To learn basic Ranch functionality, please refer to the following jupyter notebooks in the `/notebooks` directory:
|
|
107
|
+
|
|
108
|
+
- `Ranch-Demo.ipynb`
|
|
109
|
+
|
|
110
|
+
Jupyter notebooks can be started by activating the Ranch conda environment and typing `jupyter notebook`:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
conda activate <my_ranch_environment>
|
|
114
|
+
jupyter notebook
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Troubleshooting
|
|
118
|
+
|
|
119
|
+
**Issue: Conda is unable to install a library or to update to a specific library version**
|
|
120
|
+
Try installing libraries from conda-forge
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
conda install -c conda-forge *library*
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Issue: User does not have permission to install in directories**
|
|
127
|
+
Try running Anaconda Prompt as an administrator.
|
|
128
|
+
|
|
129
|
+
## Client Contact and Relationship
|
|
130
|
+
Before becoming `Ranch`, the `Standard Network Building Pipeline` consisted of a series of python notebooks, which have been implemented to build networks for regions including Minneapolis (Met Council), Bay Area (MTC), and Southeast Florida (SERPM). Those agencies all had different variations of the Standard Network Building Pipeline notebooks due to many reasons, e.g. steps in the pipeline have been getting revised and methods have been evolving, also agencies required different network features. However, the fundamental steps in the process are the same across regions. To standardize the network building process so that the same basic steps can be applied to any region, `Ranch` was created as a Python package that hosts universal network building steps. Our agency partners so far include Met Council, MTC, Miami-Dade TPO, and BART.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ranch-network-wrangler"
|
|
7
|
+
version = "0.0.1"
|
|
8
|
+
description = "A Python package for making travel model networks"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.7"
|
|
11
|
+
license = "Apache-2.0"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 1 - Planning",
|
|
15
|
+
"Natural Language :: English",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
"Programming Language :: Python",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.7",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"docker",
|
|
23
|
+
"numpy",
|
|
24
|
+
"pandas>1.0",
|
|
25
|
+
"geopandas>=0.8.0",
|
|
26
|
+
"networkx",
|
|
27
|
+
"osmnx",
|
|
28
|
+
"partridge>=1.1",
|
|
29
|
+
"peartree",
|
|
30
|
+
"pyproj",
|
|
31
|
+
"scipy",
|
|
32
|
+
"shapely",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[dependency-groups]
|
|
36
|
+
dev = [
|
|
37
|
+
"geojson",
|
|
38
|
+
"jsonschema",
|
|
39
|
+
"folium",
|
|
40
|
+
"black",
|
|
41
|
+
"isort",
|
|
42
|
+
"pytest",
|
|
43
|
+
"jupyter",
|
|
44
|
+
"notebook",
|
|
45
|
+
"pytest-notebook",
|
|
46
|
+
]
|
|
47
|
+
doc = [
|
|
48
|
+
"recommonmark",
|
|
49
|
+
"sphinx",
|
|
50
|
+
"sphinx-autodoc-typehints",
|
|
51
|
+
"sphinx-rtd-theme",
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
[project.urls]
|
|
55
|
+
Homepage = "https://github.com/network-wrangler/Ranch"
|
|
56
|
+
Repository = "https://github.com/network-wrangler/Ranch"
|
|
57
|
+
Documentation = "https://wsp-sag.github.io/Ranch/"
|
|
58
|
+
|
|
59
|
+
[tool.setuptools]
|
|
60
|
+
packages = ["ranch"]
|
|
61
|
+
include-package-data = true
|
|
62
|
+
|
|
63
|
+
[tool.uv]
|
|
64
|
+
default-groups = ["dev"]
|
|
65
|
+
|
|
66
|
+
[[tool.uv.index]]
|
|
67
|
+
name = "testpypi"
|
|
68
|
+
url = "https://test.pypi.org/simple/"
|
|
69
|
+
publish-url = "https://test.pypi.org/legacy/"
|
|
70
|
+
explicit = true
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
__version__ = "0.0.1"
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
|
|
6
|
+
from .logger import RanchLogger, setupLogging
|
|
7
|
+
from .osm import run_osmnx_extraction
|
|
8
|
+
from .parameters import Parameters
|
|
9
|
+
from .roadway import Roadway
|
|
10
|
+
from .sharedstreets import read_shst_extraction, run_shst_extraction, run_shst_match
|
|
11
|
+
from .transit import Transit
|
|
12
|
+
from .utils import link_df_to_geojson, point_df_to_geojson
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"RanchLogger",
|
|
16
|
+
"setupLogging",
|
|
17
|
+
"Roadway",
|
|
18
|
+
"run_shst_extraction",
|
|
19
|
+
"read_shst_extraction",
|
|
20
|
+
"run_shst_match",
|
|
21
|
+
"run_osmnx_extraction",
|
|
22
|
+
"link_df_to_geojson",
|
|
23
|
+
"point_df_to_geojson",
|
|
24
|
+
"Parameters",
|
|
25
|
+
"Transit",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
setupLogging(
|
|
29
|
+
log_filename=os.path.join(
|
|
30
|
+
os.getcwd(),
|
|
31
|
+
"ranch_{}.log".format(datetime.now().strftime("%Y_%m_%d__%H_%M_%S")),
|
|
32
|
+
),
|
|
33
|
+
log_to_console=True,
|
|
34
|
+
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
# Utility functions for logging
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
__all__ = ["RanchLogger", "setupLogging"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# for all the Wrangler logging needs!
|
|
13
|
+
RanchLogger = logging.getLogger("RanchLogger")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def setupLogging(
|
|
17
|
+
level: int = None, log_filename: str = None, log_to_console: bool = False
|
|
18
|
+
):
|
|
19
|
+
"""
|
|
20
|
+
Sets up the RanchLogger w.r.t. the debug file location and if logging to console.
|
|
21
|
+
|
|
22
|
+
args:
|
|
23
|
+
level: the level of logging that will be recorded
|
|
24
|
+
log_filename: the location of the log file that will get created to add the DEBUG log
|
|
25
|
+
log_to_console: if True, logging will go to the console at INFO level
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
if level is None:
|
|
29
|
+
RanchLogger.setLevel(logging.DEBUG)
|
|
30
|
+
else:
|
|
31
|
+
RanchLogger.setLevel(level)
|
|
32
|
+
|
|
33
|
+
FORMAT = logging.Formatter(
|
|
34
|
+
"%(asctime)-15s %(levelname)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S,"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if log_filename:
|
|
38
|
+
file_handler = logging.FileHandler(log_filename)
|
|
39
|
+
file_handler.setLevel(logging.DEBUG)
|
|
40
|
+
file_handler.setFormatter(FORMAT)
|
|
41
|
+
RanchLogger.addHandler(file_handler)
|
|
42
|
+
|
|
43
|
+
if log_to_console:
|
|
44
|
+
console_handler = logging.StreamHandler(sys.stdout)
|
|
45
|
+
console_handler.setLevel(logging.INFO)
|
|
46
|
+
console_handler.setFormatter(FORMAT)
|
|
47
|
+
RanchLogger.addHandler(console_handler)
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
import geopandas as gpd
|
|
5
|
+
import networkx as nx
|
|
6
|
+
import osmnx as ox
|
|
7
|
+
import pandas as pd
|
|
8
|
+
from pyproj import CRS
|
|
9
|
+
|
|
10
|
+
from .logger import RanchLogger
|
|
11
|
+
from .parameters import standard_crs, alt_standard_crs
|
|
12
|
+
from .utils import link_df_to_geojson, point_df_to_geojson
|
|
13
|
+
|
|
14
|
+
__all__ = ["run_osmnx_extraction"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def run_osmnx_extraction(input_polygon_file: str, output_dir: str):
|
|
18
|
+
"""
|
|
19
|
+
run osmnx extraction with input polygon
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
input_area_polygon_file: input polygon file that defines the extract region
|
|
23
|
+
output_extraction_file: output file that stores the extraction
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
if not input_polygon_file:
|
|
27
|
+
msg = "Missing polygon file for sharedstreet extraction."
|
|
28
|
+
RanchLogger.error(msg)
|
|
29
|
+
raise ValueError(msg)
|
|
30
|
+
|
|
31
|
+
if not output_dir:
|
|
32
|
+
msg = "Please specify output filename for extraction result."
|
|
33
|
+
RanchLogger.error(msg)
|
|
34
|
+
raise ValueError(msg)
|
|
35
|
+
|
|
36
|
+
if input_polygon_file:
|
|
37
|
+
filename, file_extension = os.path.splitext(input_polygon_file)
|
|
38
|
+
if file_extension in [".shp", ".geojson"]:
|
|
39
|
+
polygon_gdf = gpd.read_file(input_polygon_file)
|
|
40
|
+
|
|
41
|
+
else:
|
|
42
|
+
msg = "Invalid boundary file, should be .shp or .geojson"
|
|
43
|
+
RanchLogger.error(msg)
|
|
44
|
+
raise ValueError(msg)
|
|
45
|
+
|
|
46
|
+
# avoid conversion between WGS lat-long and NAD lat-long
|
|
47
|
+
if polygon_gdf.crs == alt_standard_crs:
|
|
48
|
+
polygon_gdf.crs = standard_crs
|
|
49
|
+
|
|
50
|
+
# convert to lat-long
|
|
51
|
+
polygon_gdf = polygon_gdf.to_crs(standard_crs)
|
|
52
|
+
|
|
53
|
+
boundary = polygon_gdf.geometry.unary_union
|
|
54
|
+
|
|
55
|
+
# OSM extraction
|
|
56
|
+
G_drive = ox.graph_from_polygon(boundary, network_type="all", simplify=False)
|
|
57
|
+
|
|
58
|
+
link_gdf = ox.graph_to_gdfs(G_drive, nodes=False, edges=True)
|
|
59
|
+
node_gdf = ox.graph_to_gdfs(G_drive, nodes=True, edges=False)
|
|
60
|
+
|
|
61
|
+
# write out osm extraction
|
|
62
|
+
link_prop = link_gdf.drop("geometry", axis=1).columns.tolist()
|
|
63
|
+
link_geojson = link_df_to_geojson(link_gdf, link_prop)
|
|
64
|
+
|
|
65
|
+
with open(os.path.join(output_dir, "link.geojson"), "w") as f:
|
|
66
|
+
json.dump(link_geojson, f)
|
|
67
|
+
|
|
68
|
+
node_prop = node_gdf.drop("geometry", axis=1).columns.tolist()
|
|
69
|
+
node_geojson = point_df_to_geojson(node_gdf, node_prop)
|
|
70
|
+
|
|
71
|
+
with open(os.path.join(output_dir, "node.geojson"), "w") as f:
|
|
72
|
+
json.dump(node_geojson, f)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def add_two_way_osm(link_gdf, osmnx_link):
|
|
76
|
+
"""
|
|
77
|
+
for osm with oneway = False, add the reverse direction to complete
|
|
78
|
+
|
|
79
|
+
Parameters
|
|
80
|
+
------------
|
|
81
|
+
osm link from shst extraction, plus shst info
|
|
82
|
+
|
|
83
|
+
return
|
|
84
|
+
------------
|
|
85
|
+
complete osm link
|
|
86
|
+
"""
|
|
87
|
+
osm_link_gdf = link_gdf.copy()
|
|
88
|
+
osm_link_gdf["wayId"] = osm_link_gdf["wayId"].astype(int)
|
|
89
|
+
osm_link_gdf.drop("name", axis=1, inplace=True)
|
|
90
|
+
|
|
91
|
+
osmnx_link_gdf = osmnx_link.copy()
|
|
92
|
+
|
|
93
|
+
osmnx_link_gdf.drop_duplicates(subset=["osmid"], inplace=True)
|
|
94
|
+
osmnx_link_gdf.drop(["length", "u", "v", "geometry"], axis=1, inplace=True)
|
|
95
|
+
|
|
96
|
+
RanchLogger.info(
|
|
97
|
+
"shst extraction has {} geometries".format(osm_link_gdf.id.nunique())
|
|
98
|
+
)
|
|
99
|
+
RanchLogger.info("shst extraction has {} osm links".format(osm_link_gdf.shape[0]))
|
|
100
|
+
|
|
101
|
+
osm_link_gdf["u"] = osm_link_gdf.nodeIds.apply(lambda x: int(x[0]))
|
|
102
|
+
osm_link_gdf["v"] = osm_link_gdf.nodeIds.apply(lambda x: int(x[-1]))
|
|
103
|
+
|
|
104
|
+
RanchLogger.info("---joining osm shst with osmnx data---")
|
|
105
|
+
osm_link_gdf = pd.merge(
|
|
106
|
+
osm_link_gdf, osmnx_link_gdf, left_on=["wayId"], right_on=["osmid"], how="left"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
reverse_osm_link_gdf = osm_link_gdf[
|
|
110
|
+
(osm_link_gdf.oneWay == False)
|
|
111
|
+
& (osm_link_gdf.forwardReferenceId != osm_link_gdf.backReferenceId)
|
|
112
|
+
& (osm_link_gdf.u != osm_link_gdf.v)
|
|
113
|
+
].copy()
|
|
114
|
+
|
|
115
|
+
RanchLogger.info(
|
|
116
|
+
"shst extraction has {} two-way osm links".format(reverse_osm_link_gdf.shape[0])
|
|
117
|
+
)
|
|
118
|
+
RanchLogger.info(
|
|
119
|
+
"and they are {} geometrys".format(reverse_osm_link_gdf.id.nunique())
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
reverse_osm_link_gdf.rename(
|
|
123
|
+
columns={
|
|
124
|
+
"u": "v",
|
|
125
|
+
"v": "u",
|
|
126
|
+
"forwardReferenceId": "backReferenceId",
|
|
127
|
+
"backReferenceId": "forwardReferenceId",
|
|
128
|
+
"fromIntersectionId": "toIntersectionId",
|
|
129
|
+
"toIntersectionId": "fromIntersectionId",
|
|
130
|
+
},
|
|
131
|
+
inplace=True,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
reverse_osm_link_gdf["reverse_out"] = 1
|
|
135
|
+
|
|
136
|
+
osm_link_gdf = pd.concat(
|
|
137
|
+
[osm_link_gdf, reverse_osm_link_gdf], sort=False, ignore_index=True
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
osm_link_gdf.rename(
|
|
141
|
+
columns={
|
|
142
|
+
"forwardReferenceId": "shstReferenceId",
|
|
143
|
+
"geometryId": "shstGeometryId",
|
|
144
|
+
},
|
|
145
|
+
inplace=True,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
osm_link_gdf.drop("backReferenceId", axis=1, inplace=True)
|
|
149
|
+
|
|
150
|
+
RanchLogger.info(
|
|
151
|
+
"after join, ther are {} osm links from shst extraction, \
|
|
152
|
+
out of which there are {} links that do not have osm info, \
|
|
153
|
+
due to shst extraction (default tile 181224) contains {} osm ids that are not included in latest OSM extraction, \
|
|
154
|
+
e.g. private streets, closed streets.".format(
|
|
155
|
+
len(osm_link_gdf),
|
|
156
|
+
len(osm_link_gdf[osm_link_gdf.osmid.isnull()]),
|
|
157
|
+
osm_link_gdf[osm_link_gdf.osmid.isnull()].wayId.nunique(),
|
|
158
|
+
)
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
RanchLogger.info(
|
|
162
|
+
"after join, there are {} shst referencies".format(
|
|
163
|
+
osm_link_gdf.groupby(["shstReferenceId", "shstGeometryId"]).count().shape[0]
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
return osm_link_gdf
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def highway_attribute_list_to_value(x, highway_to_roadway_dict, roadway_hierarchy_dict):
|
|
171
|
+
"""
|
|
172
|
+
clean up osm highway, and map to standard roadway
|
|
173
|
+
"""
|
|
174
|
+
if type(x.highway) == list:
|
|
175
|
+
value_list = list(set([highway_to_roadway_dict[c] for c in x.highway]))
|
|
176
|
+
if len(value_list) == 1:
|
|
177
|
+
if value_list[0] != "":
|
|
178
|
+
return value_list[0]
|
|
179
|
+
else:
|
|
180
|
+
if type(x.roadClass) == list:
|
|
181
|
+
return highway_to_roadway_dict[x.roadClass[0].lower()]
|
|
182
|
+
else:
|
|
183
|
+
return highway_to_roadway_dict[x.roadClass.lower()]
|
|
184
|
+
|
|
185
|
+
else:
|
|
186
|
+
ret_val = value_list[0]
|
|
187
|
+
ret_val_level = roadway_hierarchy_dict[ret_val]
|
|
188
|
+
for c in value_list:
|
|
189
|
+
val_level = roadway_hierarchy_dict[c]
|
|
190
|
+
if val_level < ret_val_level:
|
|
191
|
+
ret_val = c
|
|
192
|
+
ret_val_level = val_level
|
|
193
|
+
else:
|
|
194
|
+
continue
|
|
195
|
+
return ret_val
|
|
196
|
+
else:
|
|
197
|
+
if x.highway == "":
|
|
198
|
+
return highway_to_roadway_dict[x.roadClass.lower()]
|
|
199
|
+
else:
|
|
200
|
+
return highway_to_roadway_dict[x.highway]
|