-
Notifications
You must be signed in to change notification settings - Fork 13
Adding a new branch to the root tree
The RootManager is a singleton class, (one RootManager object is used in the whole treatment) and the contact point between the Geant4 Simulation and the root tree, hence it's the only root class declared explicitly in the G4 simulation. Its major role is to draw the parameters (that we agree on) and store them in a another container (basically a c++ map with addings) for further analysis. I will explain later why a map-like class was used.
NB : The RootManager needs to be updated at each time we add a branch (a detector) in the RootTree. In the following description I point out were the developer needs to add stuff.
RootManager() : Constructor
-
It creates the file
-
allocate the setter classes (fSpiceData, fGriffinData...)
-
allocate the user histograms
-
allocate the tree
-
And set the branches to the trees
~RootManager() : Destructor
(NB : the constructor and destructor can only be called in the class itself and not from the outside)
fRootManager : this static member is created once and is always returned by the public function RootManager::instance()
fRootfile : A root file to store the tree and any other histogram created by the user.
fHist : A sample random histogram (more histogram can be added by each user without any lateral effects to the other users). This has been said, one can make the histograms from the tree. This histogram member is obsolete for now.
fGeantEvent : A map of RawG4Event (container class explained later), the key of the map is the number of the touched segment for now, but in the future will be the mnemonic.
fSpiceData : A pointer to the Class SpiceData, it defines the structure of the data written in the branch of the detector, it's basically a "setter" class.
(NB : When adding a new detector, a corresponding setter class need to be written, and added to the root manager in the same style.)
instance() : Returns the singleton object. When it is called, it creates the fRootManager member if it's not created yet, or it will return it if it already exist.
SetTree() : Set the branches (NB : When adding a new detector, a corresponding branch need to be added)
FillHist(...) : Fill the defined histogram
FillG4Hit(...) : Fill a hit and store it in the fGeantEvent amp (NB : A full G4 event is a collection of hits)
SetEventNumber(...) : Set the Event number of Geant in a detector class
SortEvent() :
-
Go through the map of the RawG4Event, and set each event collection to the corresponding branch according to the "key" of the map (Add the same for a new detector)
-
Now that All the parameters are set in the "setter classes", Fill each branch.
-
Clear the map of the RawG4Event objects
-
Clear the Setter Class (Add the same for a new detector)
SetSpiceEvent(...) : Set the data in the Spice writing Class.
(NB : When adding a new detector, a corresponding function, e.g. SetGriffinEvent, need to be written, and added to the root manager in the same style.)
Close() : Close the root Manager (NB : Called at the end of the simulation)
The RawG4Event is a container class of any geant4 event. The present G4 simulation gives the energy deposit in each step of interaction (called Hit). The same thing applies to any other physical parameters such as the position and the momentum..etc.. However in real life, we only have access to the total deposited energy in one segment. And the real life quantities need to be worked out from the "hit Collection". Basically this class contains c++ vectors to store all the physical parameters from one complex G4 event and other functions to perform operation and return specific values of the hit collection.
The functions in this class are straight forward and easy to understand, the main aim is to get the energy (and other quantities) from the segment. Some function give the total energy, regardless of the ID, some other functions gets the energy of a specific ID or a specific particle type... etc.. These functions are used in the RootManager when filling the branches. It's better to understand how this class works from an example:
A G4 event could consists of a primary gamma and a primary electron (e.g a cascade) For the analysis of Spice, it was important to know not only the details of the detected particles, but also the nature of the Primary particle.
Here's a Spice decay situation
at the source :
emission of a primary conversion electron ID = 1, Pdg = 11, Energy = 300 keV, theta = 40 degree
emission of a primary gamma ID = 2, Pdg = 22, Energy = 700 keV, theta = 60 degree
emission of a primary gamma ID = 3, Pdg = 22, Energy = 900 keV, theta = 80 degree
in a segment : In one segment of the detector, one could end up by this hit collection (one column represents one hit):
PrimaryID : 1 1 1 2 2 2 1 1 3 3 (The same values are repeated for each hit )
PrimaryPdg : 11 11 11 22 22 22 11 11 22 22 (Idem)
PrimaryEnergy : 300 300 300 700 700 700 300 300 900 900 (Idem)
PrimaryTheta : 40 40 40 60 60 60 80 80 80 80 (Idem)
Pdg : 11 22 11 22 22 11 11 11 22 11 (An event could start with an electron (pdg = 11) from the target and ends up as a scattered gammas (pdg = 22) in the detector )
Energy : 40 60 30 400 300 70 10 90 300 400 (Here the energy of the last gamma (ID = 3) is not complete..)
NB : In the naming of the members
- 1."HC" stands for HitCollection
- 2."Primary" word stands for the primary events
The TSpiceData is a Setter Class. It could be used to write or to read from a Root Tree branch. The root manager contains a pointer to this class and its address is set to a branch on the root tree. When a G4event is collected, a "key" indicates that it's Spice event, and the root manager will call void RootManager::SetSpiceEvent(key) to set the values from the G4Event to the TSpiceData object.
When a new detector is added, a Setter class must be written. It must contain all the parameters that need to figure in the Tree Branch. This parameters could be what we expect from an experiment (e.g. Detector number, segment number, energy ) and other extra information from the simulation (The energy of the primary particle, its type, angle of emissions.. etc..)
The structure of the data is a collection of c++ vectors.
Here's a description of the members:
fSpice_Theta_DetNbr : The detector number (in the SPICE case the SiLi might be replaced by another S3)
fSpice_Theta_StripNbr : The Theta(radial) segment number
fSpice_Theta_Energy : The Theta(radial) energy
fSpice_Phi_DetNbr : (idem : specific for the Phi)
fSpice_Phi_StripNbr : (idem : specific for the Phi)
fSpice_Phi_Energy : (idem : specific for the Phi)
fPositionFirstHit : The position of the first hit on the detector
fPrimaryTheta : The polar angle of emission for the primary event
fPrimaryPhi : The azimuthal angle of emission for the primary event
fPrimaryEnergy : The energy of the primary event upon emission
fPrimaryPdg : The particle type of the primary event upon emission
fPdg : The particle type of a hit
fEventNumber : The event number from Geant4
The rest of the Class are setters and getters of the above variables, used to write and read the tree respectively.
Notes : **The code is modular, we should keep it this way, A detector <=> separate writing class ** For each new detector a "Setter" root-class must be written.
-
All the files corresponding to the "Setter" class goes in the folder dataRootClass/ (${myROOTclassDir} in the CMakeLists.txt)
-
copy the New_linkdef.h in the directory ${myROOTclassDir} and Replace "New" by the name of your detector
-
Change the Makefile in dataRootClass/ to compile the new files, 'make clean' and 'make' to create the libraries
-
go to the block [ # Specify Shared libraries ]
- Add the name of the new shared library correponding to the new detector e.g. SHARELIB = libSpiceData.so libS3Data.so libNewData.so -
go to the block [ # Create dictionaries and compile ]
- Copy the commented block with detector "New" - Replace "New" by the name of your detector -
go to the block [ # Manage dependances ]
- Copy the commented block with detector "New" - Replace "New" by the name of your detector
-
-
change the CMakeLists.txt under the detectorSimulations (INSTALL) directory
-
go to the block [ # Adding a variable to use root through out the G4 project ]
- Declare the root class in the CMakeLists on top by copying [ #set(myROOTNewclass TNewData.cpp) ] - Replace "New" by the name of your detector -
go to the block [ # Use root in the project ]
- Copy the commented block with detector "New" - Replace "New" by the name of your detector (don't forget to specify the dictionary file that is generated by rootcint (starting with "dict"), you will use it in the next step.) - Each detector has a name_linkdef.h file that could be used to specify some options while adding a class in root. -
go to the block [ # Add the executable, and link it to the Geant4 libraries ]
- Copy the commented block with detector "New" - Replace "New" by the name of your detector (the dictionary file must be the same)
-
-
Finally, in ./src/RootManager.hh, add the header of the new class and use it e.g.
#include "RawG4Event.hh" #include "relative/path/to/dataRootClass/TSpiceData.h" #include "relative/path/to/dataRootClass/TNewData.h"