How to plot an irregular spaced RGB image using python and basemap?
Asked Answered
M

1

4

Given that I have three matrices which describe the data that I want to plot:

  • lons - 2D matrix with [n_lons,n_lats]
  • lats - 2D matrix with [n_lons,n_lats]
  • dataRGB - 3D matrix with [n_lons,n_lats,3]

what is the preferred way to plot such data using python and basemap.

For pseudo-color data this is quite simple using the pcolormesh method:

  • data - 2D matrix with [n_lons,n_lats]

    m = Basemap(...)

    m.pcolormesh(lons,lats,data,latlon=True)

From reading the documentation, it seems to me that the imshow command should be used in this case, but for this method regularly gridded data is needed and I would have to regridd and interpolate my data.

Is there any other way to plot the data?

Magree answered 6/3, 2014 at 11:12 Comment(0)
M
2

I ran into this same issue awhile ago, and this is the only solution I could come up with:

(Note that this works with matplotlib 1.3.0, but not 1.1.0)

from mpl_toolkits.basemap import Basemap

import numpy.ma as ma
import numpy as np

m = Basemap() #Define your map projection here

Assuming var is your variable of interest (NxMx3),lats is (N)x(M) and lons is (N)x(M):

We need to convert pixel center lat/lons to pixel corner lat/lons (N+1)x(M+1)

cornerLats=getCorners(lat);cornerLons=getCorners(lon)

Get coordinate corners

xCorners,yCorners=m(cornerLats,cornerLons,inverse=True)

Mask the data that is invalid

var=ma.masked_where(np.isnan(var),var)

We need a flattened tuple(N*M,3) to pass to pcolormesh

colorTuple=tuple(np.array([var[:,:,0].flatten(),var[:,:,1].flatten(),var[:,:,2].flatten()]).transpose().tolist())

Setting a larger linewidth will result in more edge distortion, and a

smaller linewidth will result in a screwed up image for some reason.

m.pcolormesh(xCorners,yCorners,var[:,:,0],color=colorTuple,clip_on=True,linewidth=0.05)

def getCorners(centers):

    one = centers[:-1,:]
    two = centers[1:,:]
    d1 = (two - one) / 2.
    one = one - d1
    two = two + d1
    stepOne = np.zeros((centers.shape[0] + 1,centers.shape[1]))
    stepOne[:-2,:] = one
    stepOne[-2:,:] = two[-2:,:]
    one = stepOne[:,:-1]
    two = stepOne[:,1:]
    d2 = (two - one) / 2.
    one = one - d2
    two = two + d2
    stepTwo = np.zeros((centers.shape[0] + 1,centers.shape[1] + 1))
    stepTwo[:,:-2] = one
    stepTwo[:,-2:] = two[:,-2:]
    return stepTwo
Mccain answered 2/5, 2014 at 19:54 Comment(3)
Thanks for sharing your solution! For me, it seems that the color keyword is ignored by pcolormesh. Also I had to set the linewidth to zero, otherwise for each pixel a surrounding polygon is drawn which effectively renders a black image.Magree
Yeh, you may have to tinker with linewidth. Essentially, if I set linewidth=0, I get the same image as if I plotted the image with pcolor instead of pcolormesh. Did you enter the colorTuple on a 0.0 - 1.0 range instead of a 0-255? I actually have rgb pictures of MISR data (www-misr.jpl.nasa.gov) that I overlay onto a basemap background with this code, so it should work. Can you share a 3x3 array of your lats, lons, and rgb tuples?Mccain
This solution almost works for me, but my image is scrambledRemanent

© 2022 - 2024 — McMap. All rights reserved.