-
Notifications
You must be signed in to change notification settings - Fork 827
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add endpoint_attrs param to simplify_graph to flexibly relax strictness #1117
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #1117 +/- ##
=======================================
Coverage 97.86% 97.86%
=======================================
Files 28 28
Lines 2531 2534 +3
=======================================
+ Hits 2477 2480 +3
Misses 54 54 ☔ View full report in Codecov by Sentry. |
@csebastiao would you like to test this out with a specific case? |
@gboeing I have tested it on my side on the two examples of the Toy graph and Copenhagen custom bicycle attribute and both are returning the expected behaviors. It's all good for me. |
Thanks. Can you provide a code snippet for testing your use case? |
Oh sure sorry about that, here is the one for the Toy Graph made by hand: import networkx as nx
import shapely
import osmnx as ox
G = nx.Graph()
G.add_node(1, x=1, y=1)
G.add_node(2, x=2, y=1)
G.add_node(3, x=2.5, y=1.5)
G.add_node(4, x=3, y=2.5)
G.add_node(5, x=3.5, y=3.5)
G.add_node(6, x=3, y=4)
G.add_node(7, x=3, y=5)
G.add_node(8, x=3.5, y=5.5)
G.add_node(9, x=3.5, y=6.5)
G.add_node(10, x=4, y=7)
G.add_node(11, x=5, y=8)
G.add_node(12, x=6, y=8)
G.add_node(13, x=6.5, y=8.5)
G.add_node(14, x=7, y=9)
G.add_node(15, x=7.5, y=8.5)
G.add_node(16, x=8, y=8)
G.add_node(17, x=7.5, y=7.5)
G.add_node(18, x=7, y=7)
G.add_node(19, x=6.5, y=7.5)
# add length and osmid just for the osmnx function to work
for i in range(1, 19):
G.add_edge(i, i + 1, length=1, osmid=i)
G.add_node(20, x=4, y=4)
G.add_node(21, x=4, y=5)
G.add_edge(5, 20, length=1, osmid=20)
G.add_edge(20, 21, length=1, osmid=21)
G.add_edge(21, 8, length=1, osmid=22)
G.add_edge(19, 12, length=1, osmid=23)
# give three value of color to see the discrimination for an attribute
for i in range(2, 8):
G.edges[i, i + 1]["color"] = 1
G.edges[1, 2]["color"] = 2
G.edges[5, 20]["color"] = 1
G.edges[20, 21]["color"] = 1
G.edges[21, 8]["color"] = 1
for i in range(8, 11):
G.edges[i, i + 1]["color"] = 3
for i in range(11, 19):
G.edges[i, i + 1]["color"] = 2
G.edges[19, 12]["color"] = 2
G = nx.MultiDiGraph(G)
# add crs for the ox_plot_graph to work
G.graph["crs"] = "epsg:4326"
ec = ox.plot.get_edge_colors_by_attr(G, "color", cmap="Set1")
ox.plot_graph(
G,
figsize=(12, 8),
bgcolor="w",
node_color="black",
node_size=30,
edge_color=ec,
edge_linewidth=3,
)
G_simple = ox.simplify_graph(G, endpoint_attrs=["color"])
ec_s = ox.plot.get_edge_colors_by_attr(G_simple, "color", cmap="Set1")
ox.plot_graph(
G_simple,
figsize=(12, 8),
bgcolor="w",
node_color="black",
node_size=30,
edge_color=ec_s,
edge_linewidth=3,
) Which can be asserted with assert len(G_simple) == len(ox.simplify_graph(G)) + 2 One way to see it on an actual OSMnx graph is with this basic example: import osmnx as ox
protected_dict = {}
protected_dict["sidewalk:left:bicycle"] = "yes"
protected_dict["sidewalk:left:right"] = "yes"
protected_dict["cycleway:left"] = ["shared_lane", "shared_busway", "track"]
protected_dict["cycleway:right"] = ["shared_lane", "shared_busway", "track"]
protected_dict["cycleway:both"] = "lane"
protected_dict["cycleway"] = ["shared_lane", "shared_busway", "opposite_lane", "opposite"]
protected_dict["bicycle"] = ["designated", "yes", "official", "use_sidepath"]
protected_dict["highway"] = ["cycleway", "bridleway"]
protected_dict["cyclestreet"] = "yes"
protected_dict["bicycle_road"] = "yes"
for val in protected_dict:
if val not in ox.settings.useful_tags_way:
ox.settings.useful_tags_way += [val]
G = ox.graph_from_place("Frederiksberg Municipality, Denmark", simplify=False)
for edge in G.edges:
for key in list(protected_dict.keys()):
if key in list(G.edges[edge].keys()):
if G.edges[edge][key] in protected_dict[key]:
G.edges[edge]["cycling"] = 1
break
else:
G.edges[edge]["cycling"] = 0
else:
G.edges[edge]["cycling"] = 0
G_s = ox.simplify_graph(G, endpoint_attrs=None)
G_ns = ox.simplify_graph(G, endpoint_attrs=["osmid"])
G_attr = ox.simplify_graph(G, endpoint_attrs=["cycling"])
ec = ox.plot.get_edge_colors_by_attr(G_attr, "cycling", cmap="RdYlGn")
ox.plot_graph(
G_attr,
figsize=(12, 8),
bgcolor="w",
node_color="black",
node_size=10,
edge_color=ec,
edge_linewidth=1,
) To take a specific node (even thought with the ever-updating OSM I don't know if the exact values will stay) one can look at the node G_attr.edges(1262273553, data=True) It only exists when discriminating with the cycling (or osmid) attribute: assert 1262273553 not in G_s
assert 1262273553 in G_attr This should be the case as there are only two edges |
|
I believe this is ready to merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few minor comments. Really like the explicit numbered rules in the comments, helps a lot with understanding the code!
Note that #1145 additionally adds a |
Resolves #625
This PR:
endpoint_attrs
param tosimplification.simplify_graph
function to flexibly relax strictnessstrict
param insimplification.simplify_graph
function in favor of newendpoint_attrs
paramsimplification
modulePer the new deprecation message: