[Solved] How to generate filtered histogram using RDataFrame


ROOT Version: 6.24/02
Platform: Linux/Fedora 34
Compiler: gcc version 11.3.1 20220421


Hello,

I have a ROOT file which contains a tree with several branches and I’m trying to use RDataFrame to generate a histogram for one of the branches (eX) as shown below:

ROOT::RDataFrame df("gTree", "testF.root");
auto h = df.Fill(TH1D("eX","eX",8192.,0,8192),{"eX"});
h->Draw();

This works perfectly as expected.

Please note that eX is a variable array of type ULong64_t

However, when I try to apply filter e.g. eX > 100 using an example given here & using the following code

ROOT::RDataFrame df("gTree", "testF.root");
auto h = df.Filter("eX > 100").Histo1D("eX");
h->Draw();

It is throwing the following error:

In module 'ROOTDataFrame':
/opt/root/pro/include/ROOT/RDF/InterfaceUtils.hxx:276:4: error: static_assert failed due to requirement 'std::is_convertible<ROOT::VecOps::RVec<int>, bool>::value' "filter expression returns a type that is not convertible to bool"
   static_assert(std::is_convertible<FilterRet_t, bool>::value,
   ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/root/pro/include/ROOT/RDF/InterfaceUtils.hxx:389:17: note: in instantiation of function template specialization 'ROOT::Internal::RDF::CheckFilter<__rdf::(lambda at input_line_33:2:16)>' requested here
   RDFInternal::CheckFilter(f);
                ^
input_line_35:2:23: note: in instantiation of function template specialization 'ROOT::Internal::RDF::JitFilterHelper<__rdf::(lambda at input_line_33:2:16) &, ROOT::Detail::RDF::RNodeBase>' requested here
 ROOT::Internal::RDF::JitFilterHelper(__rdf::lambda0, new const char*[1]{"E_Ge"}, 1, "", reinterpret_cast<std::weak_ptr<ROOT::Detail::RDF::RJittedFilter>*>(0x4953920), reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>(0x497b9b0),reinterpret_cast<ROOT::Internal::RDF::RBookedDefines*>(0x6295660));
                      ^
In module 'ROOTDataFrame':
/opt/root/pro/include/ROOT/RDF/RFilter.hxx:108:14: error: no viable conversion from returned value of type 'ROOT::VecOps::RVec<int>' to function return type 'bool'
      return fFilter(fValues[slot][S]->template Get<ColTypes>(entry)...);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Any help is highly appreciated.

Regards,

Ajay

Dear Ajay,

The Filter method is used to select entries in a dataset. If you want to filter the entries in a RVec, as in your case, the way to proceed would be:

ROOT::RDataFrame df("gTree", "testF.root");
auto h = df.Define("eX_100", "eX[eX> 100]").Histo1D("eX_100");
h->Draw();

If you are curious about what happens in this expression eX[eX> 100] you can have a look at the ROOT prompt snapshot below - most of RVec operations are about indices:

root [0] ROOT::VecOps::RVec<ULong64_t> v {0,1,101,200}
(ROOT::VecOps::RVec<ULong64_t> &) { 0, 1, 101, 200 }
root [1] v>100
(ROOT::VecOps::RVec<int>) { 0, 0, 1, 1 }
root [2] v[v>100]

If you are thinking to move to a fully compiled version of RDataFrame for performance reasons, you can always have a look to this operation on RVecs.

I hope this helps!

Cheers,
D

1 Like

Dear @Danilo,
Thank you very much! That is exactly what I was looking for!
I’m now planning to move my existing data analysis codes to RDataFrame framework
for better performance.
Regards,
Ajay

Dear @ajaydeo,

This is great to hear! Don’t hesitate to come back to us in case you have more questions.

In order to complete my previous message, let me add the fully compiled version of the RDataFrame snippet above:

ROOT::RDataFrame df("gTree", "testF.root");
auto eXFilter = [](const ROOT::RVecI&  v) {return ROOT::VecOps::Filter(v, [](int i){return i>100;});};
auto h = df.Define("eX_100", eXFilter, {"eX"}).Histo1D<ROOT::RVecI>("eX_100");
h->Draw();

Cheers,
D

1 Like

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