Documentation / User's manual in C++ :
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.
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.
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.
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}`
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.
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
:
Having the function in a separated file
MyFunction.C
and load it through ROOT by callinggROOT->LoadMacro("MyFunction.C");
Having the function in a separated file
MyFunction.C
and include this file in the header ofanalysis.C
as#include "MyFunction.C"
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 throughLoadMacro
(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.
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:
The ROOT user guide (https://root.cern.ch/root/htmldoc/guides/users-guide/ROOTUsersGuideA4.pdf): useful and relatively complete gathering of information. It might be helpful to keep it locally as a reference.
The ROOT Class index (https://root.cern.ch/root/html/ClassIndex.html): Very complete description of all the classes and their methods. One can spent hour passing through these pages to discover what's doable using the various objects. It is even possible to mask/show inherited method for sake of simplicity.
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).