Read 2-dimensional array branch with rdataframe in PyROOT


ROOT Version: 6.32.06
Platform: Alma Linux 9
Compiler: c++ (GCC) 11.4.1


I have a ROOT C++ macro that succesfully defines a RDataFrame column from a 2Darray and plots it. The 2D array was defined in a previous post: read-2-dimensional-c-array-branch-with-rdataframe

#include <ROOT/RDataFrame.hxx>
#include <TCanvas.h>

void gRooTracker() {
  ROOT::RDataFrame gDF("DetSimPassThru/gRooTracker","events.1.edep.root");
  auto gDFExpanded = gDF.Define("nuE", [](const ROOT::VecOps::RVec<double>& mom4) { return mom4[3]; }, {"StdHepP4"});
  auto gH = gDFExpanded.Histo1D("nuE");
  
  TCanvas *c = new TCanvas("c", "Canvas", 800, 600);
  gH->Draw();
  c->Update();
  c->SaveAs("gRooTracker.png");
  c->Draw();
}

I was trying to have an equivalent piece of code in pyROOT. This is my best attempt:

import ROOT
from ROOT import TChain
from ROOT import TCanvas
from ROOT import RDataFrame
from ROOT import RVec

df = RDataFrame("DetSimPassThru/gRooTracker","events.1.edep.root") 
ROOT.gInterpreter.ProcessLine("""
double GenieE(const ROOT::VecOps::RVec<double>& mom4) {
    return mom4[3];  
}
""")

df_new = df.Define("nuE", "GenieE", ["StdHepP4"])

h = df_new.Histo1D("nuE")
c = ROOT.TCanvas()
h.Draw()
c.Draw()
c.SaveAs("E_nu.png")

This solution seems to work up to the column definition, but then when I attempt to draw the histogram I get a very long error message, which I pasted below. Could you help me figure out what I’m doing wrong?

