ATLAS Offline Software
Loading...
Searching...
No Matches
D3PD::D3PDMCTruthClassifier Class Reference

Work around MCTruthClassifier brain-damage. More...

#include <D3PDMCTruthClassifier.h>

Inheritance diagram for D3PD::D3PDMCTruthClassifier:
Collaboration diagram for D3PD::D3PDMCTruthClassifier:

Public Member Functions

 D3PDMCTruthClassifier (const std::string &type, const std::string &name, const IInterface *parent)
 Standard Gaudi tool constructor.
virtual StatusCode initialize ()
 Standard Gaudi initialize method.
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleTruthClassifier (const xAOD::Electron *el)
 Run the classifier for an electron.
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleTruthClassifier (const xAOD::Photon *el)
 Run the classifier for a photon.
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleTruthClassifier (const xAOD::Muon *mu)
 Run the classifier for a muon.
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOriginparticleTruthClassifier (const xAOD::TruthParticle *, MCTruthPartClassifier::Info *info=nullptr) 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::Jet *, bool DR, 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 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

bool get_tptruth_name (const std::string &tp_name, std::string &tptruth_name)
 Try to find a TrackParticleTruthCollection pointing at TP_NAME.
void getProperty1 (const std::string &pname, std::string &value)
 Helper to retrieve the value of a Gaudi property.
void setProperty1 (const std::string &pname, const std::string &value)
 Helper to set the value of a Gaudi property.
double detEta (double x, double y) const
double detPhi (double x, double y) const
bool TruthLoopDetectionMethod1 (const xAOD::TruthVertex *childOrigVtx, const xAOD::TruthParticle *parent) const
bool TruthLoopDetectionMethod2 (const xAOD::TruthParticle *child, const xAOD::TruthParticle *parent) const
bool TruthLoopDetectionMethod3 (const xAOD::TruthVertex *childOrigVtx, const xAOD::TruthParticle *parent) const
MCTruthPartClassifier::ParticleOrigin defOrigOfElectron (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 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
double fracParticleInJet (const xAOD::TruthParticle *, const xAOD::Jet *, bool DR, bool nparts) 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

ServiceHandle< StoreGateSvcm_sg
 The StoreGate service.
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

Work around MCTruthClassifier brain-damage.

This avoids having to specify the container names during configuration.

MCTruthClassifier requires specifying, at configuration time, the names of the TrackParticleContainer and TrackParticleTruthCollection objects to use for the mapping. This is painful in for electrons in the case where one may have several different track containers.

What we do to make this easier is to search through SG to find a truth collection that points at the TrackParticleContainer that contains the tracks for the electron we're looking at.

Definition at line 41 of file D3PDMCTruthClassifier.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

◆ D3PDMCTruthClassifier()

D3PD::D3PDMCTruthClassifier::D3PDMCTruthClassifier ( const std::string & type,
const std::string & name,
const IInterface * parent )

Standard Gaudi tool constructor.

Parameters
typeThe name of the tool type.
nameThe tool name.
parentThe tool's Gaudi parent.

Definition at line 39 of file D3PDMCTruthClassifier.cxx.

42 : MCTruthClassifier (type, name, parent),
43 m_sg ("StoreGateSvc", name)
44{
45}
ServiceHandle< StoreGateSvc > m_sg
The StoreGate service.
MCTruthClassifier(const std::string &type)

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 }
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)

◆ 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
privateinherited

Definition at line 247 of file MCTruthClassifierGen.cxx.

