You are here

Working with macros

By far, the most productive way to use ROOT interactively is to keep open your favorite editor and save all commands into a ROOT macro file. We may test different commands during the interactive session, and save the "good" ones in the macro. This way, we can rerun the entire sequence of commands by means of the .x ROOT command (note that hereafter we are dropping the sequential numbering of the CINT prompt). If myMacro.cxx is the name of the file in which we save all commands:

root [] .x myMacro.cxx

The following example shows the most trivial form of a ROOT macro, and how to run it in "batch" mode (the dollar sign is the prompt of the Unix shell).

$ cat myMacro.cxx
void myMacro(){
  cout << "Trivial ROOT macro: Hello, World!" << endl;
  // it sounds like "Cogito, ergo sum" said by HAL9000 ...
}
$ root -q -b myMacro.cxx
  *******************************************
  *                                         *
  *        W E L C O M E  to  R O O T       *
  *                                         *
  *   Version   5.20/00      24 June 2008   *
  *                                         *
  *  You are welcome to visit our Web site  *
  *          http://root.cern.ch            *
  *                                         *
  *******************************************

ROOT 5.20/00 (trunk@24524, Jun 25 2008, 12:52:00 on linux)

CINT/ROOT C/C++ Interpreter version 5.16.29, Jan 08, 2008
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0]
Processing myMacro.cxx...
Trivial ROOT macro: Hello, World!

As you see, there is no need to include the iostream header file: it is already done by ROOT. The option -b means "batch mode", whereas -q makes ROOT exit after the macro execution (otherwise the user gets the CINT prompt, but without being able to see any graphical output).

It is also possible to pass arguments to the macro, as shown below (we omit the welcome message):

$ cat myMacro.cxx
int myMacro(int k=0){
 
  cout << "The input parameter was " << k << endl;
  return k;
 
}
 
$ root
root [] .x myMacro.cxx
The input parameter was 0
(int)0
root [] .x myMacro.cxx(5)
The input parameter was 5
(int)5
root [] int j=-100;
root [] .x myMacro.cxx(j)
The input parameter was -100
(int)(-100)
root [] .q

Here we used the ROOT command .x to execute the macro in different ways. Every time, the returned value and its type are displayed by ROOT. To obtain a similar result from the Unix shell, one has to issue a command like root -b -q "myMacro.cxx(-3)" (the parentheses have special meaning for the shell, hence we need to quote the macro call into a string).

We can also put the definition of more than one function in our macro, without the need to have one function with the same name as the file. However, in this case we can not use the file name as it were a function. Instead, we need first to load all functions, to be able to use them later on. This is done with the .L command:

root [] .!cat myMacro.cxx // .! to invoke a shell command
int myMacro(int k=0){
 
  cout << "The input parameter was " << k << endl;
  return k;
 
}
 
double anotherFunc(int j=0){
 
  double pp = 2*acos(-1);
  double x = 1.5*j + pp*myMacro(j);
  return x;
 
}
 
root [] .L myMacro.cxx
root [] anotherFunc(1);
The input parameter was 1
(double)7.78318530717958623e+00
root [] anotherFunc(2);
The input parameter was 2
(double)1.55663706143591725e+01
root [] anotherFunc();
The input parameter was 0
(double)0.00000000000000000e+00
root [] anotherFunc(-3);
The input parameter was -3
(double)(-2.33495559215387587e+01)