Skip to content

Commit

Permalink
warn user if saving project graph as osm xml and add tests for saving…
Browse files Browse the repository at this point in the history
… projected and consolidated graphs as xml
  • Loading branch information
gboeing committed Mar 2, 2024
1 parent a64979c commit ca9744b
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 9 deletions.
15 changes: 14 additions & 1 deletion osmnx/_osm_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import networkx as nx
import pandas as pd

from . import projection
from . import settings
from . import utils
from . import utils_graph
Expand Down Expand Up @@ -160,7 +161,7 @@ def _save_graph_xml(
Parameters
----------
G
Unsimplified graph to save as an OSM XML file.
Unsimplified, unprojected graph to save as an OSM XML file.
filepath
Path to the saved file including extension. If None, use default
`settings.data_folder/graph.osm`.
Expand Down Expand Up @@ -211,6 +212,18 @@ def _save_graph_xml(
else:
gdf[col] = gdf[col].fillna(value)

# warn user if graph is projected then remove lat/lon gdf_nodes columns if
# they exist, as x/y cols will be saved as lat/lon node attributes instead
if projection.is_projected(G.graph["crs"]):
msg = (
"Graph should be unprojected: the existing lat-lon node attributes will "
"be discarded and the projected x-y coordinates will be saved as lat-lon "
"node attributes instead. Project your graph back to lat-lon to avoid this."
)
warn(msg, category=UserWarning, stacklevel=2)
for col in set(gdf_nodes.columns) & {"lat", "lon"}:
gdf_nodes = gdf_nodes.drop(columns=[col])

# transform nodes gdf to meet OSM XML spec
# 1) reset index (osmid) then rename osmid, x, and y columns
# 2) round lat/lon coordinates
Expand Down
4 changes: 2 additions & 2 deletions osmnx/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,14 @@ def save_graph_xml(
This function merges graph edges such that each OSM way has one entry in
the XML output, with the way's nodes topologically sorted. `G` must be
unsimplified to save as OSM XML: otherwise, one edge could comprise
multiple OSM ways, making it impossible to properly group edges by way.
multiple OSM ways, making it impossible to group and sort edges in way.
`G` should also have been created with `ox.settings.all_oneway=True` for
this function to behave properly.
Parameters
----------
G
Unsimplified graph to save as an OSM XML file.
Unsimplified, unprojected graph to save as an OSM XML file.
filepath
Path to the saved file including extension. If None, use default
`settings.data_folder/graph.osm`.
Expand Down
18 changes: 12 additions & 6 deletions tests/test_osmnx.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def test_osm_xml() -> None:

Path.unlink(Path(temp_filename))

# test .osm xml saving
# test OSM xml saving
G = ox.graph_from_point(location_point, dist=500, network_type="drive", simplify=False)
fp = Path(ox.settings.data_folder) / "graph.osm"
ox.io.save_graph_xml(G, filepath=fp, way_tag_aggs={"lanes": "sum"})
Expand All @@ -180,14 +180,20 @@ def test_osm_xml() -> None:
default_overpass_settings = ox.settings.overpass_settings
ox.settings.overpass_settings += '[date:"2023-04-01T00:00:00Z"]'
point = (39.0290346, -84.4696884)
G = ox.graph_from_point(point, dist=500, dist_type="bbox", network_type="drive", simplify=True)
with pytest.raises(ox._errors.GraphSimplificationError):
ox.io.save_graph_xml(G)
G = ox.graph_from_point(point, dist=500, dist_type="bbox", network_type="drive", simplify=False)
nx.set_node_attributes(G, 0, name="uid")
ox.io.save_graph_xml(G)
_ = etree.parse(fp, parser=parser) # noqa: S320
G = ox.graph_from_xml(fp) # issues UserWarning

# raise error if trying to save a simplified graph
with pytest.raises(ox._errors.GraphSimplificationError):
ox.io.save_graph_xml(ox.simplification.simplify_graph(G))

# save a projected/consolidated graph as OSM XML
Gc = ox.simplification.consolidate_intersections(ox.projection.project_graph(G))
nx.set_node_attributes(Gc, 0, name="uid")
ox.io.save_graph_xml(Gc, fp) # issues UserWarning
Gc = ox.graph.graph_from_xml(fp) # issues UserWarning
_ = etree.parse(fp, parser=parser) # noqa: S320

# restore settings
ox.settings.overpass_settings = default_overpass_settings
Expand Down

0 comments on commit ca9744b

Please sign in to comment.