Find the Index of a TTree entry matching Selection

Hi All,

I’d like to be able to retrieve the index (or an array of indices) of a TTree entry based on a const *char selection. E.G. something of the form:

Long64_t TTree::GetEntryIndex(const *char selection);

Ideally this function would return the index of the TTree entry which pass my selection or a pointer to an array in the case there is more than one.

This seems like it should be implemented so maybe I’m just missing something on the TTree page. If that is the case I’ll appreciate you pointing me in the right direction.

Thanks in Advance.

Okay…well something I just learned is that what I want is called the “Row” of the TTree. So replace all my previous mentions of index/indices with row/rows.

And to be more clear I can use TTree::Scan() to do for example:

root [3] RunTree->Scan("runID","runID==12122019")
************************
*    Row   *     runID *
************************
*      476 *  12122019 *
************************
==> 1 selected entry
(Long64_t)1

I want to retrieve that row number…476 in this case.

I think “Row” in this case is only used for printing the result of TTree::Scan, I don’t think it can be used programmatically. The index you are looking for is a special variable called Entry$, which is just the index of the entry in the TTree (or TChain). You can see other special variables on this page: http://root.cern.ch/root/html/TTree.html if you search for the string “Entry$”.

Now as to getting your list of indexes matching the criteria, I think you can use a “TEntryList” which is an object whose purpose is to store a list of TTree indexes. Again you can search the link above for that string and you’ll find some documentation.

Jean-François

Thanks Jean-François!

These variables are great…I don’t know how I missed them!

Well, perhaps Entry$ wasn’t designed to be used programatically, but one can always hack things together :wink:

This code does exactly what I want for my specific application. It assumes that only one entry in the tree will match the selection criteria. This is clearly a bad assumption in general and this code could be generalized further for a broader application, but since its just a hack for me to accomplish what I want for the moment it’ll work fine.

Long64_t GetTreeIndex(TTree *tree, const char* selection){
  tree->Draw("Entry$>>hist(Entries$,0,Entries$)",selection,"goff");
  TH1I *hist = (TH1I*)gDirectory->Get("hist");
  Long64_t iEntry = hist->GetBinLowEdge(hist->FindFirstBinAbove(0));
  delete hist;
  return iEntry;
}

One strange thing is that “>>hist(Entries$,0,Entries$)” seems to ignore my requested binning structure.

I’m open to more elegant hacks as well…
Cheers,
Chris

Yeah that’s a pretty impressive hack…and I thought I’d done strange things with TTree::Draw.

If it’s ignoring Entries$ for your histogram limits, you could try:

auto nentries = tree->GetEntries();
TString draw_command = TString::Format("Entry$ >> hist(%d,0,%d)",nentries,nentries);
tree->Draw(draw_command,selection,"goff");

I often do that where I construct the TTree::Draw command (or bits of it) using TString::Format.

By the way, if you are compiling code & wish to continue assuming that only one entry passes your selection, you could write a function that loops over the TTree entries the traditional way but returns as soon as it finds the first passing entry. Then if the single passing entry is early in the tree, you won’t waste time looping through the whole thing. If you turn off the un-needed branches and compile your code, it should be as fast as TTree::Draw, probably even faster since you won’t be filling a temporary histogram.

Jean-François