## Blop Tutorial

The basic layout of scripts

Blop can also run interactively: simply type at your shell prompt:
blop
and hit enter. Now the commands are expected from the terminal. These commands should be valid C++ commands.

Most often, if you produce plots for a document, these plots will need refinement, include some more data, etc. In this case it is much more efficient not to type all the commands producing your plots, but put these into a script file (referred to as script.C in the following). This file should be like a C++ program: it must contain a

main()
{
...
}

function (and possibly other functions as well). To let blop execute your script file (that is, the main function in your script file), type
blop script.C

The usual Hello World example

Like every tutorial I have seen up to now, this one also begins with the Hello World example. Create the file script.C to contain the code below, and then execute as shown above. Voila, 'Hello World' will be printed to your terminal

// --- script.C
main()
{
cout<<"Hello World\n";
}

Not bad, hmm? So blop also has the most popular feature of today's softwares. Great! But there are better tools for this purpose (I recommend, for example: echo "Hello World")
Plotting some data

So let's plot some data. Edit the file datafile to contain this:

1 1
2 4
3 9
4 16

To plot this data, start blop interactively, and write at the prompt:
plot("datafile",_1,_2).drawstyle(points).pointtype(fcircle).legend("my data");
A gv (ghostview) window will appear on your screen, showing the produced plot. This command is quite self-explanatory, except maybe the symbols _1 and _2. These indicate, that the first and second columns should be plotted from the given datafile. We will come back to this later. To get the possible drawstyles and pointtypes, say at your shell prompt:
blop -h drawstyle
blop -h pointtype

Let's try to do now the same thing from a script. Remember that you have to put your statements within the main(){...} function! Create the following script.C file, and execute it (blop script.C)

// ---- script.C
main()
{
plot("datafile",_1,_2).drawstyle(points).pointtype(fsquare).legend("my data");
}

Waiting for the plot to appear.... but nothing happens. There isn't any output file produced, either. This is because the plot(...) function only creates a plot in the current canvas (which is a kind of virtual drawing surface, which only exists in the computer's memory). The current canvas needs to be printed to a terminal, in order to really see it. In interactive mode this happens automatically after the execution of a function (the current canvas is printed into a postscript file (eps terminal), which is then automatically shown in a gv process) In script mode one needs to do it explicitely:
// ----- script.C
main()
{
plot(....);
eps::print("test.eps");
}

This additional function call prints the current canvas into an eps terminal (an .eps file, as specified in the argument). To see the available terminals, say at your shell prompt:
blop -h terminals

Instead of plotting the first two columns, you can specify arbitrarily complex combinations of columns to be plotted. For example is your datafile contains 3 columns, you can plot the sin^2 of the second + the cos^2 of the third column as a function of the first one by saying:

plot("datafile", _1, sin(_2)*sin(_2)+cos(_3)*cos(_3));

The plot(...) function automatically clears the current plot before producing a new one. If you want to plot several graphs on the same figure, use the mplot function instead ('m' means 'multi': this function does not clear the figure before plotting the graph)

Plotting functions

Now let's plot some functions. The following code plots a sinus curve in the range [0:10]

main()
{
plot(_1, sin(_1)).p1range(0,10);
eps::print("sinus.eps");
}

So we meet again this funny symbol _1. What is this actually? This is a blop function: a function-object, which can be evaluated with arguments. The _1 symbol is a predefined function object, which - when evaluated - simply returns its first arguments. The following code will print the number 3 to the terminal:
cerr<<_1(3,4,5)<

