ATLAS Offline Software
Loading...
Searching...
No Matches
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
9using namespace TauAnalysisTools;
10using namespace ADD_CMODE(TauAnalysisTools);
11
12//=================================PUBLIC-PART==================================
13//______________________________________________________________________________
14TauTruthMatchingTool::TauTruthMatchingTool( const std::string& name )
15 : BuildTruthTaus(name)
16 , m_accPtVis("pt_vis")
17 , m_accEtaVis("eta_vis")
18 , m_accPhiVis("phi_vis")
19 , m_accMVis("m_vis")
20{}
21
22//______________________________________________________________________________
23StatusCode TauTruthMatchingTool::initialize()
24{
25 ATH_MSG_INFO( "Initializing TauTruthMatchingTool" );
26
27 // configure BuildTruthTaus in truth matching mode, not truth tau building mode
28 TauTruthMatchingTool::BuildTruthTaus::setTruthMatchingMode();
29
30 if (TauTruthMatchingTool::BuildTruthTaus::initialize().isFailure())
31 {
32 ATH_MSG_FATAL("Failed initializing BuildTruthTaus");
33 return StatusCode::FAILURE;
34 }
35 return StatusCode::SUCCESS;
36}
37
38//______________________________________________________________________________
39std::unique_ptr<TauTruthMatchingTool::ITruthTausEvent> TauTruthMatchingTool::getEvent() const
40{
41 const EventContext& ctx = Gaudi::Hive::currentContext();
42 auto truthTausEvent = std::make_unique<TruthTausEvent>();
43 if (retrieveTruthTaus(*truthTausEvent, ctx).isFailure()) {
44 truthTausEvent.reset();
45 }
46 return truthTausEvent;
47}
48
49//______________________________________________________________________________
50const xAOD::TruthParticle* TauTruthMatchingTool::getTruth(const xAOD::TauJet& xTau)
51{
52 return getTruth (xTau, m_truthTausEvent);
53}
54
55
56const xAOD::TruthParticle* TauTruthMatchingTool::getTruth(const xAOD::TauJet& xTau,
57 ITruthTausEvent& itruthTausEvent) const
58{
59 TruthTausEvent& truthTausEvent = dynamic_cast<TruthTausEvent&> (itruthTausEvent);
60 const EventContext& ctx = Gaudi::Hive::currentContext();
61 if (retrieveTruthTaus(truthTausEvent, ctx).isFailure())
62 return nullptr;
63
64 if (findTruthTau(xTau, truthTausEvent).isFailure())
65 ATH_MSG_WARNING("There was a failure in finding the matched truth tau");
66
67 static const SG::ConstAccessor<char> accIsTruthMatched("IsTruthMatched");
68 static const SG::ConstAccessor< ElementLink< xAOD::TruthParticleContainer > > accTruthParticleLink("truthParticleLink");
69
70 // derivations may drop IsTruthMatched, redecorate using truthParticleLink (this assumes links to truth leptons are preserved, i.e. TruthTaus, TruthElectron, TruthMuon)
71 if ( !(*m_bIsTruthMatchedAvailable.ptr()) && (*m_bIsTruthParticleLinkAvailable.ptr())) {
72 ATH_MSG_DEBUG("TauJetContainer has truthParticleLink available while IsTruthMatched not available. Re-evaluate IsTruthMatched");
73 static const SG::Decorator<char> decIsTruthMatched("IsTruthMatched");
74 if (accTruthParticleLink(xTau)) {
75 decIsTruthMatched(xTau) = (char)true;
76 } else {
77 decIsTruthMatched(xTau) = (char)false;
78 }
79 }
80
81 // if matched to a truth particle return its pointer, else return a null pointer
82 if (static_cast<bool>(accIsTruthMatched(xTau)))
83 {
84 if (accTruthParticleLink(xTau).isValid())
85 {
86 return *accTruthParticleLink(xTau);
87 }
88 else
89 {
90 ATH_MSG_WARNING("ElementLink to TruthParticle is not valid.");
91 return nullptr;
92 }
93 }
94
95 return nullptr;
96}
97
98//______________________________________________________________________________
99std::vector<const xAOD::TruthParticle*> TauTruthMatchingTool::getTruth(const std::vector<const xAOD::TauJet*>& vTaus)
100{
101 std::vector<const xAOD::TruthParticle*> vTruths;
102 for (auto xTau : vTaus)
103 vTruths.push_back(getTruth(*xTau));
104 return vTruths;
105}
106
108// Wrapper functions //
110
111//______________________________________________________________________________
112TLorentzVector TauTruthMatchingTool::getTruthTauP4Vis(const xAOD::TauJet& xTau)
113{
114 const xAOD::TruthParticle* xTruthTau = getTruth(xTau);
115 TLorentzVector vTLV;
116 if (xTruthTau == nullptr)
117 {
118 ATH_MSG_INFO("no truth particle was found, returning TLorentzVector with all values equal to 0");
119 } else {
120 vTLV = getTruthTauP4Vis(*xTruthTau);
121 }
122 return vTLV;
123}
124
125//______________________________________________________________________________
126TLorentzVector TauTruthMatchingTool::getTruthTauP4Vis(const xAOD::TruthParticle& xTruthTau) const
127{
128 TLorentzVector vTLV;
129 static const SG::ConstAccessor<double> acc ("pt_vis");
130 if (!acc.isAvailable(xTruthTau))
131 return vTLV;
132 vTLV.SetPtEtaPhiM(
133 m_accPtVis(xTruthTau),
134 m_accEtaVis(xTruthTau),
135 m_accPhiVis(xTruthTau),
136 m_accMVis(xTruthTau));
137 return vTLV;
138}
139
140//______________________________________________________________________________
141TLorentzVector TauTruthMatchingTool::getTruthTauP4Invis(const xAOD::TauJet& xTau)
142{
143 const xAOD::TruthParticle* xTruthTau = getTruth(xTau);
144 TLorentzVector vTLV;
145 if (xTruthTau == nullptr)
146 {
147 ATH_MSG_INFO("no truth particle was found, returning TLorentzVector with all values equal to 0");
148 } else {
149 vTLV = getTruthTauP4Invis(*xTruthTau);
150 }
151 return vTLV;
152}
153
154//______________________________________________________________________________
155TLorentzVector TauTruthMatchingTool::getTruthTauP4Invis(const xAOD::TruthParticle& xTruthTau) const
156{
157 TLorentzVector vTLV;
158
159 static const SG::ConstAccessor<double> accPtInvis("pt_invis");
160 static const SG::ConstAccessor<double> accEtaInvis("eta_invis");
161 static const SG::ConstAccessor<double> accPhiInvis("phi_invis");
162 static const SG::ConstAccessor<double> accMInvis("m_invis");
163
164 if (!accPtInvis.isAvailable(xTruthTau))
165 return vTLV;
166 vTLV.SetPtEtaPhiM(
167 accPtInvis(xTruthTau),
168 accEtaInvis(xTruthTau),
169 accPhiInvis(xTruthTau),
170 accMInvis(xTruthTau));
171 return vTLV;
172}
173
174//______________________________________________________________________________
175TauAnalysisTools::TruthMatchedParticleType TauTruthMatchingTool::getTruthParticleType(const xAOD::TauJet& xTau)
176{
177 return ADD_CMODE(TauAnalysisTools)::getTruthParticleType(xTau);
178}
179
180//______________________________________________________________________________
181bool TauTruthMatchingTool::matchTruthLeptonicTauDecay(const xAOD::IParticle* p, const xAOD::TruthParticleContainer* truth_taus)
182{
183 // input check
184 if (p->type() != xAOD::Type::Muon && p->type() != xAOD::Type::Electron)
185 return false;
186
187 // loop over truth_tau container
188 for (auto truth_tau : *truth_taus) {
189 if (!truth_tau->isTau()) {
190 continue;
191 }
192 static const SG::ConstAccessor<char> accIsHadronicTau ("IsHadronicTau");
193 if( accIsHadronicTau(*truth_tau)){
194 continue;
195 }
196
197 static const SG::ConstAccessor<std::vector<int> > accDecayModeVector("DecayModeVector");
198 if (accDecayModeVector.isAvailable(*truth_tau))
199 {
200 std::vector<int> vDecayMode = accDecayModeVector(*truth_tau);
201 for (auto decayMode : vDecayMode) {
202 if (p->type() == xAOD::Type::Electron) {
203 if (fabs(decayMode) != 11)
204 continue;
205 } else if (p->type() == xAOD::Type::Muon) {
206 if (fabs(decayMode) != 13)
207 continue;
208 }
209 TLorentzVector vis = getTruthTauP4Vis(*truth_tau);
210 if (vis.DeltaR(p->p4()) < 0.2) {
211 return true;
212 }
213 }
214 }
215 }
216 // matching not found
217 return false;
218}
219
220//______________________________________________________________________________
221int TauTruthMatchingTool::getNTauDecayParticles(const xAOD::TauJet& xTau, int iPdgId, bool bCompareAbsoluteValues)
222{
223 const xAOD::TruthParticle* xTruthTau = getTruth(xTau);
224 if (xTruthTau == nullptr)
225 {
226 ATH_MSG_DEBUG("no truth particle was found, return 0");
227 return 0;
228 }
229 static const SG::ConstAccessor<std::vector<int> > accDecayModeVector("DecayModeVector");
230 if (!accDecayModeVector.isAvailable(*xTruthTau))
231 {
232 ATH_MSG_INFO("found truth particle is not a truth tau, return 0");
233 return 0;
234 }
235 return getNTauDecayParticles(*xTruthTau,iPdgId, bCompareAbsoluteValues);
236}
237
238//______________________________________________________________________________
239int TauTruthMatchingTool::getNTauDecayParticles(const xAOD::TruthParticle& xTruthTau, int iPdgId, bool bCompareAbsoluteValues) const
240{
241 int iNum = 0;
242 static const SG::ConstAccessor<std::vector<int> > accDecayModeVector("DecayModeVector");
243 if (!accDecayModeVector.isAvailable(xTruthTau))
244 {
245 ATH_MSG_WARNING("passed truth particle is not a truth tau, return 0");
246 return 0;
247 }
248
249 for(auto iPdgId2 : accDecayModeVector(xTruthTau))
250 if (!bCompareAbsoluteValues)
251 {
252 if (iPdgId2 == iPdgId) iNum++;
253 }
254 else
255 {
256 if (std::abs(iPdgId2) == std::abs(iPdgId)) iNum++;
257 }
258 return iNum;
259}
260
261//______________________________________________________________________________
262xAOD::TauJetParameters::DecayMode TauTruthMatchingTool::getDecayMode(const xAOD::TauJet& xTau)
263{
264 const xAOD::TruthParticle* xTruthTau = getTruth(xTau);
265 if (xTruthTau == nullptr)
266 {
267 ATH_MSG_DEBUG("no truth particle was found, return Mode_Error");
269 }
270 static const SG::ConstAccessor<size_t> accNumCharged("numCharged");
271 if (!accNumCharged.isAvailable(*xTruthTau))
272 {
273 ATH_MSG_INFO("found truth particle is not a truth tau, return Mode_Error");
275 }
276 return getDecayMode(*xTruthTau);
277}
278
279//______________________________________________________________________________
280xAOD::TauJetParameters::DecayMode TauTruthMatchingTool::getDecayMode(const xAOD::TruthParticle& xTruthTau) const
281{
282 static const SG::ConstAccessor<size_t> accNumCharged("numCharged");
283 if (!accNumCharged.isAvailable(xTruthTau))
284 {
285 ATH_MSG_WARNING("passed truth particle is not a truth tau, return Mode_Error");
287 }
288
289 int iCharged = getNTauDecayParticles(xTruthTau,MC::PIPLUS, true) + getNTauDecayParticles(xTruthTau,MC::KPLUS, true);
290 int iNeutral = getNTauDecayParticles(xTruthTau,MC::PI0, true);
291 if (iCharged == 1)
292 {
293 if (iNeutral == 0) return xAOD::TauJetParameters::DecayMode::Mode_1p0n;
294 if (iNeutral == 1) return xAOD::TauJetParameters::DecayMode::Mode_1p1n;
295 if (iNeutral >= 2) return xAOD::TauJetParameters::DecayMode::Mode_1pXn;
296 }
297 else if (iCharged == 3)
298 {
299 if (iNeutral == 0) return xAOD::TauJetParameters::DecayMode::Mode_3p0n;
300 if (iNeutral >= 1) return xAOD::TauJetParameters::DecayMode::Mode_3pXn;
301 }
302
303 if (iCharged == 2 or iCharged == 4 or iCharged == 5)
305 if (iCharged == 0 or iCharged >=6)
307
308 // if you got here, something should have gone wrong
310}
311
313// Private Part //
315
316//______________________________________________________________________________
317StatusCode TauTruthMatchingTool::findTruthTau(const xAOD::TauJet& xTau,
318 TruthTausEvent& truthTausEvent) const
319{
320 // check if decorations were already added to the first passed tau
321 if (!m_bIsTruthMatchedAvailable.isValid()) {
322 static const SG::ConstAccessor<char> accIsTruthMatched("IsTruthMatched");
323 m_bIsTruthMatchedAvailable.set (accIsTruthMatched.isAvailable(xTau));
324 }
325 // check if decorations were already added to the first passed tau
326 if (!m_bIsTruthParticleLinkAvailable.isValid()) {
328 accTruthParticleLink("truthParticleLink");
329 m_bIsTruthParticleLinkAvailable.set (accTruthParticleLink.isAvailable(xTau));
330 }
331
332 if (*m_bIsTruthMatchedAvailable.ptr() || *m_bIsTruthParticleLinkAvailable.ptr()) {
333 if (!m_bForceCheckTruthMatch) return StatusCode::SUCCESS;
334 }
335
336 // only search for truth taus once
337
338 // need to be reviewed
339
340 if (m_bTruthTauAvailable)
341 return checkTruthMatch(xTau, *truthTausEvent.m_xTruthTauContainerConst, truthTausEvent);
342 else
343 return checkTruthMatch(xTau, *truthTausEvent.m_xTruthTauContainer, truthTausEvent);
344}
345
346//______________________________________________________________________________
347StatusCode TauTruthMatchingTool::checkTruthMatch (const xAOD::TauJet& xTau, const xAOD::TruthParticleContainer& xTruthTauContainer, const TruthTausEvent& truthTausEvent) const
348{
349 const xAOD::TruthParticle* xTruthMatch = nullptr;
350 const xAOD::Jet* xTruthJetMatch = nullptr;
351 TruthMatchedParticleType eTruthMatchedParticleType = Unknown;
352 static const SG::Decorator<char> decIsTruthMatched("IsTruthMatched");
353 static const SG::Decorator< ElementLink< xAOD::JetContainer > > decTruthJetLink("truthJetLink");
354
355 for (auto xTruthTauIt : xTruthTauContainer)
356 {
357 TLorentzVector vTruthVisTLV;
358 vTruthVisTLV.SetPtEtaPhiM(m_accPtVis(*xTruthTauIt),
359 m_accEtaVis(*xTruthTauIt),
360 m_accPhiVis(*xTruthTauIt),
361 m_accMVis(*xTruthTauIt));
362 if (xTau.p4().DeltaR(vTruthVisTLV) <= m_dMaxDeltaR)
363 {
364 static const SG::ConstAccessor<char> accIsHadronicTau("IsHadronicTau");
365 if (static_cast<bool>(accIsHadronicTau(*xTruthTauIt)))
366 eTruthMatchedParticleType = TruthHadronicTau;
367 else
368 eTruthMatchedParticleType = TruthLeptonicTau;
369
370 xTruthMatch = xTruthTauIt;
371 break;
372 }
373 }
374
375 double dPtMax = 0.;
376 if (!xTruthMatch and truthTausEvent.m_xTruthMuonContainerConst)
377 {
378 dPtMax = 0.;
379 for (auto xTruthMuonIt : *truthTausEvent.m_xTruthMuonContainerConst)
380 {
381 if (xTau.p4().DeltaR(xTruthMuonIt->p4()) <= m_dMaxDeltaR)
382 {
383 if (xTruthMuonIt->pt()<dPtMax)
384 continue;
385 eTruthMatchedParticleType = TruthMuon;
386 xTruthMatch = xTruthMuonIt;
387 dPtMax = xTruthMuonIt->pt();
388 }
389 }
390 }
391
392 if (!xTruthMatch and truthTausEvent.m_xTruthElectronContainerConst)
393 {
394 dPtMax = 0.;
395 for (auto xTruthElectronIt : *truthTausEvent.m_xTruthElectronContainerConst)
396 {
397 if (xTau.p4().DeltaR(xTruthElectronIt->p4()) <= m_dMaxDeltaR)
398 {
399 if (xTruthElectronIt->pt()<dPtMax)
400 continue;
401 eTruthMatchedParticleType = TruthElectron;
402 xTruthMatch = xTruthElectronIt;
403 dPtMax = xTruthElectronIt->pt();
404 }
405 }
406 }
407
408 if (truthTausEvent.m_xTruthJetContainerConst)
409 {
410 dPtMax = 0.;
411 for (auto xTruthJetIt : *truthTausEvent.m_xTruthJetContainerConst)
412 {
413 if (xTau.p4().DeltaR(xTruthJetIt->p4()) <= m_dMaxDeltaR)
414 {
415 if (xTruthJetIt->pt()<dPtMax)
416 continue;
417 xTruthJetMatch = xTruthJetIt;
418 dPtMax = xTruthJetIt->pt();
419 }
420 }
421 }
422
423 if (xTruthMatch)
424 decIsTruthMatched(xTau) = (char)true;
425 else
426 decIsTruthMatched(xTau) = (char)false;
427
428 if (xTruthJetMatch)
429 {
430 ElementLink < xAOD::JetContainer > lTruthParticleLink(xTruthJetMatch, *truthTausEvent.m_xTruthJetContainerConst);
431 decTruthJetLink(xTau) = lTruthParticleLink;
432 }
433 else
434 {
435 ElementLink < xAOD::JetContainer > lTruthParticleLink;
436 decTruthJetLink(xTau) = lTruthParticleLink;
437 }
438
439 // create link to the original TruthParticle
440 static const SG::Decorator< ElementLink< xAOD::TruthParticleContainer > > decTruthParticleLink("truthParticleLink");
441
442 if (xTruthMatch)
443 {
444 if (eTruthMatchedParticleType == TruthHadronicTau or eTruthMatchedParticleType == TruthLeptonicTau)
445 {
446 ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthMatch, xTruthTauContainer);
447 decTruthParticleLink(xTau) = lTruthParticleLink;
448 }
449 else if (eTruthMatchedParticleType == TruthMuon)
450 {
451 ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthMatch, *truthTausEvent.m_xTruthMuonContainerConst);
452 decTruthParticleLink(xTau) = lTruthParticleLink;
453 }
454 else if (eTruthMatchedParticleType == TruthElectron)
455 {
456 ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink(xTruthMatch, *truthTausEvent.m_xTruthElectronContainerConst);
457 decTruthParticleLink(xTau) = lTruthParticleLink;
458 }
459 }
460 else
461 {
462 ElementLink < xAOD::TruthParticleContainer > lTruthParticleLink;
463 decTruthParticleLink(xTau) = lTruthParticleLink;
464 }
465
466 return StatusCode::SUCCESS;
467}
468
469
477StatusCode
478TauTruthMatchingTool::lockDecorations (const xAOD::TauJetContainer& taus) const
479{
481 static const SG::Decorator<char> decIsTruthMatched("IsTruthMatched");
482 static const SG::Decorator< ElementLink< xAOD::JetContainer > > decTruthJetLink("truthJetLink");
483 static const SG::Decorator< ElementLink< xAOD::TruthParticleContainer > > decTruthParticleLink("truthParticleLink");
484 taus_nc.lockDecoration (decIsTruthMatched.auxid());
485 taus_nc.lockDecoration (decTruthJetLink.auxid());
486 taus_nc.lockDecoration (decTruthParticleLink.auxid());
487 return StatusCode::SUCCESS;
488}
489
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
#define ADD_CMODE(name)
static Double_t taus
#define ATLAS_THREAD_SAFE
Helper class to provide constant type-safe access to aux data.
Class providing the definition of the 4-vector interface.
virtual double pt() const
The transverse momentum ( ) of the particle.
Definition Jet_v1.cxx:44
virtual FourMom_t p4() const
The full 4-momentum of the particle.
Definition TauJet_v3.cxx:96
virtual double pt() const override final
The transverse momentum ( ) of the particle.
static const int PI0
static const int KPLUS
static const int PIPLUS
SG::Decorator< T, ALLOC > Decorator
Helper class to provide type-safe access to aux data, specialized for JaggedVecElt.
Definition AuxElement.h:576
@ Muon
The object is a muon.
Definition ObjectType.h:48
@ Electron
The object is an electron.
Definition ObjectType.h:46
Jet_v1 Jet
Definition of the current "jet version".
TauJet_v3 TauJet
Definition of the current "tau version".
Definition TauJet.h:17
TruthParticle_v1 TruthParticle
Typedef to implementation.
TauJetContainer_v3 TauJetContainer
Definition of the current "taujet container version".
TruthParticleContainer_v1 TruthParticleContainer
Declare the latest version of the truth particle container.