RDataFrame Fill Action

Hi!

I have a question regarding the Fill action of the RDataFrame.
In the Cheat Sheet I found the description “Fill a user-defined object with the values of the specified branches, as if by calling `Obj.Fill(branch1, branch2, …).” and further in the documentation:
“T must be a type that provides a copy- or move-constructor and a T::Fill method that takes as many arguments as the column names pass as columnList. The arguments of T::Fill must have type equal to the one of the specified columns (these types are passed as template parameters to this method).”

So I would expect that I can build my own class which has a Fill method. But it seems like that the class has to be a TH* class as the following code does not compile due to a static assert.

#include <TROOT.h>
#include <ROOT/RDataFrame.hxx>
#include <ROOT/RVec.hxx>
#include <TH1F.h>

class Test
{
    TH1F hist;
public:
    void Fill(const int val)
    {   
        hist.Fill(val);
    }   
};

int main()
{
    const std::string file = "myfile.root";
    auto df = ROOT::RDataFrame("Events", file);

    auto something = df.Fill(Test(), {"nMuon"});

    return 0;
}
g++ -pthread -std=c++11 -m64 -I/home/jonas/physics_tools/root_git/builddir/include -g -O3 -c -o main.o main.cc
In file included from /home/jonas/physics_tools/root_git/builddir/include/ROOT/RDF/RInterface.hxx:18:0,
                 from /home/jonas/physics_tools/root_git/builddir/include/ROOT/RDataFrame.hxx:19,
                 from main.cc:2:
/home/jonas/physics_tools/root_git/builddir/include/ROOT/RDF/InterfaceUtils.hxx: In instantiation of ‘struct ROOT::Internal::RDF::IsV7Hist<Test>’:
/home/jonas/physics_tools/root_git/builddir/include/ROOT/RDF/RInterface.hxx:1322:53:   required from ‘ROOT::RDF::RResultPtr<T1> ROOT::RDF::RInterface<Proxied, DataSource>::Fill(T&&, const ColumnNames_t&) [with T = Test; Proxied = ROOT::Detail::RDF::RLoopManager; DataSource = void; ROOT::RDF::RInterface<Proxied, DataSource>::ColumnNames_t = std::vector<std::__cxx11::basic_string<char> >]’
main.cc:21:47:   required from here
/home/jonas/physics_tools/root_git/builddir/include/ROOT/RDF/InterfaceUtils.hxx:97:4: error: static assertion failed: not implemented for this type
    static_assert(std::is_base_of<TH1, T>::value, "not implemented for this type");
    ^~~~~~~~~~~~~

So where is my code wrong or does the class need to be a TH*? But if yes then why should I not use the Histo*D action directly? Of course I could derive my class from TH1 but I would like to avoid that if possible.

best
Jonas


ROOT Version: master (915eb58de43fd5a8c14c77605e99393e599cbabc)
Platform: Ubuntu18
Compiler: gcc7.3.0


Hi Jonas,

this is a problem. Thanks for identifying it: I opened a ticket to track the progress of the fix (https://sft.its.cern.ch/jira/browse/ROOT-9737)
Now, in order to unblock you for the moment, would perhaps the usage of Foreach or a custom action be a possibility?

Cheers,
Danilo

Hi Danilo,

Thank You for fixing it. Foreach would be possible but not optimal. But I think I won’t have a lot of time the next few weeks to work on this project so I will just wait for the fix :slight_smile:

Maybe one further question (maybe answered from what I saw in your PR for this bug). Does Fill need to be thread safe or does each thread fill its separate object and they are merged in the end. I see the requirement to implement an Add function in your PR so I would assume that the jobs are merged in the end and that only one thread is calling the Fill method of my object?

best
Jonas

Hi Jonas,

Thank You for fixing it. Foreach would be possible but not optimal. But I think I won’t have a lot of time the next few weeks to work on this project so I will just wait for the fix :slight_smile:
OK: we’ll jkeep you posted.

Maybe one further question (maybe answered from what I saw in your PR for this bug). Does Fill need to be thread safe or does each thread fill its separate object and they are merged in the end. I see the requirement to implement an Add function in your PR so I would assume that the jobs are merged in the end and that only one thread is calling the Fill method of my object?

We do not require that Fill is thread safe. This is usually a burden too big to impose to the user: as you correctly guess, we create copies of the objects and merge them at the end of the event loop.
The experts can decide to go for a TS action with custom actions anyway.

Cheers,
Danilo

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