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, HDF5, AIDA XML and CSV).
Since Geant4 10.7, there is an analysis manager class capable to mix output file formats:
G4GenericAnalysisManager
Mixing of different output types is supported for histogram and profiles objects, only one output type is supported for ntuples.
An analysis manager class is available also for each supported output format:
G4CsvAnalysisManager
G4Hdf5AnalysisManager
G4RootAnalysisManager
G4XmlAnalysisManager
For a simplicity of use, each analysis manager provides the complete
access to all interfaced functions though it is implemented via a more
complex design. This design allows the user to use all output technologies
in an identical way via a generic G4AnalysisManager
type defined as:
using G4AnalysisManager = G4XyzAnalysisManager;
// where Xyz = Generic, Csv, Hdf5, Root, Xml
The managers are implemented as Geant4 singletons. User code will access a
pointer to a single instance of the desired manager. The manager is created
with the first call to the Instance()
function and it is deleted
by Geant4 kernel at the end of a user application. All objects created via
analysis manager are deleted automatically with the manager.
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.
Analysis Manager¶
To use Geant4 analysis, an instance of the analysis manager must be
created. 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 example of the code for creating the analysis manager extracted from the basic B4 example is given below:
#include "G4AnalysisManager.hh"
namespace B4
{
RunAction::RunAction()
{
// Create analysis manager
auto analysisManager = G4AnalysisManager::Instance();
analysisManager->SetVerboseLevel(1);
}
}
It is recommended, but not necessary, to create the analysis manager in the user run action constructor. This guarantees correct behavior in multi-threading mode.
The G4AnalysisManager.hh header (since Geant4 11.0) defines the
G4GenericAnalysisManager
as G4AnalysisManager
type:
#ifndef G4AnalysisManager_h
#define G4AnalysisManager_h
#include "G4GenericAnalysisManager.hh"
using G4AnalysisManager = G4GenericAnalysisManager;
#endif
The level of informative printings can be set by
SetVerboseLevel(G4int)
. Currently the levels from 0 (default) up to
4 are supported.
The verbose level can be also set via the UI command:
/analysis/verbose level
Since Gean4 version 11 the analysis manager is defined as a Geant4
thread-local singleton and users need not and should not delete its
instance. Public functions Clear()
and Reset()
are provided to allow
resetting and deleting all allocated analysis objects and clearing their collections:
G4bool Reset();
void Clear();
The Clear()
function can be used as a replacement for deleting the analysis manager
in the applications that allocate the analysis data in the begin of run and deleted
the analysis manager in the end of run.
Data ressetting can be also performed with a UI command (Since Geant4 11.1):
/analysis/reset
The list of all analysis objects can be obtained by the List()
function with
an optional boolean argument to choose to display only active objects:
G4bool List(G4bool onlyIfActive = true) const;
or a UI command:
/analysis/list [onlyIfActive]
Files handling¶
Below we give an example of opening and closing a file extracted from the basic example B4:
#include "G4AnalysisManager.hh"
void RunAction::BeginOfRunAction(const G4Run* run)
{
// Get analysis manager
auto analysisManager = G4AnalysisManager::Instance();
// Open an output file
G4String fileName = "B4.root";
analysisManager->OpenFile(fileName);
}
void RunAction::EndOfRunAction(const G4Run* aRun)
{
// Save histograms
auto analysisManager = G4AnalysisManager::Instance();
analysisManager->Write();
analysisManager->CloseFile();
}
The following G4AnalysisManager
functions are defined for handling files:
G4bool OpenFile(const G4String& fileName = "");
G4bool Write();
G4bool CloseFile(G4bool reset = true);
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. Since Geant4 version 11 multiple files can be hadled at a time,
the functions remain valid and define the name of the default file.
The call to Write()
triggers writing remaining data to all open files
and the call to CloseFile()
closing all files and automatic resetting histograms and
ntuples data. Since Geant4 10.5, it is possible to close a file without
resetting the histogram data. This feature is used in example B5
to keep the histograms available for visualization plotting (resetting of histograms
is then performed by a call to Reset()
in the begin of the next run).
Another use case is in MPI extended examples to write the histograms collected on the master
rank before they are merged and written in another file.
Since Geant4 11.1, it is possible to call Write()
multiple times before closing
a file. The written objects will then be written with a new name composed of the original name
appended with a suffix containing the object cycle number, for example:
myHisto myHisto;1 myHisto;2 etc. in case of the Root output
myHisto myHisto_v1 myHisto_v2 etc. in case of the other output types
The fuctions for file handling can be also performed with UI commands (since Geant4 11.1):
/analysis/openFile [fileName]
/analysis/write
/analysis/closeFile [isReset]
An extended analysis example, AnaEx03, has been added to demonstrate usage of the analysis commands for file management and in particular writing histograms and ntuples in a file multiple times.
As G4GenericAnalysisManager
can handle all supported file formats, the file names
should be provided with an extension (.csv, .hdf5, .root or .xml).
To continue using file names without extensions, users can set the default
file type using the G4AnalysisManager
function
(since Geant4 version 11.0):
void SetDefaultFileType(const G4String& value);
or a UI command:
/analysis/setDefaultFileType fileType
... where fileType = csv, hdf5, root, xml
Multiple files handling¶
Users can choose to write selected objects in a different file than the default one using the
G4AnalysisManager
functions
void SetH1FileName(G4int objectId, const G4String& name);
//... etc. for H2, H3, P1, P2
void SetNtupleFileName(G4int objectId, const G4String& name);
The setting can be also performed with UI commands:
/analysis/h1/setFileName id name
/analysis/h1/setFileNameToAll name
... etc. for h2, h3, p1, p2
/analysis/ntuple/setFileName id fileName
/analysis/ntuple/setFileNameToAll fileName
While it is possible to mix output types for histogram and profiles objects, only one output type is supported for ntuples. Saving of histograms and ntuple in two output files in a Root file format is demonstrated in the basic B5 example.
The output specific analysis managers (the analysis manager defined via the
G4XxxAnalysisManager.hh, Xxx = Csv, Hdf5, Root, Xml
include) can also handle multiple
files, but all files must be of the same (manager specific) output type.
Depending on the selected output format more files can be generated even when only one file name is set. This is the case of XML, which does not allow writing more than one ntuple in a file, and CSV, which is writing each object (histograms, profile or ntuple) in a separate file. The ntuple (or histogram) file name is then generated automatically from the base file name and the ntuple (or histogram) name.
File Directories¶
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 G4AnalysisManager
functions:
SetHistoDirectoryName(const G4String&)
SetNtupleDirectoryName(const G4String&)
The following commands for handling files and directories are available
/analysis/setFileName name # Set name for the output file
/analysis/setHistoDirName name # Set name for the histograms directory
/analysis/setNtupleDirName name # Set name for the histograms directory
Since Geant4 version 11, in case of the Csv output type, which does not support
a directory structure within a file, directories are interpreted as file system directories.
The histogram and ntuple files are saved in directories, if their names are set and
if the directories exist in the file system. If a directory does not exists
(the existence is checked at SetHisto/NtupleDirectoryName()
call),
the histograms/ntuples are written in the current directory and a warning is issued.
Histograms¶
The code for handling histograms given in the following example is extracted the B4 example classes. In this example, the histograms are created in the run action constructor and they are filled in the end of event.
#include "G4AnalysisManager.hh"
RunAction::RunAction()
{
// Create analysis manager
// ...
// Creating histograms
analysisManager->CreateH1("Eabs","Edep in absorber", 100, 0., 800*MeV);
analysisManager->CreateH1("Egap","Edep in gap", 100, 0., 100*MeV);
}
void EventAction::EndOfEventAction(const G4Run* aRun)
{
// Fill histograms
auto analysisManager = G4AnalysisManager::Instance();
analysisManager->FillH1(0, fEnergyAbs);
analysisManager->FillH1(1, fEnergyGap);
}
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 edges 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
Histograms Properties.
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.
All histograms created by G4AnalysisManager
are automatically
deleted with deleting the G4AnalysisManager
object in the end
of the application or by the call to G4AnalysisManager::Clear()
.
Histograms can be also created via UI commands. The commands to create 1D histogram:
/analysis/h1/create # Create 1D histogram
name title [nbin min max] [unit] [fcn] [binScheme]
The commands to create 2D histogram:
/analysis/h2/create # Create 2D histogram
name title [nxbin xmin xmax xunit xfcn xbinScheme nybin ymin ymax yunit yfcn yBinScheme]
The commands to create 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]
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.
Histogram properties can be also defined via UI commands. The commands to define 1D histogram
/analysis/h1/set id nbin min max [unit] [fcn] [binScheme] # Set parameters
The commands to define 2D histogram:
# Set parameters for the 2D histogram of #id
/analysis/h2/set
id nxbin xmin xmax xunit xfcn xbinScheme nybin ymin ymax yunit yfcn yBinScheme
# Set parameters per dimension
/analysis/h2/setX id nbin min max [unit] [fcn] [binScheme] # Set x-parameters
/analysis/h2/setY id nbin min max [unit] [fcn] [binScheme] # Set y-parameters
The commands to define 3D histogram:
# Set parameters for the 3D histogram of #id
/analysis/h3/set =
id nxbin xmin xmax xunit xfcn xbinScheme nybin ymin ymax yunit yfcn yBinScheme nzbin zmin zmax zunit zfcn zBinScheme
# Set parameters per dimension
/analysis/h3/setX id nbin min max [unit] [fcn] [binScheme] # Set x-parameters
/analysis/h3/setY id nbin min max [unit] [fcn] [binScheme] # Set y-parameters
/analysis/h3/setY id nbin min max [unit] [fcn] [binScheme] # Set z-parameters
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);
The corresponding UI commands
/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
The same set of commands is available for the other histogram types and profiles, under the appropriate directory.
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);
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 the Activation of Analysis Objects section.
ASCII option: if activated the histogram is also printed in an ASCII file when Write() function is called.
Plotting option: if activated the histogram is plotted in a file of Postscript format when Write() function is called. See more details in the Plotting section.
File name: if defined, the histogram is written in a new file with the histogram file name which is open at the
Write()
call and then closed with all files open atCloseFile()
call.
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.
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 edges 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 limits will be
considered at filling time. The other parameters in both functions are
optional and their meaning is explained in Profiles Properties.
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 in the end
of the application or by the call to G4AnalysisManager::Clear()
.
Profiles can be also created via UI commands. The commands to create 1D profile
/analysis/p1/create # Create 1D profile
name title [nxbin xmin xmax xunit xfcn xbinScheme ymin ymax yunit yfcn]
The commands to create 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]
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.
Profiles properties can be also defined via UI commands. The commands to define 1D profile
/analysis/p1/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/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
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);
The parameters can be also set via the same set of UI commands as the histogram parameters available under the appropriate directory.
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);
Profiles Properties¶
All histogram features described in the Histograms Properties section are also available for profiles.
Ntuples¶
In the following example the code for handling ntuples extracted from
basic example B4, from the B4::RunAction
and B4a::EventAction
classes, is presented.
#include "G4AnalysisManager.hh"
RunAction::RunAction()
: G4UserRunAction()
{
// Create analysis manager
// ...
// Create ntuple
man->CreateNtuple("B4", "Edep and TrackL");
man->CreateNtupleDColumn("Eabs");
man->CreateNtupleDColumn("Egap");
man->FinishNtuple();
}
void EventAction::EndOfEventAction(const G4Run* aRun)
{
G4AnalysisManager* man = G4AnalysisManager::Instance();
man->FillNtupleDColumn(0, fEnergyAbs);
man->FillNtupleDColumn(1, fEnergyGap);
man->AddNtupleRow();
}
Since 10.0 release, there is no limitation for the number of ntuples
that can be handled by G4AnalysisManager
. Handling of two ntuples is
demonstrated in extended analysis/AnaEx01 example.
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 G4String
type
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
in the end of the application or by the call to G4AnalysisManager::Clear()
.
Since Geant4 11.2 ntuple can be also created via UI commands:
/analysis/ntuple/create name title
/analysis/ntuple/create[I|F|D|S]Column name
/analysis/ntuple/finish
Filling Ntuples¶
The ntuple values of fundamental and string types 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);
// 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);
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.
The FillNtupleXColumn()
functions should not be called for the columns of
vector type, as these are directly associated with the vector reference and so don’t
need to be filled.
When all ntuple columns are filled, the ntuple fill has to be closed by calling
AddNtupleRow()
:
// Methods for ntuple with id = FirstNtupleId
G4bool AddNtupleRow();
// Methods for ntuple with id > FirstNtupleId (when more ntuples exist)
G4bool AddNtupleRow(G4int ntupleId);
Analysis objects handling¶
While the functions for creating and filling analysis objects (histograms, profiles and ntuples) are specific to the object type, the functions for objects access, activation and newly added objects deleting have the same signature for all objects and can be described in a common section.
Accessing Analysis Objects¶
G4AnalysisManager
provides the direct access to the g4tools
histogram, profiles and ntuple objects via their integer identifiers:
tools::histo::h1d* GetH1(G4int id, G4bool warn = true, G4bool onlyIfActive = true) const;
tools::histo::h2d* GetH2(G4int id, G4bool warn = true, G4bool onlyIfActive = true) const;
tools::histo::h3d* GetH3(G4int id, G4bool warn = true, G4bool onlyIfActive = true) const;
tools::histo::p1d* GetP1(G4int id, G4bool warn = true, G4bool onlyIfActive = true) const;
tools::histo::p2d* GetP2(G4int id, G4bool warn = true, G4bool onlyIfActive = true) const;
ntuple_type GetNtuple(G4bool warn = true, G4bool onlyIfActive = true) const;
ntuple_type GetNtuple(G4int id, G4bool warn = true, G4bool onlyIfActive = true) const;
If an object with a given id
is not found, a warning is issued
unless it is explicitly disabled by the user. The id
parameter can be ommitted in GetNtuple
, the analysis manager then returns the first ntuple created. The last optional boolean argument
can be used to choose to get only an active object.
The GetNtuple
return type depends on the choice of the analysis manager type. G4GenericAnalysisManager
(default) returns tools::ntuple_booking*
, that is used to construct ntuples and is common to all managers. The output specific managers return their specific ntuple type.
With using auto
, users need not to declare the g4tools object type explicitly.
In example B4, the g4tools histogram functions mean()
and rms()
are called:
auto 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;
// ...
}
Besides the fast access to analysis objects via their integer identifiers, histograms
and profiles 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;
// etc for H2, H3, P1, P2
This way is however less efficient and it is not recommended for frequently called
functions as e.g. Fill()
.
The list of defined analysis objects can be obtained by the List*()
function
with an optional boolean argument to choose to display only active objects:
G4bool ListH1(G4bool onlyIfActive = true) const;
// etc for H2, H3, P1, P2, Ntuple
or by corresponding UI commands:
/analysis/h1/list [onlyIfActive]
// etc for h2, h3, p1, p2, ntuple
Activation of Analysis Objects¶
The activation option allows the user to activate only selected histograms, profiles or ntuples. When this option is activated, only the analysis objects 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:
auto 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
The activation option is not switched on by default. It has to be
activated either via analysisManager SetActivation(true)
call as
above or via the UI command:
/analysis/setActivation true|false # Set activation option
When no parameters need to be changed a histogram can be activated using “setActivation” command:
/analysis/h1/setActivation id true|false # Set activation to histogram #id
/analysis/h1/setActivationToAll true|false # Set activation to all 1D histograms.
// etc for h2, h3, p1, p2, ntuple
Deleting Selected Analysis Objects¶
Though there is no need for users to take care of memory management of the analysis objects (histograms, profiles and ntuples) as this is completely handled by the analysis manager, since Geant4 11.2, users have a possibility to delete selected objects using the following analysis manager functions:
G4bool DeleteH1(G4int id, G4bool keepSetting = false);
// etc for H2, H3, P1, P2, Ntuple
and corresponding UI commands:
/analysis/h1/delete id [keepSetting]
// etc for h2, h3, p1, p2, ntuple
The integer identifiers of already created objects do not change with deleting selected objects. GetHn|Pn|Ntuple(idx)
function will return nullptr
if the object at the idx
position was deleted. It is under user responsibility to test the returned value before its use. When an analysis manager function is called with idx
of an object that was deleted, a warning is issued, but no segmentation violation error happens.
When a new object is created after some objects were deleted, it gets attributed the first available identifier. If, for example, we create five h1
histograms before Run 0
and
then delete the h1
histograms with id = 2
and id = 4
before Run 1
, and create again two new h1
histograms before Run 2
these new histograms get id = 2
and id = 4
.
If keepSetting
was set to true
, the additional information (object activation, object file name etc.) is kept after object deleting and it is automatically set to the new object created at this id
.
Deleting and re-creating of selected histograms is demonstrated in extended analysis example, AnaEx03.
Plotting¶
For the interactive histograms and profiles plotting available with the Geant4 visualization system see Visualization of histograms (plotting).
In this section we describe how a graphics output file in the Postscript format containing selected histograms and
profiles can be produced with analysis tools (since Geant4 10.2).
The batch plotting can be activated using G4AnalysisManager
functions:
auto analysisManager = G4AnalysisManager::Instance();
analysisManager->SetH1Plotting(id, true);
// etc for H2, H3, P1, P2
or using the UI commands
/analysis/h1/setPlotting id true|false # (In)Activate plottig for 1D histogram #id
/analysis/h1/setPlottingToAll true|false # (In)Activate plotting for all 1D histograms.
# etc. for h2, h3, p1, p2
If Geant4 libraries are built with support for Freetype font rendering, user can choose from three plotting styles:
ROOT_default: ROOT style with high resolution fonts (default)
hippodraw: hippodraw style with high resolution fonts
inlib_default: PAW style with low resolution fonts”)
otherwise only the inlib_default
style with low resolution fonts is
available.
The page size of the graphics output is fixed to A4 format. Users can
choose the page layout which is defined by the number columns and the
number of rows in a page. Depending on the selected plotting style, the
maximum number of plots is limited to 3 columns x 5 rows for the styles
with high resolution fonts and to 2 columns x 3 rows for the
inlib_default
style.
Finally, users can also customize the plot dimensions, which represent the plotter window size (width and height) in pixels.
The customization of the plotting can be done via the UI commands in
/analysis/plot
directory:
/analysis/plot/setStyle styleName
/analysis/plot/setLayout columns rows
/analysis/plot/setDimensions width height
Opening more configuration parameters for users customisation can be considered in future according to the users feedback.
Parallel Processing¶
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, by default, written on separate files, which names are generated automatically from a base file name, a thread identifier and eventually also an ntuple name. Since Geant4 version 10.3 it is possible to activate merging of ntuples with the ROOT output type:
auto analysisManager = G4AnalysisManager::Instance();
analysisManager->SetNtupleMerging(true);
The ntuples produced on workers will be then progressively being merged to the main ntuples on the master.
By default, the ntuples are written at the same file as the final histograms.
Users can also select merging in a given number of files via the optional
parameter of the SetNtupleMerging()
function:
void SetNtupleMerging(G4bool mergeNtuples, G4int nofReducedNtupleFiles = 0);
No merging of ntuples is provided with HDF5, CSV and AIDA XML formats.
Users can override the defaults and change the ntuple merging mode with a dedicated function (since 10.5, with the added second argument in 10.6):
void SetNtupleRowWise(G4bool rowWise, G4bool rowMode = true);
The available merging modes:
column-wise not preserving rows (
rowWise = false, rowMode=false
)The fastest option, but without preserving the ntuple rows after merging.
row-wise (
rowWise = true, rowMode value is not used
)In order to preserve an “event point of view” (the ntuple rows) after merging, a row-wise merging mode was introduced in 10.4 and became a default in 10.5. In this mode, columns are defined as leaves of a single TBranch attached to each ntuple per worker.
This approach has an inconvenience that as column-wise is used in sequential mode and row-wise is used in parallel, the user will have different data schema (different organizations of TBranches and TLeaves) in files, which may complicate his life when reading back his data. While this does not affect a simple analysis using
TTree::Draw("branchName")
, different methods need to be used to access the data per branch. The example macros with a simple analysis are provided in basic examples (for example B4/macros/plotNtuple.C) and a complete access to data is demonstrated in several extended examples (for example medical/dna/dnaphysics/plot.C).column-wise with preserving rows (
rowWise = false, rowMode=true
)The column-wise mode enhanced with preserving the ntuple rows, it became a default in 10.6. It requires larger memory size than the other two modes depending on the users applications.
Users can also change the default values of basket size (32000) and basket entries (4000) using functions (since 10.6).
void SetBasketSize(unsigned int basketSize);
void SetBasketEntries(unsigned int basketEntries);
In previous Geant4 versions the basket size could be set as an optional argument of the SetNtupleMerging
function.
To simplify the scaling of a Geant4 application across nodes on a
cluster Geant4 provides the support of MPI. In particular it is possible
to run a hybrid MPI/MT application that uses MPI to scale across nodes
and MT to scale across cores. This is demonstrated in the extended
example parallel/MPI/exMPI03
which includes usage of Geant4
analysis for histograms.
An example parallel/MPI/exMPI04
, the same as exMPI03 with added ntuple,
shows how to merge, using g4tools, ntuples via MPI in sequential mode,
so that the entire statistics is accumulated in a single output file.
If MT is enabled, the ntuples are merged from threads to files per ranks.
Combined MT + MPI merging is not yet supported.
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, Hdf5, 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
,std::vector<int>
,std::vector<float>
,std::vector<double>
,std::vector<std::string>
Optional directory structure limited to one directory for histograms and/or one for ntuples