BRAT 2.4.5
Class index
Full class index
brahmlib
BRAHMS
ROOT page
//____________________________________________________________________
//
// BrEventNode is a BRAHMS data class providing storage and access
// function for event data information. The data is stored in
// BrDataObject objects that are kept inside a THashList (currently a
// TObjArray). 
//
// This allows modification of the BrEvent content by the user, with
// the BrDataObject providing a standard interface for information
// retrieval, bookkeeping and I/O selection. 
//
// Note that the node own its contained objects.  That is, when the
// node is deleted via a operator delete, the objects contained in the
// class is deleted too, and you can no longer refence that memory.
// See also BrEventNode::~BrEventNode and chapter 8 in [1].
//
// A consideration on owner ship (Christian Holm):
// -----------------------------------------------
// Since the node owns it's refenerenced (or contained) objects, it's
// impossible for a BrModule to have a cache of memory to be reused
// in the event loop.  This is a rather unfortunate sideeffect.  
//
// What we'd like to allow for modules to do, is to create a
// TClonesArray and use that as a memory pool: 
//
//   In BrModule::Init: 
//     
//       fPool = new TClonesArray("BrSomeDataClass"); 
//
// This pool will then be used in the event loop, and references into
// that pool will be put in the node:
//
//   In BrModule::Event(inNode, outNode):
//
//       fPool->Clear(); 
//       ... 
//       BrSomeDataClass* data = 
//         new((*fPool)[fNData++]) BrSomeDataClass();
//       outNode->AddObject(data);
//
// If a module does not want to pool the memory (?), then it must
// explicitly set the kCanDelete bit: 
//
//    In BrModule::Event(inNode, outNode):
//
//       BrSomeDataClass* data = new BrSomeDataClass();
//       data->SetBit(kCanDelete, kTRUE);
//       outNode->AddObject(data);
//
// Ofcourse the data class could per default set that bit. 
// 
// This strategy could significantly speed up the BRAT code, since the
// ::operator new and ::operator delete messages are very expensive
// indeed, which can be circumvented by using a pool of data. 
// 
// The strategy outlined of course requires that BrSomeDataClass is of
// fixed size, that is does not allocate memory, and pointers should
// be non-persistant (requirement of TClonesArray). 
// 
// Since using this strategy has far reaching effects on the code, it
// will not be implmented at this time (Mon Aug 20 16:15:13 2001), but
// _must_ await a consensues decision. 
//
// Side note:
// ----------
// Note the use ofHashTables. This will be most efficient to access
// data by name. This should be chekced out carefully, and performence
// measured. Note this is in fact not the case simple TObjArrays are
// used. 
//
// 
/* 
   References: 

[1] ROOT Users Guide */ // //____________________________________________________________________ // // $Id: BrEventNode.cxx,v 1.3 2001/08/21 16:16:36 cholm Exp $ // $Author: cholm $ // $Date: 2001/08/21 16:16:36 $ // #include "BrEventNode.h" #include "BrDataTable.h" // // Root classes // #include "TBuffer.h" #include "TClass.h" #if ROOT_VERSION_CODE >= ROOT_VERSION(2,25,3) #include "TROOT.h" #endif #include <iostream.h> // Change: // January 6, 1999 FV // Added method // BrRemoveDataObject(object) to enable an easy way of removing // datatables and simpler dataobjects from a node e.g to make a // reduced size output file. Example (without check for existence of // nodes...) // // BrEventNode* fs_node = (BrEventNode*)digitized_node->GetObject("FFS"); // BrDataTable* t1b = digitized_node->GetDataTable("TPCSequence T1B"); // fs_node->RemoveDataObject(t1b); // t1b->Delete(); // // May 17, 2000 FV // Removed entries list in ListObjects-- DataObject do NOT have an entries // method unless they are tables. // // September 19, 2000, Christian Holm // Preprocessor conditional code for ROO 2.25/03 // (IndentLevel => gROOT->IndentLevel etc.) // //____________________________________________________________ ClassImp(BrEventNode); //____________________________________________________________ BrEventNode::BrEventNode() { // Constructor. Set counter and list data members to zero. // Don't use this constructor unless you have to and know // what you are doing // Use BrEventNode(Char_t Name) instead fObjectList = 0; fVerbose = 0; } //____________________________________________________________ BrEventNode::BrEventNode(const Char_t* Name, const Char_t *Title ) : BrDataObject(Name,Title) { // Constructor. Create the hash table // for storing the data objects for this event. Set the // eventnode name fObjectList = 0; fVerbose = 0; } //_______________________________________________________________________ BrEventNode::BrEventNode(const BrEventNode &node) { // Copy constructor. This is done in a simple way for now. // and this will NOT work as defined!!!! // Int_t len = sizeof(BrEventNode); memcpy(this, &node, len); } //_______________________________________________________________________ BrEventNode::~BrEventNode() { // Destructor. Delete BrEventNode and all the data objects currently // owned by BrEventNode. It is assumed but not checked that all // member in the lower nodes are also deleted. // // It's controversial wether we should actually call // TObjArray::Delete here. Maybe a TObjArray::Clear would be // better. if(fObjectList) { fObjectList->Delete(); delete fObjectList; fObjectList = 0; } } //_______________________________________________________________________ void BrEventNode::CheckList() { // Check if list exist. If not, create it. if (!fObjectList) fObjectList = new TObjArray(); } //_______________________________________________________________________ Int_t BrEventNode::AddObject(BrDataObject *object) { // Add a BrDataObejct to the EventNode. The object can be simple, // or an EventNode.. // CheckList(); fObjectList->Add(object); if(fVerbose) cout << "<BrEventNode::AddObject>: Add data Object " << object->GetName() << ", total of " << fObjectList->GetSize() << " objects" << endl; return fObjectList->GetSize(); } //_____________________________________________________________________ BrEventNode* BrEventNode::GetEventNode(const Char_t *name) const { // Return the node named name if(!fObjectList) return 0; //If no list, means nothing in it to get TString n(name); TIter next(fObjectList); BrDataObject *object; while ((object = (BrDataObject*)next())){ // First check if the object really is a BrEventNode (for type // safe returns), and then compare the name. if (object->IsA()->InheritsFrom(BrEventNode::Class()) && !n.CompareTo(object->GetName())) return (BrEventNode*)object; // If the next object is a node, then we search that. In this way, // we recursively search the tree. if(object->IsNode()) { object = ((BrEventNode*)object)->GetEventNode(name); // If the object is found in a sub node, then we return // immediatly. if(object) return (BrEventNode*)object; } } return 0; } //_____________________________________________________________________ BrDataTable* BrEventNode::GetDataTable(const Char_t *name) const { // Get a pointer to a BrDataObject with the given Name in the node // or lower in the tree. Only the first occurence of an object with // a specified name is returned. Recursive calls are made if // EventNodes are part of the list. // if(!fObjectList) return 0; //If no list, means nothing in it to get TString n(name); TIter next(fObjectList); BrDataObject *object; while ((object = (BrDataObject*)next())){ // First check if the object really is a BrDataTable (for type // safe returns), and then compare the name. if (object->IsA()->InheritsFrom(BrDataTable::Class()) && !n.CompareTo(object->GetName())) return (BrDataTable*)object; // If the next object is a node, then we search that. In this way, // we recursively search the tree. if(object->IsNode()) { object = ((BrEventNode*)object)->GetDataTable(name); // If the object is found in a sub node, then we return // immediatly. if(object) return (BrDataTable*)object; } } return 0; } //_______________________________________________________________________ BrDataObject* BrEventNode::GetObject(const Char_t *name) const { // Get a pointer to a BrDataObject with the given Name in the node // or lower in the tree. Only the first occurence of an object with // a specified name is returned. Recursive calls are made if // EventNodes are part of the list. if(!fObjectList) return 0; //If no list, means nothing in it to get TString n(name); TIter next(fObjectList); BrDataObject *object; while ((object = (BrDataObject*)next())){ // Since any object we can add to the node is derived from // BrDataObject, we really don't need to make a type check here. if (!n.CompareTo(object->GetName())) return (BrDataObject*)object; if(object->IsNode()){ object = ((BrEventNode*)object)->GetObject(name); // If the object is found in a sub node, then we return // immediatly. if(object) return object; } } return 0; } //______________________________________________________ void BrEventNode::Clear(Option_t* option) { // Clear internal TObjArray object. That is, remove pointers to // actual objects. The objects are only deleted (memory freed) if // the TObjArray::SetOwner(kTRUE) message has been sent, or the // kCanDelete bit is set (see also the class description). if(fObjectList) fObjectList->Clear(option); } //______________________________________________________ void BrEventNode::ListObjects() const { // List on standard out a summary of BrDataObjects in the // EventNode. The listing is recursive. All levels are scanned. // Depreciated. Use Print instead. if(!fObjectList) return; //no need to print if no object list yet BrDataObject *object; Int_t num = 0; TIter NextObject(fObjectList); while((object = (BrDataObject*)NextObject())) { #if ROOT_VERSION_CODE >= ROOT_VERSION(2,25,3) gROOT->IndentLevel(); #else IndentLevel(); #endif cout << num << " - " << object << " - " << object->GetName() << " - " << object->GetTitle() << endl; if(object->IsNode()){ #if ROOT_VERSION_CODE >= ROOT_VERSION(2,25,3) gROOT->IncreaseDirLevel(); #else IncreaseDirLevel(); #endif ((BrEventNode*) object)->ListObjects(); #if ROOT_VERSION_CODE >= ROOT_VERSION(2,25,3) gROOT->DecreaseDirLevel(); #else DecreaseDirLevel(); #endif } num++; } } //______________________________________________________ void BrEventNode::Copy(BrEventNode &eventnode) { //Copy contents from this into eventnode BrDataObject::Copy(eventnode); eventnode.fVerbose = fVerbose; if(!fObjectList) return; TIter next(fObjectList); BrDataObject* dataObj; while((dataObj = (BrDataObject*)next())) eventnode.AddObject(dataObj); } //________________________________________________________________ void BrEventNode::RemoveDataObject(BrDataObject* object) { // Remove Dataobject from Table, but do not delete obejct. // if(fObjectList) fObjectList->Remove(object); } //________________________________________________________________ BrEventNode& BrEventNode::operator +=(const BrEventNode& node) { // This operator takes matching elements of nodes and adds them // together. The cases when one node has elements that the other // does not is not yet taken into account. // objlist1 is local object list // objlist2 is object list of node we are adding to. // nument1 is number of entries of local object list // nument2 is number of entries of node we are adding to // object1 is object found in local list // object2 is object found in node we are adding to TObjArray *objlist1; TObjArray *objlist2; objlist1 = GetObjectList(); if (!objlist1) return *this; Int_t nument1 = objlist1->GetEntries(); objlist2 = node.GetObjectList(); if (!objlist2) return *this; Int_t nument2 = objlist2->GetEntries(); TObject *object1 = 0; TObject *object2 = 0; for(Int_t i1 = 0; i1 < nument1; i1++) { object1 = objlist1->At(i1); for(Int_t i2 = 0; i2 < nument2; i2++) { object2 = objlist2->At(i2); if(!strcmp(object1->GetName(),object2->GetName())) { // We have found two objects with the same name. Add them // together if (object1->IsA() == BrEventNode::Class()) *(BrEventNode*)object1 += *(BrEventNode*)object2; else if (object1->IsA() == BrDataTable::Class()) *(BrDataTable*)object1 += *(BrDataTable*)object2; #if 0 // I took out this instance, since it seems rediculus to // have a special case for it. else if(object1->IsA() == BrGeantHeader::Class()) // It is not clear to me what to do about BrGeantHeaders // when mixing events. It should be discussed if this // facility is really used. For the moment, I just add // them to the list. How we get them both out will be // another story. this->AddObject((BrDataObject*)object2); #endif else { #ifdef USE_NODE_FULL_CONCAT this->AddObject((BrDataObject*)object2); #else cout << "Object found in EventNode " << node.GetName () << " is off class " << object1->IsA()->Class_Name() << "." << endl << "There is no support for it yet, " << "please see your BRAT manager" << endl; #endif } // Break out of this loop, cause we found machting objects. // Zero the thing, so that we know if the object was found of // not. object2 = 0; break; } } } return *this; } //________________________________________________________________ void BrEventNode::Browse(TBrowser* b) { if(!fObjectList) return; TIter next(fObjectList); TObject* obj; while((obj = next())) b->Add(obj); } //________________________________________________________________ void BrEventNode::Print(Option_t* option) const { // Print all contained objects, passing the option along. // Options: // R Recursive print [Default] // See also BrDataObject::Print BrDataObject::Print(option); if(!fObjectList) return; //no need to go further if no object list. TString opt(option); opt.ToLower(); if (opt.Contains("r")) { gROOT->IncreaseDirLevel(); TIter next(fObjectList); TObject *obj = 0; while((obj = next())) { gROOT->IndentLevel(); obj->Print(option); } gROOT->DecreaseDirLevel(); } } //________________________________________________________________ BrEventNode& operator+(const BrEventNode& node1, const BrEventNode& node2) { // This operator takes matching elements of nodes and adds them // together. The cases when one node has elements that the other // does not is not yet taken into account. TObjArray *objlist1,*objlist2; objlist1 = node1.GetObjectList(); Int_t nument1 = objlist1->GetEntries(); objlist2 = node2.GetObjectList(); Int_t nument2 = objlist2->GetEntries(); BrEventNode *tmp = new BrEventNode(node1.GetName()); if(objlist1) { for(Int_t i1=0;i1<nument1;i1++) { TObject *object1 = objlist1->At(i1); for(Int_t i2=0;i2<nument2;i2++) { TObject *object2 = objlist2->At(i2); if(!strcmp(object1->GetName(),object2->GetName())) { // We have found two objects with the same name. Add them // to the output event if(!strcmp(object1->IsA()->GetName(),"BrEventNode")) { BrEventNode *tmpnode = new BrEventNode(*(BrEventNode*)object1 + *(BrEventNode*)object2); tmp->AddEventNode(tmpnode); } else if(!strcmp(object1->IsA()->GetName(),"BrDataTable")) { BrDataTable *tmptable = new BrDataTable(*(BrDataTable*)object1 + *(BrDataTable*)object2); tmp->AddDataTable(tmptable); } else if(!strcmp(object1->IsA()->GetName(),"BrGeantHeader")) { // It is not clear to me what to do about BrGeantHeaders // when mixing events. It should be discussed if this // facility is really used. For the moment, I just add // them to the list. How we get them both out will be // another story. tmp->AddObject((BrDataObject*)object1); tmp->AddObject((BrDataObject*)object2); } else { cout<< "Object found in EventNode " << node1.GetName() << " is " <<object1->IsA()->GetName() << "." <<endl; cout<<"There is no support for it yet, " "please see your BRAT manager"<<endl; } } } } } return *tmp; } //____________________________________________________________________ BrEventNode& BrEventNode::operator=(const BrEventNode &rhs) { // BrEventNode assignment operator. // This is done with a simple memcpy for the moment. if (this != &rhs) { Int_t len = sizeof(BrEventNode); memcpy(this,&rhs,len); } return *this; } //____________________________________________________________ BrEventNode & BrEventNode::operator=(const BrEvent &rhs) { // BrEvent to BrEventNode assignment operator. cout<< "Inside assignment of BrEvent to BrEventNode. " << "Should we be here? see BRAT manager" << endl; return *this; } /* //______________________________________________________________________________ void BrEventNode::Streamer(TBuffer &R__b) { // Stream an object of class BrEvent. if (R__b.IsReading()) { Version_t R__v = R__b.ReadVersion(); BrDataObject::Streamer(R__b); R__b >> fVerbose; R__b >> fObjectList; } else { R__b.WriteVersion(BrEventNode::IsA()); BrDataObject::Streamer(R__b); R__b << fVerbose; // make a temporary hashtable for the objects marked // as persistent and store only those in the output // buffer. Since this is a node iterative calls should probably be // implemented. What has to be done for BrEvent that is a derived // Class ? // TObkArray *temp = new TObjArray(); TIter NextObject(fObjectList); TObject *obj; while(obj = NextObject()) { temp->Add(obj); } R__b << temp; temp->Clear(); delete temp; } } */ // $Log: BrEventNode.cxx,v $ // Revision 1.3 2001/08/21 16:16:36 cholm // Added method CheckLis for on-demand allocation. // Added some more documentation. // Added type-safety to GetDataTable, GetEventNode methods. // // Revision 1.2 2001/08/08 21:52:08 hagel // Eliminate memory leak by creating on demand fObjectList and fEventHeader // // Revision 1.1.1.1 2001/06/21 14:54:58 hagel // Initial revision of brat2 // // Revision 1.25 2001/06/01 15:46:54 cholm // Fixed creation id class to be more clean. Now sets the user name // (if avaliable) has a Print method. // PRint method in BrDataObject. // Print method in BrDataTable // Print method in BrEvent // Print method in BrEventNode // // Revision 1.24 2000/10/03 19:29:59 cholm // Made IsFolder() const (since it is in TObject) which was needed for the // objects to be browsable. Aslo, as of ROOT version 2.25.02 there's a list // of special objects, which BrEventIO now is added to. Some doc to // BrEventNode::Clear() added! Added method BrEventNode::SetOwner(). // Christian Holm // // Revision 1.23 2000/09/19 11:34:17 cholm // Since TObject::IndentLevel() is moved to TROOT::IndentLevel(), and similar // for TObject::IncreaseDirLevel(), and TObject::DecreaseDirLevel() as of // ROOT 2.25.03, I've made these corrections, conditional on the ROOT version // of course. // // Revision 1.22 2000/06/15 14:17:04 alv // Made more of the Get-methods const member functions // // Revision 1.21 2000/06/03 18:20:48 videbaek // Maded BrEbentIO derice from BrModule and related changes. // // Revision 1.20 2000/05/18 20:25:40 videbaek // Removed flawed usage of Brdataobject->GetEntries() in listobjects. // // Revision 1.19 2000/05/17 10:36:23 ouerdane // see top of file // // Revision 1.18 2000/04/13 00:02:29 cholm // Added methods for browsing BrEvents, either directly or via // a BrEventIO. Also added method GetROOTFile to BrEventIO. // // Revision 1.17 2000/01/07 01:29:44 videbaek // Added RemoveDataObject.1 // // Revision 1.16 2000/01/06 16:03:03 videbaek // Added method RemoveDataObject(object) // // Revision 1.15 1999/12/30 19:43:09 videbaek // imple cleanup of code // // Revision 1.14 1999/09/13 21:06:51 videbaek // Modify constructor to deal properly with Title param // // Revision 1.13 1999/06/01 20:38:31 hagel // Added GetEventNode(...) // // Revision 1.12 1999/05/12 16:22:21 hagel // Implemented + , =+ and = operators for BrEventNode. These will be useful // for adding events together. Has been tested for single pion events and seems // to work. In the course of implementing this, several conflicts with const were // identified. These were cleaned up by adding appropriate const's where needed. // It was checked that it did not break other things. // // Revision 1.11 1999/03/07 00:00:42 hagel // // Revision 1.10 1998/08/27 21:31:39 hagel // Change Copy to copy from this to object // // Revision 1.9 1998/08/20 14:28:18 hagel // Add Copy method + cleanup // // Revision 1.8 1998/08/14 21:26:25 videbaek // Some cleanup mods // // Revision 1.7 1998/08/05 15:40:29 hagel // Add Clear to BrEventNode // // Revision 1.6 1998/07/03 16:01:53 hagel // Clean up g++ warnings // // Revision 1.5 1998/04/30 17:12:18 videbaek // Added functionality to BrIOModule // // Revision 1.3 1998/03/09 20:53:50 videbaek // Ensure that pointers are non-NULL before deleting // // Revision 1.2 1998/03/06 22:09:59 videbaek // Working update // // Revision 1.1.1.1 1998/03/04 21:32:48 brahmlib // Brat base

This page automatically generated by script docBrat by Christian Holm

Copyright ; 2002 BRAHMS Collaboration <brahmlib@rcf.rhic.bnl.gov>
Last Update on by

Validate HTML
Validate CSS