Skip to content

Commit

Permalink
Merge pull request #1273 from gboeing/simp
Browse files Browse the repository at this point in the history
only allow topological node consolidation to be run once on a graph
  • Loading branch information
gboeing authored Jan 25, 2025
2 parents ce0615b + 0786a73 commit 5aac9c1
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## 2.0.2 (TBD)

- improve docstrings (#1272)
- fix bug where consolidate_intersections function would mutate the passed-in graph (#1273)
- provide user-friendly error message if consolidate_intersections is run more than once (#1273)

## 2.0.1 (2025-01-01)

Expand Down
5 changes: 4 additions & 1 deletion osmnx/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,10 @@ def load_graphml(
raise ValueError(msg)

# specify default graph/node/edge attribute values' data types
default_graph_dtypes = {"simplified": _convert_bool_string}
default_graph_dtypes = {
"consolidated": _convert_bool_string,
"simplified": _convert_bool_string,
}
default_node_dtypes = {
"elevation": float,
"elevation_res": float,
Expand Down
17 changes: 12 additions & 5 deletions osmnx/simplification.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def simplify_graph( # noqa: C901, PLR0912
Returns
-------
G
Gs
Topologically simplified graph, with a new `geometry` attribute on
each simplified edge.
"""
Expand Down Expand Up @@ -513,19 +513,19 @@ def consolidate_intersections(
Returns
-------
G or gs
Gc or gs
If `rebuild_graph=True`, returns MultiDiGraph with consolidated
intersections and (optionally) reconnected edge geometries. If
`rebuild_graph=False`, returns GeoSeries of Points representing the
centroids of street intersections.
"""
# make a copy to not mutate original graph object caller passed in
G = G.copy()

# if dead_ends is False, discard dead-ends to retain only intersections
if not dead_ends:
spn = stats.streets_per_node(G)
dead_end_nodes = [node for node, count in spn.items() if count <= 1]

# make a copy to not mutate original graph object caller passed in
G = G.copy()
G.remove_nodes_from(dead_end_nodes)

if rebuild_graph:
Expand Down Expand Up @@ -630,6 +630,10 @@ def _consolidate_intersections_rebuild_graph( # noqa: C901,PLR0912,PLR0915
A rebuilt graph with consolidated intersections and (optionally)
reconnected edge geometries.
"""
if G.graph.get("consolidated"): # pragma: no cover
msg = "This graph has already been consolidated, cannot consolidate it again."
raise GraphSimplificationError(msg)

# default node attributes to aggregate upon consolidation
if node_attr_aggs is None:
node_attr_aggs = {"elevation": "mean"}
Expand Down Expand Up @@ -715,6 +719,9 @@ def _consolidate_intersections_rebuild_graph( # noqa: C901,PLR0912,PLR0915
node_attrs[col] = unique_vals
Gc.add_node(cluster_label, **node_attrs)

# mark the graph as having been consolidated
G.graph["consolidated"] = True

if len(G.edges) == 0 or not reconnect_edges:
# if reconnect_edges is False or there are no edges in original graph
# (after dead-end removed), then skip edges and return new graph as-is
Expand Down

0 comments on commit 5aac9c1

Please sign in to comment.