9.2.  Analysis Manager Classes

The analysis manager classes provide uniform interfaces to the g4tools package and hide the differences between use of g4tools classes for the supported output formats (ROOT, AIDA XML, CSV and HBOOK).

An analysis manager class is available for each supported output format:

For a simplicity of use, each analysis maneger provides the complete access to all interfaced functions though it is implemented via a more complex design.

The managers are implemented as singletons. User code will access a pointer to a single instance of the desired manager. The manager has to be created and deleted from the user code. All objects created via analysis manager are deleted automatically with the manager. The concrete types of the analysis manager as well as the handled g4tools objects, are hidden behind a namespace which is selected by including a dedicated include file. This allows the user to use all output technologies in an identical way via these generic types:

In addition to the G4AnalysisManager functions, a set of Geant4 UI commands for creating histograms and setting their properties is implemented in associated messenger classes.

In order to avoid a dependence of the Geant4 kernel libraries on CERNLIB the ExG4HbookAnalysisManger class is not included in the Geant4 analysis class category but in examples/extended/common/analysis together with all necessary configuration files for its build with the CERNLIB libraries.

9.2.1.  Histograms

9.2.1.1.  Basic Histograms

An example of use of analysis manager classes is provided in basic example B4, in the B4RunAction and B4EventAction classes. The code for handling histograms given in the following example is extracted from these classes.

Example 9.1.  Example with Histograms

#include "B4Analysis.hh"

B4RunAction::B4RunAction()
 : G4UserRunAction()
{ 
  // Create analysis manager
  G4AnalysisManager* analysisManager = G4AnalysisanalysisManagerager::Instance();
  analysisManager->SetVerboseLevel(1);
  analysisManager->SetFirstHistoId(1);

  // Creating histograms
  analysisManager->CreateH1("1","Edep in absorber", 100, 0., 800*MeV);
  analysisManager->CreateH1("2","Edep in gap", 100, 0., 100*MeV);
}

B4RunAction::~B4RunAction()
{
  delete G4AnalysisManager::Instance();  
}

void B4RunAction::BeginOfRunAction(const G4Run* run) 
{ 
  // Get analysis manager
  G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
  
  // Open an output file
  analysisManager->OpenFile("B4");
}

void B4aEventAction::EndOfEventAction(const G4Run* aRun)
{
  // Fill histograms
  G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
  analysisManager->FillH1(1, fEnergyAbs);
  analysisManager->FillH1(2, fEnergyGap);
}

void B4RunAction::EndOfRunAction(const G4Run* aRun)
{
  // Save histograms
  G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
  analysisManager->Write();
  analysisManager->CloseFile();
}

The code specific to the output format is hidden in B4Analysis.hh where the selection of the output format takes place.

#ifndef B4Analysis_h
#define B4Analysis_h 1

#include "g4root.hh"
//#include "g4xml.hh"
//#include "g4csv.hh"

#endif


The analysis manager object is created with the first call to G4AnalysisManager::Instance(), the next calls to this function will just provide the pointer to this analysis manager object. The client code is responsible for deleting the created object what is in our example done in the run action destructor.

The level of informative printings can be set by SetVerboseLevel(G4int). Currently the levels from 0 (default) up to 4 are supported.

9.2.1.2.  Functions for Creating Histograms

A one-dimensional (1D) histogram can be created with one of these two G4AnalysisManager functions:

    G4int CreateH1(const G4String& name, const G4String& title,
                   G4int nbins, G4double xmin, G4double xmax,
                   const G4String& unitName = "none",
                   const G4String& fcnName = "none",
                   const G4String& binSchemeName = "linear");

    G4int CreateH1(const G4String& name, const G4String& title,
                   const std::vector<G4double>& edges,
                   const G4String& unitName = "none",
                   const G4String& fcnName = "none");

where name and title parameters are self-descriptive. The histogram edgeds can be defined either via the nbins, xmin and xmax parameters (first function) representing the number of bins, the minimum and maximum histogram values, or via the const std::vector<G4double>& edges parameter (second function) representing the edges defined explicitly. The other parameters in both functions are optional and their meaning is explained in the subsection "HistogramsProperties".

