English Français

Documentation / User's manual in C++ : PDF version

I.2. ROOT Environment

I.2. ROOT Environment

Uranie can be seen as a set of extension libraries for ROOT. As such, its traditional use is through the ROOT tools, in particular the root command which offers a C++ interpreter. This is presented in this section. In the next section, PyRoot will be presented.

I.2.1. Environment variables

Assuming you are in a ROOT enabled system, your shell environment probably defines ROOTSYS, PATH and LD_LIBRARY_PATH variables (unless they are installed in standard location). In order to use Uranie, assuming it is not installed in standard or ROOT location, the environment variable LD_LIBRARY_PATH needs to be completed and must contain the sub directory lib of the Uranie installation.

To achieve this, one can set the environment variable URANIESYS to Uranie's installation directory. Then, depending on the shell family used, the variable LD_LIBRARY_PATH can be updated as follows:

Uranie may need some external libraries that must be reachable via the LD_LIBRARY_PATH. You can adapt the former script to take it into account. Uranie installation procedure provides a configuration script that tries to create a safe environment.

I.2.2. ROOT interpreter and runtime compiler

Uranie can be used through the C++ interpreter of ROOT, either using the command line, or in batch mode, the successive commands being stored in a file called a ROOT macro .

To run the macro "MyMacro.C" from a shell prompt, use the command:

root -l MyMacro.C

The -l option prevents from launching the ROOT login window. Other options that may be useful are:

  • -q: quit ROOT interpreter when the script is run.

  • -b: run in batch mode (without DISPLAY)

These options are typically used when your job needs to be distributed.

To execute a Macro from the ROOT prompt, use the command:

.x MyMacro.C

ROOT interpreter offers some facilities for macro writing. In particular, it takes care of loading the needed libraries, and does not need the #include directives.

WARNING WITH ROOT6: The new versions of ROOT (from ROOT 6.0) is now using Cling the interpreter that does also a compilation on the fly thanks to LLVM and Clang. It is now much more compliant with the C++ syntax that previous version, allowing only few simplifications (some namespace loaded and include lines brought).

Another way to run a macro in a compile way is to append one or two "+" at the end of the script.

root -l MyMacro.C+

A "+" compiles the macro if the source changes, while "++" forces a recompilation. From ROOT 6, this method does not go faster that the "interpreted" one. The only difference remaining now is to produce easily a library (.so) file.

This runtime compiler still deals with libraries auto-load, but needs the #include directives. ROOT looks for include files in standard location and in the $ROOTSYS/include directory. If Uranie is installed elsewhere, you have to specify where to find its include files.

One way to do so is to use the .rootrc file. Here is an example:

