Filling between curves conditionally

Does anybody know of an easy way to take two intersecting curves, A(x) and B(x), and fill the areas between them only when A(x) < B(x) and not when A(x) > B(x)?

···

Zane Selvans

Amateur Earthling

zane@…1923…

303/815-6866

http://zaneselvans.org

PGP Key: 55E0815F

2008/11/22 Zane Selvans <zane@...1923...>:

Does anybody know of an easy way to take two intersecting curves, A(x) and
B(x), and fill the areas between them only when A(x) < B(x) and not when
A(x) > B(x)?

Looks like this example from the new shiny matplotlib website should help:

http://matplotlib.sourceforge.net/examples/pylab_examples/fill_between_posneg.html

Angus.

···

--
Zane Selvans
Amateur Earthling
zane@...1923...
303/815-6866
http://zaneselvans.org
PGP Key: 55E0815F

--
AJC McMorland
Post-doctoral research fellow
Neurobiology, University of Pittsburgh

Fortuitously, on Friday, I added a couple of methods to the polygon
collections code to make this a lot easier. I just tweaked these
examples to work with the use case in this post. Take a look at

  http://matplotlib.sourceforge.net/examples/api/fill_where_demo.html

The code is much simpler than the fill_between_posneg original
example, which I have just removed from svn.

JDH

···

On Sat, Nov 22, 2008 at 6:46 PM, Angus McMorland <amcmorl@...287...> wrote:

2008/11/22 Zane Selvans <zane@...1923...>:

Does anybody know of an easy way to take two intersecting curves, A(x) and
B(x), and fill the areas between them only when A(x) < B(x) and not when
A(x) > B(x)?

Looks like this example from the new shiny matplotlib website should help:

http://matplotlib.sourceforge.net/examples/pylab_examples/fill_between_posneg.html

The fill between use case is common enough that I decided to make it
an axes/pyplot method. No need to use the intermediate
"mlab.poly_between" anymore. fill_between has signature::

  fill_between(x, y1, y2=0, where=None, **kwargs)

y1 or y2 can be scalars or length x arrays. If where is None, the
fill will be make everywhere between y1 and y2. If where is not None,
it is a len(x) np boolean array and the fill will happen only where
where==True.

The examples are all now folded into fill_between.py

http://matplotlib.sourceforge.net/examples/pylab_examples/fill_between.html

JDH

···

On Sun, Nov 23, 2008 at 1:26 PM, John Hunter <jdh2358@...287...> wrote:

http://matplotlib.sourceforge.net/examples/api/fill_where_demo.html

The code is much simpler than the fill_between_posneg original
example, which I have just removed from svn.

Sigh.

I’ve never been able to get the whole SciPy dependency mess to successfully build from source, so I’m running from the OS X Superpack that Chris Fonnesbeck puts out at http://macinscience.org Unfortunately some of the versions of stuff being pulled in there are kind of stale it looks like.

Maybe I should give it another go from source or pre-built SVN binaries. Has it gotten any easier lately?

Zane

···

On Nov 23, 2008, at 12:36 PM, John Hunter wrote:

On Sun, Nov 23, 2008 at 1:26 PM, John Hunter <jdh2358@…287…> wrote:

The code is much simpler than the fill_between_posneg original
example, which I have just removed from svn.

The fill between use case is common enough that I decided to make it
an axes/pyplot method. No need to use the intermediate
“mlab.poly_between” anymore. fill_between has signature::

Zane Selvans

Amateur Earthling

zane@…1923…

303/815-6866

http://zaneselvans.org

PGP Key: 55E0815F

The version of NumPy in Chris's superpack should be recent enough for
you to just need to build matplotlib from SVN and not the other stuff,
and I assume he includes installation of wxPython or some other
compatible backend for matplotlib. It's really straightforward; you
just need to get the source from svn and run the setup.py file inside
with the target "install."

Last I checked, if you were using Leopard, a bug in Apple's GCC 4.0
got angry with the -O3 optimisation flag so you had to go into
/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/config
and edit the Makefile to change "-O3" to "-Os" in the OPT line under
Compiler flags to get around that (there are other methods that are
slightly more complicated that don't sacrifice using O3, but I think
the "Os" change was deemed the easiest thing to do here). I don't know
if this has changed since then, so hopefully John or someone else will
correct me if this is no longer the case in Leopard. Either way, it's
pretty straightforward; just change one line in the Python Makefile
and matplotlib will install with a simple "sudo python setup.py
install"

Josh

···

On Sun, Nov 23, 2008 at 2:01 PM, Zane Selvans <zane@...1923...> wrote:

On Nov 23, 2008, at 12:36 PM, John Hunter wrote:

On Sun, Nov 23, 2008 at 1:26 PM, John Hunter <jdh2358@...287...> wrote:

The code is much simpler than the fill_between_posneg original

example, which I have just removed from svn.

The fill between use case is common enough that I decided to make it
an axes/pyplot method. No need to use the intermediate
"mlab.poly_between" anymore. fill_between has signature::

