Using RDataFrame::Histo2D


ROOT Version: 6.12 and 6.14
Platform: Linux and Macintosh
Compiler: gcc 6.4 and clang 8.0


I have a problem using RDataFrame::Histo2D. Here’s a simple example, derived from https://root.cern.ch/doc/master/df001__introduction_8C.html.

void fill_tree(const char *treeName, const char *fileName)
{
   ROOT::RDataFrame d(10);
   int i(0);
   d.Define("b1", [&i]() { return (double)i; })
      .Define("b2",
              [&i]() {
                 auto j = i * i;
                 ++i;
                 return j;
              })
      .Snapshot(treeName, fileName);
}
int histo2dtest()
{
   auto fileName = "df001_introduction.root";
   auto treeName = "myTree";
   fill_tree(treeName, fileName);

   ROOT::RDataFrame d(treeName, fileName);

   auto hist1 = d.Histo1D("b1");
   auto hist2 = d.Histo1D("b2");
   auto hist3 = d.Histo2D("b1","b2");	
   auto canvas1 = new TCanvas();
   hist1->Draw();
   auto canvas2 = new TCanvas();
   hist2->Draw();
   auto canvas3 = new TCanvas();
   hist3->Draw();
}

When I try to compile this in ROOT 6.14 on my Mac, I get the error that I quote below. Before you dismiss this as a macports problem: I get the same compilation error running ROOT 6.12.06 on a Linux system, substituting “ROOT::Experimental::TDataFrame” for “ROOT::RDataFrame”.

Is there some obvious mistake I’m making? I’ve tried Histo2D in several different contexts (PyROOT, Jupyter, different TTrees, two different ROOT versions, two different OSes) and always get the same error. I’d attribute this to some syntax error on my part, except that the only other ROOT forum post that mentions Histo2D uses the same syntax.

Macintosh, ROOT 6.14, clang 8:

root [0] 
Processing Histo2DTest.C...
In file included from input_line_10:1:
/Users/seligman/Downloads/Histo2DTest.C:27:19: error: no matching member function for call to 'Histo2D'
   auto hist3 = d.Histo2D("b1","b2");   
                ~~^~~~~~~
/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_macports_release_tarballs_ports_science_root6/root6/work/build/include/ROOT/RDFInterface.hxx:848:23: note: candidate function not viable: no known conversion from 'const char [3]' to 'const ROOT::RDF::TH2DModel' for 1st argument
   RResultPtr<::TH2D> Histo2D(const TH2DModel &model, std::string_view v1Name = "", std::string_view v2Name = "")
                      ^
/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_macports_release_tarballs_ports_science_root6/root6/work/build/include/ROOT/RDFInterface.hxx:881:4: note: candidate function template not viable: requires 4 arguments, but 2 were provided
   Histo2D(const TH2DModel &model, std::string_view v1Name, std::string_view v2Name, std::string_view wName)
   ^
/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_macports_release_tarballs_ports_science_root6/root6/work/build/include/ROOT/RDFInterface.hxx:899:23: note: candidate function template not viable: requires single argument 'model', but 2 arguments were provided
   RResultPtr<::TH2D> Histo2D(const TH2DModel &model)
                      ^

ROOT 6.12.06, Linux, GCC 6.4:

root [0] 
Processing Histo2Dtest.C...
In file included from input_line_10:1:
/nevis/tanya/home/seligman/review/Histo2Dtest.C:27:18: error: no matching member function for call to 'Histo2D'
  auto hist3 = d.Histo2D("b1","b2");
               ~~^~~~~~~
/usr/nevis/src/root-6.12.06-build/include/ROOT/TDFInterface.hxx:1057:25: note: candidate function not viable: no known conversion from 'const char [3]' to 'const ROOT::Experimental::TDF::TH2DModel'
      for 1st argument
   TResultProxy<::TH2D> Histo2D(const TH2DModel &model, std::string_view v1Name = "", std::string_view v2Name = "")
                        ^
/usr/nevis/src/root-6.12.06-build/include/ROOT/TDFInterface.hxx:1099:4: note: candidate function template not viable: requires 4 arguments, but 2 were provided
   Histo2D(const TH2DModel &model, std::string_view v1Name, std::string_view v2Name, std::string_view wName)
   ^
/usr/nevis/src/root-6.12.06-build/include/ROOT/TDFInterface.hxx:1126:25: note: candidate function template not viable: requires single argument 'model', but 2 arguments were provided
   TResultProxy<::TH2D> Histo2D(const TH2DModel &model)
                        ^

Hello,

the code is fine, the only issue is that Histo2D requires the user to specify the ranges and binning of the histogram. You can see ho this is done in the RDataFrame documentation and in this tutorial.

As for ROOT 6.12, ROOT::RDataFrame was not part of that release and, as you rightfully point out, the class was called ROOT::Experimental::TDataFrame.

Cheers,
D

Thanks!

However, this means there’s an inconsistency between the RDataFrame::Histo1D interface and the RDataFrame::Histo2D interface (and presumably the Histo3D interface as well). One can do

   auto hist1 = d.Histo1D("b2");

but not

   auto hist2 = d.Histo2D("b1","b2");	

which makes using the method harder to remember. I assume the internal ROOT machinery to implement the interface without an explicit “model” (as labeled in the RDataFrame documentation) is possible, because one can do something like this:

mytree->Draw("b1:b2");

This suggests that it’s possible to create a 2D histogram without initially knowing the axes ranges.

How does one go about requesting that a feature like this be incorporated into the next version of ROOT?

Hi,

the reason why Histo2D and Histo3D do not support yet automatic range settings is memory usage in the multithreaded case. If one wishes with optimal performance and scaling, e.g. w/o sinchronisation points, an important amount of memory needs to be allocated. Said that, we are aware of this asymmetry (Histo1D supports models too) and we take note of the wish you expressed.

Best,
Danilo

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