r5py 0.1.1.dev2__tar.gz → 1.0.0.dev0__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.

Files changed (75) hide show
  1. {r5py-0.1.1.dev2/src/r5py.egg-info → r5py-1.0.0.dev0}/PKG-INFO +8 -6
  2. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/pyproject.toml +15 -10
  3. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/__init__.py +6 -1
  4. r5py-1.0.0.dev0/src/r5py/__main__.py +3 -0
  5. r5py-1.0.0.dev0/src/r5py/r5/__init__.py +40 -0
  6. r5py-0.1.1.dev2/src/r5py/r5/base_travel_time_matrix_computer.py → r5py-1.0.0.dev0/src/r5py/r5/base_travel_time_matrix.py +28 -8
  7. r5py-0.1.1.dev2/src/r5py/r5/detailed_itineraries_computer.py → r5py-1.0.0.dev0/src/r5py/r5/detailed_itineraries.py +72 -19
  8. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/direct_leg.py +1 -3
  9. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/regional_task.py +12 -9
  10. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/street_layer.py +1 -0
  11. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/transfer_leg.py +2 -6
  12. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/transit_layer.py +6 -0
  13. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/transit_leg.py +1 -5
  14. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/transport_mode.py +5 -3
  15. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/transport_network.py +16 -7
  16. r5py-0.1.1.dev2/src/r5py/r5/travel_time_matrix_computer.py → r5py-1.0.0.dev0/src/r5py/r5/travel_time_matrix.py +94 -19
  17. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/trip.py +13 -8
  18. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/trip_leg.py +76 -15
  19. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/trip_planner.py +103 -47
  20. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/__init__.py +2 -0
  21. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/classpath.py +9 -5
  22. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/config.py +11 -2
  23. r5py-1.0.0.dev0/src/r5py/util/environment.py +34 -0
  24. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/good_enough_equidistant_crs.py +0 -1
  25. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/memory_footprint.py +3 -5
  26. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/sample_data_set.py +13 -5
  27. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/validating_requests_session.py +2 -2
  28. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0/src/r5py.egg-info}/PKG-INFO +8 -6
  29. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py.egg-info/SOURCES.txt +6 -6
  30. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py.egg-info/requires.txt +7 -5
  31. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_breakdownstats.py +1 -1
  32. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_camel_to_snake_case.py +1 -1
  33. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_classpath.py +1 -1
  34. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_contains_gtfs_data.py +4 -3
  35. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_data_validation.py +5 -4
  36. r5py-0.1.1.dev2/tests/test_detailed_itineraries_computer.py → r5py-1.0.0.dev0/tests/test_detailed_itineraries.py +118 -106
  37. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_deterministic_behaviour.py +1 -5
  38. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_java_casting.py +1 -1
  39. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_memory_footprint.py +1 -1
  40. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_regional_task.py +1 -1
  41. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_snake_to_camel_case.py +1 -1
  42. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_transport_mode.py +1 -1
  43. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_transport_network.py +13 -12
  44. r5py-0.1.1.dev2/tests/test_travel_time_matrix_computer.py → r5py-1.0.0.dev0/tests/test_travel_time_matrix.py +102 -87
  45. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_trip.py +37 -29
  46. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_trip_leg.py +21 -14
  47. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_validating_request_session.py +19 -13
  48. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_verbose_warnings.py +17 -11
  49. r5py-0.1.1.dev2/src/r5py/__main__.py +0 -16
  50. r5py-0.1.1.dev2/src/r5py/r5/__init__.py +0 -24
  51. r5py-0.1.1.dev2/src/r5py/sampledata/_keep/__init__.py +0 -3
  52. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/LICENSE +0 -0
  53. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/README.md +0 -0
  54. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/setup.cfg +0 -0
  55. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/access_leg.py +0 -0
  56. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/breakdown_stat.py +0 -0
  57. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/egress_leg.py +0 -0
  58. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/r5/scenario.py +0 -0
  59. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/camel_to_snake_case.py +0 -0
  60. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/contains_gtfs_data.py +0 -0
  61. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/data_validation.py +0 -0
  62. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/exceptions.py +0 -0
  63. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/jvm.py +0 -0
  64. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/parse_int_date.py +0 -0
  65. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/snake_to_camel_case.py +0 -0
  66. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py/util/warnings.py +0 -0
  67. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py.egg-info/dependency_links.txt +0 -0
  68. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/src/r5py.egg-info/top_level.txt +0 -0
  69. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_config.py +0 -0
  70. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_good_enough_equidistant_crs.py +0 -0
  71. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_parse_int_date.py +0 -0
  72. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_sample_data_set.py +0 -0
  73. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_street_layer.py +0 -0
  74. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/tests/test_transit_layer.py +0 -0
  75. {r5py-0.1.1.dev2 → r5py-1.0.0.dev0}/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.1.dev2