251{
252 ATH_MSG_DEBUG("Executing DefOrigOfElectron ");
253
254 // Find the first copy of this particle stored in the xAOD::TruthParticleContainer (i.e. the particle prior to any interactions)
255 const xAOD::TruthParticle* thePriPart = MC::findMatching(xTruthParticleContainer, thePart);
256 if (!thePriPart) return NonDefined;
257 if (!MC::isElectron(thePriPart)) return NonDefined;
258
259 //-- to define electron outcome status
260 info.particleOutCome = defOutComeOfElectron(thePriPart);
261
262 const xAOD::TruthVertex* partProdVtx = thePriPart->hasProdVtx() ? thePriPart->prodVtx() : nullptr;
263 if (!partProdVtx) return NonDefined;
264
265 if (partProdVtx->nIncomingParticles() > 1) ATH_MSG_DEBUG("DefOrigOfElectron:: electron has more than one parent.");
266
267 const xAOD::TruthParticle* ancestor = MC::findMother(thePriPart);
268 info.setMotherProperties(ancestor);
269 if (!ancestor) { return NonDefined; } // After this point "ancestor" cannot be nullptr
270
271 // Start of method 1 of protecting against loops
272 bool samePart = TruthLoopDetectionMethod1(partProdVtx, ancestor);
273 // to resolve Sherpa loop
274 // End of method 1 of protecting against loops
275
276 if ((MC::isMuon(ancestor) || MC::isTau(ancestor) || MC::isW(ancestor)) && ancestor->hasProdVtx() && !samePart) {
277 int pPDG(0);
278 const xAOD::TruthParticle* ancestorParent{};
279 do {
280 pPDG = 0; // reset pPDG
281 ancestorParent = MC::findMother(ancestor);
282 // Start of method 2 of protecting against loops
283 // to prevent Sherpa loop
284 if (ancestor == ancestorParent) { break; }
285 if (TruthLoopDetectionMethod2(ancestor,ancestorParent)) {
286 ancestorParent = ancestor;
287 break;
288 }
289 // End of method 2 of protecting against loops
290 // FIXME why are slightly different criteria used in method 1 and method 2???
291 if (ancestorParent) {
292 pPDG = ancestorParent->pdgId(); // Only set pPDG in the case that we aren't in a loop.
293 if (MC::isMuon(pPDG) || MC::isTau(pPDG) || MC::isW(pPDG)) { // There will be another iteration so set ancestor to ancestorParent
294 ancestor = ancestorParent; // ancestorParent is not nullptr here
295 }
296 }
297 } while ((MC::isMuon(pPDG) || MC::isTau(pPDG) || MC::isW(pPDG)));
298
299 if (MC::isMuon(pPDG) || MC::isTau(pPDG) || MC::isW(pPDG) || MC::isZ(pPDG) || MC::isHiggs(pPDG) ||
300 MC::isMSSMHiggs(pPDG) || MC::isHeavyBoson(pPDG) || MC::isTop(pPDG) || // MSSM Higgs bosons, Heavy bosons( Z', Z'', W'+)
301 std::abs(pPDG) == MC::WBOSON_LRSM || MC::isNeutrinoRH(pPDG) || // Left-right symmetric model WBoson || Right-handed neutrino (Pythia-specific)
302 MC::isSUSY(pPDG)) {
303 ancestor = ancestorParent; // ancestorParent is not nullptr here
304 }
305 }
306
307 info.setMotherProperties(ancestor);
308 const int ancestorPDG = ancestor->pdgId();
309 const xAOD::TruthVertex* ancestorProdVtx = ancestor->hasProdVtx() ? ancestor->prodVtx() : nullptr;
310 partProdVtx = ancestor->decayVtx();
311 const int numOfParents = partProdVtx->nIncomingParticles();
312 const int numberOfChildren = partProdVtx->nOutgoingParticles();
313
314 // Determine decay products
315 auto DP = DecayProducts(partProdVtx);
316 const int NumOfPhot = DP.pd(MC::PHOTON);
317 const int NumOfEl = DP.pd(MC::ELECTRON);
318 const int NumOfPos = DP.pd(MC::POSITRON);
319 const int NumOfquark = DP.apd({MC::DQUARK,MC::UQUARK,MC::SQUARK,MC::CQUARK,MC::BQUARK,MC::TQUARK});
320 const int NumOfgluon = DP.apd(MC::GLUON);
321 const int NumOfElNeut = DP.apd(MC::NU_E);
322 const int NumOfLQ = DP.apd(MC::LEPTOQUARK);
323 const int NumOfMuPl = DP.pd(-MC::MUON);
324 const int NumOfMuMin = DP.pd(MC::MUON);
325 const int NumOfMuNeut = DP.apd(MC::NU_MU);
326 const int NumOfTau = DP.apd(MC::TAU);
327 const int NumOfTauNeut = DP.apd(MC::NU_TAU);
328
329 samePart = false;
330 int NumOfNucFr(0);
331 const bool possibleNuclearFragment = (numOfParents == 1 && (MC::isPhoton(ancestorPDG) || MC::isElectron(ancestorPDG) || MC::isMuon(ancestorPDG) || std::abs(ancestorPDG) == MC::PIPLUS));
332 for (const auto& aChild: partProdVtx->particles_out()) {
333 if (!aChild) continue;
334 const int childPDG = aChild->pdgId();
335 if (std::abs(childPDG) == std::abs(ancestorPDG) && HepMC::is_same_generator_particle(aChild, ancestor )) samePart = true;
336 if (possibleNuclearFragment &&
337 (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?
338 std::abs(childPDG) == MC::PIPLUS || std::abs(childPDG) == MC::PI0))
339 NumOfNucFr++;
340 }
341 // End of section determining decay products
342
343 if (MC::isPhoton(ancestorPDG) && ancestorProdVtx) {
344 if (ancestorProdVtx->nIncomingParticles() > 1) { ATH_MSG_DEBUG("DefOrigOfElectron:: photon has more than one parent."); }
345 for (const auto& photonParent: ancestorProdVtx->particles_in()) {
346 if (!photonParent) continue;
347 info.photonMother = photonParent; // FIXME Just taking the first valid particle...
348 }
349 }
350
351 if ((MC::isPhoton(ancestorPDG) && numberOfChildren == 2 && NumOfEl == 1 && NumOfPos == 1) || (MC::isPhoton(ancestorPDG) && numberOfChildren == 1 && (NumOfEl == 1 || NumOfPos == 1))) return PhotonConv;
352
353 // e,gamma,pi+Nuclear->NuclearFragments+nuclons+e
354 if ((numOfParents == 1 && (MC::isPhoton(ancestorPDG) || MC::isElectron(ancestorPDG) || MC::isTau(ancestorPDG))) && numberOfChildren > 1 && NumOfNucFr != 0) return ElMagProc;
355
356 if (numOfParents == 1 && std::abs(ancestorPDG) == MC::PIPLUS && numberOfChildren > 2 && NumOfNucFr != 0) return ElMagProc;
357
358 // nuclear photo fission
359 if (MC::isPhoton(ancestorPDG) && numberOfChildren > 4 && NumOfNucFr != 0) return ElMagProc;
360
361 // unknown process el(pos)->el+pos??
362 if (MC::isElectron(ancestorPDG) && numberOfChildren == 2 && NumOfEl == 1 && NumOfPos == 1) return ElMagProc;
363
364 // unknown process el->el+el??
365 if (ancestorPDG == MC::ELECTRON && numberOfChildren == 2 && NumOfEl == 2 && NumOfPos == 0) return ElMagProc;
366
367 // unknown process pos->pos+pos??
368 if (ancestorPDG == MC::POSITRON && numberOfChildren == 2 && NumOfEl == 0 && NumOfPos == 2) return ElMagProc;
369
370 // unknown process pos/el->pos/el??
371 if (MC::isElectron(ancestorPDG) && !MC::isDecayed(ancestor) && ancestorPDG == thePriPart->pdgId() && numberOfChildren == 1 && !samePart) return ElMagProc;
372
373 // pi->pi+e+/e-; mu->mu+e+/e- ;
374 // gamma+ atom->gamma(the same) + e (compton scattering)
375 if (numberOfChildren == 2 && (NumOfEl == 1 || NumOfPos == 1) && !MC::isElectron(ancestorPDG) && samePart) return ElMagProc;
376
377 if ((ancestorPDG == MC::PI0 && numberOfChildren == 3 && NumOfPhot == 1 && NumOfEl == 1 && NumOfPos == 1) ||
378 (ancestorPDG == MC::PI0 && numberOfChildren == 4 && NumOfPhot == 0 && NumOfEl == 2 && NumOfPos == 2))
379 return DalitzDec;
380
381 // Quark weak decay
382 if (MC::isSMQuark(ancestorPDG) && numOfParents == 1 && numberOfChildren == 3 && NumOfquark == 1 && NumOfElNeut == 1) return QuarkWeakDec;
383
384 if (MC::isMuon(ancestorPDG) && NumOfNucFr != 0) return ElMagProc;
385
386 if (MC::isTop(ancestorPDG)) return top;
387
388 if (MC::isW(ancestorPDG) && ancestorProdVtx && ancestorProdVtx->nIncomingParticles() != 0) {
389
390 const xAOD::TruthVertex* prodVert = ancestorProdVtx;
391 const xAOD::TruthParticle* ptrPart{};
392 do {
393 ptrPart = prodVert->incomingParticle(0); // FIXME just taking the first one
394 prodVert = ptrPart->hasProdVtx() ? ptrPart->prodVtx() : nullptr;
395 } while (MC::isW(ptrPart) && prodVert);
396
397 if (prodVert && prodVert->nIncomingParticles() == 1) {
398 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_E) return NuREle; // Right-handed NU_E (Pythia-specific)
399 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_MU) return NuRMu; // Right-handed NU_MU (Pythia-specific)
400 if (std::abs(ptrPart->pdgId()) == MC::RH_NU_TAU) return NuRTau; // Right-handed NU_TAU (Pythia-specific)
401 }
402 return WBoson;
403 }
404 if (MC::isW(ancestorPDG)) return WBoson;
405 if (MC::isZ(ancestorPDG)) return ZBoson;
406
407 // MadGraphPythia ZWW*->lllnulnu
408 if (numOfParents == 1 && numberOfChildren > 4 && (MC::isSMQuark(ancestorPDG) || MC::isGluon(ancestorPDG))) {
409
410 const xAOD::TruthParticle* thePartToCheck = thePriPart;
411 const xAOD::TruthParticle* theParent = thePriPart->hasProdVtx() ? thePriPart->prodVtx()->incomingParticle(0) : nullptr; // FIXME just taking the first one
412 if (theParent && MC::isElectron(theParent) && MC::isDecayed(theParent)) { thePartToCheck = theParent; }
413
414 bool isZboson = false;
415 bool isWboson = false;
416 bool skipnext = false;
417
418 for (unsigned int ipOut = 0; ipOut + 1 < partProdVtx->nOutgoingParticles(); ++ipOut) {
419 const xAOD::TruthParticle* aChild = partProdVtx->outgoingParticle(ipOut);
420 if (!aChild) continue;
421 const xAOD::TruthParticle* theNextChild = nullptr;
422 for (unsigned int ipOut1 = ipOut + 1; ipOut1 < partProdVtx->nOutgoingParticles(); ipOut1++) {
423 theNextChild = partProdVtx->outgoingParticle(ipOut1);
424 if (theNextChild) break;
425 }
426 if (!theNextChild) continue;
427 if (skipnext) {
428 skipnext = false;
429 continue;
430 }
431
432 if (MC::isElectron(aChild) && MC::isElectron(theNextChild)) {
433 // Zboson
434 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
435 isZboson = true;
436 break;
437 }
438 skipnext = true;
439 } else if (MC::isElectron(aChild) && std::abs(theNextChild->pdgId()) == MC::NU_E) {
440 // WBoson
441 if (thePartToCheck == aChild || thePartToCheck == theNextChild) {
442 isWboson = true;
443 break;
444 }
445 skipnext = true;
446 }
447 }
448 if (isWboson) return WBoson;
449 if (isZboson) return ZBoson;
450 }
451 if (numOfParents == 2) {
452 //--Sherpa Z->ee
453 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && NumOfEl == 1 && NumOfPos == 1) return ZBoson;
454
455 //--Sherpa W->enu ??
456 if ((numberOfChildren - NumOfquark - NumOfgluon) == 2 && (NumOfEl == 1 || NumOfPos == 1) && NumOfElNeut == 1) return WBoson;
457
458 const int pdg1 = partProdVtx->incomingParticle(0)->pdgId();
459 const int pdg2 = partProdVtx->incomingParticle(1)->pdgId();
460 //--Sherpa ZZ,ZW
461 if ((numberOfChildren - NumOfquark - NumOfgluon) == 4 &&
462 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 4) &&
463 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) return DiBoson;
464
465 //--Sherpa VVV -- Note, have to allow for prompt photon radiation or these get lost
466 if ((numberOfChildren - NumOfquark - NumOfgluon - NumOfPhot) == 6 &&
467 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 6) &&
468 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) return MultiBoson;
469
470 //--Sherpa tttt with all t->Wb; W->lnu
471 if ((numberOfChildren - NumOfquark - NumOfgluon) == 8 &&
472 (NumOfEl + NumOfPos + NumOfMuPl + NumOfMuMin + NumOfTau + NumOfElNeut + NumOfMuNeut + NumOfTauNeut == 8) &&
473 (MC::isQuark(pdg1)||MC::isGluon(pdg1)) && (MC::isQuark(pdg2)||MC::isGluon(pdg2))) {
474 ATH_MSG_VERBOSE("MultiBoson for 4topLep");
475 return MultiBoson;
476 }
477 }
478
479 // New Sherpa Z->ee
480 if (partProdVtx == ancestorProdVtx) {
481 int NumOfEleLoop = 0;
482 int NumOfLepLoop = 0;
483 int NumOfEleNeuLoop = 0;
484 for (const auto *const pout: partProdVtx->particles_out()) {
485 if (!pout) continue;
486 for (const auto *const pin: partProdVtx->particles_in()) {
487 if (!pin) continue;
488 if (!HepMC::is_same_particle(pout,pin)) continue;
489 if (MC::isElectron(pout)) NumOfEleLoop++;
490 if (std::abs(pout->pdgId()) == MC::NU_E) NumOfEleNeuLoop++;
491 if (MC::isSMLepton(pout)) NumOfLepLoop++;
492 break; // break out of inner loop after having found two matching particles
493 }
494 }
495 if (NumOfEleLoop == 2 && NumOfEleNeuLoop == 0) return ZBoson;
496 if (NumOfEleLoop == 1 && NumOfEleNeuLoop == 1) return WBoson;
497 if ((NumOfEleLoop == 4 && NumOfEleNeuLoop == 0) || (NumOfEleLoop == 3 && NumOfEleNeuLoop == 1) ||
498 (NumOfEleLoop == 2 && NumOfEleNeuLoop == 2)) return DiBoson;
499 if (NumOfLepLoop == 4) return DiBoson;
500 }
501
502 //-- McAtNLo
503
504 if (MC::isHiggs(ancestorPDG)) return Higgs;
505
506 if (MC::isMSSMHiggs(ancestorPDG)) return HiggsMSSM; // MSSM Higgs bosons
507
508 if (MC::isHeavyBoson(ancestorPDG)) return HeavyBoson; // Heavy bosons( Z', Z'', W'+)
509
510 if (MC::isMuon(ancestorPDG)) return Mu;
511 if (MC::isTau(ancestorPDG)) {
512 const ParticleOrigin tauOrig = defOrigOfTau(xTruthParticleContainer, ancestor, ancestorPDG, info);
513 const ParticleType tautype = defTypeOfTau(tauOrig);
514 return (tautype == IsoTau)?tauOrig:TauLep;
515 }
516
517 if (std::abs(ancestorPDG) == MC::WBOSON_LRSM) return WBosonLRSM; // Left-right symmetric model WBoson (Pythia-specific)
518 if (std::abs(ancestorPDG) == MC::RH_NU_E) return NuREle; // Right-handed NU_E (Pythia-specific)
519 if (std::abs(ancestorPDG) == MC::RH_NU_MU) return NuRMu; // Right-handed NU_MU (Pythia-specific)
520 if (std::abs(ancestorPDG) == MC::RH_NU_TAU) return NuRTau; // Right-handed NU_TAU (Pythia-specific)
521 if (MC::isLeptoQuark(ancestorPDG) || NumOfLQ != 0) return LQ;
522 if (MC::isSUSY(ancestorPDG)) return SUSY;
523 if (MC::isBSM(ancestorPDG)) return OtherBSM;
524
525 const ParticleType pType = defTypeOfHadron(ancestorPDG);
526 if ((pType == BBbarMesonPart || pType == CCbarMesonPart) && ancestorProdVtx && MC::isHardScatteringVertex(ancestorProdVtx)) isPrompt = true;
527 return convHadronTypeToOrig(pType, ancestorPDG);
528}
#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
bool TruthLoopDetectionMethod1(const xAOD::TruthVertex *childOrigVtx, const xAOD::TruthParticle *parent) const
bool TruthLoopDetectionMethod2(const xAOD::TruthParticle *child, const xAOD::TruthParticle *parent) const
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
privateinherited

