Re: filtering a tree

Rene Brun (Rene.Brun@cern.ch)
Wed, 30 Sep 1998 09:23:33 +0200


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.