Follow-up posts
I added generic broadcasting support to numpy: numpysane: a more reasonable numpy
Up to this point, a major part of PDL::Graphics::Gnuplot that was not supported
in gnuplotlib
was proper broadcasting ("threading" in PDL-speak) support. What
is this? Suppose you have 3 1D vectors: x
, y
and y2
, and you want to plot
two curves: y
vs x
and y2
vs x
. In gnuplotlib
you can do
gp.plot( (x,y), (x,y2) )
But then you're repeating the x
. It would be nicer to consolidate that. You
can join y
and y2
into a 2D numpy array:
gp.plot( x, np.vstack(y,y2) )
Interpreting the arguments in this way is what broadcasting is, and I just
added support for this into gnuplotlib
.
It would appear that this is something that PDL does much better than numpy, in
general. While in PDL threading is a fundamental concept that's supported widely
across the whole system, in numpy broadcasting only really exists for
fundamental operations (addition, multiplication, etc). Thus numpy lacks an
equivalent of thread_define
, and I had to implement it myself. Note the
implementation isn't pretty, but it's just complicated by nature.
Something numpy does better than PDL is the wider range of types that can live in their arrays. I can thus put strings into arrays, and use broadcasting to plot stuff with different labels and styles. This clearly requires an example. Let's plot the Conchoids of de Sluze:
import numpy as np import gnuplotlib as gp theta = np.linspace(0, 2*np.pi, 1000) # dim=( 1000,) a = np.arange(-4,3)[:, np.newaxis] # dim=(7,1) gp.plot( theta, 1./np.cos(theta) + a*np.cos(theta), # broadcasted. dim=(7,1000) _with = 'lines', set = 'polar', square = True, yrange = [-5,5], legend = a.ravel() )
This is a plot in polar coordinates. I use broadcasting to generate a numpy
array that has all the r
values for all my curves in it. This array was
generated by a single command. And I plot it against the one array of
theta
values, again in a single command. I also use broadcasting to generate
labels. Generally these would be strings, and I can do that with numpy, but here
just printing the numerical value of the a
parameter is sufficient. The
result:
Another example:
import numpy as np import gnuplotlib as gp x,y = np.mgrid[-10:11, -10:11] z = np.sqrt(x*x + y*y) x = x[:, 2:12] z = z[:, 2:12] gp.plot((np.rollaxis( np.dstack((x,z)), 2,0), {'tuplesize': 3, 'with': np.array(('points palette pt 7','points ps variable pt 6'))}), square = 1)
Here the dimensions of x
and z
end up as (21,10). We stack them together
into an array of dimensions (2,21,10). Furthermore, the with
key option is
also an array, but with dimension (2,) and two strings in it, indicating how
each broadcast slice should be plotted. We thus plot x
as a matrix with a
varying color and z
as a matrix with a varying point size. The result:
Works OK, and this will be very useful.