r5py 0.1.1.dev0__tar.gz → 0.1.2__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.
Potentially problematic release.
This version of r5py might be problematic. Click here for more details.
- {r5py-0.1.1.dev0/src/r5py.egg-info → r5py-0.1.2}/PKG-INFO +42 -4
- {r5py-0.1.1.dev0 → r5py-0.1.2}/pyproject.toml +11 -8
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/__init__.py +2 -1
- r5py-0.1.2/src/r5py/__main__.py +3 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/__init__.py +14 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/base_travel_time_matrix_computer.py +4 -5
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/detailed_itineraries_computer.py +6 -10
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/direct_leg.py +1 -3
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/regional_task.py +44 -38
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/street_layer.py +1 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/transfer_leg.py +2 -6
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/transit_layer.py +2 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/transit_leg.py +1 -5
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/transport_mode.py +5 -3
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/transport_network.py +26 -11
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/travel_time_matrix_computer.py +4 -15
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/trip.py +8 -4
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/trip_leg.py +44 -5
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/trip_planner.py +81 -39
- r5py-0.1.2/src/r5py/sampledata/_keep/__init__.py +3 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/__init__.py +2 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/classpath.py +9 -5
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/config.py +21 -2
- r5py-0.1.2/src/r5py/util/environment.py +34 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/good_enough_equidistant_crs.py +0 -1
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/memory_footprint.py +3 -5
- r5py-0.1.2/src/r5py/util/sample_data_set.py +74 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/validating_requests_session.py +2 -2
- {r5py-0.1.1.dev0 → r5py-0.1.2/src/r5py.egg-info}/PKG-INFO +42 -4
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py.egg-info/SOURCES.txt +4 -2
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py.egg-info/requires.txt +12 -5
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_breakdownstats.py +1 -1
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_camel_to_snake_case.py +1 -1
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_classpath.py +1 -1
- r5py-0.1.2/tests/test_config.py +27 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_contains_gtfs_data.py +4 -3
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_data_validation.py +5 -4
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_detailed_itineraries_computer.py +37 -49
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_java_casting.py +1 -1
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_memory_footprint.py +1 -1
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_regional_task.py +1 -1
- r5py-0.1.1.dev0/tests/test_data_set.py → r5py-0.1.2/tests/test_sample_data_set.py +9 -6
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_snake_to_camel_case.py +1 -1
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_transport_mode.py +1 -1
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_transport_network.py +41 -12
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_travel_time_matrix_computer.py +36 -26
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_validating_request_session.py +19 -13
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_verbose_warnings.py +10 -4
- r5py-0.1.1.dev0/src/r5py/__main__.py +0 -16
- r5py-0.1.1.dev0/src/r5py/util/data_set.py +0 -74
- r5py-0.1.1.dev0/tests/test_config.py +0 -14
- {r5py-0.1.1.dev0 → r5py-0.1.2}/LICENSE +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/README.md +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/setup.cfg +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/access_leg.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/breakdown_stat.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/egress_leg.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/r5/scenario.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/camel_to_snake_case.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/contains_gtfs_data.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/data_validation.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/exceptions.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/jvm.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/parse_int_date.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/snake_to_camel_case.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py/util/warnings.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py.egg-info/dependency_links.txt +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/src/r5py.egg-info/top_level.txt +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_deterministic_behaviour.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_good_enough_equidistant_crs.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_parse_int_date.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_street_layer.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_transit_layer.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_trip.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_trip_leg.py +0 -0
- {r5py-0.1.1.dev0 → r5py-0.1.2}/tests/test_trip_planner.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: r5py
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Python wrapper for the R5 routing analysis engine
|
|
5
5
|
Author: Willem Klumpenhouwer, Marcus Sairava, Rafael Pereira, Henrikki Tenkanen
|
|
6
6
|
Author-email: Christoph Fink <christoph.fink@helsinki.fi>
|
|
@@ -14,11 +14,49 @@ Classifier: Programming Language :: Python :: 3
|
|
|
14
14
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
15
15
|
Classifier: License :: OSI Approved :: MIT License
|
|
16
16
|
Classifier: Operating System :: OS Independent
|
|
17
|
-
Requires-Python: >=3.
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
|
-
Provides-Extra: doc
|
|
20
|
-
Provides-Extra: test
|
|
21
19
|
License-File: LICENSE
|
|
20
|
+
Requires-Dist: ConfigArgParse
|
|
21
|
+
Requires-Dist: filelock
|
|
22
|
+
Requires-Dist: fiona
|
|
23
|
+
Requires-Dist: geopandas
|
|
24
|
+
Requires-Dist: importlib_resources
|
|
25
|
+
Requires-Dist: joblib
|
|
26
|
+
Requires-Dist: jpype1
|
|
27
|
+
Requires-Dist: numpy
|
|
28
|
+
Requires-Dist: pandas>=2.1.0
|
|
29
|
+
Requires-Dist: psutil
|
|
30
|
+
Requires-Dist: pyproj
|
|
31
|
+
Requires-Dist: requests
|
|
32
|
+
Requires-Dist: shapely>=2.0
|
|
33
|
+
Provides-Extra: docs
|
|
34
|
+
Requires-Dist: contextily; extra == "docs"
|
|
35
|
+
Requires-Dist: folium; extra == "docs"
|
|
36
|
+
Requires-Dist: GitPython; extra == "docs"
|
|
37
|
+
Requires-Dist: h3>=4.0.0b2; extra == "docs"
|
|
38
|
+
Requires-Dist: jupyterlab_myst; extra == "docs"
|
|
39
|
+
Requires-Dist: mapclassify; extra == "docs"
|
|
40
|
+
Requires-Dist: matplotlib; extra == "docs"
|
|
41
|
+
Requires-Dist: myst-nb; extra == "docs"
|
|
42
|
+
Requires-Dist: nbsphinx; extra == "docs"
|
|
43
|
+
Requires-Dist: pybtex-apa7-style; extra == "docs"
|
|
44
|
+
Requires-Dist: r5py.sampledata.helsinki>=0.1.1; extra == "docs"
|
|
45
|
+
Requires-Dist: r5py.sampledata.sao_paulo>=0.1.1; extra == "docs"
|
|
46
|
+
Requires-Dist: shapely; extra == "docs"
|
|
47
|
+
Requires-Dist: sphinx; extra == "docs"
|
|
48
|
+
Requires-Dist: sphinx-book-theme; extra == "docs"
|
|
49
|
+
Requires-Dist: sphinx-design; extra == "docs"
|
|
50
|
+
Requires-Dist: sphinxcontrib-bibtex; extra == "docs"
|
|
51
|
+
Requires-Dist: sphinxcontrib-images; extra == "docs"
|
|
52
|
+
Provides-Extra: tests
|
|
53
|
+
Requires-Dist: pyarrow; extra == "tests"
|
|
54
|
+
Requires-Dist: pytest; extra == "tests"
|
|
55
|
+
Requires-Dist: pytest-asyncio; extra == "tests"
|
|
56
|
+
Requires-Dist: pytest-cov; extra == "tests"
|
|
57
|
+
Requires-Dist: pytest-lazy-fixtures; extra == "tests"
|
|
58
|
+
Requires-Dist: r5py.sampledata.helsinki>=0.1.1; extra == "tests"
|
|
59
|
+
Requires-Dist: r5py.sampledata.sao_paulo>=0.1.1; extra == "tests"
|
|
22
60
|
|
|
23
61
|
<img class="r5py_logo" align="right" src="https://github.com/r5py/r5py/raw/main/docs/_static/images/r5py_blue.svg" alt="r5py logo" style="width:180px; max-width:30vW;">
|
|
24
62
|
|
|
@@ -24,13 +24,13 @@ dependencies = [
|
|
|
24
24
|
"joblib",
|
|
25
25
|
"jpype1",
|
|
26
26
|
"numpy",
|
|
27
|
-
"pandas",
|
|
27
|
+
"pandas>=2.1.0",
|
|
28
28
|
"psutil",
|
|
29
29
|
"pyproj",
|
|
30
30
|
"requests",
|
|
31
31
|
"shapely>=2.0"
|
|
32
32
|
]
|
|
33
|
-
requires-python = ">=3.
|
|
33
|
+
requires-python = ">=3.9"
|
|
34
34
|
|
|
35
35
|
classifiers = [
|
|
36
36
|
"Programming Language :: Python :: 3",
|
|
@@ -44,11 +44,15 @@ license = {text = "GPL-3.0-or-later or MIT"}
|
|
|
44
44
|
dynamic = ["version"]
|
|
45
45
|
|
|
46
46
|
[project.optional-dependencies]
|
|
47
|
-
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
|
|
47
|
+
docs = ["contextily", "folium", "GitPython", "h3>=4.0.0b2", "jupyterlab_myst",
|
|
48
|
+
"mapclassify", "matplotlib", "myst-nb", "nbsphinx", "pybtex-apa7-style",
|
|
49
|
+
"r5py.sampledata.helsinki>=0.1.1", "r5py.sampledata.sao_paulo>=0.1.1",
|
|
50
|
+
"shapely", "sphinx", "sphinx-book-theme", "sphinx-design",
|
|
51
|
+
"sphinxcontrib-bibtex", "sphinxcontrib-images"]
|
|
52
|
+
tests = ["pyarrow", "pytest", "pytest-asyncio", "pytest-cov",
|
|
53
|
+
"pytest-lazy-fixtures", "r5py.sampledata.helsinki>=0.1.1",
|
|
54
|
+
"r5py.sampledata.sao_paulo>=0.1.1"]
|
|
55
|
+
|
|
52
56
|
|
|
53
57
|
[project.urls]
|
|
54
58
|
Documentation = "https://r5py.readthedocs.org/"
|
|
@@ -70,7 +74,6 @@ filterwarnings = [
|
|
|
70
74
|
"ignore:Could not find R5 jar, trying to download it from upstream",
|
|
71
75
|
"ignore:Successfully downloaded r5-"
|
|
72
76
|
]
|
|
73
|
-
pythonpath = ["src"]
|
|
74
77
|
testpaths = ["tests"]
|
|
75
78
|
asyncio_mode = "auto"
|
|
76
79
|
|
|
@@ -2,23 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
"""R5 classes."""
|
|
4
4
|
|
|
5
|
+
from .access_leg import AccessLeg
|
|
5
6
|
from .breakdown_stat import BreakdownStat
|
|
6
7
|
from .detailed_itineraries_computer import DetailedItinerariesComputer
|
|
8
|
+
from .direct_leg import DirectLeg
|
|
9
|
+
from .egress_leg import EgressLeg
|
|
7
10
|
from .regional_task import RegionalTask
|
|
8
11
|
from .scenario import Scenario
|
|
9
12
|
from .street_layer import StreetLayer
|
|
13
|
+
from .transfer_leg import TransferLeg
|
|
14
|
+
from .transit_leg import TransitLeg
|
|
10
15
|
from .transport_mode import TransportMode
|
|
11
16
|
from .transport_network import TransportNetwork
|
|
12
17
|
from .travel_time_matrix_computer import TravelTimeMatrixComputer
|
|
18
|
+
from .trip import Trip
|
|
19
|
+
from .trip_planner import TripPlanner
|
|
13
20
|
|
|
14
21
|
__all__ = [
|
|
22
|
+
"AccessLeg",
|
|
15
23
|
"BreakdownStat",
|
|
16
24
|
"DetailedItinerariesComputer",
|
|
25
|
+
"DirectLeg",
|
|
26
|
+
"EgressLeg",
|
|
17
27
|
"RegionalTask",
|
|
18
28
|
"Scenario",
|
|
19
29
|
"SpeedConfig",
|
|
20
30
|
"StreetLayer",
|
|
31
|
+
"TransferLeg",
|
|
32
|
+
"TransitLeg",
|
|
21
33
|
"TransportMode",
|
|
22
34
|
"TransportNetwork",
|
|
23
35
|
"TravelTimeMatrixComputer",
|
|
36
|
+
"Trip",
|
|
37
|
+
"TripPlanner",
|
|
24
38
|
]
|
|
@@ -91,6 +91,7 @@ class BaseTravelTimeMatrixComputer:
|
|
|
91
91
|
|
|
92
92
|
@property
|
|
93
93
|
def destinations(self):
|
|
94
|
+
"""The destinations of this travel time matrix (`geopandas.GeoDataFrame`)."""
|
|
94
95
|
return self._destinations
|
|
95
96
|
|
|
96
97
|
@destinations.setter
|
|
@@ -117,13 +118,10 @@ class BaseTravelTimeMatrixComputer:
|
|
|
117
118
|
pandas.DataFrame
|
|
118
119
|
Data frame in which all MAX_INT32 have been replaced by `numpy.nan`.
|
|
119
120
|
"""
|
|
120
|
-
return data_set.
|
|
121
|
+
return data_set.map(lambda x: numpy.nan if x == MAX_INT32 else x)
|
|
121
122
|
|
|
122
123
|
def _prepare_origins_destinations(self):
|
|
123
|
-
"""
|
|
124
|
-
Make sure we received enough information to route from origins to
|
|
125
|
-
destinations.
|
|
126
|
-
"""
|
|
124
|
+
"""Make sure we received enough information to route from origins to destinations."""
|
|
127
125
|
try:
|
|
128
126
|
self.origins
|
|
129
127
|
except AttributeError as exception:
|
|
@@ -165,6 +163,7 @@ class BaseTravelTimeMatrixComputer:
|
|
|
165
163
|
|
|
166
164
|
@property
|
|
167
165
|
def origins(self):
|
|
166
|
+
"""The origins of this travel time matrix (`geopandas.GeoDataFrame`)."""
|
|
168
167
|
return self._origins
|
|
169
168
|
|
|
170
169
|
@origins.setter
|
|
@@ -124,7 +124,6 @@ class DetailedItinerariesComputer(BaseTravelTimeMatrixComputer):
|
|
|
124
124
|
route number or name), `geometry` (`shapely.LineString`)
|
|
125
125
|
TODO: Add description of output data frame columns and format
|
|
126
126
|
"""
|
|
127
|
-
|
|
128
127
|
self._prepare_origins_destinations()
|
|
129
128
|
|
|
130
129
|
# warn if public transport routes are requested, but R5 has been
|
|
@@ -150,11 +149,12 @@ class DetailedItinerariesComputer(BaseTravelTimeMatrixComputer):
|
|
|
150
149
|
verbose=(10 * self.verbose), # joblib has a funny verbosity scale
|
|
151
150
|
n_jobs=self.NUM_THREADS,
|
|
152
151
|
) as parallel:
|
|
152
|
+
matrices = parallel(
|
|
153
|
+
joblib.delayed(self._travel_details_per_od_pair)(from_id, to_id)
|
|
154
|
+
for _, (from_id, to_id) in self.od_pairs.iterrows()
|
|
155
|
+
)
|
|
153
156
|
od_matrix = pandas.concat(
|
|
154
|
-
|
|
155
|
-
joblib.delayed(self._travel_details_per_od_pair)(from_id, to_id)
|
|
156
|
-
for _, (from_id, to_id) in self.od_pairs.iterrows()
|
|
157
|
-
),
|
|
157
|
+
[matrix.astype(matrices[0].dtypes) for matrix in matrices],
|
|
158
158
|
ignore_index=True,
|
|
159
159
|
)
|
|
160
160
|
|
|
@@ -162,11 +162,7 @@ class DetailedItinerariesComputer(BaseTravelTimeMatrixComputer):
|
|
|
162
162
|
return od_matrix
|
|
163
163
|
|
|
164
164
|
def _prepare_origins_destinations(self):
|
|
165
|
-
"""
|
|
166
|
-
Make sure we received enough information to route from origins to
|
|
167
|
-
destinations.
|
|
168
|
-
"""
|
|
169
|
-
|
|
165
|
+
"""Make sure we received enough information to route from origins to destinations."""
|
|
170
166
|
super()._prepare_origins_destinations()
|
|
171
167
|
|
|
172
168
|
if self.all_to_all:
|
|
@@ -57,8 +57,9 @@ class RegionalTask:
|
|
|
57
57
|
|
|
58
58
|
In **r5py**, there is usually no need to explicitely create a
|
|
59
59
|
`RegionalTask`. Rather, the constructors to the computation classes
|
|
60
|
-
(`TravelTimeMatrixComputer`, `AccessibilityEstimator`, ...) accept
|
|
61
|
-
|
|
60
|
+
(`TravelTimeMatrixComputer`, `AccessibilityEstimator`, ...) accept the
|
|
61
|
+
arguments, and pass them through to an internally handled
|
|
62
|
+
`RegionalTask`.
|
|
62
63
|
|
|
63
64
|
Arguments
|
|
64
65
|
---------
|
|
@@ -67,31 +68,30 @@ class RegionalTask:
|
|
|
67
68
|
origin : shapely.geometry.Point
|
|
68
69
|
Point to route from
|
|
69
70
|
destinations : geopandas.GeoDataFrame
|
|
70
|
-
Points to route to, has to have at least an ``id`` column
|
|
71
|
-
|
|
71
|
+
Points to route to, has to have at least an ``id`` column and a
|
|
72
|
+
geometry
|
|
72
73
|
departure : datetime.datetime
|
|
73
74
|
Find public transport connections leaving every minute within
|
|
74
|
-
``departure_time_window`` after ``departure``.
|
|
75
|
-
|
|
75
|
+
``departure_time_window`` after ``departure``. Default: current date
|
|
76
|
+
and time
|
|
76
77
|
departure_time_window : datetime.timedelta
|
|
77
|
-
(see ``departure``)
|
|
78
|
-
Default: 10 minutes
|
|
78
|
+
(see ``departure``) Default: 10 minutes
|
|
79
79
|
percentiles : list[int]
|
|
80
80
|
Return the travel time for these percentiles of all computed trips,
|
|
81
|
-
by travel time. By default, return the median travel time.
|
|
82
|
-
|
|
81
|
+
by travel time. By default, return the median travel time. Default:
|
|
82
|
+
[50]
|
|
83
83
|
transport_modes : list[r5py.TransportMode] or list[str]
|
|
84
|
-
The mode of transport to use for routing. Can be a r5py mode
|
|
85
|
-
|
|
84
|
+
The mode of transport to use for routing. Can be a r5py mode
|
|
85
|
+
enumerable, or a string representation (e.g. "TRANSIT") Default:
|
|
86
|
+
[r5py.TransportMode.TRANSIT] (all public transport)
|
|
86
87
|
access_modes : list[r5py.TransportMode] or list[str]
|
|
87
|
-
Mode of transport to public transport stops. Can be a r5py mode
|
|
88
|
-
|
|
88
|
+
Mode of transport to public transport stops. Can be a r5py mode
|
|
89
|
+
object, or a string representation (e.g. "WALK") Default:
|
|
90
|
+
[r5py.TransportMode.WALK]
|
|
89
91
|
egress_modes : list[r5py.TransportMode]
|
|
90
|
-
Mode of transport from public transport stops.
|
|
91
|
-
Default: access_modes
|
|
92
|
+
Mode of transport from public transport stops. Default: access_modes
|
|
92
93
|
max_time : datetime.timedelta
|
|
93
|
-
Maximum trip duration.
|
|
94
|
-
Default: 2 hours
|
|
94
|
+
Maximum trip duration. Default: 2 hours
|
|
95
95
|
max_time_walking : datetime.timedelta
|
|
96
96
|
Maximum time spent walking, potentially including access and egress
|
|
97
97
|
Default: max_time
|
|
@@ -99,24 +99,19 @@ class RegionalTask:
|
|
|
99
99
|
Maximum time spent cycling, potentially including access and egress
|
|
100
100
|
Default: max_time
|
|
101
101
|
max_time_driving : datetime.timedelta
|
|
102
|
-
Maximum time spent driving
|
|
103
|
-
Default: max_time
|
|
102
|
+
Maximum time spent driving Default: max_time
|
|
104
103
|
speed_walking : float
|
|
105
|
-
Mean walking speed for routing, km/h.
|
|
106
|
-
Default: 3.6 km/h
|
|
104
|
+
Mean walking speed for routing, km/h. Default: 3.6 km/h
|
|
107
105
|
speed_cycling : float
|
|
108
|
-
Mean cycling speed for routing, km/h.
|
|
109
|
-
Default: 12.0 km/h
|
|
106
|
+
Mean cycling speed for routing, km/h. Default: 12.0 km/h
|
|
110
107
|
max_public_transport_rides : int
|
|
111
|
-
Use at most ``max_public_transport_rides`` consecutive public
|
|
112
|
-
connections. Default: 8
|
|
108
|
+
Use at most ``max_public_transport_rides`` consecutive public
|
|
109
|
+
transport connections. Default: 8
|
|
113
110
|
max_bicycle_traffic_stress : int
|
|
114
|
-
Maximum stress level for cyclist routing, ranges from 1-4
|
|
115
|
-
|
|
116
|
-
Default: 3
|
|
111
|
+
Maximum stress level for cyclist routing, ranges from 1-4 see
|
|
112
|
+
https://docs.conveyal.com/learn-more/traffic-stress Default: 3
|
|
117
113
|
breakdown : bool
|
|
118
|
-
Compute a more detailed breakdown of the routes.
|
|
119
|
-
Default: False
|
|
114
|
+
Compute a more detailed breakdown of the routes. Default: False
|
|
120
115
|
"""
|
|
121
116
|
self._regional_task = com.conveyal.r5.analyst.cluster.RegionalTask()
|
|
122
117
|
self.scenario = Scenario()
|
|
@@ -205,12 +200,16 @@ class RegionalTask:
|
|
|
205
200
|
# The value is a static property of com.conveyal.r5.analyst.cluster.PathResult;
|
|
206
201
|
# static properites of Java classes can be modified in a singleton kind of way
|
|
207
202
|
try:
|
|
208
|
-
|
|
209
|
-
com.conveyal.r5.analyst.cluster.PathResult.maxDestinations,
|
|
210
|
-
len(self.destinations) + 1,
|
|
211
|
-
)
|
|
203
|
+
num_destinations = len(self.destinations)
|
|
212
204
|
except AttributeError:
|
|
213
|
-
|
|
205
|
+
num_destinations = 0
|
|
206
|
+
if (
|
|
207
|
+
num_destinations
|
|
208
|
+
> com.conveyal.r5.analyst.cluster.PathResult.MAX_PATH_DESTINATIONS
|
|
209
|
+
):
|
|
210
|
+
com.conveyal.r5.analyst.cluster.PathResult.MAX_PATH_DESTINATIONS = (
|
|
211
|
+
num_destinations + 1
|
|
212
|
+
)
|
|
214
213
|
|
|
215
214
|
@property
|
|
216
215
|
def departure(self):
|
|
@@ -251,14 +250,21 @@ class RegionalTask:
|
|
|
251
250
|
|
|
252
251
|
@property
|
|
253
252
|
def departure_time_window(self):
|
|
254
|
-
"""Find public transport connections leaving within ``departure_time_window`` after ``departure`` (datetime.timedelta).
|
|
253
|
+
"""Find public transport connections leaving within ``departure_time_window`` after ``departure`` (datetime.timedelta).
|
|
254
|
+
|
|
255
|
+
**Note:** The value of ``departure_time_window`` should be set with some
|
|
256
|
+
caution. Specifically, setting values near or below the typical headways
|
|
257
|
+
in the studied transit network may lead to routing problems. See `this
|
|
258
|
+
GitHub discussion <https://github.com/r5py/r5py/issues/292>`_ for
|
|
259
|
+
details.
|
|
260
|
+
"""
|
|
255
261
|
return self._departure_time_window
|
|
256
262
|
|
|
257
263
|
@departure_time_window.setter
|
|
258
264
|
def departure_time_window(self, departure_time_window: datetime.timedelta):
|
|
259
265
|
if departure_time_window.total_seconds() < 300:
|
|
260
266
|
warnings.warn(
|
|
261
|
-
"The provided departure time window is below 5 minutes. This may cause adverse effects with
|
|
267
|
+
"The provided departure time window is below 5 minutes. This may cause adverse effects with routing.",
|
|
262
268
|
RuntimeWarning,
|
|
263
269
|
)
|
|
264
270
|
self._departure_time_window = departure_time_window
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
"""Represent one leg of a trip, specifically transfers between public transport
|
|
5
|
-
vehicles."""
|
|
4
|
+
"""Represent one leg of a trip, specifically transfers between public transport vehicles."""
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
from .direct_leg import DirectLeg
|
|
@@ -12,7 +11,4 @@ __all__ = ["TransferLeg"]
|
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
class TransferLeg(DirectLeg):
|
|
15
|
-
"""
|
|
16
|
-
Represent one leg of a trip, specifically transfers between public transport
|
|
17
|
-
vehicles.
|
|
18
|
-
"""
|
|
14
|
+
"""Represent one leg of a trip, specifically transfers between public transport vehicles."""
|
|
@@ -90,10 +90,12 @@ class TransitLayer:
|
|
|
90
90
|
|
|
91
91
|
@functools.cached_property
|
|
92
92
|
def routes(self):
|
|
93
|
+
"""Return a list of GTFS routes."""
|
|
93
94
|
return list(self._transit_layer.routes)
|
|
94
95
|
|
|
95
96
|
@functools.cached_property
|
|
96
97
|
def trip_patterns(self):
|
|
98
|
+
"""Return a list of GTFS trip patterns."""
|
|
97
99
|
return list(self._transit_layer.tripPatterns)
|
|
98
100
|
|
|
99
101
|
|
|
@@ -68,6 +68,7 @@ class TransportMode(enum.Enum):
|
|
|
68
68
|
return None
|
|
69
69
|
|
|
70
70
|
def __add__(self, other):
|
|
71
|
+
"""Combine two transport modes."""
|
|
71
72
|
if isinstance(other, self.__class__):
|
|
72
73
|
return [self, other]
|
|
73
74
|
elif isinstance(other, list):
|
|
@@ -78,6 +79,7 @@ class TransportMode(enum.Enum):
|
|
|
78
79
|
)
|
|
79
80
|
|
|
80
81
|
def __radd__(self, other):
|
|
82
|
+
"""Combine two transport modes."""
|
|
81
83
|
if other == 0: # first iteration of sum()
|
|
82
84
|
return self
|
|
83
85
|
elif isinstance(other, list):
|
|
@@ -87,17 +89,17 @@ class TransportMode(enum.Enum):
|
|
|
87
89
|
|
|
88
90
|
@property
|
|
89
91
|
def is_leg_mode(self):
|
|
90
|
-
"""Can this TransportMode function as a LegMode
|
|
92
|
+
"""Can this TransportMode function as a LegMode?."""
|
|
91
93
|
return self.name in LEG_MODES
|
|
92
94
|
|
|
93
95
|
@property
|
|
94
96
|
def is_street_mode(self):
|
|
95
|
-
"""Can this TransportMode function as a StreetMode
|
|
97
|
+
"""Can this TransportMode function as a StreetMode?."""
|
|
96
98
|
return self.name in STREET_MODES
|
|
97
99
|
|
|
98
100
|
@property
|
|
99
101
|
def is_transit_mode(self):
|
|
100
|
-
"""Can this TransportMode function as a TransitMode
|
|
102
|
+
"""Can this TransportMode function as a TransitMode?."""
|
|
101
103
|
return self.name in TRANSIT_MODES
|
|
102
104
|
|
|
103
105
|
AIR = "AIR"
|
|
@@ -43,12 +43,14 @@ class TransportNetwork:
|
|
|
43
43
|
|
|
44
44
|
Arguments
|
|
45
45
|
---------
|
|
46
|
-
osm_pbf : str
|
|
46
|
+
osm_pbf : str | pathlib.Path
|
|
47
47
|
file path of an OpenStreetMap extract in PBF format
|
|
48
|
-
gtfs : list[str]
|
|
49
|
-
|
|
48
|
+
gtfs : str | pathlib.Path | list[str] | list[pathlib.Path]
|
|
49
|
+
path(s) to public transport schedule information in GTFS format
|
|
50
50
|
"""
|
|
51
51
|
osm_pbf = self._working_copy(pathlib.Path(osm_pbf)).absolute()
|
|
52
|
+
if isinstance(gtfs, (str, pathlib.Path)):
|
|
53
|
+
gtfs = [gtfs]
|
|
52
54
|
gtfs = [str(self._working_copy(path).absolute()) for path in gtfs]
|
|
53
55
|
|
|
54
56
|
transport_network = com.conveyal.r5.transit.TransportNetwork()
|
|
@@ -87,15 +89,17 @@ class TransportNetwork:
|
|
|
87
89
|
self._transport_network = transport_network
|
|
88
90
|
|
|
89
91
|
def __del__(self):
|
|
90
|
-
"""
|
|
91
|
-
Delete all temporary files upon destruction.
|
|
92
|
-
"""
|
|
92
|
+
"""Delete all temporary files upon destruction."""
|
|
93
93
|
MAX_TRIES = 10
|
|
94
94
|
|
|
95
95
|
# first, close the open osm_file,
|
|
96
96
|
# delete Java objects, and
|
|
97
97
|
# trigger Java garbage collection
|
|
98
|
-
|
|
98
|
+
try:
|
|
99
|
+
self.osm_file.close()
|
|
100
|
+
except jpype.JVMNotRunning:
|
|
101
|
+
# JVM was stopped already, file should be closed
|
|
102
|
+
pass
|
|
99
103
|
try:
|
|
100
104
|
del self.street_layer
|
|
101
105
|
except AttributeError: # might not have been accessed a single time
|
|
@@ -104,13 +108,23 @@ class TransportNetwork:
|
|
|
104
108
|
del self.transit_layer
|
|
105
109
|
except AttributeError:
|
|
106
110
|
pass
|
|
107
|
-
|
|
111
|
+
try:
|
|
112
|
+
del self._transport_network
|
|
113
|
+
except AttributeError:
|
|
114
|
+
pass
|
|
108
115
|
|
|
109
|
-
time.sleep(0
|
|
110
|
-
|
|
116
|
+
time.sleep(1.0)
|
|
117
|
+
try:
|
|
118
|
+
jpype.java.lang.System.gc()
|
|
119
|
+
except jpype.JVMNotRunning:
|
|
120
|
+
pass
|
|
111
121
|
|
|
112
122
|
# then, try to delete all files in cache directory
|
|
113
|
-
|
|
123
|
+
try:
|
|
124
|
+
temporary_files = [child for child in self._cache_directory.iterdir()]
|
|
125
|
+
except FileNotFoundError: # deleted in the meantime/race condition
|
|
126
|
+
temporary_files = []
|
|
127
|
+
|
|
114
128
|
for _ in range(MAX_TRIES):
|
|
115
129
|
for temporary_file in temporary_files:
|
|
116
130
|
try:
|
|
@@ -200,6 +214,7 @@ class TransportNetwork:
|
|
|
200
214
|
|
|
201
215
|
@property
|
|
202
216
|
def extent(self):
|
|
217
|
+
"""The geographic area covered, as a `shapely.box`."""
|
|
203
218
|
# TODO: figure out how to get the extent of the GTFS schedule,
|
|
204
219
|
# then find the smaller extent of the two (or the larger one?)
|
|
205
220
|
return self.street_layer.extent
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import copy
|
|
6
6
|
|
|
7
|
-
import joblib
|
|
8
7
|
import pandas
|
|
9
8
|
|
|
10
9
|
from .base_travel_time_matrix_computer import BaseTravelTimeMatrixComputer
|
|
@@ -40,20 +39,10 @@ class TravelTimeMatrixComputer(BaseTravelTimeMatrixComputer):
|
|
|
40
39
|
self._prepare_origins_destinations()
|
|
41
40
|
self.request.destinations = self.destinations
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
verbose=(10 * self.verbose), # joblib has a funny verbosity scale
|
|
48
|
-
n_jobs=self.NUM_THREADS,
|
|
49
|
-
) as parallel:
|
|
50
|
-
od_matrix = pandas.concat(
|
|
51
|
-
parallel(
|
|
52
|
-
joblib.delayed(self._travel_times_per_origin)(from_id)
|
|
53
|
-
for from_id in self.origins.id
|
|
54
|
-
),
|
|
55
|
-
ignore_index=True,
|
|
56
|
-
)
|
|
42
|
+
od_matrix = pandas.concat(
|
|
43
|
+
[self._travel_times_per_origin(from_id) for from_id in self.origins.id],
|
|
44
|
+
ignore_index=True,
|
|
45
|
+
)
|
|
57
46
|
|
|
58
47
|
try:
|
|
59
48
|
od_matrix = od_matrix.to_crs(self._origins_crs)
|
|
@@ -15,9 +15,7 @@ __all__ = ["Trip"]
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class Trip:
|
|
18
|
-
"""
|
|
19
|
-
Represent one trip, consisting of one or more `TripLeg`s.
|
|
20
|
-
"""
|
|
18
|
+
"""Represent one trip, consisting of one or more `r5py.r5.TripLeg`."""
|
|
21
19
|
|
|
22
20
|
COLUMNS = [
|
|
23
21
|
"segment",
|
|
@@ -25,7 +23,7 @@ class Trip:
|
|
|
25
23
|
|
|
26
24
|
def __init__(self, legs=[]):
|
|
27
25
|
"""
|
|
28
|
-
Represent one trip, consisting of one of more `TripLeg
|
|
26
|
+
Represent one trip, consisting of one of more `r5py.r5.TripLeg`.
|
|
29
27
|
|
|
30
28
|
Arguments
|
|
31
29
|
=========
|
|
@@ -34,7 +32,13 @@ class Trip:
|
|
|
34
32
|
"""
|
|
35
33
|
self.legs = legs
|
|
36
34
|
|
|
35
|
+
def __eq__(self, other):
|
|
36
|
+
"""Check whether `self` and `other` are equal."""
|
|
37
|
+
if isinstance(other, self.__class__):
|
|
38
|
+
return self.legs == other.legs
|
|
39
|
+
|
|
37
40
|
def __repr__(self):
|
|
41
|
+
"""Return a string representation of `self`."""
|
|
38
42
|
legs = ", ".join([str(leg) for leg in self.legs])
|
|
39
43
|
return (
|
|
40
44
|
f"<{self.__class__.__name__}: "
|