3

I am trying to plot some weather data over a map using Basemap (I'm open to trying cartopy also) on Python. Right now, my weather data looks like this. My data source is basically an array with each position corresponding to a square of the grid and each value indicating the color that square should be. The code used to generate this image looks like this, where each square of the grid equals to 1000 m:

grid_0 = np.asarray(dec.split())
grid_1=np.reshape(grid_0,(n_cols,n_rows))
grid_2 = grid_1.astype(float)

# Make plot
plt.figure(figsize=(30,30))
fig, ax = plt.subplots()

plt.axis('off')
cax = ax.imshow(grid_2, interpolation='nearest', cmap=cmap)

I have the information on where geographically the lower corner of the grid is located. I believe that the best way of plotting this on a map is somehow using the contourf() function, but I'm quite new to Basemap and can't find a way of transforming this to something that contourf() can understand. To lpot the map I'm using Basemap, where lon_air and lat_air are the coordinates of a certain airport:

fig=figure(1, figsize=(19, 15))

m = Basemap(projection='cyl', llcrnrlon=lon_air-25, llcrnrlat=lat_air-15,
            urcrnrlon=lon_air+25, urcrnrlat=lat_air+15, resolution='h', area_thresh=10000)

m.drawstates(linewidth=0.5, color='black', zorder=4)
m.drawcountries(linewidth=2.0, color='white', zorder=3)
m.drawmapboundary(fill_color='#e5f5ff')
m.fillcontinents(color='#DFDFDF', zorder=1)
m.scatter(lon_air, lat_air,marker='o',color='k', zorder=10)

x0, y0 = lon_air-((360*920)/(4*np.pi*6371)),lat_air-((360*920)/(4*np.pi*6371)) 
x1, y1 = lon_air+((360*920)/(4*np.pi*6371)), lat_air+((360*920)/(4*np.pi*6371)) 

im = plt.imshow(plt.imread('./pngs/9905.png'), extent=(x0, x1, y0, y1), zorder=2)
plt.show()

I will edit the post if somebody think that more details are needed. Thanks in advance to everyone!

  • 2
    what code do you have to generate the weather data and the map separately? If we can see that we may be better able to help you merge the two – Aaron Aug 31 '18 at 13:46
  • 1
    As Aaron said, having code in the question can help you get to your answer. It looks as if you're trying to plot some radar data from the photo provided. I'd look into metpy ([link to docs](https://unidata.github.io/MetPy/latest/index.html)) and see if there's anything in there that could apply to you. – Brandon Molyneaux Sep 01 '18 at 14:00
  • Thanks for your comments guys, I edited my question and I'll check MetPy right now :) – Guillermo Moreno Castaño Sep 03 '18 at 10:06

1 Answers1

1

Producing a Basemap.contourf plot is a pretty standard procedure. Your plt.imread command should return you a 2D numpy array (assuming it is grey scale), so do something like this to get the actual data and its dimensions:

data = plt.imread('./pngs/9905.png')
lx, ly = data.shape

Next you need to provide coordinates for each point of your data. For contourf this is done providing two additional 2D fields, one with the x-coordinates and one with the y-coordinates. You can get the right form with np.linspace and np.meshgrid:

lon0, lat0 = lon_air-((360*920)/(4*np.pi*6371)),lat_air-((360*920)/(4*np.pi*6371))
lon1, lat1 = lon_air+((360*920)/(4*np.pi*6371)), lat_air+((360*920)/(4*np.pi*6371))
lons = np.linspace(lon0, lon1, lx)  #1D
lats = np.linspace(lat0, lat1, ly)  #1D
lon, lat = np.meshgrid(lons,lats)   #1D --> 2D

Now you still need to convert your map coordinates into projection coordinates and then plot the whole thing:

x,y = m(lon, lat)
m.contourf(x,y,data)
plt.show()

There may be still some issues with the arrangement of the data (it's sometimes a bit confusing), so you might have to transpose it (data.T) or invert a dimension (by indexing [::-1]). If you run into these kind of problems, please ask (or provide an example image), then I can adjust the answer accordingly. Oh, and remember to add a

import numpy as np

somewhere in the beginning of your script.

Thomas Kühn
  • 9,412
  • 3
  • 47
  • 63
  • Thanks Thomas, this is the closest I've gotten to the desired product. The image is not black and white, so I get a 3D array, with lz=4 that I believe is the one causing me problems. I managed to print the same grid_3 but I get a white background that shouldnt be there. When using fig = plt.figure() m = [...] x,y = m(lon, lat) m.contourf(x,y,data, zorder=10, cmap=cmap) img=plt.show() fig.savefig('./9905/each'.png') I get: ValueError: operands could not be broadcast together with shapes (993,1032,4) (1032,993) And with data.t: Input z must be a 2D array. – Guillermo Moreno Castaño Sep 06 '18 at 12:05
  • @GuillermoMorenoCastaño If the data you get back from `plt.imread()` has a z-dimension of 4, this means that your image is an rgba image, e.g. three colour channels and and an alpha channel. In this case, you first need to think what these colours and the alpha *mean* in terms of data representation. My guess is that your image *already* represents a pseudo-colour image (be it a contour plot or something else), which means that you probably only want to overlay the image over the map and not use `pyplot.contourf()` at all... – Thomas Kühn Sep 06 '18 at 14:15
  • ...[here](https://stackoverflow.com/q/27275669/2454357) the use of `Basemap.imshow()` is discussed, but apparently this only works for cylindrical maps. Is there any way that you could get your weather data as real data, not an image? – Thomas Kühn Sep 06 '18 at 14:17