where copyRootTree is a separate function that acts on a tree calling functions such as GetListOfLeaves and other chain/tree type methods.
I would have though chain->SetEntryList(elist,"ne"); would have been enough to make sure the new event list is looped on instead of the old one, however the output looks something like this:
new list entries = 3207
old chain entries = 3324
events processed: 0 (0% of 3324)
events processed: 1000 (30% of 3324)
events processed: 2000 (60% of 3324)
This is what I suspected, but I hoped I was doing some stupid mistake.
We do the typical tree.GetEntries to loop. But also things like tree.GetListOfLeaves which get used quite a bit.
I was hoping to avoid rewriting a whole class just to account for the case where someone wants to add a TCut selection.
Is there anyway to force the new selection to propagate to a ttree with the ability to use all methods?
You can ‘simply’ update your existing code to read:
auto filteredEntry = tree->GetEntryNumber( entrynumber ); // If no entry list, this will return 'entrynumber'
auto localEntry = tree->LoadTree( filteredEntry );
Is there some way to do this without creating an entry list? Ideally we could define the cut using the same kind of expressions we pass to TTree::Draw and then check whether entries pass the cut in the loop.
The issue is that in this method, we loop over all the data files twice: once to define the entry list and again to read the entries we actually want.
We’re often running over a chain of many files, so I’m not sure whether this is what we want. Where does the copy of the tree go? Will it try to load the whole chain into memory?
@pcanal, what we’re really looking for (which doesn’t exist, that I know of) is something like this
TCompiledCut cut(some_tcut_string);
int entries = tchain->GetEntries();
for (int entry = 0; entry < entries; entry++) {
tchain->GetEntry(entry);
if (!cut(tchain)) continue;
// do things
}
i.e. we want a way to test one entry to see if it passes the cut, preferably one which doesn’t load the whole chain into memory or require us to loop over the chain twice.
We don’t want to use a TDataFrame for this. But it looks like the following should work:
// this function is defined somewhere
bool pass(TTreeFormula* cut) {
if (!cut) return true;
cut->UpdateFormulaLeaves();
Int_t ndata = cut->GetNdata();
for(Int_t current = 0; current < ndata; current++) {
if (cut->EvalInstance(current) == 0) return false;
}
return true;
}
// and then we define the cut
TTreeFormula* cut = new TTreeFormula("Selection", selection, chain);
// and in the event loop, call
if (!pass(cut)) continue;
@pcanal, there’s a lot of other stuff going on in the code you pointed to, but I think this is all we need, correct?
This looks fine. Note that UpdateFormulaLeaves needs to be called ‘only’ at the file boundary of a TChain (hence the somewhat complex test surrounding it in the original code); doing it ‘too often’ would hurt the result but will be slower.