Re: filtering a tree

T Auger (thauger@phns27.saclay.cea.fr)
Mon, 5 Oct 1998 17:08:48 +0200


Hi Rene,
I tried your suggestion and I still run into the same problem. It
seems related to memory issue since it works when I fill the new tree
with only a few events ~10-20 but it still crashes when I try to call
Draw() after I filled it about 100 times. I did another test directly
with CloneTree (ROOT version 2.11), it gives the same result:

root [0] TFile f("/home/crash30/thierry/run12415/run12415_v1.root");
root [1] TTree *tree = (TTree*)gDirectory->Get("T");
root [2] TClasEvent *event2;
root [3] tree->SetBranchAddress("event",&event2);
root [4] TTree *tree2 = (TTree*) tree->CloneTree(100);
root [5] tree2.Draw("event.Mm_gp()")
Warning in <MakeDefCanvas>: creating a default canvas with name c1
Warning in <TBranchObject::GetBasket>: Estimated keylen too small=2468
Fatal in <operator new>: storage exhausted
aborting

if I try with only 10 events it works...
I am clueless,
Thierry.

Rene Brun writes:
> Hi Thierry,
> In $ROOTSYS/tutorials/copytree.C and copytree2.C, we show
> examples how to copy a subset of a Tree to another file.
> The first part of your macro below preceeding the statement
> TEventList *elist1 = ...
> could be replaced by
> TTree *tree_out = tree->CloneTree(0);
>
> When specifying the argument 0 (number of events to copy),
> CloneTree will only build the new Tree header. You can then
> loop with your EventList to copy only the selected events.
> I do not have the specs of your TClasEvent class.
> It could be that you hit a patological problem that I fixed
> in our development version in TTree::CloneTree.
> The logic in CloneTree now looks like:
>
> // we make a full copy of this tree
> TTree *tree = (TTree*)Clone();
> if (tree == 0) return 0;
>
> tree->Reset();
>
> // copy branch addresses starting from branches
> Int_t i;
> TObjArray *branches = GetListOfBranches();
> Int_t nbranches = branches->GetEntriesFast();
> for (i=0;i<nbranches;i++) {
> TBranch *branch = (TBranch*)branches->UncheckedAt(i);
> if (branch->GetAddress()) {
> tree->SetBranchAddress(branch->GetName(),branch->GetAddress());
> }
> }
> // copy branch addresses starting from leaves
> TObjArray *leaves = GetListOfLeaves();
> TObjArray *tleaves = tree->GetListOfLeaves();
> Int_t nleaves = leaves->GetEntriesFast();
> for (i=0;i<nleaves;i++) {
> TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(i);
> TBranch *branch = leaf->GetBranch();
> if (branch->GetAddress()) {
> tree->SetBranchAddress(branch->GetName(),branch->GetAddress());
> } else {
> TLeaf *leaf2 = (TLeaf*)tleaves->UncheckedAt(i);
> leaf2->SetAddress(leaf->GetValuePointer());
> }
> }
>
> // may be copy some events
> if (nevents < 0) nevents = Int_t(fEntries);
> if (nevents > fEntries) nevents = Int_t(fEntries);
> for (i=0;i<nevents;i++) {
> GetEvent(i);
> tree->Fill();
> }
> return tree;
>
>
> Let me know if this fixes your problem. If it does, then
> I would suggest you replace the bulk of your code by CloneTree(0)
> once the new version 2.00/12 appears.
>
> Rene Brun
>
>
> T Auger wrote:
> >
> > Hi ROOTers,
> > I am trying to copy from an existing tree only a fraction of the
> > events into a new tree. To do this filtering, I would like to be able to use
> > TCut as arguments like when I do a tree.Draw(); so I create an
> > TEventList which I then use to get the events which do satisfy my
> > criteria. I can create a tree but when I try to do a Draw() on this
> > new tree, ROOT bumps with this message:
> >
> > root [3] tree_out.Draw("event.Mm_gp()")
> > Warning in <MakeDefCanvas>: creating a default canvas with name c1
> > Warning in <TBranchObject::GetBasket>: Estimated keylen too small=2468
> > Fatal in <operator new>: storage exhausted
> > aborting
> >
> > I do not understand what's happening. It is quite similar to what's being
> > done in the CloneTree() TTree member function.
> > here is the macro :
> >
> > {
> > gROOT->Reset();
> > TFile f("/home/crash30/thierry/run12415/run12415_v1.root");
> > TTree *tree = (TTree*)gDirectory->Get("T");
> > TTree *tree_out = (TTree*) tree->Clone();
> > TClasEvent *event;
> > Int_t nbytes = 0;
> > Float_t test;
> > tree->SetBranchAddress("event",&event);
> > cout<<" Nentries "<<tree->GetEntries()<<endl;
> > tree_out->Reset();
> > // tree_out->Branch("event", "TClasEvent", &event, 1000,0);
> > // copy branch addresses
> > Int_t i;
> > TObjArray *leaves = tree->GetListOfLeaves();
> > TObjArray *tleaves = tree_out->GetListOfLeaves();
> > Int_t nleaves = leaves->GetEntriesFast();
> > for (i=0;i<nleaves;i++) {
> > TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(i);
> > TBranch *branch = leaf->GetBranch();
> > if (branch->GetAddress()) {
> > tree_out->SetBranchAddress(branch->GetName(),branch->GetAddress());
> > } else {
> > TLeaf *leaf2 = (TLeaf*)tleaves->UncheckedAt(i);
> > leaf2->SetAddress(leaf->GetValuePointer());
> > }
> > }
> >
> > TEventList *elist1 = new TEventList("elist1","test",10000);
> >
> > tree->Draw(">>elist1","event.Mm_gp()>0","",1000);
> > Int_t nentries = elist1->GetN();
> > for (Int_t i=0; i<nentries;i++) {
> > if(i%100 == 0) cout<<"alors"<<endl;
> > nbytes += tree->GetEvent(elist1->GetEntry(i));
> > tree_out->Fill();
> > event->Clear();
> > }
> > }
> >
> > Does anyone see how this could work (or why it doesn't work)?
> > sincerely,
> > Thierry.
>