pandana 0.2.0__zip → 0.4.0__zip
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.
- {pandana-0.2.0 → pandana-0.4.0}/MANIFEST.in +0 -2
- {pandana-0.2.0/pandana.egg-info → pandana-0.4.0}/PKG-INFO +20 -15
- {pandana-0.2.0 → pandana-0.4.0}/README.rst +17 -13
- {pandana-0.2.0 → pandana-0.4.0}/ez_setup.py +22 -2
- pandana-0.4.0/pandana/__init__.py +3 -0
- pandana-0.4.0/pandana/loaders/osm.py +189 -0
- {pandana-0.2.0 → pandana-0.4.0}/pandana/network.py +177 -170
- pandana-0.4.0/pandana/utils.py +27 -0
- {pandana-0.2.0 → pandana-0.4.0/pandana.egg-info}/PKG-INFO +20 -15
- {pandana-0.2.0 → pandana-0.4.0}/pandana.egg-info/SOURCES.txt +2 -31
- pandana-0.4.0/pandana.egg-info/requires.txt +8 -0
- {pandana-0.2.0 → pandana-0.4.0}/setup.cfg +0 -1
- {pandana-0.2.0 → pandana-0.4.0}/setup.py +42 -34
- pandana-0.4.0/src/accessibility.cpp +374 -0
- pandana-0.4.0/src/accessibility.h +133 -0
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/DataStructures/Percent.h +5 -5
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/POIIndex/POIIndex.h +2 -1
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/libch.cpp +61 -48
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/libch.h +23 -13
- pandana-0.4.0/src/cyaccess.cpp +10356 -0
- pandana-0.4.0/src/cyaccess.pyx +176 -0
- pandana-0.4.0/src/graphalg.cpp +111 -0
- pandana-0.4.0/src/graphalg.h +50 -0
- {pandana-0.2.0 → pandana-0.4.0}/src/shared.h +1 -2
- pandana-0.2.0/pandana/__init__.py +0 -3
- pandana-0.2.0/pandana/loaders/osm.py +0 -394
- pandana-0.2.0/pandana/utils.py +0 -38
- pandana-0.2.0/pandana.egg-info/pbr.json +0 -1
- pandana-0.2.0/pandana.egg-info/requires.txt +0 -5
- pandana-0.2.0/src/accessibility.cpp +0 -369
- pandana-0.2.0/src/accessibility.h +0 -122
- pandana-0.2.0/src/ann_1.1.2/ann2fig/ann2fig.cpp +0 -588
- pandana-0.2.0/src/ann_1.1.2/include/ANN/ANN.h +0 -830
- pandana-0.2.0/src/ann_1.1.2/include/ANN/ANNperf.h +0 -223
- pandana-0.2.0/src/ann_1.1.2/include/ANN/ANNx.h +0 -169
- pandana-0.2.0/src/ann_1.1.2/src/ANN.cpp +0 -201
- pandana-0.2.0/src/ann_1.1.2/src/bd_fix_rad_search.cpp +0 -61
- pandana-0.2.0/src/ann_1.1.2/src/bd_pr_search.cpp +0 -62
- pandana-0.2.0/src/ann_1.1.2/src/bd_search.cpp +0 -61
- pandana-0.2.0/src/ann_1.1.2/src/bd_tree.cpp +0 -417
- pandana-0.2.0/src/ann_1.1.2/src/bd_tree.h +0 -100
- pandana-0.2.0/src/ann_1.1.2/src/brute.cpp +0 -109
- pandana-0.2.0/src/ann_1.1.2/src/kd_dump.cpp +0 -444
- pandana-0.2.0/src/ann_1.1.2/src/kd_fix_rad_search.cpp +0 -183
- pandana-0.2.0/src/ann_1.1.2/src/kd_fix_rad_search.h +0 -44
- pandana-0.2.0/src/ann_1.1.2/src/kd_pr_search.cpp +0 -219
- pandana-0.2.0/src/ann_1.1.2/src/kd_pr_search.h +0 -49
- pandana-0.2.0/src/ann_1.1.2/src/kd_search.cpp +0 -210
- pandana-0.2.0/src/ann_1.1.2/src/kd_search.h +0 -48
- pandana-0.2.0/src/ann_1.1.2/src/kd_split.cpp +0 -428
- pandana-0.2.0/src/ann_1.1.2/src/kd_split.h +0 -85
- pandana-0.2.0/src/ann_1.1.2/src/kd_tree.cpp +0 -405
- pandana-0.2.0/src/ann_1.1.2/src/kd_tree.h +0 -197
- pandana-0.2.0/src/ann_1.1.2/src/kd_util.cpp +0 -439
- pandana-0.2.0/src/ann_1.1.2/src/kd_util.h +0 -124
- pandana-0.2.0/src/ann_1.1.2/src/perf.cpp +0 -136
- pandana-0.2.0/src/ann_1.1.2/src/pr_queue.h +0 -125
- pandana-0.2.0/src/ann_1.1.2/src/pr_queue_k.h +0 -118
- pandana-0.2.0/src/graphalg.cpp +0 -144
- pandana-0.2.0/src/graphalg.h +0 -53
- pandana-0.2.0/src/nearestneighbor.cpp +0 -106
- pandana-0.2.0/src/nearestneighbor.h +0 -37
- pandana-0.2.0/src/pyaccesswrap.cpp +0 -514
- {pandana-0.2.0 → pandana-0.4.0}/pandana/loaders/__init__.py +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/pandana/loaders/pandash5.py +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/pandana/testing.py +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/pandana.egg-info/dependency_links.txt +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/pandana.egg-info/top_level.txt +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/BasicDefinitions.h +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/Contractor/ContractionCleanup.h +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/Contractor/Contractor.h +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/DataStructures/BinaryHeap.h +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/DataStructures/DynamicGraph.h +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/DataStructures/SimpleCHQuery.h +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/DataStructures/StaticGraph.h +0 -0
- {pandana-0.2.0 → pandana-0.4.0}/src/contraction_hierarchies/src/Util/HyperThreading.h +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 1.1
|
|
2
2
|
Name: pandana
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Pandas Network Analysis - dataframes of network queries, quickly
|
|
5
5
|
Home-page: https://udst.github.io/pandana/
|
|
6
|
-
Author:
|
|
6
|
+
Author: UrbanSim Inc.
|
|
7
7
|
Author-email: UNKNOWN
|
|
8
8
|
License: AGPL
|
|
9
9
|
Description: Pandana
|
|
@@ -17,8 +17,6 @@ Description: Pandana
|
|
|
17
17
|
:alt: Coverage Status
|
|
18
18
|
:target: https://coveralls.io/r/UDST/pandana
|
|
19
19
|
|
|
20
|
-
A nice slideshow showing example code is available
|
|
21
|
-
`here <http://bit.ly/1tivyjw>`__.
|
|
22
20
|
|
|
23
21
|
In this case, a picture is worth a thousand words. The image below shows
|
|
24
22
|
the distance to the *2nd* nearest restaurant (rendered by matplotlib)
|
|
@@ -48,8 +46,8 @@ Description: Pandana
|
|
|
48
46
|
their environment.
|
|
49
47
|
|
|
50
48
|
We look forward to creative uses of a general library like this - please
|
|
51
|
-
let us know
|
|
52
|
-
|
|
49
|
+
let us know if you think you have a great use case by tweeting us at
|
|
50
|
+
``@urbansim`` or post on the UrbanSim `forum`_.
|
|
53
51
|
|
|
54
52
|
Docs
|
|
55
53
|
----
|
|
@@ -64,22 +62,29 @@ Description: Pandana
|
|
|
64
62
|
Acknowledgments
|
|
65
63
|
---------------
|
|
66
64
|
|
|
67
|
-
None of this would be possible without the help of Dennis Luxen
|
|
68
|
-
|
|
69
|
-
you Dennis!
|
|
70
|
-
|
|
71
|
-
Nearest neighbor queries are performed with the fastest k-d tree around,
|
|
72
|
-
i.e. ANN (http://www.cs.umd.edu/~mount/ANN/).
|
|
65
|
+
None of this would be possible without the help of Dennis Luxen and
|
|
66
|
+
his OSRM (https://github.com/DennisOSRM/Project-OSRM). Thank you Dennis!
|
|
73
67
|
|
|
74
68
|
Academic Literature
|
|
75
69
|
-------------------
|
|
76
70
|
|
|
77
|
-
|
|
78
|
-
methodology <
|
|
79
|
-
|
|
71
|
+
A `complete description of the
|
|
72
|
+
methodology <http://onlinepubs.trb.org/onlinepubs/conferences/2012/4thITM/Papers-A/0117-000062.pdf>`__
|
|
73
|
+
was presented at the Transportation Research Board Annual Conference in 2012. Please cite this paper when referring
|
|
80
74
|
to the methodology implemented by this library.
|
|
81
75
|
|
|
76
|
+
Related UDST libraries
|
|
77
|
+
----------------------
|
|
78
|
+
|
|
79
|
+
- `OSMnet`_
|
|
80
|
+
- `UrbanAccess`_
|
|
81
|
+
|
|
82
|
+
.. _forum: http://discussion.urbansim.com/
|
|
83
|
+
.. _OSMnet: https://github.com/udst/osmnet
|
|
84
|
+
.. _UrbanAccess: https://github.com/UDST/urbanaccess
|
|
85
|
+
|
|
82
86
|
Platform: UNKNOWN
|
|
83
87
|
Classifier: Development Status :: 3 - Alpha
|
|
84
88
|
Classifier: Programming Language :: Python :: 2.7
|
|
89
|
+
Classifier: Programming Language :: Python :: 3.5
|
|
85
90
|
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
|
|
@@ -9,8 +9,6 @@ Pandana
|
|
|
9
9
|
:alt: Coverage Status
|
|
10
10
|
:target: https://coveralls.io/r/UDST/pandana
|
|
11
11
|
|
|
12
|
-
A nice slideshow showing example code is available
|
|
13
|
-
`here <http://bit.ly/1tivyjw>`__.
|
|
14
12
|
|
|
15
13
|
In this case, a picture is worth a thousand words. The image below shows
|
|
16
14
|
the distance to the *2nd* nearest restaurant (rendered by matplotlib)
|
|
@@ -40,8 +38,8 @@ queries are a more accurate representation of how people interact with
|
|
|
40
38
|
their environment.
|
|
41
39
|
|
|
42
40
|
We look forward to creative uses of a general library like this - please
|
|
43
|
-
let us know
|
|
44
|
-
|
|
41
|
+
let us know if you think you have a great use case by tweeting us at
|
|
42
|
+
``@urbansim`` or post on the UrbanSim `forum`_.
|
|
45
43
|
|
|
46
44
|
Docs
|
|
47
45
|
----
|
|
@@ -56,17 +54,23 @@ Pandana is also available.
|
|
|
56
54
|
Acknowledgments
|
|
57
55
|
---------------
|
|
58
56
|
|
|
59
|
-
None of this would be possible without the help of Dennis Luxen
|
|
60
|
-
|
|
61
|
-
you Dennis!
|
|
62
|
-
|
|
63
|
-
Nearest neighbor queries are performed with the fastest k-d tree around,
|
|
64
|
-
i.e. ANN (http://www.cs.umd.edu/~mount/ANN/).
|
|
57
|
+
None of this would be possible without the help of Dennis Luxen and
|
|
58
|
+
his OSRM (https://github.com/DennisOSRM/Project-OSRM). Thank you Dennis!
|
|
65
59
|
|
|
66
60
|
Academic Literature
|
|
67
61
|
-------------------
|
|
68
62
|
|
|
69
|
-
|
|
70
|
-
methodology <
|
|
71
|
-
|
|
63
|
+
A `complete description of the
|
|
64
|
+
methodology <http://onlinepubs.trb.org/onlinepubs/conferences/2012/4thITM/Papers-A/0117-000062.pdf>`__
|
|
65
|
+
was presented at the Transportation Research Board Annual Conference in 2012. Please cite this paper when referring
|
|
72
66
|
to the methodology implemented by this library.
|
|
67
|
+
|
|
68
|
+
Related UDST libraries
|
|
69
|
+
----------------------
|
|
70
|
+
|
|
71
|
+
- `OSMnet`_
|
|
72
|
+
- `UrbanAccess`_
|
|
73
|
+
|
|
74
|
+
.. _forum: http://discussion.urbansim.com/
|
|
75
|
+
.. _OSMnet: https://github.com/udst/osmnet
|
|
76
|
+
.. _UrbanAccess: https://github.com/UDST/urbanaccess
|
|
@@ -39,6 +39,7 @@ except ImportError:
|
|
|
39
39
|
DEFAULT_VERSION = "5.7"
|
|
40
40
|
DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
|
|
41
41
|
|
|
42
|
+
|
|
42
43
|
def _python_cmd(*args):
|
|
43
44
|
"""
|
|
44
45
|
Return True if the command succeeded.
|
|
@@ -130,7 +131,7 @@ def _do_download(version, download_base, to_dir, download_delay):
|
|
|
130
131
|
|
|
131
132
|
|
|
132
133
|
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
|
133
|
-
|
|
134
|
+
to_dir=os.curdir, download_delay=15):
|
|
134
135
|
to_dir = os.path.abspath(to_dir)
|
|
135
136
|
rep_modules = 'pkg_resources', 'setuptools'
|
|
136
137
|
imported = set(sys.modules).intersection(rep_modules)
|
|
@@ -160,6 +161,7 @@ def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
|
|
160
161
|
del pkg_resources, sys.modules['pkg_resources']
|
|
161
162
|
return _do_download(version, download_base, to_dir, download_delay)
|
|
162
163
|
|
|
164
|
+
|
|
163
165
|
def _clean_check(cmd, target):
|
|
164
166
|
"""
|
|
165
167
|
Run the command to download target. If the command fails, clean up before
|
|
@@ -172,6 +174,7 @@ def _clean_check(cmd, target):
|
|
|
172
174
|
os.unlink(target)
|
|
173
175
|
raise
|
|
174
176
|
|
|
177
|
+
|
|
175
178
|
def download_file_powershell(url, target):
|
|
176
179
|
"""
|
|
177
180
|
Download the file at url to target using Powershell (which will validate
|
|
@@ -191,6 +194,7 @@ def download_file_powershell(url, target):
|
|
|
191
194
|
]
|
|
192
195
|
_clean_check(cmd, target)
|
|
193
196
|
|
|
197
|
+
|
|
194
198
|
def has_powershell():
|
|
195
199
|
if platform.system() != 'Windows':
|
|
196
200
|
return False
|
|
@@ -202,12 +206,15 @@ def has_powershell():
|
|
|
202
206
|
return False
|
|
203
207
|
return True
|
|
204
208
|
|
|
209
|
+
|
|
205
210
|
download_file_powershell.viable = has_powershell
|
|
206
211
|
|
|
212
|
+
|
|
207
213
|
def download_file_curl(url, target):
|
|
208
214
|
cmd = ['curl', url, '--silent', '--output', target]
|
|
209
215
|
_clean_check(cmd, target)
|
|
210
216
|
|
|
217
|
+
|
|
211
218
|
def has_curl():
|
|
212
219
|
cmd = ['curl', '--version']
|
|
213
220
|
with open(os.path.devnull, 'wb') as devnull:
|
|
@@ -217,12 +224,15 @@ def has_curl():
|
|
|
217
224
|
return False
|
|
218
225
|
return True
|
|
219
226
|
|
|
227
|
+
|
|
220
228
|
download_file_curl.viable = has_curl
|
|
221
229
|
|
|
230
|
+
|
|
222
231
|
def download_file_wget(url, target):
|
|
223
232
|
cmd = ['wget', url, '--quiet', '--output-document', target]
|
|
224
233
|
_clean_check(cmd, target)
|
|
225
234
|
|
|
235
|
+
|
|
226
236
|
def has_wget():
|
|
227
237
|
cmd = ['wget', '--version']
|
|
228
238
|
with open(os.path.devnull, 'wb') as devnull:
|
|
@@ -232,8 +242,10 @@ def has_wget():
|
|
|
232
242
|
return False
|
|
233
243
|
return True
|
|
234
244
|
|
|
245
|
+
|
|
235
246
|
download_file_wget.viable = has_wget
|
|
236
247
|
|
|
248
|
+
|
|
237
249
|
def download_file_insecure(url, target):
|
|
238
250
|
"""
|
|
239
251
|
Use Python to download the file, even though it cannot authenticate the
|
|
@@ -250,8 +262,10 @@ def download_file_insecure(url, target):
|
|
|
250
262
|
with open(target, "wb") as dst:
|
|
251
263
|
dst.write(data)
|
|
252
264
|
|
|
265
|
+
|
|
253
266
|
download_file_insecure.viable = lambda: True
|
|
254
267
|
|
|
268
|
+
|
|
255
269
|
def get_best_downloader():
|
|
256
270
|
downloaders = (
|
|
257
271
|
download_file_powershell,
|
|
@@ -262,8 +276,10 @@ def get_best_downloader():
|
|
|
262
276
|
viable_downloaders = (dl for dl in downloaders if dl.viable())
|
|
263
277
|
return next(viable_downloaders, None)
|
|
264
278
|
|
|
279
|
+
|
|
265
280
|
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
|
266
|
-
|
|
281
|
+
to_dir=os.curdir, delay=15,
|
|
282
|
+
downloader_factory=get_best_downloader):
|
|
267
283
|
"""
|
|
268
284
|
Download setuptools from a specified location and return its filename
|
|
269
285
|
|
|
@@ -287,12 +303,14 @@ def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
|
|
|
287
303
|
downloader(url, saveto)
|
|
288
304
|
return os.path.realpath(saveto)
|
|
289
305
|
|
|
306
|
+
|
|
290
307
|
def _build_install_args(options):
|
|
291
308
|
"""
|
|
292
309
|
Build the arguments to 'python setup.py install' on the setuptools package
|
|
293
310
|
"""
|
|
294
311
|
return ['--user'] if options.user_install else []
|
|
295
312
|
|
|
313
|
+
|
|
296
314
|
def _parse_args():
|
|
297
315
|
"""
|
|
298
316
|
Parse the command line for options
|
|
@@ -318,6 +336,7 @@ def _parse_args():
|
|
|
318
336
|
# positional arguments are ignored
|
|
319
337
|
return options
|
|
320
338
|
|
|
339
|
+
|
|
321
340
|
def main():
|
|
322
341
|
"""Install or upgrade setuptools and EasyInstall"""
|
|
323
342
|
options = _parse_args()
|
|
@@ -328,5 +347,6 @@ def main():
|
|
|
328
347
|
)
|
|
329
348
|
return _install(archive, _build_install_args(options))
|
|
330
349
|
|
|
350
|
+
|
|
331
351
|
if __name__ == '__main__':
|
|
332
352
|
sys.exit(main())
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tools for creating Pandana networks from OpenStreetMap.
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import pandas as pd
|
|
7
|
+
import requests
|
|
8
|
+
from osmnet.load import network_from_bbox
|
|
9
|
+
|
|
10
|
+
from .. import Network
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def pdna_network_from_bbox(
|
|
14
|
+
lat_min=None, lng_min=None, lat_max=None, lng_max=None, bbox=None,
|
|
15
|
+
network_type='walk', two_way=True,
|
|
16
|
+
timeout=180, memory=None, max_query_area_size=50 * 1000 * 50 * 1000):
|
|
17
|
+
"""
|
|
18
|
+
Make a Pandana network from a bounding lat/lon box
|
|
19
|
+
request to the Overpass API. Distance will be in the default units meters.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
lat_min, lng_min, lat_max, lng_max : float
|
|
24
|
+
bbox : tuple
|
|
25
|
+
Bounding box formatted as a 4 element tuple:
|
|
26
|
+
(lng_max, lat_min, lng_min, lat_max)
|
|
27
|
+
network_type : {'walk', 'drive'}, optional
|
|
28
|
+
Specify whether the network will be used for walking or driving.
|
|
29
|
+
A value of 'walk' attempts to exclude things like freeways,
|
|
30
|
+
while a value of 'drive' attempts to exclude things like
|
|
31
|
+
bike and walking paths.
|
|
32
|
+
two_way : bool, optional
|
|
33
|
+
Whether the routes are two-way. If True, node pairs will only
|
|
34
|
+
occur once.
|
|
35
|
+
timeout : int, optional
|
|
36
|
+
the timeout interval for requests and to pass to Overpass API
|
|
37
|
+
memory : int, optional
|
|
38
|
+
server memory allocation size for the query, in bytes.
|
|
39
|
+
If none, server will use its default allocation size
|
|
40
|
+
max_query_area_size : float, optional
|
|
41
|
+
max area for any part of the geometry, in the units the geometry is in
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
network : pandana.Network
|
|
46
|
+
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
nodes, edges = network_from_bbox(lat_min=lat_min, lng_min=lng_min,
|
|
50
|
+
lat_max=lat_max, lng_max=lng_max,
|
|
51
|
+
bbox=bbox, network_type=network_type,
|
|
52
|
+
two_way=two_way, timeout=timeout,
|
|
53
|
+
memory=memory,
|
|
54
|
+
max_query_area_size=max_query_area_size)
|
|
55
|
+
|
|
56
|
+
return Network(
|
|
57
|
+
nodes['x'], nodes['y'],
|
|
58
|
+
edges['from'], edges['to'], edges[['distance']])
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def process_node(e):
|
|
62
|
+
"""
|
|
63
|
+
Process a node element entry into a dict suitable for going into
|
|
64
|
+
a Pandas DataFrame.
|
|
65
|
+
|
|
66
|
+
Parameters
|
|
67
|
+
----------
|
|
68
|
+
e : dict
|
|
69
|
+
Returns
|
|
70
|
+
-------
|
|
71
|
+
node : dict
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
uninteresting_tags = {
|
|
75
|
+
'source',
|
|
76
|
+
'source_ref',
|
|
77
|
+
'source:ref',
|
|
78
|
+
'history',
|
|
79
|
+
'attribution',
|
|
80
|
+
'created_by',
|
|
81
|
+
'tiger:tlid',
|
|
82
|
+
'tiger:upload_uuid',
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
node = {
|
|
86
|
+
'id': e['id'],
|
|
87
|
+
'lat': e['lat'],
|
|
88
|
+
'lon': e['lon']
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if 'tags' in e:
|
|
92
|
+
for t, v in list(e['tags'].items()):
|
|
93
|
+
if t not in uninteresting_tags:
|
|
94
|
+
node[t] = v
|
|
95
|
+
|
|
96
|
+
return node
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def make_osm_query(query):
|
|
100
|
+
"""
|
|
101
|
+
Make a request to OSM and return the parsed JSON.
|
|
102
|
+
|
|
103
|
+
Parameters
|
|
104
|
+
----------
|
|
105
|
+
query : str
|
|
106
|
+
A string in the Overpass QL format.
|
|
107
|
+
|
|
108
|
+
Returns
|
|
109
|
+
-------
|
|
110
|
+
data : dict
|
|
111
|
+
|
|
112
|
+
"""
|
|
113
|
+
osm_url = 'http://www.overpass-api.de/api/interpreter'
|
|
114
|
+
req = requests.get(osm_url, params={'data': query})
|
|
115
|
+
req.raise_for_status()
|
|
116
|
+
|
|
117
|
+
return req.json()
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def build_node_query(lat_min, lng_min, lat_max, lng_max, tags=None):
|
|
121
|
+
"""
|
|
122
|
+
Build the string for a node-based OSM query.
|
|
123
|
+
|
|
124
|
+
Parameters
|
|
125
|
+
----------
|
|
126
|
+
lat_min, lng_min, lat_max, lng_max : float
|
|
127
|
+
tags : str or list of str, optional
|
|
128
|
+
Node tags that will be used to filter the search.
|
|
129
|
+
See http://wiki.openstreetmap.org/wiki/Overpass_API/Language_Guide
|
|
130
|
+
for information about OSM Overpass queries
|
|
131
|
+
and http://wiki.openstreetmap.org/wiki/Map_Features
|
|
132
|
+
for a list of tags.
|
|
133
|
+
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
query : str
|
|
137
|
+
|
|
138
|
+
"""
|
|
139
|
+
if tags is not None:
|
|
140
|
+
if isinstance(tags, str):
|
|
141
|
+
tags = [tags]
|
|
142
|
+
tags = ''.join('[{}]'.format(t) for t in tags)
|
|
143
|
+
else:
|
|
144
|
+
tags = ''
|
|
145
|
+
|
|
146
|
+
query_fmt = (
|
|
147
|
+
'[out:json];'
|
|
148
|
+
'('
|
|
149
|
+
' node'
|
|
150
|
+
' {tags}'
|
|
151
|
+
' ({lat_min},{lng_min},{lat_max},{lng_max});'
|
|
152
|
+
');'
|
|
153
|
+
'out;')
|
|
154
|
+
|
|
155
|
+
return query_fmt.format(
|
|
156
|
+
lat_min=lat_min, lng_min=lng_min, lat_max=lat_max, lng_max=lng_max,
|
|
157
|
+
tags=tags)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def node_query(lat_min, lng_min, lat_max, lng_max, tags=None):
|
|
161
|
+
"""
|
|
162
|
+
Search for OSM nodes within a bounding box that match given tags.
|
|
163
|
+
|
|
164
|
+
Parameters
|
|
165
|
+
----------
|
|
166
|
+
lat_min, lng_min, lat_max, lng_max : float
|
|
167
|
+
tags : str or list of str, optional
|
|
168
|
+
Node tags that will be used to filter the search.
|
|
169
|
+
See http://wiki.openstreetmap.org/wiki/Overpass_API/Language_Guide
|
|
170
|
+
for information about OSM Overpass queries
|
|
171
|
+
and http://wiki.openstreetmap.org/wiki/Map_Features
|
|
172
|
+
for a list of tags.
|
|
173
|
+
|
|
174
|
+
Returns
|
|
175
|
+
-------
|
|
176
|
+
nodes : pandas.DataFrame
|
|
177
|
+
Will have 'lat' and 'lon' columns, plus other columns for the
|
|
178
|
+
tags associated with the node (these will vary based on the query).
|
|
179
|
+
Index will be the OSM node IDs.
|
|
180
|
+
|
|
181
|
+
"""
|
|
182
|
+
node_data = make_osm_query(build_node_query(
|
|
183
|
+
lat_min, lng_min, lat_max, lng_max, tags=tags))
|
|
184
|
+
|
|
185
|
+
if len(node_data['elements']) == 0:
|
|
186
|
+
raise RuntimeError('OSM query results contain no data.')
|
|
187
|
+
|
|
188
|
+
nodes = [process_node(n) for n in node_data['elements']]
|
|
189
|
+
return pd.DataFrame.from_records(nodes, index='id')
|