Definition at line 531 of file MCTruthClassifierGen.cxx.

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

Definition at line 1203 of file MCTruthClassifierGen.cxx.

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

◆ defOrigOfPhoton()

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

Definition at line 940 of file MCTruthClassifierGen.cxx.

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

Definition at line 759 of file MCTruthClassifierGen.cxx.

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

◆ detEta()

double MCTruthClassifier::detEta ( double x,
double y ) const
inlineprivateinherited

Definition at line 159 of file MCTruthClassifier.h.

159{ return std::abs(x - y); }
#define y
#define x

◆ detPhi()

double MCTruthClassifier::detPhi ( double x,
double y ) const
inlineprivateinherited

Definition at line 160 of file MCTruthClassifier.h.

160 {
161 double det = x - y;
162 if (det > M_PI) det = det - 2. * M_PI;
163 if (det < -M_PI) det = det + 2. * M_PI;
164 return std::abs(det);
165 }
#define M_PI

◆ 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
finaloverridevirtualinherited

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
101 // eleptical cone for extrapolations m_partExtrConePhi X m_partExtrConeEta
102 if (!isFwrdEle && m_ROICone && std::hypot( detPhi(phiClus, thePart->phi())/m_partExtrConePhi, detEta(etaClus, thePart->eta())/m_partExtrConeEta) > 1.0) {
103 continue;
104 }
105 // Also check if the clus and true have different sign , i they need both to be <0 or >0
106 if (isFwrdEle && // It is forward and
107 (((etaClus < 0) - (thePart->eta() < 0) != 0)
108 // The truth eta has different sign wrt to the fwd electron
109 || (std::fabs(thePart->eta()) < m_FwdElectronTruthExtrEtaCut) // or the truth is less than 2.4 (default cut)
110 || (std::fabs(thePart->eta() - etaClus) > m_FwdElectronTruthExtrEtaWindowCut) // or if the delta Eta between el and truth is > 0.15
111 ) // then do no extrapolate this truth Particle for this fwd electron
112 ) {
113 continue;
114 }
115 double dR(-999.);
116 bool isNCone = false;
117 bool isExt = genPartToCalo(ctx, clus, thePart, isFwrdEle, dR, isNCone, *caloDDMgr);
118 if (!isExt) continue;
119 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(), thePart);
120 if (info) {
121 info->egPartPtr.push_back(thePart);
122 info->egPartdR.push_back(dR);
123 info->egPartClas.push_back(particleTruthClassifier(theMatchPart, info));
124 }
125 // Gen particles Not forward
126 if (!isFwrdEle) {
127 // the leading photon or electron inside narrow eleptical cone
128 // m_phtClasConePhi X m_phtClasConeEta
129 if ((iParticlePDG == 22 || std::abs(iParticlePDG) == 11) && isNCone && pt > LeadingPhtPT) {
130 theEgamma = thePart;
131 LeadingPhtPT = pt;
132 LeadingPhtdR = dR;
133 }
134 // leading particle (excluding photon and electron) inside narrow eleptic
135 // cone m_phtClasConePhi X m_phtClasConeEta
136 if ((iParticlePDG != 22 && std::abs(iParticlePDG) != 11) && isNCone && pt > LeadingPartPT) {
137 theLeadingPartInCone = thePart;
138 LeadingPartPT = pt;
139 LeadingPartdR = dR;
140 };
141 // the best dR matched particle outside narrow eleptic cone cone
142 // m_phtClasConePhi X m_phtClasConeEta
143 if (!isNCone && dR < BestPartdR) {
144 theBestPartOutCone = thePart;
145 BestPartdR = dR;
146 };
147 } else {
148 if (dR < BestPartdR) {
149 theBestPartdR = thePart;
150 BestPartdR = dR;
151 };
152 }
153 }
154
155 if (theEgamma != nullptr) {
156 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(), theEgamma);
157 if (info) info->deltaRMatch = LeadingPhtdR;
158 } else if (theLeadingPartInCone != nullptr) {
159 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theLeadingPartInCone);
160 if (info) info->deltaRMatch = LeadingPartdR;
161 } else if (theBestPartOutCone != nullptr) {
162 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theBestPartOutCone);
163 if (info) info->deltaRMatch = BestPartdR;
164 } else if (isFwrdEle && theBestPartdR != nullptr) {
165 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theBestPartdR );
166 if (info) info->deltaRMatch = BestPartdR;
167 } else {
168 theMatchPart = nullptr;
169 }
170 if (isFwrdEle || theMatchPart != nullptr || !m_inclG4part) return theMatchPart;
171
172 // additional loop over G4 particles,
173 for (const auto* const thePart : tps) {
174 if (!MC::isStable(thePart)) continue;
175 if (!HepMC::is_simulation_particle(thePart)) continue;
176 long iParticlePDG = thePart->pdgId();
177 // exclude neutrino
178 if (std::abs(iParticlePDG) == 12 || std::abs(iParticlePDG) == 14 || std::abs(iParticlePDG) == 16) continue;
179 if (thePart->decayVtx() != nullptr) continue;
180 if (std::hypot( detPhi(phiClus, thePart->phi())/m_partExtrConePhi, detEta(etaClus, thePart->eta())/m_partExtrConeEta ) > 1.0) continue;
181
182 double pt = thePart->pt() / Athena::Units::GeV;
183 double q = thePart->charge();
184 // exclude charged particles with pT<1 GeV
185 if (q != 0 && pt < m_pTChargePartCut) continue;
186 if (q == 0 && pt < m_pTNeutralPartCut) continue;
187
188 double dR(-999.);
189 bool isNCone = false;
190 bool isExt = genPartToCalo(ctx, clus, thePart, isFwrdEle, dR, isNCone, *caloDDMgr);
191 if (!isExt) continue;
192
193 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),thePart);
194 if (info) {
195 info->egPartPtr.push_back(thePart);
196 info->egPartdR.push_back(dR);
197 info->egPartClas.push_back(particleTruthClassifier(theMatchPart, info));
198 }
199 // the leading photon or electron inside narrow eleptical cone
200 // m_phtClasConePhi X m_phtClasConeEta
201 if ((iParticlePDG == 22 || std::abs(iParticlePDG) == 11) && isNCone && pt > LeadingPhtPT) {
202 theEgamma = thePart;
203 LeadingPhtPT = pt;
204 LeadingPhtdR = dR;
205 }
206 // leading particle (excluding photon or electron) inside narrow eleptic
207 // cone m_phtClasConePhi X m_phtClasConeEta
208 if ((iParticlePDG != 22 && std::abs(iParticlePDG) != 11) && isNCone && pt > LeadingPartPT) {
209 theLeadingPartInCone = thePart;
210 LeadingPartPT = pt;
211 LeadingPartdR = dR;
212 }
213 // the best dR matched particle outside narrow eleptic cone cone
214 // m_phtClasConePhi X m_phtClasConeEta
215 if (!isNCone && dR < BestPartdR) {
216 theBestPartOutCone = thePart;
217 BestPartdR = dR;
218 }
219 }
220
221 if (theEgamma != nullptr) {
222 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theEgamma);
223 if (info) info->deltaRMatch = LeadingPhtdR;
224 } else if (theLeadingPartInCone != nullptr) {
225 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theLeadingPartInCone);
226 if (info) info->deltaRMatch = LeadingPartdR;
227 } else if (theBestPartOutCone != nullptr) {
228 theMatchPart = MC::findMatching(truthParticleContainerReadHandle.ptr(),theBestPartOutCone);
229 if (info) info->deltaRMatch = BestPartdR;
230 } else {
231 theMatchPart = nullptr;
232 }
233 ATH_MSG_DEBUG("succeeded egammaClusMatch ");
234 return theMatchPart;
235}
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
float m_FwdElectronTruthExtrEtaWindowCut
double detEta(double x, double y) const
virtual std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin > particleTruthClassifier(const xAOD::TruthParticle *, MCTruthPartClassifier::Info *info=nullptr) const override final
double detPhi(double x, double y) const
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.

