I'm trying to plot the river of a specific area but I don't understand why osmnx
cannot find it in certain places.
I have this code
import osmnx as ox
Sriver = ox.graph_from_place('Providencia, Chile',
# retain_all=False,
# truncate_by_edge=False,
# simplify=True,
custom_filter='["waterway"~"river"]',
# custom_filter='way["waterway"]'
)
But this fails with: Found no graph nodes within the requested polygon
If I query the features from OSM maps, the river is clearly there https://www.openstreetmap.org/query?lat=-33.41919&lon=-70.61062
Should I use other filters? I could not find more information in the docs. Or, is there a way to extract all available filters I can use from an area?
As described in the OSMnx documentation's Getting Started guide:
Under the hood, OSMnx does several things to generate the best possible model. It initially creates a 500m-buffered graph before truncating it to your desired query area, to ensure accurate streets-per-node stats and to attenuate graph perimeter effects. It also simplifies the graph topology as discussed below.
You said:
I'm trying to plot the river of a specific area but I don't understand why osmnx cannot find it in certain places.
... but take a more careful look at the complete error traceback you're getting:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[2], line 3
1 import osmnx as ox
----> 3 Sriver = ox.graph_from_place('Providencia, Chile',
4 # retain_all=False,
5 # truncate_by_edge=False,
6 # simplify=True,
7 custom_filter='["waterway"~"river"]',
8 # custom_filter='way["waterway"]'
9 )
File ~/Dropbox/Documents/School/Projects/Code/osmnx-repos/osmnx/osmnx/graph.py:375, in graph_from_place(query, network_type, simplify, retain_all, truncate_by_edge, which_result, buffer_dist, clean_periphery, custom_filter)
372 utils.log("Constructed place geometry polygon(s) to query API")
374 # create graph using this polygon(s) geometry
--> 375 G = graph_from_polygon(
376 polygon,
377 network_type=network_type,
378 simplify=simplify,
379 retain_all=retain_all,
380 truncate_by_edge=truncate_by_edge,
381 clean_periphery=clean_periphery,
382 custom_filter=custom_filter,
383 )
385 utils.log(f"graph_from_place returned graph with {len(G):,} nodes and {len(G.edges):,} edges")
386 return G
File ~/Dropbox/Documents/School/Projects/Code/osmnx-repos/osmnx/osmnx/graph.py:492, in graph_from_polygon(polygon, network_type, simplify, retain_all, truncate_by_edge, clean_periphery, custom_filter)
485 G_buff = simplification.simplify_graph(G_buff)
487 # truncate graph by original polygon to return graph within polygon
488 # caller wants. don't simplify again: this allows us to retain
489 # intersections along the street that may now only connect 2 street
490 # segments in the network, but in reality also connect to an
491 # intersection just outside the polygon
--> 492 G = truncate.truncate_graph_polygon(G_buff, polygon, retain_all, truncate_by_edge)
494 # count how many physical streets in buffered graph connect to each
495 # intersection in un-buffered graph, to retain true counts for each
496 # intersection, even if some of its neighbors are outside the polygon
497 spn = stats.count_streets_per_node(G_buff, nodes=G.nodes)
File ~/Dropbox/Documents/School/Projects/Code/osmnx-repos/osmnx/osmnx/truncate.py:162, in truncate_graph_polygon(G, polygon, retain_all, truncate_by_edge, quadrat_width, min_num)
159 if not to_keep:
160 # no graph nodes within the polygon: can't create a graph from that
161 msg = "Found no graph nodes within the requested polygon"
--> 162 raise ValueError(msg)
164 # now identify all nodes whose point geometries lie outside the polygon
165 gs_nodes_outside_poly = gs_nodes[~gs_nodes.index.isin(to_keep)]
ValueError: Found no graph nodes within the requested polygon
OSMnx is finding the river you're searching for. It does so as a 500m buffered graph then truncates it back down to your desired study area. But because you're requesting that OSMnx automatically simplify the graph topology, and because you have a very trivial spatial geometry as your only result, the simplification step removes all the graph nodes within your study area, leaving only a couple endpoints beyond your study area but within that 500m buffer. So, upon truncating to your study area, it finds no graph nodes remaining within your study boundary itself.
You can solve this problem by 1) not simplifying the graph at all, or 2) simplifying the graph after constructing it. A simple example of both options, plus an illustration of what is happening:
import osmnx as ox
# get boundary polygon and unsimplified graph
gdf = ox.geocode_to_gdf("Providencia, Chile")
geom = gdf.iloc[0]["geometry"]
G = ox.graph_from_polygon(geom, retain_all=True, truncate_by_edge=True, simplify=False, custom_filter='["waterway"~"river"]')
# plot unsimplified graph over boundary polygon
ax = gdf.plot()
fig, ax = ox.plot_graph(G, ax=ax, node_color="r", edge_color="k")
# plot simplified graph over boundary polygon
Gs = ox.simplify_graph(G)
ax = gdf.plot()
fig, ax = ox.plot_graph(Gs, ax=ax, node_color="r", edge_color="k")