Revision: 6423
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6423&view=rev
Author:   jdh2358
Date:     2008-11-20 18:58:54 +0000 (Thu, 20 Nov 2008)

Log Message:
-----------
added some helper functions for poly collections and masked regions

Modified Paths:
--------------
    trunk/matplotlib/CHANGELOG
    trunk/matplotlib/lib/matplotlib/collections.py
    trunk/matplotlib/lib/matplotlib/mlab.py
    trunk/matplotlib/src/_backend_agg.cpp

Added Paths:
-----------
    trunk/matplotlib/examples/api/filled_masked_regions.py

Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG  2008-11-20 15:46:46 UTC (rev 6422)
+++ trunk/matplotlib/CHANGELOG  2008-11-20 18:58:54 UTC (rev 6423)
@@ -1,3 +1,11 @@
+2008-11-20 Added some static helper methods
+           BrokenHBarCollection.span_masked and
+           PolyCollection.fill_between_masked for visualizing
+           non-masked regions.  In the longer term, the better
+           solution will be to fix the relevant classes and functions
+           to handle masked data, so this may be a temporary solution
+           - JDH
+
 2008-11-12 Add x_isdata and y_isdata attributes to Artist instances,
            and use them to determine whether either or both
            coordinates are used when updating dataLim.  This is

Added: trunk/matplotlib/examples/api/filled_masked_regions.py
===================================================================
--- trunk/matplotlib/examples/api/filled_masked_regions.py                      
        (rev 0)
+++ trunk/matplotlib/examples/api/filled_masked_regions.py      2008-11-20 
18:58:54 UTC (rev 6423)
@@ -0,0 +1,45 @@
+"""
+Illustrate some helper functions for shading regions where a logical
+mask is True
+"""
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.collections as collections
+
+
+t = np.arange(0.0, 2, 0.01)
+s = np.sin(2*np.pi*t)
+
+fig = plt.figure()
+ax = fig.add_subplot(111)
+ax.set_title('using fill_between_masked')
+ax.plot(t, s, '-')
+ax.axhline(0, color='black', lw=2)
+
+collection = collections.PolyCollection.fill_between_masked(t, s, s>=0, 
yboundary=0, color='green', alpha=0.5)
+ax.add_collection(collection)
+
+collection = collections.PolyCollection.fill_between_masked(t, s, s<=0, 
yboundary=0, color='red', alpha=0.5)
+ax.add_collection(collection)
+
+
+fig = plt.figure()
+ax = fig.add_subplot(111)
+ax.set_title('using span_masked')
+ax.plot(t, s, '-')
+ax.axhline(0, color='black', lw=2)
+
+collection = collections.BrokenBarHCollection.span_masked(t, s>0, ymin=0, 
ymax=1, facecolor='green', alpha=0.5)
+ax.add_collection(collection)
+
+collection = collections.BrokenBarHCollection.span_masked(t, s<0, ymin=-1, 
ymax=0, facecolor='red', alpha=0.5)
+ax.add_collection(collection)
+
+
+
+plt.show()
+
+
+
+
+

Modified: trunk/matplotlib/lib/matplotlib/collections.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/collections.py      2008-11-20 15:46:46 UTC 
(rev 6422)
+++ trunk/matplotlib/lib/matplotlib/collections.py      2008-11-20 18:58:54 UTC 
(rev 6423)
@@ -19,6 +19,7 @@
 import matplotlib.artist as artist
 import matplotlib.backend_bases as backend_bases
 import matplotlib.path as mpath