3
+ Version: 1.0.0.dev0
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>
@@ -41,8 +41,8 @@ Requires-Dist: matplotlib; extra == "docs"
41
41
  Requires-Dist: myst-nb; extra == "docs"
42
42
  Requires-Dist: nbsphinx; extra == "docs"
43
43
  Requires-Dist: pybtex-apa7-style; extra == "docs"
44
- Requires-Dist: r5py.sampledata.helsinki>=0.1.1.dev2; extra == "docs"
45
- Requires-Dist: r5py.sampledata.sao_paulo>=0.1.1.dev2; 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
46
  Requires-Dist: shapely; extra == "docs"
47
47
  Requires-Dist: sphinx; extra == "docs"
48
48
  Requires-Dist: sphinx-book-theme; extra == "docs"
@@ -50,12 +50,14 @@ Requires-Dist: sphinx-design; extra == "docs"
50
50
  Requires-Dist: sphinxcontrib-bibtex; extra == "docs"
51
51
  Requires-Dist: sphinxcontrib-images; extra == "docs"
52
52
  Provides-Extra: tests
53
+ Requires-Dist: pyarrow; extra == "tests"
53
54
  Requires-Dist: pytest; extra == "tests"
54
55
  Requires-Dist: pytest-asyncio; extra == "tests"
55
56
  Requires-Dist: pytest-cov; extra == "tests"
56
- Requires-Dist: pytest-lazy-fixture; extra == "tests"
57
- Requires-Dist: r5py.sampledata.helsinki>=0.1.1.dev2; extra == "tests"
58
- Requires-Dist: r5py.sampledata.sao_paulo>=0.1.1.dev2; 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"
60
+ Requires-Dist: typing-extensions; extra == "tests"
59
61
 
60
62
  <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;">
61
63
 
@@ -46,13 +46,12 @@ dynamic = ["version"]
46
46
  [project.optional-dependencies]
47
47
  docs = ["contextily", "folium", "GitPython", "h3>=4.0.0b2", "jupyterlab_myst",
48
48
  "mapclassify", "matplotlib", "myst-nb", "nbsphinx", "pybtex-apa7-style",
49
- "r5py.sampledata.helsinki>=0.1.1.dev2",
50
- "r5py.sampledata.sao_paulo>=0.1.1.dev2", "shapely", "sphinx",
51
- "sphinx-book-theme", "sphinx-design", "sphinxcontrib-bibtex",
52
- "sphinxcontrib-images"]
53
- tests = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-lazy-fixture",
54
- "r5py.sampledata.helsinki>=0.1.1.dev2",
55
- "r5py.sampledata.sao_paulo>=0.1.1.dev2"]
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", "typing-extensions"]
56
55
 
57
56
 
58
57
  [project.urls]
@@ -61,15 +60,21 @@ Repository = "https://github.com/r5py/r5py.git"
61
60
  "Change log" = "https://github.com/r5py/r5py/blob/main/CHANGELOG.md"
62
61
  "Bug tracker" = "https://github.com/r5py/r5py/issues"
63
62
 
