I just started looking at pyx; it looks like a very good balance of power and
sane, good-looking defaults.

Anyway, one of the capabilities I like is filled graphs. So I started
experimenting with graphs/integral and graphs/partialfill in the gallery, and
believe I have come up with something a bit more generic that may be useful for
others as an example. Feel free to put it into the gallery, if you like.

It is basically a recipe for (a) drawing invisible plots in a graph, (b) filling
the area between any two plots in a graph, and (c) moving the fill item to the
back so that it doesn't obscure the actual graph. (c) is done by reordering
graphxy.items -- is there a cleaner way to re-order the components?

These are attached:

- errorarea.pdf - an example showing what I was trying to achieve, a shaded
error area (instead of error bars) around a curve

- bg_graphxy.py, errorarea.py, speed1.dat, speed2.dat - the source of the above

- partialfill2.py, integral2.py - further examples, showing how these current
examples from the gallery are greatly simplified by the bg_graphxy class (it is
not my intention to disparage these gallery examples, I learnt a lot from them)

Hope it's useful to someone.


--
-j.


from pyx import *

class bg_graphxy(graph.graphxy):
    def path_between(self, f, a=None, b=None):
        """Return the path f between x=a and x=b"""
        if a == None: a = self.axes['x'].axis.min
        if b == None: b = self.axes['x'].axis.max
        xa = self.xgridpath(a)
        xb = self.xgridpath(b)
        f_at_xa = f.intersect(xa)[0][0]
        f_at_xb = f.intersect(xb)[0][0]
        return f.split([f_at_xa, f_at_xb])[1]

    def area_between(self, f0, f1, a=None, b=None):
        """Return the area between the two plot paths f0 and f1, from x=a to
        x=b."""
        f0 = self.path_between(f0, a, b)
        f1 = self.path_between(f1, a, b).reversed()
        return f0 << f1

    def move_to_back(self, n=1):
        """Cycle the previous n items to the bottom (background)"""
        self.items = self.items[-n:] + self.items[:-n]

Attachment: errorarea.pdf
Description: Adobe PDF document

from pyx import *
from bg_graphxy import bg_graphxy

g = bg_graphxy(width=8,
               x=graph.axis.log(max=50),
               y=graph.axis.linear())

hidden = g.plot([graph.data.file('speed1.dat', x=1, y='$2/.97*.91'),
                 graph.data.file('speed1.dat', x=1, y='$2/.97')],
                [graph.style.line(None)])

shown = g.plot([graph.data.file('speed1.dat', x=1, y=2),
                graph.data.file('speed2.dat', x=1, y=2)],
               [graph.style.line()])

g.finish()
    
fill_colour = color.gray(.8)
area1 = g.area_between(g.ygridpath(1), shown[1].path, 1, 3)
area2 = g.area_between(hidden[0].path, hidden[1].path, 3, 44)
g.fill(area1, [fill_colour])
g.fill(area2, [fill_colour])
g.move_to_back(2)

g.writePDFfile('errorarea')
g.writeEPSfile('errorarea')

from pyx import *
from bg_graphxy import bg_graphxy

a, b = 2, 9 # integral area

p = graph.axis.painter.regular(basepathattrs=[deco.earrow.normal],
                               titlepos=0.98, titledirection=None)
ticks = [graph.axis.tick.tick(a, label="$a$"),
         graph.axis.tick.tick(b, label="$b$")]
g = bg_graphxy(width=8, x2=None, y2=None,
               x=graph.axis.linear(title="$x$", min=0, max=10,
                                   manualticks=ticks,
                                   parter=None, painter=p),
               y=graph.axis.linear(title="$y$", parter=None, painter=p))
d = g.plot(graph.data.function("y(x)=(x-3)*(x-5)*(x-7)"))
g.finish()

area = g.area_between(g.xbasepath(), d.path, a, b)
area[-1].close()
g.stroke(area, [deco.filled([color.gray(0.8)])])
g.text(g.pos(0.5 * (a + b), 0)[0], 1,
       r"\int_a^b f(x){\rm d}x", [text.halign.center, text.mathmode])

g.writeEPSfile("integral2")
g.writePDFfile("integral2")

from pyx import *
from bg_graphxy import bg_graphxy

g = bg_graphxy(width=10,
               x=graph.axis.linear(min=-1.0, max=1.0),
               y=graph.axis.linear(min=-1.3, max=1.3))

pihoriz = g.plot(graph.data.function("y(x)=0.5*x", points=2),
                [graph.style.line(None)]) # hidden
pifline = g.plot(graph.data.function("y(x)=sin(1.0/(x**2+0.02122))", points=1000))

# graph must be finished before we can access the paths
g.finish()

# fill area below horizontal with gray, and area above function with white
area_below_horiz = g.area_between(g.xbasepath(), pihoriz.path)
area_above_fline = g.area_between(pihoriz.path, pifline.path)
g.fill(area_below_horiz, [color.gray(0.6)])
g.fill(area_above_fline, [color.gray(1.0)])
g.move_to_back(2)

g.writeEPSfile("partialfill2")
g.writePDFfile("partialfill2")

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
PyX-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/pyx-user

Reply via email to