Adding osmnx plot to pygmt figure

Hi, I am trying to plot elevation contours (with pygmt) as well as an osm object/graph (with osmnx) into the same figure. However, I only accomplish to plot them separately (see below); this because there is no common axes object or the like I could associate both plots with.

This is the code:

import osmnx as ox
import pygmt

# plotting elevation contours with pygmt

grid = pygmt.datasets.load_earth_relief(resolution="30s", region=[10.532455,10.879898,46.556972,46.713973])
fig = pygmt.Figure()
fig.grdcontour(grid=grid)
fig.show()

# plotting a river with osmnx

etsch = ox.graph.graph_from_bbox(bbox=[46.713973, 46.556972, 10.879898, 10.532455], simplify=False, custom_filter='["waterway"~"river"]')
ox.plot_graph(etsch, node_size=0, edge_color="tab:blue");

Alternatively, I could combine the figures (as .svg) afterwards, but that would be a workaround only.

Any advice would be highly appreciated. Best, –Knut/

Hi,

I’m afraid the answer is no. Although what you see is a png image (I think) what GMT really produces is a PostScript file. So, in order to achieve what you are asking osmnx should be able to produce PS too and merge the two files taking into consideration different image scales etc.

You best bet is to use osmnx to extract the data and use it in pygmt.

And, please used the PyGMT tag when asking python related questions.

1 Like

Hello @goett2win,

welcome to the GMT forum :slightly_smiling_face: !

I have not worked with OSMnx yet, but this Python package looks quite interesting and promising! There seems to be an integration with GeoPandas (Getting Started - OSMnx 1.9.4 documentation) and the possibility to convert the OSMnx related MultiDiGraph object to a geopandas GeoDataFrame or a tuple of GeoDataFrames (User Reference - OSMnx 1.9.4 documentation). A GeoDataFrame can be plotted with PyGMT. In this way, one can plot data related to OSMnx in a PyGMT Figure. But combining OSMnx and PyGMT figures is very likely not possible, as mentioned by @Joaquim.

import osmnx as ox
import pygmt


lon_min = 10.532455
lon_max = 10.879898
lat_min = 46.556972
lat_max = 46.713973

# Download Earth relief via pygmt
grid = pygmt.datasets.load_earth_relief(
    resolution="30s", region=[lon_min, lon_max, lat_min, lat_max],
)

# Get data via osmnx: rivers
# The expected order of coordinates in `bbox` will change in the v2.0.0 release to
# `(left, bottom, right, top)`.
etsch = ox.graph.graph_from_bbox(
    bbox=[lat_max, lat_min, lon_max, lon_min],
    # bbox=[lon_min, lat_min, lon_max, lat_max],
    simplify=False, custom_filter='["waterway"~"river"]',
)
# Convert MultiDiGraph to GeoDataFrame
# https://osmnx.readthedocs.io/en/stable/user-reference.html#osmnx.convert.graph_to_gdfs
etsch_gdf = ox.convert.graph_to_gdfs(
    etsch, nodes=True, edges=True, node_geometry=True, fill_edge_geometry=True,
)
# etsch_gdf[0] -> POINT geometry
# etsch_gdf[1] -> LINE geometry

# -----------------------------------------------------------------------------
fig = pygmt.Figure()

# Plot Earth relief grid as contour lines
fig.grdcontour(grid=grid, frame=True)

# Plot GeoDataFrame
fig.plot(data=etsch_gdf[0], style="c0.1c", fill="red")
fig.plot(data=etsch_gdf[1], pen="1p,blue,solid")

fig.show()

4 Likes

Thank you very much for this comprehensive solution. I ran into some other bug / version incompatibility, though. Anyway, this solution works, in principle!