ATLAS Offline Software
Loading...
Searching...
No Matches
MCTruthClassifier Class Reference

#include <MCTruthClassifier.h>

Inheritance diagram for MCTruthClassifier:
Collaboration diagram for MCTruthClassifier:

Public Member Functions

 MCTruthClassifier (const std::string &type)
virtual ~MCTruthClassifier ()=default
virtual StatusCode initialize () override
 Dummy implementation of the initialisation function.
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleTruthClassifier (const xAOD::TruthParticle *, MCTruthPartClassifier::Info *info=nullptr) const override final
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleHepMCTruthClassifier (const HepMcParticleLink &theLink, MCTruthPartClassifier::Info *info=nullptr) const override final
virtual const xAOD::TruthParticlegetGenPart (const xAOD::TrackParticle *, MCTruthPartClassifier::Info *info=nullptr) const override final
virtual const xAOD::TruthParticleegammaClusMatch (const xAOD::CaloCluster *, bool, MCTruthPartClassifier::Info *info) const override final
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleTruthClassifier (const xAOD::TrackParticle *, MCTruthPartClassifier::Info *info=nullptr) const override final
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleTruthClassifier (const xAOD::Electron *, MCTruthPartClassifier::Info *info=nullptr) const override final
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleTruthClassifier (const xAOD::Photon *, MCTruthPartClassifier::Info *info=nullptr) const override final
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleTruthClassifier (const xAOD::Muon *, MCTruthPartClassifier::Info *info=nullptr) const override final
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleTruthClassifier (const xAOD::CaloCluster *, MCTruthPartClassifier::Info *info=nullptr) const override final
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleTruthClassifier (const xAOD::Jet *, bool DR, MCTruthPartClassifier::Info *info=nullptr) const override final
virtual void print () const
 Print the state of the tool.
ServiceHandle< StoreGateSvc > & evtStore ()
 The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
const ServiceHandle< StoreGateSvc > & detStore () const
 The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.
virtual StatusCode sysInitialize () override
 Perform system initialization for an algorithm.
virtual StatusCode sysStart () override
 Handle START transition.
virtual std::vector< Gaudi::DataHandle * > inputHandles () const override
 Return this algorithm's input handles.
virtual std::vector< Gaudi::DataHandle * > outputHandles () const override
 Return this algorithm's output handles.
Gaudi::Details::PropertyBase & declareProperty (Gaudi::Property< T, V, H > &t)
void updateVHKA (Gaudi::Details::PropertyBase &)
MsgStream & msg () const
bool msgLvl (const MSG::Level lvl) const
Additional helper functions, not directly mimicking Athena
template<class T>
const T * getProperty (const std::string &name) const
 Get one of the tool's properties.
const std::string & msg_level_name () const __attribute__((deprecated))
 A deprecated function for getting the message level's name.
const std::string & getName (const void *ptr) const
 Get the name of an object that is / should be in the event store.
SG::sgkey_t getKey (const void *ptr) const
 Get the (hashed) key of an object that is in the event store.

Protected Member Functions

void renounceArray (SG::VarHandleKeyArray &handlesArray)
 remove all handles from I/O resolution
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce (T &h)
void extraDeps_update_handler (Gaudi::Details::PropertyBase &ExtraDeps)
 Add StoreName to extra input/output deps as needed.

Private Types

typedef ServiceHandle< StoreGateSvcStoreGateSvc_t

Private Member Functions

MCTruthPartClassifier::ParticleOrigin defOrigOfElectron (const xAOD::TruthParticleContainer &xTruthParticleContainer, const xAOD::TruthParticle *, bool &isPrompt, MCTruthPartClassifier::Info &info) const
 namespace
MCTruthPartClassifier::ParticleOrigin defOrigOfMuon (const xAOD::TruthParticleContainer &xTruthParticleContainer, const xAOD::TruthParticle *, bool &isPrompt, MCTruthPartClassifier::Info &info) const
MCTruthPartClassifier::ParticleOrigin defOrigOfTau (const xAOD::TruthParticleContainer &xTruthParticleContainer, const xAOD::TruthParticle *, int motherPDG, MCTruthPartClassifier::Info &info) const
MCTruthPartClassifier::ParticleOrigin defOrigOfPhoton (const xAOD::TruthParticleContainer &xTruthParticleContainer, const xAOD::TruthParticle *, bool &isPrompt, MCTruthPartClassifier::Info &info) const
MCTruthPartClassifier::ParticleOrigin defOrigOfNeutrino (const xAOD::TruthParticleContainer &xTruthParticleContainer, const xAOD::TruthParticle *, bool &isPrompt, MCTruthPartClassifier::Info &info) const
bool genPartToCalo (const EventContext &ctx, const xAOD::CaloCluster *clus, const xAOD::TruthParticle *thePart, bool isFwrdEle, double &dRmatch, bool &isNarrowCone, const CaloDetDescrManager &caloDDMgr) const
void findJetConstituents (const xAOD::Jet *, std::set< const xAOD::TruthParticle * > &constituents, bool DR) const
Gaudi::Details::PropertyBase & declareGaudiProperty (Gaudi::Property< T, V, H > &hndl, const SG::VarHandleKeyType &)
 specialization for handling Gaudi::Property<SG::VarHandleKey>

Private Attributes

SG::ReadHandleKey< xAOD::TruthParticleContainerm_truthParticleContainerKey {this,"xAODTruthParticleContainerName","TruthParticles","ReadHandleKey for xAOD::TruthParticleContainer"}
ToolHandle< Trk::IParticleCaloExtensionToolm_caloExtensionTool {this,"ParticleCaloExtensionTool",""}
SG::ReadCondHandleKey< CaloDetDescrManagerm_caloMgrKey {this,"CaloDetDescrManager",""}
ToolHandle< xAOD::ITruthParticlesInConeToolm_truthInConeTool {this,"TruthInConeTool","xAOD::TruthParticlesInConeTool/TruthParticlesInConeTool"}
bool m_FwdElectronUseG4Sel
float m_FwdElectronTruthExtrEtaCut
float m_FwdElectronTruthExtrEtaWindowCut
float m_partExtrConeEta
float m_partExtrConePhi
bool m_useCaching
float m_phtClasConePhi
float m_phtClasConeEta
float m_phtdRtoTrCut
float m_fwrdEledRtoTrCut
bool m_ROICone
float m_pTChargePartCut
float m_pTNeutralPartCut
bool m_inclG4part
SG::ReadHandleKey< xAODTruthParticleLinkVectorm_truthLinkVecReadHandleKey {this,"xAODTruthLinkVector","xAODTruthLinks", "ReadHandleKey for xAODTruthParticleLinkVector"}
float m_deltaRMatchCut
float m_deltaPhiMatchCut
int m_NumOfSiHitsCut
float m_jetPartDRMatch
StoreGateSvc_t m_evtStore
 Pointer to StoreGate (event store by default).
StoreGateSvc_t m_detStore
 Pointer to StoreGate (detector store by default).
std::vector< SG::VarHandleKeyArray * > m_vhka
bool m_varHandleArraysDeclared

Detailed Description

Definition at line 55 of file MCTruthClassifier.h.

Member Typedef Documentation

◆ StoreGateSvc_t

typedef ServiceHandle<StoreGateSvc> AthCommonDataStore< AthCommonMsg< AlgTool > >::StoreGateSvc_t
privateinherited

Definition at line 388 of file AthCommonDataStore.h.

Constructor & Destructor Documentation

◆ MCTruthClassifier()

MCTruthClassifier::MCTruthClassifier ( const std::string & type)
inline

Definition at line 60 of file MCTruthClassifier.h.

60 : asg::AsgTool(type) {
61#if !defined(XAOD_ANALYSIS) && !defined(GENERATIONBASE)
62 declareProperty("FwdElectronUseG4Sel", m_FwdElectronUseG4Sel = true,
63 "Use Geant4 selection for forward electrons calo clusters");
64 declareProperty("FwdElectronTruthExtrEtaCut",
66 "Cut on the eta of the truth Particles to be extrapolated "
67 "for Fwd electrons");
69 "FwdElectronTruthExtrEtaWindowCut",
71 "Cut on the delta eta of the truth Particles to be extrapolated for "
72 "Fwd electrons and the current FwdElectron");
73 declareProperty("partExtrConePhi", m_partExtrConePhi = 0.4);
74 declareProperty("partExtrConeEta", m_partExtrConeEta = 0.2);
75 declareProperty("phtClasConePhi", m_phtClasConePhi = 0.05);
76 declareProperty("phtClasConeEta", m_phtClasConeEta = 0.025);
77 declareProperty("useCaching", m_useCaching = true);
78 declareProperty("phtdRtoTrCut", m_phtdRtoTrCut = 0.1);
79 declareProperty("fwrdEledRtoTrCut", m_fwrdEledRtoTrCut = 0.15);
80 declareProperty("ROICone", m_ROICone = false);
81 //AV: those below are needed in egammaClusMatch
82 declareProperty("pTChargePartCut", m_pTChargePartCut = 1.0);
83 declareProperty("pTNeutralPartCut", m_pTNeutralPartCut = 0.);
84 declareProperty("inclG4part", m_inclG4part = false);
85#endif
86#ifndef GENERATIONBASE
87 declareProperty("deltaRMatchCut", m_deltaRMatchCut = 0.2);
88 declareProperty("deltaPhiMatchCut", m_deltaPhiMatchCut = 0.2);
89 declareProperty("NumOfSiHitsCut", m_NumOfSiHitsCut = 3);
90 declareProperty("jetPartDRMatch", m_jetPartDRMatch = 0.4);
91#endif
92 }
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
float m_FwdElectronTruthExtrEtaWindowCut

◆ ~MCTruthClassifier()

virtual MCTruthClassifier::~MCTruthClassifier ( )
virtualdefault

Member Function Documentation

◆ declareGaudiProperty()

Gaudi::Details::PropertyBase & AthCommonDataStore< AthCommonMsg< AlgTool > >::declareGaudiProperty ( Gaudi::Property< T, V, H > & hndl,
const SG::VarHandleKeyType &  )
inlineprivateinherited

specialization for handling Gaudi::Property<SG::VarHandleKey>

Definition at line 156 of file AthCommonDataStore.h.

158 {
160 hndl.value(),
161 hndl.documentation());
162
163 }

◆ declareProperty()

Gaudi::Details::PropertyBase & AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty ( Gaudi::Property< T, V, H > & t)
inlineinherited

Definition at line 145 of file AthCommonDataStore.h.

145 {
146 typedef typename SG::HandleClassifier<T>::type htype;
148 }
Gaudi::Details::PropertyBase & declareGaudiProperty(Gaudi::Property< T, V, H > &hndl, const SG::VarHandleKeyType &)
specialization for handling Gaudi::Property<SG::VarHandleKey>

◆ defOrigOfElectron()

ParticleOrigin MCTruthClassifier::defOrigOfElectron ( const xAOD::TruthParticleContainer & xTruthParticleContainer,
const xAOD::TruthParticle * thePart,
bool & isPrompt,
MCTruthPartClassifier::Info & info ) const
private

namespace

Definition at line 254 of file MCTruthClassifierGen.cxx.

