Using imshow with basemap: mismatch between colours and map borders

294 Views Asked by At

I am trying to plot some grib data using basemap and imshow instead of contourf. When I plot it with contourf I get the proper boundaries and colours, but when I do it with imshow there is a mismatch between the image and the map. Plot with contourf using contourf. Plot with imshow using imwshow

I am using an lcc projection. In the documentation I see some examples using a cylindrical projection, but I also get the mismatch in this case. The relevant code is below.

m = Basemap(llcrnrlon=-55, llcrnrlat=55.8, urcrnrlon=80, urcrnrlat=80, lat_1=72, lat_0=72., lon_0=-36, resolution='h', projection='lcc')
x, y = m(lons, lats)

data = data - 273.15
import matplotlib as mpl
cmap = mpl.cm.RdBu_r
norm = mpl.colors.Normalize(vmin=-55, vmax=15)
minVal = min(data.flatten())
maxVal = max(data.flatten())
clev = np.arange(minVal,maxVal,0.01)
#using contourf
CS_tmp = m.contourf(x,y,data,clev,cmap=plt.cm.coolwarm)
#using imshow
CS_tmp = m.imshow(data2,cmap=cmap) #,extent=extent)

My question is, what sort of transformation should I apply to the data? I tried to follow this tutorial https://basemaptutorial.readthedocs.io/en/latest/utilities.html#interp which makes reference to transform_scalar, which will only work for cylindrical projections.

It suggest to use interp for a non-cyl projection "When the input matrix is not regular in longitude-latitude (i.e. is not a cylindric projection), this method can’t be used properly, since the longitude-latitude grid won’t be regular. See the interp example for a solution."

I tried following the example there, but this didn't work and I am still seeing the mismatch

x2 = np.linspace(x[0][0],x[0][-1],x.shape[1]*2)
y2 = np.linspace(y[0][0],y[-1][0],y.shape[0]*2)
x2, y2 = np.meshgrid(x2, y2)
data_trans = interp(data,  x[0], y[:, 0], x2, y2,order=1)

Could anyone tell me what would the adequate transformation here?

Thanks for any help

Carlos

1

There are 1 best solutions below

0
On

I think the problem is that the imshow plot fits into the whole figure window in your plot because matplotlib can't obtain any coordinate information from your array.

If you would use another projection it would be possible to set the boundaries correctly but as you use a polar based projection the extent of the coordinates goes up to 80° in Latitude and Longitude.

So you have to add nan's to your data2 array.

Code could look like this:

# take a raw array of zeros along longitude axes 
base_nan_array = np.zeros(len(x))

# find out how many rows must be added
n_lat_rows =len(y) - data2.shape[1]

# fill up nan array 
nan_array = np.array([base_nan_array,]*n_lat_rows)

# append to data (you have to find the direction of append on your own bc. no test data is avail.)
np.append([data2, nan_array], axis=0)

This will make your array cover the whole extend of your basemap.