ATLAS Offline Software
CustomGetterUtils.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
6 
7 #include <optional>
8 
9 namespace {
10 
12  // ______________________________________________________________________
13  // Custom getters for jet input features
14  std::function<double(const xAOD::Jet&)> customJetGetter(
15  const std::string& name)
16  {
17  if (name == "pt") {
18  return [](const xAOD::Jet& j) -> float {return j.pt();};
19  }
20  if (name == "log_pt") {
21  return [](const xAOD::Jet& j) -> float {return std::log(j.pt());};
22  }
23  if (name == "eta") {
24  return [](const xAOD::Jet& j) -> float {return j.eta();};
25  }
26  if (name == "abs_eta") {
27  return [](const xAOD::Jet& j) -> float {return std::abs(j.eta());};
28  }
29  if (name == "energy") {
30  return [](const xAOD::Jet& j) -> float {return j.e();};
31  }
32  if (name == "mass") {
33  return [](const xAOD::Jet& j) -> float {return j.m();};
34  }
35 
36  throw std::logic_error("no match for custom getter " + name);
37  }
38 
39  // _______________________________________________________________________
40  // Custom getters for jet constituents
41 
42  // wraps non-custom getters into sequences, also adds a name
43  template <typename T, typename U>
44  class NamedSeqGetter{
45  private:
47  std::string m_name;
48  public:
49  NamedSeqGetter(const std::string& name):
50  m_getter(name),
51  m_name(name)
52  {}
53 
54  std::pair<std::string, std::vector<double>>
55  operator()(const xAOD::Jet&, const std::vector<const U*>& constituents) const {
56  std::vector<double> sequence;
57  for (const U* el: constituents) {
58  sequence.push_back(m_getter(*el));
59  }
60  return {m_name, sequence};
61  }
62  };
63 
64  // wraps custom getters into sequences, doesn't add a name
65  template <typename Const>
66  class CustomSeqGetter
67  {
68  using F = std::function<double(const Const&, const xAOD::Jet&)>;
69  private:
70  F m_getter;
71  public:
72  CustomSeqGetter(F getter): m_getter(getter) {}
73 
74  std::vector<double>
75  operator()(const xAOD::Jet& jet, const std::vector<const Const*>& constituents) const {
76  std::vector<double> sequence;
77  sequence.reserve(constituents.size());
78  for (const auto* constituent: constituents) {
79  sequence.push_back(m_getter(*constituent, jet));
80  }
81  return sequence;
82  }
83  };
84 
85  // Getters from xAOD::TrackParticle with IP dependencies
86  std::optional<SequenceGetterFunc<xAOD::TrackParticle>>
87  getterFromTracksWithIpDep(
88  const std::string& name,
89  const std::string& prefix)
90  {
91  using Tp = xAOD::TrackParticle;
92  using Jet = xAOD::Jet;
93 
95  if (name == "IP3D_signed_d0_significance") {
96  return CustomSeqGetter<Tp>([a](const Tp& tp, const Jet& j){
97  return a.getSignedIp(tp, j).ip3d_signed_d0_significance;
98  });
99  }
100  if (name == "IP3D_signed_z0_significance") {
101  return CustomSeqGetter<Tp>([a](const Tp& tp, const Jet& j){
102  return a.getSignedIp(tp, j).ip3d_signed_z0_significance;
103  });
104  }
105  if (name == "IP2D_signed_d0") {
106  return CustomSeqGetter<Tp>([a](const Tp& tp, const Jet& j){
107  return a.getSignedIp(tp, j).ip2d_signed_d0;
108  });
109  }
110  if (name == "IP3D_signed_d0") {
111  return CustomSeqGetter<Tp>([a](const Tp& tp, const Jet& j){
112  return a.getSignedIp(tp, j).ip3d_signed_d0;
113  });
114  }
115  if (name == "IP3D_signed_z0") {
116  return CustomSeqGetter<Tp>([a](const Tp& tp, const Jet& j){
117  return a.getSignedIp(tp, j).ip3d_signed_z0;
118  });
119  }
120  if (name == "d0" || name == "btagIp_d0") {
121  return CustomSeqGetter<Tp>([a](const Tp& tp, const Jet&){
122  return a.d0(tp);
123  });
124  }
125  if (name == "z0SinTheta" || name == "btagIp_z0SinTheta") {
126  return CustomSeqGetter<Tp>([a](const Tp& tp, const Jet&){
127  return a.z0SinTheta(tp);
128  });
129  }
130  if (name == "d0Uncertainty") {
131  return CustomSeqGetter<Tp>([a](const Tp& tp, const Jet&){
132  return a.d0Uncertainty(tp);
133  });
134  }
135  if (name == "z0SinThetaUncertainty") {
136  return CustomSeqGetter<Tp>([a](const Tp& tp, const Jet&){
137  return a.z0SinThetaUncertainty(tp);
138  });
139  }
140  return std::nullopt;
141  }
142 
143 
144  // Getters from xAOD::TrackParticle without IP dependencies
145  std::optional<SequenceGetterFunc<xAOD::TrackParticle>>
146  getterFromTracksNoIpDep(const std::string& name)
147  {
148  using Tp = xAOD::TrackParticle;
149  using Jet = xAOD::Jet;
150 
151  if (name == "phiUncertainty") {
152  return CustomSeqGetter<Tp>([](const Tp& tp, const Jet&) {
153  return std::sqrt(tp.definingParametersCovMatrixDiagVec().at(2));
154  });
155  }
156  if (name == "thetaUncertainty") {
157  return CustomSeqGetter<Tp>([](const Tp& tp, const Jet&) {
158  return std::sqrt(tp.definingParametersCovMatrixDiagVec().at(3));
159  });
160  }
161  if (name == "qOverPUncertainty") {
162  return CustomSeqGetter<Tp>([](const Tp& tp, const Jet&) {
163  return std::sqrt(tp.definingParametersCovMatrixDiagVec().at(4));
164  });
165  }
166  if (name == "z0RelativeToBeamspot") {
167  return CustomSeqGetter<Tp>([](const Tp& tp, const Jet&) {
168  return tp.z0();
169  });
170  }
171  if (name == "log_z0RelativeToBeamspotUncertainty") {
172  return CustomSeqGetter<Tp>([](const Tp& tp, const Jet&) {
173  return std::log(std::sqrt(tp.definingParametersCovMatrixDiagVec().at(1)));
174  });
175  }
176  if (name == "z0RelativeToBeamspotUncertainty") {
177  return CustomSeqGetter<Tp>([](const Tp& tp, const Jet&) {
178  return std::sqrt(tp.definingParametersCovMatrixDiagVec().at(1));
179  });
180  }
181  if (name == "numberOfPixelHitsInclDead") {
182  SG::AuxElement::ConstAccessor<unsigned char> pix_hits("numberOfPixelHits");
183  SG::AuxElement::ConstAccessor<unsigned char> pix_dead("numberOfPixelDeadSensors");
184  return CustomSeqGetter<Tp>([pix_hits, pix_dead](const Tp& tp, const Jet&) {
185  return pix_hits(tp) + pix_dead(tp);
186  });
187  }
188  if (name == "numberOfSCTHitsInclDead") {
189  SG::AuxElement::ConstAccessor<unsigned char> sct_hits("numberOfSCTHits");
190  SG::AuxElement::ConstAccessor<unsigned char> sct_dead("numberOfSCTDeadSensors");
191  return CustomSeqGetter<Tp>([sct_hits, sct_dead](const Tp& tp, const Jet&) {
192  return sct_hits(tp) + sct_dead(tp);
193  });
194  }
195  if (name == "numberOfInnermostPixelLayerHits21p9") {
196  SG::AuxElement::ConstAccessor<unsigned char> barrel_hits("numberOfInnermostPixelLayerHits");
197  SG::AuxElement::ConstAccessor<unsigned char> endcap_hits("numberOfInnermostPixelLayerEndcapHits");
198  return CustomSeqGetter<Tp>([barrel_hits, endcap_hits](const Tp& tp, const Jet&) {
199  return barrel_hits(tp) + endcap_hits(tp);
200  });
201  }
202  if (name == "numberOfNextToInnermostPixelLayerHits21p9") {
203  SG::AuxElement::ConstAccessor<unsigned char> barrel_hits("numberOfNextToInnermostPixelLayerHits");
204  SG::AuxElement::ConstAccessor<unsigned char> endcap_hits("numberOfNextToInnermostPixelLayerEndcapHits");
205  return CustomSeqGetter<Tp>([barrel_hits, endcap_hits](const Tp& tp, const Jet&) {
206  return barrel_hits(tp) + endcap_hits(tp);
207  });
208  }
209  if (name == "numberOfInnermostPixelLayerSharedHits21p9") {
210  SG::AuxElement::ConstAccessor<unsigned char> barrel_hits("numberOfInnermostPixelLayerSharedHits");
211  SG::AuxElement::ConstAccessor<unsigned char> endcap_hits("numberOfInnermostPixelLayerSharedEndcapHits");
212  return CustomSeqGetter<Tp>([barrel_hits, endcap_hits](const Tp& tp, const Jet&) {
213  return barrel_hits(tp) + endcap_hits(tp);
214  });
215  }
216  if (name == "numberOfInnermostPixelLayerSplitHits21p9") {
217  SG::AuxElement::ConstAccessor<unsigned char> barrel_hits("numberOfInnermostPixelLayerSplitHits");
218  SG::AuxElement::ConstAccessor<unsigned char> endcap_hits("numberOfInnermostPixelLayerSplitEndcapHits");
219  return CustomSeqGetter<Tp>([barrel_hits, endcap_hits](const Tp& tp, const Jet&) {
220  return barrel_hits(tp) + endcap_hits(tp);
221  });
222  }
223  return std::nullopt;
224  }
225 
226 
227  // Getters from general xAOD::IParticle and derived classes
228  template <typename T> std::optional<SequenceGetterFunc<T>>
229  getterFromIParticles(const std::string& name)
230  {
231  using Jet = xAOD::Jet;
232  if (name == "pt") {
233  return CustomSeqGetter<T>([](const T& p, const Jet&) {
234  return p.pt();
235  });
236  }
237  if (name == "log_pt") {
238  return CustomSeqGetter<T>([](const T& p, const Jet&) {
239  return std::log(p.pt());
240  });
241  }
242  if (name == "ptfrac") {
243  return CustomSeqGetter<T>([](const T& p, const Jet& j) {
244  return p.pt() / j.pt();
245  });
246  }
247  if (name == "log_ptfrac") {
248  return CustomSeqGetter<T>([](const T& p, const Jet& j) {
249  return std::log(p.pt() / j.pt());
250  });
251  }
252  if (name == "eta") {
253  return CustomSeqGetter<T>([](const T& p, const Jet&) {
254  return p.eta();
255  });
256  }
257  if (name == "deta") {
258  return CustomSeqGetter<T>([](const T& p, const Jet& j) {
259  return p.eta() - j.eta();
260  });
261  }
262  if (name == "abs_deta") {
263  return CustomSeqGetter<T>([](const T& p, const Jet& j) {
264  return copysign(1.0, j.eta()) * (p.eta() - j.eta());
265  });
266  }
267  if (name == "phi") {
268  return CustomSeqGetter<T>([](const T& p, const Jet&) {
269  return p.phi();
270  });
271  }
272  if (name == "dphi") {
273  return CustomSeqGetter<T>([](const T& p, const Jet& j) {
274  return p.p4().DeltaPhi(j.p4());
275  });
276  }
277  if (name == "dr") {
278  return CustomSeqGetter<T>([](const T& p, const Jet& j) {
279  return p.p4().DeltaR(j.p4());
280  });
281  }
282  if (name == "log_dr") {
283  return CustomSeqGetter<T>([](const T& p, const Jet& j) {
284  return std::log(p.p4().DeltaR(j.p4()));
285  });
286  }
287  if (name == "log_dr_nansafe") {
288  return CustomSeqGetter<T>([](const T& p, const Jet& j) {
289  return std::log(p.p4().DeltaR(j.p4()) + 1e-7);
290  });
291  }
292  if (name == "mass") {
293  return CustomSeqGetter<T>([](const T& p, const Jet&) {
294  return p.m();
295  });
296  }
297  if (name == "energy") {
298  return CustomSeqGetter<T>([](const T& p, const Jet&) {
299  return p.e();
300  });
301  }
302  return std::nullopt;
303  }
304 
305 }
306  namespace FlavorTagDiscriminants {
307  namespace getter_utils {
308  // ________________________________________________________________
309  // Interface functions
310  //
311  // As long as we're giving lwtnn pair<name, double> objects, we
312  // can't use the raw getter functions above (which only return a
313  // double). Instead we'll wrap those functions in another function,
314  // which returns the pair we wanted.
315  //
316  // Case for jet variables
317  std::function<std::pair<std::string, double>(const xAOD::Jet&)>
318  namedCustomJetGetter(const std::string& name) {
319  auto getter = customJetGetter(name);
320  return [name, getter](const xAOD::Jet& j) {
321  return std::make_pair(name, getter(j));
322  };
323  }
324 
325  // Case for constituent variables
326  // Returns getter function with dependencies
327  template <typename T>
328  std::pair<SequenceGetterFunc<T>, std::set<std::string>>
329  buildCustomSeqGetter(const std::string& name, const std::string& prefix) {
330 
331  if constexpr (std::is_same_v<T, xAOD::TrackParticle>) {
332  if (auto getter = getterFromTracksWithIpDep(name, prefix)) {
334  return {*getter, deps};
335  }
336  if (auto getter = getterFromTracksNoIpDep(name)) {
337  return {*getter, {}};
338  }
339  }
340  if (auto getter = getterFromIParticles<T>(name)){
341  return {*getter, {}};
342  }
343  throw std::logic_error("no match for custom getter " + name);
344  }
345 
346  // ________________________________________________________________________
347  // Class implementation
348  //
349  template <typename T>
350  std::pair<typename SeqGetter<T>::InputSequence, std::set<std::string>>
351  SeqGetter<T>::getNamedCustomSeqGetter(const std::string& name, const std::string& prefix) {
352  auto [getter, deps] = buildCustomSeqGetter<T>(name, prefix);
353  return {
354  [n=name, g=getter](const xAOD::Jet& j, const std::vector<const T*>& t) {
355  return std::make_pair(n, g(j, t));
356  },
357  deps
358  };
359  }
360 
361  template <typename T>
362  std::pair<typename SeqGetter<T>::InputSequence, std::set<std::string>>
364  const std::string prefix = options.track_prefix;
365  switch (cfg.type) {
366  case ConstituentsEDMType::INT: return {
367  NamedSeqGetter<int, T>(cfg.name), {cfg.name}
368  };
369  case ConstituentsEDMType::FLOAT: return {
370  NamedSeqGetter<float, T>(cfg.name), {cfg.name}
371  };
372  case ConstituentsEDMType::CHAR: return {
373  NamedSeqGetter<char, T>(cfg.name), {cfg.name}
374  };
375  case ConstituentsEDMType::UCHAR: return {
376  NamedSeqGetter<unsigned char, T>(cfg.name), {cfg.name}
377  };
379  return getNamedCustomSeqGetter(
380  cfg.name, options.track_prefix);
381  }
382  default: {
383  throw std::logic_error("Unknown EDM type for constituent.");
384  }
385  }
386  }
387 
388  template <typename T>
389  SeqGetter<T>::SeqGetter(std::vector<InputVariableConfig> inputs, const FTagOptions& options)
390  {
391  std::map<std::string, std::string> remap = options.remap_scalar;
392  for (const InputVariableConfig& input_cfg: inputs) {
393  auto [seqGetter, seq_deps] = seqFromConsituents(input_cfg, options);
394 
395  if(input_cfg.flip_sign){
396  auto seqGetter_flip=[g=seqGetter](const xAOD::Jet&jet, const Const& constituents){
397  auto [n,v] = g(jet,constituents);
398  std::for_each(v.begin(), v.end(), [](double &n){ n=-1.0*n; });
399  return std::make_pair(n,v);
400  };
401  m_sequence_getters.push_back(seqGetter_flip);
402  }
403  else{
404  m_sequence_getters.push_back(seqGetter);
405  }
406  m_deps.merge(seq_deps);
407  if (auto h = remap.extract(input_cfg.name)){
408  m_used_remap.insert(h.key());
409  }
410  }
411  }
412 
413  template <typename T>
414  std::pair<std::vector<float>, std::vector<int64_t>> SeqGetter<T>::getFeats(
415  const xAOD::Jet& jet, const Const& constituents) const
416  {
417  std::vector<float> cnsts_feats;
418  int num_vars = m_sequence_getters.size();
419  int num_cnsts = 0;
420 
421  int cnst_var_idx = 0;
422  for (const auto& seq_getter: m_sequence_getters){
423  auto input_sequence = seq_getter(jet, constituents).second;
424 
425  if (cnst_var_idx==0){
426  num_cnsts = static_cast<int>(input_sequence.size());
427  cnsts_feats.resize(num_cnsts * num_vars);
428  }
429 
430  // need to transpose + flatten
431  for (unsigned int cnst_idx=0; cnst_idx<input_sequence.size(); cnst_idx++){
432  cnsts_feats.at(cnst_idx*num_vars + cnst_var_idx) = input_sequence.at(cnst_idx);
433  }
434  cnst_var_idx++;
435  }
436  std::vector<int64_t> cnsts_feat_dim = {num_cnsts, num_vars};
437  return {cnsts_feats, cnsts_feat_dim};
438  }
439 
440  template <typename T>
441  std::map<std::string, std::vector<double>> SeqGetter<T>::getDL2Feats(
442  const xAOD::Jet& jet, const Const& constituents) const
443  {
444  std::map<std::string, std::vector<double>> feats;
445  for (const auto& seq_getter: m_sequence_getters){
446  feats.insert(seq_getter(jet, constituents));
447  }
448  return feats;
449  }
450 
451  template <typename T>
452  std::set<std::string> SeqGetter<T>::getDependencies() const {
453  return m_deps;
454  }
455  template <typename T>
456  std::set<std::string> SeqGetter<T>::getUsedRemap() const {
457  return m_used_remap;
458  }
459 
460 
461  // Explicit instantiations of supported types (IParticle, TrackParticle)
462  template class SeqGetter<xAOD::IParticle>;
463  template class SeqGetter<xAOD::TrackParticle>;
464  }
465 }
FlavorTagDiscriminants::getter_utils::SeqGetter::getFeats
std::pair< std::vector< float >, std::vector< int64_t > > getFeats(const xAOD::Jet &jet, const Const &constituents) const
Definition: CustomGetterUtils.cxx:414
FlavorTagDiscriminants::getter_utils::SeqGetter::getDL2Feats
std::map< std::string, std::vector< double > > getDL2Feats(const xAOD::Jet &jet, const Const &constituents) const
Definition: CustomGetterUtils.cxx:441
BTagTrackIpAccessor.h
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
ParticleSigStateImpl::eta
virtual double eta() const
pseudo rapidity
Definition: ParticleSigStateImpl.h:735
FlavorTagDiscriminants
This file contains "getter" functions used for accessing tagger inputs from the EDM.
Definition: AssociationEnums.h:11
Jet
Basic data class defines behavior for all Jet objects The Jet class is the principal data class for...
Definition: Reconstruction/Jet/JetEvent/JetEvent/Jet.h:47
CustomGetterUtils.h
FlavorTagDiscriminants::getter_utils::SequenceGetterFunc
std::function< std::vector< double >(const xAOD::Jet &, const Constituents< T > &)> SequenceGetterFunc
Definition: CustomGetterUtils.h:50
met::DeltaR
@ DeltaR
Definition: METRecoCommon.h:11
FlavorTagDiscriminants::getter_utils::SeqGetter< xAOD::IParticle >
FlavorTagDiscriminants::getter_utils::buildCustomSeqGetter
std::pair< SequenceGetterFunc< T >, std::set< std::string > > buildCustomSeqGetter(const std::string &name, const std::string &prefix)
Definition: CustomGetterUtils.cxx:329
ParticleTest.tp
tp
Definition: ParticleTest.py:25
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:54
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
FlavorTagDiscriminants::getter_utils::SeqGetter::seqFromConsituents
std::pair< InputSequence, std::set< std::string > > seqFromConsituents(const InputVariableConfig &cfg, const FTagOptions &options)
Definition: CustomGetterUtils.cxx:363
postInclude.inputs
inputs
Definition: postInclude.SortInput.py:15
xAOD::TrackParticle
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Definition: Event/xAOD/xAODTracking/xAODTracking/TrackParticle.h:13
FlavorTagDiscriminants::getter_utils::namedCustomJetGetter
std::function< std::pair< std::string, double >const xAOD::Jet &)> namedCustomJetGetter(const std::string &)
Definition: CustomGetterUtils.cxx:318
BTagTrackIpAccessor
Definition: BTagTrackIpAccessor.h:29
FlavorTagDiscriminants::getter_utils::SeqGetter::getDependencies
std::set< std::string > getDependencies() const
Definition: CustomGetterUtils.cxx:452
FlavorTagDiscriminants::getter_utils::SeqGetter::Const
Constituents< T > Const
Definition: CustomGetterUtils.h:72
FlavorTagDiscriminants::ConstituentsEDMType::CUSTOM_GETTER
@ CUSTOM_GETTER
jet
Definition: JetCalibTools_PlotJESFactors.cxx:23
BTagTrackIpAccessor::getTrackIpDataDependencyNames
std::set< std::string > getTrackIpDataDependencyNames() const
Definition: BTagTrackIpAccessor.cxx:128
python.CaloCondTools.g
g
Definition: CaloCondTools.py:15
beamspotman.n
n
Definition: beamspotman.py:731
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
plotIsoValidation.el
el
Definition: plotIsoValidation.py:197
python.AtlRunQueryLib.options
options
Definition: AtlRunQueryLib.py:379
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
WriteCaloSwCorrections.cfg
cfg
Definition: WriteCaloSwCorrections.py:23
FlavorTagDiscriminants::ConstituentsEDMType::UCHAR
@ UCHAR
FlavorTagDiscriminants::FTagOptions
Definition: DataPrepUtilities.h:45
python.PyAthena.v
v
Definition: PyAthena.py:157
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
FlavorTagDiscriminants::ConstituentsEDMType::CHAR
@ CHAR
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
a
TList * a
Definition: liststreamerinfos.cxx:10
h
remap
std::map< std::string, std::string > remap
list of directories to be explicitly remapped
Definition: hcg.cxx:92
ParticleSigStateImpl::pt
virtual double pt() const
transverse momentum
Definition: ParticleSigStateImpl.h:767
F
#define F(x, y, z)
Definition: MD5.cxx:112
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
FlavorTagDiscriminants::ConstituentsEDMType::FLOAT
@ FLOAT
FlavorTagDiscriminants::getter_utils::SeqGetter::getUsedRemap
std::set< std::string > getUsedRemap() const
Definition: CustomGetterUtils.cxx:456
FlavorTagDiscriminants::ConstituentsEDMType::INT
@ INT
FlavorTagDiscriminants::InputVariableConfig
Definition: ConstituentsLoader.h:53
FlavorTagDiscriminants::getter_utils::SeqGetter::SeqGetter
SeqGetter(std::vector< InputVariableConfig > inputs, const FTagOptions &options)
Definition: CustomGetterUtils.cxx:389
xAOD::Jet
Jet_v1 Jet
Definition of the current "jet version".
Definition: Event/xAOD/xAODJet/xAODJet/Jet.h:17
TSU::T
unsigned long long T
Definition: L1TopoDataTypes.h:35
FlavorTagDiscriminants::getter_utils::SeqGetter::getNamedCustomSeqGetter
std::pair< InputSequence, std::set< std::string > > getNamedCustomSeqGetter(const std::string &name, const std::string &prefix)
Definition: CustomGetterUtils.cxx:351