Re: [ROOT] Making a TTree containing a subset of another TTree...

From: Rene Brun (Rene.Brun@cern.ch)
Date: Tue Aug 13 2002 - 08:45:59 MEST


Hi Steve,

In your attempt to mimic the code of TTreePlayer::CopyTree,
you put code inside the loop that should be outside.
Try the bit of code below

Rene Brun

void OldTree::Loop()
{
   if (fChain == 0) return;

   TFile oFile("newfile.root","recreate"); // Added by Steve
   TTree* newtree = (TTree*)fChain->GetTree()->CloneTree(0);

   Int_t nentries = Int_t(fChain->GetEntriesFast());

   Int_t nbytes = 0, nb = 0, tnumber = -1;
   for (Int_t jentry=0; jentry<nentries;jentry++) {
      Int_t ientry = LoadTree(jentry);
      if (ientry < 0) break;
      nb = fChain->GetEntry(jentry);   nbytes += nb;

      if (tnumber != fChain->GetTreeNumber()) {
         tnumber = fChain->GetTreeNumber();
         fChain->CopyAddresses(newtree);
      }

      if (passAnalysis()) newtree->Fill();
   }

   newtree->Write();
}


On Mon, 12 Aug 2002, Steve Sekula wrote:

> Hello,
> 
> The general question which I am hoping to address is as follows: given 
> an TChain of files, chain, containing a TTree, oldtree, what is the 
> "correct" way to obtain a new tree, newtree, which contains a subset of 
> oldtree's events?
> 
> In my current analysis, I begin with one of the TFiles in the chain, 
> "file.root", and generate a class based off the tree, oldtree, in that file:
> 
>  > TFile f("file.root")
>  > oldtree->MakeClass("OldTree");
> 
> Inside of OldTree.h I define a new method, passAnalysis(), which returns 
> a boolean. I then flesh out this method in OldTree.C, but the bottom 
> line is that it examines the values of branches (and functions of those 
> branches) in the structure of oldtree and decides whether or not to pass 
> the event.
> 
> I then edit the Loop() function and add the following code, so that a 
> new TTree is created from the old one, based on the results of the 
> passAnalysis() method:
> 
> void OldTree::Loop()
> {
>    if (fChain == 0) return;
> 
>    TFile oFile("newfile.root","recreate"); // Added by Steve
>    TTree* newtree; // Added by Steve
> 
>    Int_t nentries = Int_t(fChain->GetEntriesFast());
> 
>    Int_t nbytes = 0, nb = 0;
>    for (Int_t jentry=0; jentry<nentries;jentry++) {
>       Int_t ientry = LoadTree(jentry); //in case of a TChain, ientry is 
> the entry number in the current file
>       if (ientry < 0) break;
>       nb = fChain->GetEntry(jentry);   nbytes += nb;
> 
>       if (jentry == 0) { // Copy the structure of the old tree, added by 
> Steve
>          newtree = (fChain->GetTree())->CloneTree(0);  // added by Steve
>          fChain->CopyAddresses(newtree);               // added by Steve
>       }
> 
>       Bool_t passes = passAnalysis();
>       if (passes) newtree->Fill();
>    }
> 
>    if (newtree) newtree->Write();
>    oFile.Close()
> }
> 
> I then start ROOT and run the code on a TChain of files with _identical_ 
> structure to file.root:
> 
>  > .L OldTree.C;
>  > TChain chain("oldtree");
>  > chain.Add("*.root");
>  > OldTree test(&chain);
>  > test.Loop();
> 
> This then leads to the memory filling extremely rapidly on the host 
> machine (about 5% per second) until I achieve a wonderful segementation 
> violation (long before the completion of the for-loop). However, this 
> method of copying only a subset of interesting events in the tree has 
> worked in the past.
> 
> The first thing that occurred to me was that instead of the above one 
> could use CopyTree and apply it with conditions supplied by TCut 
> objects. However, our current analysis structure is based not just on 
> the values of the branches in the TTree but also on complicated 
> functions derived from those branches which are called by 
> passAnalysis(); it's therefore not a simple matter of using TCut objects.
> 
> It seems like the above procedure - CloneTree(0), copy addresses, and 
> Fill() - ought to work. But it seems to lead to a rapid fill of the 
> system memory and the inevitable crash that results from such behaviour. 
> We are in the process of finding a simple way to migrate to TCut 
> objects, but since this above procedure carried us through ROOT version 
> 3.03.05 (we are now using 3.03.07) it seems it ought to still work.
> 
> So to retiterate my question: (apart from using CopyTree and TCut 
> objects) what is the best/correct way to make a copy of the subset of 
> events in one TTree into another TTree with identical structure?
> 
> Regards,
> Steve Sekula
> 
> 
> 



This archive was generated by hypermail 2b29 : Sat Jan 04 2003 - 23:51:04 MET