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).