On Thu, Apr 30, 2009 at 2:29 PM, John Hunter <jdh2...@gmail.com> wrote:
>
>
> On Thu, Apr 30, 2009 at 4:14 PM, T J <tjhn...@gmail.com> wrote:
>>
>> Fill between is for filling between two y-values over a range of
>> x-values.  Is there anything which fills between to x-values over a
>> range of y-values?
>
> Nothing with the ease of use of fill_between, but you can always write your
> own PolyCollection, which is what fill_between does (see the function
> implementation for details) or create a Polygon for a simple region.  My use
> cases are typically in the time series world where I have datetime on the
> x-axis and some range of values on the y.  If folks think it is sufficiently
> useful to have a fill_betweenx function with a similar interface, you could
> probably fairly easy port fill_between to fill_betweenx.
>
>   http://matplotlib.sourceforge.net/faq/howto_faq.html#contributing-howto
>

Done.  Attached diff is against rev7075.
Index: lib/matplotlib/pyplot.py
===================================================================
--- lib/matplotlib/pyplot.py	(revision 7075)
+++ lib/matplotlib/pyplot.py	(working copy)
@@ -1185,7 +1185,8 @@
     figtext         add text in figure coords
     figure          create or change active figure
     fill            make filled polygons
-    fill_between    make filled polygons
+    fill_between    make filled polygons between two sets of y-values
+    fill_betweenx   make filled polygons between two sets of x-values
     gca             return the current axes
     gcf             return the current figure
     gci             get the current image, or None
@@ -1945,6 +1946,28 @@
 
 # This function was autogenerated by boilerplate.py.  Do not edit as
 # changes will be lost
+def fill_betweenx(*args, **kwargs):
+    # allow callers to override the hold state by passing hold=True|False
+    b = ishold()
+    h = kwargs.pop('hold', None)
+    if h is not None:
+        hold(h)
+    try:
+        ret =  gca().fill_betweenx(*args, **kwargs)
+        draw_if_interactive()
+    except:
+        hold(b)
+        raise
+
+    hold(b)
+    return ret
+if Axes.fill_betweenx.__doc__ is not None:
+    fill_betweenx.__doc__ = dedent(Axes.fill_betweenx.__doc__) + """
+
+Additional kwargs: hold = [True|False] overrides default hold state"""
+
+# This function was autogenerated by boilerplate.py.  Do not edit as
+# changes will be lost
 def hexbin(*args, **kwargs):
     # allow callers to override the hold state by passing hold=True|False
     b = ishold()
Index: lib/matplotlib/axes.py
===================================================================
--- lib/matplotlib/axes.py	(revision 7075)
+++ lib/matplotlib/axes.py	(working copy)
@@ -5809,10 +5809,10 @@
           an N length np array of the x data
 
         *y1*
-          an N length scalar or np array of the x data
+          an N length scalar or np array of the y data
 
         *y2*
-          an N length scalar or np array of the x data
+          an N length scalar or np array of the y data
 
         *where*
            if None, default to fill between everywhere.  If not None,
@@ -5827,6 +5827,12 @@
         %(PolyCollection)s
 
         .. plot:: mpl_examples/pylab_examples/fill_between.py
