Fill vector<Struct> using RDataFrame Define

Dear experts,
I have some compiled code reading a tuple which contains branches in the form
vector x,
vector y,

I have a struct

struct Point2D{ 
   float x;
   float y;
   Point2D() = default;
   Point2D( float _x, float _y): x(_x), y(_y){};
}

my code is the following :

auto make_Points2D = [] ( vector<float> x, vector<float> y){ 
    vector<Point2D> points; points.reserve( x.size()); 
   for( int j =0; j < x.size() ; ++j){ 
     points.emplace_back( x[j], y[j]);
   } 
   return points;
}
//---opther struct for Points3D
ROOT::RDataFrame df( "t","f.root"); 
auto df_final = df.Filter("afilter")
                           .Define( "points2D", make_Points2D, { "x","y"} 
                            .Define( "points3D", make_Points3D, { "x","y","z"} ;
auto All2DPoints = df_final.Take<vector<Point2D>>( "points2D"); 
auto All3DPoints = df_final.Take<vector<Point3D>>( "points3D"); 

The code run and the vectors aree filled but, when running it i get bunch of errors like :

input_line_48:1:49: error: use of undeclared identifier 'Point2D'
namespace __tdf1 {  using Point2D4_type = vector<Point2D>; }

Thanks for any suggestions


_ROOT Version: 6.16.0
Platform: Not Provided
Compiler: Not Provided


I’m sure @Danilo can help you to solve this issue

Thanks for the trust, @bellenot!
Ranato,

the issue, fixed in master and forthcoming 6.18, is that RDF expects the interpreter to know about Point2D.
I see at least two ways of fixing this.

  1. Use a pair instead of a point
  2. Declare the code of Point2D to the interpreter
    In any case I would remove the copy of std vectors in the signature of the lambda and use const references instead.

Cheers,
D

1 Like

Hi @Danilo, unfortunately i did like that (ask for the Point2D) because was faster, but in my use case i have somehting more complex with 8-9 privatee members…
I think i would go for the declaration. How can i do that?

Is something like this ?

 d.Define("p", "struct{blabla}; .... all my lambda function;  return p;")?

Renato.

Well, i don’t know how to let the interpreter know about tthat. I am trying to produce a std::ttuple in the lambda and for my classes i define a constructor with the tuple forwarding arguments.

gInterpreter->Declare("struct YourStruct {...};");

should do the job.

Sorry i was too naive in the comment, i guess the gInterpreter thing is going to work in a macro-like system. I have a CMake project for which i probably have to make Dictionaries to my classes etc…
If you say that ROOT/master will have not the issue, i am going to update ROOT.

I had the struct définition in the same file of the main executable I was compiling.
Moving all classes and struct to an header and cpp file plus a Linkdef for them and linking the executable to the produced library with the dictionary generated made disappear the issue.
However, after recompiling with Root/mastet and keeping the old structure (structs defined in same file of the executable) was still producing the error.
Thanks a lot for the help.

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