Re: filtering a tree

From: Rene Brun (Rene.Brun@cern.ch)
Date: Wed Sep 30 1998 - 09:23:33 MEST


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.



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:34:38 MET