def test_gdf_from_place(): # test loading spatial boundaries and plotting city = ox.gdf_from_place(place1) city_projected = ox.projection.project_gdf(city, to_crs="epsg:3395") city = ox.gdf_from_place(place1, buffer_dist=100) ox.plot_shape(city)
def get_outline(city_str, i_max=4): #We define a success flag and an error message in case we can't find the # city outline: success = False error = None #Ideally, we should get it very simply from OSMnx: gdf = ox.gdf_from_place(city_str) #If there are no result, then there is nothing we can do: if gdf.size == 0: error = "NoResultError" #In case there is at least one result, we should inspect it to know if it # is good or if we need to search for other results: else: gdf, success, error = inspect(gdf) #In case we did not achieve success, we can check other results of # the gdf search: if success == "False": i = 2 while i < i_max and success == False: try: gdf = ox.gdf_from_place(city_str, which_result=i) if gdf.size != 0: gdf, success, error = inspect(gdf) i += 1 else: #In this case there are no more significant results: i = i_max #Of course, there may not be i results. In this case there is # no need on iterating further: except: i = i_max return success, error, gdf
def get_polygon(string): lis = glob('data/AOI/*/*.shp') city = [] for i in lis: x = i.split('\\')[-1] city.append(x.split('_')[0]) if string in city: l = glob('data/AOI/{}/*.shp'.format(string)) adm = gpd.GeoDataFrame.from_file(l[0]) adm = adm.to_crs(epsg=4326) pol = [i for i in adm.geometry] boundary_poly = cascaded_union(pol) else: boundary_GDF = ox.gdf_from_place('{}'.format(string), which_result=1) boundary_poly = boundary_GDF.loc[0, 'geometry'] if boundary_poly.geom_type == 'Polygon': boundary_poly = boundary_poly else: try: boundary_GDF = ox.gdf_from_place('{}'.format(string), which_result=2) boundary_poly = boundary_GDF.loc[0, 'geometry'] except: print('Polygon not available') boundary_poly = -1 return boundary_poly
def test_gdf_shapefiles(): # test loading spatial boundaries, saving as shapefile, and plotting city = ox.gdf_from_place('Manhattan, New York City, New York, USA') city_projected = ox.project_gdf(city, to_crs={'init': 'epsg:3395'}) ox.save_gdf_shapefile(city_projected) city = ox.gdf_from_place('Manhattan, New York City, New York, USA', buffer_dist=100) ox.plot_shape(city)
def test_gdf_shapefiles(): city = ox.gdf_from_place('Manhattan, New York City, New York, USA') city_projected = ox.project_gdf(city, to_crs={'init':'epsg:3395'}) ox.save_gdf_shapefile(city_projected) city = ox.gdf_from_place('Manhattan, New York City, New York, USA', buffer_dist=100) ox.plot_shape(city)
def test_gdf_shapefiles(): # test loading spatial boundaries, saving as shapefile, and plotting city = ox.gdf_from_place('Manhattan, New York City, New York, USA') city_projected = ox.project_gdf(city, to_crs={'init':'epsg:3395'}) ox.save_gdf_shapefile(city_projected) city = ox.gdf_from_place('Manhattan, New York City, New York, USA', buffer_dist=100) ox.plot_shape(city)
def test_gdf_shapefiles(): with httmock.HTTMock(get_mock_response_content()): city = ox.gdf_from_place('Manhattan, New York City, New York, USA') city_projected = ox.project_gdf(city, to_crs={'init':'epsg:3395'}) ox.save_gdf_shapefile(city_projected) with httmock.HTTMock(get_mock_response_content()): city = ox.gdf_from_place('Manhattan, New York City, New York, USA', buffer_dist=100) ox.plot_shape(city)
def bbox_from_name(area_name, crs=None): # Get the shape by using osmnx, it returns the shape in DEFAULT_CRS boundary = osmnx.gdf_from_place(area_name) if isinstance(boundary.loc[0]['geometry'], shapely.geometry.Point): boundary = osmnx.gdf_from_place(area_name, which_result=2) if crs is None: return boundary return boundary.to_crs(crs)
def _gdf_from_places(queries): """ Create a GeoDataFrame from a list of place names to query. Parameters ---------- queries : list list of query strings or structured query dicts to geocode/download, one at a time gdf_name : string name attribute metadata for GeoDataFrame (this is used to save shapefile later) buffer_dist : float distance to buffer around the place geometry, in meters Returns ------- GeoDataFrame """ # create an empty GeoDataFrame then append each result as a new row gdf = gpd.GeoDataFrame() for query in queries: gdf = gdf.append( ox.gdf_from_place(query['query_str'], query['which_result'])) # reset the index, name the GeoDataFrame gdf = gdf.reset_index().drop(labels='index', axis=1) gdf.gdf_name = 'unnamed' # set the original CRS of the GeoDataFrame to default_crs, and return it gdf.crs = ox.settings.default_crs ox.utils.log( 'Finished creating GeoDataFrame with {} rows from {} queries'.format( len(gdf), len(queries))) return gdf
def test_pois(): import pytest # download all points of interests from place gdf = ox.pois_from_place(place='Kamppi, Helsinki, Finland') # get all restaurants and schools from place restaurants = ox.pois_from_place(place='Emeryville, California, USA', amenities=['restaurant']) schools = ox.pois_from_place(place='Emeryville, California, USA', amenities=['school']) # get all universities from Boston area (with 2 km buffer to cover also Cambridge) boston_q = "Boston, Massachusetts, United States of America" boston_poly = ox.gdf_from_place(boston_q, buffer_dist=2000) universities = ox.pois_from_polygon(boston_poly.geometry.values[0], amenities=['university']) # by point and by address restaurants = ox.pois_from_point(point=(42.344490, -71.070570), distance=1000, amenities=['restaurant']) restaurants = ox.pois_from_address(address='Emeryville, California, USA', distance=1000, amenities=['restaurant']) # should raise an exception # polygon or -north, south, east, west- should be provided with pytest.raises(ValueError): ox.create_poi_gdf(polygon=None, north=None, south=None, east=None, west=None) gdf = ox.pois_from_place(place='kusatsu, shiga, japan', which_result=2)
def GetOSMdata(placename='University of Lagos', EPSGcode='28992'): """This function uses the OSMNX package to extract a geometry representing the placename provided as input and transforms to the required projection (EPSG code)""" CampusGDF = ox.gdf_from_place(placename) CampusGDF = ox.project_gdf(CampusGDF, to_latlong = True) bboxUniversity_Lagos = list(CampusGDF.total_bounds) xmin, ymin, xmax, ymax = bboxWageningen BuildingsGDF = ox.footprints.create_footprints_gdf(polygon=CampusGDF, west=xmin, south=ymin, east=xmax, north=ymax, footprint_type='building') BuildingsGDF = gpd.overlay(CampusGDF, BuildingsGDF, how='intersection') PavedGDF = ox.footprints.create_footprints_gdf(polygon=CampusGDF, west=xmin, south=ymin, east=xmax, north=ymax, footprint_type='highway') PavedGDF = gpd.overlay(PavedGDF, BuildingsGDF, how="difference") WaterGDF = ox.footprints.create_footprints_gdf(polygon=CampusGDF, west=xmin, south=ymin, east=xmax, north=ymax, footprint_type='water') WaterGDF = gpd.overlay(WaterGDF, PavedGDF, how="difference") GreenGDF = ox.footprints.create_footprints_gdf(polygon = CampusGDF, north=ymax, south=ymin, east=xmax, west=xmin, footprint_type='natural') GreenGDF = gpd.overlay(GreenGDF, CampusGDF, how="intersection") CampusGDF = ox.projection.project_gdf(CampusGDF) BuildingsGDF = ox.projection.project_gdf(BuildingsGDF) PavedGDF = ox.projection.project_gdf(PavedGDF) WaterGDF = ox.projection.project_gdf(WaterGDF) GreenGDF = ox.projection.project_gdf(GreenGDF) return CampusGDF, BuildingsGDF, PavedGDF, WaterGDF, GreenGDF
def main(): city = ox.gdf_from_place('San Francisco, California, USA') G = ox.graph_from_place('San Francisco, California, USA') fullTransition = collections.defaultdict(dict) for node in G.nodes(): #print G.node[node].keys() #print node['lat'] nodeLat = G.nodes[node]['x'] nodeLong = G.nodes[node]['y'] key = (nodeLat, nodeLong) if key not in fullTransition: allEdgeList = [] allEdges = G.edges(node) for edge in allEdges: transition = edge[1] if transition in G.nodes(): transitionLat = G.nodes[transition]['x'] transitionLong = G.nodes[transition]['y'] allEdgeList.append((transitionLat, transitionLong)) fullTransition[key] = allEdgeList #fullTransition[key] = 0 new_df = [] for k, v in fullTransition.iteritems(): for value in v: new_df.append([k, value]) ndf = pd.DataFrame(new_df, columns=['s', 's*']) ndf.to_csv("edges.csv")
def get_graph(place): string = place.split(',')[0] print('Fetching graph data for {}'.format(place)) poly = get_polygon(string) if poly == -1: gdf = ox.gdf_from_place('{}'.format(string)) G = ox.graph_from_bbox(gdf.bbox_north, gdf.bbox_south, gdf.bbox_east, gdf.bbox_west) val = 0 else: try: G = nx.read_gpickle('data/{a}/{a}'.format(a=string)) val = 1 except FileNotFoundError: G = ox.graph_from_polygon(poly, network_type='drive') val = 0 G = ox.project_graph(G) print('Writing graph file') try: os.mkdir('data/{}'.format(string)) except FileExistsError: pass if val != 1: nx.write_gpickle(G, path='data/{a}/{a}'.format(a=string)) return G
def __init__(self): # uncomment for log console ox.config(use_cache=True, log_console=True) self.italy_gdf = ox.gdf_from_place('Italy') self.map = None self.route = None self.route_cache = [] self.load_Italy()
def get_osm_polygon(self, name, select=1, buffer_dist=20): log.info('searching for query=%s, which_result=%s', name, select) gdf = osmnx.gdf_from_place(name, buffer_dist=buffer_dist, which_result=select) log.info('gdf=%s', gdf) polygon = gdf.geometry.values[0] return polygon
def draw_map(self, padx=0.001, pady=0.001): """ Generate a 2d matplotlib plot with buildings and the drone flight path Args: padx: the number of meters to add either side of the drone data. TODO: Actually make this meters, not latitude pady: the number of meters to add top and bottom of the drone data. TODO: Actually make this meters, not longitude Returns: fig: A matplotlib figure containing the drone map """ north = max(self.drone_data["OSD.latitude"]) + pady south = min(self.drone_data["OSD.latitude"]) - pady east = max(self.drone_data["OSD.longitude"]) + padx west = min(self.drone_data["OSD.longitude"]) - padx # Fetch the OSM data place = "Åkersberga, Sweden" graph = ox.graph_from_bbox(north, south, east, west) area = ox.gdf_from_place(place) buildings = ox.create_footprints_gdf( "shapely Polygon", north, south, east, west) _, edges = ox.graph_to_gdfs(graph) # Plot the different map features self.fig, self.ax = plt.subplots(figsize=(10, 7)) area.plot(ax=self.ax, facecolor='black') edges.plot(ax=self.ax, linewidth=1, edgecolor='#BC8F8F') buildings.plot(ax=self.ax, facecolor='khaki', alpha=0.7) try: leisure = ox.create_footprints_gdf( "shapely Polygon", north, south, east, west, "leisure") parks = leisure[leisure["leisure"].isin(["park","playground"])] parks.plot(ax=self.ax, facecolor='limegreen') except: print("No parks within bbox") self.ax.axis("equal") self.ax.set_xlim(west, east) self.xlim_diff = east - west self.ax.set_ylim(north, south) plt.tight_layout() # Event handlers def on_xlims_change(axes): # Update the reference scale for arrow drawing # TODO: Find some way to update the map on zoom action, rather than # having to wait for the slider to be updated x, xmax = self.ax.get_xlim() self.xlim_diff = xmax - x # Set callback, to update arrow size when screen is zoomed self.ax.callbacks.connect('xlim_changed', on_xlims_change)
def recover_osm_area(self): """ Recover area from OpenStreetMap, based of a name of locality :return: GeoDataFrame (epsg: 4326) : gdf_area """ logging.info("data recovery from OSM") logging.info("-- recover territory") self.gdf_area = ox.gdf_from_place(self.place_name) assert self.gdf_area.count().max > 0, "No territory name {}".format(self.place_name)
def calcStats(self, G, city): gdf = ox.gdf_from_place(city) area = ox.project_gdf(gdf).unary_union.area stats = ox.stats.basic_stats(G, area=area) stat = {} stat["length_total"] = stats["edge_length_total"] stat["length_single"] = stats["street_length_total"] stat["length_average"] = stats["street_length_avg"] stat["length_density"] = stats["edge_density_km"] stat["intersection_density"] = stats["intersection_density_km"] return stat
def get_buildings(city_name): """ Arguments : city_name = string ('Loerrach, Baden-Wuerttemberg, Gernamy') Downloads the footprint of the city buildings form osm database. Returns a GeoDataFrame gdf. """ # download city boundary city = ox.gdf_from_place(city_name).geometry.iloc[0] # download buildings inside the boundary buildings = ox.buildings.create_buildings_gdf(city) return buildings
def get_street_structure(city_name): """ Get street structure of a city :param city_name: city name like 'Campbell, California, USA' :return: a tuple of list of paths and a nodes dictionary """ city_boundaries = ox.gdf_from_place(city_name) city_paths_nodes = ox.osm_net_download( city_boundaries['geometry'].unary_union, network_type="drive") nodes_dict = get_nodes_dict(city_paths_nodes) paths = [p for p in city_paths_nodes[0]['elements'] if p['type'] != 'node'] return paths, nodes_dict
def fetch_osm_data(name): """ Fetch OSM data for a given place. :param str name: name of the place. """ logging.info("Fetching city graph for {!r}".format(name)) # Find the place by name and convert it to a polygon gdf = osmnx.gdf_from_place(name) logging.info("Found geodata frame") polygon = gdf["geometry"].unary_union if not isinstance(polygon, (Polygon, MultiPolygon)): raise ValueError( "invalid geometry. " "Expected Polygon or MultiPolygon, but got {} instead. " "Perhabs the place does not exist.".format(type(polygon))) # Fetch all the networks and public transportation routes networks = {} for path_type in list(TransportType): if path_type in TRANSPORT_TO_NETWORK: logging.info("Fetching {} network".format(path_type)) network_type = TRANSPORT_TO_NETWORK[path_type] networks[path_type] = osmnx.graph_from_polygon( polygon, network_type=network_type, simplify=False) elif path_type in TRANSPORT_TO_ROUTE: logging.info("Fetching {} routes".format(path_type)) route_type = TRANSPORT_TO_ROUTE[path_type] networks[path_type] = routes_from_polygon(polygon, route_type=route_type) else: logging.warning( "TransportType {} is not recognized as either network type " "or route type. Ignoring it".format(path_type)) # Fetch all the building footprints logging.info("Importing footprints") footprints = osmnx.footprints_from_polygon(polygon) footprints["name"] = footprints["name"].fillna(value="") # Fetch all the points of interest logging.info("Importing points of interest") pois = pois_from_polygon(polygon) pois["name"] = pois["name"].fillna(value="") return gdf, networks, footprints, pois
def download_place(place, network_type='drive', file_prefix=None, which_result=1, project=True, tolerance=0): """ Downloads streets and buildings for a place, saves the data to disk and returns them """ if file_prefix is None: file_prefix = 'data/{}'.format(utils.string_to_filename(place)) if which_result is None: which_result = which_result_polygon(place) # Streets streets = ox.graph_from_place(place, network_type=network_type, which_result=which_result) if project: streets = ox.project_graph(streets) filename_streets = '{}_streets.pickle.xz'.format(file_prefix) utils.save(streets, filename_streets) # Boundary and buildings boundary = ox.gdf_from_place(place, which_result=which_result) polygon = boundary['geometry'].iloc[0] buildings = ox.create_buildings_gdf(polygon) if project: buildings = ox.project_gdf(buildings) boundary = ox.project_gdf(boundary) # Save buildings filename_buildings = '{}_buildings.pickle.xz'.format(file_prefix) utils.save(buildings, filename_buildings) # Build and save simplified buildings if tolerance != 0: filename_buildings_simpl = '{}_buildings_{:.2f}.pickle.xz'.format( file_prefix, tolerance) buildings = simplify_buildings(buildings) utils.save(buildings, filename_buildings_simpl) # Save boundary filename_boundary = '{}_boundary.pickle.xz'.format(file_prefix) utils.save(boundary, filename_boundary) # Return data data = {'streets': streets, 'buildings': buildings, 'boundary': boundary} return data
def build_gdf(places, gdf_name, location=PATH_GDF, save_gdf=True): places = [places] if isinstance(places, list) else places state = False print(f'Building GDF for {places}') try: gdf = ox.gdf_from_place(places, gdf_name=gdf_name) ox.save_gdf_shapefile(gdf, gdf_name, location) if save_gdf else None state = True except Exception as exc: print(exc) return state
def test_pois(): # download all points of interests from place gdf = ox.pois_from_place(place='Kamppi, Helsinki, Finland') # Get all restaurants and schools from place restaurants = ox.pois_from_place(place='Emeryville, California, USA', amenities=['restaurant']) schools = ox.pois_from_place(place='Emeryville, California, USA', amenities=['school']) # Get all Universities from Boston area (with 2 km buffer to cover also Cambridge) boston_q = "Boston, Massachusetts, United States of America" boston_poly = ox.gdf_from_place(boston_q, buffer_dist=2000) universities = ox.pois_from_polygon(boston_poly.geometry.values[0], amenities=['university'])
def GeocodePlacenameToGDF(placename='AOI', EPSGcode='28992'): """This function uses the OSMNX package to extract a geometry representing the placename provided as input and transforms to the required projection (EPSG code)""" import osmnx as ox PlaceGDF = ox.gdf_from_place(placename) # check first whether there is any output to return if len(PlaceGDF) == 1: # project GDFs to the required projection crs = 'epsg:'+EPSGcode try: PlaceGDF = PlaceGDF.to_crs({'init': crs}) except: print("Given EPSG-code doesn't exist") else: return PlaceGDF else: print("We're sorry, but the given placename is not found within OpenStreetMap. Check for typos or try another placename")
def test_pois(): # download all points of interests from place gdf = ox.pois_from_place(place='Kamppi, Helsinki, Finland') # get all restaurants and schools from place restaurants = ox.pois_from_place(place='Emeryville, California, USA', amenities=['restaurant']) schools = ox.pois_from_place(place='Emeryville, California, USA', amenities=['school']) # get all universities from Boston area (with 2 km buffer to cover also Cambridge) boston_q = "Boston, Massachusetts, United States of America" boston_poly = ox.gdf_from_place(boston_q, buffer_dist=2000) universities = ox.pois_from_polygon(boston_poly.geometry.values[0], amenities=['university']) # by point and by address restaurants = ox.pois_from_point(point=(42.344490, -71.070570), distance=1000, amenities=['restaurant']) restaurants = ox.pois_from_address(address='Emeryville, California, USA', distance=1000, amenities=['restaurant'])
def __init__(self, name: str): """[summary] Args: name (str): [description] Raises: TypeError: [description] """ self.name = name self.gdf = ox.gdf_from_place(name) self.official_name = self.gdf.place_name.values[0] self.geometry = self.gdf.geometry[0] if not type(self.geometry) is Polygon or type( self.geometry) is MultiPolygon: raise TypeError( "Location geometry was not a Polygon or a MultiPolygon")
def get_polygon(place): """ Get Polygon Parameters ---------- df_osm_data : geopandas.GeoDataFrame input OSM data frame geo_filename : string filename for GeoDataFrame storage Returns Polygon """ # Get polygon poly_gdf = ox.gdf_from_place(place, which_result=1) polygon = poly_gdf.geometry[0] return polygon
def get_city_from_osm(city_name, network_type="drive"): """ Get city data from OSM as an osmnx data structure. :param city_name: city name like 'Campbell, California, USA' :param network_type: string: {'walk', 'bike', 'drive', 'drive_service', 'all', 'all_private', 'none'} :return: city data structure """ city_paths_nodes = None for which_result in range(1, 4): try: city_boundaries = ox.gdf_from_place(city_name, which_result=which_result) city_paths_nodes = ox.osm_net_download( city_boundaries['geometry'].unary_union, network_type=network_type) break except Exception as e: logger.exception(e) return None return city_paths_nodes
def download_streets_from_name(place, which_result=1, prefix=None, directory='', debug=False, use_sumo_downloader=False, script_dir=None): """Downloads a street data defined by it's name from OpenStreetMap""" # Setup OSMnx ox_a.setup() if use_sumo_downloader: if script_dir is None: script_dir = search_tool_dir() api_resp = ox.osm_polygon_download( place, limit=which_result, polygon_geojson=0) if not api_resp: raise RuntimeError('Place not found') area_id = api_resp[which_result - 1]['osm_id'] exit_code = download_streets_from_id( area_id, prefix, directory, debug, script_dir) return exit_code else: if prefix is None: prefix = 'osm' file_name = prefix + '_city.osm.xml' file_path = os.path.join(directory, file_name) gdf_place = ox.gdf_from_place(place, which_result=which_result) polygon = gdf_place['geometry'].unary_union response = osm_xml.osm_net_download(polygon, network_type='drive') with open(file_path, 'wb') as file: return_code = file.write(response[0]) return return_code
def city_polygon_bbox(city_name): """ Get the polygon, the bounding box and the place name (with region, country, etc) of a city :param city_name: the city of intereset (eg 'Toulouse') :return: a tuple of (shapely Polygon, bbox [east, north, west, south], place name [string]) """ city = osmnx.gdf_from_place(city_name) # retrieve data from row row = city.loc[0] polygon = row.get('geometry') bbox_east = row.get('bbox_east') bbox_north = row.get('bbox_north') bbox_south = row.get('bbox_south') bbox_west = row.get('bbox_west') place_name = row.get('place_name') # build bbox bbox = (bbox_east, bbox_north, bbox_west, bbox_south) return polygon, bbox, place_name
def get_bufferedstudyregion_bbox(filepath, place=None, buffer_dist=1e4, crs=None, to_crs=None, to_latlong=True): """ If the studyregion shapefile exist: Get bbox from a GeoDataFrame file with the UTM zone appropriate for its geometries' centroid. Bounding box formatted as a 4 element tuple: (lng_max, lat_min, lng_min, lat_max) Else: Get bbox from the query to geocode to get geojson boundary polygon from OSM Parameters ---------- filepath : String the name of the shapefile path(including file extension) place : String the query to geocode to get geojson boundary polygon buffer_dist : float distance to buffer around the place geometry, in meters crs : dict the starting coordinate reference system of the passed-in geometry, default value (None) will set settings.default_crs as the CRS to_crs : dict if not None, just project to this CRS instead of to UTM to_latlong : bool if True, projects to latlong instead of to UTM Returns ------- tuple (geometry_proj, crs), the projected shapely geometry and the crs of the projected geometry """ if os.path.exists(filepath): polygon_buffer = get_bufferedstudyregion_polygon(filepath, buffer_dist=1e4, crs=crs, to_crs=to_crs, to_latlong=True) bbox = polygon_buffer[0].bounds else: gdf = ox.gdf_from_place(query, gdf_name=None, which_result=1, buffer_dist=buffer_dist) bbox = gdf.geometry.bounds[['miny','minx','maxy','maxx']].values[0].tolist() bbox = ','.join(['{}'.format(x) for x in bbox]) return bbox
place_names = ['Ho Chi Minh City, Vietnam', #'Beijing, China', #'Jakarta, Indonesia', 'London, UK', 'Los Angeles, California, USA', 'Manila, Philippines', #'Mexico City, Mexico', 'New Delhi, India', 'Sao Paulo, Brazil', 'New York, New York, USA', 'Seoul', 'Singapore', #'Tokyo, Japan', #'Nairobi, Kenya', #'Bangalore, India' ] # In this for-loop, we save all the shapefiles for the valid cities. for city in place_names: city_admin_20kmbuff = ox.gdf_from_place(city, gdf_name = 'global_cities', buffer_dist = 20000) fig, ax = ox.plot_shape(city_admin_20kmbuff) ox.save_gdf_shapefile(city_admin_20kmbuff, filename = city) # In this for-loop, we save all the street networks for the valid cities. for city in place_names: grid = ox.graph_from_place(city, network_type = 'drive', retain_all = True) grid_projected = ox.project_graph(grid) ox.save_graph_shapefile(grid_projected, filename = city + '_grid') ox.plot_graph(grid_projected)
if not os.path.exists(directory): os.makedirs(directory) for place in places: name = (place.replace(",","").replace(" ","")) # make better place_names print('working on: ', name) #make a geodataframe of the street network (outline) from openstreetmap place names # use retain_all if you want to keep all disconnected subgraphs (e.g. when your places aren't adjacent) G = ox.graph_from_place(place, network_type='drive', retain_all=True) G = ox.project_graph(G) #make a geodataframe of the shape (outline) from openstreetmap place names gdf = ox.gdf_from_place(place) gdf = ox.project_gdf(gdf) ox.save_graph_shapefile(G, filename=name) print(name, ' has crs:' ) gdf.to_crs({'init': 'epsg:3395'}) # Confirm big step of projection change # calculate basic stats for the shape # TODO adjust this to calculate stats based on neighborhoods stats = ox.basic_stats(G, area=gdf['geometry'].area[0]) print('area', gdf['area'][0] / 10**6, 'sqkm') # save to file: def ensure_dir(file_path):