It defines a list of C++ compiler options that are added at compile time: -I adds an include path; -D defines a CPP macro. This CPP macro can be used to write a single source code for both interpreted or compiled runs, hiding or showing part of source lines (#include declarations for example).

Another way is to use the rootlogon.C file. If this file is available in the active directory, it will be systematically loaded by ROOT before the application is launched. A more thorough discussion on this file can be found in Section I.2.4.

This allows both the interpreter and the compiler to find the needed files.

One important advantage of runtime compilation is that error messages are more easily understandable.

I.2.3. Standard compilation

For C++ enthusiasts, it is possible to use ROOT (and subsequently Uranie) as a set of libraries, and to compile an executable. In this case, you have to take care of linked libraries. In order to help the user, ROOT provides a macro that give many of the needed flag to perform the compilation, both to give the path to the headers and the path to the libraries.

g++ -o OutputName TheFileName.C  `root-config --cflags --libs`

For this example:

  • OutputName: the name of the resulting executable

  • TheFileName.C: the C++ file containing the code

  • `root-config --cflags --libs`: this command provides all the necessary flags to compile most of the macros using ROOT.

This is a logic we acknowledge and try to follow as well for Uranie: if one wants to compile an Uranie macro, one can use two flags.

  • URANIECPPFLAG: it defines all the include path needed and add on top the ones from ROOT;

  • URANIELDFLAG: it defines the linking option and path to library and add on top the ones from ROOT;

With this, an example of standalone compilation for a given macro UranieMacro.C will be:

g++ -o OutputExecutable UranieMacro.C  `echo ${URANIECPPFLAG} ${URANIELDFLAG}`

I.2.4. Uranie namespace

As for the vast majority of ROOT's classes, Uranie's classes started with a capital T (for instance "TFoo.h", if a class would be called "Foo"). Most of them inherit from TNamed, a generic class of ROOT which offers method for name and title bookkeeping. This is an important feature of the way ROOT-files are written (the name being the tag used to write or read any object and to handle them in memory). These classes belong to a specific namespace, in order to prevent any mixing between ROOT and Uranie (even though in practice, the name of the new classes implemented in Uranie is checked not to exist in ROOT for obvious safety and clarity reasons). Uranie defines many namespaces dedicated to the different module already introduced in Section I.1.1.

  • URANIE::DataServer ; the namespace associated with the DataServer library

  • URANIE::Launcher ; the namespace associated with the Launcher library

  • URANIE::Sampler ; the namespace associated with the Sampler library

  • URANIE::Optimizer ; the namespace associated with the Optimizer library

  • URANIE::Modeler ; the namespace associated with the Modeler library

  • URANIE::Sensitivity ; the namespace associated with the Sensitivity library

  • URANIE::Relauncher ; the namespace associated with the Relauncher library

  • URANIE::MpiRelauncher ; the namespace associated with the Relauncher library once used with MPI

  • URANIE::Calibration ; the namespace associated with the Calibration library

  • URANIE::MetaModelOptim ; the namespace associated with the MetaModelOptim library

  • URANIE::Reoptimizer ; the namespace associated with the Reoptimizer library

  • URANIE::UncertModeler ; the namespace associated with the UncertModeler library

  • URANIE::Reliability ; the namespace associated with the Reliability library

You can use the full qualified name to access to Uranie classes or use the using namespace directives to use the short name.

Another way to use the short name is to use again the rootlogon.C macro. If done so, all macros could access Uranie classes via the short name implicitly. Here is an example of rootlogon.C file:

using namespace URANIE::DataServer;
using namespace URANIE::Launcher;
using namespace URANIE::Sampler;
using namespace URANIE::Optimizer;
using namespace URANIE::Modeler;
using namespace URANIE::UncertModeler;
using namespace URANIE::Sensitivity;
using namespace URANIE::Relauncher;
using namespace URANIE::Reoptimizer;
using namespace URANIE::Calibration;
using namespace URANIE::Reliability;
// using namespace URANIE::XMLProblem;
// using namespace URANIE::MpiRelauncher;

void rootlogon()
{

    gStyle->SetPalette(1);
    gStyle->SetOptDate(21);

    //General graphical style
    // Default colors
    int white = 0;
    int color = 30;

    //Legend
    gStyle->SetLegendBorderSize(0);
    gStyle->SetFillStyle(0);

    // Pads
    gStyle->SetPadColor(white);
    gStyle->SetTitleFillColor(white);
    gStyle->SetStatColor(white);

}

/* ==================== Hint ====================
   
   Might be practical to store this in a convenient place (for instance
   your home directory) and to create an alias to make sure that you use
   only one rootlogon file independently of where you are.
  
   example : alias root="root -l ${HOME}/rootlogon.C"
   
   Many style issue can be set once and for all here.

   Warnings : 
    => The name of the main function (in between the void and the () part) 
    has to be the same as the name of the file (without extension).
    => If you intend to change this file name and make it a hidden file (let's 
    say  ${HOME}/.toto.C, the name of the main function would have to start with 
    an underscore, so here it would be "void _toto()".
*/

The most generic solution to simply don't have to bother with namespaces while possibly tuning root graphical options to ones taste is to centralise this file and make it our own. By putting it somewhere central (for instance as a hidden file in your home folder, something like ~/.rootlogon.C) it is possible to make an alias that could have two purposes:

With this kind of alias, one can have two interesting by-products: on the one hand, there will be no splash screen anymore (resulting from the "-l" option) while on the other hand, all the Uranie namespaces will be loaded along with your own graphical preferences, if you have any.

I.2.5. Important modifications going from ROOT v5 to ROOT v6

This part summarises the important modifications that are brought when changing ROOT versions. This affects some of the Uranie macros and if you've used Uranie before version 4.X, this part can be useful to understand the modifications that will mainly affect the constructor of some Uranie's objects.

The main subject is the way to handle function. As an example, we will considerer the "very" simple function that with two inputs returns the sum of these two values (c.f. the Addition function below).

void Addition(double *x, double *y)
{
    y[0] = x[0] + x[1] ;
}

In C++, within the Uranie framework, there are three ways to use this function in a macro, that would be called analysis.C:

  1. Having the function in a separated file MyFunction.C and load it through ROOT by calling

    gROOT->LoadMacro("MyFunction.C");
  2. Having the function in a separated file MyFunction.C and include this file in the header of analysis.C as

    #include "MyFunction.C"
  3. Having the function in the same file (analysis.C) before the main function.

This is common practice both for the 5 and 6 versions of ROOT.

From this, the way to handle this function is a little bit different going from one ROOT major-version (i.e. 5.X) to another one (i.e. 6.X).

ROOT 5.X:

Disregarding the chosen option to read the function (1, 2, or 3 discussed above) the interpreter (CInt for these versions of ROOT) is associating to the pointer of the function Addition (which is a pointer of the form (void *)(double *, double*) a name, which it uses as a tag by CInt. The name is in this case "Addition". For the 3 configuration defined up there, one can use the name and/or the pointer to access the function.

ROOT 6.X:

On the other hand, for these versions of ROOT, the interpreter is, as stated previously, a runtime compiler, so it behaves very much like expected from properly C++ compiled code. When calling the function thanks to its pointer (the (void *)(double *, double*) object) no information on a name is accessible. Compared to ROOT 5, there is no pointer to the function if it is loaded through LoadMacro (which is perfectly logic from a C++ point of view). The second and third access method can, on the other hand, use both the pointer and the name.

This obliges us to change several constructor that had been (over ?) simplified: in ROOT 5 versions, the compulsory information were often just a pointer to the TDataServer object and either the name of the function or a pointer to it. From this, if nothing else was specified, all current inputs in the TDataServer were used as inputs (this behaviour could be changed usually providing at third argument) and the output variables were named using the tag taken from CInt (this behaviour could be changed as well usually providing a fourth argument). Having no tag anymore from CInt when running ROOT 6, the (usually) optional third and fourth arguments become now compulsory.

I.2.6. References

The ROOT environment [Brun:1997pa] has already been under development for a long time now, it's documentation is very well advanced and is organised with different level of precision. One can indeed find many useful information in:

There are also many examples and macros that show how to handle the objects provided:

  • The Howto website: https://root.cern.ch/howtos

  • All the macro contained in the tutorial folder, installed once ROOT has been installed (check in the $ROOTSYS/tutorials folder).

/language/en