258{
259 ATH_MSG_DEBUG("Executing DefOrigOfElectron ");
260
261 // Find the first copy of this particle stored in the xAOD::TruthParticleContainer (i.e. the particle prior to any interactions)
262 const xAOD::TruthParticle* thePriPart = MC::findMatching(xTruthParticleContainer, thePart);
263 if (!thePriPart) return NonDefined;
264 if (!MC::isElectron(thePriPart)) return NonDefined;
265
266 //-- to define electron outcome status
267 info.particleOutCome = defOutComeOfElectron(thePriPart);
268
269 const xAOD::TruthVertex* partProdVtx = thePriPart->hasProdVtx() ? thePriPart->prodVtx() : nullptr;
270 if (!partProdVtx) return NonDefined;
271
272 if (partProdVtx->nIncomingParticles() > 1) ATH_MSG_DEBUG("DefOrigOfElectron:: electron has more than one parent.");
273
274 const xAOD::TruthParticle* ancestor = MC::findMother(thePriPart);
275 info.setMotherProperties(ancestor);
276 if (!ancestor) { return NonDefined; } // After this point "ancestor" cannot be nullptr
277
278 // Start of method 1 of protecting against loops
279 bool samePart = TruthLoopDetectionMethod1(partProdVtx, ancestor);
280 // to resolve Sherpa loop
281 // End of method 1 of protecting against loops
282
283 if ((MC::isMuon(ancestor) || MC::isTau(ancestor) || MC::isW(ancestor)) && ancestor->hasProdVtx() && !samePart) {
284 int pPDG(0);
285 const xAOD::TruthParticle* ancestorParent{};
286 do {
287 pPDG = 0; // reset pPDG
288 ancestorParent = MC::findMother(ancestor);
289 // Start of method 2 of protecting against loops
290 // to prevent Sherpa loop
291 if (ancestor == ancestorParent) { break; }
292 if (TruthLoopDetectionMethod2(ancestor,ancestorParent)) {
293 ancestorParent = ancestor;
294 break;
295 }
296 // End of method 2 of protecting against loops
297 // FIXME why are slightly different criteria used in method 1 and method 2???
298 if (ancestorParent) {
299 pPDG = ancestorParent->pdgId(); // Only set pPDG in the case that we aren't in a loop.
300 if (MC::isMuon(pPDG) || MC::isTau(pPDG) || MC::isW(pPDG)) { // There will be another iteration so set ancestor to ancestorParent
301 ancestor = ancestorParent; // ancestorParent is not nullptr here
302 }
303 }
304 } while ((MC::isMuon(pPDG) || MC::isTau(pPDG) || MC::isW(pPDG)));
305
306 if (MC::isMuon(pPDG) || MC::isTau(pPDG) || MC::isW(pPDG) || MC::isZ(pPDG) || MC::isHiggs(pPDG) ||
307 MC::isMSSMHiggs(pPDG) || MC::isHeavyBoson(pPDG) || MC::isTop(pPDG) || // MSSM Higgs bosons, Heavy bosons( Z', Z'', W'+)
308 std::abs(pPDG) == MC::WBOSON_LRSM || MC::isNeutrinoRH(pPDG) || // Left-right symmetric model WBoson || Right-handed neutrino (Pythia-specific)
309 MC::isSUSY(pPDG)) {
310 ancestor = ancestorParent; // ancestorParent is not nullptr here
311 }
312 }
313
314 info.setMotherProperties(ancestor);
315 const int ancestorPDG = ancestor->pdgId();
316 const xAOD::TruthVertex* ancestorProdVtx = ancestor->hasProdVtx() ? ancestor->prodVtx() : nullptr;
317 partProdVtx = ancestor->decayVtx();
318 const int numOfParents = partProdVtx->nIncomingParticles();
319 const int numberOfChildren = partProdVtx->nOutgoingParticles();
320
321 // Determine decay products
322 auto DP = DecayProducts(partProdVtx);
323 const int NumOfPhot = DP.pd(MC::PHOTON);
324 const int NumOfEl = DP.pd(MC::ELECTRON);
325 const int NumOfPos = DP.pd(MC::POSITRON);
326 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
327 const int NumOfgluon = DP.apd(MC::GLUON);
328 const int NumOfElNeut = DP.apd(MC::NU_E);
329 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
330 const int NumOfMuPl = DP.pd(-MC::MUON);
331 const int NumOfMuMin = DP.pd(MC::MUON);
332 const int NumOfMuNeut = DP.apd(MC::NU_MU);
333 const int NumOfTau = DP.apd(MC::TAU);
334 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
335
336 samePart = false;
337 int NumOfNucFr(0);
338 const bool possibleNuclearFragment = (numOfParents == 1 && (MC::isPhoton(ancestorPDG) || MC::isElectron(ancestorPDG) || MC::isMuon(ancestorPDG) || std::abs(ancestorPDG) == MC::PIPLUS));
339 for (const auto& aChild: partProdVtx->particles_out()) {
340 if (!aChild) continue;
341 const int childPDG = aChild->pdgId();
342 if (std::abs(childPDG) == std::abs(ancestorPDG) && HepMC::is_same_generator_particle(aChild, ancestor )) samePart = true;
343 if (possibleNuclearFragment &&
344 (MC::isNucleus(childPDG) || childPDG == 0 || childPDG == MC::PROTON || childPDG == MC::NEUTRON || // FIXME Do we really expect particles with PDG_ID = 0 in the truth record?
345 std::abs(childPDG) == MC::PIPLUS || std::abs(childPDG) == MC::PI0))
346 NumOfNucFr++;
347 }
348 // End of section determining decay products
349
350 if (MC::isPhoton(ancestorPDG) && ancestorProdVtx) {
351 if (ancestorProdVtx->nIncomingParticles() > 1) { ATH_MSG_DEBUG("DefOrigOfElectron:: photon has more than one parent."); }
352 for (const auto& photonParent: ancestorProdVtx->particles_in()) {
353 if (!photonParent) continue;
354 info.photonMother = photonParent; // FIXME Just taking the first valid particle...
355 }
356 }
357
358 if ((MC::isPhoton(ancestorPDG) && numberOfChildren == 2 && NumOfEl == 1 && NumOfPos == 1) || (MC::isPhoton(ancestorPDG) && numberOfChildren == 1 && (NumOfEl == 1 || NumOfPos == 1))) return PhotonConv;
359
360 // e,gamma,pi+Nuclear->NuclearFragments+nuclons+e
361 if ((numOfParents == 1 && (MC::isPhoton(ancestorPDG) || MC::isElectron(ancestorPDG) || MC::isTau(ancestorPDG))) && numberOfChildren > 1 && NumOfNucFr != 0) return ElMagProc;
362
363 if (numOfParents == 1 && std::abs(ancestorPDG) == MC::PIPLUS && numberOfChildren > 2 && NumOfNucFr != 0) return ElMagProc;
364
365 // nuclear photo fission
366 if (MC::isPhoton(ancestorPDG) && numberOfChildren > 4 && NumOfNucFr != 0) return ElMagProc;
367
368 // unknown process el(pos)->el+pos??
369 if (MC::isElectron(ancestorPDG) && numberOfChildren == 2 && NumOfEl == 1 && NumOfPos == 1) return ElMagProc;
370
371 // unknown process el->el+el??
372 if (ancestorPDG == MC::ELECTRON && numberOfChildren == 2 && NumOfEl == 2 && NumOfPos == 0) return ElMagProc;
373
374 // unknown process pos->pos+pos??
375 if (ancestorPDG == MC::POSITRON && numberOfChildren == 2 && NumOfEl == 0 && NumOfPos == 2) return ElMagProc;
376
377 // unknown process pos/el->pos/el??
378 if (MC::isElectron(ancestorPDG) && !MC::isDecayed(ancestor) && ancestorPDG == thePriPart->pdgId() && numberOfChildren == 1 && !samePart) return ElMagProc;
379
380 // pi->pi+e+/e-; mu->mu+e+/e- ;
381 // gamma+ atom->gamma(the same) + e (compton scattering)
382 if (numberOfChildren == 2 && (NumOfEl == 1 || NumOfPos == 1) && !MC::isElectron(ancestorPDG) && samePart) return ElMagProc;
383
384 if ((ancestorPDG == MC::PI0 && numberOfChildren == 3 && NumOfPhot == 1 && NumOfEl == 1 && NumOfPos == 1) ||
385 (ancestorPDG == MC::PI0 && numberOfChildren == 4 && NumOfPhot == 0 && NumOfEl == 2 && NumOfPos == 2))
386 return DalitzDec;
387
388 // Quark weak decay
389 if (MC::isSMQuark(ancestorPDG) && numOfParents == 1 && numberOfChildren == 3 && NumOfquark == 1 && NumOfElNeut == 1) return QuarkWeakDec;
390
391 if (MC::isMuon(ancestorPDG) && NumOfNucFr != 0) return ElMagProc;
392
393 if (MC::isTop(ancestorPDG)) return top;
394
395 if (MC::isW(ancestorPDG) && ancestorProdVtx && ancestorProdVtx->nIncomingParticles() != 0) {
396
397 const xAOD::TruthVertex* prodVert = ancestorProdVtx;
398 const xAOD::TruthParticle* ptrPart{};
399 do {
400 ptrPart = prodVert->incomingParticle(0); // FIXME just taking the first one
401 prodVert = ptrPart->hasProdVtx() ? ptrPart->prodVtx() : nullptr;
402 } while (MC::isW(ptrPart) && prodVert);
403
404 if (prodVert && prodVert->nIncomingParticles() == 1) {
405 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_E) return NuREle; // Right-handed NU_E (Pythia-specific)
406 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_MU) return NuRMu; // Right-handed NU_MU (Pythia-specific)
407 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_TAU) return NuRTau; // Right-handed NU_TAU (Pythia-specific)
408 }
409 return WBoson;
410 }
411 if (MC::isW(ancestorPDG)) return WBoson;
412 if (MC::isZ(ancestorPDG)) return ZBoson;
413
414 // MadGraphPythia ZWW*->lllnulnu
415 if (numOfParents == 1 && numberOfChildren > 4 && (MC::isSMQuark(ancestorPDG) || MC::isGluon(ancestorPDG))) {
416
417 const xAOD::TruthParticle* thePartToCheck = thePriPart;
418 const xAOD::TruthParticle* theParent = thePriPart->hasProdVtx() ? thePriPart->prodVtx()->incomingParticle(0) : nullptr; // FIXME just taking the first one
419 if (theParent && MC::isElectron(theParent) && MC::isDecayed(theParent)) { thePartToCheck = theParent; }
420
421 bool isZboson = false;
422 bool isWboson = false;
423 bool skipnext = false;
424
425 for (unsigned int ipOut = 0; ipOut + 1 < partProdVtx->nOutgoingParticles(); ++ipOut) {
426 const xAOD::TruthParticle* aChild = partProdVtx->outgoingParticle(ipOut);
427 if (!aChild) continue;
428 const xAOD::TruthParticle* theNextChild = nullptr;
429 for (unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->nOutgoingParticles(); ipOut1++) {
430 theNextChild = partProdVtx->outgoingParticle(ipOut1);
431 if (theNextChild) break;
432 }
433 if (!theNextChild) continue;
434 if (skipnext) {
435 skipnext = false;
436 continue;
437 }
438
439 if (MC::isElectron(aChild) && MC::isElectron(theNextChild)) {
440 // Zboson
441 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
442 isZboson = true;
443 break;
444 }
445 skipnext = true;
446 } else if (MC::isElectron(aChild) && std::abs(theNextChild->pdgId()) == MC::NU_E) {
447 // WBoson
448 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
449 isWboson = true;
450 break;
451 }
452 skipnext = true;
453 }
454 }
455 if (isWboson) return WBoson;
456 if (isZboson) return ZBoson;
457 }
458 if (numOfParents == 2) {
459 //--Sherpa Z->ee
460 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && NumOfEl == 1 && NumOfPos == 1) return ZBoson;
461
462 //--Sherpa W->enu ??
463 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && (NumOfEl == 1 || NumOfPos == 1) && NumOfElNeut == 1) return WBoson;
464
465 const int pdg1 = partProdVtx->incomingParticle(0)->pdgId();
466 const int pdg2 = partProdVtx->incomingParticle(1)->pdgId();
467 //--Sherpa ZZ,ZW
468 if ((numberOfChildren - NumOfquark - NumOfgluon) == 4 &&
469 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
470 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) return DiBoson;
471
472 //--Sherpa VVV -- Note, have to allow for prompt photon radiation or these get lost
473 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 &&
474 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
475 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) return MultiBoson;
476
477 //--Sherpa tttt with all t->Wb; W->lnu
478 if ((numberOfChildren - NumOfquark - NumOfgluon) == 8 &&
479 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 8) &&
480 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) {
481 ATH_MSG_VERBOSE("MultiBoson for 4topLep");
482 return MultiBoson;
483 }
484
485 //--Sherpa Vgamma ( Z->ee+gamma or W->enu+gamma )
486 if ((numberOfChildren - NumOfquark - NumOfgluon) >= 3 && NumOfPhot >= 1 && NumOfEl == 1 && NumOfPos == 1) {
487 ATH_MSG_VERBOSE("Sherpa ee + gamma");
488 return ZBoson;
489 }
490 if ((numberOfChildren - NumOfquark - NumOfgluon) >= 3 && NumOfPhot >= 1 && (NumOfEl == 1 || NumOfPos == 1) && NumOfElNeut == 1) {
491 ATH_MSG_VERBOSE("Sherpa enu + gamma");
492 return WBoson;
493 }
494 }
495
496 // New Sherpa Z->ee
497 if (partProdVtx == ancestorProdVtx) {
498 int NumOfEleLoop = 0;
499 int NumOfLepLoop = 0;
500 int NumOfEleNeuLoop = 0;
501 for (const auto *const pout: partProdVtx->particles_out()) {
502 if (!pout) continue;
503 for (const auto *const pin: partProdVtx->particles_in()) {
504 if (!pin) continue;
505 if (!HepMC::is_same_particle(pout,pin)) continue;
506 if (MC::isElectron(pout)) NumOfEleLoop++;
507 if (std::abs(pout->pdgId()) == MC::NU_E) NumOfEleNeuLoop++;
508 if (MC::isSMLepton(pout)) NumOfLepLoop++;
509 break; // break out of inner loop after having found two matching particles
510 }
511 }
512 if (NumOfEleLoop == 2 && NumOfEleNeuLoop == 0) return ZBoson;
513 if (NumOfEleLoop == 1 && NumOfEleNeuLoop == 1) return WBoson;
514 if ((NumOfEleLoop == 4 && NumOfEleNeuLoop == 0) || (NumOfEleLoop == 3 && NumOfEleNeuLoop == 1) ||
515 (NumOfEleLoop == 2 && NumOfEleNeuLoop == 2)) return DiBoson;
516 if (NumOfLepLoop == 4) return DiBoson;
517 }
518
519 //-- McAtNLo
520
521 if (MC::isHiggs(ancestorPDG)) return Higgs;
522
523 if (MC::isMSSMHiggs(ancestorPDG)) return HiggsMSSM; // MSSM Higgs bosons
524
525 if (MC::isHeavyBoson(ancestorPDG)) return HeavyBoson; // Heavy bosons( Z', Z'', W'+)
526
527 if (MC::isMuon(ancestorPDG)) return Mu;
528 if (MC::isTau(ancestorPDG)) {
529 const ParticleOrigin tauOrig = defOrigOfTau(xTruthParticleContainer, ancestor, ancestorPDG, info);
530 const ParticleType tautype = defTypeOfTau(tauOrig);
531 return (tautype == IsoTau)?tauOrig:TauLep;
532 }
533
534 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM) return WBosonLRSM; // Left-right symmetric model WBoson (Pythia-specific)
535 if (std::abs(ancestorPDG) == MC::RH_NU_E) return NuREle; // Right-handed NU_E (Pythia-specific)
536 if (std::abs(ancestorPDG) == MC::RH_NU_MU) return NuRMu; // Right-handed NU_MU (Pythia-specific)
537 if (std::abs(ancestorPDG) == MC::RH_NU_TAU) return NuRTau; // Right-handed NU_TAU (Pythia-specific)
538 if (MC::isLeptoQuark(ancestorPDG) || NumOfLQ != 0) return LQ;
539 if (MC::isSUSY(ancestorPDG)) return SUSY;
540 if (MC::isBSM(ancestorPDG)) return OtherBSM;
541
542 const ParticleType pType = defTypeOfHadron(ancestorPDG);
543 if ((pType == BBbarMesonPart || pType == CCbarMesonPart) && ancestorProdVtx && MC::isHardScatteringVertex(ancestorProdVtx)) isPrompt = true;
544 return convHadronTypeToOrig(pType, ancestorPDG);
545}
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
ParticleType
Definition TruthClasses.h:8
@ CCbarMesonPart
@ IsoTau
@ BBbarMesonPart
ParticleOrigin
@ MultiBoson
@ SUSY
@ DalitzDec
@ NuRTau
@ DiBoson
@ ZBoson
@ top
@ HeavyBoson
@ ElMagProc
@ PhotonConv
@ NuRMu
@ QuarkWeakDec
@ LQ
@ Higgs
@ Mu
@ WBoson
@ WBosonLRSM
@ OtherBSM
@ HiggsMSSM
@ NuREle
@ TauLep
@ NonDefined
MCTruthPartClassifier::ParticleOrigin defOrigOfTau(const xAOD::TruthParticleContainer &xTruthParticleContainer, const xAOD::TruthParticle *, int motherPDG, MCTruthPartClassifier::Info &info) const
int pdgId() const
PDG ID code.
const TruthVertex_v1 * decayVtx() const
The decay vertex of this particle.
bool hasProdVtx() const
Check for a production vertex on this particle.
const TruthVertex_v1 * prodVtx() const
The production vertex of this particle.
const TruthParticle_v1 * outgoingParticle(size_t index) const
Get one of the outgoing particles.
const TruthParticle_v1 * incomingParticle(size_t index) const
Get one of the incoming particles.
std::vector< const TruthParticle * > particles_out() const
Get the outgoing particles.
size_t nOutgoingParticles() const
Get the number of outgoing particles.
size_t nIncomingParticles() const
Get the number of incoming particles.
std::vector< const TruthParticle * > particles_in() const
Get the incoming particles.
bool is_same_generator_particle(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same generated particle.
bool is_same_particle(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same particle.
ParticleOutCome defOutComeOfElectron(T thePart)
ParticleOrigin convHadronTypeToOrig(ParticleType pType, int motherPDG)
ParticleType defTypeOfTau(ParticleOrigin TauOrig)
ParticleType defTypeOfHadron(int pdg)
int isPrompt(const unsigned int classify, bool allow_prompt_tau_decays=true)
static const int PI0
static const int UQUARK
T findMatching(C TruthContainer, T p)
Function to find a particle in container.
bool isNeutrinoRH(const T &p)
PDG Rule 12: APID: Helper function for right-handed neutrino states These are generator defined PDG I...
bool isZ(const T &p)
static const int SQUARK
static const int NEUTRON
static const int DQUARK
static const int MUON
bool isHardScatteringVertex(T pVert)
Function to classify the vertex as hard scattering vertex.
bool isSMLepton(const T &p)
APID: the fourth generation leptons are not standard model leptons.
static const int CQUARK
bool isPhoton(const T &p)
bool isW(const T &p)
static const int PHOTON
static const int RH_NU_TAU
static const int WBOSON_LRSM
static const int TQUARK
static const int TAU
static const int GLUON
bool isElectron(const T &p)
static const int ELECTRON
static const int PIPLUS
bool isSMQuark(const T &p)
bool isTop(const T &p)
static const int POSITRON
bool isMuon(const T &p)
bool isSUSY(const T &p)
static const int NU_MU
bool isMSSMHiggs(const T &p)
APID: Additional Higgs bosons for MSSM (Used in MCTruthClassifier).
bool isDecayed(const T &p)
Identify if the particle decayed.
bool isQuark(const T &p)
PDG rule 2: Quarks and leptons are numbered consecutively starting from 1 and 11 respectively; to do ...
T findMother(T thePart)
Function to get a mother of particle. MCTruthClassifier legacy.
static const int NU_E
static const int BQUARK
bool isHiggs(const T &p)
APID: HIGGS boson is only one particle.
static const int LEPTOQUARK
static const int NU_TAU
bool isNucleus(const T &p)
PDG rule 16 Nuclear codes are given as 10-digit numbers ±10LZZZAAAI.
static const int RH_NU_MU
bool isGluon(const T &p)
bool isHeavyBoson(const T &p)
APID: Additional "Heavy"/"prime" versions of W and Z bosons (Used in MCTruthClassifier).
bool isLeptoQuark(const T &p)
PDG rule 11c: “One-of-a-kind” exotic particles are assigned numbers in the range 41–80.
static const int RH_NU_E
PDG Rule 12: Generator defined PDG ID values for right handed neutrinos and corresponding W+ boson fr...
bool isTau(const T &p)
static const int PROTON
bool isBSM(const T &p)
APID: graviton and all Higgs extensions are BSM.
TruthVertex_v1 TruthVertex
Typedef to implementation.
Definition TruthVertex.h:15
TruthParticle_v1 TruthParticle
Typedef to implementation.

◆ defOrigOfMuon()

ParticleOrigin MCTruthClassifier::defOrigOfMuon ( const xAOD::TruthParticleContainer & xTruthParticleContainer,
const xAOD::TruthParticle * thePart,
bool & isPrompt,
MCTruthPartClassifier::Info & info ) const
private

Definition at line 548 of file MCTruthClassifierGen.cxx.

552{
553 ATH_MSG_DEBUG("Executing DefOrigOfMuon ");
554
555 // Find the first copy of this particle stored in the xAOD::TruthParticleContainer (i.e. the particle prior to any interactions)
556 const xAOD::TruthParticle* thePriPart = MC::findMatching(xTruthParticleContainer, thePart);
557 if (!thePriPart) return NonDefined;
558 if (!MC::isMuon(thePriPart)) return NonDefined;
559
560 //-- to define muon outcome status
561 info.particleOutCome = defOutComeOfMuon(thePriPart);
562
563 const xAOD::TruthVertex* partProdVtx = thePriPart->hasProdVtx() ? thePriPart->prodVtx() : nullptr;
564 if (!partProdVtx) return NonDefined;
565
566 if (partProdVtx->nIncomingParticles() > 1) ATH_MSG_DEBUG("DefOrigOfMuon:: muon has more than one parent.");
567
568 const xAOD::TruthParticle* ancestor = MC::findMother(thePriPart);
569 info.setMotherProperties(ancestor);
570 if (!ancestor) { return NonDefined; } // ancestor is not a nullptr beyond this point
571
572 // "method 1" for finding Sherpa loops from defOrigOfElectron not used here. Why?
573
574 if ((MC::isTau(ancestor)|| MC::isW(ancestor)) && ancestor->hasProdVtx()) {
575 int pPDG(0);
576 const xAOD::TruthParticle* ancestorParent{};
577 do {
578 pPDG = 0;
579 ancestorParent = MC::findMother(ancestor);
580 // Start of method 2 of protecting against loops
581 // to prevent Sherpa loop
582 if (ancestor == ancestorParent) { break; }
583 if (TruthLoopDetectionMethod2(ancestor,ancestorParent)) {
584 ancestorParent = ancestor;
585 break;
586 }
587 // End of method 2 of protecting against loops
588
589 if (ancestorParent) {
590 pPDG = ancestorParent->pdgId();// Only set pPDG in the case that we aren't in a loop.
591 if (MC::isMuon(pPDG) || MC::isTau(pPDG) || MC::isW(pPDG)) { // FIXME should this be (MC::isTau(pPDG) || MC::isW(pPDG)) ???
592 // There will be another iteration so set ancestor to ancestorParent
593 ancestor = ancestorParent; // ancestorParent is not nullptr here
594 }
595 }
596 } while ((MC::isMuon(pPDG) || MC::isTau(pPDG) || MC::isW(pPDG))); // FIXME should this be (MC::isTau(pPDG) || MC::isW(pPDG)) ???
597
598 if (MC::isTau(pPDG) || MC::isW(pPDG) || MC::isZ(pPDG) || MC::isHiggs(pPDG) ||
599 MC::isMSSMHiggs(pPDG) || MC::isHeavyBoson(pPDG) || MC::isTop(pPDG) || // MSSM Higgs bosons, Heavy bosons( Z', Z'', W'+)
600 std::abs(pPDG) == MC::WBOSON_LRSM || MC::isNeutrinoRH(pPDG) || // Left-right symmetric model WBoson || Right-handed neutrino (Pythia-specific)
601 MC::isSUSY(pPDG)) {
602 ancestor = ancestorParent; // ancestorParent is not nullptr here
603 }
604 }
605
606 info.setMotherProperties(ancestor);
607 const int ancestorPDG = ancestor->pdgId();
608 const xAOD::TruthVertex* ancestorProdVtx = ancestor->hasProdVtx() ? ancestor->prodVtx() : nullptr;
609 partProdVtx = ancestor->decayVtx();
610 const int numOfParents = partProdVtx->nIncomingParticles();
611 const int numberOfChildren = partProdVtx->nOutgoingParticles();
612
613 // Determine decay products
614 auto DP = DecayProducts(partProdVtx);
615 const int NumOfPhot = DP.pd(MC::PHOTON);
616 const int NumOfEl = DP.pd(MC::ELECTRON);
617 const int NumOfPos = DP.pd(MC::POSITRON);
618 const int NumOfElNeut = DP.apd(MC::NU_E);
619 const int NumOfMuNeut = DP.apd(MC::NU_MU);
620 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
621 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
622 const int NumOfgluon = DP.apd(MC::GLUON);
623 const int NumOfMuPl = DP.pd(-MC::MUON);
624 const int NumOfMuMin = DP.pd(MC::MUON);
625 const int NumOfTau = DP.apd(MC::TAU);
626 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
627 // End of section determining decay products
628
629 if (std::abs(ancestorPDG) == MC::PIPLUS && numberOfChildren == 2 && NumOfMuNeut == 1) return PionDecay;
630 if (std::abs(ancestorPDG) == MC::KPLUS && numberOfChildren == 2 && NumOfMuNeut == 1) return KaonDecay;
631 if (MC::isTau(ancestorPDG)) {
632 const ParticleOrigin tauOrig = defOrigOfTau(xTruthParticleContainer, ancestor, ancestorPDG, info);
633 const ParticleType tautype = defTypeOfTau(tauOrig);
634 return (tautype == IsoTau)?tauOrig:TauLep;
635 }
636
637 if (MC::isTop(ancestorPDG)) return top;
638 // Quark weak decay
639 if (MC::isSMQuark(ancestorPDG) && numOfParents == 1 && numberOfChildren == 3 && NumOfquark == 1 && NumOfMuNeut == 1) return QuarkWeakDec;
640
641 if (MC::isW(ancestorPDG) && ancestorProdVtx && ancestorProdVtx->nIncomingParticles() != 0) {
642 const xAOD::TruthVertex* prodVert = ancestorProdVtx;
643 const xAOD::TruthParticle* itrP;
644 do {
645 itrP = prodVert->incomingParticle(0); // FIXME just taking the first one
646 prodVert = itrP->hasProdVtx() ? itrP->prodVtx() : nullptr;
647 } while (MC::isW(itrP) && prodVert);
648
649 if (prodVert && prodVert->nIncomingParticles() == 1) {
650 if (std::abs(itrP->pdgId()) == MC::RH_NU_E) return NuREle; // Right-handed NU_E (Pythia-specific)
651 if (std::abs(itrP->pdgId()) == MC::RH_NU_MU) return NuRMu; // Right-handed NU_MU (Pythia-specific)
652 if (std::abs(itrP->pdgId()) == MC::RH_NU_TAU) return NuRTau; // Right-handed NU_TAU (Pythia-specific)
653 }
654 return WBoson;
655 }
656 if (MC::isW(ancestorPDG)) return WBoson;
657 if (MC::isZ(ancestorPDG)) return ZBoson;
658 if (MC::isPhoton(ancestorPDG) && numberOfChildren == 2 && NumOfMuMin == 1 && NumOfMuPl == 1) return PhotonConv;
659 //-- Exotics
660
661 // MadGraphPythia ZWW*->lllnulnu
662 if (numOfParents == 1 && numberOfChildren > 4 && (MC::isSMQuark(ancestorPDG) || MC::isGluon(ancestorPDG))) {
663 bool isZboson = false;
664 bool isWboson = false;
665 bool skipnext = false;
666 for (unsigned int ipOut = 0; ipOut + 1 < partProdVtx->nOutgoingParticles(); ipOut++) {
667 if (skipnext) {
668 skipnext = false;
669 continue;
670 }
671 const xAOD::TruthParticle* aChild = partProdVtx->outgoingParticle(ipOut);
672 if (!aChild) continue;
673 const xAOD::TruthParticle* theNextChild{};
674 for (unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->nOutgoingParticles(); ipOut1++) {
675 theNextChild = partProdVtx->outgoingParticle(ipOut1);
676 if (theNextChild) break;
677 }
678 if (!theNextChild) continue;
679 if (MC::isMuon(aChild) && MC::isMuon(theNextChild)) {
680 // Zboson
681 if (thePriPart == aChild || thePriPart == theNextChild) {
682 isZboson = true;
683 break;
684 }
685 skipnext = true;
686 } else if (MC::isMuon(aChild) && std::abs(theNextChild->pdgId()) == MC::NU_MU) {
687 // WBoson
688 if (thePriPart == aChild || thePriPart == theNextChild) {
689 isWboson = true;
690 break;
691 }
692 skipnext = true;
693 }
694 }
695 if (isWboson) return WBoson;
696 if (isZboson) return ZBoson;
697 }
698 if (numOfParents == 2 ) {
699 //--Sherpa Z->mumu
700 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && NumOfMuPl == 1 && NumOfMuMin == 1) return ZBoson;
701
702 //--Sherpa W->munu ??
703 // if(numOfParents==2&&(numberOfChildren-NumOfquark-NumOfgluon)==2&&(NumOfEl==1||NumOfPos==1)&&NumOfElNeut==1) return WBoson;
704 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && (NumOfMuPl == 1 || NumOfMuMin == 1) && NumOfMuNeut == 1) return WBoson;
705
706 const int pdg1 = partProdVtx->incomingParticle(0)->pdgId();
707 const int pdg2 = partProdVtx->incomingParticle(1)->pdgId();
708 //--Sherpa ZZ,ZW
709 if ((numberOfChildren - NumOfquark - NumOfgluon) == 4 &&
710 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
711 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) return DiBoson;
712
713 //--Sherpa VVV -- Note, have to allow for prompt photon radiation or these get lost
714 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 &&
715 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
716 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) return MultiBoson;
717
718 //--Sherpa tttt with all t->Wb; W->lnu
719 if ((numberOfChildren - NumOfquark - NumOfgluon) == 8 &&
720 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 8) &&
721 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) {
722 ATH_MSG_VERBOSE("MultiBoson for 4topLep");
723 return MultiBoson;
724 }
725
726 //--Sherpa Vgamma ( Z->ee+gamma or W->enu+gamma )
727 if ((numberOfChildren - NumOfquark - NumOfgluon) >= 3 && NumOfPhot >= 1 && NumOfMuPl == 1 && NumOfMuMin == 1) {
728 ATH_MSG_VERBOSE("Sherpa mumu + gamma");
729 return ZBoson;
730 }
731 if ((numberOfChildren - NumOfquark - NumOfgluon) >= 3 && NumOfPhot >= 1 && (NumOfMuPl == 1 || NumOfMuMin == 1) && NumOfMuNeut == 1) {
732 ATH_MSG_VERBOSE("Sherpa munu + gamma");
733 return WBoson;
734 }
735
736 }
737
738 //--New Sherpa Z->mumu
739 if (partProdVtx == ancestorProdVtx) {
740 int NumOfMuLoop = 0;
741 int NumOfMuNeuLoop = 0;
742 int NumOfLepLoop = 0;
743 for (const auto & pout: partProdVtx->particles_out()) {
744 if (!pout) continue;
745 for (const auto & pin: partProdVtx->particles_in()) {
746 if (!pin) continue;
747 if (HepMC::is_same_particle(pout,pin)) {
748 if (MC::isMuon(pout)) NumOfMuLoop++;
749 if (std::abs(pout->pdg_id()) == MC::NU_MU) NumOfMuNeuLoop++;
750 if (MC::isSMLepton(pout)) NumOfLepLoop++;
751 break; // break out of inner loop after having found two matching particles
752 }
753 }
754 }
755 if (NumOfMuLoop == 2 && NumOfMuNeuLoop == 0) return ZBoson;
756 if (NumOfMuLoop == 1 && NumOfMuNeuLoop == 1) return WBoson;
757 if ((NumOfMuLoop == 4 && NumOfMuNeuLoop == 0) || (NumOfMuLoop == 3 && NumOfMuNeuLoop == 1) ||
758 (NumOfMuLoop == 2 && NumOfMuNeuLoop == 2)) return DiBoson;
759 if (NumOfLepLoop == 4) return DiBoson;
760 }
761
762 //-- McAtNLo
763
764 if (MC::isHiggs(ancestorPDG)) return Higgs;
765
766 if (MC::isMSSMHiggs(ancestorPDG)) return HiggsMSSM; // MSSM Higgs bosons
767
768 if (MC::isHeavyBoson(ancestorPDG)) return HeavyBoson; // Heavy bosons( Z', Z'', W'+)
769
770 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM) return WBosonLRSM; // Left-right symmetric model WBoson (Pythia-specific)
771 if (std::abs(ancestorPDG) == MC::RH_NU_E) return NuREle; // Right-handed NU_E (Pythia-specific)
772 if (std::abs(ancestorPDG) == MC::RH_NU_MU) return NuRMu; // Right-handed NU_MU (Pythia-specific)
773 if (std::abs(ancestorPDG) == MC::RH_NU_TAU) return NuRTau; // Right-handed NU_TAU (Pythia-specific)
774 if (MC::isLeptoQuark(ancestorPDG) || NumOfLQ != 0) return LQ;
775 if (MC::isSUSY(ancestorPDG)) return SUSY;
776 if (MC::isBSM(ancestorPDG)) return OtherBSM;
777
778 const ParticleType pType = defTypeOfHadron(ancestorPDG);
779 if ((pType == BBbarMesonPart || pType == CCbarMesonPart) && ancestorProdVtx && MC::isHardScatteringVertex(ancestorProdVtx)) isPrompt = true;
780
781 return convHadronTypeToOrig(pType, ancestorPDG);
782}
@ PionDecay
@ KaonDecay
ParticleOutCome defOutComeOfMuon(T thePart)
static const int KPLUS

