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