On 05/27/2010 01:58 PM, T J wrote:
> On Thu, May 27, 2010 at 3:23 PM, Eric Firing<efiring@...> wrote:
>> I'm not sure I understand the problem; could you provide a tiny example
>> to illustrate?
> Sure, let me focus just on the interpolation and I'll leave the
> filtering issue out.
> In the script below, I plot a 3x3 array with the center element having
> an "over" value. In the default case, because its value is over, the
> colormap will assign it the maximum color. I also plot the case when
> the "over" color is explicitly set to the minimum color and also to
> white. What I want is this:
> The center element should be an equal mixture of the 4 elements around it.
You can't do this via any manipulation of the colormap, or any fancier
colormap specification--instead, you have to manipulate the data value.
For example, you could identify the "over" values in your data, and
then use 2-D interpolation to replace them with the values you want.
Basemap includes a 2-D interpolation routine:
from mpl_toolkits.basemap import interp
> This is partially achieved with "white" (and I suppose I could pick
> "grey" or "black"), but I think it might be nicer if it were a pure
> mixture, rather than a mixture of the surrounding colors and the
> "over" color.
> The script is attached below. Sorry it is a bit long, but I needed a
> discrete colormap. Can we get cmap_discrete() into matplotlib?
No, because it doesn't make much sense, given the mpl paradigm in which
a colormap and a norm work together. If you want 4 colors, make a
colormap with 4 colors, and use a norm that maps your data to those 4
cm4 = get_cmap('jet', 4)
cm4a = mpl.colors.ListedColormap(get_cmap('jet', 256)([20, 70, 150, 200]))
You can select any discrete set of colors you want using ListedColormap.
Then you can use the default Normalize, or a custom BoundaryNorm, to map
data ranges to the colors. You just don't need a lookup table with 1024
entries to specify 4 colors--it doesn't gain you anything.
> import matplotlib.pyplot as plt
> import matplotlib.colors
> import numpy as np
> from scipy import interpolate
> #### http://www.scipy.org/Cookbook/Matplotlib/ColormapTransformations
> #### Can this be added to matplotlib?
> def cmap_discretize(cmap, N):
> """Return a discrete colormap from the continuous colormap cmap.
> cmap: colormap instance, eg. cm.jet.
> N: Number of colors.
> x = resize(arange(100), (5,100))
> djet = cmap_discretize(cm.jet, 5)
> imshow(x, cmap=djet)
> cdict = cmap._segmentdata.copy()
> # N colors
> colors_i = np.linspace(0,1.,N)
> # N+1 indices
> indices = np.linspace(0,1.,N+1)
> for key in ('red','green','blue'):
> # Find the N colors
> D = np.array(cdict[key])
> I = interpolate.interp1d(D[:,0], D[:,1])
> colors = I(colors_i)
> # Place these colors at the correct indices.
> A = np.zeros((N+1,3), float)
> A[:,0] = indices
> A[1:,1] = colors
> A[:-1,2] = colors
> # Create a tuple for the dictionary.
> L = 
> for l in A:
> cdict[key] = tuple(L)
> # Return colormap object.
> return matplotlib.colors.LinearSegmentedColormap('colormap',cdict,1024)
> def draw(m, cm, norm, ncolors):
> ax = plt.gca()
> ai = ax.imshow(m, cmap=cm, norm=norm, interpolation='gaussian')
> cb = ax.figure.colorbar(ai)
> cb.set_ticks(np.linspace(.5, ncolors-.5, ncolors))
> cb.set_ticklabels(['$%s$' % (i,) for i in np.arange(ncolors)])
> return ai, cb
> if __name__ == '__main__':
> ncolors = 4
> norm = plt.Normalize(vmax=ncolors)
> m = np.array([[0, 0, 1],
> [3, 10, 1],
> [3, 2, 2]])
> for over in [None, 'min', (1,1,1,1)]:
> f = plt.figure()
> cm = cmap_discretize(plt.cm.jet, ncolors)
> if over == 'min':
> elif over is not None:
> ai, cb = draw(m, cm, norm, ncolors)