◆ defOrigOfNeutrino()

ParticleOrigin MCTruthClassifier::defOrigOfNeutrino ( const xAOD::TruthParticleContainer & xTruthParticleContainer,
const xAOD::TruthParticle * thePart,
bool & isPrompt,
MCTruthPartClassifier::Info & info ) const
private

Definition at line 1239 of file MCTruthClassifierGen.cxx.

1243{
1244 ATH_MSG_DEBUG("Executing DefOrigOfNeutrino ");
1245
1246 const int nuFlav = std::abs(thePart->pdgId());
1247 // Find the first copy of this particle stored in the xAOD::TruthParticleContainer (i.e. the particle prior to any interactions)
1248 const xAOD::TruthParticle* thePriPart = MC::findMatching(xTruthParticleContainer, thePart);
1249 if (!thePriPart) return NonDefined;
1250 if (std::abs(thePriPart->pdgId()) != nuFlav) return NonDefined; // FIXME should this be if (!MC::isSMNeutrino(thePriPart) || abs(thePriPart->pdgId()) != nuFlav) return NonDefined; // (Use MC::isNeutrino if 4th generation neutrinos OK)
1251
1252 //-- to define neutrino outcome status
1253 info.particleOutCome = NonInteract;
1254
1255 const xAOD::TruthVertex* partProdVtx = thePriPart->hasProdVtx() ? thePriPart->prodVtx() : nullptr;
1256 if (!partProdVtx) return NonDefined;
1257
1258 if (partProdVtx->nIncomingParticles() > 1) ATH_MSG_DEBUG("DefOrigOfNeutrino:: neutrino has more than one parent.");
1259
1260 const xAOD::TruthParticle* ancestor = MC::findMother(thePriPart);
1261 info.setMotherProperties(ancestor);
1262 if (!ancestor) { return NonDefined; } // ancestor is not a nullptr beyond this point
1263
1264 // Start of method 3 of protecting against loops
1265 // to resolve Sherpa loop
1266 bool samePart = TruthLoopDetectionMethod1(partProdVtx, ancestor);
1267 // End of method 3 of protecting against loops
1268
1269 if ((std::abs(ancestor->pdgId()) == nuFlav || MC::isTau(ancestor) || MC::isW(ancestor)) && ancestor->hasProdVtx() && !samePart) {
1270 int pPDG(0);
1271 const xAOD::TruthParticle* ancestorParent{};
1272 do {
1273 pPDG = 0;
1274 ancestorParent = MC::findMother(ancestor);
1275 // Start of method 2 of protecting against loops
1276 // to prevent Sherpa loop
1277 if (TruthLoopDetectionMethod2(ancestor,ancestorParent)) {
1278 ancestorParent = ancestor;
1279 break;
1280 }
1281 //
1282 if (ancestorParent) {
1283 pPDG = ancestorParent->pdgId(); // FIXME difference in behaviour compared to defOrigOfElectron/Muon pPDG set even if we are in a loop
1284 }
1285 // to prevent Sherpa loop
1286 if (ancestor == ancestorParent) { break; }
1287 // End of method 2 of protecting against Sherpa loops
1288 if (std::abs(pPDG) == nuFlav || MC::isTau(pPDG) || MC::isW(pPDG) ) {
1289 // There will be another iteration so set ancestor to ancestorParent
1290 ancestor = ancestorParent; // ancestorParent is not a nullptr
1291 info.setMotherProperties(ancestor); // FIXME difference in behaviour compared to MCTruthClassifier::defOrigOfElectron/Muon
1292 }
1293
1294 } while ((std::abs(pPDG) == nuFlav || MC::isTau(pPDG) || MC::isW(pPDG)));
1295
1296 if (std::abs(pPDG) == nuFlav || MC::isTau(pPDG) || MC::isW(pPDG) || MC::isZ(pPDG) || MC::isHiggs(pPDG) ||
1297 MC::isMSSMHiggs(pPDG) || MC::isHeavyBoson(pPDG) || MC::isTop(pPDG) || // MSSM Higgs bosons, Heavy bosons( Z', Z'', W'+)
1298 std::abs(pPDG) == MC::WBOSON_LRSM || MC::isNeutrinoRH(pPDG) || // Left-right symmetric model WBoson || Right-handed neutrino (Pythia-specific)
1299 MC::isSUSY(pPDG)) {
1300 ancestor = ancestorParent; // ancestorParent is not nullptr here
1301 info.setMotherProperties(ancestor);
1302 }
1303 }
1304 //if ancestor is still nullptr, we have a problem
1305 if (!ancestor) return NonDefined; // FIXME it should not be possible for ancestor to be nullptr at this point???
1306
1307 info.setMotherProperties(ancestor);
1308 const int ancestorPDG = ancestor->pdgId();
1309 partProdVtx = ancestor->decayVtx();
1310 const xAOD::TruthVertex* ancestorProdVtx = ancestor->hasProdVtx() ? ancestor->prodVtx() : nullptr;
1311 const int numOfParents = partProdVtx->nIncomingParticles();
1312 const int numberOfChildren = partProdVtx->nOutgoingParticles();
1313
1314 // Determine decay products
1315 auto DP = DecayProducts(partProdVtx);
1316 const int NumOfPhot = DP.pd(MC::PHOTON);
1317 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
1318 const int NumOfgluon = DP.apd(MC::GLUON);
1319 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
1320 const int NumOfElNeut = DP.apd(MC::NU_E);
1321 const int NumOfMuNeut = DP.apd(MC::NU_MU);
1322 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
1323 const int NumOfEl = DP.apd(MC::ELECTRON);
1324 const int NumOfMu = DP.apd(MC::MUON);
1325 const int NumOfTau = DP.apd(MC::TAU);
1326
1327 samePart = false;
1328 for (const auto& aChild: partProdVtx->particles_out()) {
1329 if (!aChild) continue;
1330 if (aChild->pdgId() == ancestorPDG && HepMC::is_same_generator_particle(aChild,ancestor)) {
1331 samePart = true;
1332 break;
1333 }
1334 }
1335 // End of section determining decay products
1336
1337 // Quark weak decay
1338 if (MC::isQuark(ancestorPDG) && numOfParents == 1 && numberOfChildren == 3 && NumOfquark == 1 && (NumOfEl == 1 || NumOfMu == 1 || NumOfTau == 1)) return QuarkWeakDec;
1339 if (MC::isTop(ancestorPDG)) return top;
1340
1341 if (MC::isW(ancestorPDG) && ancestorProdVtx && ancestorProdVtx->nIncomingParticles() != 0) {
1342 const xAOD::TruthVertex* prodVert = ancestorProdVtx;
1343 const xAOD::TruthParticle* ptrPart;
1344 do {
1345 ptrPart = prodVert->incomingParticle(0); // FIXME just taking the first one
1346 prodVert = ptrPart->hasProdVtx() ? ptrPart->prodVtx() : nullptr;
1347 } while (MC::isW(ptrPart) && prodVert);
1348
1349 if (prodVert && prodVert->nIncomingParticles() == 1) {
1350 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_E) return NuREle; // Right-handed NU_E (Pythia-specific)
1351 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_MU) return NuRMu; // Right-handed NU_MU (Pythia-specific)
1352 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_TAU) return NuRTau; // Right-handed NU_TAU (Pythia-specific)
1353 }
1354 return WBoson;
1355 }
1356 if (MC::isW(ancestorPDG)) return WBoson;
1357 if (MC::isZ(ancestorPDG)) return ZBoson;
1358
1359 //-- Exotics
1360
1361 // MadGraphPythia ZWW*->lllnulnu or ZWW*->nunulnulnu (don't even know if the latter is generated)
1362 if (numOfParents == 1 && numberOfChildren > 4 && (MC::isSMQuark(ancestorPDG) || MC::isGluon(ancestorPDG))) {
1363
1364 const xAOD::TruthParticle* thePartToCheck = thePriPart;
1365 const xAOD::TruthParticle* theParent = thePriPart->hasProdVtx() ? thePriPart->prodVtx()->incomingParticle(0) : nullptr; // FIXME just taking the first one
1366
1367 if (MC::isElectron(theParent) && MC::isDecayed(theParent)) { thePartToCheck = theParent; }
1368 bool isZboson = false;
1369 bool isWboson = false;
1370 bool skipnext = false;
1371
1372 for (unsigned int ipOut = 0; ipOut + 1 < partProdVtx->nOutgoingParticles(); ++ipOut) {
1373 const xAOD::TruthParticle* aChild = partProdVtx->outgoingParticle(ipOut);
1374 if (!aChild) continue;
1375 const xAOD::TruthParticle* theNextChild{};
1376 for (unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->nOutgoingParticles(); ipOut1++) {
1377 theNextChild = partProdVtx->outgoingParticle(ipOut1);
1378 if (theNextChild) break;
1379 }
1380 if (!theNextChild) continue;
1381
1382 if (skipnext) {
1383 skipnext = false;
1384 continue;
1385 }
1386
1387 const int apdgID1 = std::abs(aChild->pdgId());
1388 const int apdgID2 = std::abs(theNextChild->pdgId());
1389 if (apdgID1 == apdgID2 && MC::isSMNeutrino(apdgID1)) {
1390 // Zboson
1391 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
1392 isZboson = true;
1393 break;
1394 }
1395 skipnext = true;
1396 } else if ((apdgID1 == MC::ELECTRON && apdgID2 == MC::NU_E) ||
1397 (apdgID1 == MC::NU_E && apdgID2 == MC::ELECTRON) ||
1398 (apdgID1 == MC::MUON && apdgID2 == MC::NU_MU) ||
1399 (apdgID1 == MC::NU_MU && apdgID2 == MC::MUON) ||
1400 (apdgID1 == MC::TAU && apdgID2 == MC::NU_TAU) ||
1401 (apdgID1 == MC::NU_TAU && apdgID2 == MC::TAU)
1402 ) {
1403 // WBoson
1404 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
1405 isWboson = true;
1406 break;
1407 }
1408 skipnext = true;
1409 }
1410 }
1411 if (isWboson) return WBoson;
1412 if (isZboson) return ZBoson;
1413 }
1414
1415 if (numOfParents == 2) {
1416 //--Sherpa Z->nunu
1417 if ( (numberOfChildren - NumOfquark - NumOfgluon) == 2 && (NumOfElNeut == 2 || NumOfMuNeut == 2 || NumOfTauNeut == 2)) return ZBoson;
1418
1419 //--Sherpa W->enu ??
1420 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && ((NumOfEl == 1 && NumOfElNeut == 1) || (NumOfMu == 1 && NumOfMuNeut == 1) || (NumOfTau == 1 && NumOfTauNeut == 1))) return WBoson;
1421
1422 const int pdg1 = partProdVtx->incomingParticle(0)->pdgId();
1423 const int pdg2 = partProdVtx->incomingParticle(1)->pdgId();
1424 //--Sherpa ZZ,ZW
1425 if ( (numberOfChildren - NumOfquark - NumOfgluon) == 4 && (NumOfEl + NumOfMu + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
1426 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) return DiBoson;
1427
1428 //--Sherpa VVV -- Note, have to allow for prompt photon radiation or these get lost
1429 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 && (NumOfEl + NumOfMu + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
1430 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) return MultiBoson;
1431
1432 //--Sherpa Vgamma ( Z->nunu+gamma )
1433 if ((numberOfChildren - NumOfquark - NumOfgluon) >= 3 && NumOfPhot >= 1 && (NumOfElNeut == 2 || NumOfMuNeut == 2 || NumOfTauNeut == 2)) {
1434 ATH_MSG_VERBOSE("Sherpa nunu + gamma");
1435 return ZBoson;
1436 }
1437 }
1438
1439 // New Sherpa Z->nunu
1440 if (partProdVtx == ancestorProdVtx) {
1441 int NumOfLepLoop = 0;
1442 int NumOfNeuLoop = 0;
1443 for (const auto *const pout: partProdVtx->particles_out()) {
1444 if (!pout) continue;
1445 for (const auto *const pin: partProdVtx->particles_in()) {
1446 if (!pin) continue;
1447 if (HepMC::is_same_particle(pin,pout)) continue;
1448 const int apdgid = std::abs(pout->pdgId());
1449 if (MC::isSMLepton(apdgid)) {
1450 if (MC::isSMNeutrino(apdgid)) { NumOfNeuLoop++; }
1451 else { NumOfLepLoop++; }
1452 }
1453 break; // break out of inner loop after having found two matching particles
1454 }
1455 }
1456 if (NumOfNeuLoop == 2 && NumOfLepLoop == 0) return ZBoson;
1457 if (NumOfNeuLoop == 1 && NumOfLepLoop == 1) return WBoson;
1458 if (NumOfNeuLoop + NumOfLepLoop == 4) return DiBoson;
1459 }
1460
1461 //-- McAtNLo
1462
1463 if (MC::isHiggs(ancestorPDG)) return Higgs;
1464 if (MC::isMSSMHiggs(ancestorPDG)) return HiggsMSSM; // MSSM Higgs bosons
1465 if (MC::isHeavyBoson(ancestorPDG)) return HeavyBoson; // Heavy bosons( Z', Z'', W'+)
1466
1467 if (MC::isTau(ancestorPDG)) {
1468 const ParticleOrigin tauOrig = defOrigOfTau(xTruthParticleContainer, ancestor, ancestorPDG, info);
1469 const ParticleType tautype = defTypeOfTau(tauOrig);
1470 return (tautype == IsoTau)?tauOrig:TauLep;
1471 }
1472
1473 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM) return WBosonLRSM; // Left-right symmetric model WBoson (Pythia-specific)
1474 if (std::abs(ancestorPDG) == MC::RH_NU_E) return NuREle; // Right-handed NU_E (Pythia-specific)
1475 if (std::abs(ancestorPDG) == MC::RH_NU_MU) return NuRMu; // Right-handed NU_MU (Pythia-specific)
1476 if (std::abs(ancestorPDG) == MC::RH_NU_TAU) return NuRTau; // Right-handed NU_TAU (Pythia-specific)
1477 if (MC::isLeptoQuark(ancestorPDG) || NumOfLQ != 0) return LQ;
1478 if (MC::isSUSY(ancestorPDG)) return SUSY;
1479 if (MC::isBSM(ancestorPDG)) return OtherBSM;
1480
1481 const ParticleType pType = defTypeOfHadron(ancestorPDG);
1482 if ((pType == BBbarMesonPart || pType == CCbarMesonPart) && ancestorProdVtx && MC::isHardScatteringVertex(ancestorProdVtx)) isPrompt = true;
1483
1484 return convHadronTypeToOrig(pType, ancestorPDG);
1485}
@ NonInteract
bool isSMNeutrino(const T &p)

