Vector operation in TTree->Draw()

Hi,

is it possible to define a function operating on a vector, compile and load it, and then use it on a vector in a TTree directly in TTree->Draw()?

For example:

#include <vector>
#include <accumulate>
using namespace std;

double vecsum (vector<double> x) {
   return accumulate(x.begin(),x.end(),0);
}

double vecsum (vector<bool> x) {
   return count(x.begin(),x.end(),true);
}

and

root [0] .L vecsum.C++
root [1] mytree->Draw("vecsum(myvectorofdouble)")

Any variation of this I’ve tried gets me Error in <TTreeFormula::Compile>: Bad numerical expression

Thanks,
Sara

Hi Sara,

did you have a look to TDataFrame? It solves exactly this and other problems! https://root.cern/doc/v610/classROOT_1_1Experimental_1_1TDataFrame.html

For example, in your case (assuming the existence of a file called myfile.root and that the branch containing the vectors):

ROOT::Experimental::TDataFrame tdf("mytree", "myfile.root");
auto h = tdf.Define("sum_d", vecsum_d, {"myvectorofdouble"}).Histo1D("sum_d");
h->Draw();

Cheers,
D

2 Likes

Hi Danilo,

Thanks for pointing me to TDataFrame, it seems I was a little behind on the latest developments.

I had a quick read of the main page and the tutorials and this seems very nice.
I already have a first challenge I cannot figure out though.

Using C++ I can do:

auto h = tdf.Define("sum_d", vecsum_d, {"myvectorofdouble"}) \
   .Histo1D({"h","",4,0,4},"sum_d");

whereas in python I try:

tdf.Define('sum_d','vecsum_d(myvectorofdouble)').Histo1D('sum_d')

This works fine, but I can’t manage to pass on my chosen histogram parameters.
Also, is it possible to define the histogram type, both in C++ and python?

Thanks,
Sara

Hi Sara,
for what concerns passing your own histogram parameters also from python, it’s coming with the next release (6.12, in November) and it is already possible if you compile our master branch from source. It looks like this:

d = ROOT.ROOT.Experimental.TDataFrame("tree", "file.root")
h = d.Histo1D(("h", "h", 128, 0, 1), "x")

Changing the type of the histogram used by Histo1D is not currently possible, but from C++ you can pass whatever object has a Fill method to the Fill action:

ROOT::Experimental::TDataFrame d(10);
// define column "x" to always return 42 and fill a TH2I with it
auto hi = d.Define("x", "42").Fill(TH2I("hi", "hi", 100, 0, 10), {"x"});
hi->Draw();

Filling a generic object via Fill is not currently possible from python, but we might add it if there’s enough request for it, so let us know if you have a use-case that requires it!

Cheers,
Enrico

Hi Enrico,

thanks for the quick answer. I will have to be a little patient then, as I unfortunately need to run this in more places than just on my own laptop.

Concerning the Fill functionality in python, I suppose being able to set the parameters in Histo1D is already a nice start, but undoubtedly one is at some point going to want to fill for example a histogram with non-equidistant (e.g. logarithmic) binning. In that case the original d.Histo1D(("h", "h", 128, 0, 1), "x") is no longer sufficient and something like Fill(object,"x") would be required.

Cheers,
Sara

2 Likes

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