RDF Define at PyROOT using C++ code not working

I am trying to define some RVec variable using C++ syntax into PyROOT rdf. Basically some operation with track momentums (tr_px, tr_py).

ROOT.gInterpreter.Declare('''
                          std::vector<float> make_pT_RVec(std::vector<float> tr_px, std::vector<float> tr_py){

                          const auto size = tr_px.size();
                          std::vector<float> pT_RVec(size);

                          for (size_t i=0; i < size; ++i) {
                              pT_RVec[i] = tr_px[i]*tr_px[i]+tr_py[i]*tr_py[i]; 
                            }

                         return pT_RVec;
                         }''')

new_rdf = rdf.Define("pT_RVec", "make_pT_RVec(tr_px, tr_py)")

It gives an error that I don’t understand:

runtime_error: Template method resolution failed:
  ROOT::RDF::RInterface<ROOT::Detail::RDF::RRange<ROOT::Detail::RDF::RLoopManager>,void> 
ROOT::RDF::RInterface<ROOT::Detail::RDF::RRange<ROOT::Detail::RDF::RLoopManager>,void>::Define(basic_string_view<char,char_traits<char> > name, basic_string_view<char,char_traits<char> > expression) =>
    runtime_error: 
RDataFrame: An error occurred during just-in-time compilation. The lines above might indicate the cause of the crash
 All RDF objects that have not run an event loop yet should be considered in an invalid state.

Please read tips for efficient and successful posting and posting code

ROOT Version: Not Provided
Platform: Not Provided
Compiler: Not Provided


The function signature seems wrong, should be something like

std::vector<float> myfunction(std::vector<float> input1,...){
...
}

std::vector alone is likely the reason of the crash.
Cheers

Edit: I saw you modified the original post, are you sure the branches you try to process have the vector signature?

You can check

df.GetColumnType("tr_px")

If they are RVec, try to change the signature of the function arguments.

1 Like

Yes. I think that was the problem. I put the wrong type, it was an RVec.

Thanks you @RENATO_QUAGLIANI

1 Like

not sure if it’s automatically handled, but when i need to combine RVec object with custom function i always avoid to make copies for each call , with const even better if possible

make_pT_RVec(const RVec<float> & tr_px, const RVec<float> tr_py){

A thing you can also bare in mind is that if you would have done

Define( "pt2", "tr_px*tr_px + tr_py*tr_py")

RDF is smart enough to provide vector[size] * vector[size] = product-element wise or also with vector*scalar. Not sure if the pow( RVec<T>, 0.5 ) is also implemented (apparently yes, see next comment) , if so you would not even need to declare your function

Just testeed on ROOT prompt,

root [3] ROOT::VecOps::RVec<double> a{1,2,3};
root [4] ROOT::VecOps::RVec<double> b{2,4,2};
root [5] a*b
(ROOT::VecOps::RVec<decltype(v0[0] * v1[0])>) { 2.0000000, 8.0000000, 6.0000000 }
root [6] pow( (a*a + b*b),0.5)
(ROOT::VecOps::RVec<PromoteTypes<double, double> >) { 2.2360680, 4.4721360, 3.6055513 }

seems it’s implemented .
You could have simply done :

Define( "tr_pt" , "pow( tr_px * tr_px + tr_py * tr_py , 0.5)")
//or Define( "tr_pt" , "sqrt( tr_px * tr_px + tr_py * tr_py )")

Yes I know. This was the starting point of a more complex custom function.
Thank you

Good point! Thank you

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