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.
@@ -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]