From: <ef...@us...> - 2008-02-02 07:53:07
|
Revision: 4930 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4930&view=rev Author: efiring Date: 2008-02-01 23:53:03 -0800 (Fri, 01 Feb 2008) Log Message: ----------- Added BoundaryNorm to support irregular discrete color intervals Modified Paths: -------------- trunk/matplotlib/examples/colorbar_only.py trunk/matplotlib/lib/matplotlib/colorbar.py trunk/matplotlib/lib/matplotlib/colors.py Modified: trunk/matplotlib/examples/colorbar_only.py =================================================================== --- trunk/matplotlib/examples/colorbar_only.py 2008-02-01 20:15:59 UTC (rev 4929) +++ trunk/matplotlib/examples/colorbar_only.py 2008-02-02 07:53:03 UTC (rev 4930) @@ -2,12 +2,12 @@ Make a colorbar as a separate figure. ''' -import pylab -import matplotlib as mpl +from matplotlib import pyplot, mpl # Make a figure and axes with dimensions as desired. -fig = pylab.figure(figsize=(8,1.5)) -ax = fig.add_axes([0.05, 0.4, 0.9, 0.5]) +fig = pyplot.figure(figsize=(8,3)) +ax1 = fig.add_axes([0.05, 0.65, 0.9, 0.15]) +ax2 = fig.add_axes([0.05, 0.25, 0.9, 0.15]) # Set the colormap and norm to correspond to the data for which # the colorbar will be used. @@ -19,10 +19,33 @@ # standalone colorbar. There are many more kwargs, but the # following gives a basic continuous colorbar with ticks # and labels. -cb = mpl.colorbar.ColorbarBase(ax, cmap=cmap, +cb1 = mpl.colorbar.ColorbarBase(ax1, cmap=cmap, norm=norm, orientation='horizontal') -cb.set_label('Some Units') +cb1.set_label('Some Units') -pylab.show() +# The second example illustrates the use of a ListedColormap, a +# BoundaryNorm, and extended ends to show the "over" and "under" +# value colors. +cmap = mpl.colors.ListedColormap(['r', 'g', 'b', 'c']) +cmap.set_over('0.25') +cmap.set_under('0.75') +# If a ListedColormap is used, the length of the bounds array must be +# one greater than the length of the color list. The bounds must be +# monotonically increasing. +bounds = [1, 2, 4, 7, 8] +norm = mpl.colors.BoundaryNorm(bounds) +cb2 = mpl.colorbar.ColorbarBase(ax2, cmap=cmap, + norm=norm, + # to use 'extend', you must + # specify two extra boundaries: + boundaries=[0]+bounds+[13], + extend='both', + ticks=bounds, # optional + spacing='proportional', + orientation='horizontal') +cb2.set_label('Discrete intervals, some other units') + +pyplot.show() + Modified: trunk/matplotlib/lib/matplotlib/colorbar.py =================================================================== --- trunk/matplotlib/lib/matplotlib/colorbar.py 2008-02-01 20:15:59 UTC (rev 4929) +++ trunk/matplotlib/lib/matplotlib/colorbar.py 2008-02-02 07:53:03 UTC (rev 4930) @@ -356,7 +356,7 @@ if b is None: b = self.boundaries if b is not None: - self._boundaries = npy.array(b) + self._boundaries = npy.asarray(b, dtype=float) if self.values is None: self._values = 0.5*(self._boundaries[:-1] + self._boundaries[1:]) @@ -456,7 +456,12 @@ Return colorbar data coordinates for the boundaries of a proportional colorbar. ''' - y = self.norm(self._boundaries.copy()) + if isinstance(self.norm, colors.BoundaryNorm): + b = self._boundaries[self._inside] + y = (self._boundaries - self._boundaries[0]) + y = y / (self._boundaries[-1] - self._boundaries[0]) + else: + y = self.norm(self._boundaries.copy()) if self.extend in ('both', 'min'): y[0] = -0.05 if self.extend in ('both', 'max'): @@ -492,7 +497,7 @@ within range, together with their corresponding colorbar data coordinates. ''' - if isinstance(self.norm, colors.NoNorm): + if isinstance(self.norm, (colors.NoNorm, colors.BoundaryNorm)): b = self._boundaries xn = x xout = x Modified: trunk/matplotlib/lib/matplotlib/colors.py =================================================================== --- trunk/matplotlib/lib/matplotlib/colors.py 2008-02-01 20:15:59 UTC (rev 4929) +++ trunk/matplotlib/lib/matplotlib/colors.py 2008-02-02 07:53:03 UTC (rev 4930) @@ -684,7 +684,37 @@ else: return vmin * pow((vmax/vmin), value) +class BoundaryNorm(Normalize): + def __init__(self, boundaries, clip=False): + self.clip = clip + self.vmin = boundaries[0] + self.vmax = boundaries[-1] + self.boundaries = npy.asarray(boundaries) + self.midpoints = 0.5 *(self.boundaries[:-1] + self.boundaries[1:]) + self.N = len(self.boundaries) + def __call__(self, x, clip=None): + if clip is None: + clip = self.clip + x = ma.asarray(x) + mask = ma.getmaskarray(x) + xx = x.filled(self.vmax+1) + if clip: + npy.clip(xx, self.vmin, self.vmax) + iret = npy.zeros(x.shape, dtype=npy.int16) + for i, b in enumerate(self.boundaries): + iret[xx>=b] = i + iret[xx<self.vmin] = -1 + iret[xx>=self.vmax] = self.N + ret = ma.array(iret / float(self.N-1), mask=mask) + if ret.shape == () and not mask: + ret = float(ret) # assume python scalar + return ret + + def inverse(self, value): + return self.midpoints[int(value*(self.N-1))] + + class NoNorm(Normalize): ''' Dummy replacement for Normalize, for the case where we This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |