Define call returning void

Hi all,

I’m (ab)using RDataFrame to perform small calculations using the Define action taking 2 strings as input and saving it’s output in histograms/trees/workspaces. The reason I’m using this, rather that the functor-based action is that my executable reads json-like config files with boost property_tree, whose underlying data type can’t be easily casted to a functor (maybe there is a way to do this?).
Now I ran into a corner case where I tried to calculate an opening angle

... 
df = df.Define("K_3V","TVector3()")//returns TVector3
df = df.Define("dump","K_3V.SetPtEtaPhi(K_PT,K_ETA,K_PHI)")//returns void
...
df = df.Define("KPi_OA","K_3V.Angle(Pi_3V)")//Pi_3V analogous to K_3V

This implementation raises errors from (what i think is) JIT compilation and then produces a seg-fault. The most relevant error message seems to be

error: cannot form a reference to 'void'

I can provide more information from this example if needed.

Of course the calculation can be done in various ways, but I thought it could be interesting for you to see this use-case. Do you have any suggestion how to do calculations like this? The more general question I would derive from this is: can one implement a multi-line functor using the string-only Define action?

Cheers,
Marian


ROOT Version: 6.16.00 (LCG95)
Platform: x86_64-slc6-gcc8-opt
Compiler: gcc 8.2.0-3fa06


Hi Marian,
Define defines a new column. By design each expression passed to Define must define something, so it has to return something. There is another important reason why what you are doing won’t work: if nothing ever references the "dump" column anywhere, the computation will not even be triggered!

can one implement a multi-line functor using the string-only Define action?

Yes, there is no limitation, just add a return statement at the end.
I believe what you want is:

df.Define("K_3V", "TVector3 v; v.SetPtEtaPhi(K_PT, K_ETA, K_PHI); return v;")

but as expressions grow in complexity, I suggest you switch to corresponding functions:

TVector3 def_k3v(double K_PT, double K_ETA, double K_PHI) {
    TVector3 v;
    v.SetPtEtaPhi(K_PT, K_ETA, K_PHI);
    return v;
}

// ...
df.Define("KPi_OA", def_k3v, {"K_PT", "K_ETA", "K_PHI"});

Cheers,
Enrico

Hi Enrico,
Using Define with a return statement like this looks very natural. Shame on me to not having figured out this one. For this calculation I don’t really have a large enough benchmark sample at hand, but at first glance

"TVector3 v,w; v.SetPtEtaPhi(K_PT, K_ETA, K_PHI); w.SetPtEtaPhi(Pi_PT,Pi_ETA,Pi_PHI); return v.Angle(w);"

looks even faster than my workaround solution

"TVector3(K_PT*std::cos(K_PHI),K_PT*std::sin(K_PHI),K_PT*std::sinh(K_ETA))"
...

Thanks,
Marian

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