Hello,
I am trying to use histograms as input of “Define” in Root Data Frame, but it does not look like trivial. I want to do something as simple as:
.Define(“weights”,“compute_weights(mu_pt,mu_eta,histo2D)”)
compute_weights is a C++ function where I will read the muon eta and pt values (potentially more than one per event, but it’s irrelevant here) and a 2D histogram. How can I do this?
Thanks, Guillelmo
Hi @ceballos ,
and welcome to the ROOT forum.
is histo2D a variable defined outside of RDF? If so, you need a lambda that captures it (or equivalentely a functor class that has it as a data member):
TH2D histo2D;
df.Define("weights", [&histo2D] (const ROOT::RVecF &pt, const ROOT::RVecF &eta) {
return compute_weights(pt, eta, histo2D);
},
{"mu_pt", "mu_eta"});
or
struct WeightsComputer {
TH2D *fHist2D;
WeightsComputer(TH2D *h) : fHist2D(h) {}
ROOT::RVecF operator()(const ROOT::RVecF &pt, const ROOT::RVecF &eta) {
return compute_weights(pt, eta, fHist2D);
}
};
df.Define("weights", WeightsComputer(&histo2D), {"mu_pt", "mu_eta"});
I didn’t
I hope this helps!
Enrico
Hello,
yes, histo2D indeed a variable member outside RDF. I’ve tried to use the struct, and I think it’s “almost” working. I am trying to use pyroot. I have a C++ external struct as you write, but then the Define doesn’t work well.
I am not allowed to write:
df.Define(“weights”, ROOT.WeightsComputer(&histo2D), {“mu_pt”, “mu_eta”})
I tried (without &)
df.Define(“weights”, ROOT.WeightsComputer(histo2D), {“mu_pt”, “mu_eta”})
But then, it says:
Error sample: Template method resolution failed:
TypeError: takes at most 2 arguments (3 given)
Failed to instantiate “Define(std::string,WeightsComputer&,set)”
Failed to instantiate “Define(std::string,WeightsComputer*,set)”
Failed to instantiate “Define(std::string,WeightsComputer,set)”
Thanks! Guillelmo
Not sure what the problem is, maybe the curly braces instead of the parens for the last argument of Define. This works (at least with the master branch):
In [4]: ROOT.gInterpreter.Declare("""
...: // dummy implementation
...: ROOT::RVecF compute_weights(const ROOT::RVecF &, const ROOT::RVecF &, TH2D &h) {
...: return {};
...: }
...:
...: struct WeightsComputer {
...: TH2D *fHist2D;
...: WeightsComputer(TH2D *h) : fHist2D(h) {}
...:
...: ROOT::RVecF operator()(const ROOT::RVecF &pt, const ROOT::RVecF &eta) {
...: return compute_weights(pt, eta, *fHist2D);
...: }
...: };
...: """)
Out[4]: True
In [5]: df = ROOT.RDataFrame(10).Define("mu_pt", "ROOT::RVecF{}").Define("mu_eta", "mu_pt")
In [9]: h = ROOT.TH2D()
In [10]: df.Define("weights", ROOT.WeightsComputer(h), ("mu_pt", "mu_eta"))
Out[10]: <cppyy.gbl.ROOT.RDF.RInterface<ROOT::Detail::RDF::RLoopManager,void> object at 0x55bc07a443f0>
Cheers,
Enrico
Hi Enrico,
thanks a lot for your help! It works now. It seems the issue was that I was using {“pt”, “eta”} in Define, while it should be (“pt”, “eta”). After making this change, I am able to get the proper information from the histogram in the function.
Thanks again, Guillelmo