◆ defOrigOfPhoton()

ParticleOrigin MCTruthClassifier::defOrigOfPhoton ( const xAOD::TruthParticleContainer & xTruthParticleContainer,
const xAOD::TruthParticle * thePart,
bool & isPrompt,
MCTruthPartClassifier::Info & info ) const
private

Definition at line 976 of file MCTruthClassifierGen.cxx.

980{
981 if (!thePart) return NonDefined; // FIXME Why is this extra protection needed for this function and not the others?
982 ATH_MSG_DEBUG("Executing DefOrigOfPhoton ");
983
984 info.resetMotherProperties();
985 info.photonMother = nullptr;
986
987 // Find the first copy of this particle stored in the xAOD::TruthParticleContainer (i.e. the particle prior to any interactions)
988 const xAOD::TruthParticle* thePriPart = MC::findMatching(xTruthParticleContainer, thePart);
989 if (!thePriPart) return NonDefined;
990 if (!MC::isPhoton(thePriPart)) return NonDefined;
991
992 const xAOD::TruthVertex* partProdVtx = thePriPart->hasProdVtx() ? thePriPart->prodVtx() : nullptr;
993
994 //-- to define photon outcome status
995 info.particleOutCome = defOutComeOfPhoton(thePriPart);
996
997 if (!partProdVtx) return NonDefined;
998
999 int numOfParents = partProdVtx->nIncomingParticles();
1000 if (partProdVtx->nIncomingParticles() > 1) ATH_MSG_DEBUG("DefOrigOfPhoton:: photon has more than one parent.");
1001
1002 const xAOD::TruthParticle* ancestor = MC::findMother(thePriPart);
1003 info.setMotherProperties(ancestor);
1004 if (!ancestor) { return NonDefined; } // ancestor is not a nullptr beyond this point
1005
1006 int ancestorPDG = ancestor->pdgId();
1007 // "method 1" for finding Sherpa loops from defOrigOfElectron not used here. Why?
1008 const xAOD::TruthVertex* ancestorProdVtx = ancestor->hasProdVtx() ? ancestor->prodVtx() : nullptr;
1009
1010 partProdVtx = ancestor->decayVtx(); // FIXME how often does this line actually change the pointer???
1011 numOfParents = partProdVtx->nIncomingParticles();
1012
1013 const int numberOfChildren = partProdVtx->nOutgoingParticles();
1014
1015 // Determine decay products
1016 auto DP = DecayProducts(partProdVtx);
1017 const int NumOfEl = DP.pd(MC::ELECTRON);
1018 const int NumOfPos = DP.pd(MC::POSITRON);
1019 const int NumOfMu = DP.apd(MC::MUON);
1020 const int NumOfTau = DP.apd(MC::TAU);
1021 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
1022 const int NumOfLep = NumOfEl + NumOfPos + NumOfMu + NumOfTau;
1023 const int NumOfNeut = DP.apd({MC::NU_E,MC::NU_MU,MC::NU_TAU});
1024 const int NumOfPht = DP.pd(MC::PHOTON);
1025
1026 int childPDG(0);
1027 int NumOfPartons(0);
1028 int NumOfNucFr(0);
1029 const bool possibleNuclearFragment = (numOfParents == 1 && (MC::isPhoton(ancestorPDG) || MC::isElectron(ancestorPDG) || std::abs(ancestorPDG) == MC::PIPLUS));
1030 const xAOD::TruthParticle* child{};
1031 for (const auto& pout: partProdVtx->particles_out()) {
1032 if (!pout) continue;
1033 childPDG = pout->pdg_id();
1034 if (possibleNuclearFragment &&
1035 (MC::isNucleus(childPDG) || childPDG == 0 || childPDG == MC::PROTON || childPDG == MC::NEUTRON)) { // FIXME Do we really expect particles with PDG_ID = 0 in the truth record?
1036 NumOfNucFr++;
1037 }
1038 if (std::abs(childPDG) < MC::ELECTRON ||
1039 (std::abs(childPDG) > MC::NU_TAU && std::abs(childPDG) < 43 && !MC::isPhoton(childPDG))) {
1040 // FIXME Too loose? This definition picks up 4th generation quarks and leptons as well as all gauge bosons and leptoquarks.
1041 // Suggest MC::isSMQuark(childPDG) || (MC::isBoson(childPDG) && !MC::isPhoton(childPDG))
1042 // or maybe even MC::isSMQuark(childPDG) || MC::isGluon(childPDG)
1043 // AKA const int NumOfPartons = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK,MC::GLUON});
1044 NumOfPartons++;
1045 }
1046 if (childPDG == ancestorPDG) {
1047 child = pout;
1048 }
1049 }
1050 // End of section determining decay products
1051
1052 bool foundISR = false;
1053 bool foundFSR = false;
1054 if (numOfParents == 1 && numberOfChildren == 2 && child && HepMC::is_same_generator_particle(child, ancestor)) return BremPhot;
1055 if (numOfParents == 1 && numberOfChildren == 2 && MC::isElectron(ancestorPDG) && NumOfPht == 2) return ElMagProc;
1056
1057 // decay of W,Z and Higgs to lepton with FSR generated by Pythia
1058 if (numOfParents == 1 && numberOfChildren == 2 && (MC::isElectron(ancestorPDG) || MC::isMuon(ancestorPDG) || MC::isTau(ancestorPDG)) &&
1059 !(child && HepMC::is_same_generator_particle(child, ancestor)) && ancestorProdVtx &&
1060 ancestorProdVtx->nIncomingParticles() == 1) {
1061 int itr = 0;
1062 int PartPDG = 0;
1063 const xAOD::TruthVertex* prodVert = ancestorProdVtx;
1064 const xAOD::TruthVertex* Vert{};
1065 do {
1066 Vert = prodVert;
1067 for (const auto & pin: Vert->particles_in()) {
1068 if (!pin) continue;
1069 PartPDG = std::abs(pin->pdgId());
1070 prodVert = pin->prodVtx();
1071 if (MC::isZ(PartPDG) || MC::isW(PartPDG) || MC::isHiggs(PartPDG)) foundFSR = true;
1072 }
1073 itr++;
1074 if (itr > 100) { // FIXME Improve loop detection here?
1075 ATH_MSG_WARNING("DefOrigOfPhoton:: infinite while");
1076 break;
1077 }
1078 } while (prodVert && std::abs(ancestorPDG) == PartPDG);
1079
1080 if (foundFSR) return FSRPhot;
1081 }
1082
1083 // Nucl reaction
1084 // gamma+Nuclear=>gamma+Nucl.Fr+Nuclons+pions
1085 // e+Nuclear=>e+gamma+Nucl.Fr+Nuclons+pions
1086 // pi+Nuclear=>gamma+Nucl.Fr+Nuclons+pions
1087
1088 if ((numOfParents == 1 && (MC::isPhoton(ancestorPDG) || MC::isElectron(ancestorPDG)) && numberOfChildren > 2 && NumOfNucFr != 0) ||
1089 (numOfParents == 1 && std::abs(ancestorPDG) == MC::PIPLUS && numberOfChildren > 10 && NumOfNucFr != 0) ||
1090 (numOfParents == 1 && MC::isPhoton(ancestorPDG) && numberOfChildren > 10 && MC::isStable(ancestor)) ||
1091 (numOfParents == 1 && MC::isNucleus(ancestorPDG) && std::abs(ancestorPDG) != MC::PROTON)) // FIXME vetoing protons here to preserve previous behaviour
1092 return NucReact;
1093
1094 if (MC::isMuon(ancestorPDG) && NumOfMu == 0) return Mu;
1095 if (MC::isTau(ancestorPDG) && NumOfTau == 0) return TauLep;
1096
1097 if (numOfParents == 1 && ancestor->status() == 3) return (foundISR)? ISRPhot:UndrPhot; // FIXME foundISR is always false at this point
1098
1099 //-- to find initial and final state raiation and underline photons
1100 //-- SUSY
1101 if (numOfParents == 1 && (MC::isSMQuark(ancestorPDG) || MC::isGluon(ancestorPDG)) &&
1102 (numberOfChildren != NumOfPht + NumOfPartons || !MC::Pythia8::isConditionA(ancestor))) {
1103 for (const auto& pout: partProdVtx->particles_out()) {
1104 if (!pout) continue;
1105 if (ancestorPDG != pout->pdgId()) continue;
1106 const xAOD::TruthVertex* Vrtx = pout->decayVtx();
1107 if (!Vrtx) continue;
1108 if (Vrtx->nOutgoingParticles() != 1 && Vrtx->nIncomingParticles() == 1) continue;
1109 if (!Vrtx->outgoingParticle(0)) continue;
1110 if (Vrtx->outgoingParticle(0)->pdgId() == 91) foundISR = true; // Herwig "cluster"
1111 }
1112 return (foundISR)?ISRPhot:UndrPhot;
1113 }
1114
1115 //-- to find final state radiation
1116 //-- Exotics
1117
1118 // FSR from Photos
1119 //-- Exotics- CompHep
1120 if (numOfParents == 2 && ((MC::isElectron(ancestorPDG) && NumOfEl == 1 && NumOfPos == 1) || (MC::isMuon(ancestorPDG) && NumOfMu == 2) || (MC::isTau(ancestorPDG) && NumOfTau == 2))) {
1121 if (std::abs(partProdVtx->incomingParticle(0)->pdgId()) == std::abs(partProdVtx->incomingParticle(1)->pdgId())) return FSRPhot;
1122 }
1123
1124 if (numOfParents == 2 && NumOfLep == 1 && NumOfNeut == 1 && (MC::isElectron(ancestorPDG) || std::abs(ancestorPDG) == MC::NU_E)) return FSRPhot;
1125
1126 //-- Exotics - CompHep
1127 if (MC::isElectron(ancestorPDG) && numOfParents == 1 && numberOfChildren == 2 && (NumOfEl == 1 || NumOfPos == 1) && NumOfPht == 1 &&
1128 !( child && HepMC::is_same_generator_particle(child, ancestor)) && !HepMC::is_simulation_particle(child) && !HepMC::is_simulation_particle(ancestor))
1129 return FSRPhot;
1130
1131 // FSR from Photos
1132 if (MC::isZ(ancestorPDG) && ((NumOfEl + NumOfPos == 2 || NumOfEl + NumOfPos == 4) || (NumOfMu == 2 || NumOfMu == 4) || (NumOfTau == 2 || NumOfTau == 4)) && NumOfPht > 0) return FSRPhot;
1133
1134 if (NumOfPht > 0 && (std::abs(ancestorPDG) == MC::WBOSON_LRSM || MC::isNeutrinoRH(ancestorPDG))) return FSRPhot; // Left-right symmetric model WBoson || Right-handed neutrinos (Pythia-specific)
1135
1136 if (numOfParents == 2 && NumOfLQ == 1) return FSRPhot;
1137
1138 //--- other process
1139
1140 if (MC::isZ(ancestorPDG)) return ZBoson;
1141 if (MC::isW(ancestorPDG)) {
1142
1143 if (NumOfLep == 1 && NumOfNeut == 1 && numberOfChildren == NumOfLep + NumOfNeut + NumOfPht) return FSRPhot;
1144
1145 if (ancestorProdVtx && ancestorProdVtx->nIncomingParticles() != 0) {
1146 const xAOD::TruthVertex* prodVert = ancestorProdVtx;
1147 const xAOD::TruthParticle* itrP;
1148 do {
1149 itrP = prodVert->incomingParticle(0); // FIXME just taking the first one
1150 prodVert = itrP->hasProdVtx() ? itrP->prodVtx() : nullptr;
1151 } while (MC::isW(itrP) && prodVert);
1152
1153 if (prodVert && prodVert->nIncomingParticles() == 1 ) {
1154 if ( MC::isTau(itrP)) return TauLep;
1155 if ( MC::isMuon(itrP)) return Mu;
1156 if ( std::abs(itrP->pdgId()) == MC::RH_NU_E) return NuREle; // Right-handed NU_E (Pythia-specific)
1157 if ( std::abs(itrP->pdgId()) == MC::RH_NU_MU) return NuRMu; // Right-handed NU_MU (Pythia-specific)
1158 if ( std::abs(itrP->pdgId()) == MC::RH_NU_TAU) return NuRTau; // Right-handed NU_TAU (Pythia-specific)
1159 }
1160 } else
1161 return WBoson;
1162 }
1163
1164 // MadGraphPythia ZWW*->lllnulnu
1165 if (numOfParents == 1 && numberOfChildren > 4 && (MC::isSMQuark(ancestorPDG) || MC::isGluon(ancestorPDG))) {
1166 bool isZboson = false;
1167 bool isWboson = false;
1168 bool skipnext = false;
1169 for (unsigned int ipOut = 0; ipOut + 1 < partProdVtx->nOutgoingParticles(); ipOut++) {
1170 if (skipnext) {
1171 skipnext = false;
1172 continue;
1173 }
1174 const xAOD::TruthParticle* aChild = partProdVtx->outgoingParticle(ipOut);
1175 if (!aChild) continue;
1176 const xAOD::TruthParticle* theNextChild{};
1177 for (unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->nOutgoingParticles(); ipOut1++) {
1178 theNextChild = partProdVtx->outgoingParticle(ipOut1);
1179 if (theNextChild) break;
1180 }
1181 if (!theNextChild) continue;
1182 if (MC::isTau(aChild) && MC::isTau(theNextChild)) {
1183 // Zboson
1184 if (thePriPart == aChild || thePriPart == theNextChild) {
1185 isZboson = true;
1186 break;
1187 }
1188 skipnext = true;
1189 } else if (MC::isTau(aChild) && std::abs(theNextChild->pdgId()) == MC::NU_TAU) {
1190 // WBoson
1191 if (thePriPart == aChild || thePriPart == theNextChild) {
1192 isWboson = true;
1193 break;
1194 }
1195 skipnext = true;
1196 }
1197 }
1198 if (isWboson) return WBoson;
1199 if (isZboson) return ZBoson;
1200 }
1201
1202 //--Sherpa ZZ,ZW+FSR
1203 if (numOfParents == 4 && (numberOfChildren - NumOfPht) == 4 && (NumOfLep + NumOfNeut == 4)) {
1204 if (MC::isSMLepton(partProdVtx->incomingParticle(0))&&MC::isSMLepton(partProdVtx->incomingParticle(1))
1205 && MC::isSMLepton(partProdVtx->incomingParticle(2))&&MC::isSMLepton(partProdVtx->incomingParticle(3)))
1206 return FSRPhot;
1207 }
1208
1209 //--New Sherpa single photon
1210 if (partProdVtx == ancestorProdVtx) {
1211 for (const auto *const pout: partProdVtx->particles_out()) {
1212 if (!pout) continue;
1213 for (const auto *const pin: partProdVtx->particles_in()) {
1214 if (!pin) continue;
1215 if (!HepMC::is_same_particle(pout,pin)) continue;
1216 if (MC::isPhoton(pout)) return SinglePhot;
1217 break; // break out of inner loop after having found two matching particles
1218 }
1219 }
1220 }
1221
1222 if (MC::isHiggs(ancestorPDG)) return Higgs;
1223 if (std::abs(ancestorPDG) == MC::PI0) return PiZero;
1224 if (MC::isMSSMHiggs(ancestorPDG)) return HiggsMSSM; // MSSM Higgs bosons
1225 if (MC::isHeavyBoson(ancestorPDG) || std::abs(ancestorPDG) == 5100039 ) return HeavyBoson; // Heavy Bosons (Z' Z'' W'+) + KK excited graviton
1226
1227 if (MC::isSUSY(ancestorPDG)) return SUSY;
1228 if (MC::isBSM(ancestorPDG)) return OtherBSM;
1229
1230 // Pythia8 gamma+jet samples
1231 if (MC::Pythia8::isConditionA(ancestor) && MC::isStable(thePriPart) && NumOfPht == 1 && numberOfChildren == (NumOfPht + NumOfPartons)) return PromptPhot;
1232
1233 const ParticleType pType = defTypeOfHadron(ancestorPDG);
1234 if ((pType == BBbarMesonPart || pType == CCbarMesonPart) && ancestorProdVtx && MC::isHardScatteringVertex(ancestorProdVtx)) isPrompt = true;
1235 return convHadronTypeToOrig(pType, ancestorPDG);
1236}
#define ATH_MSG_WARNING(x)
@ UndrPhot
@ BremPhot
@ ISRPhot
@ PiZero
@ PromptPhot
@ FSRPhot
@ NucReact
@ SinglePhot
int status() const
Status code.
bool is_simulation_particle(const T &p)
Method to establish if a particle (or barcode) was created during the simulation (TODO update to be s...
ParticleOutCome defOutComeOfPhoton(T thePart)
bool isConditionA(const T &p)
To be understood.
bool isStable(const T &p)
Identify if the particle is stable, i.e. has not decayed.

◆ defOrigOfTau()

ParticleOrigin MCTruthClassifier::defOrigOfTau ( const xAOD::TruthParticleContainer & xTruthParticleContainer,
const xAOD::TruthParticle * thePart,
int motherPDG,
MCTruthPartClassifier::Info & info ) const
private

Definition at line 785 of file MCTruthClassifierGen.cxx.

789{
790 ATH_MSG_DEBUG("Executing DefOrigOfTau ");
791
792 // Find the first copy of this particle stored in the xAOD::TruthParticleContainer (i.e. the particle prior to any interactions)
793 const xAOD::TruthParticle* thePriPart = MC::findMatching(xTruthParticleContainer, thePart);
794 if (!thePriPart) return NonDefined;
795 if (!MC::isTau(thePriPart)) return NonDefined;
796
797 //-- to define tau outcome status
798 if (MC::isPhysical(thePriPart)) info.particleOutCome = defOutComeOfTau(thePriPart); // FIXME why do we need the additional check on MC::isPhysical here c.f. defOrigOfElectron and defOrigOfMuon?
799
800 const xAOD::TruthVertex* partProdVtx = thePriPart->hasProdVtx() ? thePriPart->prodVtx() : nullptr;
801 if (!partProdVtx) return NonDefined;
802
803 if (partProdVtx->nIncomingParticles() > 1) ATH_MSG_DEBUG("DefOrigOfTau:: tau has more than one parent.");
804
805 const xAOD::TruthParticle* ancestor = MC::findMother(thePriPart);
806 info.setMotherProperties(ancestor);
807 if (!ancestor) { return NonDefined; } // ancestor is not a nullptr beyond this point
808
809 // "method 1" for finding Sherpa loops from defOrigOfElectron not used here. Why?
810
811 // Difference from defOrigOfElectron and defOrigOfMuon - no loop through ancestor particles
812
813 if (MC::isW(ancestorPDGin) && ancestor->hasProdVtx()) { // FIXME ancestorPDGin here could in principle be inconsistent with ancestorProdVtx
814 const xAOD::TruthParticle* ancestorParent = MC::findMother(ancestor);
815 if (ancestorParent && MC::isTop(ancestorParent->pdgId())) {
816 ancestor = ancestorParent; //...so ancestor cannot be nullptr
817 }
818 }
819
820 const int ancestorPDG = ancestor->pdgId();
821 info.setMotherProperties(ancestor);
822 const xAOD::TruthVertex* ancestorProdVtx = ancestor->hasProdVtx() ? ancestor->prodVtx() : nullptr;
823 partProdVtx = ancestor->decayVtx();
824 if (!partProdVtx) return NonDefined; // FIXME not sure this could ever be true?
825 const int numOfParents = partProdVtx->nIncomingParticles();
826
827 // Determine decay products
828 auto DP = DecayProducts(partProdVtx);
829 const int numberOfChildren = DP.size();
830 const int NumOfPhot = DP.pd(MC::PHOTON);
831 const int NumOfEl = DP.pd(MC::ELECTRON);
832 const int NumOfPos = DP.pd(MC::POSITRON);
833 const int NumOfElNeut = DP.apd(MC::NU_E);
834 const int NumOfMuNeut = DP.apd(MC::NU_MU);
835 /* const int NumOfLQ = DP.apd(MC::LEPTOQUARK); */ // FIXME Leptoquarks not an option?
836 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
837 const int NumOfgluon = DP.apd(MC::GLUON);
838 const int NumOfMuPl = DP.pd(-MC::MUON);
839 const int NumOfMuMin = DP.pd(MC::MUON);
840 const int NumOfTau = DP.apd(MC::TAU);
841 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
842 // End of section determining decay products
843
844 if (MC::isTop(ancestorPDG)) return top;
845 if (MC::isW(ancestorPDG) && ancestorProdVtx && ancestorProdVtx->nIncomingParticles() != 0) {
846 const xAOD::TruthVertex* prodVert = ancestorProdVtx;
847 const xAOD::TruthParticle* itrP;
848 do {
849 itrP = prodVert->incomingParticle(0); // FIXME just taking the first one
850 prodVert = itrP->hasProdVtx() ? itrP->prodVtx() : nullptr;
851 } while (MC::isW(itrP) && prodVert);
852
853 if (prodVert && prodVert->nIncomingParticles() == 1 ) {
854 if (std::abs(itrP->pdgId()) == MC::RH_NU_E) return NuREle; // Right-handed NU_E (Pythia-specific)
855 if (std::abs(itrP->pdgId()) == MC::RH_NU_MU) return NuRMu; // Right-handed NU_MU (Pythia-specific)
856 if (std::abs(itrP->pdgId()) == MC::RH_NU_TAU) return NuRTau; // Right-handed NU_TAU (Pythia-specific)
857 }
858 return WBoson;
859 }
860 if (MC::isW(ancestorPDG)) { return WBoson;}
861 if (MC::isZ(ancestorPDG)) { return ZBoson;}
862 if (numOfParents == 1 && numberOfChildren > 4 && (MC::isSMQuark(ancestorPDG) || MC::isGluon(ancestorPDG))) {
863 bool isZboson = false;
864 bool isWboson = false;
865 bool skipnext = false;
866 for (unsigned int ipOut = 0; ipOut + 1 < partProdVtx->nOutgoingParticles(); ipOut++) {
867 if (skipnext) {
868 skipnext = false;
869 continue;
870 }
871 const xAOD::TruthParticle* aChild = partProdVtx->outgoingParticle(ipOut);
872 if (!aChild) continue;
873 const xAOD::TruthParticle* theNextChild{};
874 for (unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->nOutgoingParticles(); ipOut1++) {
875 theNextChild = partProdVtx->outgoingParticle(ipOut1);
876 if (theNextChild) break;
877 }
878 if (!theNextChild) {
879 continue;
880 }
881 if (MC::isTau(aChild) && MC::isTau(theNextChild)) {
882 // Zboson
883 if (thePriPart == aChild || thePriPart == theNextChild) {
884 isZboson = true;
885 break;
886 }
887 skipnext = true;
888 } else if (MC::isTau(aChild) && std::abs(theNextChild->pdgId()) == MC::NU_TAU) {
889 // WBoson
890 if (thePriPart == aChild || thePriPart == theNextChild) {
891 isWboson = true;
892 break;
893 }
894 skipnext = true;
895 }
896 }
897 if (isWboson) return WBoson;
898 if (isZboson) return ZBoson;
899 }
900 if (numOfParents == 2 ) {
901 const int pdg1 = partProdVtx->incomingParticle(0)->pdgId();
902 const int pdg2 = partProdVtx->incomingParticle(1)->pdgId();
903 //--Sherpa Z->tautau
904 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && NumOfTau == 2 && (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) return ZBoson; // FIXME Why the extra checks on incoming particles compared to Z->ee, Z->mumu and Z->nunu?
905
906 //--Sherpa W->taunu new
907 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && NumOfTau == 1 && NumOfTauNeut == 1) return WBoson;
908
909 //--Sherpa ZZ,ZW
910 if ((numberOfChildren - NumOfquark - NumOfgluon) == 4 &&
911 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
912 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) return DiBoson;
913
914 //--Sherpa VVV -- Note, have to allow for prompt photon radiation or these get lost
915 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 &&
916 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
917 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) return MultiBoson;
918
919 //--Sherpa tttt with all t->Wb; W->lnu
920 if ((numberOfChildren - NumOfquark - NumOfgluon) == 8 &&
921 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 8) &&
922 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) {
923 ATH_MSG_VERBOSE("MultiBoson for 4topLep");
924 return MultiBoson;
925 }
926
927 //--Sherpa Vgamma ( Z->tautau+gamma or W->taunu+gamma )
928 if ((numberOfChildren - NumOfquark - NumOfgluon) >= 3 && NumOfPhot >= 1 && NumOfTau == 2) {
929 ATH_MSG_VERBOSE("Sherpa tautau + gamma");
930 return ZBoson;
931 }
932 if ((numberOfChildren - NumOfquark - NumOfgluon) >= 3 && NumOfPhot >= 1 && NumOfTau == 1 && NumOfTauNeut == 1) {
933 ATH_MSG_VERBOSE("Sherpa taunu + gamma");
934 return WBoson;
935 }
936 }
937
938 // New Sherpa Z->tautau
939 if (partProdVtx == ancestorProdVtx) {
940 int NumOfTauLoop = 0;
941 int NumOfTauNeuLoop = 0;
942 int NumOfLepLoop = 0;
943 for ( const auto *const pout: partProdVtx->particles_out()) {
944 if (!pout) continue;
945 for (const auto *const pin: partProdVtx->particles_in()) {
946 if (!pin) continue;
947 if (!HepMC::is_same_particle(pout,pin)) continue;
948 if (MC::isTau(pout)) NumOfTauLoop++;
949 if (std::abs(pout->pdgId()) == MC::NU_TAU) NumOfTauNeuLoop++;
950 if (MC::isSMLepton(pout)) NumOfLepLoop++;
951 break; // break out of inner loop after having found two matching particles
952 }
953 }
954 if (NumOfTauLoop == 2 && NumOfTauNeuLoop == 0) return ZBoson;
955 if (NumOfTauLoop == 1 && NumOfTauNeuLoop == 1) return WBoson;
956 if ((NumOfTauLoop == 4 && NumOfTauNeuLoop == 0) || (NumOfTauLoop == 3 && NumOfTauNeuLoop == 1) || (NumOfTauLoop == 2 && NumOfTauNeuLoop == 2)) return DiBoson;
957 if (NumOfLepLoop == 4) return DiBoson;
958 }
959
960 //-- McAtNLo
961
962 if (MC::isHiggs(ancestorPDG)) return Higgs;
963 if (MC::isMSSMHiggs(ancestorPDG)) return HiggsMSSM; // MSSM Higgs bosons
964 if (MC::isHeavyBoson(ancestorPDG)) return HeavyBoson; // Heavy bosons( Z', Z'', W'+)
965 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM) return WBosonLRSM; // Left-right symmetric model WBoson (Pythia-specific)
966 if (std::abs(ancestorPDG) == MC::RH_NU_TAU) return NuRTau; // Right-handed NU_TAU (Pythia-specific)
967 if (MC::isSUSY(ancestorPDG)) return SUSY;
968 if (MC::isBSM(ancestorPDG)) return OtherBSM;
969 if (std::abs(ancestorPDG) == MC::JPSI) return JPsi;
970
971 const ParticleType pType = defTypeOfHadron(ancestorPDG);
972 return convHadronTypeToOrig(pType, ancestorPDG);
973}
@ JPsi
ParticleOutCome defOutComeOfTau(T thePart)
static const int JPSI
bool isPhysical(const T &p)
Identify if the particle is physical, i.e. is stable or decayed.

