r5py 1.0.3__tar.gz → 1.0.4__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-1.0.3/src/r5py.egg-info → r5py-1.0.4}/PKG-INFO +3 -2
- {r5py-1.0.3 → r5py-1.0.4}/pyproject.toml +2 -1
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/__init__.py +3 -1
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/__init__.py +2 -0
- r5py-1.0.4/src/r5py/r5/elevation_cost_function.py +50 -0
- r5py-1.0.4/src/r5py/r5/elevation_model.py +84 -0
- r5py-1.0.4/src/r5py/r5/file_storage.py +84 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/transport_network.py +29 -5
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/classpath.py +2 -2
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/config.py +7 -1
- {r5py-1.0.3 → r5py-1.0.4/src/r5py.egg-info}/PKG-INFO +3 -2
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py.egg-info/SOURCES.txt +5 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py.egg-info/requires.txt +2 -1
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/__init__.py +18 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/file_digest.py +3 -3
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/r5_jar.py +2 -2
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/transport_network.py +22 -0
- r5py-1.0.4/tests/data/test_isochrones_bicycle.gpkg.zip +0 -0
- r5py-1.0.4/tests/data/test_isochrones_car.gpkg.zip +0 -0
- r5py-1.0.4/tests/data/test_isochrones_transit.gpkg.zip +0 -0
- r5py-1.0.4/tests/data/test_isochrones_walk.gpkg.zip +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_config.py +20 -0
- r5py-1.0.4/tests/test_elevation_cost_function.py +31 -0
- r5py-1.0.4/tests/test_file_storage.py +51 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_java_casting.py +8 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_transport_network.py +54 -0
- r5py-1.0.3/tests/data/test_isochrones_bicycle.gpkg.zip +0 -0
- r5py-1.0.3/tests/data/test_isochrones_car.gpkg.zip +0 -0
- r5py-1.0.3/tests/data/test_isochrones_transit.gpkg.zip +0 -0
- r5py-1.0.3/tests/data/test_isochrones_walk.gpkg.zip +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/LICENSE +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/MANIFEST.in +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/README.md +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/setup.cfg +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/__main__.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/access_leg.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/base_travel_time_matrix.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/detailed_itineraries.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/direct_leg.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/egress_leg.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/isochrones.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/regional_task.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/scenario.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/street_layer.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/street_segment.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/transfer_leg.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/transit_layer.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/transit_leg.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/transport_mode.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/travel_time_matrix.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/trip.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/trip_leg.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/r5/trip_planner.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/__init__.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/camel_to_snake_case.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/contains_gtfs_data.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/data_validation.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/environment.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/exceptions.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/file_digest.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/good_enough_equidistant_crs.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/jvm.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/memory_footprint.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/parse_int_date.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/sample_data_set.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/snake_to_camel_case.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/spatially_clustered_geodataframe.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/validating_requests_session.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/warnings.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py/util/working_copy.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py.egg-info/dependency_links.txt +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/src/r5py.egg-info/top_level.txt +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/__init__.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/data_directory.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/destinations.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/garbage_collection.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/origins.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/routing_parameters.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/routing_results.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/sample_data.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/conftest_d/upstream_r5.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_broken_gtfs.zip +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_detailed_itineraries_bicycle.gpkg.zip +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_detailed_itineraries_car.gpkg.zip +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_detailed_itineraries_transit.gpkg.zip +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_detailed_itineraries_walk.gpkg.zip +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_invalid_points_duplicate_ids.geojson +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_invalid_points_no_id_column.geojson +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_isochrones_from_multiple_origins.gpkg.zip +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_multiple_origins.geojson +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_snapped_population_grid_centroids.geojson +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_travel_times_bicycle.csv +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_travel_times_car.csv +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_travel_times_transit.csv +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_travel_times_walk.csv +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_valid_points_data.geojson +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_valid_single_point_data.geojson +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_walking_details_not_snapped.csv +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_walking_details_snapped.csv +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_walking_times_not_snapped.csv +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/data/test_walking_times_snapped.csv +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/temporary_directory.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_camel_to_snake_case.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_classpath.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_contains_gtfs_data.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_data_validation.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_detailed_itineraries.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_deterministic_behaviour.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_file_digest.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_good_enough_equidistant_crs.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_isochrones.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_memory_footprint.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_parse_int_date.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_regional_task.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_sample_data_set.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_snake_to_camel_case.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_street_layer.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_transit_layer.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_transport_mode.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_travel_time_matrix.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_trip.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_trip_leg.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_trip_planner.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_validating_request_session.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_verbose_warnings.py +0 -0
- {r5py-1.0.3 → r5py-1.0.4}/tests/test_working_directory.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: r5py
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: Python wrapper for the R5 routing analysis engine
|
|
5
5
|
Author: Christoph Fink, Willem Klumpenhouwer, Marcus Sairava, Rafael Pereira, Henrikki Tenkanen
|
|
6
6
|
License: GPL-3.0-or-later or MIT
|
|
@@ -26,6 +26,7 @@ Requires-Dist: numpy
|
|
|
26
26
|
Requires-Dist: pandas>=2.1.0
|
|
27
27
|
Requires-Dist: psutil
|
|
28
28
|
Requires-Dist: pyproj
|
|
29
|
+
Requires-Dist: rasterio
|
|
29
30
|
Requires-Dist: requests
|
|
30
31
|
Requires-Dist: scikit-learn
|
|
31
32
|
Requires-Dist: shapely>=2.0
|
|
@@ -55,7 +56,7 @@ Requires-Dist: pyarrow; extra == "tests"
|
|
|
55
56
|
Requires-Dist: pytest; extra == "tests"
|
|
56
57
|
Requires-Dist: pytest-cov; extra == "tests"
|
|
57
58
|
Requires-Dist: pytest-lazy-fixtures; extra == "tests"
|
|
58
|
-
Requires-Dist: r5py.sampledata.helsinki>=0.
|
|
59
|
+
Requires-Dist: r5py.sampledata.helsinki>=1.0.3; extra == "tests"
|
|
59
60
|
Requires-Dist: r5py.sampledata.sao_paulo>=0.1.1; extra == "tests"
|
|
60
61
|
Requires-Dist: typing-extensions; extra == "tests"
|
|
61
62
|
Dynamic: license-file
|
|
@@ -26,6 +26,7 @@ dependencies = [
|
|
|
26
26
|
"pandas>=2.1.0",
|
|
27
27
|
"psutil",
|
|
28
28
|
"pyproj",
|
|
29
|
+
"rasterio",
|
|
29
30
|
"requests",
|
|
30
31
|
"scikit-learn",
|
|
31
32
|
"shapely>=2.0",
|
|
@@ -52,7 +53,7 @@ docs = ["contextily", "folium", "GitPython", "h3>=4.0.0b2", "jupyterlab_myst",
|
|
|
52
53
|
"shapely", "sphinx", "sphinx-book-theme", "sphinx-design",
|
|
53
54
|
"sphinxcontrib-bibtex", "sphinxcontrib-images"]
|
|
54
55
|
tests = ["pyarrow", "pytest", "pytest-cov", "pytest-lazy-fixtures",
|
|
55
|
-
"r5py.sampledata.helsinki>=0.
|
|
56
|
+
"r5py.sampledata.helsinki>=1.0.3", "r5py.sampledata.sao_paulo>=0.1.1",
|
|
56
57
|
"typing-extensions"]
|
|
57
58
|
|
|
58
59
|
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
"""Python wrapper for the R5 routing analysis engine."""
|
|
4
4
|
|
|
5
|
-
__version__ = "1.0.
|
|
5
|
+
__version__ = "1.0.4"
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
from .r5 import (
|
|
9
9
|
DetailedItineraries,
|
|
10
10
|
DetailedItinerariesComputer,
|
|
11
|
+
ElevationCostFunction,
|
|
11
12
|
Isochrones,
|
|
12
13
|
RegionalTask,
|
|
13
14
|
TransportMode,
|
|
@@ -19,6 +20,7 @@ from .r5 import (
|
|
|
19
20
|
__all__ = [
|
|
20
21
|
"DetailedItineraries",
|
|
21
22
|
"DetailedItinerariesComputer",
|
|
23
|
+
"ElevationCostFunction",
|
|
22
24
|
"Isochrones",
|
|
23
25
|
"RegionalTask",
|
|
24
26
|
"TransportMode",
|
|
@@ -6,6 +6,7 @@ from .access_leg import AccessLeg
|
|
|
6
6
|
from .detailed_itineraries import DetailedItineraries, DetailedItinerariesComputer
|
|
7
7
|
from .direct_leg import DirectLeg
|
|
8
8
|
from .egress_leg import EgressLeg
|
|
9
|
+
from .elevation_cost_function import ElevationCostFunction
|
|
9
10
|
from .isochrones import Isochrones
|
|
10
11
|
from .regional_task import RegionalTask
|
|
11
12
|
from .scenario import Scenario
|
|
@@ -24,6 +25,7 @@ __all__ = [
|
|
|
24
25
|
"DetailedItinerariesComputer",
|
|
25
26
|
"DirectLeg",
|
|
26
27
|
"EgressLeg",
|
|
28
|
+
"ElevationCostFunction",
|
|
27
29
|
"Isochrones",
|
|
28
30
|
"RegionalTask",
|
|
29
31
|
"Scenario",
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"""The elevation cost functions supported by R5 (Tobler, Minetti)."""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import enum
|
|
8
|
+
|
|
9
|
+
import jpype
|
|
10
|
+
|
|
11
|
+
from ..util import start_jvm
|
|
12
|
+
|
|
13
|
+
import com.conveyal.r5
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
__all__ = ["ElevationCostFunction"]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
start_jvm()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ElevationCostFunction(enum.Enum):
|
|
23
|
+
"""
|
|
24
|
+
Elevation cost functions.
|
|
25
|
+
|
|
26
|
+
TOBLER: Waldo Tobler’s hiking function, cf. https://en.wikipedia.org/wiki/Tobler%27s_hiking_function
|
|
27
|
+
MINETTI: Minetti et al.’s perceived effort/energy consumption, cf.
|
|
28
|
+
https://doi.org/10.1152/japplphysiol.01177.2001
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
@classmethod
|
|
32
|
+
def _missing_(cls, value):
|
|
33
|
+
value = str(value).upper()
|
|
34
|
+
for member in cls:
|
|
35
|
+
if value == member.value:
|
|
36
|
+
return member
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
TOBLER = "TOBLER"
|
|
40
|
+
MINETTI = "MINETTI"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@jpype._jcustomizer.JConversion(
|
|
44
|
+
"com.conveyal.r5.analyst.scenario.RasterCost.CostFunction",
|
|
45
|
+
exact=ElevationCostFunction,
|
|
46
|
+
)
|
|
47
|
+
def _cast_LegMode(java_class, object_):
|
|
48
|
+
return com.conveyal.r5.analyst.scenario.RasterCost.CostFunction.valueOf(
|
|
49
|
+
object_.name
|
|
50
|
+
)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"""Load a digital elevation model and apply it to an r5py.TransportNetwork."""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import rasterio
|
|
8
|
+
|
|
9
|
+
from .elevation_cost_function import ElevationCostFunction
|
|
10
|
+
from .file_storage import FileStorage
|
|
11
|
+
from ..util import WorkingCopy
|
|
12
|
+
|
|
13
|
+
import com.conveyal.analysis
|
|
14
|
+
import com.conveyal.r5
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
__all__ = ["ElevationModel"]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ElevationModel:
|
|
21
|
+
"""Load a digital elevation model and apply it to an r5py.TransportNetwork."""
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
elevation_model,
|
|
26
|
+
elevation_cost_function=ElevationCostFunction.TOBLER,
|
|
27
|
+
):
|
|
28
|
+
"""
|
|
29
|
+
Load an elevation model.
|
|
30
|
+
|
|
31
|
+
Arguments
|
|
32
|
+
---------
|
|
33
|
+
elevation_model : str | pathlib.Path
|
|
34
|
+
file path to a digital elevation model in TIF format,
|
|
35
|
+
single-band, the value of which is the elevation in metres
|
|
36
|
+
elevation_cost_function : r5py.ElevationCostFunction
|
|
37
|
+
which algorithm to use to compute the added effort and travel time
|
|
38
|
+
of slopes
|
|
39
|
+
"""
|
|
40
|
+
elevation_model = WorkingCopy(elevation_model)
|
|
41
|
+
elevation_model = self._convert_tiff_to_format_readable_by_r5(elevation_model)
|
|
42
|
+
|
|
43
|
+
# instantiate an com.conveyal.file.FileStorage singleton
|
|
44
|
+
com.conveyal.analysis.components.WorkerComponents.fileStorage = FileStorage()
|
|
45
|
+
|
|
46
|
+
self._elevation_model = com.conveyal.r5.analyst.scenario.RasterCost()
|
|
47
|
+
self._elevation_model.dataSourceId = f"{elevation_model.with_suffix('')}"
|
|
48
|
+
self._elevation_model.costFunction = elevation_cost_function
|
|
49
|
+
|
|
50
|
+
def apply_to(self, transport_network):
|
|
51
|
+
"""
|
|
52
|
+
Add the costs associated with elevation traversal to a transport network.
|
|
53
|
+
|
|
54
|
+
Arguments
|
|
55
|
+
---------
|
|
56
|
+
transport_network : r5py.TransportNetwork
|
|
57
|
+
The transport network to which to add slope costs
|
|
58
|
+
"""
|
|
59
|
+
self._elevation_model.resolve(transport_network)
|
|
60
|
+
self._elevation_model.apply(transport_network)
|
|
61
|
+
|
|
62
|
+
@staticmethod
|
|
63
|
+
def _convert_tiff_to_format_readable_by_r5(tiff):
|
|
64
|
+
# javax.imagio does not allow all compression/predictor
|
|
65
|
+
# combinations of TIFFs
|
|
66
|
+
# to work around it, convert the input to a format known to work.
|
|
67
|
+
|
|
68
|
+
input_tiff = tiff.with_stem(f".{tiff.stem}")
|
|
69
|
+
output_tiff = tiff.with_suffix(".tif")
|
|
70
|
+
tiff.rename(input_tiff)
|
|
71
|
+
|
|
72
|
+
with rasterio.open(input_tiff) as source:
|
|
73
|
+
metadata = source.profile
|
|
74
|
+
metadata.update(
|
|
75
|
+
{
|
|
76
|
+
"compress": "LZW",
|
|
77
|
+
"predictor": "2",
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
with rasterio.open(output_tiff, "w", **metadata) as destination:
|
|
81
|
+
destination.write(source.read())
|
|
82
|
+
input_tiff.unlink()
|
|
83
|
+
|
|
84
|
+
return output_tiff
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"""A thin layer around com.conveyal.r5.file.FileStorage."""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import jpype
|
|
8
|
+
|
|
9
|
+
from ..util import start_jvm
|
|
10
|
+
|
|
11
|
+
import com.conveyal.file
|
|
12
|
+
import java.io.File
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
__all__ = ["FileStorage"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
start_jvm()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@jpype.JImplements(com.conveyal.file.FileStorage)
|
|
22
|
+
class FileStorage:
|
|
23
|
+
"""A thin layer around com.conveyal.r5.file.FileStorage."""
|
|
24
|
+
|
|
25
|
+
@jpype.JOverride
|
|
26
|
+
def moveIntoStorage(self, *args):
|
|
27
|
+
"""Not implemented."""
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
@jpype.JOverride
|
|
31
|
+
def getFile(self, file_storage_key):
|
|
32
|
+
"""
|
|
33
|
+
Return a java.io.File for the file identified by file_storage_key.
|
|
34
|
+
|
|
35
|
+
Arguments
|
|
36
|
+
---------
|
|
37
|
+
file_storage_key : com.conveyal.r5.file.FileStorageKey
|
|
38
|
+
An R5 object referencing a certain file
|
|
39
|
+
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
java.io.File
|
|
43
|
+
The file identified by file_storage_key
|
|
44
|
+
"""
|
|
45
|
+
return java.io.File(file_storage_key.path)
|
|
46
|
+
|
|
47
|
+
@jpype.JOverride
|
|
48
|
+
def getURL(self, file_storage_key):
|
|
49
|
+
"""
|
|
50
|
+
Return an URL for the file identified by file_storage_key.
|
|
51
|
+
|
|
52
|
+
Arguments
|
|
53
|
+
---------
|
|
54
|
+
file_storage_key : com.conveyal.r5.file.FileStorageKey
|
|
55
|
+
An R5 object referencing a certain file
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
str
|
|
60
|
+
An imaginary URL pointing to the file identified by file_storage_key
|
|
61
|
+
"""
|
|
62
|
+
return f"file://{file_storage_key.path}"
|
|
63
|
+
|
|
64
|
+
@jpype.JOverride
|
|
65
|
+
def delete(self, *args):
|
|
66
|
+
"""Not implemented."""
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
@jpype.JOverride
|
|
70
|
+
def exists(self, file_storage_key):
|
|
71
|
+
"""
|
|
72
|
+
Check whether the file identified by file_storage_key exists.
|
|
73
|
+
|
|
74
|
+
Arguments
|
|
75
|
+
---------
|
|
76
|
+
file_storage_key : com.conveyal.r5.file.FileStorageKey
|
|
77
|
+
An R5 object referencing a certain file
|
|
78
|
+
|
|
79
|
+
Returns
|
|
80
|
+
-------
|
|
81
|
+
bool
|
|
82
|
+
Whether or not the file identified by file_storage_key exists
|
|
83
|
+
"""
|
|
84
|
+
return self.getFile(file_storage_key).exists()
|
|
@@ -12,12 +12,15 @@ import warnings
|
|
|
12
12
|
import jpype
|
|
13
13
|
import jpype.types
|
|
14
14
|
|
|
15
|
+
from .elevation_cost_function import ElevationCostFunction
|
|
16
|
+
from .elevation_model import ElevationModel
|
|
15
17
|
from .street_layer import StreetLayer
|
|
16
18
|
from .transit_layer import TransitLayer
|
|
17
19
|
from .transport_mode import TransportMode
|
|
18
20
|
from ..util import Config, contains_gtfs_data, FileDigest, start_jvm, WorkingCopy
|
|
19
21
|
from ..util.exceptions import GtfsFileError
|
|
20
22
|
|
|
23
|
+
import com.conveyal.analysis
|
|
21
24
|
import com.conveyal.gtfs
|
|
22
25
|
import com.conveyal.osmlib
|
|
23
26
|
import com.conveyal.r5
|
|
@@ -36,7 +39,14 @@ start_jvm()
|
|
|
36
39
|
class TransportNetwork:
|
|
37
40
|
"""Wrap a com.conveyal.r5.transit.TransportNetwork."""
|
|
38
41
|
|
|
39
|
-
def __init__(
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
osm_pbf,
|
|
45
|
+
gtfs=[],
|
|
46
|
+
elevation_model=None,
|
|
47
|
+
elevation_cost_function=ElevationCostFunction.TOBLER,
|
|
48
|
+
allow_errors=False,
|
|
49
|
+
):
|
|
40
50
|
"""
|
|
41
51
|
Load a transport network.
|
|
42
52
|
|
|
@@ -46,6 +56,12 @@ class TransportNetwork:
|
|
|
46
56
|
file path of an OpenStreetMap extract in PBF format
|
|
47
57
|
gtfs : str | pathlib.Path | list[str] | list[pathlib.Path]
|
|
48
58
|
path(s) to public transport schedule information in GTFS format
|
|
59
|
+
elevation_model : str | pathlib.Path
|
|
60
|
+
file path to a digital elevation model in TIF format,
|
|
61
|
+
single-band, the value of which is the elevation in metres
|
|
62
|
+
elevation_cost_function : r5py.ElevationCostFunction
|
|
63
|
+
which algorithm to use to compute the added effort and travel time
|
|
64
|
+
of slopes
|
|
49
65
|
allow_errors : bool
|
|
50
66
|
try to proceed with loading the transport network even if input data
|
|
51
67
|
contain errors
|
|
@@ -57,16 +73,18 @@ class TransportNetwork:
|
|
|
57
73
|
|
|
58
74
|
# a hash representing all input files
|
|
59
75
|
digest = hashlib.sha256(
|
|
60
|
-
"".join(
|
|
61
|
-
|
|
62
|
-
|
|
76
|
+
"".join(
|
|
77
|
+
[FileDigest(osm_pbf)]
|
|
78
|
+
+ [FileDigest(path) for path in gtfs]
|
|
79
|
+
+ [FileDigest(elevation_model) if elevation_model is not None else ""]
|
|
80
|
+
).encode("utf-8")
|
|
63
81
|
).hexdigest()
|
|
64
82
|
|
|
65
83
|
try:
|
|
66
84
|
transport_network = self._load_pickled_transport_network(
|
|
67
85
|
Config().CACHE_DIR / f"{digest}.transport_network"
|
|
68
86
|
)
|
|
69
|
-
except FileNotFoundError:
|
|
87
|
+
except (FileNotFoundError, java.io.IOError, java.lang.RuntimeException):
|
|
70
88
|
transport_network = com.conveyal.r5.transit.TransportNetwork()
|
|
71
89
|
transport_network.scenarioId = PACKAGE
|
|
72
90
|
|
|
@@ -122,6 +140,12 @@ class TransportNetwork:
|
|
|
122
140
|
|
|
123
141
|
transport_network.transitLayer.buildDistanceTables(None)
|
|
124
142
|
|
|
143
|
+
if elevation_model is not None:
|
|
144
|
+
ElevationModel(
|
|
145
|
+
elevation_model,
|
|
146
|
+
elevation_cost_function,
|
|
147
|
+
).apply_to(transport_network)
|
|
148
|
+
|
|
125
149
|
osm_file.close() # not needed after here?
|
|
126
150
|
|
|
127
151
|
self._save_pickled_transport_network(
|
|
@@ -18,9 +18,9 @@ from .warnings import R5pyWarning
|
|
|
18
18
|
|
|
19
19
|
# update these to use a newer R5 version if no R5 available locally
|
|
20
20
|
R5_JAR_URL = (
|
|
21
|
-
"https://github.com/r5py/r5/releases/download/v7.
|
|
21
|
+
"https://github.com/r5py/r5/releases/download/v7.4-r5py/r5-v7.4-r5py-all.jar"
|
|
22
22
|
)
|
|
23
|
-
R5_JAR_SHA256 = "
|
|
23
|
+
R5_JAR_SHA256 = "c51b566671165d113add84e10e60fb9273014ca4a2e2a52591446954f68e7340"
|
|
24
24
|
# ---
|
|
25
25
|
|
|
26
26
|
|
|
@@ -92,7 +92,13 @@ class Config:
|
|
|
92
92
|
FileNotFoundError, # broken symlink
|
|
93
93
|
PermissionError,
|
|
94
94
|
):
|
|
95
|
-
|
|
95
|
+
try:
|
|
96
|
+
cached_file.unlink()
|
|
97
|
+
except (
|
|
98
|
+
IsADirectoryError, # only available on Linux kernels
|
|
99
|
+
PermissionError, # what’s raised instead on Win and MacOs
|
|
100
|
+
):
|
|
101
|
+
pass
|
|
96
102
|
|
|
97
103
|
return cache_dir
|
|
98
104
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: r5py
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: Python wrapper for the R5 routing analysis engine
|
|
5
5
|
Author: Christoph Fink, Willem Klumpenhouwer, Marcus Sairava, Rafael Pereira, Henrikki Tenkanen
|
|
6
6
|
License: GPL-3.0-or-later or MIT
|
|
@@ -26,6 +26,7 @@ Requires-Dist: numpy
|
|
|
26
26
|
Requires-Dist: pandas>=2.1.0
|
|
27
27
|
Requires-Dist: psutil
|
|
28
28
|
Requires-Dist: pyproj
|
|
29
|
+
Requires-Dist: rasterio
|
|
29
30
|
Requires-Dist: requests
|
|
30
31
|
Requires-Dist: scikit-learn
|
|
31
32
|
Requires-Dist: shapely>=2.0
|
|
@@ -55,7 +56,7 @@ Requires-Dist: pyarrow; extra == "tests"
|
|
|
55
56
|
Requires-Dist: pytest; extra == "tests"
|
|
56
57
|
Requires-Dist: pytest-cov; extra == "tests"
|
|
57
58
|
Requires-Dist: pytest-lazy-fixtures; extra == "tests"
|
|
58
|
-
Requires-Dist: r5py.sampledata.helsinki>=0.
|
|
59
|
+
Requires-Dist: r5py.sampledata.helsinki>=1.0.3; extra == "tests"
|
|
59
60
|
Requires-Dist: r5py.sampledata.sao_paulo>=0.1.1; extra == "tests"
|
|
60
61
|
Requires-Dist: typing-extensions; extra == "tests"
|
|
61
62
|
Dynamic: license-file
|
|
@@ -15,6 +15,9 @@ src/r5py/r5/base_travel_time_matrix.py
|
|
|
15
15
|
src/r5py/r5/detailed_itineraries.py
|
|
16
16
|
src/r5py/r5/direct_leg.py
|
|
17
17
|
src/r5py/r5/egress_leg.py
|
|
18
|
+
src/r5py/r5/elevation_cost_function.py
|
|
19
|
+
src/r5py/r5/elevation_model.py
|
|
20
|
+
src/r5py/r5/file_storage.py
|
|
18
21
|
src/r5py/r5/isochrones.py
|
|
19
22
|
src/r5py/r5/regional_task.py
|
|
20
23
|
src/r5py/r5/scenario.py
|
|
@@ -58,7 +61,9 @@ tests/test_contains_gtfs_data.py
|
|
|
58
61
|
tests/test_data_validation.py
|
|
59
62
|
tests/test_detailed_itineraries.py
|
|
60
63
|
tests/test_deterministic_behaviour.py
|
|
64
|
+
tests/test_elevation_cost_function.py
|
|
61
65
|
tests/test_file_digest.py
|
|
66
|
+
tests/test_file_storage.py
|
|
62
67
|
tests/test_good_enough_equidistant_crs.py
|
|
63
68
|
tests/test_isochrones.py
|
|
64
69
|
tests/test_java_casting.py
|
|
@@ -8,6 +8,7 @@ numpy
|
|
|
8
8
|
pandas>=2.1.0
|
|
9
9
|
psutil
|
|
10
10
|
pyproj
|
|
11
|
+
rasterio
|
|
11
12
|
requests
|
|
12
13
|
scikit-learn
|
|
13
14
|
shapely>=2.0
|
|
@@ -41,6 +42,6 @@ pyarrow
|
|
|
41
42
|
pytest
|
|
42
43
|
pytest-cov
|
|
43
44
|
pytest-lazy-fixtures
|
|
44
|
-
r5py.sampledata.helsinki>=0.
|
|
45
|
+
r5py.sampledata.helsinki>=1.0.3
|
|
45
46
|
r5py.sampledata.sao_paulo>=0.1.1
|
|
46
47
|
typing-extensions
|
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
"""Fixtures to be used in r5py tests."""
|
|
5
5
|
|
|
6
|
+
# geopandas 1.0.1 imports shapely.geos which raises
|
|
7
|
+
# a Deprecation warning in Shapely 2.1.0
|
|
8
|
+
import warnings
|
|
9
|
+
|
|
10
|
+
with warnings.catch_warnings():
|
|
11
|
+
warnings.filterwarnings(
|
|
12
|
+
"ignore",
|
|
13
|
+
category=DeprecationWarning,
|
|
14
|
+
message=".*shapely.geos.*deprecated.*",
|
|
15
|
+
)
|
|
16
|
+
import geopandas # noqa: F401
|
|
17
|
+
|
|
6
18
|
|
|
7
19
|
from .destinations import (
|
|
8
20
|
population_grid,
|
|
@@ -74,12 +86,15 @@ from .sample_data import (
|
|
|
74
86
|
|
|
75
87
|
from .transport_network import (
|
|
76
88
|
broken_gtfs_file_path,
|
|
89
|
+
cache_directory,
|
|
90
|
+
elevation_model_file_path,
|
|
77
91
|
gtfs_file_path,
|
|
78
92
|
gtfs_timezone_helsinki,
|
|
79
93
|
helsinki_osm_pbf_file_path,
|
|
80
94
|
not_a_gtfs_file,
|
|
81
95
|
sao_paulo_osm_pbf_file_path,
|
|
82
96
|
transport_network,
|
|
97
|
+
transport_network_checksum,
|
|
83
98
|
transport_network_files_tuple,
|
|
84
99
|
transport_network_from_test_directory,
|
|
85
100
|
transport_network_from_test_files,
|
|
@@ -92,12 +107,14 @@ from .upstream_r5 import (
|
|
|
92
107
|
|
|
93
108
|
__all__ = [
|
|
94
109
|
"broken_gtfs_file_path",
|
|
110
|
+
"cache_directory",
|
|
95
111
|
"can_compute_detailed_route_geometries",
|
|
96
112
|
"departure_datetime",
|
|
97
113
|
"detailed_itineraries_bicycle",
|
|
98
114
|
"detailed_itineraries_car",
|
|
99
115
|
"detailed_itineraries_transit",
|
|
100
116
|
"detailed_itineraries_walk",
|
|
117
|
+
"elevation_model_file_path",
|
|
101
118
|
"file_digest_blake2b",
|
|
102
119
|
"file_digest_blake2s",
|
|
103
120
|
"file_digest_sha256",
|
|
@@ -135,6 +152,7 @@ __all__ = [
|
|
|
135
152
|
"sao_paulo_osm_pbf_file_path",
|
|
136
153
|
"snapped_population_grid_points",
|
|
137
154
|
"transport_network",
|
|
155
|
+
"transport_network_checksum",
|
|
138
156
|
"transport_network_files_tuple",
|
|
139
157
|
"transport_network_from_test_directory",
|
|
140
158
|
"transport_network_from_test_files",
|
|
@@ -9,12 +9,12 @@ import pytest
|
|
|
9
9
|
from .routing_results import ISOCHRONES_WALK
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
ISOCHRONES_WALK_BLAKE2B = "
|
|
12
|
+
ISOCHRONES_WALK_BLAKE2B = "e5c0fe9d34b512363c876eec81439b2708a1171272dd721a40aefe502c6e0dc73811aab0f109a45ab83645b88dea38051112ede7fc4b99a1231d92e3b4492e11"
|
|
13
13
|
ISOCHRONES_WALK_BLAKE2S = (
|
|
14
|
-
"
|
|
14
|
+
"3d46b490841df409cbb962e25d4201bda0eea5b825fc1181cb0babfddf457299"
|
|
15
15
|
)
|
|
16
16
|
ISOCHRONES_WALK_SHA256 = (
|
|
17
|
-
"
|
|
17
|
+
"1d899da67faed2f49a0dd870b1dc33b4c7bd695b18eafc08640a662b442e935c"
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
|
|
@@ -10,9 +10,9 @@ import pytest
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
R5_JAR_URL = (
|
|
13
|
-
"https://github.com/r5py/r5/releases/download/v7.
|
|
13
|
+
"https://github.com/r5py/r5/releases/download/v7.4-r5py/r5-v7.4-r5py-all.jar"
|
|
14
14
|
)
|
|
15
|
-
R5_JAR_SHA256 = "
|
|
15
|
+
R5_JAR_SHA256 = "c51b566671165d113add84e10e60fb9273014ca4a2e2a52591446954f68e7340"
|
|
16
16
|
R5_JAR_SHA256_INVALID = "adfadsfadsfadsfasdfasdf"
|
|
17
17
|
R5_JAR_SHA256_GITHUB_ERROR_MESSAGE_WHEN_POSTING = (
|
|
18
18
|
"14aa2347be79c280e4d0fd3a137fb8f5bf2863261a1e48e1a122df1a52a0f453"
|
|
@@ -26,6 +26,14 @@ def broken_gtfs_file_path():
|
|
|
26
26
|
yield BROKEN_GTFS_FILE
|
|
27
27
|
|
|
28
28
|
|
|
29
|
+
@pytest.fixture
|
|
30
|
+
def elevation_model_file_path():
|
|
31
|
+
"""Return the file path of a GTFS sample data set."""
|
|
32
|
+
import r5py.sampledata.helsinki
|
|
33
|
+
|
|
34
|
+
yield r5py.sampledata.helsinki.elevation_model
|
|
35
|
+
|
|
36
|
+
|
|
29
37
|
@pytest.fixture
|
|
30
38
|
def gtfs_file_path():
|
|
31
39
|
"""Return the file path of a GTFS sample data set."""
|
|
@@ -64,6 +72,20 @@ def transport_network_files_tuple():
|
|
|
64
72
|
yield r5py.sampledata.helsinki.osm_pbf, [r5py.sampledata.helsinki.gtfs]
|
|
65
73
|
|
|
66
74
|
|
|
75
|
+
@pytest.fixture
|
|
76
|
+
def transport_network_checksum():
|
|
77
|
+
"""Return the checksum of the default transport network (from files tuple)."""
|
|
78
|
+
yield "43bb097531f722016b26293d9e1cd11878d91e07e89846e1f5ba85c43a4b243c"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@pytest.fixture
|
|
82
|
+
def cache_directory():
|
|
83
|
+
"""Return a pathlib.Path pointing to r5py’s cache directory."""
|
|
84
|
+
from r5py.util.config import Config
|
|
85
|
+
|
|
86
|
+
yield Config().CACHE_DIR
|
|
87
|
+
|
|
88
|
+
|
|
67
89
|
@pytest.fixture
|
|
68
90
|
def transport_network(transport_network_from_test_files):
|
|
69
91
|
"""Return an `r5py.TransportNetwork`."""
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -46,3 +46,23 @@ class TestConfig:
|
|
|
46
46
|
_ = config.CACHE_DIR # re-evaluate cache dir contents
|
|
47
47
|
|
|
48
48
|
assert not expired_file.exists()
|
|
49
|
+
|
|
50
|
+
def test_cache_clearing_skip_directory(self):
|
|
51
|
+
config = r5py.util.config.Config()
|
|
52
|
+
|
|
53
|
+
past_best_by_date = (
|
|
54
|
+
datetime.datetime.now() - CACHE_MAX_AGE - datetime.timedelta(seconds=1)
|
|
55
|
+
).timestamp()
|
|
56
|
+
|
|
57
|
+
expired_directory = pathlib.Path(config.CACHE_DIR / "expired-dir")
|
|
58
|
+
expired_directory.mkdir()
|
|
59
|
+
os.utime(expired_directory, (past_best_by_date, past_best_by_date))
|
|
60
|
+
|
|
61
|
+
config.__dict__.pop("CACHE_DIR", None) # clear functools.cached_property
|
|
62
|
+
_ = config.CACHE_DIR # re-evaluate cache dir contents
|
|
63
|
+
|
|
64
|
+
assert expired_directory.exists()
|
|
65
|
+
try:
|
|
66
|
+
expired_directory.rmdir()
|
|
67
|
+
except PermissionError:
|
|
68
|
+
pass # Windows ...
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
import r5py
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestElevationCostFunction:
|
|
10
|
+
def test_some_weird_combinations(self):
|
|
11
|
+
# not as a parametrized test as pytest has troubles with
|
|
12
|
+
# functions as parametrized fixtures (tries to evaluate?)
|
|
13
|
+
assert r5py.ElevationCostFunction("tobler") == r5py.ElevationCostFunction.TOBLER
|
|
14
|
+
assert r5py.ElevationCostFunction("Tobler") == r5py.ElevationCostFunction.TOBLER
|
|
15
|
+
assert r5py.ElevationCostFunction("tObLeR") == r5py.ElevationCostFunction.TOBLER
|
|
16
|
+
assert r5py.ElevationCostFunction("TOBLER") == r5py.ElevationCostFunction.TOBLER
|
|
17
|
+
assert (
|
|
18
|
+
r5py.ElevationCostFunction("minetti") == r5py.ElevationCostFunction.MINETTI
|
|
19
|
+
)
|
|
20
|
+
assert (
|
|
21
|
+
r5py.ElevationCostFunction("Minetti") == r5py.ElevationCostFunction.MINETTI
|
|
22
|
+
)
|
|
23
|
+
assert (
|
|
24
|
+
r5py.ElevationCostFunction("mInEtTi") == r5py.ElevationCostFunction.MINETTI
|
|
25
|
+
)
|
|
26
|
+
assert (
|
|
27
|
+
r5py.ElevationCostFunction("MINETTI") == r5py.ElevationCostFunction.MINETTI
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
with pytest.raises(ValueError):
|
|
31
|
+
_ = r5py.ElevationCostFunction("FooBarInvalidCostFunction")
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import pathlib
|
|
5
|
+
|
|
6
|
+
import r5py
|
|
7
|
+
|
|
8
|
+
import com.conveyal.file
|
|
9
|
+
import java.io
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestFileStorage:
|
|
13
|
+
def test_void_methods(self):
|
|
14
|
+
file_storage = r5py.r5.file_storage.FileStorage()
|
|
15
|
+
assert file_storage.moveIntoStorage() is None
|
|
16
|
+
assert file_storage.delete() is None
|
|
17
|
+
|
|
18
|
+
def test_get_file(self):
|
|
19
|
+
file_storage = r5py.r5.file_storage.FileStorage()
|
|
20
|
+
fake_file_path = pathlib.Path("/home/foo/bar.txt")
|
|
21
|
+
gotten_file = file_storage.getFile(
|
|
22
|
+
com.conveyal.file.FileStorageKey(
|
|
23
|
+
com.conveyal.file.FileCategory.DATASOURCES,
|
|
24
|
+
f"{fake_file_path.with_suffix('')}",
|
|
25
|
+
)
|
|
26
|
+
)
|
|
27
|
+
assert isinstance(gotten_file, java.io.File)
|
|
28
|
+
assert str(gotten_file) == f"{fake_file_path.with_suffix('')}"
|
|
29
|
+
|
|
30
|
+
def test_get_url(self):
|
|
31
|
+
file_storage = r5py.r5.file_storage.FileStorage()
|
|
32
|
+
fake_file_path = pathlib.Path("/home/foo/bar.txt")
|
|
33
|
+
gotten_url = file_storage.getURL(
|
|
34
|
+
com.conveyal.file.FileStorageKey(
|
|
35
|
+
com.conveyal.file.FileCategory.DATASOURCES,
|
|
36
|
+
f"{fake_file_path.with_suffix('')}",
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
assert isinstance(gotten_url, str)
|
|
40
|
+
assert gotten_url == f"file://{fake_file_path.with_suffix('')}"
|
|
41
|
+
|
|
42
|
+
def test_exists(self):
|
|
43
|
+
file_storage = r5py.r5.file_storage.FileStorage()
|
|
44
|
+
fake_file_path = pathlib.Path("/home/foo/bar.txt")
|
|
45
|
+
exists = file_storage.exists(
|
|
46
|
+
com.conveyal.file.FileStorageKey(
|
|
47
|
+
com.conveyal.file.FileCategory.DATASOURCES,
|
|
48
|
+
f"{fake_file_path.with_suffix('')}",
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
assert not exists
|
|
@@ -28,6 +28,14 @@ class TestJavaCasting:
|
|
|
28
28
|
(r5py.TransportMode.WALK, com.conveyal.r5.api.util.LegMode),
|
|
29
29
|
(r5py.TransportMode.BICYCLE_RENT, com.conveyal.r5.api.util.LegMode),
|
|
30
30
|
(r5py.TransportMode.CAR_PARK, com.conveyal.r5.api.util.LegMode),
|
|
31
|
+
(
|
|
32
|
+
r5py.ElevationCostFunction.TOBLER,
|
|
33
|
+
com.conveyal.r5.analyst.scenario.RasterCost.CostFunction,
|
|
34
|
+
),
|
|
35
|
+
(
|
|
36
|
+
r5py.ElevationCostFunction.MINETTI,
|
|
37
|
+
com.conveyal.r5.analyst.scenario.RasterCost.CostFunction,
|
|
38
|
+
),
|
|
31
39
|
],
|
|
32
40
|
)
|
|
33
41
|
def test_transport_modes_cast(self, python_object, java_class):
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
|
|
3
3
|
import pathlib
|
|
4
|
+
import random
|
|
4
5
|
import shutil
|
|
6
|
+
import string
|
|
5
7
|
|
|
6
8
|
import geopandas
|
|
7
9
|
import pytest
|
|
@@ -190,3 +192,55 @@ class Test_TransportNetwork:
|
|
|
190
192
|
[broken_gtfs_file_path],
|
|
191
193
|
allow_errors=True,
|
|
192
194
|
)
|
|
195
|
+
|
|
196
|
+
def test_transport_network_with_elevation_model_tobler(
|
|
197
|
+
self,
|
|
198
|
+
helsinki_osm_pbf_file_path,
|
|
199
|
+
gtfs_file_path,
|
|
200
|
+
elevation_model_file_path,
|
|
201
|
+
):
|
|
202
|
+
_ = r5py.TransportNetwork(
|
|
203
|
+
osm_pbf=helsinki_osm_pbf_file_path,
|
|
204
|
+
gtfs=[gtfs_file_path],
|
|
205
|
+
elevation_model=elevation_model_file_path,
|
|
206
|
+
elevation_cost_function=r5py.ElevationCostFunction.TOBLER,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
def test_transport_network_with_elevation_model_minetti(
|
|
210
|
+
self,
|
|
211
|
+
helsinki_osm_pbf_file_path,
|
|
212
|
+
gtfs_file_path,
|
|
213
|
+
elevation_model_file_path,
|
|
214
|
+
):
|
|
215
|
+
_ = r5py.TransportNetwork(
|
|
216
|
+
osm_pbf=helsinki_osm_pbf_file_path,
|
|
217
|
+
gtfs=[gtfs_file_path],
|
|
218
|
+
elevation_model=elevation_model_file_path,
|
|
219
|
+
elevation_cost_function=r5py.ElevationCostFunction.MINETTI,
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
def test_invalid_cache(
|
|
223
|
+
self,
|
|
224
|
+
transport_network_files_tuple,
|
|
225
|
+
cache_directory,
|
|
226
|
+
transport_network_checksum,
|
|
227
|
+
):
|
|
228
|
+
_ = r5py.TransportNetwork(*transport_network_files_tuple)
|
|
229
|
+
del _
|
|
230
|
+
|
|
231
|
+
(
|
|
232
|
+
cache_directory / f"{transport_network_checksum}.transport_network"
|
|
233
|
+
).write_text("".join(random.choices(string.printable, k=64)))
|
|
234
|
+
|
|
235
|
+
_ = r5py.TransportNetwork(*transport_network_files_tuple)
|
|
236
|
+
|
|
237
|
+
def test_cache_exists(
|
|
238
|
+
self,
|
|
239
|
+
transport_network,
|
|
240
|
+
cache_directory,
|
|
241
|
+
transport_network_checksum,
|
|
242
|
+
):
|
|
243
|
+
del transport_network
|
|
244
|
+
assert (
|
|
245
|
+
cache_directory / f"{transport_network_checksum}.transport_network"
|
|
246
|
+
).exists()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|