// TEventSample.cxx
// Author: Axel Naumann <mailto:axel@fnal.gov> 10/02/2001
//@(#) 10/02/2001
#include "TFile.h"
#include "TChain.h"
#include "TKey.h"
#include "TRandom.h"
#include "TProcessID.h"
#include "TEventSample.h"
#include "TSeed.h"
#include "TProcessEvent.h"
#include "TSeedList.h"
#include <climits>
#include <iostream>
#include <fstream>
Int_t seed::TEventSample::fNumWarnings=0;
Int_t seed::TEventSample::fNumErrors=0;
//_________________________________________________________________________________________________________________________
//
// This class manages the data conversion from n-tuple to class objects as well
// as the data stored in class objects themselves. See the documentation on SEED
//
// A short summary: To work with a seed::TEventSample you have to
// 1) write your own seed (deriving from seed::TSeedABC) which fills data from an n-tuple into a class
// 2) create a seed::TEventSample from an n-tuple calling the seed::TEventSample::Create method using your seed::TSeed's
// 3) load it using the seed::TEventSample::Load method and read its data by means of the seed::TSeedData class
//
ClassImp(seed::TEventSample)
seed::TEventSample::TEventSample():
fTreeEvent(NULL),
fDisableSetEntry(kFALSE),
fNtupleFileName(NULL),
fNtupleID(NULL),
fSeedFileOption("NEW"),
fSAFName("SeedActivation.ini"),
fDebug(gDebug>1?gDebug:1),
fFirstEntry(0),
fNumEntries(-1),
fUserParameter(NULL),
fNtupleTree(NULL),
fSaveSeedData(kTRUE),
fProcessEvent(NULL),
fCrossEventRefs(kFALSE),
fFileCF(NULL)
{
// default constructor. Should only be called before seed::TEventSample::Create.
// Otherwise use the static seed::TEventSample::Load which returns a
// seed::TEventSample*
}
seed::TEventSample::TEventSample(const seed::TEventSample & es)
{
// copy constructor. May not be used, as seed::TEventSample represents one TTree.
// Use multiple references to one seed::TEventSample instead.
Warning("seed::TEventSample::TEventSample(const seed::TEventSample &es)",
"Copy constructor should not be called!");
AddWarning();
}
seed::TEventSample::~TEventSample()
{
// default destructor
if (fFileCF) delete fFileCF;
for (std::map < std::string, TClonesArray * >::iterator iMap =
fMapCA.begin(); iMap != fMapCA.end(); iMap++) {
if (iMap->second != NULL) {
iMap->second->Delete();
}
};
if (fDebug>0) {
std::cout<<"This instances of TEventSample encountered"<<std::endl;
std::cout<<" "<<GetNumErrors()<<" errors and"<<std::endl;
std::cout<<" "<<GetNumWarnings()<<" warnings."<<std::endl<<std::endl;
}
ResetErrorCounter();
}
Bool_t seed::TEventSample::SetEvent(const Int_t iEventIdx)
{
// Sets the event currently accessible by classes deriving from TSeedABC.
// Only to be called when reading data, i.e. not during Create.
//
// Returns kFALSE if the event could not be selected.
//
// Parameters
// iEventIdx: Index of the event to select (see TTree::GetEntry).
if (fDisableSetEntry) {
std::cout << "WARNING in seed::TEventSample::SetEvent(const Int_t): "
<< "This method is currently disabled "
<< "(e.g. because the TEventSample is being created)." << std::endl;
AddWarning();
return kFALSE;
}
if (iEventIdx < 0 || iEventIdx >= GetNEvents()) {
std::cout << "ERROR in TEventSample::SetEvent: Event index " <<
iEventIdx << " out of range!" << std::endl;
AddError();
return kFALSE;
}
if (fTreeEvent) fTreeEvent->GetEntry(iEventIdx);
else return kFALSE;
return kTRUE;
}
TClonesArray * seed::TEventSample::GetClonesArray(const Char_t *strSeed)
{
// returns the address of the TClonesArray corresponding to a given seed / branch
// returns NULL if either the seed is unknown or no events have been read (TClonesArray
// not yet initialized)
//
// Parameters
// strSeed: Name of the Seed / branch
if (fMapCA.find(strSeed) == fMapCA.end())
return NULL; // not a known seed
return (fMapCA[strSeed]);
};
TClonesArray * const* seed::TEventSample::GetCAPtrAddr(const Char_t *strSeed)
{
// Returns the address of the TClonesArray pointer corresponding to a given seed /
// branch. Returns NULL if either the seed is unknown or no events have been read
// (TClonesArray not yet initialized)
//
// Parameters
// strSeed: Name of the Seed / branch
if (fMapCA.find(strSeed) == fMapCA.end())
return NULL; // not a known seed
return &(fMapCA[strSeed]);
};
Int_t seed::TEventSample::GetNumberOf(const Char_t *strSeed)
{
// returns the number of entries of a given seed (branch) in the current event
// returns -1 if the seed/branch does not exist (no entry in fMapCA)
// returns -2 if the seed/branch is not activated or not yet read (fPCAArray's entry is NULL)
//
// Parameters
// strSeed: Name of the Seed / branch
if (fMapCA.find(strSeed) == fMapCA.end())
return -1; // not found
TClonesArray *pCA = fMapCA[strSeed];
if (!pCA)
return -2; // not init
return pCA->GetLast() + 1;
}
Bool_t seed::TEventSample::SetupBranches()
{
// Creates a TClonesArray for each used branch in fTreeEvents and
// enables it via TTree::SetBranchStatus. The user can enable / disable branches
// in the seed activation file
//
// Returns kFALSE is branch setup was not successful
if (!fTreeEvent) {
std::cout<<"ERROR in TEventSample::SetupBranches: "
<< "fTreeEvent is not initialized. This should never happen, "
<< "please contact manufacturer."<<std::endl;
AddError();
return kFALSE;
}
Int_t iNumBranches = fTreeEvent->GetNbranches();
fTreeEvent->SetBranchStatus("*", 0);
for (Int_t iBranch = 0; iBranch < iNumBranches; iBranch++) {
TBranch *pBranch =
(TBranch *) (*(fTreeEvent->GetListOfBranches()))[iBranch];
TString strBranch = pBranch->GetName();
if (TSeedList::GetInstance()->IsSeedEnabled(strBranch)) {
TClonesArray **pCA =
CreateCA(TSeedList::GetInstance()->GetSeed(strBranch));
fTreeEvent->SetBranchStatus(strBranch + "*", 1);
fTreeEvent->SetBranchAddress(strBranch, pCA);
if (fDebug>1)
std::cout << "Told seed "<<strBranch<<" to read its branch."
<< std::endl;
} else if (fDebug>0)
std::cout << "Seed for Branch " << strBranch.Data()
<< " not enabled, skipped." << std::endl;
pBranch->SetAutoDelete(kFALSE);
};
return kTRUE;
}
TClonesArray **seed::TEventSample::CreateCA(seed::TSeedABC * pSeed)
{
// Creates a TClonesArray for the class given by pSeed's seed::TSeedABC::GetClassName
// Internal method.
//
std::string strSN = pSeed->GetName();
if (fMapCA.find(strSN) == fMapCA.end())
fMapCA[strSN] = new TClonesArray(pSeed->GetClassName());
return &(fMapCA[strSN]);
};
Bool_t seed::TEventSample::ParseSeedActivationFile(const Char_t *cSAFName)
{
// With the Seed Activation File (SAF) one can steer which seeds will be
// used in seed::TEventSample::Create() and seed::TEventSample::Load().
// All characters beyond a '#' in a line are ignored. Each word in the file
// outside the comments is assumed to be a seed to be activated.
// If the SAF is not found, all available seeds are activated. If one seed
// given in the SAF is not found (e.g. because it is not #include'd) a
// warning is issued.
//
// This method can be called directly, superseding seeds activated by a
// prior call to ParseSeedActivationFile, e.g. from withing
// seed::TEventSample::Load or seed::TEventSample::Create.
//
// Returns kTRUE if all requested seeds are known
//
// Parameters:
// cSAFName: Path and name of the seed activation file
Bool_t bRet=kTRUE;
// disable all seeds first
TSeedList::GetInstance()->EnableAllSeeds(kFALSE);
if (strlen(cSAFName)==0) {
std::cout << "WARNING in TEventSample::ParseSeedActivationFile: "
<< "No Seed Activation File given. Enabling all available TSeeds."
<< std::endl;
TSeedList::GetInstance()->EnableAllSeeds();
AddWarning();
return kTRUE;
}
std::ifstream fstrSeed(cSAFName);
if (fstrSeed.fail()) {
std::cout << "Warning: TEventSample::ParseSeedActivationFile: Seed Activation File " <<
cSAFName << " not found. Enabling all available TSeeds." << std::endl;
TSeedList::GetInstance()->EnableAllSeeds();
AddWarning();
return kTRUE;
} else
while (!fstrSeed.fail()) {
std::string strSeed;
fstrSeed >> strSeed;
if (strSeed.length() > 0 && strSeed.c_str()[0] != '#') {
if (!TSeedList::GetInstance()->EnableSeed(strSeed.c_str())) {
std::cout <<
"Warning: TEventSample::ParseSeedActivationFile: Seed for object " <<
strSeed.c_str() << " not found. Skipped." << std::endl;
AddWarning();
bRet=kFALSE;
}
}
else fstrSeed.ignore(INT_MAX, 'n'); // ignore until end of line
}
return bRet;
}
Bool_t seed::TEventSample::ShowNtuple(const Char_t *strNTupleFileName,
const Char_t *strNTupleID)
{
// Calls TTree::Print for a given ntuple in a given file.
//
// Parameters
// strNTupleFileName: name of the file containing the n-tuple.
// strNTupleID: name of the n-tuple in the file.
//
TTree* pNtpl=GetNtupleFromFile(strNTupleFileName, strNTupleID);
if (pNtpl) pNtpl->Print();
return (pNtpl!=NULL);
}
TTree* seed::TEventSample::GetNtupleFromFile(const Char_t *cNtupleFileName,
const Char_t *cNtupleID,
Int_t debug)
{
// Extracts the n-tuple from the file and with the key name set by Create
// Internal method.
TFile *fileNTP = TFile::Open(cNtupleFileName, "READ");
if (fileNTP == NULL) {
std::cout <<
"ERROR: TEventSample::GetNtupleFromFile: Severe error trying to open the ntuple input file!"
<< std::endl;
AddError();
return NULL;
}
if (!fileNTP->IsOpen() || fileNTP->IsZombie()) {
std::cout <<
"ERROR: TEventSample::GetNtupleFromFile: Could not open input file '" <<
cNtupleFileName << "'!" << std::endl;
AddError();
return NULL;
}
if (debug>1)
std::cout<<"TEventSample::GetNtupleFromFile: Using file '"
<<cNtupleFileName<<"' as input file."<<std::endl;
TKey *pKey=NULL;
if (!cNtupleID || strlen(cNtupleID)==0)
if (gDirectory->GetListOfKeys()==NULL){
std::cout<<"ERROR in TEventSample::GetNtupleFromFile: No n-tuple ID given "
<<"and no keys in file!"<<std::endl;
AddError();
return NULL;
} else {
TIter next(gDirectory->GetListOfKeys());
TKey* pK;
while (!pKey && (pK = (TKey*) next()))
if (strcmp(pK->GetClassName(),"TTree")==0) {
pKey = pK;
std::cout<<"TEventSample::GetNtupleFromFile: Selected key '"
<< pK->GetName() <<"' as input tree."
<< std::endl;
};
if (!pKey) {
std::cout << "ERROR in TEventSample::GetNtupleFromFile: No key in "
<< "the input file contains an object of type "
<< "TTree. If you want to read an object of a "
<< "type derived from TTree you have to specify "
<< "this object's key name as second parameter "
<< "for Create." << std::endl;
AddError();
return NULL;
};
}
else {
pKey = gDirectory->GetKey(cNtupleID);
if (pKey == NULL) {
std::cout << "ERROR in TEventSample::GetNtupleFromFile: Could not find entry '" <<
cNtupleID << "' in input file!" << std::endl;
AddError();
return NULL;
}
else if (debug>0)
std::cout<<"TEventSample::GetNtupleFromFile: Selected key '"
<<cNtupleID<<"' as input tree."<<std::endl;
};
TObject* pObj = pKey->ReadObj();
if (!pObj) {
std::cout << "ERROR in TEventSample::GetNtupleFromFile: Could not load n-tuple "
<< "from file, although its key exists!" << std::endl;
AddError();
return NULL;
}
if (! pObj->InheritsFrom("TTree")) {
std::cout<<"ERROR in TEventSample::GetNtupleFromFile: Loaded n-tuple key does not "
<<"reference a TTree (or a class deriving from it) but a "
<< pObj->ClassName() <<". Unable "
<<"to handle this object as input."<<std::endl;
AddError();
return NULL;
}
return (TTree *) pObj;
}
TString seed::TEventSample::Ntuple2SeedFileName(const Char_t * strNTupleFileName){
// Given a ntuple file name this method gives a root file name.
// It simply appends "root" to the n-tuple file name - only if the
// ntuple file name already ends on ".root" the resulting filename
// will end on ".seed.root".
// This method is used if SetOutputFileName was not called with a file name
// before Create is called.
TString s = strNTupleFileName;
if (s.Index(".root", 5, s.Length()-5, TString::kExact)!=kNPOS)
s.Insert(s.Length()-5, ".seed");
else s+=".root";
return s;
}
TFile* seed::TEventSample::CreateOutputFile(){
// Creates the output file for the Create method.
// Internal method
//
// It uses the file name given by SetOutputFileName or generates
// it via Ntuple2SeedFileName. It uses TFile::Open with options
// set by SetOutputFileOption. This method deletes all prior
// entries of keys with name "EventSample" from the file!
if (fStrClassFileName.Length()==0)
fStrClassFileName = Ntuple2SeedFileName(fNtupleFileName);
TFile *fileCF =
TFile::Open(fStrClassFileName, fSeedFileOption, "seedTEventSampleFile", 3);
if (fileCF == NULL) {
std::cout <<
"Error: TEventSample::Create: Severe error trying to open the class output file!"
<< std::endl;
AddError();
return NULL;
}
if (!fileCF->IsOpen()) {
std::cout <<
"Error: TEventSample::Create: Could not open file '"
<< fStrClassFileName.Data() <<"' with option '"
<< fSeedFileOption << "'!" << std::endl;
AddError();
return NULL;
}
fileCF->Delete("EventSample;*");
fileCF->Delete("EventSampleTree;*");
return fileCF;
}
seed::TEventSample * seed::TEventSample::Load(const Char_t *strRootFileName, const Char_t* cSAFName)
{
// ===========================================================================================================
//
// Loads a seed::TEventSample created by seed::TEventSample::Create from a file.
//
// Opens a file, extracts the TEventSample and accesses data which belongs to activated seeds
// (as given in the seed activation file, see ParseSeedActivationFile).
//
// Parameters
// strRootFileName: name of the file containing the seed::TEventSample. Can contain
// wildcards for loading multiple files, see TChain::Add for valid syntax
// cSAFName: name of the seed activation file (see ParseSeedActivationFile)
//
// ===========================================================================================================
if (cSAFName) ParseSeedActivationFile(cSAFName);
seed::TEventSample* pEventSample = new TEventSample();
pEventSample->fTreeEvent = new TChain("EventSampleTree",
"TChain generated by the seed library");
((TChain*)pEventSample->fTreeEvent)->Add(strRootFileName);
pEventSample->SetupBranches();
return pEventSample;
}
seed::TEventSample& seed::TEventSample::AddFile(const Char_t* strRootFileName){
// Adds another file for reading. To be call after Load. Syntax for
// strRootFileName is the same as for TChain::Add
//
// Parameters
// strRootFileName: Name of the files to add, for syntax see TChain::Add
if (fTreeEvent->InheritsFrom("TChain"))
((TChain*)fTreeEvent)->Add(strRootFileName);
return *this;
}
Bool_t seed::TEventSample::AddGlobalObject(const Char_t *cName, TObject * pObj)
{
// Adds an object to the file holding the TEventSample during Create phase.
//
// To be called before Create. The object will not be part of the tree.
// It is global and thus independent of the current event / entry in the tree.
// AddGlobalObject creates a new key in the output file, the object will be
// written when the TEventSample is written (within Create).
//
// Parameters
// cName: Name under which the object can be accessed with GetGlobalObject
// (identical with the name of the key created in the output file for
// this object).
// pObj: Pointer to a TObject to be stored in the output file.
fMapGlobalObjects[cName] = pObj;
return true;
}
TObject *seed::TEventSample::GetGlobalObject(const Char_t *cName) const
{
// Returns an entry in seed::TEventSample's file created by AddGlobalObject.
//
// Parameters
// cName: Name of the object as given by AddGlobalObject (identical with its key name)
TObject *pObj = GetCurrentFile()->FindObject(cName);
if (pObj == NULL) {
std::cout <<
"WARNING in TEventSample::GetGlobalObject(const Char_t*): Object named "
<< cName << " not found!" << std::endl;
AddWarning();
}
return pObj;
}
Bool_t seed::TEventSample::Create(const Char_t *cNtupleFileName, const Char_t *cNtupleID){
// ===========================================================================================================
//
// Creates a TEventSample from an ntuple.
//
// See Set-methods for additional initializations of this method. Returns kFALSE if an error occurred.
//
// Parameters
// cNtupleFileName: name of the file containing the n-tuple to be processed
// cNtupleID: optional key name of the n-tuple in the file. If not given (or NULL or ""),
// the first key of type TTree in the file is used.
//
// ===========================================================================================================
fNtupleFileName = cNtupleFileName;
fNtupleID = cNtupleID;
Bool_t bChain=(strchr(cNtupleFileName, '*')!=NULL);
if (bChain) {
if (!cNtupleID || !strlen(cNtupleID)) {
std::cout<<"ERROR in TEventSample::Create: No n-tuple ID given, but"
<<" wildcarding used. Need an n-tuple ID to create a chain!"<<std::endl;
AddError();
fNtupleTree=NULL;
return kFALSE;
} else {
fNtupleTree=new TChain(cNtupleID);
if (fNtupleTree) ((TChain*)fNtupleTree)->Add(cNtupleFileName);
}
} else
fNtupleTree=GetNtupleFromFile(cNtupleFileName, cNtupleID, fDebug);
if (!fNtupleTree) return kFALSE;
Bool_t bReturn=Create(fNtupleTree);
if (bChain) delete fNtupleTree;
return bReturn;
}
Bool_t seed::TEventSample::Create(TTree* pNtupleTree){
// ===========================================================================================================
//
// Creates a TEventSample from an ntuple.
//
// See Set-methods for additional initializations of this method.
//
// Parameters
// pNtupleTree: pointer to a TTree which will be processed by TEventSample.
// This pointer can also be a TChain* as TChain derives from
// TTree, allowing multiple TTrees to be processed.
//
// ===========================================================================================================
if (fFileCF) delete fFileCF;
// remove all CAs
if (fTreeEvent) delete fTreeEvent;
for (std::map < std::string, TClonesArray * >::iterator iMap =
fMapCA.begin(); iMap != fMapCA.end(); iMap++) {
if (iMap->second != NULL) {
iMap->second->Delete();
}
};
fMapCA.clear();
if (fSAFName) ParseSeedActivationFile(fSAFName);
fFileCF = NULL;
if (fSaveSeedData) {
fFileCF = CreateOutputFile();
// fTreeEvent->SetDirectory(fFileCF);
};
fTreeEvent = new TTree("EventSampleTree",
"TEventSample generated by the seed library");
seed::TSeedList *pDFL = seed::TSeedList::GetInstance();
if (pDFL == 0)
return kFALSE;
fNtupleTree = pNtupleTree;
TSingleEntryTree seTree(*fNtupleTree, fUserParameter, &fMapUserParameters);
seTree.SetDebug(fDebug);
fTreeEvent->Reset();
pDFL->StartFillPhase(this, &seTree, fTreeEvent);
fNtupleTree->SetNotify(pDFL);
TSeedList::GetInstance()->Notify();
if (fFirstEntry != 0 && fDebug>0)
std::cout << "Skipping the first "<< fFirstEntry << " ntuple entries..."
<< std::endl;
seTree.SetEntry(fFirstEntry); // to trigger TTree::Notify, TSeedABC::Init
if (strlen(seTree.GetBranchesRead())){
if (fDebug>1) {
std::cout<<"Disableing all branches in input tree."<<std::endl;
std::cout<<"TSingleEntryTree reports branches "
<<seTree.GetBranchesRead()<<" are requested by seeds. Enableing them:"<<std::endl;
}
fNtupleTree->SetBranchStatus("*",0);
TBranch* pB;
TIter nextB(fNtupleTree->GetListOfBranches());
while((pB=(TBranch*)nextB()))
if (seTree.IsBranchRead(pB->GetName())) {
// can't go via pB in case of fNtupleTree being a TChain
fNtupleTree->SetBranchStatus(pB->GetName(),1);
if (fDebug>1)
std::cout<<" - Re-enableing branch '"<<pB->GetName()<<"' in input tree."<<std::endl;
}
}
UInt_t iRefObjects=0;
Bool_t bSaveAnyData=fSaveSeedData;
Bool_t bGetEntrySuccess=kTRUE;
Int_t iEntry = fFirstEntry;
while(bGetEntrySuccess) {
if (!fCrossEventRefs) iRefObjects=TProcessID::GetObjectCount();
bGetEntrySuccess=(seTree.SetEntry(iEntry)>0);
if (bGetEntrySuccess){
pDFL->FillSeeds(iEntry-fFirstEntry);
if (fProcessEvent != NULL) {
fDisableSetEntry = kTRUE;
fProcessEvent->Process(this, iEntry-fFirstEntry);
fDisableSetEntry = kFALSE;
}
if (fSaveSeedData) fTreeEvent->Fill();
bSaveAnyData|=fSaveSeedData;
if (!fCrossEventRefs) TProcessID::SetObjectCount(iRefObjects);
if ((iEntry +1 - fFirstEntry) % 100 == 0 && fDebug>0 || fDebug>2)
std::
cout << "Processed entry " << iEntry+1-fFirstEntry
<< std::endl;
}; // if bGetEntrySuccess
iEntry++;
}
pDFL->GetNumberOfFilledObjects();
pDFL->EndFillPhase();
if (fDebug>0){
std::cout <<"TEventSample::Create generated the following tree:"
<< std::endl;
fTreeEvent->Print();
};
if (bSaveAnyData) {
fFileCF->cd();
Write("EventSample");
fTreeEvent->Write("EventSampleTree");
for (std::map < std::string, TObject * >::iterator iGOMap =
fMapGlobalObjects.begin(); iGOMap != fMapGlobalObjects.end();
iGOMap++)
iGOMap->second->Write(iGOMap->first.c_str());
}
return kTRUE;
}
/********** Initialization methods for Create ***********/
seed::TEventSample& seed::TEventSample::SetSeedActivationFile(const Char_t *cSAF){
// Sets the file to be parsed by ParseSeedActivationFile
fSAFName = cSAF;
if (fTreeEvent) {
// reading mode
ParseSeedActivationFile(cSAF);
SetupBranches(); // update enabled branches
}
return *this;
}
seed::TEventSample& seed::TEventSample::SetOutputFileName(const Char_t *cSeedFileName){
// Sets the file name of the seed data (=output) file. Set the TFile
// option (new / append / recreate) by SetOutputFileOption.
//
// Parameters
// cSeedFileName: Name of the file, see TFile::Open for available syntax
fStrClassFileName = cSeedFileName;
return *this;
}
seed::TEventSample& seed::TEventSample::SetOutputFileOption(const Char_t *cOption){
// Sets the TFile::Open options (new / append / recreate) for the
// seed data (=output) file.
//
// Parameters
// cOption: Options, see TFile::Open
TString strOpt = cOption;
strOpt.ToUpper();
if (!(strOpt == "NEW" || strOpt == "RECREATE" || strOpt == "UPDATE")) {
std::cout <<
"ERROR: TEventSample::SetOutputFileOption: " << fSeedFileOption
<<" is an unknown option for root file creation!"
<< std::endl;
AddError();
}
else fSeedFileOption = cOption;
return *this;
}
seed::TEventSample& seed::TEventSample::SetDebug(const Int_t iDebugLevel){
// Set the debug level for TEventSample. The higher the value, the more
// debug information will be printed out (0 = off). If the value set by
// this method would be lower than the global ROOT gDebug level, ROOT's
// gDebug level is assumed. Defaults to 1.
//
// Debug output for the different debug levels:
// 0: No output, only the used seeds are printed
// 1: 0 + number and type of objects created, Print of resulting tree
// 2: 0+1 + trace of actions taken once for each conversion
// 3: 0+1+2 + trace of actions taken once for each entry
// 4: 0+1+2+3 + trace of actions taken once for each new object
//
// Parameters
// iDebugLevel: level for debug information output.
//
fDebug = (iDebugLevel<gDebug?gDebug:iDebugLevel);
return *this;
}
seed::TEventSample& seed::TEventSample::SetAuthor(const Char_t *cAuthor){
// Sets the author entry in this TEventSample's seed::TEventSampleInfo
// Parameters
// cAuthor: string to be passed to seed::TEventSampleInfo::SetAuthor
fEsInfo.SetAuthor(cAuthor);
return *this;
}
seed::TEventSample& seed::TEventSample::SetFirstEntry(const Int_t iFirstEntry){
// Sets the index of the first entry in the n-tuple to be converted by Create
// Default value: 0
// Parameters
// iFirstEntry: First entry in n-tuple to be converted by Create
fFirstEntry = iFirstEntry;
return *this;
}
seed::TEventSample& seed::TEventSample::SetNEvents(const Int_t iNumEntries){
// Sets the number of entries in the n-tuple file to be converted by Create
// Forwarded to SetNumEntries.
// "-1" means "all". Default value: -1
// Parameters
// iNumEntries: Number of entries in n-tuple file to be converted by
// Create, "-1" means "all"
return SetNumEntries(iNumEntries);
}
seed::TEventSample& seed::TEventSample::SetNumEntries(const Int_t iNumEntries){
// Sets the number of entries in the n-tuple file to be converted by Create
// "-1" means "all". Default value: -1
// Parameters
// iNumEntries: Number of entries in n-tuple file to be converted by
// Create, "-1" means "all"
fNumEntries = iNumEntries;
return *this;
}
seed::TEventSample& seed::TEventSample::SetUserParameter(void* pUserParameter){
// Sets the global "user parameter". It can be retrieved via
// seed::TSingleEntryTree::GetUserParameter(const Char_t*), which is
// accessible e.g. from within seed::TSeedABC::FillSeedData
// Parameters
// pUserParameter: something that the use wants to have passed to seeds
fUserParameter = pUserParameter;
return *this;
}
seed::TEventSample& seed::TEventSample::SetUserParameter(
const Char_t* strSeed, void* pUserParameter){
// Sets the "user parameter" for a given seed. It can be retrieved via
// seed::TSingleEntryTree::GetUserParameter(const Char_t*), which is
// accessible e.g. from within seed::TSeedABC::FillSeedData
// Parameters
// strSeed: name of the seed
// pUserParameter: something that the use wants to have passed to seeds
fMapUserParameters[strSeed]=pUserParameter;
return *this;
}
seed::TEventSample& seed::TEventSample::SetSaveOutput(Bool_t bSave){
// If kTRUE (default), the output generated by Create will be saved to
// file given by SetOutputFile.
//
// Parameters
// bSave: kTRUE if output is to be saved.
fSaveSeedData = bSave;
return *this;
}
seed::TEventSample& seed::TEventSample::SetCrossEventRefs(Bool_t bCER){
fCrossEventRefs=bCER;
return *this;
}
seed::TEventSample& seed::TEventSample::SetProcessEvent(seed::TProcessEventABC *pProcessEvent){
// Sets the class deriving from seed::TProcessEventABC which will be used
// for on-the-fly processing of the generated seed data. This class has to
// be provided by the user, implementing the seed::TProcessEventABC::Process
// method. This method is called after each event that has been processed by
// Create allowing access to the generated seed data via seed::TSeedDataABC
// derived classes (as defined by MAKE_SEED, see seed::TSeedABC).
//
// Parameters
// pProcessEvent: Pointer to a TProcessEventABC derived class
fProcessEvent = pProcessEvent;
return *this;
}
Bool_t seed::TEventSample::ReadSettings(const Char_t *cSettingsFile){
// Loads the settings from a text file to which it was saved by a prior
// call to SaveSettings. These settings will be used for the next Create
// call.
//
// Parameters
// cSettingsFile: name of the file storing settings for Create
static Char_t cSeedFileOption[100];
static Char_t cSAF[1024];
std::ifstream fstr(cSettingsFile);
if (fstr.fail()) {
std::cout << "Warning in TEventSample::SaveSettings: "
<< "Could not open input file '"
<< cSettingsFile << "'." << std::endl;
AddWarning();
return kFALSE;
};
while (!fstr.fail()) {
std::string word;
fstr >> word;
if (word.length() > 0 && word.c_str()[0] != '#') {
if (word.find("SeedFileOption")==0) {
fstr >> word;
if (word==":") fstr>>word;
if (word.find(":")==0) word=word.substr(1);
strcpy((Char_t*) &cSeedFileOption, word.c_str());
fSeedFileOption=(Char_t*) &cSeedFileOption;
std::cout << "SeedFileOption set to '" << fSeedFileOption
<<"'"<<std::endl;
}
else if (word.find("SeedActivationFile")==0
|| word.find("SAF")==0) {
fstr >> word;
if (word==":") fstr>>word;
if (word.find(":")==0) word=word.substr(1);
strcpy((Char_t*) &cSAF, word.c_str());
fSAFName=(Char_t*) &cSAF;
std::cout << "SeedActivationFile set to '" << fSAFName
<<"'"<<std::endl;
}
else if (word.find("Debug")==0) {
fstr >> word;
if (word==":") fstr>>word;
if (word.find(":")==0) word=word.substr(1);
fDebug=atoi(word.c_str());
std::cout << "Debug set to " << fDebug
<<std::endl;
}
else if (word.find("FirstEntry")==0) {
fstr >> word;
if (word==":") fstr>>word;
if (word.find(":")==0) word=word.substr(1);
fFirstEntry=atoi(word.c_str());
std::cout << "FirstEntry set to " << fDebug
<<std::endl;
}
else if (word.find("NumEntries")==0) {
fstr >> word;
if (word==":") fstr>>word;
if (word.find(":")==0) word=word.substr(1);
fNumEntries=atoi(word.c_str());
std::cout << "NumEntries set to " << fDebug
<<std::endl;
}
else if (word.find("SaveSeedData")==0) {
fstr >> word;
if (word==":") fstr>>word;
if (word.find(":")==0) word=word.substr(1);
std::string WORD=word;
if (WORD.find("TRUE")!=std::string::npos
|| WORD.find("true")!=std::string::npos)
fSaveSeedData=kTRUE;
else if (WORD.find("FALSE")!=std::string::npos
|| WORD.find("false")!=std::string::npos)
fSaveSeedData=kFALSE;
else fNumEntries=atoi(word.c_str());
std::cout << "NumEntries set to " << (fNumEntries?"kTRUE":"kFALSE")
<<std::endl;
}
else if (word.find("CrossEventRefs")==0) {
fstr >> word;
if (word==":") fstr>>word;
if (word.find(":")==0) word=word.substr(1);
std::string WORD=word;
if (WORD.find("TRUE")!=std::string::npos
|| WORD.find("true")!=std::string::npos)
fCrossEventRefs=kTRUE;
else if (WORD.find("FALSE")!=std::string::npos
|| WORD.find("false")!=std::string::npos)
fCrossEventRefs=kFALSE;
else fNumEntries=atoi(word.c_str());
std::cout << "CrossEventRefs set to " << (fCrossEventRefs?"kTRUE":"kFALSE")
<<std::endl;
}
}
else fstr.ignore(INT_MAX, 'n'); // ignore until end of line
};
return kTRUE;
}
Bool_t seed::TEventSample::SaveSettings(const Char_t *cSettingsFile){
// Saves all settings set via the seed::TEventSample::Set___ methods
// to a file. These settings can be re-used by ReadSettings.
// Settings that are stored are:
//
// fSeedFileOption (see SetOutoutFileOption)
// fSAFName (see SetSeedActivationFile)
// fDebug (see SetDebug)
// fFirstEntry (see SetFirstEntry)
// fNumEntries (see SetNumEntries)
// fSaveSeedData (see SetSaveOutput)
//
// Parameters
// cSettingsFile: name of the file in which settings should be stored
std::ofstream fstr(cSettingsFile);
if (fstr.fail()) {
std::cout << "Warning in TEventSample::SaveSettings: "
<< "Could not open output file '"
<< cSettingsFile << "'." << std::endl;
AddWarning();
return kFALSE;
};
fstr<<"# "; // to comment first = title line
fstr<<"--- TEventSample initialization settings ---"<<std::endl;
fstr<<" SeedFileOption: " << fSeedFileOption << std::endl;
fstr<< " SeedActivationFile: " << fSAFName << std::endl;
fstr<< " Debug: " << fDebug << std::endl;
fstr<< " FirstEntry: " << fFirstEntry << std::endl;
fstr<< " NumEntries: " << fNumEntries << std::endl;
fstr<< " SaveSeedData: " << (fSaveSeedData?"kTRUE":"kFALSE") << std::endl;
fstr<< " CrossEventRefs: " << (fCrossEventRefs?"kTRUE":"kFALSE") << std::endl;
return kTRUE;
}
seed::TEventSample& seed::TEventSample::PrintSettings(){
// Prints current settings for Create as set by
// seed::TEventSample::Set___ (or their default values).
// These settings will be used in the next call of the Create method.
std::cout<<"--- TEventSample initialization settings ---"<<std::endl;
std::cout<<" SeedFileOption: " << fSeedFileOption << std::endl;
std::cout<< " SeedActivationFile: " << fSAFName << std::endl;
std::cout<< " Debug: " << fDebug << std::endl;
std::cout<< " FirstEntry: " << fFirstEntry << std::endl;
std::cout<< " NumEntries: " << fNumEntries << std::endl;
std::cout<< " SaveSeedData: " << (fSaveSeedData?"kTRUE":"kFALSE") << std::endl;
std::cout<< " CrossEventRefs: " << (fCrossEventRefs?"kTRUE":"kFALSE") << std::endl;
return *this;
}
Bool_t seed::TEventSample::MakeSeed(const Char_t *cNtupleFileName,
const Char_t *cNtupleID,
const Char_t *cBranch,
const Char_t *cSeedName,
const Char_t *cDataClass) {
// Create a seed source and header file nor a given ntuple.
//
// Comments in the form '[[[ TEXT ]]]' will be created in the source to
// show code that needs to be adopted. The created code will not compile
// before these changes are made. The number of changes necessary varies
// depending on the information (number of valid parameters) passed to
// MakeSeed (only two changes in case all parameters are given).
//
// Parameters
// cNtupleFileName,
// cNtupleID: from the file cNtupleFileName, load the ntuple with key
// name cNtupleID (Default for cNtupleID: NULL: load the
// TTree in the file. See GetNtupleFromFile.) All leaves
// of this tree will be available to the seed.
// cBranch: only leaves in this branch will be available to the seed
// (Default: NULL: all branches in ntuple)
// cSeedName: name of the seed that will be created. It reflects both
// class name and file name. (Default: "TMySeed")
// cDataClass: name of the class where the ntuple data should be
// transferred to (data class). (Default: NULL: create
// comments where to change the created skeleton)
//
TTree* pNtpl=GetNtupleFromFile(cNtupleFileName, cNtupleID);
if (pNtpl) return MakeSeed(pNtpl, cBranch, cSeedName, cDataClass);
else return kFALSE;
}
Bool_t seed::TEventSample::MakeSeed(TTree* pNtupleTree,
const Char_t *cBranch,
const Char_t *cSeedName,
const Char_t *cDataClass) {
// Create a seed source and header file nor a given ntuple.
//
// Comments in the form '[[[ TEXT ]]]' will be created in the source to
// show code that needs to be adopted. The created code will not compile
// before these changes are made. The number of changes necessary varies
// depending on the information (number of valid parameters) passed to
// MakeSeed (only two changes in case all parameters are given).
//
// Parameters
// pNtupleTree: if given, all leaves of this ntuple will be available
// to the seed (Default: NULL: generate a skeleton
// independent of leaves)
// cBranch: only leaves in this branch will be available to the seed
// (Default: NULL: all branches in ntuple pNtupleTree)
// cSeedName: name of the seed that will be created. It reflects both
// class name and file name. (Default: "TMySeed")
// cDataClass: name of the class where the ntuple data should be
// transferred to (data class). (Default: NULL: create
// comments where to change the created skeleton)
//
if (!pNtupleTree && cBranch) {
std::cout<<"WARNING in TEventSample::MakeSeed: "
<<"Branch requested but no ntuple given, can't parse "
<<"content of branch without an ntuple. Will create "
<<"empty seed template instead."<<std::endl;
AddWarning();
}
TString strSeedName;
if (cSeedName) strSeedName=cSeedName;
else strSeedName="TMySeed";
std::ofstream fsHeader(strSeedName+".h");
if (fsHeader.fail()) {
std::cout<<"ERROR in TEventSample::MakeSeed: "
<<"failed to open header output file '"
<<strSeedName<<".h' . Maybe the file "
<<"already exists or you don't have write permission. "
<<std::endl;
AddError();
return kFALSE;
}
std::ofstream fsSource(strSeedName+".cxx");
if (fsSource.fail()) {
std::cout<<"ERROR in TEventSample::MakeSeed: "
<<"failed to open source output file '"
<<strSeedName<<".cxx'. Maybe the file "
<<"already exists or you don't have write permission. "
<<std::endl;
AddError();
return kFALSE;
}
// create ifdef include precompiler statement using a unique ID
Char_t cArr[20];
TRandom rnd;
rnd.SetSeed(0);
for (Int_t iChar=0; iChar<19; iChar++)
cArr[iChar]=rnd.Integer(26)+65;
cArr[19]=0;
TDatime datime;
fsHeader<<"#ifndef _INCLUDE__"<<cArr<<std::endl
<<"#define _INCLUDE__"<<cArr<<std::endl
<<std::endl
<<"#include "TSeed.h""<<std::endl
<<"#include [[[ include file for "
<< (cDataClass?cDataClass:"your data class")<<" ]]]"<<std::endl
<<std::endl
<<"// Seed generated by TEventSample::MakeSeed"<<std::endl
<<"// on "<<datime.AsSQLString()<<std::endl;
if (pNtupleTree)
fsHeader<<"// for tree "<<pNtupleTree->GetName()<<std::endl;
if (cBranch)
fsHeader<<"// and only for branch "<<cBranch<<std::endl;
fsHeader<<"class "<<strSeedName<<": public seed::TSeed< "
<<(cDataClass?cDataClass:"[[[ your data class ]]]")
<<" > {"<<std::endl
<<" public: "<<std::endl
<<" "<<strSeedName<<"(seed::TEventSample* pES=NULL): "<<std::endl
<<" seed::TSeed< "
<<(cDataClass?cDataClass:"[[[ your data class ]]]")
<<" > (""<<strSeedName<<"", pES) {}"<<std::endl
<<" virtual ~"<<strSeedName<<"(){}"<<std::endl
<<" Bool_t Init(seed::TSingleEntryTree& tree);"<<std::endl
<<" Bool_t FillSeedData(seed::TSingleEntryTree &tree, "
<<"const Int_t iEventNo);"<<std::endl
<<std::endl
<<" private:"<<std::endl
<<"// data members storing ntuple data of the current event"<<std::endl
<<"// the comments are for your information and not needed by Seed"<<std::endl
<<"// you can remove any member you do not need, as long as you "<<std::endl
<<"// also remove the corresponding Transfer request in the source."<<std::endl
<<std::endl;
fsSource<<"#include ""<<strSeedName<<".h""<<std::endl
<<std::endl
<<"Bool_t "<<strSeedName<<"::Init(seed::TSingleEntryTree& tree) {"<<std::endl
<<"// request data transfer from ntuple to members"<<std::endl
<<std::endl
<<" Bool_t bRet=kTRUE;"<<std::endl;
Bool_t bGeneric = (!pNtupleTree);
if (!bGeneric) {
if (cBranch) {
TBranch *pB=pNtupleTree->GetBranch(cBranch);
if (!pB) {
std::cout<<"WARNING in TEventSample::MakeSeed: "
<<"Branch requested not found in ntuple, can't parse "
<<"content of branch. Will create Seed for"
<<"the complete ntuple instead."<<std::endl;
AddWarning();
cBranch=NULL;
} else
MakeSeed_Branch(fsHeader, fsSource, pB);
}
if (!cBranch) {
TObjArray *branches=pNtupleTree->GetListOfBranches();
if (branches) {
TIter nextB(branches);
TBranch* pB;
while ((pB=(TBranch*)nextB())) {
MakeSeed_Branch(fsHeader, fsSource, pB);
};
} // if valid branches
} // if !cBranch
} // if !bGeneric
/* can't use else, as maybe branches were not found and we want
a template although pNtupleTree was specified */
if (bGeneric) {
fsHeader<<" [[[ Put data members here ]]] "<<std::endl
<<" [[[ One member for each ntuple leaf you want read out ]]] "<<std::endl
<<" [[[ Call TEventSample::MakeSeed with an ntuple to generate this part ]]] "<<std::endl
<<std::endl;
fsSource<<" [[[ Put tree.Transfer calls here ]]] "<<std::endl
<<" [[[ They request members to be updated with ntuple data for each event ]]] "<<std::endl
<<" [[[ Call TEventSample::MakeSeed with an ntuple to generate this part ]]] "<<std::endl
<<std::endl;
} // if bGeneric
fsHeader<<"}; "<<std::endl
<<std::endl
<<" // needed to register this seed with the framework"<<std::endl
<<" namespace { static "<<strSeedName<<" _global_static_"<<strSeedName<<"; } "<<std::endl
<<std::endl
<<"#endif "<<std::endl
<<std::endl;
fsSource<<" return bRet;"<<std::endl
<<"} "<<std::endl
<<std::endl
<<"Bool_t "<<strSeedName<<"::FillSeedData(seed::TSingleEntryTree &tree, "
<<"const Int_t iEventNo) {"<<std::endl
<<"// create objects ";
if (cDataClass) fsSource<<"of type "<<cDataClass<<" ";
fsSource<<"by calling 'NewEntry()' "<<std::endl
<<"// and initialize them using the members that are defined in "<<std::endl
<<"// the header and filled in Init."<<std::endl
<<std::endl;
if (cDataClass) fsSource<<"// Example: "<<std::endl
<<" "<<cDataClass<<"* pEntry = NewEntry();"<<std::endl
<<" pEntry->Set(...);"<<std::endl
<<std::endl;
fsSource<<" return kTRUE;"<<std::endl
<<"} "<<std::endl
<<std::endl;
std::cout<<"Created Seed "<<strSeedName<<" in files "<<strSeedName
<<".h and "<<strSeedName<<".cxx"<<std::endl
<<std::endl;
return kTRUE;
}
TFile* seed::TEventSample::GetCurrentFile() const {
if (fTreeEvent->InheritsFrom("TChain"))
return ((TChain*)fTreeEvent)->GetFile();
else
if (fTreeEvent->GetDirectory())
return fTreeEvent->GetDirectory()->GetFile();
else return NULL;
};
Bool_t seed::TEventSample::MakeSeed_Branch(
std::ofstream &fsHeader, std::ofstream &fsSource,
TBranch* pB) {
// internal method, used by MakeSeed
// creates all entries in fsHeader and fsSource for
// all leafs and branches for current branch
TObjArray* pLeaves=pB->GetListOfLeaves();
if (pLeaves && pLeaves->GetEntriesFast()) {
if (pLeaves->GetEntriesFast()>1){
fsSource<<std::endl;
fsHeader<<" // branch "<<pB->GetName()<<std::endl;
}
if (pLeaves->GetEntriesFast()>1)
fsSource<<" bRet&= tree.SetBranch(""<<pB->GetName()<<"");"<<std::endl;
TIter nextL(pLeaves);
TLeaf* pL;
while ((pL=(TLeaf*)nextL()))
MakeSeed_Leaf(fsHeader, fsSource, pL,
pLeaves->GetEntriesFast());
} // if there are leaves
TObjArray *pBranches=pB->GetListOfBranches();
if (pBranches) {
TIter nextb(pBranches);
TBranch* pIB;
while ((pIB=(TBranch*)nextb()))
MakeSeed_Branch(fsHeader, fsSource, pIB);
}
if (pLeaves && pLeaves->GetEntriesFast()>1){
// top branch
fsSource<<std::endl;
fsHeader<<std::endl;
};
return kTRUE;
}
Bool_t seed::TEventSample::MakeSeed_Leaf(
std::ofstream &fsHeader, std::ofstream &fsSource,
TLeaf* pL, Int_t iNumLeaves) {
TString strLName;
strLName+=pL->GetName();
if (pL->GetBranch()
&& ! strLName.Contains(pL->GetBranch()->GetName()))
strLName.Prepend(pL->GetBranch()->GetName());
strLName.ReplaceAll('.','_');
if (strLName.Data()[0]>='a' && strLName.Data()[0]<='z')
strLName.Replace(0,1,strLName.Data()[0]+64);
strLName.Prepend('f');
TString strType(pL->GetTypeName());
TString strSize;
Int_t iCountVal;
TLeaf* pLC=pL->GetLeafCounter(iCountVal);
// here are the cases:
// leaf; -> pLC==NULL, iCountVal==1;
// leaf[12]; -> pLC==NULL, iCountVal==12;
// leaf[otherleaf]; -> pLC==&otherleaf; iCountVal==1
// leaf[12][otherleaf]; -> pLC==&otherleaf; iCountVal==12
if (pLC || iCountVal>1) strSize="[";
if (pLC) strSize+=pLC->GetName();
else if (iCountVal>1) strSize+=iCountVal;
if (pLC || iCountVal>1) strSize+="]";
// this string is == strLName, expect for leaf[12][otherleaf]:
// to get a * as argument for Transfer we give leaf[0].
TString strLRefName=strLName;
Int_t iSize=1;
// now modify the type in case we have an array
if (pLC || iCountVal>1) {
iSize*=(pLC?pLC->GetMaximum():iCountVal);
strLName+="[";
strLName+=iSize;
strLName+="]";
strLRefName+="[0]";
};
// again, in case we have a 2dim array (fixed second length)
if (pLC && iCountVal>1) {
iSize*=iCountVal;
strLName+="[";
strLName+=iCountVal;
strLName+="]";
strLRefName+="[0]";
};
// assume max len = strlen("Double_t ") == 9
strType.Append(' ', 10-strType.Length());
fsHeader<<strType;
fsHeader<<" "<<strLName<<"; ";
if (strSize.Length()) fsHeader<<"// "<<strSize;
fsHeader<<std::endl;
fsSource<<" bRet&= tree.Transfer("<<strLRefName<<", ""<<pL->GetName();
if (iNumLeaves==1) {
fsSource<<"", "";
if (pL->GetBranch())
fsSource<<pL->GetBranch()->GetName();
else fsSource<<"[[BRANCHNAME]]";
};
fsSource<<"", "<<iSize<<");"<<std::endl;
return kTRUE;
}
Bool_t seed::TEventSample::EnableSeed(const Char_t* cSeed, Bool_t bEnable){
// enables / disables seeds.
// Disableing even works while processing input, it removes
// already existing output by the seed from the output tree
if (!cSeed) return kFALSE;
seed::TSeedList::GetInstance()->EnableSeed(cSeed, bEnable);
// if we already have a tree (which is at least slightly filled) then
// copy only the part of the tree that will be filled by seeds
if (fTreeEvent && !bEnable && fTreeEvent->GetEntries()>0){
fTreeEvent->SetBranchStatus("*",1);
TString strBranch(cSeed);
strBranch+="*";
fTreeEvent->SetBranchStatus(strBranch,0);
TTree* pTemp=fTreeEvent->CloneTree();
delete fTreeEvent;
fTreeEvent=pTemp;
}
return kTRUE;
}
void seed::TEventSample::AddWarning() { fNumWarnings++; }
void seed::TEventSample::AddError() { fNumErrors++; }
Int_t seed::TEventSample::GetNumWarnings() { return fNumWarnings; }
Int_t seed::TEventSample::GetNumErrors() { return fNumErrors; }
void seed::TEventSample::ResetErrorCounter() { fNumWarnings = fNumErrors = 0; }
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.