◆ detStore()

const ServiceHandle< StoreGateSvc > & AthCommonDataStore< AthCommonMsg< AlgTool > >::detStore ( ) const
inlineinherited

The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.

Definition at line 95 of file AthCommonDataStore.h.

◆ egammaClusMatch()

const xAOD::TruthParticle * MCTruthClassifier::egammaClusMatch ( const xAOD::CaloCluster * clus,
bool isFwrdEle,
MCTruthPartClassifier::Info * info ) const
finaloverridevirtual

Implements IMCTruthClassifier.

Definition at line 44 of file MCTruthClassifierAthena.cxx.

45{
46 ATH_MSG_DEBUG("Executing egammaClusMatch ");
47 const xAOD::TruthParticle* theMatchPart = nullptr;
48 const EventContext& ctx = info ? info->eventContext : Gaudi::Hive::currentContext();
49 // retrieve collection and get a pointer
50 SG::ReadHandle<xAOD::TruthParticleContainer> truthParticleContainerReadHandle(m_truthParticleContainerKey, ctx);
51
52 if (!truthParticleContainerReadHandle.isValid()) {
53 ATH_MSG_WARNING( " Invalid ReadHandle for xAOD::TruthParticleContainer with key: " << truthParticleContainerReadHandle.key());
54 return theMatchPart;
55 }
56
57 SG::ReadCondHandle<CaloDetDescrManager> caloMgrHandle{ m_caloMgrKey, ctx };
58 if (!caloMgrHandle.isValid()) {
59 ATH_MSG_WARNING(" Invalid ReadCondHandle for CaloDetDescrManager with key: " << m_caloMgrKey.key());
60 return theMatchPart;
61 }
62
63 const CaloDetDescrManager* caloDDMgr = *caloMgrHandle;
64 const xAOD::TruthParticle* theEgamma(nullptr);
65 const xAOD::TruthParticle* theLeadingPartInCone(nullptr);
66 const xAOD::TruthParticle* theBestPartOutCone(nullptr);
67 const xAOD::TruthParticle* theBestPartdR(nullptr);
68 double LeadingPhtPT(0);
69 double LeadingPartPT(0);
70 double LeadingPhtdR(999.);
71 double LeadingPartdR(999.);
72 double BestPartdR(999.);
73 double etaClus = clus->etaBE(2);
74 double phiClus = clus->phiBE(2);
75 if (etaClus < -900) {
76 etaClus = clus->eta();
77 }
78 if (phiClus < -900) {
79 phiClus = clus->phi();
80 }
81 std::vector<const xAOD::TruthParticle*> tps;
82 if (!m_truthInConeTool->particlesInCone(ctx, etaClus, phiClus, 0.5, tps)) {
83 ATH_MSG_WARNING("Truth Particle in Cone failed");
84 return theMatchPart;
85 }
86
87 for (const auto* const thePart : tps) {
88 // loop over the stable particle
89 if (!MC::isStable(thePart)) continue;
90 // excluding G4 particle
91 if ((!isFwrdEle || (isFwrdEle && m_FwdElectronUseG4Sel)) && HepMC::is_simulation_particle(thePart)) continue;
92 long iParticlePDG = thePart->pdgId();
93 // excluding neutrino
94 if (std::abs(iParticlePDG) == 12 || std::abs(iParticlePDG) == 14 || std::abs(iParticlePDG) == 16) continue;
95 double pt = thePart->pt() / Athena::Units::GeV;
96 double q = thePart?thePart->charge():0.0;
97 // exclude charged particles with pT<1 GeV
98 if (q != 0 && pt < m_pTChargePartCut) continue;
99 if (q == 0 && pt < m_pTNeutralPartCut) continue;
100 float deltaPhi = std::abs(std::remainder(phiClus - thePart->phi(), 2*std::numbers::pi));
101 float deteta = std::abs(etaClus - thePart->eta());
102 // eleptical cone for extrapolations m_partExtrConePhi X m_partExtrConeEta
103 if (!isFwrdEle && m_ROICone && std::hypot( deltaPhi/m_partExtrConePhi, deteta/m_partExtrConeEta) > 1.0) {
104 continue;
105 }
106 // Also check if the clus and true have different sign , i they need both to be <0 or >0
107 if (isFwrdEle && // It is forward and
108 (((etaClus < 0) - (thePart->eta() < 0) != 0)
109 // The truth eta has different sign wrt to the fwd electron
110 || (std::fabs(thePart->eta()) < m_FwdElectronTruthExtrEtaCut) // or the truth is less than 2.4 (default cut)
111 || (std::fabs(thePart->eta() - etaClus) > m_FwdElectronTruthExtrEtaWindowCut) // or if the delta Eta between el and truth is > 0.15
112 ) // then do no extrapolate this truth Particle for this fwd electron
113 ) {
114 continue;
115 }
116 double dR(-999.);
117 bool isNCone = false;
118 bool isExt = genPartToCalo(ctx, clus, thePart, isFwrdEle, dR, isNCone, *caloDDMgr);
119 if (!isExt) continue;
120 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(), thePart);
121 if (info) {
122 info->egPartPtr.push_back(thePart);
123 info->egPartdR.push_back(dR);
124 info->egPartClas.push_back(particleTruthClassifier(theMatchPart, info));
125 }
126 // Gen particles Not forward
127 if (!isFwrdEle) {
128 // the leading photon or electron inside narrow eleptical cone
129 // m_phtClasConePhi X m_phtClasConeEta
130 if ((iParticlePDG == 22 || std::abs(iParticlePDG) == 11) && isNCone && pt > LeadingPhtPT) {
131 theEgamma = thePart;
132 LeadingPhtPT = pt;
133 LeadingPhtdR = dR;
134 }
135 // leading particle (excluding photon and electron) inside narrow eleptic
136 // cone m_phtClasConePhi X m_phtClasConeEta
137 if ((iParticlePDG != 22 && std::abs(iParticlePDG) != 11) && isNCone && pt > LeadingPartPT) {
138 theLeadingPartInCone = thePart;
139 LeadingPartPT = pt;
140 LeadingPartdR = dR;
141 };
142 // the best dR matched particle outside narrow eleptic cone cone
143 // m_phtClasConePhi X m_phtClasConeEta
144 if (!isNCone && dR < BestPartdR) {
145 theBestPartOutCone = thePart;
146 BestPartdR = dR;
147 };
148 } else {
149 if (dR < BestPartdR) {
150 theBestPartdR = thePart;
151 BestPartdR = dR;
152 };
153 }
154 }
155
156 if (theEgamma != nullptr) {
157 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(), theEgamma);
158 if (info) info->deltaRMatch = LeadingPhtdR;
159 } else if (theLeadingPartInCone != nullptr) {
160 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theLeadingPartInCone);
161 if (info) info->deltaRMatch = LeadingPartdR;
162 } else if (theBestPartOutCone != nullptr) {
163 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theBestPartOutCone);
164 if (info) info->deltaRMatch = BestPartdR;
165 } else if (isFwrdEle && theBestPartdR != nullptr) {
166 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theBestPartdR );
167 if (info) info->deltaRMatch = BestPartdR;
168 } else {
169 theMatchPart = nullptr;
170 }
171 if (isFwrdEle || theMatchPart != nullptr || !m_inclG4part) return theMatchPart;
172
173 // additional loop over G4 particles,
174 for (const auto* const thePart : tps) {
175 if (!MC::isStable(thePart)) continue;
176 if (!HepMC::is_simulation_particle(thePart)) continue;
177 long iParticlePDG = thePart->pdgId();
178 // exclude neutrino
179 if (std::abs(iParticlePDG) == 12 || std::abs(iParticlePDG) == 14 || std::abs(iParticlePDG) == 16) continue;
180 if (thePart->decayVtx() != nullptr) continue;
181 const double dPhi = std::abs(std::remainder(phiClus - thePart->phi(), 2*std::numbers::pi));
182 const double dEta = std::abs(etaClus - thePart->eta());
183 if (std::hypot( dPhi/m_partExtrConePhi, dEta/m_partExtrConeEta ) > 1.0) continue;
184
185 double pt = thePart->pt() / Athena::Units::GeV;
186 double q = thePart->charge();
187 // exclude charged particles with pT<1 GeV
188 if (q != 0 && pt < m_pTChargePartCut) continue;
189 if (q == 0 && pt < m_pTNeutralPartCut) continue;
190
191 double dR(-999.);
192 bool isNCone = false;
193 bool isExt = genPartToCalo(ctx, clus, thePart, isFwrdEle, dR, isNCone, *caloDDMgr);
194 if (!isExt) continue;
195
196 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),thePart);
197 if (info) {
198 info->egPartPtr.push_back(thePart);
199 info->egPartdR.push_back(dR);
200 info->egPartClas.push_back(particleTruthClassifier(theMatchPart, info));
201 }
202 // the leading photon or electron inside narrow eleptical cone
203 // m_phtClasConePhi X m_phtClasConeEta
204 if ((iParticlePDG == 22 || std::abs(iParticlePDG) == 11) && isNCone && pt > LeadingPhtPT) {
205 theEgamma = thePart;
206 LeadingPhtPT = pt;
207 LeadingPhtdR = dR;
208 }
209 // leading particle (excluding photon or electron) inside narrow eleptic
210 // cone m_phtClasConePhi X m_phtClasConeEta
211 if ((iParticlePDG != 22 && std::abs(iParticlePDG) != 11) && isNCone && pt > LeadingPartPT) {
212 theLeadingPartInCone = thePart;
213 LeadingPartPT = pt;
214 LeadingPartdR = dR;
215 }
216 // the best dR matched particle outside narrow eleptic cone cone
217 // m_phtClasConePhi X m_phtClasConeEta
218 if (!isNCone && dR < BestPartdR) {
219 theBestPartOutCone = thePart;
220 BestPartdR = dR;
221 }
222 }
223
224 if (theEgamma != nullptr) {
225 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theEgamma);
226 if (info) info->deltaRMatch = LeadingPhtdR;
227 } else if (theLeadingPartInCone != nullptr) {
228 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theLeadingPartInCone);
229 if (info) info->deltaRMatch = LeadingPartdR;
230 } else if (theBestPartOutCone != nullptr) {
231 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theBestPartOutCone);
232 if (info) info->deltaRMatch = BestPartdR;
233 } else {
234 theMatchPart = nullptr;
235 }
236 ATH_MSG_DEBUG("succeeded egammaClusMatch ");
237 return theMatchPart;
238}
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
ToolHandle< xAOD::ITruthParticlesInConeTool > m_truthInConeTool
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
bool genPartToCalo(const EventContext &ctx, const xAOD::CaloCluster *clus, const xAOD::TruthParticle *thePart, bool isFwrdEle, double &dRmatch, bool &isNarrowCone, const CaloDetDescrManager &caloDDMgr) const
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin > particleTruthClassifier(const xAOD::TruthParticle *, MCTruthPartClassifier::Info *info=nullptr) const override final
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthParticleContainerKey
float phiBE(const unsigned layer) const
Get the phi in one layer of the EM Calo.
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double phi() const
The azimuthal angle ( ) of the particle.
float etaBE(const unsigned layer) const
Get the eta in one layer of the EM Calo.
bool dPhi(const xAOD::TauJet &tau, const xAOD::CaloVertexedTopoCluster &cluster, float &out)
bool dEta(const xAOD::TauJet &tau, const xAOD::CaloVertexedTopoCluster &cluster, float &out)

