Friend Propagation with CopyTree

My question is about tree friending propagating through TTree::CopyTree, however maybe my fundamental approach is wrong and this can be avoided.

Currently I have some detector data, which is held in a file (data.root), which has one tree (DataTree), with one branch (event) which is a custom class holding all of my event information (timestamp, energy, waveform, etc). Because I don’t want to risk corrupting my raw data, when I do analysis, I run some algorithm on each event and output the results to branch(es) in a separate tree (AnalysisTree1) in a separate file (analysis1.root). This makes it simple to open both files (as read), friend the trees, and call DataTree->Draw() using cuts on AnalysisTree branches to make plots. I can keep adding analysis by adding AnalysisTree2 and analysis2.root and friend/draw similarly. This has worked fine up until now.

Now I want do something a bit more complicated - I want to fill a histogram using values from the original tree (DataTree) and both the analysis trees (AnalysisTree1 and AnalysisTree2). Typically I would call Draw() on the friended tree and that’d be it; however, I have the additional requirement that I need to keep track of how many times I fill each bin for averaging purposes - as far as I know, there is no simple way to do this except with something like this:

vector<int> hits(binsx*binsy); // Being careful to include underflow/overflow
int bin = hPlot->Fill(val1, val2, weight);
hits.at(bin)++;

Then I can go back later and loop over hPlot->GetSize() (again being careful to account for underflow/overflow) and

for(k=0;k<hPlot->GetSize();k++) {
  if(hits.at(k) != 0)
    hPlot->SetBinContent(k, hPlot->GetBinContent(k)/hits.at(k));
  }

The problem is that I need to actually get val1 (from DataTree), val2 (from AnalysisTree1) and weight (from AnalysisTree2), so I must SetBranchAddress(); but I only want to make this plot for a subset of events determined by a TCut since I’m cutting on many branches across the different trees. If I do this:

TTree *tSelection = DataTree->CopyTree(someCut);

This gives me the original data tree appropriately cut, but doesn’t give me the analysis trees which were friended before CopyTree(); if I want to SetBranchAddress and pull out these values, I must:

AnalysisTree1->AddFriend(DataTree);
TTree *tSelection2 = AnalysisTree1->CopyTree(someCut);
// ... then later, when I want to loop
for(i=0;i < tSelection->GetEntries();i++) {
  tSelection->GetEntry(i);
  tSelection2->GetEntry(i);
  // Do some stuff
}

using the same exact cut for each analysis tree I’m interested in. This “works” but I end up calling CopyTree() 3+ times just to get the friends, and since I’m cutting on 10s of millions of events and over a dozen of branches, each call takes awhile. CopyTree() with an option to propagate to friend trees seems like the simplest solution here, as opposed to coming up with a scheme to apply my cuts to produce extra, shorter data files (taking more HD space) so that CopyTree() isn’t necessary, but it’s far from ideal, since it will pretty much remove the flexibility I get using TCut in the first place.
Thanks!

Hi,

Instead of calling CopyTree, you ought to create a TEntryList that will allow you to filter the original trees without having to copy them at all … TTree::Draw can be used to produce those TEntryList from the cuts.

Cheers,
Philippe.