Home | News | Documentation | Download

Defining "good objects" using vector of Math::LorentzVectors in RDataFrame

Hi

The code I am working with has migrated to store vectors of LorentzVectors, rather than storing vectors of pT/et/phi. In the past I had code setup which would select a subset of these variables based on condition, eg

data = data.Define("good_jet_pt","jet_pt[jet_pt > 0]")

Now the I am using LorentzVectors, I thought I should be able to do:

data = data.Define("good_jets","jet[jet.Pt() > 0]")

However, this is returning an error like:

input_line_86:2:123: error: no member named 'Pt' in 'ROOT::VecOps::RVec<ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiE4D<double> > >'
auto lambda3 = [](ROOT::VecOps::RVec<ROOT::Math::LorentzVector<ROOT::Math::PtEtaPhiE4D<double> >>& var0){return var0[var0.Pt() > 0]

I am seemingly able to define a new collection of these LorentzVectors by selecting on a different related variable but not on the functions themselves. I am wondering whether I need to switch to use VecOps::Where but I am struggling to find an example of this in RDataFrames and python.

Thanks, Ian

Hi,
note that the code inside those strings is C++.
Example usages for the different RVec helper functions can be found as part of their docs, e.g. here for Where.

So to get an RVec of pts from an RVec of LorentzVectors you can use e.g.

Map(jet, [](auto &j) { return j.Pt(); })

So you can in principle do

jet[Map(jet, [](auto &j) { return j.Pt(); }) > 0]

or maybe more readable

const auto &pts = Map(jet, [](auto &j) { return j.Pt(); });
return jet[pts > 0];

I have not tested the code, there might be typos, but it should give you an idea.
Anyway you can play with things at the ROOT prompt:

~ root -l
root [0] ROOT::RVec<ROOT::Math::PtEtaPhiMVector> jet;
root [1] jet.resize(4) // jet now contains 4 default-constructed PtEtaPhiMVectors
root [2] jet[Map(jet, [](auto &j) { return j.Pt(); }) > 0]
(ROOT::VecOps::RVec) {}

Cheers,
Enrico

Hi Enrico

Thanks for the explanations here. I think I understand, but I am finding some run time errors. If I follow correctly, doing

data = data.Define("jet_pt",Map(jet, [](auto &j) { return j.Pt(); }))

should create a flattened variable of jet pts from an RVec of LorentzVectors? I do not encounter any error when the variable is defined, but if I attempt to use this in a histogram, I am seeing a lot of errors of the type

/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/vector:336:23: error: cannot form a reference to 'void'
    typedef value_type&                              reference;

and

/usr/local/Cellar/root/6.22.08_2/include/root/ROOT/RDF/InterfaceUtils.hxx:424:11: note: in instantiation of template class 'ROOT::Detail::RDF::RCustomColumn<__rdf::(lambda at input_line_83:2:16),
      ROOT::Detail::RDF::CustomColExtraArgs::None>' requested here
      new NewCol_t(name, dummyType, std::forward<F>(f), cols, lm->GetNSlots(), newColumns)));
          ^
input_line_112:7:22: note: in instantiation of function template specialization 'ROOT::Internal::RDF::JitDefineHelper<__rdf::(lambda at input_line_83:2:16) &>' requested
      here
ROOT::Internal::RDF::JitDefineHelper(__rdf::lambda4, {"reco_jet_light_85"}, "good_jets_pt", reinterpret_cast<ROOT::Detail::RDF::RLoopMan...

I was initially trying to apply the pt selection, but as I was seeing errors, decided to try and just histogram the pt in this way first.

EDIT: The ROOT prompt does work, but I need to include the namespace ROOT::VecOps::Map otherwise I get errors (using ROOT v6.22)

EDIT2: I can see with playing that I should just use Map(...) to flatten the pt and not jet[Map(...)] but I still see the same errors.

Thanks
Ian

No, we are selecting elements of jet, and jet is an RVec of LorentzVectors, so jet_pt there is a misnomer, sorry – that returns a selection of the LorentzVectors.

If you want just the good pts you can do e.g.:

auto pts = Map(jet, [](auto &j) { return j.Pt(); }; return pts[pts > 0];

Cheers,
Enrico