◆ 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
privateinherited

Definition at line 278 of file MCRecoToTruth.cxx.

281{
282 if (DR) {
283 // use a DR matching scheme (default)
284 // retrieve collection and get a pointer
285 SG::ReadHandle<xAOD::TruthParticleContainer> truthParticleContainerReadHandle(m_truthParticleContainerKey);
286
287 if (!truthParticleContainerReadHandle.isValid()) {
288 ATH_MSG_WARNING(" Invalid ReadHandle for xAOD::TruthParticleContainer with key: " << truthParticleContainerReadHandle.key());
289 return;
290 }
291 ATH_MSG_DEBUG("xAODTruthParticleContainer with key " << truthParticleContainerReadHandle.key() << " has valid ReadHandle ");
292 // find the matching truth particles
293 for (const auto *const thePart : *truthParticleContainerReadHandle) {
294 // match truth particles to the jet
295 if (MC::isStable(thePart) && thePart->p4().DeltaR(jet->p4()) < m_jetPartDRMatch) {
296 constituents.insert(thePart);
297 }
298 }
299 }
300 else {
301 xAOD::JetConstituentVector vec = jet->getConstituents();
302 for (const auto *particle0 : vec) {
303 const xAOD::TruthParticle* thePart = dynamic_cast<const xAOD::TruthParticle*>(particle0->rawConstituent());
304 if (MC::isStable(thePart)) {
305 constituents.insert(thePart);
306 }
307 }
308 }
309}
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

