Adding new directory to FairRoot

  • Create a sub-directory in the FAIRROOT directory (MyDir)
  • Edit the file FAIRROOT/CMakeList.txt and add MyDir to the list of subdirectories

          add_subdirectory (base)
          add_subdirectory (parbase)
          add_subdirectory (geobase)
          add_subdirectory (MyDir)

  • In MyDir create a file CMakeList.txt this file should contain:

         .......(here you add the modules you use (include))

    include_directories( ${INCLUDE_DIRECTORIES})
         (any library path you need comes here)

    link_directories( ${LINK_DIRECTORIES})


    # fill list of header files from list of source files
    # by exchanging the file extension

    set(MyDir_LINKDEF MyDirLinkDef.h)


    set(MyDir_SRCS ${MyDir_SRCS} ${MyDir_DICTIONARY})

    add_library(MyDir SHARED ${MyDir_SRCS})
    target_link_libraries(Mydir ${ROOT_LIBRARIES})
    set_target_properties(MyDir PROPERTIES ${FAIRROOT_LIBRARY_PROPERTIES})

    ################ install ###################

Detector Geometry and Media

Detector geometry in FairRoot can be defined via:

  • ASCII files (Hades Geometry interface)
  • Root files (TGeoManager Object in ROOT file)
  • implimented directly in FairDetector::ConstructGeometry()

by default the geometry and media files are searched for in the $VMCWORKDIR/geometry directory, however one can define the variable GEOMPATH, which will force the framework to look for the geometry file specified in the macro first in this dir and then in the default geometry directory.

The filenames for the geometry definition and the media definition must have the suffix .geo and must contain a special keyword for every set:

  • media (for all materials needed in Geant for the standard geometry)
  • cave
  • Magnet
  • STS
  • ...

Geometry file format

