9.3.  Analysis Reader Classes

The analysis reader classes allow to read in g4analysis objects from the files generated by the analysis manager(s) during processing Geant4 application.

An analysis reader class is available for each supported output format, except for Hbook:

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.

The readers are implemented as singletons. User code will access a pointer to a single instance of the desired reader object. The reader has to be created and deleted from the user code. All objects created via analysis reader are deleted automatically with the manager. The concrete types of the analysis reader 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:

While the histograms and profiles objects handled by the analysis reader are of the same type as those handled by the analysis manager, the redaer's ntuple type is different.

All objects read with G4AnalysisReader (histograms, profiles and ntuples) get automatically attributed an integer identifier which value is returned from the "Read" ot "GetNtuple" function. The default start value is 0 and it is incremented by 1 for each next created object. The numbering each object type is independent from other objects types and also from the numbering of the same object type in analysis manager. The start identifier value can be changed in the same way as with the analysis manager (see Section 9.2.3.1).

The read objects can be accessed in the analysis reader via their integer identifiers or by their names in the same way as in the analysis manager (see Section 9.2.3.4). Note that the type of read ntuple is different from the ntuple type in the analysis manager.

The specific manager classes are singletons and so it is not possible to create more than one instance of an analysis reader of one type, eg. G4RootAnalysisReader. However two analysis reader objects of different types can coexist. Then instead of the generic G4AnalysisReader typedef the concrete type of each manager has to be given explicitly in a similar way as for the analysis managers (see Section 9.2.8).

As well as all other Geant4 categories, the analysis code has been adapted for multi-threading. In multi-threading mode, the analysis reader instances are internally created on the master or thread workers, depending on the client code call, and data reading can be processed in parallel on workers threads.

9.3.1.  Analysis Reader

For reading in the output files created with G4AnalysisManager, an instance of the analysis reader must be created. The analysis reader object is created with the first call to G4AnalysisReader::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.

The example of the code for creating the analysis reader is given below:

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

// Create (or get) analysis reader
G4AnalysisReader* analysisReader = G4AnalysisReader::Instance();
analysisReader->SetVerboseLevel(1);

// code to read data

// Delete analysis reader 
delete G4AnalysisReader::Instance();

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

9.3.2.  Files handling

The name of file to be read can be specified either via G4AnalysisReader::SetFileName() function, or directly when reading an object. It is possible to change the base file name at any time. The analysis reader can handle more than one file at same time.

G4AnalysisReader* analysisReader = G4AnalysisReader::Instance();
// Define a base file name
analysisReader->SetFileName("MyFileName");

The following functions are defined for handling files:

  void SetFileName(const G4String& fileName);
  G4String GetFileName() const;

A file is open only when any "Read" function is called. When more objects are read from the same file (Xml, Root), the file is open only once. When reading an object without specifying the file name explicitly in "Read" call, the object is searched in all open files in the order of their creation time.

9.3.3.  Histograms and Profiles

In the following example the code for reading an histogram is presented.

  // Code to create (or get) analysis reader
  G4AnalysisReader* analysisReader = G4AnalysisReader::Instance();

  // Define a base file name
  analysisReader->SetFileName("MyFileName");
  
  // Read 1D histogram of "Edep" name
  G4int h1Id = analysisReader->ReadH1("Edep");
  if ( h1Id >= 0 ) {
    G4H1* h1 = analysisReader->GetH1(h1Id);
    if ( h1 ) {
      G4cout << "   H1: " 
             << "   mean: " << h1->mean() << " rms: " << h1->rms() << G4endl;
    }  
  }

  // Delete analysis reader 
  delete G4AnalysisReader::Instance();

The histograms and profiles can be read with these G4AnalysisReader functions:

  G4int ReadH1(const G4String& h1Name, const G4String& fileName = "");
  G4int ReadH2(const G4String& h2Name, const G4String& fileName = "");
  G4int ReadH3(const G4String& h3Name, const G4String& fileName = "");
  G4int ReadP1(const G4String& h1Name, const G4String& fileName = "");
  G4int ReadP2(const G4String& h2Name, const G4String& fileName = "");

where hNname is the name of the object to be read from a file. The file name can be defined explicitly for each reading object.

All histograms and profiles created by G4AnalysisReader are automatically deleted with deleting the G4AnalysisReader object.

9.3.4.  Ntuples

In the following example the code for reading ntuples is presented.

  // Code to create (or get) analysis reader
  G4AnalysisReader* analysisReader = G4AnalysisReader::Instance();

  // Define a base file name
  analysisReader->SetFileName("MyFileName");

  // Read ntuple
  G4int ntupleId = analysisReader->GetNtuple("TrackL");; 
  if ( ntupleId >= 0 ) {
    G4double trackL;
    analysisReader->SetNtupleDColumn("Labs", trackL);
    G4cout << "Ntuple TrackL, reading selected column Labs" << G4endl;
    while ( analysisReader->GetNtupleRow() ) {
        G4cout << counter++ << "th entry: "
               << "  TrackL: " << trackL << std::endl;
    }
  }
  
  // Delete analysis reader 
  delete G4AnalysisReader::Instance();

When the ntuple columns are associated with the variables of the appropriate type, the ntuple they can be read in a loop with GetNtupleRow() function. The function returns true until all data are read in.

On overview of all available functions for ntuple reading is given below:

  // Methods to read ntuple from a file
  G4int GetNtuple(const G4String& ntupleName, const G4String& fileName = "");
  
  // Methods for ntuple with id = FirstNtupleId
  G4bool SetNtupleXColumn(const G4String& columnName, Xtype& value);
  G4bool SetNtupleXColumn(const G4String& columnName, std::vector<Xtype>& vector);
  G4bool GetNtupleRow();
  
  // Methods for ntuple with id > FirstNtupleId   
  G4bool SetNtupleXColumn(G4int ntupleId, 
                          const G4String& columnName, Xtype& value);
  G4bool SetNtupleXColumn(G4int ntupleId, 
                          const G4String& columnName, std::vector<Xtype>& vector);
  G4bool GetNtupleRow(G4int ntupleId);

where [X, Xtype] in SetNtupleXColumn() can be [I, G4int], [F, G4float], [D, G4double] or [S, G4String]. The columns of std::vector type are not supported for G4String.

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