I just released gnuplotlib 0.32. It can do this:
import gnuplotlib as gp import numpy as np import numpysane as nps th = np.linspace(0, np.pi*2, 30) gp.plot( th, nps.cat( np.cos(th), np.sin(th)), _xrange = [0,2.*np.pi], _yrange = [-1,1])
import gnuplotlib as gp import numpy as np import numpysane as nps th = np.linspace(0, np.pi*2, 30) gp.plot( (th, np.cos(th), dict(title="cos")), (th, np.sin(th), dict(title="sin")), _xrange = [0,2.*np.pi], _yrange = [-1,1], multiplot='title "multiplot sin,cos" layout 2,1')
Long version
gnuplotlib
and numpysane
are becoming mature (i.e. I use them all the time,
have done that for a while, and they work very well), so I'm going to start
doing some proselytizing on this front. I want to do a talk in the near future,
and looking forward to that, I'm going to expand the docs, and I'm implementing
some long-envisioned-but-never-completed features. The first one of these is now
complete: multiplot support for gnuplotlib
.
Gnuplot multiplots are a way to create more than one plot in a single window (or hardcopy). These are a bit of a corner case, and I've been mostly getting by without ever using these, but sometimes they're really nice. Use cases:
- Plotting several time series (or anything that shares an axis) on top of one another. You could just put all your stuff on the same plot, but if you have many different datasets, and many different y-axis scales, this becomes messy quickly
- Getting around limitations in gnuplot. I recently discovered that gnuplot doesn't have a direct way to plot several stacked contours in 3D: more than one countour at a time is possible, but they'll all be drawn at the same z coordinate. One way to work around this is to use multiplots to plot each contour as a separate plot, and to tell gnuplot to put each subplot in the same location on the page
Making gnuplotlib
support this was conceptually simple, but violated some core
assumptions of the library, so lots of typing was required to add this feature.
In the end, it came out nicely, and didn't break any of the previous APIs. The
big update two-fold. First I needed to separate plot options into
- process options: one per gnuplot process. Applies to the whole big plot.
Stuff like
terminal
orhardcopy
orwait
- subplot options: one per subplot. With multiplots we'll have many of these
at the same time. These control each plot. Stuff like
xlabel
,xrange
,3d
, etc, etc
And then all the data passed to plot()
needed to be wrappable into yet-another
outer list. While with a single subplot you'd do this:
gp.plot( (x0, y0, curve_options0), (x1, y1, curve_options1), ..., subplot_options, process_options)
In multiplot mode, you'd pass a tuple of subplots instead of a tuple of curves,
where each suplot is more or less the whole argument set from each individual
plot()
command (minus the process options):
gp.plot( ( (x0, y0, curve_options0), (x1, y1, curve_options1), ... subplot_options0 ), ( (x2, y2, curve_options2), (x3, y3, curve_options3), ... subplot_options1 ), ..., process_options )
The gnuplotlib
README and the demo have some examples. Here're some
stacked contours:
import gnuplotlib as gp import numpy as np xx,yy = np.meshgrid(np.linspace(-5,5,100), np.linspace(-5,5,100)) zz0 = np.sin(xx) + yy*yy/8. zz1 = np.sin(xx) + yy*yy/10. zz2 = np.sin(xx) + yy*yy/12. commonset = ( 'origin 0,0', 'size 1,1', 'view 60,20,1,1', 'xrange [0:100]', 'yrange [0:100]', 'zrange [0:150]', 'contour base' ) gp.plot3d( (zz0, dict(_set = commonset + ('xyplane at 10',))), (zz1, dict(_set = commonset + ('xyplane at 80', 'border 15'), unset=('ztics',))), (zz2, dict(_set = commonset + ('xyplane at 150', 'border 15'), unset=('ztics',))), tuplesize=3, _with = np.array(('lines nosurface', 'labels boxed nosurface')), square=1, multiplot=True)
This is pretty new, so if you try it out, and something is unclear or broken, please complain.