Hello,
I have a 2D numpy masked array of geo-located data -- with some data
missing -- that I wish to plot on a map. Basemap provides a nice tool
to do this, but I am stumped trying to get the colorscheme I want.
My data are only physically meaningful on land, so I am using
Basemap.maskoceans() to mask out "wet" locations (oceans, lakes, etc.)
Trouble is, now both water as well as actual missing data show up in
the missing data color.
I want to have blue water, some other (bright) color for missing data,
and a nice-looking color transition (matplotlib.cm.Blues or something
similar) for the valid data over land (values from 0 to 50). The
Cookbook example at
<http://www.scipy.org/Cookbook/Matplotlib/Plotting_Images_with_Special_Values>
addresses my problem, but I cannot get it to work. After changing
instances of matplotlib.numerix to numpy, I get a long list of
exceptions, the last of which is
TypeError: __call__() got an unexpected keyword argument 'bytes'.
This has to do with sentinelNorm, I think, but I'm not sure how to fix it.
Eventually I would like to sub-classify missing data by the type of
missing input that caused a missing value, but for now a single
missing data color is enough.
The code below does almost what I want- I just need to figure out how
to make the water blue. I have also messed around with
matplotlib.cm.BoundaryNorm to create a colormap/normalization to
handle my data, but I am getting hung up initializing the cmap,
counting bin edges, etc. I also tacked my test code for that... Any
help greatly appreciated!
Thanks,
Tim
···
--
Timothy W. Hilton
PhD Candidate, Department of Meteorology
The Pennsylvania State University
503 Walker Building, University Park, PA 16802
hilton@...3085...
#--------------------------------------------------
# amost right...
import numpy as np
import numpy.ma as ma
from mpl_toolkits.basemap import Basemap, maskoceans
import matplotlib.pyplot as plt
import matplotlib.colors
if __name__=="__main__":
# setup a basemap instance & draw a map
m_aeqd = Basemap(width=9e5,height=9e5,projection='aeqd',
lat_0=28.46,lon_0=360-80.67, resolution='i', area_thresh=1000,
rsphere=6371007.181000)
col_water='#B9D3EE' #SlateGray2
col_land ='#1C1C1C'
m_aeqd.drawmapboundary(fill_color=col_water)
# draw coasts and fill continents.
m_aeqd.drawcoastlines(linewidth=0.5)
m_aeqd.fillcontinents(color=col_land,lake_color=col_water, zorder=0)
# create a 100 x 100 pseudodata array with valid data between 0
and 50 and some "missing" data (less than zero)
n=100
X = ma.masked_less(np.random.random_integers(-1, 50, (n,n)), 0)
plot_mid = np.mean((m_aeqd.llcrnrx, m_aeqd.urcrnrx))
Xu, Xv = np.meshgrid(np.arange(stop=plot_mid + 500*n,
start=plot_mid - 500*n, step=1000),
np.arange(stop=m_aeqd.urcrnry,
start=m_aeqd.urcrnry - 1000*n, step=1000))
Xlon, Xlat = m_aeqd(Xu, Xv, inverse=True)
#setup a colormap and plot the data
cmap = matplotlib.cm.get_cmap("Blues", 25)
#mask oceans
ocean_mask = maskoceans(Xlon, Xlat, X)
#now I'm stumped how to incorporate oceans_mask into the color map
oceans_cmap = matplotlib.colors.ListedColormap((col_land, "#000000"),
name="oceans", N=2)
cmap.set_bad(color="#FF0000") #show missing vals in bright red
m_aeqd.pcolormesh(Xu, Xv, ocean_mask, cmap=cmap)
plt.colorbar()
#it seems like I could do another pcolormesh call with
#ocean_mask.mask and oceans_cmap; I'd need to set the
#transparency. It seems like the more elegant solution is to
#devise cmap to account for ocean_mask.mask (water) separately
#from X.mask (data that are actually missing). I'm not sure how
#do that though.