|
//____________________________________________________________________ // // BRAHMS Output Tree Module // // The idea for creating this class was the use of BrTrackTree to create // a usefull output tree. As opposed to BrTrackTree this module does not have // limitations on the kinds of objects included in the tree. One can add all // the kinds of objects that one usually finds in an output BrEvent. After an // analysis session one can use the output tree for easy plotting of distributions // and correlations, e.g. using the TTreeViewer. // // Usage, assuming instance 'mainModule' of BrMainModule is created: // // BrOutputTreeModule* otm = new BrOutputTreeModule("OTM", "Output Tree Module"); // otm->SetIOMode(BrIOModule::kBrJobFile | BrIOModule::kBrRecreateFile); // otm->AddFile("mytree.root"); // otm->AddElement("BrBbVertex", "BB Vertex"); // otm->AddElement("BrFFSTrack", "FFSTrack", kTRUE); // ...<Adding other elements>... // mainModule->AddModule(otm); // // The module distinguishes between two kinds of elements added to it. If the // element does not represent objects in a BrDataTable in the output BrEvent, // a branch for the class given as the first argument in AddElement() is created. // // It the element represents objects found in BrDataTables, e.g. the case for // BrFFSTrack above, a TClonesArray for these objects is instantiated and a branch for // the array is created. This behavior requires the third argument of AddElement()to // be true. For each event the instance of TClonesArray is filled with objects from its // corresponding BrDataTable and the tree is filled. // // To allow the user to create several instances of this class, the name of the tree // includes a number. Thus the first instance of this class creates a tree named 'T1', // the second instance creates a tree named 'T2' and so on. // // Since a branch name in a TTree can not contain blanks, eventual blanks in the // name of objects (second argument in AddElement()) is substituted with underscores. // Thus the element named 'BB Vertex' above will show up in the tree as 'BB_Vertex'. // // Note optional arguments in AddElement() for buffer size and split level. Also note // the possiblity to set the auto save parameter for the tree using SetAutoSave(). // Look for more information obout these parameters in the TTree class descrition and // and in the ROOT User Guide. //____________________________________________________________________ // // $Id: BrOutputTreeModule.cxx,v 1.6 2002/08/15 17:21:35 videbaek Exp $ // $Author: videbaek $ // $Date: 2002/08/15 17:21:35 $ // $Copyright: (C) 2001 BRAHMS Collaboration <brahmlib@rhic.bnl.gov> // #ifndef BRAT_BrOutputTreeModule #include "BrOutputTreeModule.h" #endif #ifndef WIN32 #include <iostream> #include <iomanip> #else #include <iostream.h> #include <iomanip.h> #endif #ifndef ROOT_TMethodCall #include "TMethodCall.h" #endif #ifndef ROOT_TROOT #include "TROOT.h" #endif //____________________________________________________________________ ClassImp(BrOutputTreeElement); //____________________________________________________________________ BrOutputTreeElement::BrOutputTreeElement(const Char_t* className, const Char_t* name, const Char_t* branchName, Bool_t isTable, Int_t arrSize, Int_t bufSize, Int_t splitLevel) : fClassName(className), fName(name), fBranchName(branchName), fIsTable(isTable) { // Named Constructor // If element is data table (isTable == kTRUE), // the name of the table is <name> // Otherwise the name of the object is <name>. // If data table create an instance of TClonesArray // Else set pointer to NULL. If not table no object will be instantiated // and assigned to fStore for this element. if (fIsTable) // Comment by cholm: This is dangerous if the class classname can // have variable size! fStore = new TClonesArray(className, arrSize); else fStore = NULL; fBufSize = bufSize; fSplitLevel = splitLevel; if (fSplitLevel) fBufSize /= 4; } //____________________________________________________________________ BrOutputTreeElement::~BrOutputTreeElement() { // Destructor. Only if this element refers to a data table, and thus an // instance of TClonesArray is allocated, this object will be deleted. if (fIsTable) delete fStore; } //____________________________________________________________________ void BrOutputTreeElement::Branch(TTree* t) { // Create branch in tree t for this element. // Abort if there is no tree if (!t) { cerr << "<BrOutputTreeElement::Branch>: There is no output tree" << endl; return; } // Replace eventual blanks in branch name with underscores. TTree truncates // blanks. TString name(fBranchName); Ssiz_t pos; while ((pos = name.First(" ")) != -1) name.Replace(pos, 1, "_"); // If data table create a TClonesArray branch if (fIsTable) fBranch = t->Bronch(name, "TClonesArray", &fStore, fBufSize, fSplitLevel); // Otherwise create a branch for the object. else { // Add . (dot) to name to make subbranches be named according to //<master branch name>.<subbranch name> name += "."; // Create dummy. TMethodCall* call = new TMethodCall(gROOT->GetClass(fClassName), fClassName, ""); Long_t addr; call->Execute((void*)0, addr); delete call; fStore = (TObject*)addr; // Branch the tree. fBranch = t->Bronch(name, fClassName, &fStore, fBufSize, fSplitLevel); // Delete dummy. delete fStore; } } //____________________________________________________________________ void BrOutputTreeElement::Event(BrEventNode* event) { // Event function. This function is called once per element per // event. If data table the table with name fName is searched for // in the event. If found the TClonesArray is filled. Otherwise the // data object with name fName is searched for in the event. If // found its address is assigned to fStore and the address of the // branch is updated. // Return if no event if (!event) return; // If data table, get table and put tracks into the clones array if (fIsTable) { // Clear the array TClonesArray *arr = (TClonesArray*) fStore; arr->Clear(); // Get data table from event BrDataTable *table = event->GetDataTable(fName); if (!table || !table->GetEntries()) return; // Add entries to clones array Int_t nEntries = table->GetEntries(); const Char_t* cn = fClassName.Data(); Char_t com[512]; for (Int_t iE = 0; iE < nEntries; iE++) { // Perform the following commands for each entry, e.g. for // BrTpcTrackCandidate: // gROOT->Reset(); // BrTpcTrackCandidate* obj // = (BrTpcTrackCandidate*)((BrDataTable*)<tableaddress>)->At(iE); // TClonesArray* arrRef = // *((TClonesArray*)<arr address>); new(arrRef[iE]) // BrTpcTrackCandidate(*obj); #ifdef INTERPETER sprintf(com, "gROOT->Reset();" "%s* dataTable = (%s*)((BrDataTable*)0x%lx)->At(%d);" "TClonesArray& arrRef = *((TClonesArray*)0x%lx);" "new(arrRef[%d]) %s(*dataTable);", cn, cn, (Long_t)table, iE, // arguments of first line (Long_t)arr, // arguments of second line iE, cn); // arguments of third line gROOT->ProcessLine(com); #else // Comment by cholm: You can get a similar effect without // using the interpretor (the gROOT->Reset() is a bit dangerous // here btw.) by using a TBuffer and the class streamers: // Fv 8/14/02: I tried to mplement this because creating rawdata // digitizaed object is horendously slow with the interpreter method // but it seems to fail. Any clues? // YES after resetting the buffer when switching mode it is all ok. // Since the intepreter is not use it is about afactor 100 faster! // TClass* cl = gROOT->GetClass(fClassName); TObject*o = arr->New(iE); TBuffer b(TBuffer::kWrite); TObject * obj = table->At(iE); obj->Streamer(b); b.SetReadMode(); b.SetBufferOffset(); o->Streamer(b); #endif } } // If not data table, get data object and update address in the branch else { // Clear fStore. No object created on the heap, and thus no need for deleting. fStore = NULL; // Get data object. fStore = event->GetObject(fName); if (!fStore) return; // Update the branch address. fBranch->SetAddress(&fStore); } } //____________________________________________________________________ void BrOutputTreeElement::Print() { // Print the parameters of this element to stdout. cout << "| " << setw(28) << fClassName << " | " << setw(23) << fName << " | " << setw(9) << (fIsTable ? "table" : "") << " |" << endl; } //____________________________________________________________________ ClassImp(BrOutputTreeModule); //____________________________________________________________________ BrOutputTreeModule::BrOutputTreeModule() { // Default constructor. DO NOT USE SetState(kSetup); Setup(); } //____________________________________________________________________ BrOutputTreeModule::BrOutputTreeModule(const Char_t* name, const Char_t* title) : BrIOModule(name, title) { // Named Constructor SetState(kSetup); Setup(); } //____________________________________________________________________ BrOutputTreeModule::~BrOutputTreeModule() { // Destructor // Delete elements in array and array itself. Elements are deleted automatically // as the array is owner. delete fElements; // Delete tree. delete fTree; // Close file if still open and delete it. if (fFile->IsOpen()) fFile->Close(); delete fFile; } //____________________________________________________________________ void BrOutputTreeModule::AddElement(const Char_t* className, const Char_t* name, const Char_t* branchName, Bool_t isTable, Int_t arrSize, Int_t bufSize, Int_t splitLevel) { // Add element to be included in tree. // Create array of elements. Make array owner of its elements so that the elements // are deleted when the array is deleted. if (!fElements) { fElements = new TObjArray; fElements->SetOwner(); } // Create element and add to list of elements BrOutputTreeElement *el = new BrOutputTreeElement(className, name, branchName, isTable, arrSize, bufSize, splitLevel); fElements->Add(el); } //____________________________________________________________________ void BrOutputTreeModule::AddElement(const Char_t* className, const Char_t* name, Bool_t isTable, Int_t arrSize, Int_t bufSize, Int_t splitLevel) { // Add element to be included in tree. AddElement(className, name, name, isTable, arrSize, bufSize, splitLevel); } //____________________________________________________________________ Bool_t BrOutputTreeModule::Close() { // Close the file Opened by the object. Return // kFALSE if no file was open. // Return kFALSE if no instance of TFile has been created. if (!fFile) { Failure("Close", "no file opened"); return kFALSE; } // Return kFALSE if file was not opened. if(!fFile->IsOpen()) { Failure("Close", "file not opened"); return kFALSE; } fFile->Write(); fFile->Flush(); fFile->Close(); delete fFile; fFile = NULL; return kTRUE; } //____________________________________________________________________ void BrOutputTreeModule::Event(BrEvent* event) { // Per event method. Info(10 ,"Event", " Start of Event"); SetState(kEvent); // Save current gDirectory and make the file the current directory. TDirectory *saveDir = gDirectory; fFile->cd(); // Check if any of the entries in event is an event node. In that case do a // nested call of this Event function. TIter nextObj(event->GetObjectList()); BrDataObject *dObj; while ((dObj = (BrDataObject*)nextObj())) if (dObj->InheritsFrom("BrEventNode")) Event((BrEvent*)dObj); // Call the event function for all elements. TIter nextEl(fElements); BrOutputTreeElement *el; while ((el = (BrOutputTreeElement*)nextEl())) el->Event(event); // Fill the tree fNumBytesWritten += fTree->Fill(); // Return to saved directory gDirectory = saveDir; gDirectory->cd(); Info(10 ,"Event", "End of Event"); } //____________________________________________________________________ Bool_t BrOutputTreeModule::Open(const Char_t* fname, const Option_t* option) { // Open ROOT file. If no options is specified, open in RECREATE mode. if (!strcasecmp(option, "read")) { Failure("Open", "Cowardly refusing to read histogram files"); return kFALSE; } // Check to see if the a file already exists and is open. if (fFile) if (fFile->IsOpen()) { Stop("Open","File %s is already opened, " "please close before trying to open", fname); return kFALSE; } // Save directory we were in before coming here. TDirectory *saveDir = gDirectory; // Save file name. fFileName = fname; // Get option to open file with. TString fileOption; if (!option) fileOption = "RECREATE"; else fileOption = option; if(DebugLevel() > 3) cout << "File option is " << fileOption.Data() << endl; // Create instance of TFile. if(!fileOption.CompareTo("RECREATE",TString::kIgnoreCase)) fFile = new TFile(fFileName,"RECREATE",fFileName,1); // Check if instance TFile was created. if (!fFile) { Failure("Open", "could not open file %s", fFileName.Data()); gDirectory = saveDir; gDirectory->cd(); delete fFile; fFile = NULL; return kFALSE; } // Check if file was opened. if (!fFile->IsOpen()) { Failure("Open", "could definitely not open file %s", fFileName.Data()); gDirectory = saveDir; gDirectory->cd(); delete fFile; fFile = NULL; return kFALSE; } // Go to the file - which we should be in anyway. fFile->cd(); // Show contents of the toplevel directory . if (DebugLevel() > 3) fFile->ls(); // Set the BrIOModule status variables . fIOStatus = 1; fEof = kFALSE; fError = kFALSE; fNumBytesWritten = 0; fNumBytesRead = 0; SetStatus(kOk); // Create tree. static Int_t treeNum = 1; fTree = new TTree(Form("T%d", treeNum++), "BRAHMS Output Tree"); fTree->SetAutoSave(GetAutoSave()); // Branch the elements. TIter next(fElements); BrOutputTreeElement *el = NULL; while ((el = (BrOutputTreeElement*)next())) el->Branch(fTree); // Go back to old gDirectory. gDirectory = saveDir; gDirectory->cd(); return kTRUE; } //____________________________________________________________________ void BrOutputTreeModule::Print(Option_t* option) const { // Print module information // See BrModule::Print for options. // In addition this module defines the Option: // <fill in here> TString opt(option); opt.ToLower(); BrIOModule::Print(option); if (opt.Contains("d")) cout << endl << " Original author: Jens Ivar Jordre" << endl << " Last Modifications: " << endl << " $Author: videbaek $" << endl << " $Date: 2002/08/15 17:21:35 $" << endl << " $Revision: 1.6 $ " << endl << endl << "-------------------------------------------------" << endl; // Return if no elements. if (opt.Contains("l") && fElements && fElements->GetEntries()) { cout << "+--------------------------------------------------------------------+" << endl << "| BrOutputTreeModule:" << setw(18) << GetName() << " " << setw(30) << GetTitle() << "|" << endl << "+--------------------------------------------------------------------+" << endl; // Call the Print function of all elements. TIter next(fElements); BrOutputTreeElement *el; Int_t ind = 0; while ((el = (BrOutputTreeElement*)next())) el->Print(); cout << "+--------------------------------------------------------------------+" << endl; } } //____________________________________________________________________ void BrOutputTreeModule::SetAutoSave(Int_t autos) { // Set tree autosave parameter. fAutoSave = autos; if (fTree) fTree->SetAutoSave(autos); } //____________________________________________________________________ void BrOutputTreeModule::Setup() { // Setup default parameters. fFile = NULL; fTree = NULL; fAutoSave = 10000000; fElements = NULL; } //____________________________________________________________________ // // $Log: BrOutputTreeModule.cxx,v $ // Revision 1.6 2002/08/15 17:21:35 videbaek // Improved dramatically execution time by getting rid of interpreter and // instead using compiled code. // // Revision 1.5 2001/12/14 15:37:50 cholm // Modified the classes to allow the concept of file set, introduced via // BrIOModule. Also use new Info method rather than explicit // if (Verbose() > 4) // cout << "Opening file ladida" << endl; // // Revision 1.4 2001/11/21 12:57:07 pchristi // Added the oppertunity to set the branchname instead of having classname as branchname. // // Revision 1.3 2001/10/20 20:40:21 jens // Some forgotten fixes. // // Revision 1.2 2001/10/20 20:37:01 jens // Small fixes in the description // // Revision 1.1 2001/10/20 03:44:44 jens // New class BrOutputTreeModule // // |
||||||
This page automatically generated by script docBrat by Christian Holm |
Copyright ; 2002 BRAHMS Collaboration
<brahmlib@rcf.rhic.bnl.gov>
|