Sunday 26 September 2010

Using macros

In the latest version of pyxplot, the concept of macro has been introduced. It works as it does in gnuplot, except that one doesn't have to set it beforehand. (Quite frankly, I have never understood why in gnuplot macros are disabled by default.) So, in the simplest case, we could just use a macro to abbreviate a couple of things, as here

mac = "with lines lw 2 lt 1"
plot sin(x) @mac
In this example, the value of the string "mac" is substituted literally on the command line, so, in effect, our plot is equivalent to
plot sin(x) with lines lw 2 lt 1
At this point, I should perhaps mention that this is not the only way of abbreviating plots. One can also use the set style command as follows:
set style 2 points pointtype 3
plot sin(x) with style 2

Now, back to the macros! Do you remember the data processing script from last time? We wanted to calculate the average of a function of a particular column. That construct worked as long as we didn't want to manipulate data across columns. You might also recall that that was possible only by tabulating the function values (i.e., writing them to a file), and then re-reading them for data processing. With macros, we can rather easily achieve what we want. Consider the following subroutine
subroutine mean(filename, func)
{
N data = 0
sum x = 0

foreach datum x in filename using @func
{
N data = N data + 1
sum x = sum x + x
}
if(N data > 0) { ; return sum x / N data ; }
}
We have a filename, and a macro. Now, the macro will be substituted literally on the command line, so we can just pass an arbitrary expression to our routine. That is, we can say
print mean(’data.dat’, "sin($1)*exp($2)")
and this will return the average of the product of the sine of the first, and the exponential of the second column in our data file.

But this is not everything! We can use the macro for defining arrays which we can manipulate, as long as the return value is a number. So, let us see, how this could be done! Let us take the following three subroutines!
subroutine a_vec(a, b, c)
{
        tmpstr = "%s%d"%(a,b)
        let @tmpstr = c
}

subroutine c_vec(a, b)
{
        tmpstr = "%s%d"%(a,b)
        let @tmpstr =
}

subroutine vec(a, b)
{
        tmpstr = "%s%d"%(a, b)
        return @tmpstr
}
The first one, when called as
call a_vec("a", 12, 123)
call a_vec("a", 13, 11) 
will create two variables, a12, and a13 with the values 123, and 11. The subroutine c_vec(a, b) will delete the bth element of vector a, and the subroutine vec(a, b) simply returns the bth element of vector a. So, if we call

print vec("a", 12)*vec("a", 13) 
1353 will be returned. You can easily see that a subroutine can now be created to fill up an array from a file, and that e.g., the scalar product of two vectors can be calculated in a straightforward way. This method works as long as the return type of a calculation is known to pyxplot. That is, while we can calculate the vector product of two vectors, we cannot return the value, simply because pyxplot wouldn't know what to return.

2 comments:

  1. Hi, I don't know if this is the right place to ask this but here it goes:
    I'm a bit experienced with GNUPlot but completely new to pyxplot. I'm trying to make a plot of a data file and the value that I wanted plotted is the difference between the value in the row i minus the value in row i-1. I know that using $ you can perform operation with values from different columns but I don't know how to do it for different rows.

    Thanks in advance! :) Bernardo.

    ReplyDelete
  2. Hello,

    I wonder if I could ask this question here. I have some particle trajectories in the form of their co-ordinates. I would like to plot them together with a transparent wall boundary so see what happens next to the wall. How can I make a transparent surface in gnuplot? I would appreciate any help in this regard.

    ReplyDelete