Let's come back to function plotting. This version of the
plot(...) function does not expect a filename as its first
argument, but only function-objects. When plotting functions, blop
scans the value of a parameter, and calls the provided functions with
this value as argument. In the above case the first  function (which
will serve as the x coordinate) is simply _1 (this
refers to the parameter itself), the second function (which will serve as the y
coordinate) is the sine of the parameter, thus, the resulting curve is
a sinus curve. (To make it clearer, blop plots functions in the sense
of gnuplot's parametric mechanism). The .p1range(0,10)
command specifies the range of the parameter (which in the current
case equals the x-range, since the x-coordinate is the parameter itself).
The following code for examples draws a circle:
plot(cos(_1),sin(_1)).p1range(0, 2*3.1415);

The object hierarchy in a figure

We can now plot datafiles and functions. Even several of them - but
only on the same figure. How can we create two graphs, shown
separately?

In order to address this question, let's see the containment
hierarchy in a plot. The following figure serves as an illustration:

The topmost element in the object hierarchy in your plot is a
canvas. This is actually your whole plot, and this is the
entity which can be printed to a terminal. This is a virtual
object existing only in the computer's memory, it does not get
realized until it is printed to a terminal.
The origin of its coordinate system is its lower left corner.
The following element is a pad, which can be contained in
a canvas or in another pad. This is used to define a
sub-space of its parent.
A frame is a rectangular area having four axes
(x1 and x2 are the horizontal, y1 and
y2 are the vertical axes). Its purpose is to contain graphs.
A frame can be contained in a canvas or
a padA frame has usually a legendbox - a rectangular
area containing samples from the graphs within the frame, with
explanation.

Here are some examples, how to create more complicated plots:

plot(_1,sin(_1));
plot(_1,sin(_1*_1));
In this example we created two pads explicitely, specifying their
extension. The pad::mknew(...) function does not only create
a new pad, but also makes this the current one (that is, any
subsequent plot(...) commands will plot into this pad). To
p.cd(1,1); // change to lower left
plot(_1,sin(_1));
p.cd(2,2); // change to upper right
plot(_1,sin(_1*_1));
This example creates a 2x2 multipad. The subpads of it can be
mframe &f = mframe::mknew(2,2); // create a 2x2 multiframe
f.cd(1,1); // change to lower left
plot(_1,sin(_1));
f.cd(2,2); // change to upper right
plot(_1,sin(_1*_1));
This example creates a multiframe. Here 2x2 frames, which share their
matching y or x axes. See blop -h mframe

Inclusion of the plots into your document

In the examples above your figure was printed to an .eps file.
However, in the introduction I promised that blop can do more than
producing a simple .eps file: it can produce "intelligent" outputs,
which then cleverly interact with your LaTeX document, into which  you
include them.

In order to produce such a file, print your canvas to a
blopeps terminal:
blopeps::print("filename.beps");

This file-type is blop's "native" filetype (or, terminal type). It is
a valid .eps file,
but it contains also some commands, which are executed by LaTeX, when
the file is included into a document (see below). Without these
commands being executed, the file looks awful, so if you open this
file for example with gv, and see something unexpected, don't
be disappointed.

If you simply include this file into your LaTeX document using for
example the \includegraphics macro, you will get the same
awful figure in your document, because this macro simply includes the
.eps source, but does not execute the LaTeX commands from this
file. To do both, blop provides the blopeps package
(by default under /usr/share/texmf/tex/latex/blopeps), and this
package provides the \blopeps{filename} macro.
Here is an excerpt from a LaTeX document:

\documentclass[a4paper]{article}
\usepackage{blopeps}
\begin{document}
.
.
\blopeps[optargs]{myfigure.beps}

The optional arguments of the \blopeps macro specifies the
width, height, linewidth, etc of the figure, in the
key=value format:

width=4cm, or pw=4cm
specify the width of the figure

height=4cm, or ph=4cm
specify the height of the figure

ps=1mm  specifies the pointsize  in the  figure (BLOP
has a built-in dimension, PS, which can be used in the user's
script  like  plot("datafile").pointsize(1.3*PS); The
actual  value  of  PS  can  be  specified  by  this  optional
argument)

lw=0.4pt
Specifies the actual value of the built-in dimension, LW,
which is the default width of lines.

Setting axis titles

Now you can plot functions and datapoints. To set the axis title, the
following functions are provided:

set::x1title("Lower horizontal axis");
set::y1title("Left vertical axis");
set::x2title("Upper horiz. axis");
set::y2title("Right vertical axis");

They set the title of the axes of the currently active frame.

Length arithmetic

BLOP provides a very easy way of calculating lengths. A special class,
length is provided for  this purpose, which can be multiplied
by a number, and  two lengths can be added. Here is  an example how to
calculate the linear combination of lengths:

length l = 3*MM + 4*EX;

In this  example MM and EX  are predefined variables
in  blop (the  first is  millimeter, the  second is  TeX's ex
dimen). The following classes of lengths are available:

Predefined lengths (units):

MM
millimeter
CM
centimeter
PT
One point
EX
TeX's ex dimen, which is the height of an 'x' in the
current font (of the document, which will include the figure).
EM
TeX's em dimen, which is the width of a "quad" in the
current font (in older terms, the width of an 'M' in the current
font)
PW
The width of the whole picture/plot
PH
The height of the whole picture/plot
LW
(linewidth) The value of this length is taken from the LaTeX
document (determined by the [lw=...] optional argument of
the \blopeps command). This length is the
default linewidth of all objects of the plots.
PS
(pointsize) The value of this length is taken from the LaTeX
document (determined by the [ps=...] optional argument of
the \blopeps command). This is the default size of points.

These lengths are constant, they can not be modified (for example
the LW=3*MM; command is invalid)
The horizontal and vertical sizes of texts:
height("some text")
width("some text")
These functions return a length, which is the correct size of the
given text in its final look. That is, these lengths are an
abstract quantity, which are a fontsize-independent tool for
object positioning. For example if you position a text label
("Label 1")
on your plot at position x1 in the horizontal direction,
and you position another label at x2 = x1 + width("Label
1"), then the second label will appear exactly at the end of
the first label, even if you change the fontsize of your document
(and therefore of these labels)
(\normalsize --> \Large, for example).

A valid piece of code is for example:
length a = 3*mm + 1.2*width("Velocity");
length b = 1.3*a + 4*pt;

The following might be  somewhat ununderstsandable, sorry. It would
improve in  the future. Skip  it maybe, and  try to begin  reading the
documentation...

In the  above example the  value of the length  b (calculated
from  the  other  length a)  is  fixed  at  the time  of  the
assignment;  that is,  if at  a later  point the  value of  the length
a is changed, it will have no effect on b. In many
cases you would like the  opposite behaviour. For example the size
(and therefore the left or right edge) of
a legendbox can  change, if you add more legends to  it. In fact, in
the current implementation its
dimensions  are  not  calculated  until  the last  moment,  when  the
legendbox is  printed to  a terminal. If  you would like  to position
something to  the right edge of  a legendbox, the  following piece of
length x = frame::current().legend()->right();

To solve this problem, the ! operator is provided to create a
reference  to  a length.  For  example if  you  want  that the  length
b  should be  1.3  times the  actual  value of  length
a, you should write
length a = 3*mm;
length b = 1.3 * !a;

Now, if at a later point you change the value of a, this will
have an effect on the value of b as well.

You can visualize the value of lengths using the <<
operator:
length a = 3*mm;
length b = 2*cm + 2*!a;
a = 5*pt;
cout<<b<<endl;

The var class

BLOP tries to simulate the nice feature of most scripting languages,
that variables can simultaneously treated as a numerical or string
value. The class var is provided for this purpose.
A variable of this type can be converted to a double or
string explicitely with the following member functions:

double var::dbl();
string var::str();

var a = "1.23";
double num_value = a.dbl();
string str_value = a.str();

When a variable of this type is manipulated as a string,
its numerical value is always
calculated as the number which is represented by that string, or zero,
if the string value does not represent a valid number (for example

var a = "some text 13";
cerr<<a.dbl()<<endl;      // this produces 0 on the output

The usual
arithmetic operator (+, -, /, *, +=, -=, *=, /=) treat them
as numerical values, while the & and
&= treat them as strings.
Examples

var a = "Hello ";
a &= "World";
a &= 4.5;

// at this point   a.dbl()   gives 0
//           and   a.str()   gives the string: "Hello World 4.5";

a += 1.3;

// at this point   a.dbl()   gives 1.3 (since a was 0 before)
//           and   a.str()   gives the string: "1.3"

a += "1.3";

// at this point   a.dbl()   gives 2.6
//           and   a.str()   gives the string: "2.6"

a &= "hello";

// at this point   a.str()   gives "2.6hello";
//           and   a.dbl()   gives 2.6, resulting from the
//                           conversion of the above string

For specifying the pointsize of a graph, (unless you have a good
reason for it) don't use 'absolute' units (that is, mm,
cm, etc). If you do not want to use points of different size,
simply do nothing in your script. If you want to use points of
different size, define these sizes as multiples of the predefined
PS unit. This allows you to change the size of the
points in all of your plots in your document with one single
command in your LaTeX document: saying
\blopps{3mm} at the beginning of your LaTeX document, the
PS unit in all subsequent plots included into this document
will be 3 mm (unless overwritten with the [ps=...] optional
argument of the \blopeps command).

The same arguments hold for linewidths. Define the linewidth of your
objects within your plot as the multiples of the LW unit, if
you want to produce lines of different widths.  The linewidth in a
single included figure can be specified by the lw=...
optional argument of the \blopeps macro, or the default
value for all figures can be set with the \bloplw macro, at
the beginning of your LaTeX document, for example \bloplw{1pt}.

Using C-functions

You can define any C-function in your script, which takes
var
arguments, and returns a var  as well, and you can plot these
functions, or use them to transform the content of
datafiles. Examples:

var f1(var a)
{
if(a < 4) return a;
if(a < 10) return sqrt(a);
return a*a;
}

var f2(var a,var b)
{
return a*cos(b) + sinh(a);
}

var f3(var a)
{
// filter out words beginning with 'fu'
if(a.str().find("fu") == 0) a = "censored";

// typeset it with bold font
a = "{\\bf " & a & "}";
return a;
}

// plot the function f1. If one single argument is provided
// for cfunc, it will be called on the first argument, so the
// next example is equivalent to plot(_1,cfunc(f1,_1)).
plot(_1,cfunc(f1)).legend("A C-function: f1");

// plot a datafile: f2 is called on the second and third columns,
// and is plotted as a function of the first column
mplot("datafile",_1,cfunc(f2,_2,_3)).drawstyle(points);

// plot data from the file: put labels (in the 4th column
// of the datafile), but filter them using f3
mplot("datafile",_1,_2,cfunc(f3,_4)).drawstyle(labels);

You can call built-in ANSI functions as well, for example
plot(_1,cfunc(sin)).legend("Sine");