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