Two-dimensional (2D) and three-dimensional (3D) histograms can be created with one of these two functions analogous to those for 1D histograms:

    G4int CreateH2(const G4String& name, const G4String& title,
                   G4int nxbins, G4double xmin, G4double xmax, 
                   G4int nybins, G4double ymin, G4double ymax,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& xbinScheme = "linear",
                   const G4String& ybinScheme = "linear");
   
    G4int CreateH2(const G4String& name, const G4String& title,
                   const std::vector<G4double>& xedges,
                   const std::vector<G4double>& yedges,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none");

    G4int CreateH3(const G4String& name, const G4String& title,
                   G4int nxbins, G4double xmin, G4double xmax, 
                   G4int nybins, G4double ymin, G4double ymax,
                   G4int nzbins, G4double zmin, G4double zmax,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& zunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& zfcnName = "none",
                   const G4String& xbinSchemeName = "linear",
                   const G4String& ybinSchemeName = "linear",
                   const G4String& zbinSchemeName = "linear");
   
    G4int CreateH3(const G4String& name, const G4String& title,
                   const std::vector<G4double>& xedges,
                   const std::vector<G4double>& yedges,
                   const std::vector<G4double>& zedges,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& zunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& zfcnName = "none");

The meaning of parameters is the same as in the functions for 1D histograms, they are just applied in x, y and z dimensions.

The histograms created with G4AnalysisManager get automatically attributed an integer identifier which value is returned from the "Create" function. The default start value is 0 and it is incremented by 1 for each next created histogram. The numbering of 2D and 3D histograms is independent from 1D histograms and so the first created 2D (or 3D) histogram identifier is equal to the start value even when several 1D histograms have been already created.

The start histogram identifier value can be changed either with the SetFirstHistoId(G4int) method, which applies the new value to all histogram types, or with the SetFirstHNId(G4int), where N = 1, 2, 3 methods, which apply the new value only to the relevant histogram type. The first method is demonstrated in the example.

The histogram names "1", "2" in the demonstrated example are defined to correspond the histograms identifiers in a similar way as in extended/analysis/AnaEx01 example. This choice is however fully in hands of the user who can prefer longer and more meaningful names.

All histograms created by G4AnalysisManager are automatically deleted with deleting the G4AnalysisManager object.

9.2.1.3.  Functions for Configuring Histograms

The properties of already created histograms can be changed with use of one of these two functions sets. For 1D histograms:

    G4bool SetH1(G4int id,
                   G4int nbins, G4double xmin, G4double xmax,
                   const G4String& unitName = "none",
                   const G4String& fcnName = "none",
                   const G4String& binSchemeName = "linear");

    G4bool SetH1(G4int id,
                   const std::vector<G4double>& edges,
                   const G4String& unitName = "none",
                   const G4String& fcnName = "none");

for 2D histograms:

    G4bool SetH2(G4int id,
                   G4int nxbins, G4double xmin, G4double xmax, 
                   G4int nybins, G4double ymin, G4double ymax,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& xbinSchemeName = "linear",
                   const G4String& ybinSchemeName = "linear");

    G4bool SetH2(G4int id,
                   const std::vector<G4double>& xedges,
                   const std::vector<G4double>& yedges,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none");

and for 3D histograms:

    G4bool SetH3(G4int id,
                   G4int nxbins, G4double xmin, G4double xmax, 
                   G4int nzbins, G4double zmin, G4double zmax,
                   G4int nybins, G4double ymin, G4double ymax,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& zunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& zfcnName = "none",
                   const G4String& xbinSchemeName = "linear",
                   const G4String& ybinSchemeName = "linear",
                   const G4String& zbinSchemeName = "linear");

    G4bool SetH3(G4int id,
                   const std::vector<G4double>& xedges,
                   const std::vector<G4double>& yedges,
                   const std::vector<G4double>& zedges,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& zunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& zfcnName = "none");

The histogram is accessed via its integer identifier. The meaning of the other parameters is the same as in "Create" functions.

A limited set of parameters for histograms plotting, the histogram and the histogram axis titles, can be also defined via functions:

    G4bool SetH1Title(G4int id, const G4String& title);
    G4bool SetH1XAxisTitle(G4int id, const G4String& title);
    G4bool SetH1YAxisTitle(G4int id, const G4String& title);
    //
    G4bool SetH2Title(G4int id, const G4String& title);
    G4bool SetH2XAxisTitle(G4int id, const G4String& title);
    G4bool SetH2YAxisTitle(G4int id, const G4String& title);
    G4bool SetH2ZAxisTitle(G4int id, const G4String& title);
    //
    G4bool SetH3Title(G4int id, const G4String& title);
    G4bool SetH3XAxisTitle(G4int id, const G4String& title);
    G4bool SetH3YAxisTitle(G4int id, const G4String& title);
    G4bool SetH3ZAxisTitle(G4int id, const G4String& title);

9.2.1.4.  Functions for Filling Histograms

The histogram values can be filled using the functions:

    G4bool FillH1(G4int id, G4double value, 
                  G4double weight = 1.0);
    G4bool FillH2(G4int id, G4double xvalue, G4double yvalue,
                  G4double weight = 1.0);
    G4bool FillH3(G4int id, 
                  G4double xvalue, G4double yvalue, G4double zvalue,
                  G4double weight = 1.0);

where the weight can be given optionally.

The histograms can be also scaled with a given factor using the functions:

    G4bool ScaleH1(G4int id, G4double factor);
    G4bool ScaleH2(G4int id, G4double factor);
    G4bool ScaleH3(G4int id, G4double factor);    

9.2.1.5.  Accessing Histograms

Besides the fast access to histograms via their integer identifiers, the histograms can be also accessed by their names using the G4AnalysisManager function providing the conversion from a name in a histogram identifier:

    G4int GetH1Id(const G4String& name, G4bool warn = true) const;
    G4int GetH2Id(const G4String& name, G4bool warn = true) const;
    G4int GetH3Id(const G4String& name, G4bool warn = true) const;

If a histogram with a given name is not found, a warning is issued unless it is explicitly disabled by the user. This way is however less efficient and it is not recommended for frequently called functions as e.g. Fill().

The analysis manager provides also the direct access to the g4tools histogram objects. The concrete histogram type is hidden behind a selected namespace. In example B4, the g4tools histogram functions mean() and rms() are called:

  G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
  if ( analysisManager->GetH1(1) ) {
    G4cout << "\n ----> print histograms statistic \n" << G4endl;
    G4cout << " EAbs : mean = " << analysisManager->GetH1(1)->mean() 
           << " rms = " << analysisManager->GetH1(1)->rms(), 
           << G4endl;
    // ...           
  }             

9.2.1.6.  Activation of Histograms

The activation option allows the user to activate only selected histograms. When this option is activated, only the histograms marked as activated are returned, filled or saved in a file. This feature is intensively used in extended/electromagnetic examples where all histograms are first created inactivated:

  G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
  analysisManager->SetActivation(true);
  // define histogram parameters name, title, nbins, vmin, vmax
  G4int id = analysisManager->CreateH1(name, title, nbins, vmin, vmax);
  analysisManager->SetH1Activation(id, false);

and then selected histograms are activated in macros, using the analysis "set" command:

/analysis/h1/set 1 100 0   50 cm        #track length of primary
/analysis/h1/set 2 100 0  300 none      #nb steps of primary

When no parameters need to be changed a histogram can be activated using "setActivation" command:

/analysis/h1/setActivation 1 true
/analysis/h1/setActivation 2 true

9.2.1.7.  Histograms Properties

The following properties, additional to those defined in g4tools, can be added to histograms via G4AnalysisManager:

  • Unit: if a histogram is defined with a unit, all filled values are automatically converted to this defined unit and the unit is added to the histogram axis title.
  • Function: if a histogram is defined with a function, the function is automatically executed on the filled values and its name is added to the histogram axis title. When a histogram is defined with both unit and function the unit is applied first. The available functions: log, log10, exp .
  • Binning scheme: user can select logarithmic binning scheme besides the linear one (default). The available binning schemes: linear, log .
  • Activation: see previous section.
  • ASCII option: if activated the histogram is also printed in an ASCII file when Write() function is called.

9.2.2.  Profiles

Profile histograms (profiles) are used to display the mean value of Y and its error for each bin in X. The displayed error is by default the standard error on the mean (i.e. the standard deviation divided by the sqrt(n).) An example of use of 1D profiles can be found in extended/electromagnetic/TestEm2. Though the functions for creating and manipulating profiles are very similar to those for histograms, they are described in this section.

9.2.2.1.  Functions for Creating Profiles

A one-dimensional (1D) profile can be created with one of these two G4AnalysisManager functions:

    G4int CreateP1(const G4String& name, const G4String& title,
                   G4int nbins, G4double xmin, G4double xmax,
                   G4double ymin = 0, G4double ymax = 0,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& xbinSchemeName = "linear");

    G4int CreateP1(const G4String& name, const G4String& title,
                   const std::vector<G4double>& edges,
                   G4double ymin = 0, G4double ymax = 0,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none");

where name and title parameters are self-descriptive. The profile edgeds can be defined either via the nbins, xmin and xmax parameters (first function) representing the number of bins, the minimum and maximum profile values, or via the const std::vector<G4double>& edges parameter (second function) representing the edges defined explicitly. If ymin and ymax parameters are provides, only values between these limnits will be considered at filling time. The other parameters in both functions are optional and their meaning is explained in the subsection "ProfilesProperties".

A two-dimensional (2D) profile can be created with one of these two functions analogous to those for 1D profiles:

    G4int CreateP2(const G4String& name, const G4String& title,
                   G4int nxbins, G4double xmin, G4double xmax,
                   G4int nybins, G4double ymin, G4double ymax, 
                   G4double zmin = 0, G4double zmax = 0,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& zunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& zfcnName = "none",
                   const G4String& xbinSchemeName = "linear", 
                   const G4String& ybinSchemeName = "linear");

    G4int CreateP2(const G4String& name, const G4String& title,
                   const std::vector<G4double>& xedges,
                   const std::vector<G4double>& yedges,
                   G4double zmin = 0, G4double zmax = 0,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& zunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& zfcnName = "none");

The meaning of parameters is the same as in the functions for 1D profiles, they are just applied in x, y and z dimensions.

The profiles created with G4AnalysisManager get automatically attributed an integer identifier which value is returned from the "Create" function. The default start value is 0 and it is incremented by 1 for each next created profile. The numbering of 2D profiles is independent from 1D profiles and so the first created 2D profile identifier is equal to the start value even when several 1D profiles have been already created.

The start profile identifier value can be changed either with the SetFirstProfileId(G4int) method, which applies the new value to both 1D and 2D profile types, or with the SetFirstPNId(G4int), where N = 1, 2 methods, which apply the new value only to the relevant profile type.

All profiles created by G4AnalysisManager are automatically deleted with deleting the G4AnalysisManager object.

9.2.2.2.  Functions for Configuring Profiles

The properties of already created profiles can be changed with use of one of these two functions sets. For 1D profiles:

    G4bool SetP1(G4int id,
                   G4int nbins, G4double xmin, G4double xmax,
                   G4double ymin = 0, G4double ymax = 0,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& xbinSchemeName = "linear");

    G4bool SetP1(G4int id,
                   const std::vector<G4double>& edges,
                   G4double ymin = 0, G4double ymax = 0,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none");

and for 2D profiles:

    G4bool SetP2(G4int id,
                   G4int nxbins, G4double xmin, G4double xmax, 
                   G4int nybins, G4double ymin, G4double ymax, 
                   G4double zmin = 0, G4double zmax = 0,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& zunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& zfcnName = "none",
                   const G4String& xbinSchemeName = "linear",
                   const G4String& ybinSchemeName = "linear");

    G4bool SetP2(G4int id,
                   const std::vector<G4double>& xedges,
                   const std::vector<G4double>& yedges,
                   G4double zmin = 0, G4double zmax = 0,
                   const G4String& xunitName = "none", 
                   const G4String& yunitName = "none",
                   const G4String& zunitName = "none",
                   const G4String& xfcnName = "none", 
                   const G4String& yfcnName = "none",
                   const G4String& zfcnName = "none");

The profile is accessed via its integer identifier. The meaning of the other parameters is the same as in "Create" functions.

A limited set of parameters for profiles plotting, the profile and the profile axis titles, can be also defined via functions:

    G4bool SetP1Title(G4int id, const G4String& title);
    G4bool SetP1XAxisTitle(G4int id, const G4String& title);
    G4bool SetP1YAxisTitle(G4int id, const G4String& title);
    //
    G4bool SetP2Title(G4int id, const G4String& title);
    G4bool SetP2XAxisTitle(G4int id, const G4String& title);
    G4bool SetP2YAxisTitle(G4int id, const G4String& title);
    G4bool SetP2ZAxisTitle(G4int id, const G4String& title);

9.2.2.3.  Functions for Filling Profiles

The profile values can be filled using the functions:

    G4bool FillP1(G4int id, 
                  G4double xvalue, G4double yvalue, 
                  G4double weight = 1.0);
    G4bool FillP2(G4int id, 
                  G4double xvalue, G4double yvalue, G4double zvalue, 
                  G4double weight = 1.0);

where the weight can be given optionally.

The profiles can be also scaled with a given factor using the functions:

    G4bool ScaleP1(G4int id, G4double factor);
    G4bool ScaleP2(G4int id, G4double factor);

9.2.2.4.  Profiles Properties

All histogram features described in sections "Accessing Histograms", "Activation of Histograms" and "Histograms Properties" are also available for profiles.

9.2.3.  Analysis Messenger

The G4AnalysisMessenger class implements the commands for creating histograms and profiles and setting their properties described below.

The commands for handling files, directories and general options:

/analysis/setFileName name           # Set name for the histograms and ntuple file
/analysis/setHistoDirName name       # Set name for the histograms directory
/analysis/setNtupleDirName name      # Set name for the histograms directory
/analysis/setActivation true|false   # Set activation option
/analysis/verbose level              # Set verbose level

The commands to create or define 1D histogram:

/analysis/h1/create 
   name title [nbin min max] [unit] [fcn] [binScheme]     # Create 1D histogram
/analysis/h1/set id nbin min max [unit] [fcn] [binScheme] # Set parameters

The commands to create or define 2D histogram:

/analysis/h2/create               # Create 2D histogram
  name title [nxbin xmin xmax xunit xfcn xbinScheme nybin ymin ymax yunit yfcn yBinScheme] 
/analysis/h2/set                  # Set parameters for the 2D histogram of #id
  id nxbin xmin xmax xunit xfcn xbinScheme nybin ymin ymax yunit yfcn yBinScheme  

The commands to create or define 3D histogram:

/analysis/h3/create               # Create 3D histogram
  name title [nxbin xmin xmax xunit xfcn xbinScheme nybin ymin ymax yunit yfcn yBinScheme nzbin zmin zmax zunit zfcn zBinScheme] 
/analysis/h3/set                  # Set parameters for the 3D histogram of #id
  id nxbin xmin xmax xunit xfcn xbinScheme nybin ymin ymax yunit yfcn yBinScheme nzbin zmin zmax zunit zfcn zBinScheme 

The commands to create or define 1D profile:

/analysis/p1/create               # Create 1D profile
  name title [nxbin xmin xmax xunit xfcn xbinScheme ymin ymax yunit yfcn] 
/analysis/h2/set                  # Set parameters for the 1D histogram of #id
  id nxbin xmin xmax xunit xfcn xbinScheme ymin ymax yunit yfcn  

The commands to create or define 2D profile:

/analysis/p2/create               # Create 2D profile
  name title [nxbin xmin xmax xunit xfcn xbinScheme nybin ymin ymax yunit yfcn yBinScheme zmin zmax zunit zfcn] 
/analysis/p2/set                  # Set parameters for the 2D profile of #id
  id nxbin xmin xmax xunit xfcn xbinScheme nybin ymin ymax yunit yfcn yBinScheme zmin zmax zunit zfcn 

The commands for histogram and profiles control:

/analysis/h1/setAscii id true|false             # Print 1D histogram of #id on ascii file.
/analysis/h1/setTitle id title                  # Set title for the 1D histogram of #id
/analysis/h1/setXaxis id title                  # Set x-axis title for the 1D histogram
/analysis/h1/setYaxis id title                  # Set y-axis title for the 1D histogram
/analysis/h1/setActivation id true|false        # Set activation for the 1D histogram
/analysis/h1/setActivationToAll  true|false     # Set activation to all 1D histograms.

The same set of commands is available for the other histogram types and profiles, under the appropriate directory.

9.2.4.  Ntuples

In the following example the code for handling ntuples extracted from basic example B4, from the B4RunAction and B4EventAction classes, is presented.

Example 9.2.  Example with Ntuple

#include "B4Analysis.hh"

B4RunAction::B4RunAction()
 : G4UserRunAction()
{ 
  // Create analysis manager
  G4AnalysisManager* man = G4AnalysisManager::Instance();
  
  // Create ntuple
  man->CreateNtuple("B4", "Edep and TrackL");
  man->CreateNtupleDColumn("Eabs");
  man->CreateNtupleDColumn("Egap");
  man->FinishNtuple();
}

B4RunAction::~B4RunAction()
{
  delete G4AnalysisManager::Instance();  
}

void B4RunAction::BeginOfRunAction(const G4Run* run) 
{ 
  // Get/create analysis manager
  G4AnalysisManager* man = G4AnalysisManager::Instance();
  
  // Open an output file
  man->OpenFile("B4");
}

void B4EventAction::EndOfEventAction(const G4Run* aRun)
{
  G4AnalysisManager* man = G4AnalysisManager::Instance();
  man->FillNtupleDColumn(0, fEnergyAbs);
  man->FillNtupleDColumn(1, fEnergyGap);
  man->AddNtupleRow();  
}

void B4RunAction::EndOfRunAction(const G4Run* aRun)
{
  // Save histograms
  G4AnalysisManager* man = G4AnalysisManager::Instance();
  man->Write();
  man->CloseFile();
}


Since 10.0 release, there is no limitation for the number of ntuples that can be handled by G4AnalysisManager. Handling of two ntuples is demostrated in extended analysis/AnaEx01 example.

9.2.4.1.  Functions for Creating Ntuples

An ntuple can be created using the following set of functions:

    G4int CreateNtuple(const G4String& name, const G4String& title);

    // Create columns in the last created ntuple
    G4int CreateNtupleXColumn(const G4String& name);
    void  FinishNtuple();   
    
    // Create columns in the ntuple with given id
    G4int CreateNtupleXColumn(G4int ntupleId, const G4String& name);
    void  FinishNtuple(G4int ntupleId); 

The first set is demonstrated in the example. The columns can take the values of G4int, G4float, G4double or G4Stringtype which is also reflected in the CreateNtupleXColumn() function names. where X can be I, F, D or S .

It is also possible to define ntuple columns of std::vector of G4int, G4float or G4double values using the functions:

    // Create columns of vector in the last created ntuple
    G4int CreateNtupleXColumn(
            const G4String& name, std::vector<Xtype>& vector);

    // Create columns of vector in the ntuple with given id
    G4int CreateNtupleXColumn(G4int ntupleId, 
            const G4String& name, std::vector<Xtype>& vector);

where [X, Xtype] can be [I, G4int], [F, G4float] or [D, G4double].

When all ntuple columns are created, the ntuple has to be closed using FinishNtuple() function.

The ntuples created with G4AnalysisManager get automatically attributed an integer identifier which value is returned from the "Create" function. The default start value is 0 and it is incremented by 1 for each next created ntuple. The start ntuple identifier value can be changed with the SetFirstNtupleId(G4int) function.

The integer identifiers are also attributed to the ntuple columns. The numbering of ntuple columns is independent for each ntuple, the identifier default start value is 0 and it is incremented by 1 for each next created column regardless its type (I, F, D or S). (If the third ntuple column of a different type than double (int or float) is created in the demonstrated example, its identifier will have the value equal 2.) The start ntuple column identifier value can be changed with the SetFirstNtupleColumnId(G4int) function.

When calls to CreateNtuple-Column() and FinishNtuple() succeed the call to CreateNtuple(), the ntupleId argument need not to be specified even when creating several ntuples. However this order is not enforced and the second set of functions with ntupleId argument is provided to allow the user to create the ntuples and their columns in whatever order.

All ntuples and ntuple columns created by G4AnalysisManager are automatically deleted with deleting the G4AnalysisManager object.

9.2.4.2.  Functions for Filling Ntuples

The ntuple values can be filled using the functions:

    // Methods for ntuple with id = FirstNtupleId                     
    G4bool FillNtupleIColumn(G4int id, G4int value);
    G4bool FillNtupleFColumn(G4int id, G4float value);
    G4bool FillNtupleDColumn(G4int id, G4double value);
    G4bool FillNtupleSColumn(G4int id, const G4String& value);
    G4bool AddNtupleRow();

    // Methods for ntuple with id > FirstNtupleId (when more ntuples exist)                      
    G4bool FillNtupleIColumn(G4int ntupleId, G4int columnId, G4int value);
    G4bool FillNtupleFColumn(G4int ntupleId, G4int columnId, G4float value);
    G4bool FillNtupleDColumn(G4int ntupleId, G4int columnId, G4double value);
    G4bool FillNtupleSColumn(G4int ntupleId, G4int id, const G4String& value);
    G4bool AddNtupleRow(G4int ntupleId);

If only one ntuple is defined in the user application, the ntuple identifier, ntupleId, need not to be specified and the first set can be used. The second set of functions has to be used otherwise. When all ntuple columns are filled, the ntuple fill has to be closed by calling AddNtupleRow().

9.2.4.3.  Accessing Ntuples

The ntuples g4tools objects can be accessed by their identifier. The concrete ntuple type is hidden behind a selected namespace:

    G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
    // If only one ntuple is defined
    G4Ntuple* ntuple = analysisManager->GetNtuple();
    // If more ntuples 
    G4int ntuple id = ...;
    G4Ntuple* ntuple = analysisManager->GetNtuple(ntupleId);

9.2.5.  Files handling

The following functions are defined for handling files:

    G4bool OpenFile(const G4String& fileName = "");
    G4bool Write(); 
    G4bool CloseFile(); 

The file name can be defined either directly with OpenFile(const G4String&) call or separately via SetFileName(const G4String&) function before calling OpenFile(). It is not possible to change the file name when a file is open and not yet closed. If a file extension is not specified in fileName, it is automatically completed according to a selected output format.

The file can be optionally structured in sub-directories. Currently only one directory for histograms and/or one directory for ntuples are supported. The directories are created automatically if their names are set to non-empty string values via SetHistoDirectoryName(const G4String&) and/or SetNtupleDirectoryName(const G4String&). This setting is ignored with the output formats which do not support this feature (XML, CSV).

Depending on the selected output format more files can be generated when more than one ntuple is defined in a user application. This is the case of XML and CSV, which do not allow writing more than one ntuple in a file. The ntuple file name is then generated automatically from the base file name and the ntuple name.

The analysis manager can handle only one base file at a time, but several base files can be generated sucessively from Geant4 session, typically one file is saved per run. A new file can be open only after a previous file was closed. An example of generated more files per session is provided in basic/B5 example and its run2.mac macro. Appending existing files is not supported. When an existing file is open again, its content is overwritten.

9.2.6.  Multi-threading

As well as all other Geant4 categories, the analysis code has been adapted for multi-threading. In multi-threading mode, the analysis manager instances are internally created on the master and thread workers and data accounting is processed in parallel on workers threads.

Histograms produced on thread workers are automatically merged on Write() call and the result is written in a master file. Merging is protected by a mutex locking, using G4AutoLock utility. Ntuples produced on thread workers are written on separate files, which names are generated automatically from a base file name, a thread identifier and eventually also an ntuple name. No merging of ntuples is performed.

No changes are required in the user client analysis code for migration to multi-threading. It is however recommended to instantiate and delete the analysis manager in the user run action constructor and destructor respectively. The master instance is necessary when histograms are used in the user application; in case only ntuples are in use, the master instance need not to be created.

The HBOOK output is not supported in multi-threading mode.

9.2.7.  Coexistence of Several Managers

The specific manager classes are singletons and so it is not possible to create more than one instance of an analysis manager of one type, eg. G4RootAnalysisManager. However two analysis manager objects of different types can coexist. Then instead of the generic G4AnalysisManager typedef the concrete type of each manager has to be given explicitly.

Example 9.3.  Example with two analysis manager instances

#include "G4CsvAnalysisManager.hh"
#include "G4XmlAnalysisManager.hh"

G4CsvAnalysisManager* csvManager = G4CsvAnalysisManager::Instance();
G4XmlAnalysisManager* xmlManager = G4XmlAnalysisManager::Instance();

Or:

#include "g4csv_defs.hh"
#include "g4xml_defs.hh"

G4Csv::G4AnalysisManager* csvManager = G4Csv::G4AnalysisManager::Instance();
G4Xml::G4AnalysisManager* xmlManager = G4Xml::G4AnalysisManager::Instance();


9.2.8.  Supported Features and Limitations

The analysis category based on g4tools is provided with certain limitations that can be reduced according to the feedback from Geant4 users and developers.

Below is a summary of currently supported features in Root, Csv and Xml manager classes:

  • Histogram types: 1D, 2D, 3D of double
  • Profile types: 1D, 2D of double
  • Ntuple column types: int, float, double, G4String
  • Optional directory structure limited to one directory for histograms and/or one for ntuples

The Hbook analysis manager does not support 3D histograms, 2D profiles and G4String ntuple column types.