Question

I'm having a hard time with plotting a basemap with Matplotlib and I'm fairly new to it so I was hoping for some help.

I have data of the format:

[ (lat1, lon1, data1), 
  (lat2, lon2, data2),
  (lat3, lon3, data3),
  ...
  (latN, lonN, dataN) ]

And here is some sample data:

(32.0, -128.5, 3.99)
(31.0, -128.0, 3.5027272727272734)
(31.5, -128.0, 3.7383333333333333)
(32.0, -128.0, 3.624)
(32.5, -128.0, 3.913157894736842)
(33.0, -128.0, 4.443333333333334)

Finally, here are some basic statistics about my data that I'm planning to plot:

LAT MIN:  22
LAT MAX:  50
LAT LEN:  1919
LON MIN:  -128
LON MAX:  -97
LON LEN:  1919
DATA MIN: 0
DATA MAX: 12
DATA LEN:  1919

I need to contour plot on a basemap of the continental United States. I can't, for the life of me, seem to figure out how to setup the data for plotting.

I read that the X-Axis (LATS) needs to be a np.array, and Y-Axis (LONS) needs to be an np.array and that Z (DATA) needs to be a MxN matrix where M = len(LATS) and N = len(LONS). So to me, I see Z as a diagonal matrix where the diagonal contains the data on the diagonal is the values found in DATA corresponding to the index of LATS and LONS.

Here is my code:

def show_map(self, a):

    a = sorted(a, key = lambda entry: entry[0])     # sort by latitude
    a = sorted(a, key = lambda entry: entry[1])     # then sort by longitude

    lats = [ x[0] for x in a ]
    lons = [ x[1] for x in a ]
    data = [ x[2] for x in a ]

    lat_min = min(lats)
    lat_max = max(lats)
    lon_min = min(lons)
    lon_max = max(lons)
    data_min = min(data)
    data_max = max(data)

    x = np.array(lats)
    y = np.array(lons)
    z = np.diag(data)

    m = Basemap(
        projection = 'merc',
        llcrnrlat=lat_min, urcrnrlat=lat_max,
        llcrnrlon=lon_min, urcrnrlon=lon_max,
        rsphere=6371200., resolution='l', area_thresh=10000
        lat_ts = 20, resolution = 'c'
    )

    fig = plt.figure()
    plt.subplot(211)
    ax = plt.gca()

    # draw parallels
    delat = 10.0
    parallels = np.arange(0., 90, delat)
    m.drawparallels(parallels, labels=[1,0,0,0], fontsize=10)

    # draw meridians
    delon = 10.
    meridians = np.arange(180.,360.,delon)
    m.drawmeridians(meridians,labels=[0,0,0,1],fontsize=10)

    # draw map features
    m.drawcoastlines(linewidth = 0.50)
    m.drawcountries(linewidth = 0.50)
    m.drawstates(linewidth = 0.25)

    ny = z.shape[0]; nx = z.shape[1]        # make grid
    lo, la = m.makegrid(nx, ny)
    X, Y = m(lo, la)
    clevs = [0,1,2.5,5,7.5,10,15,20,30,40,50,70,100,150,200,250,300,400,500,600,750]
    cs = m.contour(X, Y, z, clevs)

    plt.show()

The plot I get, however, is this: http://imgur.com/li1Wg. I need something to this effect: http://matplotlib.org/basemap/_images/plotprecip.png

Can someone point out what I'm doing wrong and help me plot this? Thank You.

Thanks

Was it helpful?

Solution

I figured out how to do it. This is the code that I finally wrote, and I think this can help other users. If there is a better way of doing this, please state it, since I'm new to Matplotlib.

https://gist.github.com/3789221

OTHER TIPS

Your linked gist is a solution but still wrong in another place.

In your question and in your linked gist you switched x and y coordinates with lon and lat.

x represents lon

y represents lat

Therefore you still get wrong results with your linked gist.

why are you writing:

z = np.diag(data) 

From the documentation, numpy.diag(v, k=0) extracts a diagonal or construct a diagonal array. That should be why you only get a "diagonal area" of values...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top