Streets-Data-Collaborative / OpenStreetCam-GeoParsing-Tool

Create a tool that, given a city, give can pull each OpenStreetCam (OSM) Track file No. associated with that city.
Apache License 2.0
7 stars 2 forks source link

Define a getIntersection() function that takes a city name as an input, and returns a list of the lat/lngs of each intersection of that city's street network #2

Closed dmarulli closed 6 years ago

dmarulli commented 6 years ago

OSMnx is a python package that can pull street grids given a street name.

The following methods will likely be helpful:

charlie-moffett commented 6 years ago

installed Geoff Boeing's OSMnx with conda & reviewing package overview: https://github.com/gboeing/osmnx

charlie-moffett commented 6 years ago

I've got a preliminary function that returns a geodataframe containing the OSM id, lat, and long for each intersection in a given city:

def getIntersection(city, state, country):
    """Takes a city name as an input and
    returns a list of the lat/longs
    of each intersection of that city's
    street network."""
    place = (city + ", " + state + ", " + country)

    # Create a networkx graph from OSM data within the spatial boundaries of some geocodable place
    G = ox.graph_from_place(place)

    # Save graph nodes as a GeoDataFrame
    nodes_gdf = ox.save_load.graph_to_gdfs(G, nodes=True, edges=False, node_geometry=True, fill_edge_geometry=False)

    # Create a new dataframe with just osmid, x, and y
    citysect = nodes_gdf[['osmid', 'x', 'y']]

    return citysect

If I then run, for example: getIntersection('Berkeley', 'California', 'USA') I get in return the geodataframe with 5707 rows × 3 columns.

In creating the networkx graph, the function will by default download all OSM streets and paths, including private-access ones. OSMnx also automatically simplifies the graph’s topology by removing all nodes that are not intersections or dead-ends.

There are other specifications and points of clarification to be included here, but I just wanted to confirm first that this is headed in the right direction.

dmarulli commented 6 years ago

Awesome. Yeah, this looks like a great start.

We will want all the tracks--including those collected by bikers on private-access roads--so no need to introduce any additional filters there.

I originally suggested a list output since that's what came to mind as a straightforward structure to loop through, but the gdf should be fine too (and can easily be massaged if not).

Just for reference though, here is what I had in mind:

If the output was of the form [(-122.247, 37.8662), (-122.247, 37.8661), ...], then when defining getAlltracks() (#4), we could start with some something like:

sequence_ids = []
for coords in getIntersection('Berkeley', 'California', 'USA'):
     tempTracks = getNearbytracks(coords)
     tempTracks_uniq = some_dedupe_routine(tempTracks)
     sequence_ids.extend(tempTracks_uniq)
return sequence_ids
dmarulli commented 6 years ago

Also I moved this card into the "In progress" stack to maintain a high-level picture of where the project is.

charlie-moffett commented 6 years ago

I've added the following to the function: mylist = citysect[['x', 'y']].values.tolist() and get an output like [[-122.2465302, 37.8661529], [-122.2470015, 37.8661398], ... ]

Do you foresee an issue with each lat/long pair being it's own list as opposed to a tuple within the larger list of pairs?

dmarulli commented 6 years ago

Not sure, probably wouldn't cause any problems, although I think using tuples happens to be the more pythonic approach (reference).

But easy enough to change either way: new_list_of_tuples = [tuple(l) for l in mylist]

charlie-moffett commented 6 years ago

Thanks for the insight. What I have now returns the output in the form you had in mind.

import osmnx as ox

def getIntersection(city, state, country):
    place = (city + ", " + state + ", " + country)
    G = ox.graph_from_place(place)
    nodes_gdf = ox.save_load.graph_to_gdfs(G, edges=False, node_geometry=False)
    nodes_list = nodes_gdf[['x', 'y']].to_records(index=False).tolist()
    return nodes_list

Should I add any code to the repo at this point, or just take a crack at the next issue by building off of the above?

dmarulli commented 6 years ago

Sure feel free to push up commits after completing each card. Looks great.