Hi Andy, The non-split mode is not implemented for TClonesArray simply because this is totally against the idea of a TClonesArray. You should use a TObjArray if it is your intention to stream the array to one single branch buffer. In this case, for each event, you will spend time in the new/delete process. I have added below two macros showing how to use a TObjarray and one single branch. The advantage of the TClonesArray is more evident when reading from the Tree. You can read about the TClonesArray advantage in the class documentation http://root.cern.ch/root/html/TClonesArray.html I also suggest you read the explanation about the container classes at: http://root.cern.ch/root/Collection1.html ftp://root.cern.ch/root/course2.ps.gz In your example, I assume that you are creating a second branch not connected with the TClonesArray. I agree that the Root code should be protected in case of a non-intended use of the class (TLeafObject::ReadBasket and TClonesArray::Streamer). I will add the protection. Here are the two small macros showing how to use the TObjArray instead; //macro andyWrite.C { gROOT->Reset(); TFile *f = new TFile("andy.root","recreate"); TTree *T = new TTree("T","Andy test"); TObjArray *ar = new TObjArray(1000); T->Branch("myBranch","TObjArray",&ar,32000,0); for (Int_t i=0;i<1500;i++) { Float_t x1 = gRandom->Rndm(); Float_t y1 = gRandom->Rndm(); Float_t x2 = x1+0.5; Float_t y2 = y1+0.5; TLine *line = new TLine(x1,y1,x2,y2); ar->Add(line); T->Fill(); } T->Print(); T->Write(); f->Close(); delete f; } //macro andyRead.C { gROOT->Reset(); TFile *f = new TFile("andy.root"); TTree *T = (TTree*)f->Get("T"); TObjArray *ar = 0; T->SetBranchAddress("myBranch",&ar); Int_t nentries = T->GetEntries(); for (Int_t i=0;i<nentries;i++) { T->GetEntry(i); Int_t nlines = ar->GetEntries(); if(i%100 == 0) printf("i=%d, nlines=%d\n",i,nlines); ar->Delete(); } } Rene Brun Andy Salnikov wrote: > > Hi all, > > yesterday I had a "fun" time, trying to make things work while writing > and reading data in the TTrees. Basically, I needed a collection of > items to be saved as a single object (branch) in the tree. I thought to > use a TClonesArray as a persistent collection, 'cause everyone says that > TClonesArray is superb. Fine. The first thing which I encountered was > that an advertised TTree:Branch("branch",&clonesPtr,xxx,0) for > TClonesArray does not seem to work at all when the splitlevel is zero. > The branch is not get created (at least not in the tree). Is it expected > to be that way? I solved this switching to BranchObject, calling > TTree::Branch("branch","TClonesArray",&clonesPtr,xxx,0). That seemed to > work, but I have been caught by the TTree::Print() output. It gave me > something like that: > > ************************************************************************ > ****** > *Tree :testStream: ROOT output stream > * > *Entries : 1000 : Total Size = 257352 bytes File Size = > 38796 * > * : : Tree compression factor = 6.63 > * > ************************************************************************ > ****** > *Branch :objectBranch : objectBranch > * > *Entries : 1000 : Total Size = 0 bytes File Size = > 0 * > *Baskets : 0 : Basket Size = 32768 bytes Compression= 1.00 > * > *....................................................................... > .....* > *Branch :listBranch : listBranch > * > *Entries : 1000 : Total Size = 257352 bytes File Size = > 38796 * > *Baskets : 8 : Basket Size = 32768 bytes Compression= 6.63 > * > *....................................................................... > .....* > > The first branch seem to have no data at all. That scared me a bit and I > have spend more time trying to figure out what's wrong with my code. I > should not have done it, cause the data were actually there, only the > output was misleading. Increasing number of event 10 times I got the > expected output: > > ************************************************************************ > ****** > *Tree :testStream: ROOT output stream > * > *Entries : 10000 : Total Size = 2861280 bytes File Size = > 434051 * > * : : Tree compression factor = 6.59 > * > ************************************************************************ > ****** > *Branch :objectBranch : objectBranch > * > *Entries : 10000 : Total Size = 255591 bytes File Size = > 40183 * > *Baskets : 9 : Basket Size = 32768 bytes Compression= 6.36 > * > *....................................................................... > .....* > *Branch :listBranch : listBranch > * > *Entries : 10000 : Total Size = 2605689 bytes File Size = > 393868 * > *Baskets : 81 : Basket Size = 32768 bytes Compression= 6.62 > * > *....................................................................... > .....* > > More serious problem was awaiting me when I tried to read back what I > have saved. I got an immediate crash when I tried to read the branch > with the TClonesArray (created as above, in a single branch with > splitlevel=0). After few hour spent in the debugger, I came to what I > think is a bug in the TClonesArray code. The TClonesArray::Streamer() > executes the following two lines: > > fKeep = new TObjArray(nobjects); > Expand(nobjects); > > Expand(), when "nobjects" is less than fSize (and this is the case), > tries to delete the items [nobjects,fSize-1] from fKeep. And it crashes, > just as anyone would expect, 'cause there are no allocated elements in > fKeep behind "nobjects". My guess is that this must be fixed, but I > myself cannot propose any fix, it look a bit complicated stuff for me. > BTW, what is the design issue behind TClonesArray "being" and TObjArray > and "having" TObjArray" at the same time. Is not this unnecessary > complication of the design? > > Cheers, > Andy.
This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:38 MET