ROOT Version: v6.14 Platform: Linux (CC7) Compiler: gcc 4.8.5
Hello everybody,
I’d like to provide a filter function for RDataFrames such that they can take a variable number of branches. Is this possible? I tried something like the following: Assuming I load a tree in a dataframe ‘d’ with the
branches ‘b1’, ‘b2’, … ‘bn’ all of the same object type TObj.
Using variadic templates I defined the filter function ‘func’ which should accept a variable number of arguments of type TObj:
When I apply this function as a filter on the dataframe ‘d’:
auto filtered = d.Filter(func<T>, {"b1", "b2", "b3"});
I get the following error:
'terminate called after throwing an instance of 'std::runtime_error'
what(): 1 column name is required but 3 were provided: "b1", "b2", "b3".
Aborted (core dumped)'
In general there is no way to create a Filter that acts on N single branches from a function that takes a std::vector.
The reason is that RDataFrame deduces, at compile-time, the types of the columns that you are using for the filter from the signature of the filter function. So the signature of the filter function must match the types of the columns exactly.
In your example, RDataFrame is deducing that your Filter takes exactly one column of type std::vector<T>, hence the error message.
However, for this particular scenario, there is a RDF helper that fits the bill: PassAsVec.
The documentation has an example usage, in your case it would look like:
auto filtered = d.Filter(PassAsVec<3, float>(func<float>), {"b1", "b2", "b3"});
You will need ROOT v6.16 or greater (or you can just copy the few lines of definition of PassAsVec in your code).