Revision: 4934
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4934&view=rev
Author:   efiring
Date:     2008-02-03 13:26:42 -0800 (Sun, 03 Feb 2008)

Log Message:
-----------
Modified BoundaryNorm, examples, colorbar support

Modified Paths:
--------------
    trunk/matplotlib/CHANGELOG
    trunk/matplotlib/examples/colorbar_only.py
    trunk/matplotlib/examples/image_masked.py
    trunk/matplotlib/lib/matplotlib/colorbar.py
    trunk/matplotlib/lib/matplotlib/colors.py

Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG  2008-02-03 21:10:22 UTC (rev 4933)
+++ trunk/matplotlib/CHANGELOG  2008-02-03 21:26:42 UTC (rev 4934)
@@ -1,3 +1,6 @@
+2008-02-03 Added BoundaryNorm, with examples in colorbar_only.py
+           and image_masked.py. - EF
+
 2008-02-03 Force dpi=72 in pdf backend to fix picture size bug. - JKS
 
 2008-02-01 Fix reference leak in ft2font Glyph objects. - MGD

Modified: trunk/matplotlib/examples/colorbar_only.py
===================================================================
--- trunk/matplotlib/examples/colorbar_only.py  2008-02-03 21:10:22 UTC (rev 
4933)
+++ trunk/matplotlib/examples/colorbar_only.py  2008-02-03 21:26:42 UTC (rev 
4934)
@@ -35,7 +35,7 @@
 # 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)
+norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
 cb2 = mpl.colorbar.ColorbarBase(ax2, cmap=cmap,
                                      norm=norm,
                                      # to use 'extend', you must

Modified: trunk/matplotlib/examples/image_masked.py
===================================================================
--- trunk/matplotlib/examples/image_masked.py   2008-02-03 21:10:22 UTC (rev 
4933)
+++ trunk/matplotlib/examples/image_masked.py   2008-02-03 21:26:42 UTC (rev 
4934)
@@ -1,6 +1,8 @@
 #!/usr/bin/env python
 '''imshow with masked array input and out-of-range colors.
 
+    The second subplot illustrates the use of BoundaryNorm to
+    get a filled contour effect.
 '''
 
 from pylab import *
@@ -31,10 +33,23 @@
 # range to which the regular palette color scale is applied.
 # Anything above that range is colored based on palette.set_over, etc.
 
+subplot(1,2,1)
 im = imshow(Zm, interpolation='bilinear',
     cmap=palette,
     norm = colors.Normalize(vmin = -1.0, vmax = 1.0, clip = False),
     origin='lower', extent=[-3,3,-3,3])
 title('Green=low, Red=high, Blue=bad')
-colorbar(im, extend='both', shrink=0.8)
+colorbar(im, extend='both', orientation='horizontal', shrink=0.8)
+
+subplot(1,2,2)
+im = imshow(Zm, interpolation='nearest',
+    cmap=palette,
+    norm = colors.BoundaryNorm([-1, -0.5, -0.2, 0, 0.2, 0.5, 1],
+                        ncolors=256, clip = False),
+    origin='lower', extent=[-3,3,-3,3])
+title('With BoundaryNorm')
+colorbar(im, extend='both', spacing='proportional',
+                orientation='horizontal', shrink=0.8)
+
 show()
+

Modified: trunk/matplotlib/lib/matplotlib/colorbar.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/colorbar.py 2008-02-03 21:10:22 UTC (rev 
4933)
+++ trunk/matplotlib/lib/matplotlib/colorbar.py 2008-02-03 21:26:42 UTC (rev 
4934)
@@ -323,6 +323,9 @@
                     nv = len(self._values)
                     base = 1 + int(nv/10)
                     locator = ticker.IndexLocator(base=base, offset=0)
+                elif isinstance(self.norm, colors.BoundaryNorm):
+                    b = self.norm.boundaries
+                    locator = ticker.FixedLocator(b, nbins=10)
                 elif isinstance(self.norm, colors.LogNorm):
                     locator = ticker.LogLocator()
                 else:
@@ -389,6 +392,23 @@
             self._boundaries = b
             self._values = v
             return
+        elif isinstance(self.norm, colors.BoundaryNorm):
+            b = list(self.norm.boundaries)
+            if self.extend in ('both', 'min'):
+                b = [b[0]-1] + b
+            if self.extend in ('both', 'max'):
+                b = b + [b[-1] + 1]
+            b = npy.array(b)
+            v = npy.zeros((len(b)-1,), dtype=float)
+            bi = self.norm.boundaries
+            v[self._inside] = 0.5*(bi[:-1] + bi[1:])
+            if self.extend in ('both', 'min'):
+                v[0] = b[0] - 1
+            if self.extend in ('both', 'max'):
+                v[-1] = b[-1] + 1
+            self._boundaries = b
+            self._values = v
+            return
         else:
             if not self.norm.scaled():
                 self.norm.vmin = 0

Modified: trunk/matplotlib/lib/matplotlib/colors.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/colors.py   2008-02-03 21:10:22 UTC (rev 
4933)
+++ trunk/matplotlib/lib/matplotlib/colors.py   2008-02-03 21:26:42 UTC (rev 
4934)
@@ -685,13 +685,41 @@
             return vmin * pow((vmax/vmin), value)
 
 class BoundaryNorm(Normalize):
-    def __init__(self, boundaries, clip=False):
+    '''
+    Generate a colormap index based on discrete intervals.
+
+    Unlike Normalize or LogNorm, BoundaryNorm maps values
+    to integers instead of to the interval 0-1.
+
+    Mapping to the 0-1 interval could have been done via
+    piece-wise linear interpolation, but using integers seems
+    simpler, and reduces the number of conversions back and forth
+    between integer and floating point.
+    '''
+    def __init__(self, boundaries, ncolors, clip=False):
+        '''
+        args:
+            boundaries: a monotonically increasing sequence
+            ncolors: number of colors in the colormap to be used
+
+        If b[i] <= v < b[i+1] then v is mapped to color j;
+        as i varies from 0 to len(boundaries)-2,
+        j goes from 0 to ncolors-1.
+
+        Out-of-range values are mapped to -1 if low and ncolors
+        if high; these are converted to valid indices by
+        Colormap.__call__.
+        '''
         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)
+        self.Ncmap = ncolors
+        if self.N-1 == self.Ncmap:
+            self._interp = False
+        else:
+            self._interp = True
 
     def __call__(self, x, clip=None):
         if clip is None:
@@ -704,15 +732,17 @@
         iret = npy.zeros(x.shape, dtype=npy.int16)
         for i, b in enumerate(self.boundaries):
             iret[xx>=b] = i
+        if self._interp:
+            iret = (iret * (float(self.Ncmap-1)/(self.N-2))).astype(npy.int16)
         iret[xx<self.vmin] = -1
-        iret[xx>=self.vmax] = self.N
-        ret = ma.array(iret / float(self.N-1), mask=mask)
+        iret[xx>=self.vmax] = self.Ncmap
+        ret = ma.array(iret, mask=mask)
         if ret.shape == () and not mask:
-            ret = float(ret)  # assume python scalar
+            ret = int(ret)  # assume python scalar
         return ret
 
     def inverse(self, value):
-        return self.midpoints[int(value*(self.N-1))]
+        return ValueError("BoundaryNorm is not invertible")
 
 
 class NoNorm(Normalize):


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to