Monday, 21 October 2019

Iterating over an isochrone in OSMNX in Python

I am trying to iterate over some polygons using OSMNX in Python based on this example but am having issues with the output.

The set up:

import geopandas as gpd
import matplotlib.pyplot as plt
import networkx as nx
import osmnx as ox
from descartes import PolygonPatch
from shapely.geometry import Point, LineString, Polygon
ox.config(log_console=True, use_cache=True)
ox.__version__

# get one color for each isochrone
iso_colours = ox.get_colors(n=len(trip_times), cmap='Reds', start=0.3, return_hex=True)

#info for later on
network_type = 'walk'
trip_times = [5, 10] #in minutes
travel_speed = 4.8 #walking speed in km/hour
metres_per_minute = travel_speed * 1000 / 60 #km per hour to m per minute

# isochrone function
def make_iso_polys(G, edge_buff=25, node_buff=50, infill=False):
    isochrone_polys = []
    for trip_time in sorted(trip_times, reverse=True):
        subgraph = nx.ego_graph(G, centre_node, radius=trip_time, distance='time')

        node_points = [Point((data['x'], data['y'])) for node, data in subgraph.nodes(data=True)]
        nodes_gdf = gpd.GeoDataFrame({'id': subgraph.nodes()}, geometry=node_points)
        nodes_gdf = nodes_gdf.set_index('id')

        edge_lines = []
        for n_fr, n_to in subgraph.edges():
            f = nodes_gdf.loc[n_fr].geometry
            t = nodes_gdf.loc[n_to].geometry
            edge_lines.append(LineString([f,t]))

        n = nodes_gdf.buffer(node_buff).geometry
        e = gpd.GeoSeries(edge_lines).buffer(edge_buff).geometry
        all_gs = list(n) + list(e)
        new_iso = gpd.GeoSeries(all_gs).unary_union

        # try to fill in surrounded areas so shapes will appear solid and blocks without white space inside them
        if infill:
            new_iso = Polygon(new_iso.exterior)
        isochrone_polys.append(new_iso)
    return isochrone_polys

# the area 
mv = ox.graph_from_bbox(-37.705, -37.796, 144.949, 144.84, network_type='walk')
mv_projected = ox.project_graph(mv)
ox.plot_graph(mv_projected)

multiple_coords = ((-37.773981, 144.915669), 
                   (-37.765443, 144.863070), 
                   (-37.736089, 144.888972), 
                   (-37.764914, 144.924148), 
                   (-37.788513, 144.930533)) 

The bit where the issue is. I have added some additional text to track what is happening in the code:

# test function to do multiple ones 
def iterate_multiple_coords(the_coordinates):
    for i in the_coordinates:
        centre_node = ox.get_nearest_node(mv, (i[0], i[1]))
        print("starting" + str(i)) # to check
        # add an edge attribute for time in minutes required to traverse each edge
        for u, v, k, data in mv_projected.edges(data=True, keys=True):
            data['time'] = data['length'] / metres_per_minute
        # make the polygons    
        isochrone_polys_iter = make_iso_polys(mv_projected, edge_buff=25, node_buff=0, infill=True)
        print("done " + str([i])) # to check
        poly_list.append(isochrone_polys_iter)
        print("appended " + str([i])) # to check
    return(poly_list)

#list of shapely objects
test = iterate_multiple_coords(multiple_coords)

This seems to work, but when you look at the polygons that have been created, they are just copies of two of them. They should all be different.

for i in test:
    print(i[0].area)
    print(i[1].area)

Just produces copies of:

[<shapely.geometry.polygon.Polygon object at 0x00000252EED81048>, <shapely.geometry.polygon.Polygon object at 0x0000025299DCD7B8>]
1221891.0262004482
278954.2285476034
[<shapely.geometry.polygon.Polygon object at 0x000002529A0FF978>, <shapely.geometry.polygon.Polygon object at 0x00000252F0884978>]
1170723.0839951886
254020.00263692273

How would I fix this? Thanks.



from Iterating over an isochrone in OSMNX in Python

No comments:

Post a Comment