def _request_network(self): """ Fetch a street network from OSM for the current query. Raises: UnableToConnectException: network connection is unavailable. """ try: if self.network_type == 'bike': osm_bike_filter = '["highway"!~"motor|proposed|construction|abandoned|platform|raceway"]["foot"!~"no"]["bicycle"!~"no"]' self.nodes, self.edges = network_from_bbox( lat_min=self.bbox[0], lng_min=self.bbox[1], lat_max=self.bbox[2], lng_max=self.bbox[3], custom_osm_filter=osm_bike_filter) else: self.nodes, self.edges = network_from_bbox( lat_min=self.bbox[0], lng_min=self.bbox[1], lat_max=self.bbox[2], lng_max=self.bbox[3], network_type=self.network_type) if self.network_type == 'drive': self.edges.drop( ['access', 'hgv', 'lanes', 'maxspeed', 'tunnel'], inplace=True, axis=1) else: self.edges.drop( ['access', 'bridge', 'lanes', 'service', 'tunnel'], inplace=True, axis=1) filename = self._get_filename() self.nodes.to_hdf(filename, 'nodes', complevel=5) self.edges.to_hdf(filename, 'edges', complevel=5) if self.logger: self.logger.info('Finished querying osm') self.logger.debug('Cached network to %s', filename) except BaseException as e: request_error = """Error trying to download OSM network. Did you reverse lat/long? Is your network connection functional? """ if self.logger: self.logger.debug(e) self.logger.error(request_error) raise UnableToConnectException()
def test_custom_query_pass(bbox5): nodes, edges = load.network_from_bbox( bbox=bbox5, custom_osm_filter='["highway"="service"]' ) assert len(nodes) == 22 assert len(edges) == 30 assert edges['highway'].unique() == 'service'
def test_column_names(bbox4): nodes, edges = load.network_from_bbox( bbox=bbox4, network_type='walk', timeout=180, memory=None, max_query_area_size=50*1000*50*1000 ) col_list = ['x', 'y', 'id'] for col in col_list: assert col in nodes.columns col_list = ['distance', 'from', 'to'] for col in col_list: assert col in edges.columns
def pdna_network_from_bbox( lat_min=None, lng_min=None, lat_max=None, lng_max=None, bbox=None, network_type='walk', two_way=True, timeout=180, memory=None, max_query_area_size=50 * 1000 * 50 * 1000): """ Make a Pandana network from a bounding lat/lon box request to the Overpass API. Distance will be in the default units meters. Parameters ---------- lat_min, lng_min, lat_max, lng_max : float bbox : tuple Bounding box formatted as a 4 element tuple: (lng_max, lat_min, lng_min, lat_max) network_type : {'walk', 'drive'}, optional Specify whether the network will be used for walking or driving. A value of 'walk' attempts to exclude things like freeways, while a value of 'drive' attempts to exclude things like bike and walking paths. two_way : bool, optional Whether the routes are two-way. If True, node pairs will only occur once. timeout : int, optional the timeout interval for requests and to pass to Overpass API memory : int, optional server memory allocation size for the query, in bytes. If none, server will use its default allocation size max_query_area_size : float, optional max area for any part of the geometry, in the units the geometry is in Returns ------- network : pandana.Network """ nodes, edges = network_from_bbox(lat_min=lat_min, lng_min=lng_min, lat_max=lat_max, lng_max=lng_max, bbox=bbox, network_type=network_type, two_way=two_way, timeout=timeout, memory=memory, max_query_area_size=max_query_area_size) return Network( nodes['x'], nodes['y'], edges['from'], edges['to'], edges[['distance']])
def ua_network_from_bbox(lat_min=None, lng_min=None, lat_max=None, lng_max=None, bbox=None, network_type='walk', timeout=180, memory=None, max_query_area_size=50 * 1000 * 50 * 1000, remove_lcn=True): """ Make a graph network (nodes and edges) from a bounding lat/lon box that is compatible with the network analysis tool Pandana Parameters ---------- lat_min : float southern latitude of bounding box lng_min : float eastern longitude of bounding box lat_max : float northern latitude of bounding box lng_max : float western longitude of bounding box bbox : tuple Bounding box formatted as a 4 element tuple: (lng_max, lat_min, lng_min, lat_max) example: (-122.304611,37.798933,-122.263412,37.822802) a bbox can be extracted for an area using: the CSV format bbox from http://boundingbox.klokantech.com/ network_type : {'walk', 'drive'}, optional Specify the network type where value of 'walk' includes roadways where pedestrians are allowed and pedestrian pathways and 'drive' includes driveable roadways. Default is walk. timeout : int, optional the timeout interval for requests and to pass to Overpass API memory : int, optional server memory allocation size for the query, in bytes. If none, server will use its default allocation size max_query_area_size : float, optional max area for any part of the geometry, in the units the geometry is in: any polygon bigger will get divided up for multiple queries to Overpass API (default is 50,000 * 50,000 units (ie, 50km x 50km in area, if units are meters)) remove_lcn : bool, optional remove low connectivity nodes from the resulting network. this ensures the resulting network does not have nodes that are unconnected from the rest of the larger network Returns ------- nodesfinal, edgesfinal : pandas.DataFrame """ start_time = time.time() # returned osm data allows travel in both directions # so that all edges in integrated network are all one way edges two_way = False nodes, edges = network_from_bbox(lat_min=lat_min, lng_min=lng_min, lat_max=lat_max, lng_max=lng_max, bbox=bbox, network_type=network_type, two_way=two_way, timeout=timeout, memory=memory, max_query_area_size=max_query_area_size) # remove low connectivity nodes and return cleaned nodes and edges if remove_lcn: log('checking for low connectivity nodes...') pandana_net = Network(nodes['x'], nodes['y'], edges['from'], edges['to'], edges[['distance']]) lcn = pandana_net.low_connectivity_nodes(impedance=10000, count=10, imp_name='distance') log('{:,} out of {:,} nodes ({:.2f} percent of total) were ' 'identified as having low connectivity and have ' 'been removed.'.format(len(lcn), len(nodes), (len(lcn) / len(nodes)) * 100)) rm_nodes = set(lcn) nodes_to_keep = ~nodes.index.isin(rm_nodes) edges_to_keep = ~(edges['from'].isin(rm_nodes) | edges['to'].isin(rm_nodes)) nodes = nodes.loc[nodes_to_keep] edges = edges.loc[edges_to_keep] log('Completed OSM data download and graph node and edge table ' 'creation in {:,.2f} seconds'.format(time.time() - start_time)) return nodes, edges else: log('Completed OSM data download and graph node and edge table ' 'creation in {:,.2f} seconds'.format(time.time() - start_time)) return nodes, edges
def ua_network_from_bbox(lat_min=None, lng_min=None, lat_max=None, lng_max=None, bbox=None, network_type='walk', timeout=180, memory=None, max_query_area_size=50 * 1000 * 50 * 1000, remove_lcn=True): """ Make a graph network (nodes and edges) from a bounding lat/lon box that is compatible with the network analysis tool Pandana Parameters ---------- lat_min : float southern latitude of bounding box lng_min : float eastern longitude of bounding box lat_max : float northern latitude of bounding box lng_max : float western longitude of bounding box bbox : tuple Bounding box formatted as a 4 element tuple: (lng_max, lat_min, lng_min, lat_max) example: (-122.304611,37.798933,-122.263412,37.822802) a bbox can be extracted for an area using: the CSV format bbox from http://boundingbox.klokantech.com/ network_type : {'walk', 'drive'}, optional Specify the network type where value of 'walk' includes roadways where pedestrians are allowed and pedestrian pathways and 'drive' includes driveable roadways. Default is walk. timeout : int, optional the timeout interval for requests and to pass to Overpass API memory : int, optional server memory allocation size for the query, in bytes. If none, server will use its default allocation size max_query_area_size : float, optional max area for any part of the geometry, in the units the geometry is in: any polygon bigger will get divided up for multiple queries to Overpass API (default is 50,000 * 50,000 units (ie, 50km x 50km in area, if units are meters)) remove_lcn : bool, optional remove low connectivity nodes from the resulting network. this ensures the resulting network does not have nodes that are unconnected from the rest of the larger network Returns ------- nodesfinal, edgesfinal : pandas.DataFrame """ start_time = time.time() # returned osm data allows travel in both directions so that # all edges in integrated network are considered one way edges two_way = False # this function a wrapper around the below OSMnet function nodes, edges = network_from_bbox(lat_min=lat_min, lng_min=lng_min, lat_max=lat_max, lng_max=lng_max, bbox=bbox, network_type=network_type, two_way=two_way, timeout=timeout, memory=memory, max_query_area_size=max_query_area_size) # only perform operations if requested by user if remove_lcn: log('checking for low connectivity nodes...') # create a Pandana network... pandana_net = Network(nodes['x'], nodes['y'], edges['from'], edges['to'], edges[['distance']]) # ...so we can remove low connectivity nodes lcn = pandana_net.low_connectivity_nodes(impedance=10000, count=10, imp_name='distance') # report how many nodes will be dropped lcn_to_node_ratio = ((len(lcn) / len(nodes)) * 100) removed_msg = ('{:,} out of {:,} nodes ({:.2f} percent ' 'of total) were identified as having low ' 'connectivity and have been ' 'removed.').format(len(lcn), len(nodes), lcn_to_node_ratio) log(removed_msg) # get unique node ids to drop rm_nodes = set(lcn) # for nodes, only keep those whose index is not in the # low connectivity nodes set list nodes_in_rm_nodes = nodes.index.isin(rm_nodes) nodes = nodes.loc[~nodes_in_rm_nodes] # similarly, we must remove all edges connected to these nodes e_fr = edges['from'] e_to = edges['to'] edges_attached_to_rm_nodes = e_fr.isin(rm_nodes) | e_to.isin(rm_nodes) edges = edges.loc[~edges_attached_to_rm_nodes] # report back performance time removal_time_diff = time.time() - start_time completed_removal = ('Completed OSM data download and graph ' 'node and edge table creation in {:,.2f} ' 'seconds').format(removal_time_diff) log(completed_removal) else: # let user know step being skipped, report back performance time no_removal_time_diff = time.time() - start_time no_removal_msg = ('Completed OSM data download and graph node ' 'and edge table creation in {:,.2f} ' 'seconds').format(no_removal_time_diff) log(no_removal_msg) return nodes, edges
def pdna_network_from_bbox(lat_min=None, lng_min=None, lat_max=None, lng_max=None, bbox=None, network_type='walk', two_way=True, timeout=180, memory=None, max_query_area_size=50 * 1000 * 50 * 1000): """ Make a Pandana network from a bounding lat/lon box via a request to the OpenStreetMap Overpass API. Distance will be in meters. Requires installing the OSMnet library. Parameters ---------- lat_min, lng_min, lat_max, lng_max : float bbox : tuple Bounding box formatted as a 4 element tuple: (lng_max, lat_min, lng_min, lat_max) network_type : {'walk', 'drive'}, optional Specify whether the network will be used for walking or driving. A value of 'walk' attempts to exclude things like freeways, while a value of 'drive' attempts to exclude things like bike and walking paths. two_way : bool, optional Whether the routes are two-way. If True, node pairs will only occur once. timeout : int, optional the timeout interval for requests and to pass to Overpass API memory : int, optional server memory allocation size for the query, in bytes. If none, server will use its default allocation size max_query_area_size : float, optional max area for any part of the geometry, in the units the geometry is in Returns ------- network : pandana.Network """ try: ModuleNotFoundError # Python 3.6+ except NameError: ModuleNotFoundError = ImportError try: from osmnet.load import network_from_bbox except ModuleNotFoundError: raise ModuleNotFoundError("OSM downloads require the OSMnet library: " "https://udst.github.io/osmnet/") nodes, edges = network_from_bbox(lat_min=lat_min, lng_min=lng_min, lat_max=lat_max, lng_max=lng_max, bbox=bbox, network_type=network_type, two_way=two_way, timeout=timeout, memory=memory, max_query_area_size=max_query_area_size) return Network(nodes['x'], nodes['y'], edges['from'], edges['to'], edges[['distance']])