input_line_76:3:96: error: no template named 'RVec'
ROOT::Internal::RDF::CallBuildAction<ROOT::Internal::RDF::ActionTags::Histo1D, double(*)(const RVec<double>>(reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>(0x559535ed5ec0), new const char*[1]{"nuE"}, 1, 1, reinterpret_cast<shared_ptr<TH1D>*>(0x559535eb2700), reinterpret_cast<std::weak_ptr<ROOT::Internal::RDF::RJittedAction>*>(0x559533e4d190), reinterpret_cast<ROOT::Internal::RDF::RColumnRegister*>(0x559536010150));
                                                                                               ^
input_line_76:3:108: error: expected ')'
ROOT::Internal::RDF::CallBuildAction<ROOT::Internal::RDF::ActionTags::Histo1D, double(*)(const RVec<double>>(reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>(0x559535ed5ec0), new const char*[1]{"nuE"}, 1, 1, reinterpret_cast<shared_ptr<TH1D>*>(0x559535eb2700), reinterpret_cast<std::weak_ptr<ROOT::Internal::RDF::RJittedAction>*>(0x559533e4d190), reinterpret_cast<ROOT::Internal::RDF::RColumnRegister*>(0x559536010150));
                                                                                                           ^
input_line_76:3:89: note: to match this '('
ROOT::Internal::RDF::CallBuildAction<ROOT::Internal::RDF::ActionTags::Histo1D, double(*)(const RVec<double>>(reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>(0x559535ed5ec0), new const char*[1]{"nuE"}, 1, 1, reinterpret_cast<shared_ptr<TH1D>*>(0x559535eb2700), reinterpret_cast<std::weak_ptr<ROOT::Internal::RDF::RJittedAction>*>(0x559533e4d190), reinterpret_cast<ROOT::Internal::RDF::RColumnRegister*>(0x559536010150));
                                                                                        ^
input_line_76:3:436: error: expected '>'
ROOT::Internal::RDF::CallBuildAction<ROOT::Internal::RDF::ActionTags::Histo1D, double(*)(const RVec<double>>(reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>(0x559535ed5ec0), new const char*[1]{"nuE"}, 1, 1, reinterpret_cast<shared_ptr<TH1D>*>(0x559535eb2700), reinterpret_cast<std::weak_ptr<ROOT::Internal::RDF::RJittedAction>*>(0x559533e4d190), reinterpret_cast<ROOT::Internal::RDF::RColumnRegister*>(0x559536010150));
                                                                                                                                                                                                                                                                                                                                                                                                                                                   ^
input_line_76:3:37: note: to match this '<'
ROOT::Internal::RDF::CallBuildAction<ROOT::Internal::RDF::ActionTags::Histo1D, double(*)(const RVec<double>>(reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>(0x559535ed5ec0), new const char*[1]{"nuE"}, 1, 1, reinterpret_cast<shared_ptr<TH1D>*>(0x559535eb2700), reinterpret_cast<std::weak_ptr<ROOT::Internal::RDF::RJittedAction>*>(0x559533e4d190), reinterpret_cast<ROOT::Internal::RDF::RColumnRegister*>(0x559536010150));
                                    ^
input_line_76:3:436: warning: declaration does not declare anything [-Wmissing-declarations]
ROOT::Internal::RDF::CallBuildAction<ROOT::Internal::RDF::ActionTags::Histo1D, double(*)(const RVec<double>>(reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>(0x559535ed5ec0), new const char*[1]{"nuE"}, 1, 1, reinterpret_cast<shared_ptr<TH1D>*>(0x559535eb2700), reinterpret_cast<std::weak_ptr<ROOT::Internal::RDF::RJittedAction>*>(0x559533e4d190), reinterpret_cast<ROOT::Internal::RDF::RColumnRegister*>(0x559536010150));
                                                                                                                                                                                                                                                                                                                                                                                                                                                   ^
In module 'ROOTDataFrame':
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:98:4: warning: inline function 'ROOT::Detail::RDF::RDefine<double (*(*)())(const ROOT::VecOps::RVec<double> &), ROOT::Detail::RDF::ExtraArgsForDefine::None>::RDefine' is not defined [-Wundefined-inline]
   RDefine(std::string_view name, std::string_view type, F expression, const ROOT::RDF::ColumnNames_t &columns,
   ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/InterfaceUtils.hxx:476:44: note: used here
   return std::unique_ptr<RDefineBase>(new RDefine<std::decay_t<F>, ExtraArgsForDefine::None>(
                                           ^
In module 'ROOTDataFrame':
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:109:4: warning: inline function 'ROOT::Detail::RDF::RDefine<double (*(*)())(const ROOT::VecOps::RVec<double> &), ROOT::Detail::RDF::ExtraArgsForDefine::None>::~RDefine' is not defined [-Wundefined-inline]
   ~RDefine() { fLoopManager->Deregister(this); }
   ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:98:4: note: used here
   RDefine(std::string_view name, std::string_view type, F expression, const ROOT::RDF::ColumnNames_t &columns,
   ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:111:9: warning: inline function 'ROOT::Detail::RDF::RDefine<double (*(*)())(const ROOT::VecOps::RVec<double> &), ROOT::Detail::RDF::ExtraArgsForDefine::None>::InitSlot' is not defined [-Wundefined-inline]
   void InitSlot(TTreeReader *r, unsigned int slot) final
        ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:98:4: note: used here
   RDefine(std::string_view name, std::string_view type, F expression, const ROOT::RDF::ColumnNames_t &columns,
   ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:119:10: warning: inline function 'ROOT::Detail::RDF::RDefine<double (*(*)())(const ROOT::VecOps::RVec<double> &), ROOT::Detail::RDF::ExtraArgsForDefine::None>::GetValuePtr' is not defined [-Wundefined-inline]
   void *GetValuePtr(unsigned int slot) final
         ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:98:4: note: used here
   RDefine(std::string_view name, std::string_view type, F expression, const ROOT::RDF::ColumnNames_t &columns,
   ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:136:26: warning: inline function 'ROOT::Detail::RDF::RDefine<double (*(*)())(const ROOT::VecOps::RVec<double> &), ROOT::Detail::RDF::ExtraArgsForDefine::None>::GetTypeId' is not defined [-Wundefined-inline]
   const std::type_info &GetTypeId() const final { return typeid(ret_type); }
                         ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:98:4: note: used here
   RDefine(std::string_view name, std::string_view type, F expression, const ROOT::RDF::ColumnNames_t &columns,
   ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:125:9: warning: inline function 'ROOT::Detail::RDF::RDefine<double (*(*)())(const ROOT::VecOps::RVec<double> &), ROOT::Detail::RDF::ExtraArgsForDefine::None>::Update' is not defined [-Wundefined-inline]
   void Update(unsigned int slot, Long64_t entry) final
        ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:98:4: note: used here
   RDefine(std::string_view name, std::string_view type, F expression, const ROOT::RDF::ColumnNames_t &columns,
   ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:134:9: warning: inline function 'ROOT::Detail::RDF::RDefine<double (*(*)())(const ROOT::VecOps::RVec<double> &), ROOT::Detail::RDF::ExtraArgsForDefine::None>::Update' is not defined [-Wundefined-inline]
   void Update(unsigned int /*slot*/, const ROOT::RDF::RSampleInfo &/*id*/) final {}
        ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:98:4: note: used here
   RDefine(std::string_view name, std::string_view type, F expression, const ROOT::RDF::ColumnNames_t &columns,
   ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:139:9: warning: inline function 'ROOT::Detail::RDF::RDefine<double (*(*)())(const ROOT::VecOps::RVec<double> &), ROOT::Detail::RDF::ExtraArgsForDefine::None>::FinalizeSlot' is not defined [-Wundefined-inline]
   void FinalizeSlot(unsigned int slot) final
        ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:98:4: note: used here
   RDefine(std::string_view name, std::string_view type, F expression, const ROOT::RDF::ColumnNames_t &columns,
   ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:148:9: warning: inline function 'ROOT::Detail::RDF::RDefine<double (*(*)())(const ROOT::VecOps::RVec<double> &), ROOT::Detail::RDF::ExtraArgsForDefine::None>::MakeVariations' is not defined [-Wundefined-inline]
   void MakeVariations(const std::vector<std::string> &variations) final
        ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:98:4: note: used here
   RDefine(std::string_view name, std::string_view type, F expression, const ROOT::RDF::ColumnNames_t &columns,
   ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:168:17: warning: inline function 'ROOT::Detail::RDF::RDefine<double (*(*)())(const ROOT::VecOps::RVec<double> &), ROOT::Detail::RDF::ExtraArgsForDefine::None>::GetVariedDefine' is not defined [-Wundefined-inline]
   RDefineBase &GetVariedDefine(const std::string &variationName) final
                ^
/opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/include/ROOT/RDF/RDefine.hxx:98:4: note: used here
   RDefine(std::string_view name, std::string_view type, F expression, const ROOT::RDF::ColumnNames_t &columns,
   ^

Hi Federico,

Could you please try

df_new = df.Define("nuE", "Genie(StdHepP4)")

?

Cheers,
D

Hi Danilo, this is something that I had already tried, but I get a different error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[5], line 15
      8 ROOT.gInterpreter.ProcessLine("""
      9 double GenieE(const ROOT::VecOps::RVec<double>& mom4) {
     10     return mom4[3];  
     11 }
     12 """)
     14 # Now define the new column in the RDataFrame
---> 15 df_new = df.Define("nuE", "GenieE(StdHepP4)")
     17 # h = df_new.Histo1D("nuE")
     18 # c = ROOT.TCanvas()
     19 # h.Draw()
     20 # c.Draw()
     21 # c.SaveAs("E_nu.png")

File /opt/exp_software/neutrino/al9/ROOT/v6.32.06/v6.32.06_install/lib/ROOT/_pythonization/_rdf_pyz.py:372, in _PyDefine(rdf, col_name, callable_or_str, cols, extra_args)
    369     raise TypeError(f"First argument of Define must be a valid string for the new column name. {type(col_name).__name__} is not a string.")
    371 if isinstance(callable_or_str, str): # If string argument is passed. Invoke the Original Define.
--> 372     return rdf._OriginalDefine(col_name, callable_or_str)
    374 if not callable(callable_or_str): # The 2st argument is either a string or a python callable.
    375     raise TypeError(f"The second argument of a Define operation should be a callable. {type(callable_or_str).__name__} object is not callable.")

TypeError: Template method resolution failed:
  ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager,void> ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager,void>::Define(string_view name, string_view expression) =>
    runtime_error: TTree leaf StdHepP4.StdHepP4 has both a leaf count and a static length. This is not supported.
  Failed to instantiate "Define(ROOT::RDataFrame&,std::string,std::string)"
  Failed to instantiate "Define(ROOT::RDataFrame*,std::string,std::string)"
  Failed to instantiate "Define(ROOT::RDataFrame,std::string,std::string)"

Hi Federico,

Sorry for suggesting something that did not work, but we think we now understand better. Could you share with us the file (cernbox, dropbox, gdrive)?

Cheers,
D