◆ fracParticleInJet()

double MCTruthClassifier::fracParticleInJet ( const xAOD::TruthParticle * thePart,
const xAOD::Jet * jet,
bool DR,
bool nparts ) const
privateinherited

Definition at line 310 of file MCRecoToTruth.cxx.

311{
312 std::set<const xAOD::TruthParticle*> constituents;
313 std::set<const xAOD::TruthParticle*> daughters;
314 std::set<const xAOD::TruthParticle*> intersect;
315
316 findJetConstituents(jet, constituents, DR);
317 MC::findParticleStableDescendants(thePart, daughters);
318 if (daughters.empty()) daughters.insert(thePart);
319 // Get the intersection of constituents and daughters
320 std::set_intersection(constituents.begin(),
321 constituents.end(),
322 daughters.begin(),
323 daughters.end(),
324 std::inserter(intersect, intersect.begin()));
325
326 if (nparts) return 1.0*intersect.size() / daughters.size();
327 double frac = 0;
328 double tot = 0;
329 for (const auto *daughter : daughters) { tot += daughter->pt();}
330 for (const auto *particle : intersect) { frac += particle->pt();}
331 return frac/tot;
332}
void findJetConstituents(const xAOD::Jet *, std::set< const xAOD::TruthParticle * > &constituents, bool DR) const
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
void findParticleStableDescendants(T thePart, std::set< T > &allstabledescendants)
Function to get the particle stable MC daughters.
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses

◆ 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
privateinherited

Definition at line 237 of file MCTruthClassifierAthena.cxx.

244{
245 dRmatch = -999.;
246 isNarrowCone = false;
247 if (thePart == nullptr) return false;
248 double phiClus = clus->phiBE(2);
249 double etaClus = clus->etaBE(2);
250 if (etaClus < -900) {
251 etaClus = clus->eta();
252 }
253 if (phiClus < -900) {
254 phiClus = clus->phi();
255 }
256 //--FixMe
257 if (isFwrdEle || (etaClus == 0. && phiClus == 0.)) {
258 phiClus = clus->phi();
259 etaClus = clus->eta();
260 }
261 // define calo sample
262 CaloSampling::CaloSample sample = CaloSampling::EMB2;
263 if ((clus->inBarrel() && !clus->inEndcap()) ||
264 (clus->inBarrel() && clus->inEndcap() && clus->eSample(CaloSampling::EMB2) >= clus->eSample(CaloSampling::EME2))) {
265 // Barrel
266 sample = CaloSampling::EMB2;
267 } else if ((!clus->inBarrel() && clus->inEndcap() && !isFwrdEle) ||
268 (clus->inBarrel() && clus->inEndcap() && clus->eSample(CaloSampling::EME2) > clus->eSample(CaloSampling::EMB2))) {
269 // End-cap
270 sample = CaloSampling::EME2;
271 } else if (isFwrdEle && clus->inEndcap()) {
272 // FCAL
273 sample = CaloSampling::FCAL2;
274 } else {
275 return false;
276 }
277 std::unique_ptr<Trk::CurvilinearParameters> params = extractParamFromTruth(*thePart);
278 if (!params) return false;
279 // create extension to sample
280 std::vector<CaloSampling::CaloSample> samples = { sample };
281 auto extension = m_caloExtensionTool->layersCaloExtension(ctx, *params, samples, etaClus, caloDDMgr);
282 bool extensionOK = (!extension.empty());
283 if (!extensionOK) {
284 ATH_MSG_WARNING("extrapolation of Truth Particle with eta " << thePart->eta() << " , charge " << thePart->charge() << " , Pt " << thePart->pt() << " to calo failed");
285 return false;
286 }
287 double etaCalo = extension[0].second->position().eta();
288 double phiCalo = extension[0].second->position().phi();
289
290 double dPhi = detPhi(phiCalo, phiClus);
291 double dEta = detEta(etaCalo, etaClus);
292 dRmatch = std::hypot(dPhi, dEta);
293
294 if ((!isFwrdEle && dRmatch > m_phtdRtoTrCut) || (isFwrdEle && dRmatch > m_fwrdEledRtoTrCut)) return false;
295 if (!isFwrdEle && std::hypot( dPhi/m_phtClasConePhi, dEta/m_phtClasConeEta ) <= 1.0) isNarrowCone = true;
296 return true;
297}
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.
bool dPhi(const xAOD::TauJet &tau, const xAOD::CaloVertexedTopoCluster &cluster, float &out)
bool dEta(const xAOD::TauJet &tau, const xAOD::CaloVertexedTopoCluster &cluster, float &out)

◆ get_tptruth_name()

bool D3PD::D3PDMCTruthClassifier::get_tptruth_name ( const std::string & tp_name,
std::string & tptruth_name )
private

Try to find a TrackParticleTruthCollection pointing at TP_NAME.

Parameters
tp_nameThe name of a TrackParticleContainer.
tptruth_name[out]The name of a TrackParticleTruthCollection pointing at it.
Returns
True if we found a good truth collection.

Definition at line 174 of file D3PDMCTruthClassifier.cxx.

176{
177 // Check all TrackParticleTruthCollections to try to find one
178 // pointing at the desired TrackParticle container.
179 std::vector<std::string> keys;
181
182 for (size_t i = 0; i < keys.size(); i++) {
183 const TrackParticleTruthCollection* tptc = 0;
184 if (m_sg->retrieve (tptc, keys[i]).isFailure() || !tptc)
185 {
186 ATH_MSG_WARNING( "Can't retrieve TrackParticleTruthCollection/"
187 << keys[i] );
188 continue;
189 }
190 tptruth_name = keys[i];
191
192 std::string target_tp_name;
194 // Older files didn't have this link. Hardcode this case.
195 target_tp_name = "TrackParticleCandidate";
196 }
197 else if (!tptc->trackParticleContainerLink().isValid())
198 continue;
199 else
200 target_tp_name = tptc->trackParticleContainerLink().dataID();
201
202 if (tp_name == target_tp_name)
203 return true;
204 }
205 return false;
206}
Athena::TPCnvVers::Old TrackParticleTruthCollection
bool isDefault() const
Test to see if we're in the default state.
DataLink< Rec::TrackParticleContainer > trackParticleContainerLink() const

◆ getGenPart()

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

Implements IMCTruthClassifier.

Definition at line 181 of file MCRecoToTruth.cxx.

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

◆ getProperty1()

void D3PD::D3PDMCTruthClassifier::getProperty1 ( const std::string & pname,
std::string & value )
private

Helper to retrieve the value of a Gaudi property.

Parameters
pnameThe name of the property. param value[out] The value of the property.

Definition at line 214 of file D3PDMCTruthClassifier.cxx.

216{
217 StatusCode sc = getProperty (pname, value);
218 if (sc.isFailure())
219 REPORT_ERROR (sc) << "Can't get property " << pname << "\n";
220}
#define REPORT_ERROR(SC)
Report an error.
static Double_t sc
const T * getProperty(const std::string &name) const
Get one of the tool's properties.
::StatusCode StatusCode
StatusCode definition for legacy code.

◆ initialize()

StatusCode D3PD::D3PDMCTruthClassifier::initialize ( void )
virtual

Standard Gaudi initialize method.

Reimplemented from MCTruthClassifier.

Definition at line 51 of file D3PDMCTruthClassifier.cxx.

52{
54 CHECK( m_sg.retrieve() );
55 return StatusCode::SUCCESS;
56}
#define CHECK(...)
Evaluate an expression and check for errors.
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.

◆ 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
finaloverridevirtualinherited

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
SG::ReadHandleKey< xAODTruthParticleLinkVector > m_truthLinkVecReadHandleKey

◆ particleTruthClassifier() [1/8]

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

