I can not figure out what is the correct syntax to apply a method on a RVecROOT::Math::PtEtaPhiEVector> in python.
I made an example
“”
import ROOT
import os,sys
if name == “main”:
path = “root://eospublic.cern.ch//eos/opendata/atlas/OutreachDatasets/2020-01-22/”
filename=path+‘GamGam/Data/data_A.GamGam.root’
print ('filename= ',filename)
d = ROOT.RDataFrame(“mini”, filename)
d=d.Filter(‘photon_n>0’,‘At least 1 photon’)
d = d.Define(“photons”, ’ ROOT::VecOps::ConstructROOT::Math::PtEtaPhiEVector(photon_pt , photon_eta, photon_phi, photon_E )')
d = d.Define(“ph_pt”,‘ROOT::VecOps::Map(photons, photons.Pt())’)
hnom = d.Histo1D(“ph_pt”)
h1.Draw()
“”
What is the correct syntax to call the Map in python ?
Thank you for the help.
Tancredi
Hi @tancredi ,
I don’t think you are forced to use helpers like Construct
or even Map
. With this example I think I am doing the same thing you are trying to do, correct me if I am wrong:
import ROOT
if __name__ == "__main__":
df = (
ROOT.RDataFrame(5)
.Define("photon_pt", "1.")
.Define("photon_eta", "2.")
.Define("photon_phi", "3.")
.Define("photon_E", "4.")
.Define("photons", "ROOT::Math::PtEtaPhiEVector(photon_pt , photon_eta, photon_phi, photon_E)")
.Define("ph_pt", "photons.Pt()")
)
df.Display(("ph_pt",)).Print()
Hello,
yes, but in my case the photon is a RVec (many photons in the event) and I need to apply a method from ROOT::Math::PtEtaPhiEVector on all elements in the RVec. I saw that the Map is needed for that.
Regards,
Tancredi
Right,
The following snippet should then be closer to your case:
import ROOT
if __name__ == "__main__":
df = (
ROOT.RDataFrame(5)
.Define("photon_pt", "ROOT::RVecD(3, 1.)")
.Define("photon_eta", "ROOT::RVecD(3, 2.)")
.Define("photon_phi", "ROOT::RVecD(3, 3.)")
.Define("photon_E", "ROOT::RVecD(3, 4.)")
.Define("photons", "ROOT::VecOps::Construct<ROOT::Math::PtEtaPhiEVector>(photon_pt, photon_eta, photon_phi, photon_E)")
.Define("ph_pt", "return ROOT::VecOps::Map(photons, [](const ROOT::Math::PtEtaPhiEVector &v){return v.Pt();}); ")
)
df.Display(("photons",)).Print()
First off, with respect to your original example which you said doesn’t work, I don’t think photons.Pt()
is doing what you think. The docs of the Map
function state that you should pass a callable that will be applied to all the elements of the collection. In your case, the collection is photons
(i.e. an RVec<ROOT::Math::PtEtaPhiEVector>
). The other argument you are passing, i.e. photons.Pt()
, is not a callable. Logically, that would mean the result of the method Pt
, which is a double
. Not even photons.Pt
would work since that is a member function of the ROOT::Math::PtEtaPhiEVector
class, and not the RVec
class which is the type of photons
. So, practically, you have to pass a callable that takes a ROOT::Math::PtEtaPhiEVector
as input argument and calls its Pt
method (that is what you see in my example above).
That being said, pay extra attention in this particular case: passing a C++ lambda to the Map
call inside the string hits a non-ideal behaviour which is documented in the docs (incidentally with exactly your use case as an example) and has also been explained in the forum in other posts (here for example). Make sure to always explicitly use return
in the strings you pass to Define
and other operations whenever another return
keyword is already present in the string.
Cheers,
Vincenzo
Hello Vincenzo,
thank you for the detailed explaination. I did not know how to construct the lambda function.
It works now !
Regards,
Tancredi