+
+        .. seealso::
+
+            :meth:`fill_betweenx`
+                for filling between two sets of x-values
+
         """
         # Handle united data, such as dates
         self._process_unit_info(xdata=x, ydata=y1, kwargs=kwargs)
@@ -5896,6 +5902,113 @@
         return collection
     fill_between.__doc__ = cbook.dedent(fill_between.__doc__) % martist.kwdocd
 
+    def fill_betweenx(self, y, x1, x2=0, where=None, **kwargs):
+        """
+        call signature::
+
+          fill_between(y, x1, x2=0, where=None, **kwargs)
+
+        Create a :class:`~matplotlib.collections.PolyCollection`
+        filling the regions between *x1* and *x2* where
+        ``where==True``
+
+        *y*
+          an N length np array of the y data
+
+        *x1*
+          an N length scalar or np array of the x data
+
+        *x2*
+          an N length scalar or np array of the x data
+
+        *where*
+           if None, default to fill between everywhere.  If not None,
+           it is a a N length numpy boolean array and the fill will
+           only happen over the regions where ``where==True``
+
+        *kwargs*
+          keyword args passed on to the :class:`PolyCollection`
+
+        kwargs control the Polygon properties:
+
+        %(PolyCollection)s
+
+        .. plot:: mpl_examples/pylab_examples/fill_betweenx.py
+
+        .. seealso::
+
+            :meth:`fill_between`
+                for filling between two sets of y-values
+
+        """
+        # Handle united data, such as dates
+        self._process_unit_info(ydata=y, xdata=x1, kwargs=kwargs)
+        self._process_unit_info(xdata=x2)
+
+        # Convert the arrays so we can work with them
+        y = np.asanyarray(self.convert_yunits(y))
+        x1 = np.asanyarray(self.convert_xunits(x1))
+        x2 = np.asanyarray(self.convert_xunits(x2))
+
+        if x1.ndim == 0:
+            x1 = np.ones_like(y)*x1
+        if x2.ndim == 0:
+            x2 = np.ones_like(y)*x2
+
+        if where is None:
+            where = np.ones(len(y), np.bool)
+        else:
+            where = np.asarray(where, np.bool)
+
+        if not (y.shape == x1.shape == x2.shape == where.shape):
+            raise ValueError("Argument dimensions are incompatible")
+
+        mask = reduce(ma.mask_or,
+                        [ma.getmask(y), ma.getmask(x1), ma.getmask(x2)])
+        if mask is not ma.nomask:
+            where &= ~mask
+
+        polys = []
+        for ind0, ind1 in mlab.contiguous_regions(where):
+            theseverts = []
+            yslice = y[ind0:ind1]
+            x1slice = x1[ind0:ind1]
+            x2slice = x2[ind0:ind1]
+
+            if not len(yslice):
+                continue
+
+            N = len(yslice)
+            Y = np.zeros((2*N+2, 2), np.float)
+
+            # the purpose of the next two lines is for when x2 is a
+            # scalar like 0 and we want the fill to go all the way
+            # down to 0 even if none of the x1 sample points do
+            Y[0] = x2slice[0], yslice[0]
+            Y[N+1] = x2slice[-1], yslice[-1]
+
+            Y[1:N+1,0] = x1slice
+            Y[1:N+1,1] = yslice
+            Y[N+2:,0] = x2slice[::-1]
+            Y[N+2:,1] = yslice[::-1]
+
+            polys.append(Y)
+
+        collection = mcoll.PolyCollection(polys, **kwargs)
+
+        # now update the datalim and autoscale
+        X1Y = np.array([x1[where], y[where]]).T
+        X2Y = np.array([x2[where], y[where]]).T
+        self.dataLim.update_from_data_xy(X1Y, self.ignore_existing_data_limits,
+                                         updatex=True, updatey=True)
+
+        self.dataLim.update_from_data_xy(X2Y, self.ignore_existing_data_limits,
+                                         updatex=False, updatey=True)
+        self.add_collection(collection)
+        self.autoscale_view()
+        return collection
+    fill_between.__doc__ = cbook.dedent(fill_between.__doc__) % martist.kwdocd
+
     #### plotting z(x,y): imshow, pcolor and relatives, contour
 
     def imshow(self, X, cmap=None, norm=None, aspect=None,
Index: boilerplate.py
===================================================================
--- boilerplate.py	(revision 7075)
+++ boilerplate.py	(working copy)
@@ -65,6 +65,7 @@
     'errorbar',
     'fill',
     'fill_between',
+    'fill_betweenx',
     'hexbin',
     'hist',
     'hlines',
Index: examples/pylab_examples/fill_betweenx.py
===================================================================
--- examples/pylab_examples/fill_betweenx.py	(revision 0)
+++ examples/pylab_examples/fill_betweenx.py	(revision 0)
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+import matplotlib.mlab as mlab
+from matplotlib.pyplot import figure, show
+import numpy as np
+
+## Copy of fill_between.py but using fill_betweenx() instead.
+
+x = np.arange(0.0, 2, 0.01)
+y1 = np.sin(2*np.pi*x)
+y2 = 1.2*np.sin(4*np.pi*x)
+
+fig = figure()
+ax1 = fig.add_subplot(311)
+ax2 = fig.add_subplot(312, sharex=ax1)
+ax3 = fig.add_subplot(313, sharex=ax1)
+
+ax1.fill_betweenx(x, 0, y1)
+ax1.set_ylabel('between y1 and 0')
+
+ax2.fill_betweenx(x, y1, 1)
+ax2.set_ylabel('between y1 and 1')
+
+ax3.fill_betweenx(x, y1, y2)
+ax3.set_ylabel('between y1 and y2')
+ax3.set_xlabel('x')
+
+# now fill between y1 and y2 where a logical condition is met.  Note
+# this is different than calling
+#   fill_between(x[where], y1[where],y2[where]
+# because of edge effects over multiple contiguous regions.
+fig = figure()
+ax = fig.add_subplot(211)
+ax.plot(y1, x, y2, x, color='black')
+ax.fill_betweenx(x, y1, y2, where=y2>=y1, facecolor='green')
+ax.fill_betweenx(x, y1, y2, where=y2<=y1, facecolor='red')
+ax.set_title('fill between where')
+
+# Test support for masked arrays.
+y2 = np.ma.masked_greater(y2, 1.0)
+ax1 = fig.add_subplot(212, sharex=ax)
+ax1.plot(y1, x, y2, x, color='black')
+ax1.fill_betweenx(x, y1, y2, where=y2>=y1, facecolor='green')
+ax1.fill_betweenx(x, y1, y2, where=y2<=y1, facecolor='red')
+ax1.set_title('Now regions with y2 > 1 are masked')
+
+# This example illustrates a problem; because of the data
+# gridding, there are undesired unfilled triangles at the crossover
+# points.  A brute-force solution would be to interpolate all
+# arrays to a very fine grid before plotting.
+
+show()
+

Property changes on: examples/pylab_examples/fill_betweenx.py
___________________________________________________________________
Name: svn:mime-type
   + text/x-python
Name: svn:keywords
   + "Author Date Id Rev URL"
Name: svn:eol-style
   + native

------------------------------------------------------------------------------
Register Now & Save for Velocity, the Web Performance & Operations 
Conference from O'Reilly Media. Velocity features a full day of 
expert-led, hands-on workshops and two days of sessions from industry 
leaders in dedicated Performance & Operations tracks. Use code vel09scf 
and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to