Reimplemented from MCTruthClassifier.

Definition at line 143 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 std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin > particleTruthClassifier(const xAOD::Electron *el)
Run the classifier for an electron.
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() [2/8]

std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin > D3PD::D3PDMCTruthClassifier::particleTruthClassifier ( const xAOD::Electron * el)
virtual

Run the classifier for an electron.

Parameters
elThe input electron.

Definition at line 65 of file D3PDMCTruthClassifier.cxx.

66{
67 // Try to find the name of the truth map container,
68 // given the name of the TrackParticleContainer.
69 bool got_names = false;
70 std::string tp_truth_name, tp_name;
71 if (el->trackParticleLink().isValid()) {
72 tp_name = el->trackParticleLink().dataID();
73 got_names = get_tptruth_name (tp_name, tp_truth_name);
74 }
75
76 // If we found the truth map container, diddle the properties
77 // for the base tool (remembering the original values).
78 std::string old_tp_truth_name, old_tp_name;
79 if (got_names) {
80 getProperty1 ("TrackParticleTruthCollection", old_tp_truth_name);
81 getProperty1 ("TrackParticleContainerName", old_tp_name);
82 setProperty1 ("TrackParticleTruthCollection", tp_truth_name);
83 setProperty1 ("TrackParticleContainerName", tp_name);
84 }
85
86 // Call the base tool.
90
91 // Restore original properties, if we changed them.
92 if (got_names) {
93 setProperty1 ("TrackParticleTruthCollection", old_tp_truth_name);
94 setProperty1 ("TrackParticleContainerName", old_tp_name);
95 }
96
97 return ret;
98}
bool get_tptruth_name(const std::string &tp_name, std::string &tptruth_name)
Try to find a TrackParticleTruthCollection pointing at TP_NAME.
void setProperty1(const std::string &pname, const std::string &value)
Helper to set the value of a Gaudi property.
void getProperty1(const std::string &pname, std::string &value)
Helper to retrieve the value of a Gaudi property.

◆ particleTruthClassifier() [3/8]

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

Reimplemented from MCTruthClassifier.

Definition at line 155 of file MCRecoToTruth.cxx.

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

◆ particleTruthClassifier() [4/8]

std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin > D3PD::D3PDMCTruthClassifier::particleTruthClassifier ( const xAOD::Muon * mu)
virtual

Run the classifier for a muon.

This function is here to avoid a problem on the mc12 validation samples.

Parameters
elThe input photon.

Definition at line 155 of file D3PDMCTruthClassifier.cxx.

156{
157 // Avoid using forward muons that have a tracklet associated to them:
158 if( mu->muonType() == xAOD::Muon::SiliconAssociatedForwardMuon ) {
160 }
161
162 // For all other muons just use the base class's function:
164}

◆ particleTruthClassifier() [5/8]

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

Reimplemented from MCTruthClassifier.

Definition at line 146 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/8]

std::pair< MCTruthPartClassifier::ParticleType, MCTruthPartClassifier::ParticleOrigin > D3PD::D3PDMCTruthClassifier::particleTruthClassifier ( const xAOD::Photon * ph)
virtual

Run the classifier for a photon.

Parameters
elThe input photon.

Definition at line 107 of file D3PDMCTruthClassifier.cxx.

108{
109 // Try to find the name of the truth map container,
110 // given the name of the TrackParticleContainer.
111 bool got_names = false;
112 std::string tp_truth_name, tp_name;
113 const xAOD::Vertex* vx = ph->vertex();
114 if (vx) {
116 for (auto trklink : links) {
117 if (trklink.isValid()) {
118 tp_name = trklink.dataID();
119 got_names = get_tptruth_name (tp_name, tp_truth_name);
120 if (got_names) break;
121 }
122 }
123 }
124
125 // If we found the truth map container, diddle the properties
126 // for the base tool (remembering the original values).
127 std::string old_tp_truth_name, old_tp_name;
128 if (got_names) {
129 getProperty1 ("TrackParticleTruthCollection", old_tp_truth_name);
130 getProperty1 ("TrackParticleContainerName", old_tp_name);
131 setProperty1 ("TrackParticleTruthCollection", tp_truth_name);
132 setProperty1 ("TrackParticleContainerName", tp_name);
133 }
134
135 // Call the base tool.
139
140 // Restore original properties, if we changed them.
141 if (got_names) {
142 setProperty1 ("TrackParticleTruthCollection", old_tp_truth_name);
143 setProperty1 ("TrackParticleContainerName", old_tp_name);
144 }
145
146 return ret;
147}
const TrackParticleLinks_t & trackParticleLinks() const
Get all the particles associated with the vertex.
std::vector< ElementLink< xAOD::TrackParticleContainer > > TrackParticleLinks_t
Type for the associated track particles.
Definition Vertex_v1.h:128

◆ particleTruthClassifier() [7/8]

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

Reimplemented from MCTruthClassifier.

Definition at line 140 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() [8/8]

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

Reimplemented from MCTruthClassifier.

Definition at line 122 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
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()

void asg::AsgTool::print ( ) const
virtualinherited

◆ 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 }

◆ setProperty1()

void D3PD::D3PDMCTruthClassifier::setProperty1 ( const std::string & pname,
const std::string & value )
private

Helper to set the value of a Gaudi property.

Parameters
pnameThe name of the property. param value The new value of the property.

Definition at line 228 of file D3PDMCTruthClassifier.cxx.

230{
231 StatusCode sc = setProperty (pname, value);
232 if (sc.isFailure())
233 REPORT_ERROR (sc) << "Can't set property " << pname << "\n";
234}
void setProperty(columnar::PythonToolHandle &self, const std::string &key, nb::object value)

◆ 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 >, AthCheckedComponent<::AthAlgTool >, and DerivationFramework::CfAthAlgTool.

◆ 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.

◆ TruthLoopDetectionMethod1()

bool MCTruthClassifier::TruthLoopDetectionMethod1 ( const xAOD::TruthVertex * childOrigVtx,
const xAOD::TruthParticle * parent ) const
privateinherited

Definition at line 190 of file MCTruthClassifierGen.cxx.

