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