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