Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cartopy Heatmap over OpenStreetMap Background

I have a created a Open Street Map plot using cartopy:

from __future__ import division
import numpy as np 
import matplotlib as mpl        
import matplotlib.pyplot as plt 
import cartopy.crs as ccrs
import cartopy.io.img_tiles as cimgt

request = cimgt.OSM()
extent = [-89, -88, 41, 42]

ax = plt.axes(projection=request.crs)
ax.set_extent(extent)

ax.add_image(request, 8)
plt.show()

enter image description here

Now I also have a list of longitude and latitude points. How can I overlay a heatmap of these longitude and latitude points over the streetmap?

I've tried using hist2d, but this doesn't work.

lons = (-88 --89)*np.random.random(100)+-89
lats = (41 - 42)*np.random.random(100)+42
ax.hist2d(lons,lats)
plt.show()

But this doesn't work.

I'm guessing I have to throw a transform argument in the plotting command somewhere? But I'm unsure how to go about it.

Thanks!

like image 783
hm8 Avatar asked Jan 03 '23 07:01

hm8


1 Answers

You are right about the need for coordinate transformation. Here is a working code with the resulting plot.

import numpy as np 
import matplotlib as mpl        
import matplotlib.pyplot as plt 
import cartopy.crs as ccrs
import cartopy.io.img_tiles as cimgt

request = cimgt.OSM()
fig, ax = plt.subplots(figsize=(10,16),
                       subplot_kw=dict(projection=request.crs))
extent = [-89, -88, 41, 42]  # (xmin, xmax, ymin, ymax)
ax.set_extent(extent)
ax.add_image(request, 8)

# generate (x, y) centering at (extent[0], extent[2])
x = extent[0] + np.random.randn(1000)
y = extent[2] + np.random.randn(1000)

# do coordinate conversion of (x,y)
xynps = ax.projection.transform_points(ccrs.Geodetic(), x, y)

# make a 2D histogram
h = ax.hist2d(xynps[:,0], xynps[:,1], bins=40, zorder=10, alpha=0.5)
#h: (counts, xedges, yedges, image)

cbar = plt.colorbar(h[3], ax=ax, shrink=0.45, format='%.1f')  # h[3]: image

plt.show()

The resulting plot:enter image description here

Edit 1

When ax is created with plt.subplots(), it has a certain projection defined. In this case, the projection is defined by the keyword projection=request.crs. To plot something on ax, you must use its coordinate system.

The coordinate conversion is done with the function transform_points() in the statement

xynps=ax.projection.transform_points(ccrs.Geodetic(), x, y)

where

  • (x, y) is a list of (longitude, latitude) values,
  • ccrs.Geodetic() signifies the values are (long, lat) in degrees

The return values xynps is an array of map coordinates. It has 2 columns for x and y that are in the appropriate coordinate system used by current ax.

like image 103
swatchai Avatar answered Jan 05 '23 14:01

swatchai