◆ evtStore()

ServiceHandle< StoreGateSvc > & AthCommonDataStore< AthCommonMsg< AlgTool > >::evtStore ( )
inlineinherited

The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.

Definition at line 85 of file AthCommonDataStore.h.

◆ extraDeps_update_handler()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::extraDeps_update_handler ( Gaudi::Details::PropertyBase & ExtraDeps)
protectedinherited

Add StoreName to extra input/output deps as needed.

use the logic of the VarHandleKey to parse the DataObjID keys supplied via the ExtraInputs and ExtraOuputs Properties to add the StoreName if it's not explicitly given

◆ findJetConstituents()

void MCTruthClassifier::findJetConstituents ( const xAOD::Jet * jet,
std::set< const xAOD::TruthParticle * > & constituents,
bool DR ) const
private

Definition at line 274 of file MCRecoToTruth.cxx.

277{
278 if (DR) {
279 // use a DR matching scheme (default)
280 // retrieve collection and get a pointer
281 SG::ReadHandle<xAOD::TruthParticleContainer> truthParticleContainerReadHandle(m_truthParticleContainerKey);
282
283 if (!truthParticleContainerReadHandle.isValid()) {
284 ATH_MSG_WARNING(" Invalid ReadHandle for xAOD::TruthParticleContainer with key: " << truthParticleContainerReadHandle.key());
285 return;
286 }
287 ATH_MSG_DEBUG("xAODTruthParticleContainer with key " << truthParticleContainerReadHandle.key() << " has valid ReadHandle ");
288 // find the matching truth particles
289 for (const auto *const thePart : *truthParticleContainerReadHandle) {
290 // match truth particles to the jet
291 if (MC::isStable(thePart) && thePart->p4().DeltaR(jet->p4()) < m_jetPartDRMatch) {
292 constituents.insert(thePart);
293 }
294 }
295 }
296 else {
297 xAOD::JetConstituentVector vec = jet->getConstituents();
298 for (const auto *particle0 : vec) {
299 const xAOD::TruthParticle* thePart = dynamic_cast<const xAOD::TruthParticle*>(particle0->rawConstituent());
300 if (MC::isStable(thePart)) {
301 constituents.insert(thePart);
302 }
303 }
304 }
305}
std::vector< size_t > vec
virtual FourMom_t p4() const
The full 4-momentum of the particle.
Definition Jet_v1.cxx:71
JetConstituentVector getConstituents() const
Return a vector of consituents. The object behaves like vector<const IParticle*>. See JetConstituentV...
Definition Jet_v1.cxx:149

◆ genPartToCalo()

bool MCTruthClassifier::genPartToCalo ( const EventContext & ctx,
const xAOD::CaloCluster * clus,
const xAOD::TruthParticle * thePart,
bool isFwrdEle,
double & dRmatch,
bool & isNarrowCone,
const CaloDetDescrManager & caloDDMgr ) const
private

Definition at line 240 of file MCTruthClassifierAthena.cxx.

247{
248 dRmatch = -999.;
249 isNarrowCone = false;
250 if (thePart == nullptr) return false;
251 double phiClus = clus->phiBE(2);
252 double etaClus = clus->etaBE(2);
253 if (etaClus < -900) {
254 etaClus = clus->eta();
255 }
256 if (phiClus < -900) {
257 phiClus = clus->phi();
258 }
259 //--FixMe
260 if (isFwrdEle || (etaClus == 0. && phiClus == 0.)) {
261 phiClus = clus->phi();
262 etaClus = clus->eta();
263 }
264 // define calo sample
265 CaloSampling::CaloSample sample = CaloSampling::EMB2;
266 if ((clus->inBarrel() && !clus->inEndcap()) ||
267 (clus->inBarrel() && clus->inEndcap() && clus->eSample(CaloSampling::EMB2) >= clus->eSample(CaloSampling::EME2))) {
268 // Barrel
269 sample = CaloSampling::EMB2;
270 } else if ((!clus->inBarrel() && clus->inEndcap() && !isFwrdEle) ||
271 (clus->inBarrel() && clus->inEndcap() && clus->eSample(CaloSampling::EME2) > clus->eSample(CaloSampling::EMB2))) {
272 // End-cap
273 sample = CaloSampling::EME2;
274 } else if (isFwrdEle && clus->inEndcap()) {
275 // FCAL
276 sample = CaloSampling::FCAL2;
277 } else {
278 return false;
279 }
280 std::unique_ptr<Trk::CurvilinearParameters> params = extractParamFromTruth(*thePart);
281 if (!params) return false;
282 // create extension to sample
283 std::vector<CaloSampling::CaloSample> samples = { sample };
284 auto extension = m_caloExtensionTool->layersCaloExtension(ctx, *params, samples, etaClus, caloDDMgr);
285 bool extensionOK = (!extension.empty());
286 if (!extensionOK) {
287 ATH_MSG_WARNING("extrapolation of Truth Particle with eta " << thePart->eta() << " , charge " << thePart->charge() << " , Pt " << thePart->pt() << " to calo failed");
288 return false;
289 }
290 double etaCalo = extension[0].second->position().eta();
291 double phiCalo = extension[0].second->position().phi();
292
293 const double dPhi = std::abs(std::remainder(phiCalo - phiClus, 2*std::numbers::pi));
294 const double dEta = std::abs(etaCalo - etaClus);
295 dRmatch = std::hypot(dPhi, dEta);
296
297 if ((!isFwrdEle && dRmatch > m_phtdRtoTrCut) || (isFwrdEle && dRmatch > m_fwrdEledRtoTrCut)) return false;
298 if (!isFwrdEle && std::hypot( dPhi/m_phtClasConePhi, dEta/m_phtClasConeEta ) <= 1.0) isNarrowCone = true;
299 return true;
300}
ToolHandle< Trk::IParticleCaloExtensionTool > m_caloExtensionTool
bool inBarrel() const
Returns true if at least one clustered cell in the barrel.
float eSample(const CaloSample sampling) const
bool inEndcap() const
Returns true if at least one clustered cell in the endcap.
virtual double pt() const override final
The transverse momentum ( ) of the particle.
double charge() const
Physical charge.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.

◆ getGenPart()

const xAOD::TruthParticle * MCTruthClassifier::getGenPart ( const xAOD::TrackParticle * trk,
MCTruthPartClassifier::Info * info = nullptr ) const
finaloverridevirtual

Implements IMCTruthClassifier.

Definition at line 177 of file MCRecoToTruth.cxx.

178{
179 // return GenParticle corresponding to given TrackParticle
180 ATH_MSG_DEBUG("Executing getGenPart ");
181 if (!trk) return nullptr;
182 if (info) {
183 info->deltaRMatch = -999.;
184 info->deltaPhi = -999.;
185 info->probTrkToTruth = 0;
186 info->numOfSiHits = 0;
187 }
188
189 uint8_t NumOfPixHits = 0;
190 uint8_t NumOfSCTHits = 0;
191 typedef ElementLink<xAOD::TruthParticleContainer> TruthLink_t;
192
193 static const SG::AuxElement::Accessor<TruthLink_t> tPL("truthParticleLink");
194 if (!tPL.isAvailable(*trk)) {
195 ATH_MSG_DEBUG("Track particle is not associated to truth particle");
196 return nullptr;
197 }
198
199 const auto& truthLink = tPL(*trk);
200 if (!truthLink.isValid()) {
201 ATH_MSG_DEBUG("Invalid link to truth particle");
202 return nullptr;
203 }
204
205 const xAOD::TruthParticle* theGenParticle = (*truthLink);
206 if (!theGenParticle) {
207 ATH_MSG_DEBUG("Could not find truth matching for track");
208 return nullptr;
209 }
210
211 if (info) {
212 static const SG::AuxElement::Accessor<float> tMP("truthMatchProbability");
213 if (tMP.isAvailable(*trk)) {
214 info->probTrkToTruth = tMP(*trk);
215 } else {
216 ATH_MSG_DEBUG("Truth match probability not available");
217 }
218 }
219
220 if (theGenParticle->status() == 3) {
221 ATH_MSG_WARNING("track matched to the truth with status " << theGenParticle->status());
222 }
223 else if (MC::isDecayed(theGenParticle)) {
224 // Matching to status == 2 particles is to be expected if
225 // quasi-stable particle simulation was used.
226 ATH_MSG_DEBUG("track matched to the truth with status " << theGenParticle->status());
227 }
228
229 if (MC::isDecayed(theGenParticle) && (MC::isElectron(theGenParticle) || MC::isMuon(theGenParticle))) {
230 const xAOD::TruthVertex* EndVrtx = theGenParticle->decayVtx();
231 const xAOD::TruthParticle* theGenPartTmp(nullptr);
232
233 if (EndVrtx != nullptr) {
234 int itr = 0;
235 do {
236 theGenPartTmp = nullptr;
237 for (const auto & theDaugt: EndVrtx->particles_out()) {
238 if (!theDaugt) continue;
239 if (theDaugt->pdgId() == theGenParticle->pdgId()) theGenPartTmp = theDaugt;
240 if (theDaugt->pdgId() != theGenParticle->pdgId() && !MC::isPhoton(theDaugt)) theGenPartTmp = nullptr;
241 }
242 itr++;
243 if (itr > 100) {
244 ATH_MSG_WARNING("getGenPart infinite while");
245 break;
246 }
247 EndVrtx = theGenPartTmp ? theGenPartTmp->decayVtx() : nullptr;
248 } while (theGenPartTmp && theGenPartTmp->pdgId() == theGenParticle->pdgId() && MC::isDecayed(theGenPartTmp) && EndVrtx != nullptr);
249
250 if (theGenPartTmp && theGenPartTmp->pdgId() == theGenParticle->pdgId()) theGenParticle = theGenPartTmp;
251 }
252 }
253
254 if (!trk->summaryValue(NumOfSCTHits, xAOD::numberOfSCTHits)) ATH_MSG_DEBUG("Could not retrieve number of SCT hits");
255 if (!trk->summaryValue(NumOfPixHits, xAOD::numberOfPixelHits)) ATH_MSG_DEBUG("Could not retrieve number of Pixel hits");
256
257 uint8_t NumOfSiHits = NumOfSCTHits + NumOfPixHits;
258
259 float deltaPhi = std::abs(std::remainder(theGenParticle->phi() - trk->phi(), 2*std::numbers::pi));
260 float deteta = std::abs(theGenParticle->eta() - trk->eta());
261 float deltaRMatch = std::hypot(deltaPhi, deteta);
262 if ((NumOfSiHits > m_NumOfSiHitsCut && deltaRMatch > m_deltaRMatchCut) ||
263 (NumOfSiHits <= m_NumOfSiHitsCut && deltaPhi > m_deltaPhiMatchCut)) theGenParticle = nullptr;
264
265 if (info) {
266 info->deltaRMatch = deltaRMatch;
267 info->deltaPhi = deltaPhi;
268 info->numOfSiHits = NumOfSiHits;
269 }
270 ATH_MSG_DEBUG("getGenPart succeeded ");
271 return (theGenParticle);
272}
ElementLink< xAOD::TruthParticleContainer > TruthLink_t
virtual double phi() const override final
The azimuthal angle ( ) of the particle (has range to .).
bool summaryValue(uint8_t &value, const SummaryType &information) const
Accessor for TrackSummary values.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
virtual double phi() const override final
The azimuthal angle ( ) of the particle.
@ numberOfSCTHits
number of hits in SCT [unit8_t].
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].