191{
192 // Start of method 1 of protecting against loops
193 const int parentPDG = parent->pdgId();
194 for (const auto& aChild: childOrigVtx->particles_out()) {
195 if (!aChild) continue;
196 if (parentPDG == aChild->pdgId() && HepMC::is_same_generator_particle(aChild, parent)) {
197 // One of the children produced in the decay of parent is
198 // actually the same particle. NB In the case of multiple
199 // children this child may not necessarily be
200 // thePriPart. Does this matter?
201 return true;
202 }
203 }
204
205 // to resolve Sherpa loop
206 return TruthLoopDetectionMethod3(childOrigVtx, parent);
207 // End of method 1 of protecting against loops
208}
bool TruthLoopDetectionMethod3(const xAOD::TruthVertex *childOrigVtx, const xAOD::TruthParticle *parent) const

◆ TruthLoopDetectionMethod2()

bool MCTruthClassifier::TruthLoopDetectionMethod2 ( const xAOD::TruthParticle * child,
const xAOD::TruthParticle * parent ) const
privateinherited

Definition at line 211 of file MCTruthClassifierGen.cxx.

212{
213 // Start of method 2 of protecting against loops
214 // to prevent Sherpa loop
215 const xAOD::TruthVertex* child_prdVtx{};
216 const xAOD::TruthVertex* child_endVtx{};
217 if (child) {
218 child_prdVtx = child->hasProdVtx() ? child->prodVtx() : nullptr;
219 child_endVtx = child->decayVtx();
220 }
221 const xAOD::TruthVertex* parent_prdVtx{};
222 const xAOD::TruthVertex* parent_endVtx{};
223 if (parent) {
224 parent_prdVtx = parent->hasProdVtx() ? parent->prodVtx() : nullptr;
225 parent_endVtx = parent->decayVtx();
226 }
227 // V0->parent->V1-> ...->V2->child->V3
228 // V3 == V0 && V1 == V2
229 return (child_endVtx == parent_prdVtx && child_prdVtx == parent_endVtx);
230}

◆ TruthLoopDetectionMethod3()

bool MCTruthClassifier::TruthLoopDetectionMethod3 ( const xAOD::TruthVertex * childOrigVtx,
const xAOD::TruthParticle * parent ) const
privateinherited

Definition at line 233 of file MCTruthClassifierGen.cxx.

234{
235 // Start of method 3 of protecting against loops
236 // to resolve Sherpa loop
237 const xAOD::TruthVertex* parentOrigVtx = parent->hasProdVtx() ? parent->prodVtx() : nullptr;
238 if (parentOrigVtx && HepMC::is_same_vertex(parentOrigVtx,childOrigVtx)) {
239 // The "parent" and the "child" have the same production vertex.
240 return true;
241 }
242 return false;
243 // End of method 3 of protecting against loops
244}
bool is_same_vertex(const T1 &p1, const T2 &p2)
Method to establish if two particles in the GenEvent actually represent the same vertex.

◆ 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",""}
privateinherited

Definition at line 226 of file MCTruthClassifier.h.

226{this,"ParticleCaloExtensionTool",""};

◆ m_caloMgrKey

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

Definition at line 227 of file MCTruthClassifier.h.

227{this,"CaloDetDescrManager",""};

◆ m_deltaPhiMatchCut

float MCTruthClassifier::m_deltaPhiMatchCut
privateinherited

Definition at line 254 of file MCTruthClassifier.h.

◆ m_deltaRMatchCut

float MCTruthClassifier::m_deltaRMatchCut
privateinherited

Definition at line 253 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
privateinherited

Definition at line 232 of file MCTruthClassifier.h.

◆ m_FwdElectronTruthExtrEtaWindowCut

float MCTruthClassifier::m_FwdElectronTruthExtrEtaWindowCut
privateinherited

Definition at line 233 of file MCTruthClassifier.h.

◆ m_FwdElectronUseG4Sel

bool MCTruthClassifier::m_FwdElectronUseG4Sel
privateinherited

Definition at line 231 of file MCTruthClassifier.h.

◆ m_fwrdEledRtoTrCut

float MCTruthClassifier::m_fwrdEledRtoTrCut
privateinherited

Definition at line 240 of file MCTruthClassifier.h.

◆ m_inclG4part

bool MCTruthClassifier::m_inclG4part
privateinherited

Definition at line 245 of file MCTruthClassifier.h.

◆ m_jetPartDRMatch

float MCTruthClassifier::m_jetPartDRMatch
privateinherited

Definition at line 256 of file MCTruthClassifier.h.

◆ m_NumOfSiHitsCut

int MCTruthClassifier::m_NumOfSiHitsCut
privateinherited

Definition at line 255 of file MCTruthClassifier.h.

◆ m_partExtrConeEta

float MCTruthClassifier::m_partExtrConeEta
privateinherited

Definition at line 234 of file MCTruthClassifier.h.

◆ m_partExtrConePhi

float MCTruthClassifier::m_partExtrConePhi
privateinherited

Definition at line 235 of file MCTruthClassifier.h.

◆ m_phtClasConeEta

float MCTruthClassifier::m_phtClasConeEta
privateinherited

Definition at line 238 of file MCTruthClassifier.h.

◆ m_phtClasConePhi

float MCTruthClassifier::m_phtClasConePhi
privateinherited

Definition at line 237 of file MCTruthClassifier.h.

◆ m_phtdRtoTrCut

float MCTruthClassifier::m_phtdRtoTrCut
privateinherited

Definition at line 239 of file MCTruthClassifier.h.

◆ m_pTChargePartCut

float MCTruthClassifier::m_pTChargePartCut
privateinherited

Definition at line 243 of file MCTruthClassifier.h.

◆ m_pTNeutralPartCut

float MCTruthClassifier::m_pTNeutralPartCut
privateinherited

Definition at line 244 of file MCTruthClassifier.h.

◆ m_ROICone

bool MCTruthClassifier::m_ROICone
privateinherited

Definition at line 241 of file MCTruthClassifier.h.

◆ m_sg

ServiceHandle<StoreGateSvc> D3PD::D3PDMCTruthClassifier::m_sg
private

The StoreGate service.

Definition at line 119 of file D3PDMCTruthClassifier.h.

◆ m_truthInConeTool

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

Definition at line 229 of file MCTruthClassifier.h.

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

◆ m_truthLinkVecReadHandleKey

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

Definition at line 250 of file MCTruthClassifier.h.

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

◆ m_truthParticleContainerKey

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

Definition at line 223 of file MCTruthClassifier.h.

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

◆ m_useCaching

bool MCTruthClassifier::m_useCaching
privateinherited

Definition at line 236 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: