ATLAS Offline Software
TauTruthMatchingTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Local include(s)
8 
9 // Core include(s):
10 #include "AthLinks/ElementLink.h"
14 
15 // EDM include(s):
16 #include "xAODTau/TauxAODHelpers.h"
17 
18 using namespace TauAnalysisTools;
19 
20 //=================================PUBLIC-PART==================================
21 //______________________________________________________________________________
22 TauTruthMatchingTool::TauTruthMatchingTool( const std::string& name )
24  , m_accPtVis("pt_vis")
25  , m_accEtaVis("eta_vis")
26  , m_accPhiVis("phi_vis")
27  , m_accMVis("m_vis")
28 {
29 }
30 
31 //______________________________________________________________________________
33 {
34  ATH_MSG_INFO( "Initializing TauTruthMatchingTool" );
35 
36  // configure BuildTruthTaus in truth matching mode, not truth tau building mode
37  TauTruthMatchingTool::BuildTruthTaus::setTruthMatchingMode();
38 
40  {
41  ATH_MSG_FATAL("Failed initializing BuildTruthTaus");
42  return StatusCode::FAILURE;
43  }
44  return StatusCode::SUCCESS;
45 }
46 
47 //______________________________________________________________________________
48 std::unique_ptr<TauTruthMatchingTool::ITruthTausEvent> TauTruthMatchingTool::getEvent() const
49 {
50  auto truthTausEvent = std::make_unique<TruthTausEvent>();
51  if (retrieveTruthTaus(*truthTausEvent).isFailure()) {
52  truthTausEvent.reset();
53  }
54  return truthTausEvent;
55 }
56 
57 //______________________________________________________________________________
59 {
60  return getTruth (xTau, m_truthTausEvent);
61 }
62 
63 
65  ITruthTausEvent& itruthTausEvent) const
66 {
67  TruthTausEvent& truthTausEvent = dynamic_cast<TruthTausEvent&> (itruthTausEvent);
68 
69  if (retrieveTruthTaus(truthTausEvent).isFailure())
70  return nullptr;
71 
72  if (findTruthTau(xTau, truthTausEvent).isFailure())
73  ATH_MSG_WARNING("There was a failure in finding the matched truth tau");
74 
75  static const SG::ConstAccessor<char> accIsTruthMatched("IsTruthMatched");
76  static const SG::ConstAccessor< ElementLink< xAOD::TruthParticleContainer > > accTruthParticleLink("truthParticleLink");
77 
78  // derivations may drop IsTruthMatched, redecorate using truthParticleLink (this assumes links to truth leptons are preserved, i.e. TruthTaus, TruthElectron, TruthMuon)
79  if ( !(*m_bIsTruthMatchedAvailable.ptr()) && (*m_bIsTruthParticleLinkAvailable.ptr())) {
80  ATH_MSG_DEBUG("TauJetContainer has truthParticleLink available while IsTruthMatched not available. Re-evaluate IsTruthMatched");
81  static const SG::Decorator<char> decIsTruthMatched("IsTruthMatched");
82  if (accTruthParticleLink(xTau)) {
83  decIsTruthMatched(xTau) = (char)true;
84  } else {
85  decIsTruthMatched(xTau) = (char)false;
86  }
87  }
88 
89  // if matched to a truth particle return its pointer, else return a null pointer
90  if (static_cast<bool>(accIsTruthMatched(xTau)))
91  {
92  if (accTruthParticleLink(xTau).isValid())
93  {
94  return *accTruthParticleLink(xTau);
95  }
96  else
97  {
98  ATH_MSG_WARNING("ElementLink to TruthParticle is not valid.");
99  return nullptr;
100  }
101  }
102 
103  return nullptr;
104 }
105 
106 //______________________________________________________________________________
107 std::vector<const xAOD::TruthParticle*> TauTruthMatchingTool::getTruth(const std::vector<const xAOD::TauJet*>& vTaus)
108 {
109  std::vector<const xAOD::TruthParticle*> vTruths;
110  for (auto xTau : vTaus)
111  vTruths.push_back(getTruth(*xTau));
112  return vTruths;
113 }
114 
116 // Wrapper functions //
118 
119 //______________________________________________________________________________
120 TLorentzVector TauTruthMatchingTool::getTruthTauP4Vis(const xAOD::TauJet& xTau)
121 {
122  const xAOD::TruthParticle* xTruthTau = getTruth(xTau);
123  TLorentzVector vTLV;
124  if (xTruthTau == nullptr)
125  {
126  ATH_MSG_INFO("no truth particle was found, returning TLorentzVector with all values equal to 0");
127  } else {
128  vTLV = getTruthTauP4Vis(*xTruthTau);
129  }
130  return vTLV;
131 }
132 
133 //______________________________________________________________________________
134 TLorentzVector TauTruthMatchingTool::getTruthTauP4Vis(const xAOD::TruthParticle& xTruthTau) const
135 {
136  TLorentzVector vTLV;
137  static const SG::ConstAccessor<double> acc ("pt_vis");
138  if (!acc.isAvailable(xTruthTau))
139  return vTLV;
140  vTLV.SetPtEtaPhiM(
141  m_accPtVis(xTruthTau),
142  m_accEtaVis(xTruthTau),
143  m_accPhiVis(xTruthTau),
144  m_accMVis(xTruthTau));
145  return vTLV;
146 }
147 
148 //______________________________________________________________________________
149 TLorentzVector TauTruthMatchingTool::getTruthTauP4Invis(const xAOD::TauJet& xTau)
150 {
151  const xAOD::TruthParticle* xTruthTau = getTruth(xTau);
152  TLorentzVector vTLV;
153  if (xTruthTau == nullptr)
154  {
155  ATH_MSG_INFO("no truth particle was found, returning TLorentzVector with all values equal to 0");
156  } else {
157  vTLV = getTruthTauP4Invis(*xTruthTau);
158  }
159  return vTLV;
160 }
161 
162 //______________________________________________________________________________
163 TLorentzVector TauTruthMatchingTool::getTruthTauP4Invis(const xAOD::TruthParticle& xTruthTau) const
164 {
165  TLorentzVector vTLV;
166 
167  static const SG::ConstAccessor<double> accPtInvis("pt_invis");
168  static const SG::ConstAccessor<double> accEtaInvis("eta_invis");
169  static const SG::ConstAccessor<double> accPhiInvis("phi_invis");
170  static const SG::ConstAccessor<double> accMInvis("m_invis");
171 
172  if (!accPtInvis.isAvailable(xTruthTau))
173  return vTLV;
174  vTLV.SetPtEtaPhiM(
175  accPtInvis(xTruthTau),
176  accEtaInvis(xTruthTau),
177  accPhiInvis(xTruthTau),
178  accMInvis(xTruthTau));
179  return vTLV;
180 }
181 
183 {
185 }
186 
187 //______________________________________________________________________________
188 int TauTruthMatchingTool::getNTauDecayParticles(const xAOD::TauJet& xTau, int iPdgId, bool bCompareAbsoluteValues)
189 {
190  const xAOD::TruthParticle* xTruthTau = getTruth(xTau);
191  if (xTruthTau == nullptr)
192  {
193  ATH_MSG_DEBUG("no truth particle was found, return 0");
194  return 0;
195  }
196  static const SG::ConstAccessor<std::vector<int> > accDecayModeVector("DecayModeVector");
197  if (!accDecayModeVector.isAvailable(*xTruthTau))
198  {
199  ATH_MSG_INFO("found truth particle is not a truth tau, return 0");
200  return 0;
201  }
202  return getNTauDecayParticles(*xTruthTau,iPdgId, bCompareAbsoluteValues);
203 }
204 
205 //______________________________________________________________________________
206 int TauTruthMatchingTool::getNTauDecayParticles(const xAOD::TruthParticle& xTruthTau, int iPdgId, bool bCompareAbsoluteValues) const
207 {
208  int iNum = 0;
209  static const SG::ConstAccessor<std::vector<int> > accDecayModeVector("DecayModeVector");
210  if (!accDecayModeVector.isAvailable(xTruthTau))
211  {
212  ATH_MSG_WARNING("passed truth particle is not a truth tau, return 0");
213  return 0;
214  }
215 
216  for(auto iPdgId2 : accDecayModeVector(xTruthTau))
217  if (!bCompareAbsoluteValues)
218  {
219  if (iPdgId2 == iPdgId) iNum++;
220  }
221  else
222  {
223  if (std::abs(iPdgId2) == std::abs(iPdgId)) iNum++;
224  }
225  return iNum;
226 }
227 
228 //______________________________________________________________________________
229 xAOD::TauJetParameters::DecayMode TauTruthMatchingTool::getDecayMode(const xAOD::TauJet& xTau)
230 {
231  const xAOD::TruthParticle* xTruthTau = getTruth(xTau);
232  if (xTruthTau == nullptr)
233  {
234  ATH_MSG_DEBUG("no truth particle was found, return Mode_Error");
236  }
237  static const SG::ConstAccessor<size_t> accNumCharged("numCharged");
238  if (!accNumCharged.isAvailable(*xTruthTau))
239  {
240  ATH_MSG_INFO("found truth particle is not a truth tau, return Mode_Error");
242  }
243  return getDecayMode(*xTruthTau);
244 }
245 
246 //______________________________________________________________________________
247 xAOD::TauJetParameters::DecayMode TauTruthMatchingTool::getDecayMode(const xAOD::TruthParticle& xTruthTau) const
248 {
249  static const SG::ConstAccessor<size_t> accNumCharged("numCharged");
250  if (!accNumCharged.isAvailable(xTruthTau))
251  {
252  ATH_MSG_WARNING("passed truth particle is not a truth tau, return Mode_Error");
254  }
255 
256  int iCharged = getNTauDecayParticles(xTruthTau,MC::PIPLUS, true) + getNTauDecayParticles(xTruthTau,MC::KPLUS, true);
257  int iNeutral = getNTauDecayParticles(xTruthTau,MC::PI0, true);
258  if (iCharged == 1)
259  {
260  if (iNeutral == 0) return xAOD::TauJetParameters::DecayMode::Mode_1p0n;
261  if (iNeutral == 1) return xAOD::TauJetParameters::DecayMode::Mode_1p1n;
262  if (iNeutral >= 2) return xAOD::TauJetParameters::DecayMode::Mode_1pXn;
263  }
264  else if (iCharged == 3)
265  {
266  if (iNeutral == 0) return xAOD::TauJetParameters::DecayMode::Mode_3p0n;
267  if (iNeutral >= 1) return xAOD::TauJetParameters::DecayMode::Mode_3pXn;
268  }
269 
270  if (iCharged == 2 or iCharged == 4 or iCharged == 5)
272  if (iCharged == 0 or iCharged >=6)
274 
275  // if you got here, something should have gone wrong
277 }
278 
280 // Private Part //
282 
283 //______________________________________________________________________________
284 StatusCode TauTruthMatchingTool::findTruthTau(const xAOD::TauJet& xTau,
285  TruthTausEvent& truthTausEvent) const
286 {
287  // check if decorations were already added to the first passed tau
288  if (!m_bIsTruthMatchedAvailable.isValid()) {
289  static const SG::ConstAccessor<char> accIsTruthMatched("IsTruthMatched");
290  m_bIsTruthMatchedAvailable.set (accIsTruthMatched.isAvailable(xTau));
291  }
292  // check if decorations were already added to the first passed tau
293  if (!m_bIsTruthParticleLinkAvailable.isValid()) {
295  accTruthParticleLink("truthParticleLink");
296  m_bIsTruthParticleLinkAvailable.set (accTruthParticleLink.isAvailable(xTau));
297  }
298 
299  if (*m_bIsTruthMatchedAvailable.ptr() || *m_bIsTruthParticleLinkAvailable.ptr()) {
300  return StatusCode::SUCCESS;
301  }
302 
303  // only search for truth taus once
304 
305  // need to be reviewed
306 
307  if (m_bTruthTauAvailable)
308  return checkTruthMatch(xTau, *truthTausEvent.m_xTruthTauContainerConst, truthTausEvent);
309  else
310  return checkTruthMatch(xTau, *truthTausEvent.m_xTruthTauContainer, truthTausEvent);
311 }
312 
313 //______________________________________________________________________________
314 StatusCode TauTruthMatchingTool::checkTruthMatch (const xAOD::TauJet& xTau, const xAOD::TruthParticleContainer& xTruthTauContainer, const TruthTausEvent& truthTausEvent) const
315 {
316  const xAOD::TruthParticle* xTruthMatch = nullptr;
317  const xAOD::Jet* xTruthJetMatch = nullptr;
318  TruthMatchedParticleType eTruthMatchedParticleType = Unknown;
319  static const SG::Decorator<char> decIsTruthMatched("IsTruthMatched");
320  static const SG::Decorator< ElementLink< xAOD::JetContainer > > decTruthJetLink("truthJetLink");
321 
322  for (auto xTruthTauIt : xTruthTauContainer)
323  {
324  TLorentzVector vTruthVisTLV;
325  vTruthVisTLV.SetPtEtaPhiM(m_accPtVis(*xTruthTauIt),
326  m_accEtaVis(*xTruthTauIt),
327  m_accPhiVis(*xTruthTauIt),
328  m_accMVis(*xTruthTauIt));
329  if (xTau.p4().DeltaR(vTruthVisTLV) <= m_dMaxDeltaR)
330  {
331  static const SG::ConstAccessor<char> accIsHadronicTau("IsHadronicTau");
332  if (static_cast<bool>(accIsHadronicTau(*xTruthTauIt)))
333  eTruthMatchedParticleType = TruthHadronicTau;
334  else
335  eTruthMatchedParticleType = TruthLeptonicTau;
336 
337  xTruthMatch = xTruthTauIt;
338  break;
339  }
340  }
341 
342  double dPtMax = 0.;
343  if (!xTruthMatch and truthTausEvent.m_xTruthMuonContainerConst)
344  {
345  dPtMax = 0.;
346  for (auto xTruthMuonIt : *truthTausEvent.m_xTruthMuonContainerConst)
347  {
348  if (xTau.p4().DeltaR(xTruthMuonIt->p4()) <= m_dMaxDeltaR)
349  {
350  if (xTruthMuonIt->pt()<dPtMax)
351  continue;
352  eTruthMatchedParticleType = TruthMuon;
353  xTruthMatch = xTruthMuonIt;
354  dPtMax = xTruthMuonIt->pt();
355  }
356  }
357  }
358 
359  if (!xTruthMatch and truthTausEvent.m_xTruthElectronContainerConst)
360  {
361  dPtMax = 0.;
362  for (auto xTruthElectronIt : *truthTausEvent.m_xTruthElectronContainerConst)
363  {
364  if (xTau.p4().DeltaR(xTruthElectronIt->p4()) <= m_dMaxDeltaR)
365  {
366  if (xTruthElectronIt->pt()<dPtMax)
367  continue;
368  eTruthMatchedParticleType = TruthElectron;
369  xTruthMatch = xTruthElectronIt;
370  dPtMax = xTruthElectronIt->pt();
371  }
372  }
373  }
374 
375  if (truthTausEvent.m_xTruthJetContainerConst)
376  {
377  dPtMax = 0.;
378  for (auto xTruthJetIt : *truthTausEvent.m_xTruthJetContainerConst)
379  {
380  if (xTau.p4().DeltaR(xTruthJetIt->p4()) <= m_dMaxDeltaR)
381  {
382  if (xTruthJetIt->pt()<dPtMax)
383  continue;
384  xTruthJetMatch = xTruthJetIt;
385  dPtMax = xTruthJetIt->pt();
386  }
387  }
388  }
389 
390  if (xTruthMatch)
391  decIsTruthMatched(xTau) = (char)true;
392  else
393  decIsTruthMatched(xTau) = (char)false;
394 
395  if (xTruthJetMatch)
396  {
397  ElementLink < xAOD::JetContainer > lTruthParticleLink(xTruthJetMatch, *truthTausEvent.m_xTruthJetContainerConst);
398  decTruthJetLink(xTau) = lTruthParticleLink;
399  }
400  else
401  {
402  ElementLink < xAOD::JetContainer > lTruthParticleLink;
403  decTruthJetLink(xTau) = lTruthParticleLink;
404  }
405 
406  // create link to the original TruthParticle
407  static const SG::Decorator< ElementLink< xAOD::TruthParticleContainer > > decTruthParticleLink("truthParticleLink");
408 
409  if (xTruthMatch)
410  {
411  if (eTruthMatchedParticleType == TruthHadronicTau or eTruthMatchedParticleType == TruthLeptonicTau)
412  {
413  ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthMatch, xTruthTauContainer);
414  decTruthParticleLink(xTau) = lTruthParticleLink;
415  }
416  else if (eTruthMatchedParticleType == TruthMuon)
417  {
418  ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthMatch, *truthTausEvent.m_xTruthMuonContainerConst);
419  decTruthParticleLink(xTau) = lTruthParticleLink;
420  }
421  else if (eTruthMatchedParticleType == TruthElectron)
422  {
423  ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthMatch, *truthTausEvent.m_xTruthElectronContainerConst);
424  decTruthParticleLink(xTau) = lTruthParticleLink;
425  }
426  }
427  else
428  {
430  decTruthParticleLink(xTau) = lTruthParticleLink;
431  }
432 
433  return StatusCode::SUCCESS;
434 }
435 
436 
445 TauTruthMatchingTool::lockDecorations (const xAOD::TauJetContainer& taus) const
446 {
447  xAOD::TauJetContainer& taus_nc ATLAS_THREAD_SAFE = const_cast<xAOD::TauJetContainer&> (taus);
448  static const SG::Decorator<char> decIsTruthMatched("IsTruthMatched");
449  static const SG::Decorator< ElementLink< xAOD::JetContainer > > decTruthJetLink("truthJetLink");
450  static const SG::Decorator< ElementLink< xAOD::TruthParticleContainer > > decTruthParticleLink("truthParticleLink");
451  taus_nc.lockDecoration (decIsTruthMatched.auxid());
452  taus_nc.lockDecoration (decTruthJetLink.auxid());
453  taus_nc.lockDecoration (decTruthParticleLink.auxid());
454  return StatusCode::SUCCESS;
455 }
456 
xAOD::TauJetParameters::Mode_1p0n
@ Mode_1p0n
Definition: TauDefs.h:386
TauAnalysisTools
Definition: TruthCollectionMakerTau.h:16
TauAnalysisTools::TruthElectron
@ TruthElectron
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/Enums.h:102
TauTruthMatchingTool.h
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
xAOD::TauJetParameters::Mode_1p1n
@ Mode_1p1n
Definition: TauDefs.h:387
TauAnalysisTools::getTruth
const xAOD::TruthParticle * getTruth(const xAOD::TauJet &xTau)
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/Root/HelperFunctions.cxx:195
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
TauAnalysisTools::IBuildTruthTaus::ITruthTausEvent
Declare the interface that the class provides.
Definition: IBuildTruthTaus.h:35
TauAnalysisTools::TruthHadronicTau
@ TruthHadronicTau
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/Enums.h:99
initialize
void initialize()
Definition: run_EoverP.cxx:894
xAOD::char
char
Definition: TrigDecision_v1.cxx:38
TauAnalysisTools::getNTauDecayParticles
int getNTauDecayParticles(const xAOD::TruthParticle &xTruthTau, int iPdgId, bool bCompareAbsoluteValues)
Count truth matched decay particles of a particular PDGID.
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/Root/HelperFunctions.cxx:257
SG::ConstAccessor< char >
SG::Decorator::auxid
SG::auxid_t auxid() const
Return the aux id for this variable.
TauAnalysisTools::TruthLeptonicTau
@ TruthLeptonicTau
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/Enums.h:100
xAOD::TauJetParameters::Mode_1pXn
@ Mode_1pXn
Definition: TauDefs.h:388
xAOD::TauJetParameters::DecayMode
DecayMode
Definition: TauDefs.h:385
TauAnalysisTools::BuildTruthTaus
Definition: BuildTruthTaus.h:39
SG::Decorator< char >
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TauxAODHelpers.h
xAOD::TruthParticle_v1
Class describing a truth particle in the MC record.
Definition: TruthParticle_v1.h:37
xAOD::TauJet_v3
Class describing a tau jet.
Definition: TauJet_v3.h:41
AthenaPoolTestRead.acc
acc
Definition: AthenaPoolTestRead.py:16
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
xAOD::TauJetParameters::Mode_3p0n
@ Mode_3p0n
Definition: TauDefs.h:389
TauAnalysisTools::TruthMuon
@ TruthMuon
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/Enums.h:101
TauAnalysisTools::TruthMatchedParticleType
TruthMatchedParticleType
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/TauAnalysisTools/Enums.h:97
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
xAOD::Jet_v1
Class describing a jet.
Definition: Jet_v1.h:57
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
xAOD::TauJet_v3::p4
virtual FourMom_t p4() const
The full 4-momentum of the particle.
Definition: TauJet_v3.cxx:96
TauAnalysisTools::getTruthParticleType
TruthMatchedParticleType getTruthParticleType(const xAOD::TauJet &xTau)
return TauJet match type
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/Root/HelperFunctions.cxx:494
xAOD::TauJetParameters::Mode_3pXn
@ Mode_3pXn
Definition: TauDefs.h:390
xAOD::TruthParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TruthParticle_v1.cxx:161
SG::ConstAccessor::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
xAOD::TauJetParameters::Mode_Error
@ Mode_Error
Definition: TauDefs.h:393
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
ConstAccessor.h
Helper class to provide constant type-safe access to aux data.
xAOD::TauJetParameters::Mode_NotSet
@ Mode_NotSet
Definition: TauDefs.h:392
xAOD::Jet_v1::pt
virtual double pt() const
The transverse momentum ( ) of the particle.
Definition: Jet_v1.cxx:44
Decorator.h
Helper class to provide type-safe access to aux data.
HelperFunctions.h
HepMCHelpers.h
xAOD::TauJetParameters::Mode_Other
@ Mode_Other
Definition: TauDefs.h:391