Speed up TTree Draw

I have a fairly large TTree, and I want to select only events within a specific, relatively small, time interval using TTree->Draw(">>elist", "abs(t-offset) <= 10") where offset is some number. I want to do this for many different offsets, so having it be quick is important. I know the data in the tree is sorted by time, so is there any way to use that to speed this up, or will I have to resort to just using a for loop to get the job done (for instance stopping the search after a time after the maximum allowed time is found)

Thanks!


ROOT Version (e.g. 6.13/01):
Platform, compiler (e.g. Ubuntu 16.04, gcc5.4):


Hi,
TTree::Draw offers a very handy syntax, but it will perform one loop over the dataset per histogram created, by design.

To get serious speed-ups, you would need to fill all your histograms in the same event loop.
Recent versions of ROOT offer an interface that solves precisely this problem (and a few more): TDataFrame.

Here’s one way to fill different histograms for different values of offset.

#include <ROOT/TDataFrame.hxx>
using namespace ROOT::Experimental; // TDataFrame lives here (until v6.14)

int macro() {
  TDataFrame d(treename, filename);
  // Your result histograms. TDF returns TResultProxy<Obj> from methods that will produce an Obj. 
  std::vector<TDF::TResultProxy<TH1D>> histos;
  for (const auto offset : {1, 2, 3}) {
     // fill an histogram with values of variable "x", for events that pass the Filter
     // this Filter returns `true` (pass) when `std::abs(t - offset) <= 10`, assuming "t" is the time variable in your tree
     auto h = d.Filter([offset] (double t) { return std::abs(t - offset) <= 10; }, {"t"}).Histo1D<double>("x");
     histos.push_back(h);
  }

  histos[0]->Draw(); // accesing a result! the event loop is triggered and all registered histograms are filled.

  return 0;
}

Note that, by design, TDataFrame only fills (all) your results when you access any of them for the first time, so here only one event loop is performed, and it is triggered by the last line.

Feel free to ask if something of the snippet above is not clear.
If you want TDataFrame to read the data and fill the histograms from multiple threads (for extra speed), just add ROOT::EnableImplicitMT() at the beginning of main.
Cheers,
Enrico

P.S.
to directly reply to your question, I don’t think there is a way to quit a TTree::Draw event loop early (the doc does not mention one).

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.