Each file consists of a list of volumes. Each volume is characterized by its name and a list of parameters. Comments (marked with // at the beginning of a line) are allowed only at the beginning or the end of a volume.

A detector may consist of several modules sitting in a keepin volume and each module consists of several daughters, grand-daughters and so on. First the keepin volume will be read and afterwards each module with all volumes inside. The general construction (keepin volumes or not, number of modules) is for each detector hardwired in the program (see chapter Implemented sets). All inner parts of a module are only defined through the input file. You are free to change the names (with some restrictions), media, shapes, dimensions, and the tree itself, e.g. by inserting volumes, without recompiling the program. The only restriction is that the program will not create a daughter before it has created its mother, thus the mother has to show up in the list before its daughters.

Important: All volumes are created in Geant with the 'ONLY' flag!

The general input for a volume (except CAVE ) looks like:

  • name of the volume
  • inout flag (only for keepin volumes and modules, not for subvolumes of a module)
  • name of the mother-volume
  • Geant shape of the volume
  • name of the medium (= material)
  • points or parameters from technical drawings (depends on the shape)
  • position (x y z) of the coordinate system, in which the points are given, in the coordinate system of the mother
  • 3x3 rotational matrix of the coordinate system listed rowwise as a vector

For explanation:

Names of volumes: For each detector the names of the keepin-volumes and the modules are hardwired in the program (see chapter Implemented sets ). The inner parts of a module have names starting with a detector specific string. Each volume to be created in Geant has a name with at least 4 characters (upper case letters). Only the first 4 characters are used in Geant. All volumes of which several copies exist have names with 5 or more characters. These additionally characters are always digits ranging from 1 to the maximum number of volumes with the same 4-character Geant name. For example Tof 1 contains 8 identical cells T01S1 ... T01S8. The volume T01S is created only once via GSVOLU(...) but positioned 8 times via GSPOS(...). The names of the sensitive volumes must have a special structure which is defined for each detector in chapter Implemented sets.

Inout flag: All keepin volumes and mothervolumes of a detector may have an inout flag. If this inout flag is 1 the volume is created otherwise not. If the flag is not given in the input file the program (next line after name of volume) the program sets it automatically to 1. By setting this flag to 0 in the input file you can prevent for example the creation of a module in a special sector. This flag is not stored in the database. When reading from database the flag is always set to 1 by the program.

Name of the mother: Each volume is positioned in a mother. The name of the mother has 4 characters ( in upper case letters) plus eventually a 5th character if several copies of the mother exist. This 5th character has to be always 1. (In Geant only 4 characters are used, but 5 characters are necessary to find the mother in Oracle.)

Geant Shape: Each volume has a shape (4 characters in upper case letters). The shapes yet implemented in the program are BOX , PGON, PCON, TRAP, TRD1, TUBE, TUBS, CONE, CONS, SPHE, ELTU.

Medium: Each volume is filled with a medium given by the name of the medium. This medium must be defined in the medium file.

Points: Each volume has parameters describing the dimensions. The number of these parameters and their meaning depend on the shape of the volume. This is explained in chapter Shapes.

Coordinate system: Each volume has a coordinate system in which the parameters are given. Its position and orientation relative to the coordinate system of the mother volume is described by a translation vector T and a 3x3 rotation matrix R according to the equation x=R*x'+T where x is the vector in the coordinate system of the mother, and x' the vector in the coordinate system of the daughter. The matrix R is listed rowwise as a vector with 9 components. Each shape has its own intrinsic orientation which is defined similar to the Geant definition except for TRAP and TRD1 (see chapter Shapes). Important: The rotation matrix should be given with a precision of 10**-6. Otherwise you would get a lot of warnings from Geant that the coordinate system is not orthogonal. As long as all volumes in a module are not rotated you may use the coordinate system of the module as the base coordinate system in which all points are given. More information about the coordinate transformations you can find in the document Hades Geometry and Database of Michael Dahlinger.

Important: Volumes of which several copies exist have a special input structure: For the first volume all information above is read. The input for the other copies looks like:

  • name of the volume
  • inout flag if is the volume is a keepin volume or a module (may be missing)
  • name of the mother
  • translation vector of the coordinate transformation
  • rotation matrix of the coordinate transformation

The other information is not necessary because it has to be identical.


A variable number of 'points' (one in each line of the input file), each having a maximum of 3 values, can be stored in the program. Apart from the shapes with 8 corners (BOX , TRAP, TRD1) the parameter are at least very similar to the ones in Geant. Except for a TRAP and a TRD1 the intrinsic coordinate systems are defined as in Geant.

This shapes has 8 corners described by the x, y, z coordinates.

This shapes has 8 corners described by the x, y, z coordinates. The corners are counted clockwise starting at the lower left corner of the bottom plane. The intrinsic coordinate system of a TRAP is different from the one in Geant. The y-axis points from the smaller side in x-direction to the larger one. A TRAP not rotated in a Box has the same intrinsic coordinate system as the BOX. In Geant the y- and x-axis point in the opposite directions.

This shapes has 8 corners described by the x, y, z coordinates. The intrinsic coordinate system of a TRD1 is the same as for a TRAP. That's different from the definition in Geant.

This shape has a variable number of 'points'.

  • point 0: NZ number of planes perpendicular to the z-axis where the section is given
  • point 1: azimuthal angle PHI1 at which the volume begins
    opening angle DPHI of the volume
    number NPDV of sides of the cross section between the phi limits
  • point 2ff:
    • z coordinate Z of the section
    • inner radius RMIN at position z
    • outer radius RMAX at position z


This shape has a variable number of 'points'.

  • point 0: NZ number of planes perpendicular to the z-axis where the section is given
  • point 1: azimuthal angle PHI1 at which the volume begins
    opening angle DPHI of the volume
  • point 2ff:
    • z coordinate Z of the section
    • inner radius RMIN at position z
    • outer radius RMAX at position z

This shape has 3 'points' with 2 parameters each.

  • Point 0: inner radius RMIN of the shell
    outer radius RMAX of the shell
  • point1: starting polar angle THE1 of the shell
    ending polar angle THE2 of the shell
  • point 2: starting azimuthal angle PHI1 of the shell
    ending azimuthal angle PHI2 of the shell

This shape has 3 'points'.

  • point 0: x, y, z coordinate of the center of the circle at the beginning of the tube
  • point 1: inner radius RMIN of the tube
    outer radius RMAX of the tube
  • point 2: x, y, z coordinate of the center of the circle at the end of the tube


This shape has 4 'points'.

  • point 0: x, y, z coordinate of the center of the circle at the beginning of the tubs
  • point 1: inner radius RMIN of the tubs
    outer radius RMAX of the tubs
  • point 2: x, y, z coordinate of the center of the circle at the end of the tubs
  • point 3: starting angle PHI1 of the segment
    ending angle PHI2 of the segment


This shape has 4 'points'.

  • point 0: x, y, z coordinate of the center of the circle at the beginning of the cone
  • point 1: inner radius RMN1 at the beginning of the cone
    outer radius RMX1at the beginning of the cone
  • point 2: x, y, z coordinate of the center of the circle at the end of the cone
  • point 3: inner radius RMN2 at the end of the cone
    outer radius RMX2 at the end of the cone


This shape has 5 'points'.

  • Point 0: x, y, z coordinate of the center of the circle at the beginning of the cons
  • point 1: inner radius RMN1 at the beginning of the cons
    outer radius RMX1 at the beginning of the cons
  • point 2: x, y, z coordinate of the center of the circle at the end of the cons
  • point 3: inner radius RMN2 at the end of the cons
    outer radius RMX2 at the end of the cons
  • point 4: starting angle PHI1 of the segment
    ending angle PHI2 of the segment


This shape has 3 'points'.

  • point 0: x, y, z coordinate of the center of the ellipsoid at the beginning of the eltu
  • point 1: semi-axis P1 along x
    semi-axis P2 along y
  • point 2: x, y, z coordinate of the center of the ellipsoid at the end of the eltu

Warning: A TUBE, TUBS, CONE, ELTU can not be rotated by different x- and y-values of the starting and ending circles. They have to be identical. A rotation can only be described by a rotation matrix.


This shape has 5 'points'. (not available in native Geant3!!)

  • point 0: R - axial radius
  • point 1: Rmin - inner radius
  • point 2: Rmax - outer radius
  • point 3: Phi1 - starting phi
  • point 4: Dphi - phi extent

Media file

Each medium is characterized by a name. The names of the materials and the media are identical. Together with the name all parameters must be given which are needed for the Geant routines GSMATE, GSMIXT, GSTMED and GSCKOV.
There are no predefined materials!

The following parameters are needed:

  • int ncomp - number of components in the material (ncomp= 1 for a basic material and <1 or >1 for a mixture
    If ncomp > 0 the array wm contains the proportion by weight of each material in the mixture.
    If ncomp < 0 the array wm contains the proportion by number of atoms of each kind.
    For more detailed information see NLMAT in Geant3 routine GSMIXT
  • float aw[ncomp] - atomic weights A for the components
  • float an[ncomp] - atomic numbers Z for the components
  • float dens - density DENS in g cm(**-3)
  • float wm[ncomp] - weights WMAT of each component in a mixture (only for a mixture)
  • int sensflag - sensitivity flag ISVOL
  • int fldflag - fieldflag IFIELD
  • float fld - maximum field value FIELDM in kilogauss
  • float epsil - boundary crossing precision EPSIL
  • int npckov - number of values used to define the optical properties of the medium.
    The variable npckov is 0 for all media except some special media used for the Rich where the tracking of the Cerenkov photons is necessary. These media have additinal parameters
    • float ppckov[npckov] - photon momentum in eV
    • float absco[npckov] - absorption length in case of dielectric and of absorption probabilities in case of a metal
    • float effic[npckov] - detection efficiency
    • float rindex[npckov] - refraction index for a dielectric, rindex[0]=0 for a metal
      Remark: In the present program version a mixture may contain a maximum of 5 components. If this is not sufficient one has to change MAXCOMP in hgeomedium.h.

The following parameters are normally not read. The default values are -1 and the real values are automatically calculated by Geant. If you want to set these values by yourself, you must type the keyword AUTONULL in your media file. After this keyword all media must contain these additional 4 parameters before the Cerenkov (int npckov).

  • float madfld - maximum angular deviation TMAXFD due to field
  • float maxstep - maximum step permitted STEMAX
  • float maxde - maximum fractional energy loss DEEMAX
  • float minstep - minimum value for step STMIN

Comments can be placed before a medium in a new line starting with //

Example for a basic material

ALUMINIUM 1 26.98 13 2.7
0 0 0 0.0001
corresponds to :
name ncomp aw an dens
sensflag fldflag fld epsil

Example for a mixture where the content of each material in the mixture is given as proportion by weight

air 3 14.01 16. 39.95. 7. 8. 18. 1.205e-3 .755 .231 .014
0 1 3. .001
corresponds to:
name ncomp aw(1) aw(2) aw(3) an(1) an(2) an(3) dens wm(1) wm(2) wm(3)
sensflag fldflag fld epsil

Example for a mixture where the content of each material in the mixture is given as number of atoms of each kind

C4F10 -2 12.01 19. 6. 9. 7.35485e-3 4. 10.
0 1 3. .001
corresponds to:
name ncomp aw(1) aw(2) an(1) an(2) dens wm(1) wm(2)
sensflag fldflag fld epsil


RICHPad -2 12.01 1.00797 6. 1. 0.717e-3 1 4
1 1 3. .001
20 0.5 0.001 .00001
5.636 40000 1.0 1.0
7.750 2280 1.0 1.0
9.540 0.0 1.0 1.0
corresponds to
name ncomp aw(1) aw(2) an(1) an(2) dens wm(1) wm(2)
sensflag fldflag fld epsil
madlfd maxstep maxde minstep
ppckov[0] absco[0] effic[0] rindex[0]
ppckov[1] absco[1] effic[1] rindex[1]
ppckov[2] absco[2] effic[2] rindex[2]


The Parameter classes contain and manage all the numerical information needed to process the data (parameter). In order to analyse the simulated data, several numerical parameters are needed, as for example, calibration/digitization parameters or geometry positions of detectors. One common characteristic to most of these parameters is that they will go through several different versions corresponding, for example, to changes in the detectors definition or any other condition. This makes necessary to have a parameter repository with a well-defined versioning system. The runtime database (realized through the FairRuntimeDb class) is such a repository. Different inputs are supported : ASCII format , ROOT binary format and Oracle Database input.

  • Parameters are connected to a runId
  • FairBaseParSet: used to store relevant info from a simulation, reconstruction or analysis run:
  • FairDetGeoPar geometry parameters
    Stored for each detectors in FairDetector::ConstructGeometry()
  • Runtime database

    The runtime database is not a database in the classical sense. Instead, it is a parameter manager. It knows the I/Os defined by the user in the macro and all parameter containers needed for the actual analysis. It manages the automatic initialization and saving to an output and contains, after all initialization and saving is done, a complete list of runs and related parameter input and output versions.
    It is represented by the class FairRuntimeDb and instantiated in the macro.
    It holds two lists: the list of parameter containers, and the list of runs and related parameter versions. The containers can be initialized automatically from one or two inputs, and written out to one output. Possible inputs/output are

    • ROOT file
    • ascii file
    • Data Base (under construction)

    If a container can not or only partly be initialized from the first input, the missing information is taken automatically from the second input. Any combination of inputs is possible. In case of a ROOT file, the first input and the output might be identical.

    Parameter containers

    The parameters are stored in parameter containers which are accessible in the runtime database via their names. To avoid unnecessary initialization and storage, the design of these containers should consider the following aspects:

    • The containers should not hold parameters which are fixed, together with parameters which change very often (maybe from run to run).
    • Parameters needed by several tasks should be stored separately from the parameters used only by one task.
    • To guarantee data consistency, the reading of redundant information into two different containers is not allowed. Only one container should be initialized via reading, the other one (or the redundant part) by copying. (Otherwise only Data Base would guarantee data consistency.)

    All container classes are derived from a common base class FairParSet.They are instantiated in the program in the SetParTask() functions of the tasks (not in the constructors!) and added to the list of containers in the runtime database. However, it is also possible to create a container explicitely in a macro, to initialize it and to add it to the list. This feature can be used, when a container should be initialized from a special input and not automatically from one of the inputs defined in the runtime database.
    Parameters used privately in a task and calculated completely from other parameters should not be added to the list of parameter containers in the runtime database. Instead, their init() function should be called explicitly in the reinit() function of the task (called automatically after the initialization of all containers for each run).
    Each container has overloaded init() and write() functions for the parameter I/O, functions to support the version management, to clear the data and to print information.

    Parameter containers class implimentation example


    #include "FairContFact.h"
    class FairContainer;
    class FairTutorialDetContFact : public FairContFact
        void setAllContainers();
        ~FairTutorialDetContFact() {}
        FairParSet* createContainer(FairContainer*);
        ClassDef( FairTutorialDetContFact,0) // Factory for all MyDet parameter containers


    #include "FairTutorialDetContFact.h"
    #include "FairTutorialDetGeoPar.h"
    #include "FairRuntimeDb.h"
    #include <iostream>
    static FairTutorialDetContFact gFairTutorialDetContFact;
      /** Constructor (called when the library is loaded) */
      fTitle="Factory for parameter containers in libTutorial1";
    void FairTutorialDetContFact::setAllContainers()
      /** Creates the Container objects with all accepted
          contexts and adds them to
          the list of containers for the Tutorial1 library.
      FairContainer* p= new FairContainer("FairTutorialDetGeoPar",
                                          "FairTutorialDet Geometry Parameters",
    FairParSet* FairTutorialDetContFact::createContainer(FairContainer* c)
      /** Calls the constructor of the corresponding parameter container.
          For an actual context, which is not an empty string and not
          the default context
          of this container, the name is concatinated with the context.
      const char* name=c->GetName();
      FairParSet* p=NULL;
      if (strcmp(name,"FairTutorialDetGeoPar")==0) {
        p=new FairTutorialDetGeoPar(c->getConcatName().Data(),
      return p;

    Parameter class example


    // -------------------------------------------------------------------------
    // -----              FairTutorialDetDigiPar header file                  -----
    // -----                 Created 15/05/08  by F. Uhlig                 -----
    // -------------------------------------------------------------------------
    #include "FairParGenericSet.h"
    #include "TObject.h"
    #include "TObjArray.h"
    #include "TArrayF.h"
    #include "TArrayI.h"
    class FairParIo;
    class FairParamList;
    class FairTutorialDetDigiPar : public FairParGenericSet
        /** Standard constructor **/
        FairTutorialDetDigiPar(const char* name    = "FairTutorialDetDigiPar",
                               const char* title   = "Tutorial Det digi parameters",
                               const char* context = "Default");
        /** Destructor **/
        virtual ~FairTutorialDetDigiPar();
        /** Initialisation from input device**/
        //virtual Bool_t init(FairParIo* input);
        /** Output to file **/
        //  virtual Int_t write(FairParIo* output);
        //  virtual void print();
        virtual void printparams();
        /** Reset all parameters **/
        virtual void clear();
        void putParams(FairParamList*);
        Bool_t getParams(FairParamList*);
        TArrayF* ftutdetdigipar;  //
        TArrayI ftutdetdigiparsector; //
        Int_t ftutdetdigiparstation; //
        FairTutorialDetDigiPar(const FairTutorialDetDigiPar&);
        FairTutorialDetDigiPar& operator=(const FairTutorialDetDigiPar&);


    // -------------------------------------------------------------------------
    // -----                FairTutorialDetDigiPar source file              -----
    // -----                  Created 05/06/08  by F. Uhlig                -----
    // -------------------------------------------------------------------------
    #include "FairTutorialDetDigiPar.h"
    #include "FairParamList.h"
    #include "FairDetParIo.h"
    #include "FairParIo.h"
    #include "TString.h"
    #include "TMath.h"
    #include <iostream>
    using std::cout;
    using std::endl;
    // -----   Standard constructor   ------------------------------------------
    FairTutorialDetDigiPar::FairTutorialDetDigiPar(const char* name,
        const char* title,
        const char* context)
      : FairParGenericSet(name, title, context)
      ftutdetdigipar= new TArrayF(10);
      //ftutdetdigipar= new TArrayF(10);
    // -------------------------------------------------------------------------
    // -----   Destructor   ----------------------------------------------------
    // -------------------------------------------------------------------------
    // -----   Public method clear   -------------------------------------------
    void FairTutorialDetDigiPar::clear()
      status = kFALSE;
    // -------------------------------------------------------------------------
    // -----   Public method printParams ---------------------------------------
    void FairTutorialDetDigiPar::printparams()
      cout <<"Print"<<endl;
      cout << "ftutdetdigiparstation: " << ftutdetdigiparstation << endl;
      Int_t size =  ftutdetdigiparsector.GetSize();
      cout <<"size: " << size << endl;
      for ( Int_t i=0; i< size; i++) {
        cout << i <<" :" << ftutdetdigiparsector.GetAt(i) << endl;
      size =  ftutdetdigipar->GetSize();
      cout <<"size: " << size << endl;
      for ( Int_t i=0; i< size; i++) {
        cout << i <<" :" << ftutdetdigipar->GetAt(i) << endl;
    // -------------------------------------------------------------------------
    void FairTutorialDetDigiPar::putParams(FairParamList* l)
      //   print();
      cout << " I am in FairTutorialDetDigiPar::putParams " << endl;
      if (!l) { return; }
      l->add("FairTutorialDetDigiStations", ftutdetdigiparstation);
      l->add("FairTutorialDetDigiSectorsPerStation", ftutdetdigiparsector);
      Int_t count_sectors = 0;
      for ( Int_t i=0; i< ftutdetdigiparstation; i++) {
      Int_t array_size = (count_sectors * 10 + ftutdetdigiparstation * 3);
      cout << "Array Size: " << array_size << endl;
      /*   Float_t zwischen[array_size];
         for ( Int_t i=0; i< array_size; i++) {
           zwischen[i] = ftutdetdigipar.GetAt(i);
    Bool_t FairTutorialDetDigiPar::getParams(FairParamList* l)
      cout << " I am in FairTutorialDetDigiPar::getParams " << endl;
      if (!l) { return kFALSE; }
      if ( ! l->fill("FairTutorialDetDigiStations", &ftutdetdigiparstation) ) { return kFALSE; }
      if ( ! l->fill("FairTutorialDetDigiSectorsPerStation", &ftutdetdigiparsector) ) { return kFALSE; }
      Int_t count_sectors = 0;
      for ( Int_t i=0; i< ftutdetdigiparstation; i++) {
      cout << "Total number of sectors: " << count_sectors<<endl;
      Int_t array_size = (count_sectors * 10 + ftutdetdigiparstation * 3);
      cout << "Array Size: " << array_size << endl;
      //Float_t zwischen[array_size];
      if (!(l->fill("FairTutorialDetDigiPar",ftutdetdigipar))) {
        cout << "--W-- Could not initialize FairTutorialDetDigiPar"<< endl;
        return kFALSE;
      //ftutdetdigipar.Set(array_size, zwischen);
      return kTRUE;

    Reading Parameters using ROOT/ASCII files

    In the run macro, when initializing one has to add:

    FairRuntimeDb* rtdb=fRun->GetRuntimeDb();
    FairParRootFileIo* input=new FairParRootFileIo();

    create ASCII IO and open it:

    FairParAsciiFileIo* inputAscii = new FairParAsciiFileIo();

    create ROOT IO and open it:

    FairParRootFileIo* inputRoot=new FairParRootFileIo();

    set the different input to the runtime database


    setting the parameters in this order means, if a parameter was found in the first input (in this case ASCII) then it will be initialized from there, and even if it exist in the second input it will not be read again.

    Writting Parameters

    Writting Parameters to Root files:

    FairRuntimeDb* rtdb = fRun->GetRuntimeDb();
    Bool_t kParameterMerged = kTRUE;
    FairParRootFileIo* parOut = new FairParRootFileIo(kParameterMerged);

    Version management in the ROOT file

    In the ROOT file parameter containers are stored as objects. Every time an object is written it gets automatically a new version incrementing the former version by 1, starting with 1 in each newly created file. By default the Read() or Find() functions provided by ROOT read the object with the highest version. A retrieval of another version is possible by adding ";version number" to the name of the parameter container. The information 'which run corresponds to which version' of each parameter container must be stored in the ROOT file together with the data.

    Adding new detector

    To create a new detector you have to implement some classes which will describe your detector. The framework deliver you with the base classes which will do most of the work concerning the I/O and geometry construction, ..etc. The following will explain in step by step how to implement a detector MyDet in this framework:
    To describe a detector (e.g MyDet ) in FairRoot you have to implement:

    Creating the CMakefile


    # Create a library called "libTutorial1" which includes the source files given in
    # the array .
    # The extension is already found.  Any number of sources could be listed here.
    # Create a library called "libTutorial1" which includes the source files given in
    # the array .
    # The extension is already found.  Any number of sources could be listed here.
    include_directories( ${INCLUDE_DIRECTORIES})
    link_directories( ${LINK_DIRECTORIES})
    #Put here your sourcefiles
    Set(HEADERS )
    Set(LINKDEF Tutorial1LinkDef.h)
    Set(LIBRARY_NAME Tutorial1)
    Set(DEPENDENCIES MCStack Base)

    Detector MC Point class


    #include "FairMCPoint.h"
    #include "TObject.h"
    #include "TVector3.h"
    class FairTutorialDetPoint : public FairMCPoint
        /** Default constructor **/
        /** Constructor with arguments
         *@param trackID  Index of MCTrack
         *@param detID    Detector ID
         *@param pos      Ccoordinates at entrance to active volume [cm]
         *@param mom      Momentum of track at entrance [GeV]
         *@param tof      Time since event start [ns]
         *@param length   Track length since creation [cm]
         *@param eLoss    Energy deposit [GeV]
        FairTutorialDetPoint(Int_t trackID, Int_t detID, TVector3 pos, TVector3 mom,
                             Double_t tof, Double_t length, Double_t eLoss);
        /** Copy constructor **/
        //    FairTutorialDetPoint(const FairTutorialDetPoint& point) { *this = point; };
        /** Destructor **/
        virtual ~FairTutorialDetPoint();
        /** Output to screen **/
        virtual void Print(const Option_t* opt) const;

    Detector class

    A detector class should inherits from the FairDetector class, the header file will looks like:


    #include "FairDetector.h"
    class FairVolume;
    class TClonesArray;
    class FairTutorialDet: public FairDetector {
        /**  Name :  Detector Name
            Active: kTRUE for active detectors  (ProcessHits() will be called)
                    kFALSE for inactive detectors
        FairTutorialDet(const char * Name, Bool_t Active);
        /** default constructor    */
        /** destructor     */
        virtual ~FairTutorialDet();
        /** Initialization of the detector is done here    */
        virtual void   Initialize();
        /** this method is called for each step during dsimulation (see FairMCApplication::Stepping()) */
        virtual Bool_t ProcessHits( FairVolume *v=0);
        /** Registers the produced collections in FairRootManager.     */
        virtual void   Register();
        /** Gets the produced collections */
        virtual TClonesArray* GetCollection(Int_t iColl) const ;
        /** has to be called after each event to reset the containers        */
        virtual void   Reset();
        /** Create the detector geometry        */
        void ConstructGeometry();
        /** This method is an example of how to add your own point of type FairTutorialDetPoint to the clones array */
         FairTutorialDetPoint* FairTutorialDet::AddHit(Int_t trackID, Int_t detID, TVector3 pos,
                                   TVector3 mom, Double_t time, Double_t length,Double_t eLoss)
        /**	The following methods can be implemented if you need to
            make any optional action in your detector during the transport.
        /**Special cuts on media specific for this detector can be implemneted here*/
        virtual void   SetSpecialPhysicsCuts(){;}
        /** This method is called after proccessing an event*/
        virtual void   EndOfEvent(){;}
        /**This method is called after tracking of a primary particle is finished */
        virtual void   FinishPrimary(){;}
        /**This is called at the end of a run*/
        virtual void   FinishRun(){;}
        /**This method is called when primary track start*/
        virtual void   BeginPrimary(){;}
        /**called after a track is finished (stopped/vanished/absorbed)*/
        virtual void   PostTrack(){;}
        /**called before a new track start stepping*/
        virtual void   PreTrack(){;}
        /**called at the begining of an event*/
        virtual void   BeginEvent(){;}
         /** container for data points */
         TClonesArray  *fMyPointCollection;

    Changing default paths

    The framework assume some default paths for geometry, configuration files etc. this can be change by defining some enviromental variables:

      setting this variable, the framework will look for the detector geometry files in this path and then in the default input directory
      Configuration files are by default in the directory gconfig, exporting the variable CONFIG_DIR one can change the path of some or all configuration files

    Data analysis

    Description and HowTo on the experimental data analysis with FairRoot can be found here.

    Download and use VirtualBox image

    ---++ Prerequisites

    * A computer with Windows, Linux or Mac OSX and 20GB free disk space
    * VirtualBox
    * The archive containing the virtual machine
    * A Archive tool which can handle 7-zip files

    ---++ How to install VirtualBox

    VirtualBox is a general-purpose full virtualizer for x86 hardware which runs on most modern operating system (Windows, Linux, Mac OSX and Solaris). It allows to run multiple operating systems (inside multiple virtual machines) at the same time. So, for example, you can run Windows and Linux on your Mac, run Windows Server 2008 on your Linux server, run Linux on your Windows PC, and so on, all alongside your existing applications. You can install and run as many virtual machines as you like -- the only practical limits are disk space and memory.

    Please download the correct version for your operating system from the following web-page and follow the installation instructions. This should be straight forward. Please download from the same web-page the extension pack if you need for example USB support inside the virtual machine. This is normally recommended. After you have installed VirtualBox double click on the extension pack (or choose open with -> VirtualBox) which will start its installation.

    ---++ Get the virtual machine image

    The zipped archive with the virtual machine image can be downloaded with the link below. Please right click on the link and choose *"Save as"* which will start the download. Please be patient, because the total size of the file is 2.5 GB.


    Put the archive in the VirtualBox directory.

    ---++ Unpack the virtual machine image

    On Windows the tool !WinRar should be able to unpack the archive. If this doesn't work please get a dedicated tool from, install it on your computer and use it for unpacking. For Mac OSX you get such an unpacker from Installation and usage should be straight forward. For linux try to install p7zip using your package manager. If there is no such tool available for your linux distribution pleas download the sources from and compile it on your own.

    Use the unpacker to unpack the archive which will result in two files which can be found in the subdirectory *PandaRoot*. The first one _PandaRoot.vbox_ is a small XML-file with the definition of the virtual machine. The second file PandaRoot-disk1.vdi is the disk image with all the data.

    ---++ How to start the virtual machine

    On Windows and Mac OSX it is enough to double click on the file symbol of PandaRoot.vbox . This will start VirtualBox and show the new virtual machine in the GUI. Here one chooses the virtual machine *PandaRoot* and then click on the *Run* icon.
    To start the virtual machine on Linux first start VirtualBox and the choose *Machine* and then *Add* from the menu.
    In the GUI select PandaRoot.vbox , which will also open another GUI with the correct machine. Here you click the *Run* icon to boot the machine.

    ---++ How to use the virtual machine.

    After some time you should see the login screen. To login please enter the correct password, the user should be already correct. The username is *fairroot* and the corresponding password is *FairRoot* . This will bring you to the Desktop. Since this is an Ubuntu system, one cannot switch to user root but one has to use the sudo command.

    The =pandaroot= release July12 and the needed external packages are already installed on the virtual system. You find =pandaroot= in =/home/fairroot=; the binaries are in =/home/fairroot/pandaroot/build=.

    External Decayers

    There is two external decayers available in FairRoot:

    • Pythia6 (G3/G4)
      Use Pythia6 as external decayer

      In the simulation macro you need to call:


      And then in the DecayConfig.C you specify for which particles Pythia should be used as decayeer. See the comments in the DecayConfig.C file.

    • User 2(3) body decay (G3/G4)
      user can define the branching ratios and partial decay modes for two and three body particle decays.
      In the simulation macro you need to call:


      And then in the UserDecay.C macro you specify for which particles this decayer has to be used and the two/three particle phase space decay mode and branching ratios. (see the UserDecay.C file for an example)

    Getting started

    Before starting with FairRoot you have to install the external packages needed, please see

    1. Build Prerequisites
    2. Installing the external packages

    After that you go and install FairRoot

    3. Installing FairRoot

    Installing FairRoot you have all the base classes you need to do simulation and reconstruction and some small examples in:

    fairroot/example (if you install in the source directory).

    How to implement a simple detector using the old ASCII interface to describe the geometry (see Detector Geometry and Media for more details about this geometry interface)
    See also Adding new detector for a detailed description of the detector class implementation, MC point class and the CMakeLists.txt

    To run this tutorial:

    • After building FairRoot successfully go to the build directory and call the configuration script ( or config.csh according to our shell)
    • cd to the Tutorial1/macros directory
    • run the following command: root run_tutorial1.C (you can also load the macro into root and then run it)

    This will start a simulation session with Geant3 and create 10 events generated by a box generator, the input in the box generator can be chosen by the user, by default in this macro we use "pions" (see macro lines 20-22) for details.
    To choose Geant4 you just have to change TGeant3 to TGeant4 in line 8 of the macro, or of you are loading the macro to root before exciting it you just give TGeant4 as second argument to the run_tutorial1 call, i.e:

    root>.L run_tutorial1.C
    root>run_tutorial(10, "TGeant4")

    This example show you how to:

    • Simulate a simple detector (run_tutorial2.C)
    • Read the simulated data, and the digitization parameters from "parameters/tutdet.digi.par" and create digitized data (create_digis.C)
    • Read the digitized data for further reconstruction (read_digis.C)

    This example demonstrate

    • detector simulation
    • event by event digitization
    • time based digitization
    • Message Queue based reconstruction: The Message Queue based reconstruction demonstrates the usage of FairMQ.
      Any number of "sampler" processes (FairMQSampler, FairMQSamplerTask, TestDetectorDigiLoader) send the data generated in the digitization step to a number of "processor" processes which do the reconstruction with the data (FairMQProcessor, FairMQProcessorTask, FairTestDetectorMQRecoTask). After the reconstruction task, the processes send the output data to a number of "sink" processes, which write the data to disk (FairMQFileSink).
      All the communication between these processes is done via FairMQ and can be configured to run over network (tcp) or on a local machine with inter-process communication (ipc).
      Currently, the number of processes and their parameters are configured with bash scripts/command line parameters. The scripts are located in the macro directory, together with for more details on how to configure them.
    • Event display

    This example demonstrate:

    • using ROOT geometry as input for detector description, i.e: the geometry is created and saved to a ROOT file from a macro ( Create_Tutorial4_Geometry.C). The ROOT file is read by the detector classes during simulation

    Shows how to use FairDB interface to write and read parameter to a database system.
    Two type of parameter classes are implemented with

    • simple data members ( FairDbTutPar)
    • complex data members i.e ROOT object ( FairDbTutParBin)

    In both cases, corresponding macro to read and write as well as a script.
    To setup the database to be used ( are available from the macro directory.
    simple simulation of the Rutherford experiment, with event display.

    Simple example for Message based processing using FairRoot.

    MC propagation

    Each simulation stage should only contain information from the previous one to avoid using MC information in a simulation stage where it will not be available later on with real data from the experiment. Nevertheless in many cases the MC information is important and a way to get access to the MC information from each simulation stage is needed.

    The basis of the introduced MC propagation mechanism in FairRoot is that each stored data object contains the information which data was used to create it. For example each MC point knows from which MC track it was coming from or each reconstructed track knows which hit was used to create the track. Technically the information is stored in an array of FairLink objects. A FairLink is a pair of a branch ID, indicating from which data-branch the data is coming from, and an index, which indicates the position in the TCLonesArray of the data-branch. A FairLink uniquely identifies a data-object and allows the retrieving of the data-object from the root-file where it is stored in.

    Following the FairLinks allows to get access from each simulation stage back to each previous stage to extract (not only) the MC information.
    More information on how to use the FairLink data can be found here

    How to implement MC propagation

    IMPORTANT With SVN revision 9240 the implementation of MC propagation has changed! A FairLink consists now of a string and an integer. The string is the branch name, where the data is stored in. The integer is the position in the TClonesArray as usual. Internally the FairRootManager translates the branch name into a unique ID which is stored in the file.

    In addition the setting of links now checks if the data the link is pointing to is transient. If this is the case the link information of the previous stage is saved instead of the original link. In this way it is ensured that the chain of link is not interrupted by intermediated data which is not stored.

    1. Derive your data class from FairMultiLinkedData*
      • If your data class already derives from FairHit or FairMCPoint this is not necessary
      • Be careful Multiple inheritance from different classes causes problems in ROOT so better avoid it.
    2. Use one of the methods SetLink, SetLinks, AddLink or AddLinks
      • Use the methods SetLink/SetLinks, AddLink/AddLinks to save the FairLink to the previous data-object
      • SetLink(FairLink) overrides an existing link array with one FairLink
      • SetLinks(FairMultiLinkedData) overrides an existing array with an array of FairLinks
      • AddLink(FairLink) / AddLinks(FairMultiLinkedData) adds the given data at the end of the existing FairLink array.
    3. Compile / Check/ Upload
      • Compile your code
      • Run a simulation
      • Check if your data class contains a fLinks branch with entries for fType and fIndex
      • Upload your code to SVN
      • Thats it. You have successfully implemented MC propagation into your code.

    How to use MC Propagation

    If you want to use MC Propagation for your data classes you first have to follow the description on Howto implement MC Propagation . After this you have to initialize your new data classes in the InitBranches method of the two tasks: PndMCMatchCreatorTask and PndMCMatchLoaderTask. This steps have to be done once for each new data class.

    The base class which contains all the link informations is PndMCMatch. It is filled by the two Tasks: PndMCMatchCreatorTask and PndMCMatchLoaderTask

    PndMCMatchCreatorTask runs through all initialized branches and extracts the stored FairLinks into the PndMCMatch class. After this the link information is stored in an individual branch so that it can be accessed without touching the original data. If this task is called in addition with other simulation tasks, it should be called as the last one, otherwise it will not contain the link information of the tasks coming after it. If you do not want to store the link data in the same root file as your data you should call PndMCMatchCreatorTask in an individual macro with a new output file name. You can work with this new file without loading the data files.

    PndMCMatchLoaderTask reads in the links from a link root file or from a data file which contains a link branch. PndMCMatchLoaderTask is automatically called if you use the PndMCMatchCreatorTask.

    After you have loaded the link information you can use either the GetMCInfo or the GetMCInfoSingle method of PndMCMatch to access the wanted link information:

    PndMCResult GetMCInfo(TString start, TString stop) needs two parameters: the start branch from where you want to have your links and the stop branch where the links should point to. So if you want to know which MC track belongs to your reconstructed tracks start would be "PndTrack" and stop "MCTrack". The output is of type PndMCResult. Basically this is an array of FairLinks. The FairLinks are ordered in the same way as the start data. So if you want to know which MC tracks belong to your reconstructed track 2 you call GetEntry(2). Be careful: this can be more than one! So the output is a FairLink array which you can iterate by calling GetLink(index). These links come with a weight which tells you how much influence the link data had to your output. The weighting of links is quite complicated and will be covered in an own wiki page.

    PndMCEntry GetMCInfoSingle(FairLink aLink, TString stop)has the same functionality as GetMCInfo. The only difference is that you start with an individual FairLink to a specific data object and you get only the FairLinks for this object. Let us take the same example like before: reconstructed track 2 -> MC tracks. Then your code would look like GetMCInfoSingle(FairLink(kTrack, 2), kMCTrack);.



    void PndMCTestMomentumCompare::Exec(Option_t* opt)
       PndMCResult myResult = fMCMatch->GetMCInfo("PndTrack", "MCTrack");
       std::cout << myResult;
       for (int i = 0; i < myResult.GetNEntries(); i++){
          PndMCEntry myLinks = myResult.GetEntry(i);
          PndTrack* myTrack = (PndTrack*)fTrack->At(i);
          std::cout << "TrackMatch for Track " << i << std::endl;
          std::cout << "P: " << myTrack->GetParamFirst().GetSDMomentum().Mag() << std::endl;
          std::cout << "Belongs to: " << std::endl;
          for (int j = 0; j < myLinks.GetNLinks(); j++){
             if (myLinks.GetLink(j).GetType() == kMCTrack){
                std::cout << "MCTrack " << myLinks.GetLink(j).GetIndex() << std::endl;
                PndMCTrack* myMCTrack = (PndMCTrack*)fMCTrack->At(myLinks.GetLink(j).GetIndex());
                std::cout << "P: " << myMCTrack->GetMomentum().Mag() << " PID: " << myMCTrack->GetPdgCode() << std::endl;
                std::cout << "--------------------------------" << std::endl;
          std::cout << std::endl;

    PROOF in FairRoot

    PROOF in FairRoot

    The necessary changes to the FairRoot allowing usage of PROOF have been added on 08.03.2012.
    In order to run FairRunAna on the PROOF cluster, one should edit the macro file, and change:

    FairRunAna* fRun = new FairRunAna(); to FairRunAna* fRun = new FairRunAna("proof");

    The example macros that show the usage of PROOF are located in macro/global/.

    Create several input files with:

    karabowi@lxi047:pandaroot_trunk:~/pandaroot_trunk/trunk/macro/global$ date; root -l -q 'sim_BARREL_1000.C(0)' &> p0.dat; date ;root -l -q 'sim_BARREL_1000.C(1)' &> p1.dat; date; root -l -q 'sim_BARREL_1000.C(2)' &> p2.dat; date; root -l -q 'sim_BARREL_1000.C(3)' &> p3.dat; date; root -l -q 'sim_BARREL_1000.C(4)' &> p4.dat; date; root -l -q 'sim_BARREL_1000.C(5)' &> p5.dat; date; root -l -q 'sim_BARREL_1000.C(6)' &> p6.dat; date; root -l -q 'sim_BARREL_1000.C(7)' &> p7.dat; date; root -l -q 'sim_BARREL_1000.C(8)' &> p8.dat; date; root -l -q 'sim_BARREL_1000.C(9)' &> p9.dat; date;

    Analyze the files in PROOF:

    karabowi@lxi047:pandaroot_trunk:~/pandaroot_trunk/trunk/macro/global$ root -l -q 'tracks_BARREL_1000.C("proof",10);

    You may also analyze the files locally:

    karabowi@lxi047:pandaroot_trunk:~/pandaroot_trunk/trunk/macro/global$ root -l -q 'tracks_BARREL_1000.C("local",10);

    Running on PROOF
    The most important difference when running on PROOF is the dialog window that will appear after PROOF starts working. // I would like to have a picture here //.

    It shows the progress of the analysis in a graphic form.

    When you look at the screen printouts, you will notice that it differs from the one you are used to.

    The major differences include:

    • the welcome message of the PROOF:
      FairRunAna::RunOnProof(0,10000): running FairAnaSelector on proof server: "workers=3" with PAR file name = "$VMCWORKDIR/gconfig/libFairRoot.par".
      +++++++ T P R O O F +++++++++++++++++++++++++++++++++
      creating TProof* proof = TProof::Open("workers=3");
      +++ Starting PROOF-Lite with 3 workers +++
      Opening connections to workers: OK (3 workers)
      Setting up worker servers: OK (3 workers)
      PROOF set to parallel mode (3 workers)
      +++++++ C R E A T E D +++++++++++++++++++++++++++++++

      The messages comes from the FairRunAna::RunOnProof() and informs where and with what options the PROOF cluster
    • the list of the enabled PROOF ARchives:
      drwxr-x--- 3 karabowi had1 22 31. Okt 13:34 libFairRoot
      lrwxrwxrwx 1 karabowi had1 60 9. Mär 11:57 libFairRoot.par -> /misc/karabowi/pandaroot_trunk/trunk/gconfig/libFairRoot.par

      In short, from this libFairRoot.par the individual workers learn that after being created they should execute the gconfig/rootlogon.C which loads the necessary libraries.
    • some lines informing the user on the number of entries, input files, status of the analysis...
      FairRunAna::RunOnProof(): The chain seems to have 10000 entries.
      FairRunAna::RunOnProof(): There are 10 files in the chain.
      FairRunAna::RunOnProof(): Starting inChain->Process("FairAnaSelector","",10000,0)

      Info in <:setqueryrunning>: starting query: 1
      Info in <:setrunning>: nwrks: 3
      Error in <:tgspeedo::build>: speedo.gif not found
      -I- FairAnaSelector::Begin()
      Looking up for exact location of files: OK (10 files)
      Looking up for exact location of files: OK (10 files)
      Info in <:tpacketizeradaptive>: Setting max number of workers per node to 3
      Validating files: OK (10 files)
      Info in <:initstats>: fraction of remote files 1.000000
      -I- FairAnaSelector::Terminate(): fOutput->ls() still sending)
      OBJ: TSelectorList TSelectorList Special TList used in the TSelector : 0
      OBJ: TList MissingFiles Doubly linked list : 0
      OBJ: TStatus PROOF_Status : 0 at: 0x3c2bd30
      OBJ: TOutputListSelectorDataMap PROOF_TOutputListSelectorDataMap_object Converter from output list to TSelector data members : 0 at: 0x2e53450
      -I- FairAnaSelector::Terminate(): -------------
      Lite-0: all output objects have been merged
      FairRunAna::RunOnProof(): inChain->Process DONE

    • there is no normal std::output the user got used to, like initialization messages, the couts from your tasks. Since the analysis was executed on several external workers, the printouts from them on what they actually did is not printed on the screen. These printouts from the workers go to special log files, which are located in:


      To make it clearer, here is the location of my log files:

      karabowi@lxi047:pandaroot_trunk:~/pandaroot_trunk/trunk/macro/global$ ls ~/.proof/pandaroot_trunk-trunk-macro-global/session-lxi047-1331290627-14341/worker-0.*.log -l
      -rw-r----- 1 karabowi had1 439090 9. Mar 11:57 /misc/karabowi/.proof/pandaroot_trunk-trunk-macro-global/session-lxi047-1331290627-14341/worker-0.0.log
      -rw-r----- 1 karabowi had1 375985 9. Mar 11:57 /misc/karabowi/.proof/pandaroot_trunk-trunk-macro-global/session-lxi047-1331290627-14341/worker-0.1.log
      -rw-r----- 1 karabowi had1 440103 9. Mar 11:57 /misc/karabowi/.proof/pandaroot_trunk-trunk-macro-global/session-lxi047-1331290627-14341/worker-0.2.log

      The log files include all the printouts from the workers.

    Moreover there are more output files than you expect:
    karabowi@lxi047:pandaroot_trunk:~/pandaroot_trunk/trunk/macro/global$ ls -ltrh tracks_*.root
    -rw-r----- 1 karabowi had1 378 9. Mar 12:37 tracks_22Part_n10000.root
    -rw-r--r-- 1 karabowi had1 1009K 9. Mar 12:37 tracks_22Part_n10000_worker_0.0.root
    -rw-r--r-- 1 karabowi had1 1013K 9. Mar 12:37 tracks_22Part_n10000_worker_0.2.root
    -rw-r--r-- 1 karabowi had1 1,3M 9. Mar 12:37 tracks_22Part_n10000_worker_0.1.root

    The individual workers create the output files on their own, and the trees/files from different workers are not merged. There is also the file one would expected created, but it should
    be changed, so that this empty tracks_22Part_n10000.root is not created at all.

    Depending on the number of input files, number of workers and the time spent for analysis of one event, the PROOF Packetizer, responsible for sending events to workers, will behave differently, but in general:

    • if there are enough trees each worker will get a tree to analyze. Any worker that finishes analyzing his tree will get another tree to analyze if there are any left. This the scenario quoted above. Looking at the output files' sizes it is easy to deduce that the worker 1 was the quickest in analyzing the trees, and therefore the got 4 of the input trees, while workers 0 and 2 got only 3 trees.
    • if there are less trees than workers or if one event analysis takes a long time, event in any tree will be distributed among different workers.

    Whatever the case, you will find out that there is no correspondance in event order between the input files and the output files. One can however still match the events between the input and output using the fRunId and fMCEntryNo stored in the EventHeader for each event.


    There are few restrictions when using PROOF:

    • tasks - in principal any task can be attached to FairRunAna and analyzed using PROOF, but most will probably crash nowadays, as the members in many tasks are not properly initialized in constructors. When running locally these uninitialized members do not cause any warnings/errors/segmentation violations, but when running on PROOF the master session will crash to prevent possible errors with uninitialized variables.
    • parameter file - to analyze trees in FairRoot you need to specify a root file with the parameters necessary for reconstruction and stored in the simulation phase. In order to reconstruct a chain of trees with several input trees the matching parameters have to be stored in ONE file. The implication is that you cannot concurrently create several input files, while doing so would spoil the parameter file. We are planning to fix this "feature" as soon as possible.

    There are now two constructors of the FairRunAna:

    • FairRunAna(); - it does not take any argument, with the old functionalities, runninig on one CPU
    • FairRunAna(const char* type, const char* proofName=""); - where:
      • "type" can be either "proof" to run on PROOF cluster or "local" to run locally, just like in FairRunAna();
      • "proofName" is the name of your PROOF cluster. One can also specify some options to PROOF here, for example:
        • proofName = "" - the default scenario. The PROOF cluster is your machine with as many workers as the CPUs the machine has
        • proofName = "workers=3" - to specify the number of workers to use
        • proofName = "pod://" - to run on the PROOF cluster created with PoD - not tested since a long time...

    The changes to the SVN include:

    • 3 new files:
      • gconfig/libFairRoot.par - PROOF ARchive file that tells PROOF which libraries to load
      • base/FairAnaSelector.{h.cxx} - the general class deriving from TSelector that manages the reconstruction with PROOF.
    • updates to files:
      • pandaroot/trunk/gconfig/basiclibs.C (modified) (1 diff)
      • fairbase/release/base/CMakeLists.txt (modified) (1 diff)
      • fairbase/release/base/FairLinkDef.h (modified) (1 diff)
      • fairbase/release/base/FairRootManager.cxx (modified) (74 diffs)
      • fairbase/release/base/FairRootManager.h (modified) (6 diffs)
      • fairbase/release/base/FairRun.cxx (modified) (3 diffs)
      • fairbase/release/base/FairRun.h (modified) (5 diffs)
      • fairbase/release/base/FairRunAna.cxx (modified) (40 diffs)
      • fairbase/release/base/FairRunAna.h (modified) (8 diffs)
      • fairbase/release/parbase/FairParAsciiFileIo.cxx (modified) (1 diff)
      • fairbase/release/parbase/FairParAsciiFileIo.h (modified) (2 diffs)
      • fairbase/release/parbase/FairParIo.cxx (modified) (1 diff)
      • fairbase/release/parbase/FairParIo.h (modified) (2 diffs)
      • fairbase/release/parbase/FairParRootFileIo.cxx (modified) (1 diff)

    To developers.

    Following are several notes to the developers that will have to make their classes usable in PROOF:

    • 1. Member initialization matters! The most common error I encountered was caused by class members not being initialized in constructors. Do initialize them and many causes of the errors will disappear.
    • 2. Some members are a bit more complicated or cannot simply be initialized to "0" or "NULL". A good way to get rid of the crash in these cases is to use "//!" which tells the streamer not to stream the value. However be careful here. For not streamed class members the member will not be copied from master to worker node. Why does it matter? The tasks are created on the master already in the macro. Often some values are changed in these tasks with dedicated Set functions. The PROOF clusters start separate processes, also on different machines, when you specify so. In order to execute exactly the task with exactly the parameters you want to have, the tasks are streamed to the nodes using the TList* fInput of the TSelector. Now assume you set some member value with Set function in the macro or in the constructor, but you switch the streaming off for that value, then the value will not be set on the worker... Remember:
      Int_t fVerbosity; // verbosity of the task will be streamed and the value passed to the worker nodes
      Int_t fVerbosity; //! verbosity of the task will not be streamed and the value will not be passed to the worker nodes
    • 3. ReInit(). I have found some serious mistakes in ReInit(). When one analyzes the chain consisting of several trees ReInit() function of the tasks is called BETWEEN the different trees, when fRunId changes from one event to another. Because of already fixed bug in FairRunAna and the fact that the option of analyzing a chain of trees was rarely used the ReInit() is ofter not properly debugged. And so I have seen following issues:
      • a/ the ReInit() returns kERROR - it means that for the next trees this task will be omitted.
      • b/ the ReInit() calls function responsible for creating detectors - in that case in the second tree the task saw twice as many detectors, in the third analyzed tree it saw 3 sets of the detectors. The task was a Hit Producer, created hits in a loop over the detectors, and therefore created normal amount of hits for the first tree, twice the normal amount for the second tree and so on.
      • c/ sometimes something is screwed up in the ReInit() in such a way, that the last entry of the first tree is treated as input to the tasks. In that case in all events in 2nd, 3rd and so on will have the same input and often also the output...

      When checking the task in PROOF, because of that I always have more files than workers, so that they have to call ReInit(). I also analyze the whole set locally and compare: the size of output files, the number of objects created by the task I debug, the shape of the distributions. In case a/ you will have less objects than expected, in case b/ more, and in case c/ you will see peaks in the distribution.

    • 4. Verbosity. For me increasing it is the fastest way of finding problems.
    • 5. DEBUGGING
      The debugging when running on PROOF is more difficult than when running locally, because you can experience errors/crashes on the master (printed on the screen) and on the slaves (in that case you have to observe the individual log files). Because of that, I advise you not to add all the tasks at once, fix them one by one. You will easily spot the errors or crash on the master. However, when the analyze crashes somewhere on the workers, you will see following printout:

      Error in TPacketizerAdaptive::SplitPerHost: The input list contains no elements
      Info in TPacketizerAdaptive::InitStats: fraction of remote files 1.000000
      Info in TProofLite::MarkBad:
      +++ Message from master at : marking lxi047:-1 (0.2) as bad
      +++ Reason: undefined message in TProof::CollectInputFrom(...)

      +++ Message from master at : marking lxi047:-1 (0.2) as bad
      +++ Reason: undefined message in TProof::CollectInputFrom(...)

      +++ Most likely your code crashed
      +++ Please check the session logs for error messages either using
      +++ the 'Show logs' button or executing
      +++ root [] TProof::Mgr("")->GetSessionLogs()->Display("*")

      You may try the suggested method, but it will print out the last 20 lines of each worker. Usually with segmentation violation your error will occur earlier, so that you will get many lines that does not any information necessary for debugging.

      For me the quickest way was to access them by:

      karabowi@lxi047:pandaroot_trunk:~/pandaroot_trunk/trunk/macro/global$ less ~/.proof/pandaroot_trunk-trunk-macro-global/last-lite-session/worker-0.2.log

      Note, that the running directory (pandaroot_trunk/trunk/macro/global) is transformed inside PROOF with and "/" are changed into "-" (pandaroot_trunk-trunk-macro-global).
      Remember also to take the log from the worker that crashed (in this case worker 0.2).

    In case of not being able to fix your problem, please contact me at

    Known issues

    The parameter file - to analyze trees in FairRoot you need to specify a root file with the parameters necessary for reconstruction and stored in the simulation phase. In order to reconstruct a chain of trees with several input trees the matching parameters have to be stored in ONE file. The implication is that you cannot concurrently create several input files, while doing so would spoil the parameter file. We are planning to fix this "feature" as soon as possible.

    The PROOF ARchive file produces error on the master. In your macro you load the rootlogon.C macro and execute it to make FairRoot classes known to ROOT's cint. When you run analysis on the PROOF, the default libFairRoot.par PROOF ARchive also loads in and executed the same macro rootlogon.C. Annoying but harmless error is printed on the screen:

    +++++++ T P R O O F +++++++++++++++++++++++++++++++++
    creating TProof* proof = TProof::Open("");
    +++ Starting PROOF-Lite with 8 workers +++
    Opening connections to workers: OK (8 workers)
    Setting up worker servers: OK (8 workers)
    PROOF set to parallel mode (8 workers)
    +++++++ C R E A T E D +++++++++++++++++++++++++++++++
    EXECUTING libFairRoot.par/SETUP.C without includes
    Function SETUP_c7827247() busy. loaded after "/misc/karabowi/pandaroot_trunk/trunk/gconfig/rootlogon.C"
    Error: G__unloadfile() Can not unload "/misc/karabowi/pandaroot_trunk/trunk/gconfig/rootlogon.C", file busy /tmp/SETUP_c7827247.C:20:
    Note: File "/misc/karabowi/pandaroot_trunk/trunk/gconfig/rootlogon.C" already loaded
    *** Interpreter error recovered ***

    Meanwhile I have added the line "DONT MIND THE ERRORS HERE, ITS EXECUTED", and am currently working on proper loading/unloading of the file.