+import matplotlib.mlab as mlab
 
 class Collection(artist.Artist, cm.ScalarMappable):
     """
@@ -234,7 +235,7 @@
             self._urls = [None,]
         else:
             self._urls = urls
-        
+
     def get_urls(self): return self._urls
 
     def set_offsets(self, offsets):
@@ -671,6 +672,49 @@
                 for x in self._sizes]
         return Collection.draw(self, renderer)
 
+
+    @staticmethod
+    def fill_between_masked(x, y, mask, yboundary=0, **kwargs):
+        """
+        Create a :class:`PolyCollection` filling the regions between *y*
+        and *yboundary7* where ``mask==True``
+
+
+        *x*
+          an N length np array of the x data
+
+        *y*
+          an N length np array of the y data
+
+        *mask*
+          an N length numpy boolean array
+
+        *yboundary*
+          a scalar to fill between *y* and the boundary
+
+        *kwargs*
+          keyword args passed on to the :class:`PolyCollection`
+
+        """
+        polys = []
+        for ind0, ind1 in mlab.contiguous_regions(mask):
+            theseverts = []
+            xslice = x[ind0:ind1]
+            yslice = y[ind0:ind1]
+            N = len(xslice)
+            X = np.zeros((2*N+2, 2), np.float)
+            X[0] = xslice[0], yboundary
+            X[N+1] = xslice[-1], yboundary
+            X[1:N+1,0] = xslice
+            X[1:N+1,1] = yslice
+            X[N+2:,0] = xslice[::-1]
+            X[N+2:,1] = yboundary
+
+            polys.append(X)
+
+        collection = PolyCollection(polys, **kwargs)
+        return collection
+
 class BrokenBarHCollection(PolyCollection):
     """
     A collection of horizontal bars spanning *yrange* with a sequence of
@@ -692,6 +736,25 @@
         PolyCollection.__init__(self, verts, **kwargs)
     __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
 
+
+    @staticmethod
+    def span_masked(x, mask, ymin, ymax, **kwargs):
+        """
+        Create a BrokenBarHCollection to plot horizontal bars from
+        over the regions in *x* where *mask* is True.  The bars range
+        on the y-axis from *ymin* to *ymax*
+
+        A :class:`BrokenBarHCollection` is returned.
+        **kwargs are passed on to the collection
+        """
+        xranges = []
+        for ind0, ind1 in mlab.contiguous_regions(mask):
+            xslice = x[ind0:ind1]
+            xranges.append((xslice[0], xslice[-1]-xslice[0]))
+
+        collection = BrokenBarHCollection(xranges, [ymin, ymax-ymin], **kwargs)
+        return collection
+
 class RegularPolyCollection(Collection):
     """Draw a collection of regular polygons with *numsides*."""
     _path_generator = mpath.Path.unit_regular_polygon

Modified: trunk/matplotlib/lib/matplotlib/mlab.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/mlab.py     2008-11-20 15:46:46 UTC (rev 
6422)
+++ trunk/matplotlib/lib/matplotlib/mlab.py     2008-11-20 18:58:54 UTC (rev 
6423)
@@ -159,7 +159,7 @@
 import csv, warnings, copy, os
 
 import numpy as np
-
+ma = np.ma
 from matplotlib import verbose
 
 import matplotlib.nxutils as nxutils
@@ -247,7 +247,7 @@
     #The checks for if y is x are so that we can use the same function to
     #implement the core of psd(), csd(), and spectrogram() without doing
     #extra calculations.  We return the unaveraged Pxy, freqs, and t.
-    
+
     #Make sure we're dealing with a numpy array. If y and x were the same
     #object to start with, keep them that way
     same_data = y is x
@@ -309,7 +309,7 @@
     Pxy /= (np.abs(windowVals)**2).sum()
     t = 1./Fs * (ind + NFFT / 2.)
     freqs = float(Fs) / pad_to * np.arange(numFreqs)
-    
+
     return Pxy, freqs, t
 
 #Split out these keyword docs so that they can be used elsewhere
@@ -2104,7 +2104,8 @@
 
 
 def csv2rec(fname, comments='#', skiprows=0, checkrows=0, delimiter=',',
-            converterd=None, names=None, missing='', missingd=None):
+            converterd=None, names=None, missing='', missingd=None,
+            use_mrecords=True):
     """
     Load data from comma/space/tab delimited file in *fname* into a
     numpy record array and return the record array.
@@ -2139,9 +2140,11 @@
       be masked, e.g. '0000-00-00' or 'unused'
 
     - *missing*: a string whose value signals a missing field regardless of
-      the column it appears in, e.g. 'unused'
+      the column it appears in
 
-    If no rows are found, *None* is returned -- see :file:`examples/loadrec.py`
+    - *use_mrecords*: if True, return an mrecords.fromrecords record array if 
any of the data are missing
+
+      If no rows are found, *None* is returned -- see 
:file:`examples/loadrec.py`
     """
 
     if converterd is None:
@@ -2338,7 +2341,8 @@
 
     if not len(rows):
         return None