◆ getKey()

SG::sgkey_t asg::AsgTool::getKey ( const void * ptr) const
inherited

Get the (hashed) key of an object that is in the event store.

This is a bit of a special one. StoreGateSvc and xAOD::Event both provide ways for getting the SG::sgkey_t key for an object that is in the store, based on a bare pointer. But they provide different interfaces for doing so.

In order to allow tools to efficiently perform this operation, they can use this helper function.

See also
asg::AsgTool::getName
Parameters
ptrThe bare pointer to the object that the event store should know about
Returns
The hashed key of the object in the store. If not found, an invalid (zero) key.

Definition at line 119 of file AsgTool.cxx.

119 {
120
121#ifdef XAOD_STANDALONE
122 // In case we use @c xAOD::Event, we have a direct function call
123 // for this.
124 return evtStore()->event()->getKey( ptr );
125#else
126 const SG::DataProxy* proxy = evtStore()->proxy( ptr );
127 return ( proxy == nullptr ? 0 : proxy->sgkey() );
128#endif // XAOD_STANDALONE
129 }
ServiceHandle< StoreGateSvc > & evtStore()

◆ getName()

const std::string & asg::AsgTool::getName ( const void * ptr) const
inherited

Get the name of an object that is / should be in the event store.

This is a bit of a special one. StoreGateSvc and xAOD::Event both provide ways for getting the std::string name for an object that is in the store, based on a bare pointer. But they provide different interfaces for doing so.

In order to allow tools to efficiently perform this operation, they can use this helper function.

See also
asg::AsgTool::getKey
Parameters
ptrThe bare pointer to the object that the event store should know about
Returns
The string name of the object in the store. If not found, an empty string.

Definition at line 106 of file AsgTool.cxx.

106 {
107
108#ifdef XAOD_STANDALONE
109 // In case we use @c xAOD::Event, we have a direct function call
110 // for this.
111 return evtStore()->event()->getName( ptr );
112#else
113 const SG::DataProxy* proxy = evtStore()->proxy( ptr );
114 static const std::string dummy = "";
115 return ( proxy == nullptr ? dummy : proxy->name() );
116#endif // XAOD_STANDALONE
117 }

◆ getProperty()

template<class T>
const T * asg::AsgTool::getProperty ( const std::string & name) const
inherited

Get one of the tool's properties.

◆ initialize()

virtual StatusCode MCTruthClassifier::initialize ( void )
inlineoverridevirtual

Dummy implementation of the initialisation function.

It's here to allow the dual-use tools to skip defining an initialisation function. Since many are doing so...

Reimplemented from asg::AsgTool.

Reimplemented in D3PD::D3PDMCTruthClassifier.

Definition at line 96 of file MCTruthClassifier.h.

96 {
97 ATH_MSG_INFO(" Initializing MCTruthClassifier");
98#ifndef XAOD_ANALYSIS
99 // Only needed for GenParticle interface
101#endif
103
104#if !defined(XAOD_ANALYSIS) && !defined(GENERATIONBASE)
105 if (!m_caloExtensionTool.empty()) {
106 ATH_CHECK(m_caloExtensionTool.retrieve());
107 } else {
108 m_caloExtensionTool.disable();
109 }
110
112
113 if (!m_truthInConeTool.empty()) {
114 ATH_CHECK(m_truthInConeTool.retrieve());
115 } else {
116 m_truthInConeTool.disable();
117 }
118#endif
119 return StatusCode::SUCCESS;
120 }
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
SG::ReadHandleKey< xAODTruthParticleLinkVector > m_truthLinkVecReadHandleKey

◆ inputHandles()

virtual std::vector< Gaudi::DataHandle * > AthCommonDataStore< AthCommonMsg< AlgTool > >::inputHandles ( ) const
overridevirtualinherited

Return this algorithm's input handles.

We override this to include handle instances from key arrays if they have not yet been declared. See comments on updateVHKA.

◆ msg()

MsgStream & AthCommonMsg< AlgTool >::msg ( ) const
inlineinherited

Definition at line 24 of file AthCommonMsg.h.

24 {
25 return this->msgStream();
26 }

◆ msg_level_name()

const std::string & asg::AsgTool::msg_level_name ( ) const
inherited

A deprecated function for getting the message level's name.

Instead of using this, weirdly named function, user code should get the string name of the current minimum message level (in case they really need it...), with:

MSG::name( msg().level() )

This function's name doesn't follow the ATLAS coding rules, and as such will be removed in the not too distant future.

Returns
The string name of the current minimum message level that's printed

Definition at line 101 of file AsgTool.cxx.

101 {
102
103 return MSG::name( msg().level() );
104 }
MsgStream & msg() const
const std::string & name(Level lvl)
Convenience function for translating message levels to strings.
Definition MsgLevel.cxx:19

◆ msgLvl()

bool AthCommonMsg< AlgTool >::msgLvl ( const MSG::Level lvl) const
inlineinherited

Definition at line 30 of file AthCommonMsg.h.

30 {
31 return this->msgLevel(lvl);
32 }

◆ outputHandles()

virtual std::vector< Gaudi::DataHandle * > AthCommonDataStore< AthCommonMsg< AlgTool > >::outputHandles ( ) const
overridevirtualinherited

Return this algorithm's output handles.

We override this to include handle instances from key arrays if they have not yet been declared. See comments on updateVHKA.

◆ particleHepMCTruthClassifier()

std::pair< ParticleType, ParticleOrigin > MCTruthClassifier::particleHepMCTruthClassifier ( const HepMcParticleLink & theLink,
MCTruthPartClassifier::Info * info = nullptr ) const
finaloverridevirtual

Implements IMCTruthClassifier.

Definition at line 25 of file MCTruthClassifierGen.cxx.

25 {
26 // Retrieve the links between HepMC and xAOD::TruthParticle
27 const EventContext& ctx = info ? info->eventContext : Gaudi::Hive::currentContext();
28 SG::ReadHandle<xAODTruthParticleLinkVector> truthParticleLinkVecReadHandle(m_truthLinkVecReadHandleKey, ctx);
29 if (!truthParticleLinkVecReadHandle.isValid()) {
30 ATH_MSG_WARNING(" Invalid ReadHandle for xAODTruthParticleLinkVector with key: " << truthParticleLinkVecReadHandle.key());
31 return std::make_pair(Unknown, NonDefined);
32 }
33 ElementLink<xAOD::TruthParticleContainer> tplink = truthParticleLinkVecReadHandle->find (theLink);
34 if (tplink.isValid()) {
35 return particleTruthClassifier (*tplink, info);
36 }
37 return std::make_pair(Unknown, NonDefined);
38}
@ Unknown
Definition TruthClasses.h:9

◆ particleTruthClassifier() [1/7]

virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin > MCTruthClassifier::particleTruthClassifier ( const xAOD::CaloCluster * ,
MCTruthPartClassifier::Info * info = nullptr ) const
finaloverridevirtual

Implements IMCTruthClassifier.

Reimplemented in D3PD::D3PDMCTruthClassifier.

◆ particleTruthClassifier() [2/7]

std::pair< ParticleType, ParticleOrigin > MCTruthClassifier::particleTruthClassifier ( const xAOD::Electron * elec,
MCTruthPartClassifier::Info * info = nullptr ) const
finaloverridevirtual

Implements IMCTruthClassifier.

Reimplemented in D3PD::D3PDMCTruthClassifier.

Definition at line 24 of file MCRecoToTruth.cxx.

25{
26 ATH_MSG_DEBUG("Executing egamma electron Classifier");
27 ParticleType parttype = Unknown;
28 ParticleOrigin partorig = NonDefined;
29 const xAOD::TruthParticle* genPart = nullptr;
30 const xAOD::TrackParticle* trkPtr = elec->trackParticle();
31 if (elec->author() != xAOD::EgammaParameters::AuthorFwdElectron ||trkPtr) {
32 // Central electron or forward electron with track (when reco
33 // implemented in the future)
34 if (!trkPtr){
35 return std::make_pair(parttype, partorig);
36 }
37 genPart = getGenPart(trkPtr);
38 } else {
39#ifndef XAOD_ANALYSIS // cluster matching available only in Athena
40 const xAOD::CaloCluster* clus = elec->caloCluster();
41 genPart = egammaClusMatch(clus, true, info);
42#else
43 ATH_MSG_WARNING("Forward Electron classification using extrapolation to Calo is available only in Athena , check your enviroment. ");
44#endif
45 }
46
47 if (info) info->genPart = genPart;
48 if (!genPart) return std::make_pair(parttype, partorig);
49 ATH_MSG_DEBUG("egamma electron Classifier succeeded ");
50 return particleTruthClassifier(genPart, info);
51}
virtual const xAOD::TruthParticle * egammaClusMatch(const xAOD::CaloCluster *, bool, MCTruthPartClassifier::Info *info) const override final
virtual const xAOD::TruthParticle * getGenPart(const xAOD::TrackParticle *, MCTruthPartClassifier::Info *info=nullptr) const override final
uint16_t author(uint16_t bitmask=EgammaParameters::AuthorALL) const
Get author.
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
const xAOD::TrackParticle * trackParticle(size_t index=0) const
Pointer to the xAOD::TrackParticle/s that match the electron candidate.
const uint16_t AuthorFwdElectron
Electron reconstructed by the Forward cluster-based algorithm.
Definition EgammaDefs.h:30
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:

◆ particleTruthClassifier() [3/7]

std::pair< ParticleType, ParticleOrigin > MCTruthClassifier::particleTruthClassifier ( const xAOD::Jet * jet,
bool DR,
MCTruthPartClassifier::Info * info = nullptr ) const
finaloverridevirtual

Implements IMCTruthClassifier.

Reimplemented in D3PD::D3PDMCTruthClassifier.

Definition at line 130 of file MCRecoToTruth.cxx.

131{
132 ATH_MSG_DEBUG("Executing Classifier with jet Input");
133 ParticleType parttype = UnknownJet;
134 ParticleOrigin partorig = NonDefined;
135 ParticleType tempparttype = UnknownJet;
136 std::set<const xAOD::TruthParticle*> allJetMothers;
137 std::set<const xAOD::TruthParticle*> constituents;
138 if (!jet) return std::make_pair(parttype, partorig);
139 allJetMothers.clear();
140 constituents.clear();
141 findJetConstituents(jet, constituents, DR);
142 // AV: Jet type is the type of hadron with "heaviest" flavour among the jet constituents.
143 // AV: No hadrons in the jet -- the flavour is unknown.
144 // AV: The algorithm will fail on 4/5 quark hadrons and probably on nonBSM hadrons. To be fixed.
145 for (const auto& thePart: constituents) {
146 MC::findParticleAncestors(thePart, allJetMothers);
147 //AV: probably skip ME particles
148 if (!MC::isPhysical(thePart)) continue;
149 // determine if hadron and its type
150 tempparttype = particleTruthClassifier(thePart, info).first;
151 if (tempparttype != Hadron) continue;
152 tempparttype = defTypeOfHadron(thePart->pdgId());
153 // classify the jet
154 if (tempparttype == BBbarMesonPart || tempparttype == BottomMesonPart || tempparttype == BottomBaryonPart) {
155 parttype = BJet;
156 continue;
157 }
158 if (tempparttype == CCbarMesonPart || tempparttype == CharmedMesonPart || tempparttype == CharmedBaryonPart) {
159 if (parttype != BJet) parttype = CJet;
160 continue;
161 }
162 if (tempparttype == StrangeBaryonPart || tempparttype == LightBaryonPart || tempparttype == StrangeMesonPart || tempparttype == LightMesonPart) {
163 if (parttype != BJet && parttype != CJet) parttype = LJet;
164 continue;
165 }
166 }
167
168 // clasify the jet origin
169 partorig = defJetOrig(allJetMothers);
170 allJetMothers.clear();
171 constituents.clear();
172 ATH_MSG_DEBUG(" jet Classifier succeeded");
173 return std::make_pair(parttype, partorig);
174}
@ Hadron
@ StrangeMesonPart
@ UnknownJet
@ CharmedMesonPart
@ BottomMesonPart
@ CJet
@ BJet
@ LightBaryonPart
@ LJet
@ CharmedBaryonPart
@ LightMesonPart
@ BottomBaryonPart
@ StrangeBaryonPart
void findJetConstituents(const xAOD::Jet *, std::set< const xAOD::TruthParticle * > &constituents, bool DR) const
ParticleOrigin defJetOrig(const T &allJetMothers)
void findParticleAncestors(T thePart, std::set< T > &allancestors)
Function to find all ancestors of the particle.

◆ particleTruthClassifier() [4/7]

virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin > MCTruthClassifier::particleTruthClassifier ( const xAOD::Muon * ,
MCTruthPartClassifier::Info * info = nullptr ) const
finaloverridevirtual

Implements IMCTruthClassifier.

Reimplemented in D3PD::D3PDMCTruthClassifier.

◆ particleTruthClassifier() [5/7]

std::pair< ParticleType, ParticleOrigin > MCTruthClassifier::particleTruthClassifier ( const xAOD::Photon * phot,
MCTruthPartClassifier::Info * info = nullptr ) const
finaloverridevirtual

Implements IMCTruthClassifier.

Reimplemented in D3PD::D3PDMCTruthClassifier.

Definition at line 54 of file MCRecoToTruth.cxx.

55{
56 ATH_MSG_DEBUG("Executing egamma photon Classifier");
57 ParticleType parttype = Unknown;
58 ParticleOrigin partorig = NonDefined;
59 const xAOD::CaloCluster* clus = phot->caloCluster();
60 if (!clus) return std::make_pair(parttype, partorig);
61 if (std::fabs(clus->eta()) > 10.0 || std::fabs(clus->phi()) > 6.28 || (clus->et()) <= 0.) return std::make_pair(parttype, partorig);
62
63 const xAOD::Vertex* VxCvPtr = phot->vertex();
64 if (VxCvPtr != nullptr) {
65 for (int itrk = 0; itrk < (int)VxCvPtr->nTrackParticles(); itrk++) {
66 if (itrk > 1) continue;
67 const xAOD::TrackParticle* trkPtr = VxCvPtr->trackParticle(itrk);
68 if (!trkPtr) continue;
69 const xAOD::TruthParticle* thePart = getGenPart(trkPtr);
70 std::pair<ParticleType, ParticleOrigin> classif = particleTruthClassifier(thePart, info);
71 if (info) {
72 info->cnvPhotTrkPtr.push_back(trkPtr);
73 info->cnvPhotTrkToTruthPart.push_back(thePart);
74 info->cnvPhotPartType.push_back(classif.first);
75 info->cnvPhotPartOrig.push_back(classif.second);
76 }
77 }
78 }
79
80 const xAOD::TruthParticle* genPart = nullptr;
81#ifndef XAOD_ANALYSIS // Fwd electron available only in Athena
82 genPart = egammaClusMatch(clus, false, info);
83#else
84 ATH_MSG_WARNING("Photon Classification using extrapolation to Calo is available only in Athena , check your enviroment. ");
85#endif
86 if (!genPart) return std::make_pair(parttype, partorig);
87 if (info) info->genPart = genPart;
88 ATH_MSG_DEBUG("egamma photon Classifier succeeded ");
89 return particleTruthClassifier(genPart, info);
90}
const xAOD::Vertex * vertex(size_t index=0) const
Pointer to the xAOD::Vertex/es that match the photon candidate.
Definition Photon_v1.cxx:61
size_t nTrackParticles() const
Get the number of tracks associated with this vertex.
const TrackParticle * trackParticle(size_t i) const
Get the pointer to a given track that was used in vertex reco.
Vertex_v1 Vertex
Define the latest version of the vertex class.

◆ particleTruthClassifier() [6/7]

std::pair< ParticleType, ParticleOrigin > MCTruthClassifier::particleTruthClassifier ( const xAOD::TrackParticle * trkPtr,
MCTruthPartClassifier::Info * info = nullptr ) const
finaloverridevirtual

Implements IMCTruthClassifier.

Reimplemented in D3PD::D3PDMCTruthClassifier.

Definition at line 11 of file MCRecoToTruth.cxx.