Sigh.
I've never been able to get the whole SciPy dependency mess to successfully
build from source, so I'm running from the OS X Superpack that Chris
Fonnesbeck puts out at http://macinscience.org Unfortunately some of the
versions of stuff being pulled in there are kind of stale it looks like.
Maybe I should give it another go from source or pre-built SVN binaries.
Has it gotten any easier lately?
Zane
--
Zane Selvans
Amateur Earthling
zane@...1923...
303/815-6866
http://zaneselvans.org
PGP Key: 55E0815F

-------------------------------------------------------------------------
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-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Either way, it’s
pretty straightforward; just change one line in the Python Makefile
and matplotlib will install with a simple “sudo python setup.py
install”

Huh, well there was a make target for Leopard that had that fixed CFLAGS that you suggested, and it seemed to build and install without any major complaints. If I rename the Matplotlib directory that was installed by the SciPy superpack, and try to fire up ipython -pylab, it seems to work! Woo hoo!

It looks like there’s a tiny doc bug here: http://matplotlib.sourceforge.net/examples/pylab_examples/fill_between.html

ax = fig.add_subplot(111)

ax1.plot(x, y1, x, y2, color=‘black’)

ax.fill_between(x, y1, y2, where=y2>y1, facecolor=‘green’)

ax.fill_between(x, y1, y2, where=y2<=y1, facecolor=‘red’)

ax.set_title(‘fill between where’)

It should be calling ax.plot() not ax1.plot()

Incidentally, when you do it with ax.plot() instead you can see more easily that the corners where the two sinusoidal functions intersect are getting kind of chopped off by the polygon filling. Don’t know if there’s an easy way to fix that - maybe by forcing the list of polygon vertices to always explicitly include the points of intersection between the functions being filled_between? Or maybe just by increasing the number of vertices, though I assume that would slow things down.

···

Zane Selvans

Amateur Earthling

zane@…1923…

303/815-6866

http://zaneselvans.org

PGP Key: 55E0815F

Some time back, I wrote code to generate a fairly complex polyfill in
a plot in R,

http://www.oplnk.net/~ajackson/weather/Temperature_2000.png

The key bit of code to find the intersections between all the curves
to fill the corners correctly is here (note that this is "R" code):

intersect <- function(a, b, c, d) {
    # test two line segments for intersection.
    # modified from segseg in "Computational Geometry in C"
    # by Joseph O'Rourke

    p = c(0,0)

   denom = a[1] * ( d[2] - c[2] ) +
           b[1] * ( c[2] - d[2] ) +
           d[1] * ( b[2] - a[2] ) +
           c[1] * ( a[2] - b[2] );

   # If denom is zero, then segments are parallel: handle separately.
   if (abs(denom) <= 1.0e-10) {
       return (c(p,0))
    }

   num = a[1] * ( d[2] - c[2] ) +
            c[1] * ( a[2] - d[2] ) +
            d[1] * ( c[2] - a[2] );
   if ( (num == 0.0) || (num == denom) ) code = 0;
   s = num / denom;

   num = -( a[1] * ( c[2] - b[2] ) +
            b[1] * ( a[2] - c[2] ) +
            c[1] * ( b[2] - a[2] ) );
   if ( (num == 0.0) || (num == denom) ) code = 0;
   t = num / denom;

   if ( (0.0 < s) && (s < 1.0) &&
             (0.0 < t) && (t < 1.0) ) {
     code = 1;
     }
   else if ( (0.0 > s) || (s > 1.0) ||
             (0.0 > t) || (t > 1.0) ) {
     code = 0;
     }

   p[1] = a[1] + s * ( b[1] - a[1] );
   p[2] = a[2] + s * ( b[2] - a[2] );

   c(p,code);
}

# Intersect two lines defined by a series of segments. Assume the
# lines have common x-values and differ only in y
# intersect is array of (x,y) values

intersect.lines <- function (y1,y2,x) {
    intersect = array(data = NA, dim = c(2,0), dimnames = NULL)
    for (i in 2:length(x)) {
       a = c(x[i-1], y1[i-1])
       b = c(x[i], y1[i])
       c = c(x[i-1], y2[i-1])
       d = c(x[i], y2[i])
       foo = intersect(a,b,c,d)
       if (foo[3]) {
            intersect = cbind(intersect, foo[1:2])
       }
    }
    intersect
}

···

On Sun, 23 Nov 2008 16:48:59 -0800 Zane Selvans <zane@...1923...> wrote:

Incidentally, when you do it with ax.plot() instead you can see more
easily that the corners where the two sinusoidal functions intersect
are getting kind of chopped off by the polygon filling. Don't know if
there's an easy way to fix that - maybe by forcing the list of polygon
vertices to always explicitly include the points of intersection
between the functions being filled_between? Or maybe just by
increasing the number of vertices, though I assume that would slow
things down.

--
-----------------------------------------------------------------------

Alan K. Jackson | To see a World in a Grain of Sand |
alan@...895... | And a Heaven in a Wild Flower, |
www.ajackson.org | Hold Infinity in the palm of your hand |
Houston, Texas | And Eternity in an hour. - Blake |

-----------------------------------------------------------------------