-    if np.any(rowmasks):
+
+    if use_mrecords and np.any(rowmasks):
         try: from numpy.ma import mrecords
         except ImportError:
             raise RuntimeError('numpy 1.05 or later is required for masked 
array support')
@@ -2938,19 +2942,25 @@
       xv, yv = poly_below(0, x, y)
       ax.fill(xv, yv)
     """
-    xs = np.asarray(xs)
-    ys = np.asarray(ys)
+    if ma.isMaskedArray(xs) or ma.isMaskedArray(ys):
+        nx = ma
+    else:
+        nx = np
+
+    xs = nx.asarray(xs)
+    ys = nx.asarray(ys)
     Nx = len(xs)
     Ny = len(ys)
     assert(Nx==Ny)
-    x = xmin*np.ones(2*Nx)
-    y = np.ones(2*Nx)
+    x = xmin*nx.ones(2*Nx)
+    y = nx.ones(2*Nx)
     x[:Nx] = xs
     y[:Nx] = ys
     y[Nx:] = ys[::-1]
     return x, y
 
 
+
 def poly_between(x, ylower, yupper):
     """
     Given a sequence of *x*, *ylower* and *yupper*, return the polygon
@@ -2961,17 +2971,23 @@
     Return value is *x*, *y* arrays for use with
     :meth:`matplotlib.axes.Axes.fill`.
     """
+    if ma.isMaskedArray(ylower) or ma.isMaskedArray(yupper) or 
ma.isMaskedArray(x):
+        nx = ma
+    else:
+        nx = np
+
     Nx = len(x)
     if not cbook.iterable(ylower):
-        ylower = ylower*np.ones(Nx)
+        ylower = ylower*nx.ones(Nx)
 
     if not cbook.iterable(yupper):
-        yupper = yupper*np.ones(Nx)
+        yupper = yupper*nx.ones(Nx)
 
-    x = np.concatenate( (x, x[::-1]) )
-    y = np.concatenate( (yupper, ylower[::-1]) )
+    x = nx.concatenate( (x, x[::-1]) )
+    y = nx.concatenate( (yupper, ylower[::-1]) )
     return x,y
 
+
 def is_closed_polygon(X):
     """
     Tests whether first and last object in a sequence are the same.  These are
@@ -2980,6 +2996,28 @@
     """
     return np.all(X[0] == X[-1])
 
+
+def contiguous_regions(mask):
+    """
+    return a list of (ind0, ind1) such that mask[ind0:ind1].all() is
+    True and we cover all such regions
+
+    TODO: this is a pure python implementation which probably has a much 
faster numpy impl
+    """
+
+    in_region = None
+    boundaries = []
+    for i, val in enumerate(mask):
+        if in_region is None and val:
+            in_region = i
+        elif in_region is not None and not val:
+            boundaries.append((in_region, i))
+            in_region = None
+
+    if in_region is not None:
+        boundaries.append((in_region, i+1))
+    return boundaries
+
 ##################################################
 # Vector and path length geometry calculations
 ##################################################

Modified: trunk/matplotlib/src/_backend_agg.cpp
===================================================================
--- trunk/matplotlib/src/_backend_agg.cpp       2008-11-20 15:46:46 UTC (rev 
6422)
+++ trunk/matplotlib/src/_backend_agg.cpp       2008-11-20 18:58:54 UTC (rev 
6423)
@@ -385,7 +385,8 @@
   if (!py_convert_bbox(box_obj.ptr(), l, b, r, t))
     throw Py::TypeError("Invalid bbox provided to copy_from_bbox");
 
-  agg::rect_i rect((int)l, height - (int)t, (int)r, height - (int)b);
+  //  std::cout << l << " " << b << " " << r << " " << t << " " << (height - 
(int)b) << " " << height - (int)t << std::endl;
+  agg::rect_i rect((int)l, height - (int)b, (int)r, height - (int)t);
 
   BufferRegion* reg = NULL;
   try {
@@ -419,9 +420,11 @@
   BufferRegion* region  = static_cast<BufferRegion*>(args[0].ptr());
 
   if (region->data==NULL)
-    return Py::Object();
-  //throw Py::ValueError("Cannot restore_region from NULL data");
+    throw Py::ValueError("Cannot restore_region from NULL data");
+    //return Py::Object();
 
+  //std::cout << "restoring " << region->width << " " << region->height << " " 
<< region->stride << " " << region->rect.x1 << " " << region->rect.y1 << 
std::endl;
+
   agg::rendering_buffer rbuf;
   rbuf.attach(region->data,
              region->width,


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 the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to