colormaps - combine linear segmented with discrete sections?
Timothy W. Hilton <hilton@...
2010-11-01 17:47:44 GMT
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
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!
Timothy W. Hilton
PhD Candidate, Department of Meteorology
The Pennsylvania State University
503 Walker Building, University Park, PA 16802
# amost right...
import numpy as np
import numpy.ma as ma
from mpl_toolkits.basemap import Basemap, maskoceans
import matplotlib.pyplot as plt
# 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,
# draw coasts and fill continents.
# create a 100 x 100 pseudodata array with valid data between 0
and 50 and some "missing" data (less than zero)
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),
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)
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"),
cmap.set_bad(color="#FF0000") #show missing vals in bright red
m_aeqd.pcolormesh(Xu, Xv, ocean_mask, cmap=cmap)
#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.
Nokia and AT&T present the 2010 Calling All Innovators-North America contest
Create new apps & games for the Nokia N8 for consumers in U.S. and Canada
$10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing
Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store