Loop over std::vector<TLorentzVector> when using RDataFrame in PyROOT


Please read tips for efficient and successful posting and posting code

ROOT Version: 6.26/04
Platform: CENTOS 7
Compiler: Not Provided


Hello,

i have a branch of a TTree that has std::vectors that each contain TLorentzVectors. I would like to loop over all of them, add the LorentzVectors and take the invariant Mas from the added LorentzVector. I tried to do this by using C++ inside PyROOT like so:

import ROOT


str_tau_ThreeTrackMass = '''
    float getM(const std::vector<TLorentzVector> v) {
        TLorentzVector result;
        for (const auto& entry : v) {
           result = result + entry;
        }
        return result.M();
}
'''

ROOT.gInterpreter.Declare(str_tau_ThreeTrackMass)

fileName = 'path/to/file.root'
f = ROOT.TFile.Open(fileName)

df = ROOT.RDataFrame('NOMINAL', fileName)

df.Define("ThreeTrackMass", "getM(tau_0_charged_tracks_p4)")

hist = df.Histo1D("ThreeTrackMass")

c = ROOT.Canvas()
hist.Draw()
c.Update()
input()

but it doesnt work and gives me the following error

[adhingra@atlasbn1 python_scripts]$ python threeTrackMass.py 
input_line_69:2:68: error: no matching function for call to 'getM'
auto lambda0 = [](ROOT::VecOps::RVec<TLorentzVector>& var0){return getM(var0)
                                                                   ^~~~
input_line_36:2:11: note: candidate function not viable: no known conversion from 'ROOT::VecOps::RVec<TLorentzVector>' to 'const std::vector<TLorentzVector>' for 1st argument
    float getM(const std::vector<TLorentzVector> v) {
          ^
In module 'ROOTVecOps':
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.26.04-83598/x86_64-centos8-gcc11-opt/include/ROOT/RVec.hxx:1452:97: error: no member named 'value' in 'ROOT::Internal::VecOps::RVecInlineStorageSize<TLorentzVector>'
class R__CLING_PTRCHECK(off) RVec : public RVecN<T, Internal::VecOps::RVecInlineStorageSize<T>::value> {
                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
input_line_73:2:73: note: in instantiation of template class 'ROOT::VecOps::RVec<TLorentzVector>' requested here
auto lambda0 = [](ROOT::VecOps::RVec<TLorentzVector>& var0){return getM(var0)
                                                                        ^
In module 'ROOTVecOps':
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.26.04-83598/x86_64-centos8-gcc11-opt/include/ROOT/RVec.hxx:1453:76: error: no member named 'value' in 'ROOT::Internal::VecOps::RVecInlineStorageSize<TLorentzVector>'
   using SuperClass = RVecN<T, Internal::VecOps::RVecInlineStorageSize<T>::value>;
                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.26.04-83598/x86_64-centos8-gcc11-opt/include/ROOT/RVec.hxx:1522:38: error: no function template matches function template specialization 'IsSmall'
   friend bool ROOT::Detail::VecOps::IsSmall<T>(const RVec<T> &v);
                                     ^
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.26.04-83598/x86_64-centos8-gcc11-opt/include/ROOT/RVec.hxx:1089:6: note: candidate template ignored: failed template argument deduction
bool IsSmall(const ROOT::VecOps::RVec<T> &v)
     ^
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.26.04-83598/x86_64-centos8-gcc11-opt/include/ROOT/RVec.hxx:1522:38: error: friend declaration of 'IsSmall' does not match any declaration in namespace 'ROOT::Detail::VecOps'
   friend bool ROOT::Detail::VecOps::IsSmall<T>(const RVec<T> &v);
                                     ^
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.26.04-83598/x86_64-centos8-gcc11-opt/include/ROOT/RVec.hxx:1089:6: note: candidate template ignored: failed template argument deduction
bool IsSmall(const ROOT::VecOps::RVec<T> &v)
     ^
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.26.04-83598/x86_64-centos8-gcc11-opt/include/ROOT/RVec.hxx:1524:38: error: no function template matches function template specialization 'IsAdopting'
   friend bool ROOT::Detail::VecOps::IsAdopting<T>(const RVec<T> &v);
                                     ^
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.26.04-83598/x86_64-centos8-gcc11-opt/include/ROOT/RVec.hxx:1095:6: note: candidate template ignored: failed template argument deduction
bool IsAdopting(const ROOT::VecOps::RVec<T> &v)
     ^
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.26.04-83598/x86_64-centos8-gcc11-opt/include/ROOT/RVec.hxx:1524:38: error: friend declaration of 'IsAdopting' does not match any declaration in namespace 'ROOT::Detail::VecOps'
   friend bool ROOT::Detail::VecOps::IsAdopting<T>(const RVec<T> &v);
                                     ^
/cvmfs/sft.cern.ch/lcg/releases/ROOT/6.26.04-83598/x86_64-centos8-gcc11-opt/include/ROOT/RVec.hxx:1095:6: note: candidate template ignored: failed template argument deduction
bool IsAdopting(const ROOT::VecOps::RVec<T> &v)
     ^
input_line_73:2:68: error: no matching function for call to 'getM'
auto lambda0 = [](ROOT::VecOps::RVec<TLorentzVector>& var0){return getM(var0)
                                                                   ^~~~
input_line_36:2:11: note: candidate function not viable: no known conversion from 'ROOT::VecOps::RVec<TLorentzVector>' to 'const std::vector<TLorentzVector>' for 1st argument
    float getM(const std::vector<TLorentzVector> v) {
          ^
Traceback (most recent call last):
  File "/afs/cern.ch/user/a/adhingra/python_scripts/threeTrackMass.py", line 21, in <module>
    df.Define("ThreeTrackMass", "getM(tau_0_charged_tracks_p4)")
cppyy.gbl.std.runtime_error: Template method resolution failed:
  ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager,void> ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager,void>::Define(basic_string_view<char,char_traits<char> > name, basic_string_view<char,char_traits<char> > expression) =>
    runtime_error: 
RDataFrame: An error occurred during just-in-time compilation. The lines above might indicate the cause of the crash
 All RDF objects that have not run an event loop yet should be considered in an invalid state.

  ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager,void> ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager,void>::Define(basic_string_view<char,char_traits<char> > name, basic_string_view<char,char_traits<char> > expression) =>
    runtime_error: 
RDataFrame: An error occurred during just-in-time compilation. The lines above might indicate the cause of the crash
 All RDF objects that have not run an event loop yet should be considered in an invalid state.

[adhingra@atlasbn1 python_scripts]$ 

i can do it in 100% python without using RDataFrame:

import ROOT

fileName = 'path/to/file.root'
f = ROOT.TFile.Open(fileName)

tree = f.Get('NOMINAL')

h = ROOT.TH1D('test', 'test', 100, 0, 2)

def fillHistogramLoop():
    for event in tree:
        
        if (tree.tau_0_n_charged_tracks < 3):
            continue

        result = ROOT.TLorentzVector()
        for p4 in tree.tau_0_charged_tracks_p4:
            result += 0.001*p4
        
        h.Fill(result.M())


fillHistogramLoop()
h.Draw()

input()

but this is really slow. any ideas what I could do?

Hi @AdvaitDhingra ,

as per the error message:

no known conversion from 'ROOT::VecOps::RVec<TLorentzVector>' to 'const std::vector<TLorentzVector>'

your function has to take a const RVec<TLorentzVector> & rather than a const std::vector<TLorentzVector> (the & is to avoid useless copies).

As a side note, in case you have the option, please note that TLorentzVector is a legacy class and the recommended type to use is ROOT::Math::LorentzVector. See ROOT: TLorentzVector Class Reference .

Cheers,
Enrico

Thanks Enrico, this worked!

1 Like

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