12{
13 ATH_MSG_DEBUG("Executing trackClassifier");
14 ParticleType parttype = Unknown;
15 ParticleOrigin partorig = NonDefined;
16 const xAOD::TruthParticle* genPart = getGenPart(trkPtr);
17 if (info) info->genPart = genPart;
18 if (!genPart) return std::make_pair(parttype, partorig);
19 ATH_MSG_DEBUG("trackClassifier succeeded ");
20 return particleTruthClassifier(genPart, info);
21}

◆ particleTruthClassifier() [7/7]

std::pair< ParticleType, ParticleOrigin > MCTruthClassifier::particleTruthClassifier ( const xAOD::TruthParticle * thePart,
MCTruthPartClassifier::Info * info = nullptr ) const
finaloverridevirtual

Implements IMCTruthClassifier.

Reimplemented in D3PD::D3PDMCTruthClassifier.

Definition at line 42 of file MCTruthClassifierGen.cxx.

42 {
43 MCTruthPartClassifier::Info tmpinfo;
44 MCTruthPartClassifier::Info& info = (infoin) ? *infoin : tmpinfo;
45
46 ATH_MSG_DEBUG("Executing particleTruthClassifier");
47
48 ParticleType partType = Unknown;
49 ParticleOrigin partOrig = NonDefined;
50 if (!thePart) {
51 return std::make_pair(partType, partOrig);
52 }
53 info.genPart = thePart;
54
55 // retrieve collection and get a pointer
56 SG::ReadHandle<xAOD::TruthParticleContainer> truthParticleContainerReadHandle(m_truthParticleContainerKey,info.eventContext);
57 if (!truthParticleContainerReadHandle.isValid()) {
58 ATH_MSG_WARNING( " Invalid ReadHandle for xAOD::TruthParticleContainer with key: " << truthParticleContainerReadHandle.key());
59 return std::make_pair(partType, partOrig);
60 }
61
62 ATH_MSG_DEBUG("xAODTruthParticleContainer with key " << truthParticleContainerReadHandle.key() << " has valid ReadHandle ");
63
64 if (!MC::isStable(thePart) && !MC::isDecayed(thePart)) {
65 return std::make_pair(GenParticle, partOrig);
66 }
67 const bool isPartHadr = MC::isHadron(thePart) && !MC::isBeam(thePart);
68 if (MC::isDecayed(thePart) && (!MC::isTau(thePart) && !isPartHadr)) return std::make_pair(GenParticle, partOrig);
69
70 // SUSY datasets: tau(status==2)->tau(status==2)
71 if (MC::isDecayed(thePart) && MC::isTau(thePart)) {
72 const xAOD::TruthVertex* endVert = thePart->decayVtx();
73 if (endVert) {
74 if (endVert->nOutgoingParticles() == 1 && MC::isTau(endVert->outgoingParticle(0))) {
75 return std::make_pair(GenParticle, partOrig);
76 }
77 }
78 }
79
80 if (MC::isStable(thePart) && MC::isSUSY(thePart)) return std::make_pair(SUSYParticle, partOrig);
81
82 if (MC::isStable(thePart) && MC::isBSM(thePart)) return std::make_pair(OtherBSMParticle, partOrig);
83
84 if (MC::isDecayed(thePart) &&
85 (!MC::isElectron(thePart) && !MC::isMuon(thePart) &&
86 !MC::isTau(thePart) && !MC::isPhoton(thePart)) &&
87 !isPartHadr)
88 return std::make_pair(GenParticle, partOrig);
89
90 // FIXME vetoing protons here to preserve previous behaviour
91 if (MC::isNucleus(thePart) && std::abs(thePart->pdgId()) != MC::PROTON) return std::make_pair(NuclFrag, partOrig);
92
93 if ( !MC::isSMLepton(thePart) && !MC::isPhoton(thePart) && !isPartHadr) return std::make_pair(partType, partOrig);
94 // don't consider generator particles
95
96 const xAOD::TruthVertex* partProdVtx = thePart->hasProdVtx() ? thePart->prodVtx() : nullptr;
97
99 if (partProdVtx) {
100 for (const auto& temp: partProdVtx->particles_in()) {if (temp) parent = temp;}
101 }
102 const int parentPDG = parent?parent->pdg_id():0;
103 info.setMotherProperties(parent);
104
105 if (!partProdVtx && HepMC::is_simulation_particle(thePart)) {
106 return std::make_pair(NonPrimary, partOrig);
107 }
108 if (!partProdVtx && MC::isElectron(thePart)) {
109 // to define electron outcome status
110 bool isPrompt = false; // updated by defOrigOfElectron
111 partOrig = defOrigOfElectron(*truthParticleContainerReadHandle, thePart, isPrompt, info);
112 return std::make_pair(UnknownElectron, partOrig);
113 }
114 if (!partProdVtx && MC::isMuon(thePart)) {
115 // to define electron outcome status
116 bool isPrompt = false; // updated by defOrigOfMuon
117 partOrig = defOrigOfMuon(*truthParticleContainerReadHandle, thePart, isPrompt, info);
118 return std::make_pair(UnknownMuon, partOrig);
119 }
120 if (!partProdVtx && MC::isTau(thePart)) {
121 // to define electron outcome status
122 partOrig = defOrigOfTau(*truthParticleContainerReadHandle, thePart, parentPDG, info);
123 return std::make_pair(UnknownTau, partOrig);
124 }
125 if (!partProdVtx && MC::isPhoton(thePart)) {
126 // to define photon outcome
127 bool isPrompt = false; // updated by defOrigOfPhoton
128 partOrig = defOrigOfPhoton(*truthParticleContainerReadHandle, thePart, isPrompt, info);
129 return std::make_pair(UnknownPhoton, partOrig);
130 }
131 if (!partProdVtx && MC::isNeutrino(thePart)) {
132 // to define neutrino outcome
133 info.particleOutCome = NonInteract;
134 return std::make_pair(Neutrino, partOrig);
135 }
136
137 if (thePart && info.Mother() && HepMC::is_same_generator_particle(thePart,info.Mother()))
138 return std::make_pair(NonPrimary, partOrig);
139
140 if (isPartHadr) return std::make_pair(Hadron, partOrig);
141
142 if (partProdVtx && parentPDG == 0 && partProdVtx->nOutgoingParticles() == 1 &&
143 partProdVtx->nIncomingParticles() == 0) {
144 if (MC::isElectron(thePart)) {
145 info.particleOutCome = defOutComeOfElectron(thePart);
146 return std::make_pair(IsoElectron, SingleElec);
147 }
148 if (MC::isMuon(thePart)) {
149 info.particleOutCome = defOutComeOfMuon(thePart);
150 return std::make_pair(IsoMuon, SingleMuon);
151 }
152 if (MC::isTau(thePart)) {
153 info.particleOutCome = defOutComeOfTau(thePart);
154 return std::make_pair(IsoTau, SingleTau);
155 }
156 if (MC::isPhoton(thePart)) {
157 info.particleOutCome = defOutComeOfPhoton(thePart);
158 return std::make_pair(IsoPhoton, SinglePhot);
159 }
160 }
161
162 if (parentPDG == thePart->pdg_id() && parent && parent->status() == 3 && MC::isDecayed(thePart)) return std::make_pair(GenParticle, partOrig);
163
164 if (MC::isElectron(thePart)) {
165 bool isPrompt = false; // updated by defOrigOfElectron
166 partOrig = defOrigOfElectron(*truthParticleContainerReadHandle, thePart, isPrompt, info);
167 partType = defTypeOfElectron(partOrig, isPrompt);
168 } else if (MC::isMuon(thePart)) {
169 bool isPrompt = false; // updated by defOrigOfMuon
170 partOrig = defOrigOfMuon(*truthParticleContainerReadHandle, thePart, isPrompt, info);
171 partType = defTypeOfMuon(partOrig, isPrompt);
172 } else if (MC::isTau(thePart)) {
173 partOrig = defOrigOfTau(*truthParticleContainerReadHandle, thePart, parentPDG, info);
174 partType = defTypeOfTau(partOrig);
175 } else if (MC::isPhoton(thePart)) {
176 bool isPrompt = false; // updated by defOrigOfPhoton
177 partOrig = defOrigOfPhoton(*truthParticleContainerReadHandle, thePart, isPrompt, info);
178 partType = defTypeOfPhoton(partOrig);
179 } else if (MC::isNeutrino(thePart)) {
180 bool isPrompt = false; // updated by defOrigOfNeutrino
181 partOrig = defOrigOfNeutrino(*truthParticleContainerReadHandle, thePart, isPrompt, info);
182 partType = Neutrino;
183 }
184
185 ATH_MSG_DEBUG("particleTruthClassifier succeeded ");
186 return std::make_pair(partType, partOrig);
187}
@ UnknownTau
@ NuclFrag
@ OtherBSMParticle
@ IsoMuon
@ IsoElectron
@ UnknownElectron
@ NonPrimary
@ IsoPhoton
@ Neutrino
@ UnknownPhoton
@ SUSYParticle
@ UnknownMuon
@ GenParticle
@ SingleElec
@ SingleMuon
@ SingleTau
MCTruthPartClassifier::ParticleOrigin defOrigOfElectron(const xAOD::TruthParticleContainer &xTruthParticleContainer, const xAOD::TruthParticle *, bool &isPrompt, MCTruthPartClassifier::Info &info) const
namespace
MCTruthPartClassifier::ParticleOrigin defOrigOfNeutrino(const xAOD::TruthParticleContainer &xTruthParticleContainer, const xAOD::TruthParticle *, bool &isPrompt, MCTruthPartClassifier::Info &info) const
MCTruthPartClassifier::ParticleOrigin defOrigOfMuon(const xAOD::TruthParticleContainer &xTruthParticleContainer, const xAOD::TruthParticle *, bool &isPrompt, MCTruthPartClassifier::Info &info) const
MCTruthPartClassifier::ParticleOrigin defOrigOfPhoton(const xAOD::TruthParticleContainer &xTruthParticleContainer, const xAOD::TruthParticle *, bool &isPrompt, MCTruthPartClassifier::Info &info) const
int pdg_id() const
PDG ID code.
ParticleType defTypeOfPhoton(ParticleOrigin PhotOrig)
ParticleType defTypeOfMuon(ParticleOrigin MuOrig, bool isPrompt)
ParticleType defTypeOfElectron(ParticleOrigin EleOrig, bool isPrompt)
bool isNeutrino(const T &p)
APID: the fourth generation neutrinos are neutrinos.
bool isBeam(const T &p)
Identify if the particle is beam particle.
bool isHadron(const T &p)

◆ print()

◆ renounce()

std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > AthCommonDataStore< AthCommonMsg< AlgTool > >::renounce ( T & h)
inlineprotectedinherited

Definition at line 380 of file AthCommonDataStore.h.

381 {
382 h.renounce();
384 }
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce(T &h)

◆ renounceArray()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::renounceArray ( SG::VarHandleKeyArray & handlesArray)
inlineprotectedinherited

remove all handles from I/O resolution

Definition at line 364 of file AthCommonDataStore.h.

364 {
366 }

◆ sysInitialize()

virtual StatusCode AthCommonDataStore< AthCommonMsg< AlgTool > >::sysInitialize ( )
overridevirtualinherited

Perform system initialization for an algorithm.

We override this to declare all the elements of handle key arrays at the end of initialization. See comments on updateVHKA.

Reimplemented in asg::AsgMetadataTool, AthCheckedComponent< AthAlgTool >, and AthCheckedComponent<::AthAlgTool >.

◆ sysStart()

virtual StatusCode AthCommonDataStore< AthCommonMsg< AlgTool > >::sysStart ( )
overridevirtualinherited

Handle START transition.

We override this in order to make sure that conditions handle keys can cache a pointer to the conditions container.

◆ updateVHKA()

void AthCommonDataStore< AthCommonMsg< AlgTool > >::updateVHKA ( Gaudi::Details::PropertyBase & )
inlineinherited

Definition at line 308 of file AthCommonDataStore.h.

308 {
309 // debug() << "updateVHKA for property " << p.name() << " " << p.toString()
310 // << " size: " << m_vhka.size() << endmsg;
311 for (auto &a : m_vhka) {
313 for (auto k : keys) {
314 k->setOwner(this);
315 }
316 }
317 }
std::vector< SG::VarHandleKeyArray * > m_vhka

Member Data Documentation

◆ m_caloExtensionTool

ToolHandle<Trk::IParticleCaloExtensionTool> MCTruthClassifier::m_caloExtensionTool {this,"ParticleCaloExtensionTool",""}
private

Definition at line 205 of file MCTruthClassifier.h.

205{this,"ParticleCaloExtensionTool",""};

◆ m_caloMgrKey

SG::ReadCondHandleKey<CaloDetDescrManager> MCTruthClassifier::m_caloMgrKey {this,"CaloDetDescrManager",""}
private

Definition at line 206 of file MCTruthClassifier.h.

206{this,"CaloDetDescrManager",""};

◆ m_deltaPhiMatchCut

float MCTruthClassifier::m_deltaPhiMatchCut
private

Definition at line 233 of file MCTruthClassifier.h.

◆ m_deltaRMatchCut

float MCTruthClassifier::m_deltaRMatchCut
private

Definition at line 232 of file MCTruthClassifier.h.

◆ m_detStore

StoreGateSvc_t AthCommonDataStore< AthCommonMsg< AlgTool > >::m_detStore
privateinherited

Pointer to StoreGate (detector store by default).

Definition at line 393 of file AthCommonDataStore.h.

◆ m_evtStore

StoreGateSvc_t AthCommonDataStore< AthCommonMsg< AlgTool > >::m_evtStore
privateinherited

Pointer to StoreGate (event store by default).

Definition at line 390 of file AthCommonDataStore.h.

◆ m_FwdElectronTruthExtrEtaCut

float MCTruthClassifier::m_FwdElectronTruthExtrEtaCut
private

Definition at line 211 of file MCTruthClassifier.h.

◆ m_FwdElectronTruthExtrEtaWindowCut

float MCTruthClassifier::m_FwdElectronTruthExtrEtaWindowCut
private

Definition at line 212 of file MCTruthClassifier.h.

◆ m_FwdElectronUseG4Sel

bool MCTruthClassifier::m_FwdElectronUseG4Sel
private

Definition at line 210 of file MCTruthClassifier.h.

◆ m_fwrdEledRtoTrCut

float MCTruthClassifier::m_fwrdEledRtoTrCut
private

Definition at line 219 of file MCTruthClassifier.h.

◆ m_inclG4part

bool MCTruthClassifier::m_inclG4part
private

Definition at line 224 of file MCTruthClassifier.h.

◆ m_jetPartDRMatch

float MCTruthClassifier::m_jetPartDRMatch
private

Definition at line 235 of file MCTruthClassifier.h.

◆ m_NumOfSiHitsCut

int MCTruthClassifier::m_NumOfSiHitsCut
private

Definition at line 234 of file MCTruthClassifier.h.

◆ m_partExtrConeEta

float MCTruthClassifier::m_partExtrConeEta
private

Definition at line 213 of file MCTruthClassifier.h.

◆ m_partExtrConePhi

float MCTruthClassifier::m_partExtrConePhi
private

Definition at line 214 of file MCTruthClassifier.h.

◆ m_phtClasConeEta

float MCTruthClassifier::m_phtClasConeEta
private

Definition at line 217 of file MCTruthClassifier.h.

◆ m_phtClasConePhi

float MCTruthClassifier::m_phtClasConePhi
private

Definition at line 216 of file MCTruthClassifier.h.

◆ m_phtdRtoTrCut

float MCTruthClassifier::m_phtdRtoTrCut
private

Definition at line 218 of file MCTruthClassifier.h.

◆ m_pTChargePartCut

float MCTruthClassifier::m_pTChargePartCut
private

Definition at line 222 of file MCTruthClassifier.h.

◆ m_pTNeutralPartCut

float MCTruthClassifier::m_pTNeutralPartCut
private

Definition at line 223 of file MCTruthClassifier.h.

◆ m_ROICone

bool MCTruthClassifier::m_ROICone
private

Definition at line 220 of file MCTruthClassifier.h.

◆ m_truthInConeTool

ToolHandle<xAOD::ITruthParticlesInConeTool> MCTruthClassifier::m_truthInConeTool {this,"TruthInConeTool","xAOD::TruthParticlesInConeTool/TruthParticlesInConeTool"}
private

Definition at line 208 of file MCTruthClassifier.h.

208{this,"TruthInConeTool","xAOD::TruthParticlesInConeTool/TruthParticlesInConeTool"};

◆ m_truthLinkVecReadHandleKey

SG::ReadHandleKey<xAODTruthParticleLinkVector> MCTruthClassifier::m_truthLinkVecReadHandleKey {this,"xAODTruthLinkVector","xAODTruthLinks", "ReadHandleKey for xAODTruthParticleLinkVector"}
private

Definition at line 229 of file MCTruthClassifier.h.

229{this,"xAODTruthLinkVector","xAODTruthLinks", "ReadHandleKey for xAODTruthParticleLinkVector"};

◆ m_truthParticleContainerKey

SG::ReadHandleKey<xAOD::TruthParticleContainer> MCTruthClassifier::m_truthParticleContainerKey {this,"xAODTruthParticleContainerName","TruthParticles","ReadHandleKey for xAOD::TruthParticleContainer"}
private

Definition at line 202 of file MCTruthClassifier.h.

202{this,"xAODTruthParticleContainerName","TruthParticles","ReadHandleKey for xAOD::TruthParticleContainer"};

◆ m_useCaching

bool MCTruthClassifier::m_useCaching
private

Definition at line 215 of file MCTruthClassifier.h.

◆ m_varHandleArraysDeclared

bool AthCommonDataStore< AthCommonMsg< AlgTool > >::m_varHandleArraysDeclared
privateinherited

Definition at line 399 of file AthCommonDataStore.h.

◆ m_vhka

std::vector<SG::VarHandleKeyArray*> AthCommonDataStore< AthCommonMsg< AlgTool > >::m_vhka
privateinherited

Definition at line 398 of file AthCommonDataStore.h.


The documentation for this class was generated from the following files: