Hi Nick, This cannot work with TClonesArray, but works with a normal TObjArray. The logic, however, could be implemented in TClonesArray too. I believe that having a TClonesArray supporting references is much better. Rene Brun Nick West wrote: > > Hi Rene, > > I have to say I am a fan of TClonesArray and your suggestion:- > > > We could may be add a few additional and specialized containers > > "a la TClonesArray". I am thinking to one specially. > > Suppose the frequent case where you have hits/tracks referencing each > > other. Having pointers as data members of the tiny objects may > > induce a big penalty in I/O (4 or 8 bytes required). In case > > you always reference the same list, it may be more clever to store > > only the index inside the list, typically saving a factor 4 or 8 > > in storage. > > is a good one but reminded me of some unfinished business. Earlier this year I > reported a problem with pointers to objects held in TClonesArrays, but got > side-track onto something else. I can still reproduce the problem in that, on > output, all such objects get written twice, and when reinput, the pointer points > to a copy of the object, NOT the one in the TClonesArray. I think the basic > problem is that, in TClonesArray::Streamer, the way objects get written out is > by:- > > fCont[i]->Streamer(b); > > rather than by writing a pointer, so the pointer address is never recorded and > so, when the pointer gets streamed, there is no entry in the map, so it > generates another copy. I have a trivial example that demonstrates this:- > > MyClass.cxx,MyClass.h Define MyClass which has a TClonesArray of MyTrack > MyTrack has a pointer to another MyTrack > > test_write.cxx Creates a TTree with a MyClass branch > Creates a MyClass, prints, fills tree once and > writes tree out. > > rest_read.cxx Opens the file, reads the tree and the first event > Prints it > > In test_write I store 2 MyTracks in the MyClass TClonesArray and point each to > the other. MyClass::Print() asks each MyTrack to print itself:- > > > MyClass 0x1403f4f38 contains: > > > > MyTrack 0x14043ff08 fPx: 1 fPy: 2 fPz: 3 > > Related track: 0x14043ffc8 > > > > MyTrack 0x14043ffc8 fPx: 4 fPy: 5 fPz: 6 > > Related track: 0x14043ff08 > > as you see "Related track" of each points to the other. However, on input in > test_read they don't:- > > > MyClass 0x1404818a8 contains: > > > > MyTrack 0x140480e88 fPx: 1 fPy: 2 fPz: 3 > > Related track: 0x140480ec8 > > > > MyTrack 0x140480f48 fPx: 4 fPy: 5 fPz: 6 > > Related track: 0x140480f08 > > If you, or anyone else, has time to look, here are the files I am using with > Digital UNIX V4.0D (Rev. 878) and Root 2.00/12 > > >>>>>MyClass_LinkDef.h > > #ifdef __CINT__ > > #pragma link off all globals; > #pragma link off all classes; > #pragma link off all functions; > > #pragma link C++ class MyClass; > #pragma link C++ class MyTrack; > > #endif > > >>>>>MyClass.h > > #ifndef MYCLASS > #define MYCLASS > > // Trivial class with TClonesArray and pointer to object it holds. > > #include "Rtypes.h" > > #include "TClonesArray.h" > > class MyClass : public TObject { > > private: > TClonesArray *fMyClonesArray; //This will hold MyTrack objects > > public: > MyClass(); > ~MyClass() {;} > void Build(); > void Print(); > > ClassDef(MyClass,1) //Trivial class > }; > > class MyTrack : public TObject { > > private: > MyTrack *fRelatedTrack; > Float_t fPx; > Float_t fPy; > Float_t fPz; > > public: > MyTrack(); > MyTrack( Float_t px, Float_t py, Float_t pz); > ~MyTrack() {;} > void AddRelatedTrack( MyTrack* t ); > void Print(); > > ClassDef(MyTrack,1) //Trivial track class > }; > > #endif > > >>>>>MyClass.cxx > > #include "MyClass.h" > #include <iostream.h> > > ClassImp(MyClass) > > static TClonesArray *gfMyClonesArray; //This is the permanent copy > > //______________________________________________________________________________ > > MyClass::MyClass() > > { > > // Create permanent TClonesArray if required. > > if ( ! gfMyClonesArray )gfMyClonesArray = new TClonesArray("MyTrack", 2); > fMyClonesArray = gfMyClonesArray; > > } > > //______________________________________________________________________________ > > void MyClass::Build() > > { > > // Store two MyTracks. > > MyTrack *t1 = new( (*fMyClonesArray)[0] ) MyTrack(1.,2.,3.); > MyTrack *t2 = new( (*fMyClonesArray)[2] ) MyTrack(4.,5.,6.); > t1->AddRelatedTrack(t2); > t2->AddRelatedTrack(t1); > > } > > //______________________________________________________________________________ > > void MyClass::Print() > > { > > cout << "MyClass " << this << " contains:" << endl << endl; > MyTrack *t = 0; > for ( Int_t tk_num = 0; tk_num < fMyClonesArray->GetEntriesFast(); tk_num++) { > if ( t = (MyTrack*) fMyClonesArray->At(tk_num) ) t->Print(); > } > > } > > ClassImp(MyTrack) > > //--------------------------------------------------------------- > > MyTrack::MyTrack() > > { > fRelatedTrack = 0; > fPx = 0.; > fPy = 0.; > fPz = 0.; > } > > //--------------------------------------------------------------- > > MyTrack::MyTrack( Float_t px, Float_t py, Float_t pz ) > > { > fRelatedTrack = 0; > fPx = px; > fPy = py; > fPz = pz; > > } > > void MyTrack::AddRelatedTrack( MyTrack* t ) > > { > fRelatedTrack = t; > } > > //--------------------------------------------------------------- > > void MyTrack::Print() > > { > cout << "MyTrack " << this > << " fPx: " << fPx << " fPy: " << fPy << " fPz: " << fPz << endl; > cout << "Related track: " << fRelatedTrack << endl << endl; > > } > > >>>>>test_write.cxx > > #include "TROOT.h" > #include "TFile.h" > #include "TTree.h" > > #include "MyClass.h" > > // Initialize the ROOT system > TROOT root("test_write","Test of TClonesArray I/O with pointers"); > > int main(int argc, char **argv) > { > > TFile *output_file = new TFile( "test.root", "RECREATE"); > > MyClass *myclass = new MyClass; > > TTree *tree = new TTree("T","Test of TClonesArray I/O with ponters"); > Int_t split = 0; > Int_t bsize = 1000; > tree->Branch("myclass", "MyClass", &myclass, bsize, split); > > myclass->Build(); > myclass->Print(); > > tree->Fill(); > output_file->Write(); > output_file->Close(); > > return 0; > } > > >>>>>test_read.cxx > > #include "TROOT.h" > #include "TFile.h" > #include "TTree.h" > > #include "MyClass.h" > > // Initialize the ROOT system > TROOT root("test_read","Test of TClonesArray I/O with pointers"); > > int main(int argc, char **argv) > { > > TFile *input_file = new TFile( "test.root", "READ"); > > MyClass *myclass = new MyClass; > > TTree *tree = (TTree*)input_file->Get("T"); > tree->SetBranchAddress("myclass", &myclass); > > tree->GetEvent( 0 ); > > myclass->Print(); > > input_file->Close(); > > return 0; > }
This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:34:41 MET