64
- [tool.coverage.run]
65
- omit = ["tests/*", ".virtualenv/**/*"]
63
+ [tool.coverage.paths]
64
+ equivalent_sources = [
65
+ "src/r5py/",
66
+ ".virtualenv/lib/python*/site-packages/r5py/",
67
+ "/opt/hostedtoolcache/Python/*/x64/lib/python*/site-packages/r5py/",
68
+ "/Library/Frameworks/Python.framework/Versions/*/lib/python*/site-packages/r5py/",
69
+ "C:/hostedtoolcache/windows/Python/*/x64/Lib/site-packages/r5py/"
70
+ ]
66
71
 
67
72
  [tool.jupytext.formats]
68
73
  "docs/notebooks/" = "ipynb"
69
74
  "docs/md/" = "md"
70
75
 
71
76
  [tool.pytest.ini_options]
72
- addopts = "-p no:faulthandler --cov --cov-report term-missing --cov-report xml"
77
+ addopts = "-p no:faulthandler --cov=r5py --cov-report term-missing --cov-report xml --import-mode=importlib"
73
78
  filterwarnings = [
74
79
  "error",
75
80
  "ignore:Could not find R5 jar, trying to download it from upstream",
@@ -2,21 +2,26 @@
2
2
 
3
3
  """Python wrapper for the R5 routing analysis engine."""
4
4
 
5
- __version__ = "0.1.1.dev2"
5
+ __version__ = "1.0.0dev0"
6
+
6
7
 
7
8
  from .r5 import (
9
+ DetailedItineraries,
8
10
  DetailedItinerariesComputer,
9
11
  RegionalTask,
10
12
  TransportMode,
11
13
  TransportNetwork,
14
+ TravelTimeMatrix,
12
15
  TravelTimeMatrixComputer,
13
16
  )
14
17
 
15
18
  __all__ = [
19
+ "DetailedItineraries",
16
20
  "DetailedItinerariesComputer",
17
21
  "RegionalTask",
18
22
  "TransportMode",
19
23
  "TransportNetwork",
24
+ "TravelTimeMatrix",
20
25
  "TravelTimeMatrixComputer",
21
26
  "__version__",
22
27
  ]
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """Python wrapper for the R5 routing analysis engine."""
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """R5 classes."""
4
+
5
+ from .access_leg import AccessLeg
6
+ from .breakdown_stat import BreakdownStat
7
+ from .detailed_itineraries import DetailedItineraries, DetailedItinerariesComputer
8
+ from .direct_leg import DirectLeg
9
+ from .egress_leg import EgressLeg
10
+ from .regional_task import RegionalTask
11
+ from .scenario import Scenario
12
+ from .street_layer import StreetLayer
13
+ from .transfer_leg import TransferLeg
14
+ from .transit_leg import TransitLeg
15
+ from .transport_mode import TransportMode
16
+ from .transport_network import TransportNetwork
17
+ from .travel_time_matrix import TravelTimeMatrix, TravelTimeMatrixComputer
18
+ from .trip import Trip
19
+ from .trip_planner import TripPlanner
20
+
21
+ __all__ = [
22
+ "AccessLeg",
23
+ "BreakdownStat",
24
+ "DetailedItineraries",
25
+ "DetailedItinerariesComputer",
26
+ "DirectLeg",
27
+ "EgressLeg",
28
+ "RegionalTask",
29
+ "Scenario",
30
+ "SpeedConfig",
31
+ "StreetLayer",
32
+ "TransferLeg",
33
+ "TransitLeg",
34
+ "TransportMode",
35
+ "TransportNetwork",
36
+ "TravelTimeMatrix",
37
+ "TravelTimeMatrixComputer",
38
+ "Trip",
39
+ "TripPlanner",
40
+ ]
@@ -6,6 +6,7 @@ import math
6
6
  import multiprocessing
7
7
  import warnings
8
8
 
9
+ import geopandas
9
10
  import numpy
10
11
  import shapely
11
12
 
@@ -14,7 +15,7 @@ from .regional_task import RegionalTask
14
15
  from .transport_network import TransportNetwork
15
16
 
16
17
 
17
- __all__ = ["BaseTravelTimeMatrixComputer"]
18
+ __all__ = ["BaseTravelTimeMatrix"]
18
19
 
19
20
 
20
21
  # R5 fills cut-off (NULL) values with MAX_INT32
@@ -26,13 +27,26 @@ MAX_INT32 = (2**31) - 1
26
27
  NUM_THREADS = math.ceil(multiprocessing.cpu_count() * 0.5)
27
28
 
28
29
 
29
- class BaseTravelTimeMatrixComputer:
30
+ class BaseTravelTimeMatrix(geopandas.GeoDataFrame):
30
31
  """Base class for travel time computers between many origins and destinations."""
31
32
 
32
33
  MAX_INT32 = MAX_INT32
33
34
 
34
35
  NUM_THREADS = NUM_THREADS
35
36
 
37
+ _r5py_attributes = [
38
+ "_destinations",
39
+ "_destinations_crs",
40
+ "_origins",
41
+ "_origins_crs",
42
+ "destinations",
43
+ "origins",
44
+ "request",
45
+ "snap_to_network",
46
+ "transport_network",
47
+ "verbose",
48
+ ]
49
+
36
50
  def __init__(
37
51
  self,
38
52
  transport_network,
@@ -71,6 +85,8 @@ class BaseTravelTimeMatrixComputer:
71
85
  ``max_time_cycling``, ``max_time_driving``, ``speed_cycling``, ``speed_walking``,
72
86
  ``max_public_transport_rides``, ``max_bicycle_traffic_stress``
73
87
  """
88
+ geopandas.GeoDataFrame.__init__(self)
89
+
74
90
  if not isinstance(transport_network, TransportNetwork):
75
91
  transport_network = TransportNetwork(*transport_network)
76
92
  self.transport_network = transport_network
@@ -89,8 +105,16 @@ class BaseTravelTimeMatrixComputer:
89
105
 
90
106
  self.verbose = Config().arguments.verbose
91
107
 
108
+ def __setattr__(self, attr, val):
109
+ """Catch our own attributes here so we don’t mess with (geo)pandas columns."""
110
+ if attr in self._r5py_attributes:
111
+ object.__setattr__(self, attr, val)
112
+ else:
113
+ super().__setattr__(attr, val)
114
+
92
115
  @property
93
116
  def destinations(self):
117
+ """The destinations of this travel time matrix (`geopandas.GeoDataFrame`)."""
94
118
  return self._destinations
95
119
 
96
120
  @destinations.setter
@@ -120,10 +144,7 @@ class BaseTravelTimeMatrixComputer:
120
144
  return data_set.map(lambda x: numpy.nan if x == MAX_INT32 else x)
121
145
 
122
146
  def _prepare_origins_destinations(self):
123
- """
124
- Make sure we received enough information to route from origins to
125
- destinations.
126
- """
147
+ """Make sure we received enough information to route from origins to destinations."""
127
148
  try:
128
149
  self.origins
129
150
  except AttributeError as exception:
@@ -161,10 +182,9 @@ class BaseTravelTimeMatrixComputer:
161
182
 
162
183
  setattr(self, f"_{which_end}", points.copy())
163
184
 
164
- self.snap_to_network = False # prevent repeated snapping on same point sets
165
-
166
185
  @property
167
186
  def origins(self):
187
+ """The origins of this travel time matrix (`geopandas.GeoDataFrame`)."""
168
188
  return self._origins
169
189
 
170
190
  @origins.setter
@@ -7,23 +7,33 @@
7
7
  import copy
8
8
  import warnings
9
9
 
10
+ try:
11
+ from warnings import deprecated
12
+ except ImportError: # Python<=3.12
13
+ from typing_extensions import deprecated
14
+
10
15
  import geopandas
11
16
  import joblib
12
17
  import pandas
13
18
 
14
- from .base_travel_time_matrix_computer import BaseTravelTimeMatrixComputer
19
+ from .base_travel_time_matrix import BaseTravelTimeMatrix
15
20
  from .trip import Trip
16
21
  from .trip_planner import ACCURATE_GEOMETRIES, TripPlanner
17
22
 
18
23
 
19
- __all__ = ["DetailedItinerariesComputer"]
24
+ __all__ = ["DetailedItineraries", "DetailedItinerariesComputer"]
20
25
 
21
26
 
22
- class DetailedItinerariesComputer(BaseTravelTimeMatrixComputer):
27
+ class DetailedItineraries(BaseTravelTimeMatrix):
23
28
  """Compute detailed itineraries between many origins and destinations."""
24
29
 
25
30
  COLUMNS = ["from_id", "to_id", "option"] + Trip.COLUMNS
26
31
 
32
+ _r5py_attributes = BaseTravelTimeMatrix._r5py_attributes + [
33
+ "all_to_all",
34
+ "od_pairs",
35
+ ]
36
+
27
37
  def __init__(
28
38
  self,
29
39
  transport_network,
@@ -36,6 +46,10 @@ class DetailedItinerariesComputer(BaseTravelTimeMatrixComputer):
36
46
  """
37
47
  Compute travel times between many origins and destinations.
38
48
 
49
+ ``r5py.DetailedItineraries`` are child classes of
50
+ ``geopandas.GeoDataFrame`` and support all of their methods and
51
+ properties, see https://geopandas.org/en/stable/docs.html
52
+
39
53
  Arguments
40
54
  ---------
41
55
  transport_network : r5py.TransportNetwork | tuple(str, list(str), dict)
@@ -58,10 +72,10 @@ class DetailedItinerariesComputer(BaseTravelTimeMatrixComputer):
58
72
  if `int`, use `snap_to_network` meters as the search radius.
59
73
  force_all_to_all : bool, default False
60
74
  If ``origins`` and ``destinations`` have the same length, by
61
- default, ``DetailedItinerariesComputer`` finds routes between pairs
75
+ default, ``DetailedItineraries`` finds routes between pairs
62
76
  of origins and destinations, i.e., it routes from origin #1 to
63
77
  destination #1, origin #2 to destination #2, ... .
64
- Set ``all_to_all=True`` to route from each origin to all
78
+ Set ``force_all_to_all=True`` to route from each origin to all
65
79
  destinations (this is the default, if ``origins`` and ``destinations``
66
80
  have different lengths, or if ``destinations`` is omitted)
67
81
  **kwargs : mixed
@@ -106,7 +120,14 @@ class DetailedItinerariesComputer(BaseTravelTimeMatrixComputer):
106
120
  else:
107
121
  self.all_to_all = force_all_to_all
108
122
 
109
- def compute_travel_details(self):
123
+ data = self._compute()
124
+ with warnings.catch_warnings():
125
+ warnings.simplefilter("ignore", category=FutureWarning)
126
+ for column in data.columns:
127
+ self[column] = data[column]
128
+ self.set_geometry("geometry")
129
+
130
+ def _compute(self):
110
131
  """
111
132
  Compute travel times from all origins to all destinations.
112
133
 
@@ -114,17 +135,21 @@ class DetailedItinerariesComputer(BaseTravelTimeMatrixComputer):
114
135
  -------
115
136
  geopandas.GeoDataFrame
116
137
  The resulting detailed routes. For each origin/destination pair,
138
+ multiple route alternatives (‘options’) might be reported that each
139
+ consist of one or more segments. Each segment represents one row.
117
140
  multiple route alternatives (‘options’) might be reported that each consist of
118
141
  one or more segments. Each segment represents one row.
142
+
119
143
  The data frame comprises of the following columns: `from_id`,
120
144
  `to_id`, `option` (`int`), `segment` (`int`), `transport_mode`
121
145
  (`r5py.TransportMode`), `departure_time` (`datetime.datetime`),
122
146
  `distance` (`float`, metres), `travel_time` (`datetime.timedelta`),
123
- `wait_time` (`datetime.timedelta`), `route` (`str`, public transport
124
- route number or name), `geometry` (`shapely.LineString`)
125
- TODO: Add description of output data frame columns and format
147
+ `wait_time` (`datetime.timedelta`), `feed` (`str`, the feed name
148
+ used), `agency_id` (`str` the public transport agency identifier),
149
+ `route_id` (`str`, public transport route ID), `start_stop_id`
150
+ (`str`, the GTFS stop_id for boarding), `end_stop_id` (`str`, the
151
+ GTFS stop_id for alighting), `geometry` (`shapely.LineString`)
126
152
  """
127
-
128
153
  self._prepare_origins_destinations()
129
154
 
130
155
  # warn if public transport routes are requested, but R5 has been
@@ -150,11 +175,12 @@ class DetailedItinerariesComputer(BaseTravelTimeMatrixComputer):
150
175
  verbose=(10 * self.verbose), # joblib has a funny verbosity scale
151
176
  n_jobs=self.NUM_THREADS,
152
177
  ) as parallel:
178
+ matrices = parallel(
179
+ joblib.delayed(self._travel_details_per_od_pair)(from_id, to_id)
180
+ for _, (from_id, to_id) in self.od_pairs.iterrows()
181
+ )
153
182
  od_matrix = pandas.concat(
154
- parallel(
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
- ),
183
+ [matrix.astype(matrices[0].dtypes) for matrix in matrices],
158
184
  ignore_index=True,
159
185
  )
160
186
 
@@ -162,11 +188,7 @@ class DetailedItinerariesComputer(BaseTravelTimeMatrixComputer):
162
188
  return od_matrix
163
189
 
164
190
  def _prepare_origins_destinations(self):
165
- """
166
- Make sure we received enough information to route from origins to
167
- destinations.
168
- """
169
-
191
+ """Make sure we received enough information to route from origins to destinations."""
170
192
  super()._prepare_origins_destinations()
171
193
 
172
194
  if self.all_to_all:
@@ -208,3 +230,34 @@ class DetailedItinerariesComputer(BaseTravelTimeMatrixComputer):
208
230
  # fmt: on
209
231
 
210
232
  return pandas.DataFrame(trips, columns=self.COLUMNS)
233
+
234
+
235
+ @deprecated(
236
+ "Use `DetailedItineraries` instead, `DetailedItinerariesComputer will be deprecated in a future release."
237
+ )
238
+ class DetailedItinerariesComputer:
239
+ """Compute detailed itineraries between many origins and destinations."""
240
+
241
+ def __init__(self, *args, **kwargs):
242
+ """Compute detailed itineraries between many origins and destinations."""
243
+ self._detailed_itineraries = DetailedItineraries(*args, **kwargs)
244
+
245
+ def compute_travel_details(self):
246
+ """
247
+ Compute travel times from all origins to all destinations.
248
+
249
+ Returns
250
+ -------
251
+ geopandas.GeoDataFrame
252
+ The resulting detailed routes. For each origin/destination pair,
253
+ multiple route alternatives (‘options’) might be reported that each consist of
254
+ one or more segments. Each segment represents one row.
255
+ The data frame comprises of the following columns: `from_id`,
256
+ `to_id`, `option` (`int`), `segment` (`int`), `transport_mode`
257
+ (`r5py.TransportMode`), `departure_time` (`datetime.datetime`),
258
+ `distance` (`float`, metres), `travel_time` (`datetime.timedelta`),
259
+ `wait_time` (`datetime.timedelta`), `route` (`str`, public transport
260
+ route number or name), `geometry` (`shapely.LineString`)
261
+ TODO: Add description of output data frame columns and format
262
+ """
263
+ return self._detailed_itineraries
@@ -15,9 +15,7 @@ __all__ = ["DirectLeg"]
15
15
 
16
16
 
17
17
  class DirectLeg(TripLeg):
18
- """
19
- Represent one leg of a public transport trip.
20
- """
18
+ """Represent one leg of a public transport trip."""
21
19
 
22
20
  def __init__(self, transport_mode, street_segment):
23
21
  """
@@ -53,11 +53,11 @@ class RegionalTask:
53
53
  A RegionalTask wraps a `com.conveyal.r5.analyst.cluster.RegionalTask`,
54
54
  which is used to specify the details of a requested computation.
55
55
  RegionalTasks underlie virtually all major computations carried out,
56
- such as, e.g., `TravelTimeMatrixComputer` or `AccessibilityEstimator`.
56
+ such as, e.g., `TravelTimeMatrix` or `AccessibilityEstimator`.
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 the
60
+ (`TravelTimeMatrix`, `AccessibilityEstimator`, ...) accept the
61
61
  arguments, and pass them through to an internally handled
62
62
  `RegionalTask`.
63
63
 
@@ -200,12 +200,16 @@ class RegionalTask:
200
200
  # The value is a static property of com.conveyal.r5.analyst.cluster.PathResult;
201
201
  # static properites of Java classes can be modified in a singleton kind of way
202
202
  try:
203
- com.conveyal.r5.analyst.cluster.PathResult.maxDestinations = max(
204
- com.conveyal.r5.analyst.cluster.PathResult.maxDestinations,
205
- len(self.destinations) + 1,
206
- )
203
+ num_destinations = len(self.destinations)
207
204
  except AttributeError:
208
- pass
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
+ )
209
213
 
210
214
  @property
211
215
  def departure(self):
@@ -246,8 +250,7 @@ class RegionalTask:
246
250
 
247
251
  @property
248
252
  def departure_time_window(self):
249
- """Find public transport connections leaving within
250
- ``departure_time_window`` after ``departure`` (datetime.timedelta).
253
+ """Find public transport connections leaving within ``departure_time_window`` after ``departure`` (datetime.timedelta).
251
254
 
252
255
  **Note:** The value of ``departure_time_window`` should be set with some
253
256
  caution. Specifically, setting values near or below the typical headways
@@ -40,6 +40,7 @@ class StreetLayer:
40
40
 
41
41
  @functools.cached_property
42
42
  def extent(self):
43
+ """The geographic area covered, as a `shapely.box`."""
43
44
  envelope = self._street_layer.envelope
44
45
  return shapely.box(
45
46
  envelope.getMinX(),
@@ -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,12 +90,18 @@ 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
 
101
+ def get_stop_id_from_index(self, stop_index):
102
+ """Get the GTFS stop id for the `stop_index`-th stop of this transit layer."""
103
+ return self._transit_layer.stopIdForIndex[stop_index]
104
+
99
105
 
100
106
  @jpype._jcustomizer.JConversion(
101
107
  "com.conveyal.r5.transit.TransitLayer", exact=TransitLayer
@@ -11,8 +11,4 @@ __all__ = ["TransitLeg"]
11
11
 
12
12
 
13
13
  class TransitLeg(TripLeg):
14
- """
15
- Represent one leg of a public transport trip.
16
- """
17
-
18
- pass
14
+ """Represent one leg of a public transport trip."""
@@ -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"
@@ -89,9 +89,7 @@ class TransportNetwork:
89
89
  self._transport_network = transport_network
90
90
 
91
91
  def __del__(self):
92
- """
93
- Delete all temporary files upon destruction.
94
- """
92
+ """Delete all temporary files upon destruction."""
95
93
  MAX_TRIES = 10
96
94
 
97
95
  # first, close the open osm_file,
@@ -110,13 +108,23 @@ class TransportNetwork:
110
108
  del self.transit_layer
111
109
  except AttributeError:
112
110
  pass
113
- del self._transport_network
111
+ try:
112
+ del self._transport_network
113
+ except AttributeError:
114
+ pass
114
115
 
115
- time.sleep(0.5)
116
- jpype.java.lang.System.gc()
116
+ time.sleep(1.0)
117
+ try:
118
+ jpype.java.lang.System.gc()
119
+ except jpype.JVMNotRunning:
120
+ pass
117
121
 
118
122
  # then, try to delete all files in cache directory
119
- temporary_files = [child for child in self._cache_directory.iterdir()]
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
+
120
128
  for _ in range(MAX_TRIES):
121
129
  for temporary_file in temporary_files:
122
130
  try:
@@ -206,6 +214,7 @@ class TransportNetwork:
206
214
 
207
215
  @property
208
216
  def extent(self):
217
+ """The geographic area covered, as a `shapely.box`."""
209
218
  # TODO: figure out how to get the extent of the GTFS schedule,
210
219
  # then find the smaller extent of the two (or the larger one?)
211
220
  return self.street_layer.extent