As I said, this is a really simple, brute force solution to the problem, and it only seems to work for a single tree.
/*
* and_entry_lists(TEntryList * l1, TEntryList * l2, TTree * t,
* const char * name = 0, const char * title = 0)
* creates a new TEntryList containing only the entries that appear in both
* l1 and l2.
*
* we have to pass the TTree to associate the list with the tree.
*
*/
TEntryList * and_entry_lists(TEntryList * l1, TEntryList * l2, TTree * t,
const char * name = 0, const char * title = 0){
// create the name and title strings for the list to be created
char nbuf[265], tbuf[256];
if (name) strncpy(nbuf, name, 256);
else sprintf(nbuf, "%s_and_%s", l1->GetName(), l2->GetName());
if (title) strncpy(tbuf, title, 256);
else sprintf(tbuf, "%s and %s", l1->GetName(), l2->GetName());
// I don't know if this has any actual effect, but I was getting
// strange results so I figured it couldn't hurt.
t->SetEntryList(0);
// check the current directory to see if a list with this name already exists
TEntryList * l; gDirectory->GetObject(nbuf, l);
if (l) l->Reset(); // if the list already exists, reset it. We're overwriting it.
else l = new TEntryList(nbuf, tbuf, t); // if not, create a new list
// loop over all of the entries of l1
for (int i(0); i < l1->GetN(); i++)
// check if l2 contains the l1 entry with index i
if (l2->Contains(l1->GetEntry(i),t))
// if l2 contains the entry, add it to the new list.
l->Enter(l1->GetEntry(i), t);
return l;
}
I’ve tried another method similar to this, and had similar results. In that method, I cloned l1 and then removed any entry from the clone that is not present in l2.
When these functions operate on TChains, it seems as though they only look at the entries into the first TTree. The first tree’s worth of entries get and-ed, but then it just seems to skip the rest so that the result contains all of the remaining entries in l1 whether they appear in l2 or not. However, looking at the header and source for the TEntryList class, I’m not sure why it doesn’t work. GetN() returns the value of the variable fN, which is always incremented when a new entry is added to the list from any tree, so it should be the total number of entries including entries from all of the associated trees. Supplying a TChain as the second argument to the Contains and Enter functions should make the index relative to the TChain, not a particular TTree in the chain.
(As a side note, I haven’t really tested this theory in great detail. I’ve looked at the number of entries that are in the lists for different trees and done some arithmetic, and it seems about right. I haven’t actually created a minimum example and explicitly verified that this is what is happening.)
The trouble, I think, stems from TEntryList being both a class that contains a list of entries for a TTree, but also a container class for a list of TEntryLists (that are each associated with specific trees) when it is associated with a TChain.
I think that in order to do this properly, one would have to create a function that operates more like the Subtract member function of the TEntryList class (https://root.cern.ch/root/html/src/TEntryList.cxx.html#JrDxj), but this seems to be a lot more effort. The Subtract function searches each list of TEntryLists for TEntryLists that correspond to the same tree, and then operate on those sublists.
I don’t really need a proper solution for my particular problem because both of my lists are derived from the same TChain, so I was really hoping that my quick hack would work.
Any ideas?
–Chad