ATLAS Offline Software
Loading...
Searching...
No Matches
MC Namespace Reference

Namespaces

namespace  Pythia8
namespace  HepMCStr
namespace  HepMC
namespace  HepMC3

Classes

class  DecodedPID
 Implementation of classification functions according to PDG2022. More...
class  Loops

Functions

template<class VTX>
auto particles_in (const VTX *p)
template<class VTX>
auto particles_in (const std::shared_ptr< VTX > &p)
template<class T>
bool isQuark (const T &p)
 PDG rule 2: Quarks and leptons are numbered consecutively starting from 1 and 11 respectively; to do this they are first ordered by family and within families by weak isospin.
template<>
bool isQuark (const int &p)
template<>
bool isQuark (const DecodedPID &p)
template<class T>
bool isSMQuark (const T &p)
template<>
bool isSMQuark (const int &p)
template<>
bool isSMQuark (const DecodedPID &p)
template<class T>
bool isStrange (const T &p)
template<>
bool isStrange (const int &p)
template<class T>
bool isCharm (const T &p)
template<>
bool isCharm (const int &p)
template<class T>
bool isBottom (const T &p)
template<>
bool isBottom (const int &p)
template<class T>
bool isTop (const T &p)
template<>
bool isTop (const int &p)
template<class T>
bool isLepton (const T &p)
 APID: the fourth generation leptons are leptons.
template<>
bool isLepton (const int &p)
template<>
bool isLepton (const DecodedPID &p)
template<class T>
bool isSMLepton (const T &p)
 APID: the fourth generation leptons are not standard model leptons.
template<>
bool isSMLepton (const int &p)
template<>
bool isSMLepton (const DecodedPID &p)
template<class T>
bool isChLepton (const T &p)
 APID: the fourth generation leptons are leptons.
template<>
bool isChLepton (const int &p)
template<class T>
bool isElectron (const T &p)
template<>
bool isElectron (const int &p)
template<class T>
bool isMuon (const T &p)
template<>
bool isMuon (const int &p)
template<class T>
bool isTau (const T &p)
template<>
bool isTau (const int &p)
template<class T>
bool isNeutrino (const T &p)
 APID: the fourth generation neutrinos are neutrinos.
template<>
bool isNeutrino (const int &p)
template<class T>
bool isSMNeutrino (const T &p)
template<>
bool isSMNeutrino (const int &p)
template<class T>
bool isFourthGeneration (const T &p)
 Is this a 4th generation fermion?
template<>
bool isFourthGeneration (const int &p)
template<class T>
bool isDiquark (const T &p)
 PDG rule 4 Diquarks have 4-digit numbers with nq1 >= nq2 and nq3 = 0 APID: states with top quarks are diquarks APID: states with fourth generation quarks are not diquarks.
template<>
bool isDiquark (const DecodedPID &p)
template<>
bool isDiquark (const int &p)
template<class T>
bool isMeson (const T &p)
 Table 43.1 PDG rule 5a: The numbers specifying the meson’s quark content conform to the convention nq1= 0 and nq2 >= nq3.
template<>
bool isMeson (const DecodedPID &p)
template<>
bool isMeson (const int &p)
template<class T>
bool isQuarkonium (const T &p)
 Is this a heavy-flavour quarkonium meson?
template<>
bool isQuarkonium (const DecodedPID &p)
template<>
bool isQuarkonium (const int &p)
template<class T>
bool isBaryon (const T &p)
 Table 43.2 APID: states with fourth generation quarks are not baryons.
template<>
bool isBaryon (const DecodedPID &p)
template<>
bool isBaryon (const int &p)
template<class T>
bool isTetraquark (const T &p)
 PDG rule 14 The 9-digit tetra-quark codes are ±1nrnLnq1nq20nq3nq4nJ.
template<>
bool isTetraquark (const DecodedPID &p)
template<>
bool isTetraquark (const int &p)
template<class T>
bool isPentaquark (const T &p)
 PDG rule 15 The 9-digit penta-quark codes are ±1nrnLnq1nq2nq3nq4nq5nJ, sorted such that nq1≥nq2≥nq3≥nq4.
template<>
bool isPentaquark (const DecodedPID &p)
template<>
bool isPentaquark (const int &p)
template<class T>
bool isHadron (const T &p)
template<>
bool isHadron (const DecodedPID &p)
template<>
bool isHadron (const int &p)
template<class T>
bool isTrajectory (const T &p)
 PDG rule 8: The pomeron and odderon trajectories and a generic reggeon trajectory of states in QCD areassigned codes 990, 9990, and 110 respectively.
template<>
bool isTrajectory (const int &p)
template<class T>
bool isBoson (const T &p)
 PDG rule 9: Two-digit numbers in the range 21–30 are provided for the Standard Model gauge and Higgs bosons.
template<>
bool isBoson (const int &p)
template<>
bool isBoson (const DecodedPID &p)
template<class T>
bool isGluon (const T &p)
template<>
bool isGluon (const int &p)
template<class T>
bool isPhoton (const T &p)
template<>
bool isPhoton (const int &p)
template<class T>
bool isZ (const T &p)
template<>
bool isZ (const int &p)
template<class T>
bool isW (const T &p)
template<>
bool isW (const int &p)
template<class T>
bool isHeavyBoson (const T &p)
 APID: Additional "Heavy"/"prime" versions of W and Z bosons (Used in MCTruthClassifier).
template<>
bool isHeavyBoson (const int &p)
template<class T>
bool isHiggs (const T &p)
 APID: HIGGS boson is only one particle.
template<>
bool isHiggs (const int &p)
template<class T>
bool isMSSMHiggs (const T &p)
 APID: Additional Higgs bosons for MSSM (Used in MCTruthClassifier).
template<>
bool isMSSMHiggs (const int &p)
template<class T>
bool isGraviton (const T &p)
template<>
bool isGraviton (const int &p)
template<class T>
bool isResonance (const T &p)
template<class T>
bool isLeptoQuark (const T &p)
 PDG rule 11c: “One-of-a-kind” exotic particles are assigned numbers in the range 41–80.
template<>
bool isLeptoQuark (const int &p)
template<class T>
bool isPythia8Specific (const T &p)
template<>
bool isPythia8Specific (const DecodedPID &p)
template<>
bool isPythia8Specific (const int &p)
template<class T>
bool isNeutrinoRH (const T &p)
 PDG Rule 12: APID: Helper function for right-handed neutrino states These are generator defined PDG ID values for right handed neutrinos.
template<>
bool isNeutrinoRH (const int &p)
template<class T>
bool isGenSpecific (const T &p)
 Main Table for MC internal use 81–100,901–930,998-999,1901–1930,2901–2930, and 3901–3930.
template<>
bool isGenSpecific (const int &p)
template<class T>
bool isGeantino (const T &p)
template<>
bool isGeantino (const int &p)
template<class T>
bool isGlueball (const T &p)
 APID: Definition of Glueballs: SM glueballs 99X (X=1,5), 999Y (Y=3,7).
template<>
bool isGlueball (const DecodedPID &p)
template<>
bool isGlueball (const int &p)
template<class T>
bool isSquark (const T &p)
 PDG rule 11d Fundamental supersymmetric particles are identified by adding a nonzero n to the particle number.
template<>
bool isSquark (const DecodedPID &p)
template<>
bool isSquark (const int &p)
template<class T>
bool isSquarkLH (const T &p)
template<>
bool isSquarkLH (const DecodedPID &p)
template<>
bool isSquarkLH (const int &p)
template<class T>
bool isSquarkRH (const T &p)
template<>
bool isSquarkRH (const DecodedPID &p)
template<>
bool isSquarkRH (const int &p)
template<class T>
bool isSlepton (const T &p)
template<>
bool isSlepton (const DecodedPID &p)
template<>
bool isSlepton (const int &p)
template<class T>
bool isSleptonLH (const T &p)
template<>
bool isSleptonLH (const DecodedPID &p)
template<>
bool isSleptonLH (const int &p)
template<class T>
bool isSleptonRH (const T &p)
template<>
bool isSleptonRH (const DecodedPID &p)
template<>
bool isSleptonRH (const int &p)
template<class T>
bool isGaugino (const T &p)
template<>
bool isGaugino (const DecodedPID &p)
template<>
bool isGaugino (const int &p)
template<class T>
bool isSuperpartner (const T &p)
template<>
bool isSuperpartner (const DecodedPID &p)
template<>
bool isSuperpartner (const int &p)
template<class T>
bool isTechnicolor (const T &p)
 PDG rule 11e Technicolor states have n = 3, with technifermions treated like ordinary fermions.
template<>
bool isTechnicolor (const DecodedPID &p)
template<>
bool isTechnicolor (const int &p)
template<class T>
bool isExcited (const T &p)
 PDG rule 11f Excited (composite) quarks and leptons are identified by setting n= 4 and nr= 0.
template<>
bool isExcited (const DecodedPID &p)
template<>
bool isExcited (const int &p)
template<class T>
bool isRGlueball (const T &p)
 PDG rule 11g: Within several scenarios of new physics, it is possible to have colored particles sufficiently long-lived for color-singlet hadronic states to form around them.
template<>
bool isRGlueball (const DecodedPID &p)
template<>
bool isRGlueball (const int &p)
template<class T>
bool isRMeson (const T &p)
template<>
bool isRMeson (const DecodedPID &p)
template<>
bool isRMeson (const int &p)
template<class T>
bool isRBaryon (const T &p)
template<>
bool isRBaryon (const DecodedPID &p)
template<>
bool isRBaryon (const int &p)
template<class T>
bool isRHadron (const T &p)
template<>
bool isRHadron (const DecodedPID &p)
template<>
bool isRHadron (const int &p)
template<class T>
bool hasSquark (const T &p, const int &q)
template<>
bool hasSquark (const DecodedPID &p, const int &q)
template<>
bool hasSquark (const int &p, const int &q)
template<class T>
bool isSUSY (const T &p)
template<>
bool isSUSY (const DecodedPID &p)
template<>
bool isSUSY (const int &p)
template<class T>
bool isKK (const T &p)
 PDG rule 11h A black hole in models with extra dimensions has code 5000040.
template<>
bool isKK (const DecodedPID &p)
template<>
bool isKK (const int &p)
template<class T>
bool isMonopole (const T &p)
 PDG rule 11i Magnetic monopoles and dyons are assumed to have one unit of Dirac monopole charge and a variable integer number nq1nq2 nq3 units of electric charge.
template<>
bool isMonopole (const DecodedPID &p)
template<>
bool isMonopole (const int &p)
template<class T>
bool isDM (const T &p)
 PDG rule 11j: The nature of Dark Matter (DM) is not known, and therefore a definitive classificationis too early.
template<>
bool isDM (const int &p)
template<class T>
bool isHiddenValley (const T &p)
 PDG rule 11k Hidden Valley particles have n = 4 and n_r = 9, and trailing numbers in agreement with their nearest-analog standard particles, as far as possible.
template<>
bool isHiddenValley (const DecodedPID &p)
template<>
bool isHiddenValley (const int &p)
template<class T>
bool isGenericMultichargedParticle (const T &p)
 In addition, there is a need to identify ”Q-ball” and similar very exotic (multi-charged) particles which may have large, non-integer charge.
template<>
bool isGenericMultichargedParticle (const DecodedPID &p)
template<>
bool isGenericMultichargedParticle (const int &p)
template<class T>
bool isNucleus (const T &p)
 PDG rule 16 Nuclear codes are given as 10-digit numbers ±10LZZZAAAI.
template<>
bool isNucleus (const DecodedPID &p)
template<>
bool isNucleus (const int &p)
template<class T>
bool hasQuark (const T &p, const int &q)
template<>
bool hasQuark (const DecodedPID &p, const int &q)
template<>
bool hasQuark (const int &p, const int &q)
template<class T>
bool hasStrange (const T &p)
template<class T>
bool hasCharm (const T &p)
template<class T>
bool hasBottom (const T &p)
template<class T>
bool hasTop (const T &p)
template<class T>
int baryonNumber3 (const T &p)
template<>
int baryonNumber3 (const DecodedPID &p)
template<>
int baryonNumber3 (const int &p)
template<class T>
double baryonNumber (const T &p)
template<>
double baryonNumber (const DecodedPID &p)
template<>
double baryonNumber (const int &p)
template<class T>
int strangeness (const T &p)
template<>
int strangeness (const DecodedPID &p)
template<>
int strangeness (const int &p)
template<class T>
int numberOfLambdas (const T &p)
template<>
int numberOfLambdas (const DecodedPID &p)
template<>
int numberOfLambdas (const int &p)
template<class T>
int numberOfProtons (const T &p)
template<>
int numberOfProtons (const DecodedPID &p)
template<>
int numberOfProtons (const int &p)
template<class T>
bool isBSM (const T &p)
 APID: graviton and all Higgs extensions are BSM.
template<>
bool isBSM (const DecodedPID &p)
template<>
bool isBSM (const int &p)
template<class T>
bool isTransportable (const T &p)
template<>
bool isTransportable (const DecodedPID &p)
template<>
bool isTransportable (const int &p)
template<class T>
bool isValid (const T &p)
 Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
template<>
bool isValid (const DecodedPID &p)
template<>
bool isValid (const int &p)
template<class T>
int leadingQuark (const T &p)
template<>
int leadingQuark (const DecodedPID &p)
template<>
int leadingQuark (const int &p)
template<class T>
bool isLightHadron (const T &p)
template<class T>
bool isHeavyHadron (const T &p)
template<class T>
bool isStrangeHadron (const T &p)
template<class T>
bool isCharmHadron (const T &p)
template<class T>
bool isBottomHadron (const T &p)
template<class T>
bool isTopHadron (const T &p)
template<class T>
bool isLightMeson (const T &p)
template<class T>
bool isHeavyMeson (const T &p)
template<class T>
bool isStrangeMeson (const T &p)
template<class T>
bool isCharmMeson (const T &p)
template<class T>
bool isBottomMeson (const T &p)
template<class T>
bool isTopMeson (const T &p)
template<class T>
bool isCCbarMeson (const T &p)
template<>
bool isCCbarMeson (const DecodedPID &p)
template<>
bool isCCbarMeson (const int &p)
template<class T>
bool isBBbarMeson (const T &p)
template<>
bool isBBbarMeson (const DecodedPID &p)
template<>
bool isBBbarMeson (const int &p)
template<class T>
bool isLightBaryon (const T &p)
template<class T>
bool isHeavyBaryon (const T &p)
template<class T>
bool isStrangeBaryon (const T &p)
template<class T>
bool isCharmBaryon (const T &p)
template<class T>
bool isBottomBaryon (const T &p)
template<class T>
bool isTopBaryon (const T &p)
template<class T>
bool isWeaklyDecayingBHadron (const T &p)
template<>
bool isWeaklyDecayingBHadron (const int &p)
template<>
bool isWeaklyDecayingBHadron (const DecodedPID &p)
template<class T>
bool isWeaklyDecayingCHadron (const T &p)
template<>
bool isWeaklyDecayingCHadron (const int &p)
template<>
bool isWeaklyDecayingCHadron (const DecodedPID &p)
template<class T>
int charge3 (const T &p)
template<class T>
double fractionalCharge (const T &p)
template<class T>
double charge (const T &p)
template<class T>
double threeCharge (const T &p)
template<class T>
bool isCharged (const T &p)
template<>
int charge3 (const DecodedPID &p)
template<>
int charge3 (const int &p)
template<class T>
bool isNeutral (const T &p)
template<>
bool isNeutral (const DecodedPID &p)
template<>
bool isNeutral (const int &p)
template<>
double fractionalCharge (const DecodedPID &p)
template<>
double fractionalCharge (const int &p)
template<class T>
bool isEMInteracting (const T &p)
template<>
bool isEMInteracting (const int &p)
template<class T>
bool isParton (const T &p)
template<class T>
int spin2 (const T &p)
template<>
int spin2 (const DecodedPID &p)
template<>
int spin2 (const int &p)
template<class T>
double spin (const T &p)
template<>
double spin (const DecodedPID &p)
template<>
double spin (const int &p)
template<class T>
std::vector< int > containedQuarks (const T &p)
template<>
std::vector< int > containedQuarks (const int &p)
template<>
std::vector< int > containedQuarks (const DecodedPID &p)
template<class T>
bool isStrongInteracting (const T &p)
template<>
bool isStrongInteracting (const int &p)
template<class T>
bool isInteracting (const T &p)
 Identify if the particle with given PDG ID would not interact with the detector, i.e. not a neutrino or WIMP.
template<class T>
bool isChargedNonShowering (const T &p)
 Identify if the particle with given PDG ID would produce ID tracks but not shower in the detector if stable.
template<class T>
bool isBeam (const T &p)
 Identify if the particle is beam particle.
template<class T>
bool isDecayed (const T &p)
 Identify if the particle decayed.
template<class T>
bool isStable (const T &p)
 Identify if the particle is stable, i.e. has not decayed.
template<class T>
bool isFinalState (const T &p)
 Identify if the particle is final state particle.
template<class T>
bool isPhysical (const T &p)
 Identify if the particle is physical, i.e. is stable or decayed.
template<class T>
bool isGenStable (const T &p)
 Determine if the particle is stable at the generator (not det-sim) level,.
template<class T>
bool isSimStable (const T &p)
 Identify if the particle is considered stable at the post-detector-sim stage.
template<class T>
bool isSimInteracting (const T &p)
 Identify if the particle could interact with the detector during the simulation, e.g. not a neutrino or WIMP.
template<class T>
bool isStableOrSimDecayed (const T &p)
 Identify if particle is satble or decayed in simulation.
template<class T>
bool isZeroEnergyPhoton (const T &p)
 Identify a photon with zero energy. Probably a workaround for a generator bug.
template<class T>
bool isSpecialNonInteracting (const T &p)
 Identify a special non-interacting particles.
template<class T>
findMother (T thePart)
 Function to get a mother of particle. MCTruthClassifier legacy.
template<class C, class T>
findMatching (C TruthContainer, T p)
 Function to find a particle in container.
template<class T>
void findParticleAncestors (T thePart, std::set< T > &allancestors)
 Function to find all ancestors of the particle.
template<class T>
void findParticleStableDescendants (T thePart, std::set< T > &allstabledescendants)
 Function to get the particle stable MC daughters.
template<class T>
bool isHardScatteringVertex (T pVert)
 Function to classify the vertex as hard scattering vertex.
template<class T, class U>
bool isFromHadron (T p, U hadron, bool &fromTau, bool &fromBSM)
 Function to classify the particle.
template<class T>
auto findSimulatedEndVertex (T thePart) -> decltype(thePart->end_vertex())
 Function to find the end vertex of a particle.
template<class V>
auto findFinalStateParticles (V theVert) -> decltype(theVert->particles_out())
 Function to find the stable particle descendants of the given vertex..
void GeVToMeV (HepMC::GenEvent *evt)
void MeVToGeV (HepMC::GenEvent *evt)

Variables

static const int TABLESIZE = 100
static const std::array< int, TABLESIZEtriple_charge
static const std::array< int, TABLESIZEdouble_spin
static const int DQUARK = 1
static const int UQUARK = 2
static const int SQUARK = 3
static const int CQUARK = 4
static const int BQUARK = 5
static const int TQUARK = 6
static const int BPRIME = 7
static const int TPRIME = 8
static const int QUARK_LIMIT = BPRIME
static const int ELECTRON = 11
static const int POSITRON = -ELECTRON
static const int NU_E = 12
static const int MUON = 13
static const int NU_MU = 14
static const int TAU = 15
static const int NU_TAU = 16
static const int LPRIME = 17
static const int NUPRIME = 18
static const int GLUON = 21
static const int COMPOSITEGLUON = 9
static const int PHOTON = 22
static const int Z0BOSON = 23
static const int WPLUSBOSON = 24
static const int HIGGSBOSON = 25
static const int ZPRIME = 32
static const int ZDBLPRIME = 33
static const int WPLUSPRIME = 34
static const int HIGGS2 = 35
static const int HIGGS3 = 36
static const int HIGGSPLUS = 37
static const int HIGGSPLUSPLUS = 38
static const int GRAVITON = 39
static const int HIGGS4 = 40
static const int LEPTOQUARK = 42
static const int DARKPHOTON = 60000
 PDG Ids for Mavtop madgraph UFO model found under DarkX.
static const int MAVTOP = 60001
static const int PIPLUS = 211
static const int PIMINUS = -PIPLUS
static const int PI0 = 111
static const int K0L = 130
static const int K0S = 310
static const int K0 = 311
static const int KPLUS = 321
static const int DPLUS = 411
static const int DSTAR = 413
static const int D0 = 421
static const int DSPLUS = 431
static const int JPSI = 443
static const int B0 = 511
static const int BCPLUS = 541
static const int PROTON = 2212
static const int NEUTRON = 2112
static const int LAMBDA0 = 3122
static const int LAMBDACPLUS = 4122
static const int LAMBDAB0 = 5122
static const int PSI2S = 20443
static const int RH_NU_E = 9900012
 PDG Rule 12: Generator defined PDG ID values for right handed neutrinos and corresponding W+ boson from a Left-Right symmetric Standard Model extension.
static const int RH_NU_MU = 9900014
static const int RH_NU_TAU = 9900016
static const int WBOSON_LRSM = 9900024
static const int LEAD = 1000822080
static const int OXYGEN = 1000080160
static const int NEON = 1000100200
static const int HELIUM = 1000020040
static const int POMERON = 990
 PDG rule 8: The pomeron and odderon trajectories and a generic reggeon trajectory of states in QCD areassigned codes 990, 9990, and 110 respectively.
static const int ODDERON = 9990
static const int REGGEON = 110
static const int GEANTINOPLUS = 998
 PDG rule 10: Codes 81–100 are reserved for generator-specific pseudoparticles and concepts.
static const int GEANTINO0 = 999
static const std::array< int, 10 > is_strange

Function Documentation

◆ baryonNumber() [1/3]

template<>
double MC::baryonNumber ( const DecodedPID & p)
inline

Definition at line 775 of file HepMCHelpers.h.

◆ baryonNumber() [2/3]

template<>
double MC::baryonNumber ( const int & p)
inline

Definition at line 776 of file HepMCHelpers.h.

795{
796 template <class VTX>
797 auto particles_in (const VTX* p) { return p->particles_in(); }
798 template <class VTX>
799 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
800
801 namespace Pythia8
802 {
804 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
805
806 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
807
808 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
809 }
810
811#include "AtlasPID.h"
812
814 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
815
817 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
818
820 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
821
823 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
824
826 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
827
829 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
830
832 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
833
835 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
836
838 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
839
841 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
842
846 template <class T> inline bool isStableOrSimDecayed(const T& p) {
847 const auto vertex = p->end_vertex();
848 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
849 }
850
852 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
853
855 template <class T> inline bool isSpecialNonInteracting(const T& p) {
856 const int apid = std::abs(p->pdg_id());
857 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
858 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
859 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
860 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
861 return false;
862 }
863
865
866 template <class T> T findMother(T thePart) {
867 auto partOriVert = thePart->production_vertex();
868 if (!partOriVert) return nullptr;
869
870 long partPDG = thePart->pdg_id();
871 long MotherPDG(0);
872
873 auto MothOriVert = partOriVert;
874 MothOriVert = nullptr;
875 T theMoth(nullptr);
876
877 size_t itr = 0;
878 do {
879 if (itr != 0) partOriVert = MothOriVert;
880 for ( const auto& p : particles_in(partOriVert) ) {
881 theMoth = p;
882 if (!theMoth) continue;
883 MotherPDG = theMoth->pdg_id();
884 MothOriVert = theMoth->production_vertex();
885 if (MotherPDG == partPDG) break;
886 }
887 itr++;
888 if (itr > 100) {
889 break;
890 }
891 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
892 MothOriVert != partOriVert);
893 return theMoth;
894 }
895
897
898 template <class C, class T> T findMatching(C TruthContainer, T p) {
899 T ptrPart = nullptr;
900 if (!p) return ptrPart;
901 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
902 for (T truthParticle : *TruthContainer) {
903 if (HepMC::is_sim_descendant(p,truthParticle)) {
904 ptrPart = truthParticle;
905 break;
906 }
907 }
908 }
909 else {
910 for (T truthParticle : TruthContainer) {
911 if (HepMC::is_sim_descendant(p,truthParticle)) {
912 ptrPart = truthParticle;
913 break;
914 }
915 }
916 }
917 return ptrPart;
918 }
920
921 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
922 auto prodVtx = thePart->production_vertex();
923 if (!prodVtx) return;
924 for (const auto& theMother: prodVtx->particles_in()) {
925 if (!theMother) continue;
926 allancestors.insert(theMother);
927 findParticleAncestors(theMother, allancestors);
928 }
929 }
930
932
933 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
934 auto endVtx = thePart->end_vertex();
935 if (!endVtx) return;
936 for (const auto& theDaughter: endVtx->particles_out()) {
937 if (!theDaughter) continue;
938 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
939 allstabledescendants.insert(theDaughter);
940 }
941 findParticleStableDescendants(theDaughter, allstabledescendants);
942 }
943 }
944
948
949 template <class T> bool isHardScatteringVertex(T pVert) {
950 if (pVert == nullptr) return false;
951 T pV = pVert;
952 int numOfPartIn(0);
953 int pdg(0);
954
955 do {
956 pVert = pV;
957 auto incoming = pVert->particles_in();
958 numOfPartIn = incoming.size();
959 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
960 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
961
962 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
963
964 if (numOfPartIn == 2) {
965 auto incoming = pVert->particles_in();
966 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
967 }
968 return false;
969}
970
974
975 template <class T, class U>
976 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
977 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
978 auto vtx = p->production_vertex();
979 if (!vtx) return false;
980 bool fromHad = false;
981 for ( const auto& parent : particles_in(vtx) ) {
982 if (!parent) continue;
983 // should this really go into parton-level territory?
984 // probably depends where BSM particles are being decayed
985 fromBSM |= isBSM(parent);
986 if (!isPhysical(parent)) return false;
987 fromTau |= isTau(parent);
988 if (isHadron(parent)&&!isBeam(parent)) {
989 if (!hadron) hadron = parent; // assumes linear hadron parentage
990 return true;
991 }
992 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
993 }
994 return fromHad;
995 }
996
999
1000 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1001 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1002 decltype(thePart->end_vertex()) pVert(nullptr);
1003 if (EndVert != nullptr) {
1004 do {
1005 bool samePart = false;
1006 pVert = nullptr;
1007 auto outgoing = EndVert->particles_out();
1008 auto incoming = EndVert->particles_in();
1009 for (const auto& itrDaug: outgoing) {
1010 if (!itrDaug) continue;
1011 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1012 // brem on generator level for tau
1013 (outgoing.size() == 1 && incoming.size() == 1 &&
1015 itrDaug->pdg_id() == thePart->pdg_id()) {
1016 samePart = true;
1017 pVert = itrDaug->end_vertex();
1018 }
1019 }
1020 if (samePart) EndVert = pVert;
1021 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1022 }
1023 return EndVert;
1024 }
1025
1027
1028 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1029 if (!theVert) return {};
1030 decltype(theVert->particles_out()) finalStatePart;
1031 auto outgoing = theVert->particles_out();
1032 for (const auto& thePart: outgoing) {
1033 if (!thePart) continue;
1034 finalStatePart.push_back(thePart);
1035 if (isStable(thePart)) continue;
1036 V pVert = findSimulatedEndVertex(thePart);
1037 if (pVert == theVert) break; // to prevent Sherpa loop
1038 if (pVert != nullptr) {
1039 auto vecPart = findFinalStateParticles<V>(pVert);
1040 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1041 }
1042 }
1043 return finalStatePart;
1044 }
1045#if !defined(XAOD_ANALYSIS)
1046#include "AtlasHepMC/GenEvent.h"
1047inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1048inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1049
1050#endif
1051}
1052#endif
struct color C
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_simulation_vertex(const T &v)
Method to establish if the vertex was created during simulation (TODO migrate to be based on status).
constexpr int SIM_STATUS_THRESHOLD
Constant definiting the status threshold for simulated particles, eg. can be used to separate generat...
int status(const T &p)
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...
constexpr bool is_smart_ptr_v
bool is_sim_descendant(const T1 &p1, const T2 &p2)
Method to check if the first particle is a descendant of the second in the simulation,...
HepMC3::GenEvent GenEvent
bool isConditionB(const T &p)
bool isConditionA(const T &p)
To be understood.
bool isConditionC(const T &p)
T findMatching(C TruthContainer, T p)
Function to find a particle in container.
static const int GRAVITON
auto particles_in(const VTX *p)
bool isZeroEnergyPhoton(const T &p)
Identify a photon with zero energy. Probably a workaround for a generator bug.
bool isHardScatteringVertex(T pVert)
Function to classify the vertex as hard scattering vertex.
void MeVToGeV(HepMC::GenEvent *evt)
bool isStableOrSimDecayed(const T &p)
Identify if particle is satble or decayed in simulation.
bool isPhoton(const T &p)
bool isSpecialNonInteracting(const T &p)
Identify a special non-interacting particles.
bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM)
Function to classify the particle.
bool isStable(const T &p)
Identify if the particle is stable, i.e. has not decayed.
bool isGeantino(const T &p)
bool isSimInteracting(const T &p)
Identify if the particle could interact with the detector during the simulation, e....
void GeVToMeV(HepMC::GenEvent *evt)
bool isEMInteracting(const T &p)
void findParticleAncestors(T thePart, std::set< T > &allancestors)
Function to find all ancestors of the particle.
bool isStrongInteracting(const T &p)
bool isInteracting(const T &p)
Identify if the particle with given PDG ID would not interact with the detector, i....
bool isMuon(const T &p)
bool isSUSY(const T &p)
auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out())
Function to find the stable particle descendants of the given vertex..
static const int NU_MU
bool isChargedNonShowering(const T &p)
Identify if the particle with given PDG ID would produce ID tracks but not shower in the detector if ...
bool isDecayed(const T &p)
Identify if the particle decayed.
T findMother(T thePart)
Function to get a mother of particle. MCTruthClassifier legacy.
void findParticleStableDescendants(T thePart, std::set< T > &allstabledescendants)
Function to get the particle stable MC daughters.
static const int NU_E
bool isBeam(const T &p)
Identify if the particle is beam particle.
static const int NU_TAU
bool isFinalState(const T &p)
Identify if the particle is final state particle.
bool isGenStable(const T &p)
Determine if the particle is stable at the generator (not det-sim) level,.
bool isHadron(const T &p)
bool isSimStable(const T &p)
Identify if the particle is considered stable at the post-detector-sim stage.
auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex())
Function to find the end vertex of a particle.
bool isTau(const T &p)
bool isPhysical(const T &p)
Identify if the particle is physical, i.e. is stable or decayed.
bool isBSM(const T &p)
APID: graviton and all Higgs extensions are BSM.
unsigned long long T

◆ baryonNumber() [3/3]

template<class T>
double MC::baryonNumber ( const T & p)
inline

Definition at line 774 of file HepMCHelpers.h.

793{
794 template <class VTX>
795 auto particles_in (const VTX* p) { return p->particles_in(); }
796 template <class VTX>
797 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
798
799 namespace Pythia8
800 {
802 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
803
804 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
805
806 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
807 }
808
809#include "AtlasPID.h"
810
812 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
813
815 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
816
818 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
819
821 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
822
824 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
825
827 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
828
830 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
831
833 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
834
836 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
837
839 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
840
844 template <class T> inline bool isStableOrSimDecayed(const T& p) {
845 const auto vertex = p->end_vertex();
846 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
847 }
848
850 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
851
853 template <class T> inline bool isSpecialNonInteracting(const T& p) {
854 const int apid = std::abs(p->pdg_id());
855 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
856 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
857 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
858 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
859 return false;
860 }
861
863
864 template <class T> T findMother(T thePart) {
865 auto partOriVert = thePart->production_vertex();
866 if (!partOriVert) return nullptr;
867
868 long partPDG = thePart->pdg_id();
869 long MotherPDG(0);
870
871 auto MothOriVert = partOriVert;
872 MothOriVert = nullptr;
873 T theMoth(nullptr);
874
875 size_t itr = 0;
876 do {
877 if (itr != 0) partOriVert = MothOriVert;
878 for ( const auto& p : particles_in(partOriVert) ) {
879 theMoth = p;
880 if (!theMoth) continue;
881 MotherPDG = theMoth->pdg_id();
882 MothOriVert = theMoth->production_vertex();
883 if (MotherPDG == partPDG) break;
884 }
885 itr++;
886 if (itr > 100) {
887 break;
888 }
889 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
890 MothOriVert != partOriVert);
891 return theMoth;
892 }
893
895
896 template <class C, class T> T findMatching(C TruthContainer, T p) {
897 T ptrPart = nullptr;
898 if (!p) return ptrPart;
899 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
900 for (T truthParticle : *TruthContainer) {
901 if (HepMC::is_sim_descendant(p,truthParticle)) {
902 ptrPart = truthParticle;
903 break;
904 }
905 }
906 }
907 else {
908 for (T truthParticle : TruthContainer) {
909 if (HepMC::is_sim_descendant(p,truthParticle)) {
910 ptrPart = truthParticle;
911 break;
912 }
913 }
914 }
915 return ptrPart;
916 }
918
919 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
920 auto prodVtx = thePart->production_vertex();
921 if (!prodVtx) return;
922 for (const auto& theMother: prodVtx->particles_in()) {
923 if (!theMother) continue;
924 allancestors.insert(theMother);
925 findParticleAncestors(theMother, allancestors);
926 }
927 }
928
930
931 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
932 auto endVtx = thePart->end_vertex();
933 if (!endVtx) return;
934 for (const auto& theDaughter: endVtx->particles_out()) {
935 if (!theDaughter) continue;
936 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
937 allstabledescendants.insert(theDaughter);
938 }
939 findParticleStableDescendants(theDaughter, allstabledescendants);
940 }
941 }
942
946
947 template <class T> bool isHardScatteringVertex(T pVert) {
948 if (pVert == nullptr) return false;
949 T pV = pVert;
950 int numOfPartIn(0);
951 int pdg(0);
952
953 do {
954 pVert = pV;
955 auto incoming = pVert->particles_in();
956 numOfPartIn = incoming.size();
957 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
958 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
959
960 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
961
962 if (numOfPartIn == 2) {
963 auto incoming = pVert->particles_in();
964 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
965 }
966 return false;
967}
968
972
973 template <class T, class U>
974 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
975 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
976 auto vtx = p->production_vertex();
977 if (!vtx) return false;
978 bool fromHad = false;
979 for ( const auto& parent : particles_in(vtx) ) {
980 if (!parent) continue;
981 // should this really go into parton-level territory?
982 // probably depends where BSM particles are being decayed
983 fromBSM |= isBSM(parent);
984 if (!isPhysical(parent)) return false;
985 fromTau |= isTau(parent);
986 if (isHadron(parent)&&!isBeam(parent)) {
987 if (!hadron) hadron = parent; // assumes linear hadron parentage
988 return true;
989 }
990 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
991 }
992 return fromHad;
993 }
994
997
998 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
999 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1000 decltype(thePart->end_vertex()) pVert(nullptr);
1001 if (EndVert != nullptr) {
1002 do {
1003 bool samePart = false;
1004 pVert = nullptr;
1005 auto outgoing = EndVert->particles_out();
1006 auto incoming = EndVert->particles_in();
1007 for (const auto& itrDaug: outgoing) {
1008 if (!itrDaug) continue;
1009 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1010 // brem on generator level for tau
1011 (outgoing.size() == 1 && incoming.size() == 1 &&
1013 itrDaug->pdg_id() == thePart->pdg_id()) {
1014 samePart = true;
1015 pVert = itrDaug->end_vertex();
1016 }
1017 }
1018 if (samePart) EndVert = pVert;
1019 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1020 }
1021 return EndVert;
1022 }
1023
1025
1026 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1027 if (!theVert) return {};
1028 decltype(theVert->particles_out()) finalStatePart;
1029 auto outgoing = theVert->particles_out();
1030 for (const auto& thePart: outgoing) {
1031 if (!thePart) continue;
1032 finalStatePart.push_back(thePart);
1033 if (isStable(thePart)) continue;
1034 V pVert = findSimulatedEndVertex(thePart);
1035 if (pVert == theVert) break; // to prevent Sherpa loop
1036 if (pVert != nullptr) {
1037 auto vecPart = findFinalStateParticles<V>(pVert);
1038 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1039 }
1040 }
1041 return finalStatePart;
1042 }
1043#if !defined(XAOD_ANALYSIS)
1044#include "AtlasHepMC/GenEvent.h"
1045inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1046inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1047
1048#endif
1049}
1050#endif

◆ baryonNumber3() [1/3]

template<>
int MC::baryonNumber3 ( const DecodedPID & p)
inline

Definition at line 750 of file HepMCHelpers.h.

769{
770 template <class VTX>
771 auto particles_in (const VTX* p) { return p->particles_in(); }
772 template <class VTX>
773 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
774
775 namespace Pythia8
776 {
778 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
779
780 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
781
782 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
783 }
784
785#include "AtlasPID.h"
786
788 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
789
791 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
792
794 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
795
797 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
798
800 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
801
803 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
804
806 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
807
809 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
810
812 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
813
815 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
816
820 template <class T> inline bool isStableOrSimDecayed(const T& p) {
821 const auto vertex = p->end_vertex();
822 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
823 }
824
826 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
827
829 template <class T> inline bool isSpecialNonInteracting(const T& p) {
830 const int apid = std::abs(p->pdg_id());
831 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
832 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
833 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
834 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
835 return false;
836 }
837
839
840 template <class T> T findMother(T thePart) {
841 auto partOriVert = thePart->production_vertex();
842 if (!partOriVert) return nullptr;
843
844 long partPDG = thePart->pdg_id();
845 long MotherPDG(0);
846
847 auto MothOriVert = partOriVert;
848 MothOriVert = nullptr;
849 T theMoth(nullptr);
850
851 size_t itr = 0;
852 do {
853 if (itr != 0) partOriVert = MothOriVert;
854 for ( const auto& p : particles_in(partOriVert) ) {
855 theMoth = p;
856 if (!theMoth) continue;
857 MotherPDG = theMoth->pdg_id();
858 MothOriVert = theMoth->production_vertex();
859 if (MotherPDG == partPDG) break;
860 }
861 itr++;
862 if (itr > 100) {
863 break;
864 }
865 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
866 MothOriVert != partOriVert);
867 return theMoth;
868 }
869
871
872 template <class C, class T> T findMatching(C TruthContainer, T p) {
873 T ptrPart = nullptr;
874 if (!p) return ptrPart;
875 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
876 for (T truthParticle : *TruthContainer) {
877 if (HepMC::is_sim_descendant(p,truthParticle)) {
878 ptrPart = truthParticle;
879 break;
880 }
881 }
882 }
883 else {
884 for (T truthParticle : TruthContainer) {
885 if (HepMC::is_sim_descendant(p,truthParticle)) {
886 ptrPart = truthParticle;
887 break;
888 }
889 }
890 }
891 return ptrPart;
892 }
894
895 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
896 auto prodVtx = thePart->production_vertex();
897 if (!prodVtx) return;
898 for (const auto& theMother: prodVtx->particles_in()) {
899 if (!theMother) continue;
900 allancestors.insert(theMother);
901 findParticleAncestors(theMother, allancestors);
902 }
903 }
904
906
907 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
908 auto endVtx = thePart->end_vertex();
909 if (!endVtx) return;
910 for (const auto& theDaughter: endVtx->particles_out()) {
911 if (!theDaughter) continue;
912 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
913 allstabledescendants.insert(theDaughter);
914 }
915 findParticleStableDescendants(theDaughter, allstabledescendants);
916 }
917 }
918
922
923 template <class T> bool isHardScatteringVertex(T pVert) {
924 if (pVert == nullptr) return false;
925 T pV = pVert;
926 int numOfPartIn(0);
927 int pdg(0);
928
929 do {
930 pVert = pV;
931 auto incoming = pVert->particles_in();
932 numOfPartIn = incoming.size();
933 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
934 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
935
936 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
937
938 if (numOfPartIn == 2) {
939 auto incoming = pVert->particles_in();
940 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
941 }
942 return false;
943}
944
948
949 template <class T, class U>
950 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
951 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
952 auto vtx = p->production_vertex();
953 if (!vtx) return false;
954 bool fromHad = false;
955 for ( const auto& parent : particles_in(vtx) ) {
956 if (!parent) continue;
957 // should this really go into parton-level territory?
958 // probably depends where BSM particles are being decayed
959 fromBSM |= isBSM(parent);
960 if (!isPhysical(parent)) return false;
961 fromTau |= isTau(parent);
962 if (isHadron(parent)&&!isBeam(parent)) {
963 if (!hadron) hadron = parent; // assumes linear hadron parentage
964 return true;
965 }
966 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
967 }
968 return fromHad;
969 }
970
973
974 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
975 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
976 decltype(thePart->end_vertex()) pVert(nullptr);
977 if (EndVert != nullptr) {
978 do {
979 bool samePart = false;
980 pVert = nullptr;
981 auto outgoing = EndVert->particles_out();
982 auto incoming = EndVert->particles_in();
983 for (const auto& itrDaug: outgoing) {
984 if (!itrDaug) continue;
985 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
986 // brem on generator level for tau
987 (outgoing.size() == 1 && incoming.size() == 1 &&
989 itrDaug->pdg_id() == thePart->pdg_id()) {
990 samePart = true;
991 pVert = itrDaug->end_vertex();
992 }
993 }
994 if (samePart) EndVert = pVert;
995 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
996 }
997 return EndVert;
998 }
999
1001
1002 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1003 if (!theVert) return {};
1004 decltype(theVert->particles_out()) finalStatePart;
1005 auto outgoing = theVert->particles_out();
1006 for (const auto& thePart: outgoing) {
1007 if (!thePart) continue;
1008 finalStatePart.push_back(thePart);
1009 if (isStable(thePart)) continue;
1010 V pVert = findSimulatedEndVertex(thePart);
1011 if (pVert == theVert) break; // to prevent Sherpa loop
1012 if (pVert != nullptr) {
1013 auto vecPart = findFinalStateParticles<V>(pVert);
1014 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1015 }
1016 }
1017 return finalStatePart;
1018 }
1019#if !defined(XAOD_ANALYSIS)
1020#include "AtlasHepMC/GenEvent.h"
1021inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1022inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1023
1024#endif
1025}
1026#endif

◆ baryonNumber3() [2/3]

template<>
int MC::baryonNumber3 ( const int & p)
inline

Definition at line 772 of file HepMCHelpers.h.

791{
792 template <class VTX>
793 auto particles_in (const VTX* p) { return p->particles_in(); }
794 template <class VTX>
795 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
796
797 namespace Pythia8
798 {
800 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
801
802 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
803
804 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
805 }
806
807#include "AtlasPID.h"
808
810 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
811
813 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
814
816 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
817
819 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
820
822 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
823
825 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
826
828 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
829
831 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
832
834 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
835
837 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
838
842 template <class T> inline bool isStableOrSimDecayed(const T& p) {
843 const auto vertex = p->end_vertex();
844 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
845 }
846
848 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
849
851 template <class T> inline bool isSpecialNonInteracting(const T& p) {
852 const int apid = std::abs(p->pdg_id());
853 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
854 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
855 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
856 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
857 return false;
858 }
859
861
862 template <class T> T findMother(T thePart) {
863 auto partOriVert = thePart->production_vertex();
864 if (!partOriVert) return nullptr;
865
866 long partPDG = thePart->pdg_id();
867 long MotherPDG(0);
868
869 auto MothOriVert = partOriVert;
870 MothOriVert = nullptr;
871 T theMoth(nullptr);
872
873 size_t itr = 0;
874 do {
875 if (itr != 0) partOriVert = MothOriVert;
876 for ( const auto& p : particles_in(partOriVert) ) {
877 theMoth = p;
878 if (!theMoth) continue;
879 MotherPDG = theMoth->pdg_id();
880 MothOriVert = theMoth->production_vertex();
881 if (MotherPDG == partPDG) break;
882 }
883 itr++;
884 if (itr > 100) {
885 break;
886 }
887 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
888 MothOriVert != partOriVert);
889 return theMoth;
890 }
891
893
894 template <class C, class T> T findMatching(C TruthContainer, T p) {
895 T ptrPart = nullptr;
896 if (!p) return ptrPart;
897 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
898 for (T truthParticle : *TruthContainer) {
899 if (HepMC::is_sim_descendant(p,truthParticle)) {
900 ptrPart = truthParticle;
901 break;
902 }
903 }
904 }
905 else {
906 for (T truthParticle : TruthContainer) {
907 if (HepMC::is_sim_descendant(p,truthParticle)) {
908 ptrPart = truthParticle;
909 break;
910 }
911 }
912 }
913 return ptrPart;
914 }
916
917 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
918 auto prodVtx = thePart->production_vertex();
919 if (!prodVtx) return;
920 for (const auto& theMother: prodVtx->particles_in()) {
921 if (!theMother) continue;
922 allancestors.insert(theMother);
923 findParticleAncestors(theMother, allancestors);
924 }
925 }
926
928
929 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
930 auto endVtx = thePart->end_vertex();
931 if (!endVtx) return;
932 for (const auto& theDaughter: endVtx->particles_out()) {
933 if (!theDaughter) continue;
934 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
935 allstabledescendants.insert(theDaughter);
936 }
937 findParticleStableDescendants(theDaughter, allstabledescendants);
938 }
939 }
940
944
945 template <class T> bool isHardScatteringVertex(T pVert) {
946 if (pVert == nullptr) return false;
947 T pV = pVert;
948 int numOfPartIn(0);
949 int pdg(0);
950
951 do {
952 pVert = pV;
953 auto incoming = pVert->particles_in();
954 numOfPartIn = incoming.size();
955 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
956 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
957
958 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
959
960 if (numOfPartIn == 2) {
961 auto incoming = pVert->particles_in();
962 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
963 }
964 return false;
965}
966
970
971 template <class T, class U>
972 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
973 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
974 auto vtx = p->production_vertex();
975 if (!vtx) return false;
976 bool fromHad = false;
977 for ( const auto& parent : particles_in(vtx) ) {
978 if (!parent) continue;
979 // should this really go into parton-level territory?
980 // probably depends where BSM particles are being decayed
981 fromBSM |= isBSM(parent);
982 if (!isPhysical(parent)) return false;
983 fromTau |= isTau(parent);
984 if (isHadron(parent)&&!isBeam(parent)) {
985 if (!hadron) hadron = parent; // assumes linear hadron parentage
986 return true;
987 }
988 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
989 }
990 return fromHad;
991 }
992
995
996 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
997 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
998 decltype(thePart->end_vertex()) pVert(nullptr);
999 if (EndVert != nullptr) {
1000 do {
1001 bool samePart = false;
1002 pVert = nullptr;
1003 auto outgoing = EndVert->particles_out();
1004 auto incoming = EndVert->particles_in();
1005 for (const auto& itrDaug: outgoing) {
1006 if (!itrDaug) continue;
1007 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1008 // brem on generator level for tau
1009 (outgoing.size() == 1 && incoming.size() == 1 &&
1011 itrDaug->pdg_id() == thePart->pdg_id()) {
1012 samePart = true;
1013 pVert = itrDaug->end_vertex();
1014 }
1015 }
1016 if (samePart) EndVert = pVert;
1017 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1018 }
1019 return EndVert;
1020 }
1021
1023
1024 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1025 if (!theVert) return {};
1026 decltype(theVert->particles_out()) finalStatePart;
1027 auto outgoing = theVert->particles_out();
1028 for (const auto& thePart: outgoing) {
1029 if (!thePart) continue;
1030 finalStatePart.push_back(thePart);
1031 if (isStable(thePart)) continue;
1032 V pVert = findSimulatedEndVertex(thePart);
1033 if (pVert == theVert) break; // to prevent Sherpa loop
1034 if (pVert != nullptr) {
1035 auto vecPart = findFinalStateParticles<V>(pVert);
1036 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1037 }
1038 }
1039 return finalStatePart;
1040 }
1041#if !defined(XAOD_ANALYSIS)
1042#include "AtlasHepMC/GenEvent.h"
1043inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1044inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1045
1046#endif
1047}
1048#endif

◆ baryonNumber3() [3/3]

template<class T>
int MC::baryonNumber3 ( const T & p)
inline

Definition at line 749 of file HepMCHelpers.h.

768{
769 template <class VTX>
770 auto particles_in (const VTX* p) { return p->particles_in(); }
771 template <class VTX>
772 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
773
774 namespace Pythia8
775 {
777 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
778
779 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
780
781 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
782 }
783
784#include "AtlasPID.h"
785
787 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
788
790 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
791
793 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
794
796 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
797
799 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
800
802 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
803
805 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
806
808 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
809
811 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
812
814 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
815
819 template <class T> inline bool isStableOrSimDecayed(const T& p) {
820 const auto vertex = p->end_vertex();
821 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
822 }
823
825 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
826
828 template <class T> inline bool isSpecialNonInteracting(const T& p) {
829 const int apid = std::abs(p->pdg_id());
830 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
831 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
832 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
833 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
834 return false;
835 }
836
838
839 template <class T> T findMother(T thePart) {
840 auto partOriVert = thePart->production_vertex();
841 if (!partOriVert) return nullptr;
842
843 long partPDG = thePart->pdg_id();
844 long MotherPDG(0);
845
846 auto MothOriVert = partOriVert;
847 MothOriVert = nullptr;
848 T theMoth(nullptr);
849
850 size_t itr = 0;
851 do {
852 if (itr != 0) partOriVert = MothOriVert;
853 for ( const auto& p : particles_in(partOriVert) ) {
854 theMoth = p;
855 if (!theMoth) continue;
856 MotherPDG = theMoth->pdg_id();
857 MothOriVert = theMoth->production_vertex();
858 if (MotherPDG == partPDG) break;
859 }
860 itr++;
861 if (itr > 100) {
862 break;
863 }
864 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
865 MothOriVert != partOriVert);
866 return theMoth;
867 }
868
870
871 template <class C, class T> T findMatching(C TruthContainer, T p) {
872 T ptrPart = nullptr;
873 if (!p) return ptrPart;
874 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
875 for (T truthParticle : *TruthContainer) {
876 if (HepMC::is_sim_descendant(p,truthParticle)) {
877 ptrPart = truthParticle;
878 break;
879 }
880 }
881 }
882 else {
883 for (T truthParticle : TruthContainer) {
884 if (HepMC::is_sim_descendant(p,truthParticle)) {
885 ptrPart = truthParticle;
886 break;
887 }
888 }
889 }
890 return ptrPart;
891 }
893
894 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
895 auto prodVtx = thePart->production_vertex();
896 if (!prodVtx) return;
897 for (const auto& theMother: prodVtx->particles_in()) {
898 if (!theMother) continue;
899 allancestors.insert(theMother);
900 findParticleAncestors(theMother, allancestors);
901 }
902 }
903
905
906 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
907 auto endVtx = thePart->end_vertex();
908 if (!endVtx) return;
909 for (const auto& theDaughter: endVtx->particles_out()) {
910 if (!theDaughter) continue;
911 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
912 allstabledescendants.insert(theDaughter);
913 }
914 findParticleStableDescendants(theDaughter, allstabledescendants);
915 }
916 }
917
921
922 template <class T> bool isHardScatteringVertex(T pVert) {
923 if (pVert == nullptr) return false;
924 T pV = pVert;
925 int numOfPartIn(0);
926 int pdg(0);
927
928 do {
929 pVert = pV;
930 auto incoming = pVert->particles_in();
931 numOfPartIn = incoming.size();
932 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
933 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
934
935 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
936
937 if (numOfPartIn == 2) {
938 auto incoming = pVert->particles_in();
939 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
940 }
941 return false;
942}
943
947
948 template <class T, class U>
949 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
950 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
951 auto vtx = p->production_vertex();
952 if (!vtx) return false;
953 bool fromHad = false;
954 for ( const auto& parent : particles_in(vtx) ) {
955 if (!parent) continue;
956 // should this really go into parton-level territory?
957 // probably depends where BSM particles are being decayed
958 fromBSM |= isBSM(parent);
959 if (!isPhysical(parent)) return false;
960 fromTau |= isTau(parent);
961 if (isHadron(parent)&&!isBeam(parent)) {
962 if (!hadron) hadron = parent; // assumes linear hadron parentage
963 return true;
964 }
965 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
966 }
967 return fromHad;
968 }
969
972
973 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
974 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
975 decltype(thePart->end_vertex()) pVert(nullptr);
976 if (EndVert != nullptr) {
977 do {
978 bool samePart = false;
979 pVert = nullptr;
980 auto outgoing = EndVert->particles_out();
981 auto incoming = EndVert->particles_in();
982 for (const auto& itrDaug: outgoing) {
983 if (!itrDaug) continue;
984 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
985 // brem on generator level for tau
986 (outgoing.size() == 1 && incoming.size() == 1 &&
988 itrDaug->pdg_id() == thePart->pdg_id()) {
989 samePart = true;
990 pVert = itrDaug->end_vertex();
991 }
992 }
993 if (samePart) EndVert = pVert;
994 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
995 }
996 return EndVert;
997 }
998
1000
1001 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1002 if (!theVert) return {};
1003 decltype(theVert->particles_out()) finalStatePart;
1004 auto outgoing = theVert->particles_out();
1005 for (const auto& thePart: outgoing) {
1006 if (!thePart) continue;
1007 finalStatePart.push_back(thePart);
1008 if (isStable(thePart)) continue;
1009 V pVert = findSimulatedEndVertex(thePart);
1010 if (pVert == theVert) break; // to prevent Sherpa loop
1011 if (pVert != nullptr) {
1012 auto vecPart = findFinalStateParticles<V>(pVert);
1013 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1014 }
1015 }
1016 return finalStatePart;
1017 }
1018#if !defined(XAOD_ANALYSIS)
1019#include "AtlasHepMC/GenEvent.h"
1020inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1021inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1022
1023#endif
1024}
1025#endif

◆ charge()

template<class T>
double MC::charge ( const T & p)
inline

Definition at line 998 of file HepMCHelpers.h.

1017{
1018 template <class VTX>
1019 auto particles_in (const VTX* p) { return p->particles_in(); }
1020 template <class VTX>
1021 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1022
1023 namespace Pythia8
1024 {
1026 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1027
1028 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1029
1030 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1031 }
1032
1033#include "AtlasPID.h"
1034
1036 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1037
1039 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1040
1042 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1043
1045 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1046
1048 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1049
1051 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1052
1054 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1055
1057 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1058
1060 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1061
1063 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1064
1068 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1069 const auto vertex = p->end_vertex();
1070 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1071 }
1072
1074 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1075
1077 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1078 const int apid = std::abs(p->pdg_id());
1079 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1080 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1081 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1082 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1083 return false;
1084 }
1085
1087
1088 template <class T> T findMother(T thePart) {
1089 auto partOriVert = thePart->production_vertex();
1090 if (!partOriVert) return nullptr;
1091
1092 long partPDG = thePart->pdg_id();
1093 long MotherPDG(0);
1094
1095 auto MothOriVert = partOriVert;
1096 MothOriVert = nullptr;
1097 T theMoth(nullptr);
1098
1099 size_t itr = 0;
1100 do {
1101 if (itr != 0) partOriVert = MothOriVert;
1102 for ( const auto& p : particles_in(partOriVert) ) {
1103 theMoth = p;
1104 if (!theMoth) continue;
1105 MotherPDG = theMoth->pdg_id();
1106 MothOriVert = theMoth->production_vertex();
1107 if (MotherPDG == partPDG) break;
1108 }
1109 itr++;
1110 if (itr > 100) {
1111 break;
1112 }
1113 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1114 MothOriVert != partOriVert);
1115 return theMoth;
1116 }
1117
1119
1120 template <class C, class T> T findMatching(C TruthContainer, T p) {
1121 T ptrPart = nullptr;
1122 if (!p) return ptrPart;
1123 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1124 for (T truthParticle : *TruthContainer) {
1125 if (HepMC::is_sim_descendant(p,truthParticle)) {
1126 ptrPart = truthParticle;
1127 break;
1128 }
1129 }
1130 }
1131 else {
1132 for (T truthParticle : TruthContainer) {
1133 if (HepMC::is_sim_descendant(p,truthParticle)) {
1134 ptrPart = truthParticle;
1135 break;
1136 }
1137 }
1138 }
1139 return ptrPart;
1140 }
1142
1143 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1144 auto prodVtx = thePart->production_vertex();
1145 if (!prodVtx) return;
1146 for (const auto& theMother: prodVtx->particles_in()) {
1147 if (!theMother) continue;
1148 allancestors.insert(theMother);
1149 findParticleAncestors(theMother, allancestors);
1150 }
1151 }
1152
1154
1155 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1156 auto endVtx = thePart->end_vertex();
1157 if (!endVtx) return;
1158 for (const auto& theDaughter: endVtx->particles_out()) {
1159 if (!theDaughter) continue;
1160 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1161 allstabledescendants.insert(theDaughter);
1162 }
1163 findParticleStableDescendants(theDaughter, allstabledescendants);
1164 }
1165 }
1166
1170
1171 template <class T> bool isHardScatteringVertex(T pVert) {
1172 if (pVert == nullptr) return false;
1173 T pV = pVert;
1174 int numOfPartIn(0);
1175 int pdg(0);
1176
1177 do {
1178 pVert = pV;
1179 auto incoming = pVert->particles_in();
1180 numOfPartIn = incoming.size();
1181 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1182 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1183
1184 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1185
1186 if (numOfPartIn == 2) {
1187 auto incoming = pVert->particles_in();
1188 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1189 }
1190 return false;
1191}
1192
1196
1197 template <class T, class U>
1198 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1199 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1200 auto vtx = p->production_vertex();
1201 if (!vtx) return false;
1202 bool fromHad = false;
1203 for ( const auto& parent : particles_in(vtx) ) {
1204 if (!parent) continue;
1205 // should this really go into parton-level territory?
1206 // probably depends where BSM particles are being decayed
1207 fromBSM |= isBSM(parent);
1208 if (!isPhysical(parent)) return false;
1209 fromTau |= isTau(parent);
1210 if (isHadron(parent)&&!isBeam(parent)) {
1211 if (!hadron) hadron = parent; // assumes linear hadron parentage
1212 return true;
1213 }
1214 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1215 }
1216 return fromHad;
1217 }
1218
1221
1222 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1223 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1224 decltype(thePart->end_vertex()) pVert(nullptr);
1225 if (EndVert != nullptr) {
1226 do {
1227 bool samePart = false;
1228 pVert = nullptr;
1229 auto outgoing = EndVert->particles_out();
1230 auto incoming = EndVert->particles_in();
1231 for (const auto& itrDaug: outgoing) {
1232 if (!itrDaug) continue;
1233 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1234 // brem on generator level for tau
1235 (outgoing.size() == 1 && incoming.size() == 1 &&
1237 itrDaug->pdg_id() == thePart->pdg_id()) {
1238 samePart = true;
1239 pVert = itrDaug->end_vertex();
1240 }
1241 }
1242 if (samePart) EndVert = pVert;
1243 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1244 }
1245 return EndVert;
1246 }
1247
1249
1250 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1251 if (!theVert) return {};
1252 decltype(theVert->particles_out()) finalStatePart;
1253 auto outgoing = theVert->particles_out();
1254 for (const auto& thePart: outgoing) {
1255 if (!thePart) continue;
1256 finalStatePart.push_back(thePart);
1257 if (isStable(thePart)) continue;
1258 V pVert = findSimulatedEndVertex(thePart);
1259 if (pVert == theVert) break; // to prevent Sherpa loop
1260 if (pVert != nullptr) {
1261 auto vecPart = findFinalStateParticles<V>(pVert);
1262 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1263 }
1264 }
1265 return finalStatePart;
1266 }
1267#if !defined(XAOD_ANALYSIS)
1268#include "AtlasHepMC/GenEvent.h"
1269inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1270inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1271
1272#endif
1273}
1274#endif

◆ charge3() [1/3]

template<>
int MC::charge3 ( const DecodedPID & p)
inline

Codes 411nq1nq2 nq3 0 are then used when the magnetic and electrical charge sign agree and 412nq1nq2 nq3 0 when they disagree, with the overall sign of the particle set by the magnetic charge.

Definition at line 1008 of file HepMCHelpers.h.

1027{
1028 template <class VTX>
1029 auto particles_in (const VTX* p) { return p->particles_in(); }
1030 template <class VTX>
1031 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1032
1033 namespace Pythia8
1034 {
1036 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1037
1038 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1039
1040 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1041 }
1042
1043#include "AtlasPID.h"
1044
1046 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1047
1049 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1050
1052 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1053
1055 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1056
1058 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1059
1061 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1062
1064 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1065
1067 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1068
1070 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1071
1073 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1074
1078 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1079 const auto vertex = p->end_vertex();
1080 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1081 }
1082
1084 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1085
1087 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1088 const int apid = std::abs(p->pdg_id());
1089 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1090 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1091 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1092 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1093 return false;
1094 }
1095
1097
1098 template <class T> T findMother(T thePart) {
1099 auto partOriVert = thePart->production_vertex();
1100 if (!partOriVert) return nullptr;
1101
1102 long partPDG = thePart->pdg_id();
1103 long MotherPDG(0);
1104
1105 auto MothOriVert = partOriVert;
1106 MothOriVert = nullptr;
1107 T theMoth(nullptr);
1108
1109 size_t itr = 0;
1110 do {
1111 if (itr != 0) partOriVert = MothOriVert;
1112 for ( const auto& p : particles_in(partOriVert) ) {
1113 theMoth = p;
1114 if (!theMoth) continue;
1115 MotherPDG = theMoth->pdg_id();
1116 MothOriVert = theMoth->production_vertex();
1117 if (MotherPDG == partPDG) break;
1118 }
1119 itr++;
1120 if (itr > 100) {
1121 break;
1122 }
1123 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1124 MothOriVert != partOriVert);
1125 return theMoth;
1126 }
1127
1129
1130 template <class C, class T> T findMatching(C TruthContainer, T p) {
1131 T ptrPart = nullptr;
1132 if (!p) return ptrPart;
1133 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1134 for (T truthParticle : *TruthContainer) {
1135 if (HepMC::is_sim_descendant(p,truthParticle)) {
1136 ptrPart = truthParticle;
1137 break;
1138 }
1139 }
1140 }
1141 else {
1142 for (T truthParticle : TruthContainer) {
1143 if (HepMC::is_sim_descendant(p,truthParticle)) {
1144 ptrPart = truthParticle;
1145 break;
1146 }
1147 }
1148 }
1149 return ptrPart;
1150 }
1152
1153 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1154 auto prodVtx = thePart->production_vertex();
1155 if (!prodVtx) return;
1156 for (const auto& theMother: prodVtx->particles_in()) {
1157 if (!theMother) continue;
1158 allancestors.insert(theMother);
1159 findParticleAncestors(theMother, allancestors);
1160 }
1161 }
1162
1164
1165 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1166 auto endVtx = thePart->end_vertex();
1167 if (!endVtx) return;
1168 for (const auto& theDaughter: endVtx->particles_out()) {
1169 if (!theDaughter) continue;
1170 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1171 allstabledescendants.insert(theDaughter);
1172 }
1173 findParticleStableDescendants(theDaughter, allstabledescendants);
1174 }
1175 }
1176
1180
1181 template <class T> bool isHardScatteringVertex(T pVert) {
1182 if (pVert == nullptr) return false;
1183 T pV = pVert;
1184 int numOfPartIn(0);
1185 int pdg(0);
1186
1187 do {
1188 pVert = pV;
1189 auto incoming = pVert->particles_in();
1190 numOfPartIn = incoming.size();
1191 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1192 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1193
1194 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1195
1196 if (numOfPartIn == 2) {
1197 auto incoming = pVert->particles_in();
1198 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1199 }
1200 return false;
1201}
1202
1206
1207 template <class T, class U>
1208 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1209 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1210 auto vtx = p->production_vertex();
1211 if (!vtx) return false;
1212 bool fromHad = false;
1213 for ( const auto& parent : particles_in(vtx) ) {
1214 if (!parent) continue;
1215 // should this really go into parton-level territory?
1216 // probably depends where BSM particles are being decayed
1217 fromBSM |= isBSM(parent);
1218 if (!isPhysical(parent)) return false;
1219 fromTau |= isTau(parent);
1220 if (isHadron(parent)&&!isBeam(parent)) {
1221 if (!hadron) hadron = parent; // assumes linear hadron parentage
1222 return true;
1223 }
1224 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1225 }
1226 return fromHad;
1227 }
1228
1231
1232 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1233 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1234 decltype(thePart->end_vertex()) pVert(nullptr);
1235 if (EndVert != nullptr) {
1236 do {
1237 bool samePart = false;
1238 pVert = nullptr;
1239 auto outgoing = EndVert->particles_out();
1240 auto incoming = EndVert->particles_in();
1241 for (const auto& itrDaug: outgoing) {
1242 if (!itrDaug) continue;
1243 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1244 // brem on generator level for tau
1245 (outgoing.size() == 1 && incoming.size() == 1 &&
1247 itrDaug->pdg_id() == thePart->pdg_id()) {
1248 samePart = true;
1249 pVert = itrDaug->end_vertex();
1250 }
1251 }
1252 if (samePart) EndVert = pVert;
1253 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1254 }
1255 return EndVert;
1256 }
1257
1259
1260 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1261 if (!theVert) return {};
1262 decltype(theVert->particles_out()) finalStatePart;
1263 auto outgoing = theVert->particles_out();
1264 for (const auto& thePart: outgoing) {
1265 if (!thePart) continue;
1266 finalStatePart.push_back(thePart);
1267 if (isStable(thePart)) continue;
1268 V pVert = findSimulatedEndVertex(thePart);
1269 if (pVert == theVert) break; // to prevent Sherpa loop
1270 if (pVert != nullptr) {
1271 auto vecPart = findFinalStateParticles<V>(pVert);
1272 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1273 }
1274 }
1275 return finalStatePart;
1276 }
1277#if !defined(XAOD_ANALYSIS)
1278#include "AtlasHepMC/GenEvent.h"
1279inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1280inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1281
1282#endif
1283}
1284#endif

◆ charge3() [2/3]

template<>
int MC::charge3 ( const int & p)
inline

Definition at line 1083 of file HepMCHelpers.h.

1102{
1103 template <class VTX>
1104 auto particles_in (const VTX* p) { return p->particles_in(); }
1105 template <class VTX>
1106 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1107
1108 namespace Pythia8
1109 {
1111 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1112
1113 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1114
1115 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1116 }
1117
1118#include "AtlasPID.h"
1119
1121 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1122
1124 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1125
1127 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1128
1130 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1131
1133 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1134
1136 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1137
1139 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1140
1142 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1143
1145 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1146
1148 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1149
1153 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1154 const auto vertex = p->end_vertex();
1155 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1156 }
1157
1159 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1160
1162 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1163 const int apid = std::abs(p->pdg_id());
1164 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1165 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1166 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1167 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1168 return false;
1169 }
1170
1172
1173 template <class T> T findMother(T thePart) {
1174 auto partOriVert = thePart->production_vertex();
1175 if (!partOriVert) return nullptr;
1176
1177 long partPDG = thePart->pdg_id();
1178 long MotherPDG(0);
1179
1180 auto MothOriVert = partOriVert;
1181 MothOriVert = nullptr;
1182 T theMoth(nullptr);
1183
1184 size_t itr = 0;
1185 do {
1186 if (itr != 0) partOriVert = MothOriVert;
1187 for ( const auto& p : particles_in(partOriVert) ) {
1188 theMoth = p;
1189 if (!theMoth) continue;
1190 MotherPDG = theMoth->pdg_id();
1191 MothOriVert = theMoth->production_vertex();
1192 if (MotherPDG == partPDG) break;
1193 }
1194 itr++;
1195 if (itr > 100) {
1196 break;
1197 }
1198 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1199 MothOriVert != partOriVert);
1200 return theMoth;
1201 }
1202
1204
1205 template <class C, class T> T findMatching(C TruthContainer, T p) {
1206 T ptrPart = nullptr;
1207 if (!p) return ptrPart;
1208 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1209 for (T truthParticle : *TruthContainer) {
1210 if (HepMC::is_sim_descendant(p,truthParticle)) {
1211 ptrPart = truthParticle;
1212 break;
1213 }
1214 }
1215 }
1216 else {
1217 for (T truthParticle : TruthContainer) {
1218 if (HepMC::is_sim_descendant(p,truthParticle)) {
1219 ptrPart = truthParticle;
1220 break;
1221 }
1222 }
1223 }
1224 return ptrPart;
1225 }
1227
1228 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1229 auto prodVtx = thePart->production_vertex();
1230 if (!prodVtx) return;
1231 for (const auto& theMother: prodVtx->particles_in()) {
1232 if (!theMother) continue;
1233 allancestors.insert(theMother);
1234 findParticleAncestors(theMother, allancestors);
1235 }
1236 }
1237
1239
1240 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1241 auto endVtx = thePart->end_vertex();
1242 if (!endVtx) return;
1243 for (const auto& theDaughter: endVtx->particles_out()) {
1244 if (!theDaughter) continue;
1245 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1246 allstabledescendants.insert(theDaughter);
1247 }
1248 findParticleStableDescendants(theDaughter, allstabledescendants);
1249 }
1250 }
1251
1255
1256 template <class T> bool isHardScatteringVertex(T pVert) {
1257 if (pVert == nullptr) return false;
1258 T pV = pVert;
1259 int numOfPartIn(0);
1260 int pdg(0);
1261
1262 do {
1263 pVert = pV;
1264 auto incoming = pVert->particles_in();
1265 numOfPartIn = incoming.size();
1266 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1267 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1268
1269 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1270
1271 if (numOfPartIn == 2) {
1272 auto incoming = pVert->particles_in();
1273 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1274 }
1275 return false;
1276}
1277
1281
1282 template <class T, class U>
1283 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1284 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1285 auto vtx = p->production_vertex();
1286 if (!vtx) return false;
1287 bool fromHad = false;
1288 for ( const auto& parent : particles_in(vtx) ) {
1289 if (!parent) continue;
1290 // should this really go into parton-level territory?
1291 // probably depends where BSM particles are being decayed
1292 fromBSM |= isBSM(parent);
1293 if (!isPhysical(parent)) return false;
1294 fromTau |= isTau(parent);
1295 if (isHadron(parent)&&!isBeam(parent)) {
1296 if (!hadron) hadron = parent; // assumes linear hadron parentage
1297 return true;
1298 }
1299 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1300 }
1301 return fromHad;
1302 }
1303
1306
1307 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1308 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1309 decltype(thePart->end_vertex()) pVert(nullptr);
1310 if (EndVert != nullptr) {
1311 do {
1312 bool samePart = false;
1313 pVert = nullptr;
1314 auto outgoing = EndVert->particles_out();
1315 auto incoming = EndVert->particles_in();
1316 for (const auto& itrDaug: outgoing) {
1317 if (!itrDaug) continue;
1318 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1319 // brem on generator level for tau
1320 (outgoing.size() == 1 && incoming.size() == 1 &&
1322 itrDaug->pdg_id() == thePart->pdg_id()) {
1323 samePart = true;
1324 pVert = itrDaug->end_vertex();
1325 }
1326 }
1327 if (samePart) EndVert = pVert;
1328 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1329 }
1330 return EndVert;
1331 }
1332
1334
1335 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1336 if (!theVert) return {};
1337 decltype(theVert->particles_out()) finalStatePart;
1338 auto outgoing = theVert->particles_out();
1339 for (const auto& thePart: outgoing) {
1340 if (!thePart) continue;
1341 finalStatePart.push_back(thePart);
1342 if (isStable(thePart)) continue;
1343 V pVert = findSimulatedEndVertex(thePart);
1344 if (pVert == theVert) break; // to prevent Sherpa loop
1345 if (pVert != nullptr) {
1346 auto vecPart = findFinalStateParticles<V>(pVert);
1347 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1348 }
1349 }
1350 return finalStatePart;
1351 }
1352#if !defined(XAOD_ANALYSIS)
1353#include "AtlasHepMC/GenEvent.h"
1354inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1355inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1356
1357#endif
1358}
1359#endif

◆ charge3() [3/3]

template<class T>
int MC::charge3 ( const T & p)
inline

Definition at line 996 of file HepMCHelpers.h.

1015{
1016 template <class VTX>
1017 auto particles_in (const VTX* p) { return p->particles_in(); }
1018 template <class VTX>
1019 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1020
1021 namespace Pythia8
1022 {
1024 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1025
1026 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1027
1028 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1029 }
1030
1031#include "AtlasPID.h"
1032
1034 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1035
1037 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1038
1040 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1041
1043 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1044
1046 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1047
1049 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1050
1052 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1053
1055 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1056
1058 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1059
1061 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1062
1066 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1067 const auto vertex = p->end_vertex();
1068 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1069 }
1070
1072 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1073
1075 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1076 const int apid = std::abs(p->pdg_id());
1077 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1078 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1079 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1080 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1081 return false;
1082 }
1083
1085
1086 template <class T> T findMother(T thePart) {
1087 auto partOriVert = thePart->production_vertex();
1088 if (!partOriVert) return nullptr;
1089
1090 long partPDG = thePart->pdg_id();
1091 long MotherPDG(0);
1092
1093 auto MothOriVert = partOriVert;
1094 MothOriVert = nullptr;
1095 T theMoth(nullptr);
1096
1097 size_t itr = 0;
1098 do {
1099 if (itr != 0) partOriVert = MothOriVert;
1100 for ( const auto& p : particles_in(partOriVert) ) {
1101 theMoth = p;
1102 if (!theMoth) continue;
1103 MotherPDG = theMoth->pdg_id();
1104 MothOriVert = theMoth->production_vertex();
1105 if (MotherPDG == partPDG) break;
1106 }
1107 itr++;
1108 if (itr > 100) {
1109 break;
1110 }
1111 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1112 MothOriVert != partOriVert);
1113 return theMoth;
1114 }
1115
1117
1118 template <class C, class T> T findMatching(C TruthContainer, T p) {
1119 T ptrPart = nullptr;
1120 if (!p) return ptrPart;
1121 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1122 for (T truthParticle : *TruthContainer) {
1123 if (HepMC::is_sim_descendant(p,truthParticle)) {
1124 ptrPart = truthParticle;
1125 break;
1126 }
1127 }
1128 }
1129 else {
1130 for (T truthParticle : TruthContainer) {
1131 if (HepMC::is_sim_descendant(p,truthParticle)) {
1132 ptrPart = truthParticle;
1133 break;
1134 }
1135 }
1136 }
1137 return ptrPart;
1138 }
1140
1141 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1142 auto prodVtx = thePart->production_vertex();
1143 if (!prodVtx) return;
1144 for (const auto& theMother: prodVtx->particles_in()) {
1145 if (!theMother) continue;
1146 allancestors.insert(theMother);
1147 findParticleAncestors(theMother, allancestors);
1148 }
1149 }
1150
1152
1153 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1154 auto endVtx = thePart->end_vertex();
1155 if (!endVtx) return;
1156 for (const auto& theDaughter: endVtx->particles_out()) {
1157 if (!theDaughter) continue;
1158 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1159 allstabledescendants.insert(theDaughter);
1160 }
1161 findParticleStableDescendants(theDaughter, allstabledescendants);
1162 }
1163 }
1164
1168
1169 template <class T> bool isHardScatteringVertex(T pVert) {
1170 if (pVert == nullptr) return false;
1171 T pV = pVert;
1172 int numOfPartIn(0);
1173 int pdg(0);
1174
1175 do {
1176 pVert = pV;
1177 auto incoming = pVert->particles_in();
1178 numOfPartIn = incoming.size();
1179 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1180 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1181
1182 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1183
1184 if (numOfPartIn == 2) {
1185 auto incoming = pVert->particles_in();
1186 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1187 }
1188 return false;
1189}
1190
1194
1195 template <class T, class U>
1196 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1197 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1198 auto vtx = p->production_vertex();
1199 if (!vtx) return false;
1200 bool fromHad = false;
1201 for ( const auto& parent : particles_in(vtx) ) {
1202 if (!parent) continue;
1203 // should this really go into parton-level territory?
1204 // probably depends where BSM particles are being decayed
1205 fromBSM |= isBSM(parent);
1206 if (!isPhysical(parent)) return false;
1207 fromTau |= isTau(parent);
1208 if (isHadron(parent)&&!isBeam(parent)) {
1209 if (!hadron) hadron = parent; // assumes linear hadron parentage
1210 return true;
1211 }
1212 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1213 }
1214 return fromHad;
1215 }
1216
1219
1220 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1221 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1222 decltype(thePart->end_vertex()) pVert(nullptr);
1223 if (EndVert != nullptr) {
1224 do {
1225 bool samePart = false;
1226 pVert = nullptr;
1227 auto outgoing = EndVert->particles_out();
1228 auto incoming = EndVert->particles_in();
1229 for (const auto& itrDaug: outgoing) {
1230 if (!itrDaug) continue;
1231 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1232 // brem on generator level for tau
1233 (outgoing.size() == 1 && incoming.size() == 1 &&
1235 itrDaug->pdg_id() == thePart->pdg_id()) {
1236 samePart = true;
1237 pVert = itrDaug->end_vertex();
1238 }
1239 }
1240 if (samePart) EndVert = pVert;
1241 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1242 }
1243 return EndVert;
1244 }
1245
1247
1248 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1249 if (!theVert) return {};
1250 decltype(theVert->particles_out()) finalStatePart;
1251 auto outgoing = theVert->particles_out();
1252 for (const auto& thePart: outgoing) {
1253 if (!thePart) continue;
1254 finalStatePart.push_back(thePart);
1255 if (isStable(thePart)) continue;
1256 V pVert = findSimulatedEndVertex(thePart);
1257 if (pVert == theVert) break; // to prevent Sherpa loop
1258 if (pVert != nullptr) {
1259 auto vecPart = findFinalStateParticles<V>(pVert);
1260 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1261 }
1262 }
1263 return finalStatePart;
1264 }
1265#if !defined(XAOD_ANALYSIS)
1266#include "AtlasHepMC/GenEvent.h"
1267inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1268inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1269
1270#endif
1271}
1272#endif

◆ containedQuarks() [1/3]

template<>
std::vector< int > MC::containedQuarks ( const DecodedPID & p)
inline

Definition at line 1182 of file HepMCHelpers.h.

1201{
1202 template <class VTX>
1203 auto particles_in (const VTX* p) { return p->particles_in(); }
1204 template <class VTX>
1205 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1206
1207 namespace Pythia8
1208 {
1210 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1211
1212 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1213
1214 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1215 }
1216
1217#include "AtlasPID.h"
1218
1220 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1221
1223 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1224
1226 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1227
1229 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1230
1232 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1233
1235 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1236
1238 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1239
1241 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1242
1244 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1245
1247 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1248
1252 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1253 const auto vertex = p->end_vertex();
1254 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1255 }
1256
1258 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1259
1261 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1262 const int apid = std::abs(p->pdg_id());
1263 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1264 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1265 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1266 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1267 return false;
1268 }
1269
1271
1272 template <class T> T findMother(T thePart) {
1273 auto partOriVert = thePart->production_vertex();
1274 if (!partOriVert) return nullptr;
1275
1276 long partPDG = thePart->pdg_id();
1277 long MotherPDG(0);
1278
1279 auto MothOriVert = partOriVert;
1280 MothOriVert = nullptr;
1281 T theMoth(nullptr);
1282
1283 size_t itr = 0;
1284 do {
1285 if (itr != 0) partOriVert = MothOriVert;
1286 for ( const auto& p : particles_in(partOriVert) ) {
1287 theMoth = p;
1288 if (!theMoth) continue;
1289 MotherPDG = theMoth->pdg_id();
1290 MothOriVert = theMoth->production_vertex();
1291 if (MotherPDG == partPDG) break;
1292 }
1293 itr++;
1294 if (itr > 100) {
1295 break;
1296 }
1297 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1298 MothOriVert != partOriVert);
1299 return theMoth;
1300 }
1301
1303
1304 template <class C, class T> T findMatching(C TruthContainer, T p) {
1305 T ptrPart = nullptr;
1306 if (!p) return ptrPart;
1307 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1308 for (T truthParticle : *TruthContainer) {
1309 if (HepMC::is_sim_descendant(p,truthParticle)) {
1310 ptrPart = truthParticle;
1311 break;
1312 }
1313 }
1314 }
1315 else {
1316 for (T truthParticle : TruthContainer) {
1317 if (HepMC::is_sim_descendant(p,truthParticle)) {
1318 ptrPart = truthParticle;
1319 break;
1320 }
1321 }
1322 }
1323 return ptrPart;
1324 }
1326
1327 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1328 auto prodVtx = thePart->production_vertex();
1329 if (!prodVtx) return;
1330 for (const auto& theMother: prodVtx->particles_in()) {
1331 if (!theMother) continue;
1332 allancestors.insert(theMother);
1333 findParticleAncestors(theMother, allancestors);
1334 }
1335 }
1336
1338
1339 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1340 auto endVtx = thePart->end_vertex();
1341 if (!endVtx) return;
1342 for (const auto& theDaughter: endVtx->particles_out()) {
1343 if (!theDaughter) continue;
1344 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1345 allstabledescendants.insert(theDaughter);
1346 }
1347 findParticleStableDescendants(theDaughter, allstabledescendants);
1348 }
1349 }
1350
1354
1355 template <class T> bool isHardScatteringVertex(T pVert) {
1356 if (pVert == nullptr) return false;
1357 T pV = pVert;
1358 int numOfPartIn(0);
1359 int pdg(0);
1360
1361 do {
1362 pVert = pV;
1363 auto incoming = pVert->particles_in();
1364 numOfPartIn = incoming.size();
1365 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1366 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1367
1368 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1369
1370 if (numOfPartIn == 2) {
1371 auto incoming = pVert->particles_in();
1372 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1373 }
1374 return false;
1375}
1376
1380
1381 template <class T, class U>
1382 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1383 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1384 auto vtx = p->production_vertex();
1385 if (!vtx) return false;
1386 bool fromHad = false;
1387 for ( const auto& parent : particles_in(vtx) ) {
1388 if (!parent) continue;
1389 // should this really go into parton-level territory?
1390 // probably depends where BSM particles are being decayed
1391 fromBSM |= isBSM(parent);
1392 if (!isPhysical(parent)) return false;
1393 fromTau |= isTau(parent);
1394 if (isHadron(parent)&&!isBeam(parent)) {
1395 if (!hadron) hadron = parent; // assumes linear hadron parentage
1396 return true;
1397 }
1398 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1399 }
1400 return fromHad;
1401 }
1402
1405
1406 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1407 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1408 decltype(thePart->end_vertex()) pVert(nullptr);
1409 if (EndVert != nullptr) {
1410 do {
1411 bool samePart = false;
1412 pVert = nullptr;
1413 auto outgoing = EndVert->particles_out();
1414 auto incoming = EndVert->particles_in();
1415 for (const auto& itrDaug: outgoing) {
1416 if (!itrDaug) continue;
1417 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1418 // brem on generator level for tau
1419 (outgoing.size() == 1 && incoming.size() == 1 &&
1421 itrDaug->pdg_id() == thePart->pdg_id()) {
1422 samePart = true;
1423 pVert = itrDaug->end_vertex();
1424 }
1425 }
1426 if (samePart) EndVert = pVert;
1427 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1428 }
1429 return EndVert;
1430 }
1431
1433
1434 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1435 if (!theVert) return {};
1436 decltype(theVert->particles_out()) finalStatePart;
1437 auto outgoing = theVert->particles_out();
1438 for (const auto& thePart: outgoing) {
1439 if (!thePart) continue;
1440 finalStatePart.push_back(thePart);
1441 if (isStable(thePart)) continue;
1442 V pVert = findSimulatedEndVertex(thePart);
1443 if (pVert == theVert) break; // to prevent Sherpa loop
1444 if (pVert != nullptr) {
1445 auto vecPart = findFinalStateParticles<V>(pVert);
1446 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1447 }
1448 }
1449 return finalStatePart;
1450 }
1451#if !defined(XAOD_ANALYSIS)
1452#include "AtlasHepMC/GenEvent.h"
1453inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1454inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1455
1456#endif
1457}
1458#endif

◆ containedQuarks() [2/3]

template<>
std::vector< int > MC::containedQuarks ( const int & p)
inline

Definition at line 1160 of file HepMCHelpers.h.

1179{
1180 template <class VTX>
1181 auto particles_in (const VTX* p) { return p->particles_in(); }
1182 template <class VTX>
1183 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1184
1185 namespace Pythia8
1186 {
1188 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1189
1190 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1191
1192 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1193 }
1194
1195#include "AtlasPID.h"
1196
1198 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1199
1201 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1202
1204 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1205
1207 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1208
1210 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1211
1213 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1214
1216 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1217
1219 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1220
1222 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1223
1225 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1226
1230 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1231 const auto vertex = p->end_vertex();
1232 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1233 }
1234
1236 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1237
1239 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1240 const int apid = std::abs(p->pdg_id());
1241 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1242 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1243 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1244 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1245 return false;
1246 }
1247
1249
1250 template <class T> T findMother(T thePart) {
1251 auto partOriVert = thePart->production_vertex();
1252 if (!partOriVert) return nullptr;
1253
1254 long partPDG = thePart->pdg_id();
1255 long MotherPDG(0);
1256
1257 auto MothOriVert = partOriVert;
1258 MothOriVert = nullptr;
1259 T theMoth(nullptr);
1260
1261 size_t itr = 0;
1262 do {
1263 if (itr != 0) partOriVert = MothOriVert;
1264 for ( const auto& p : particles_in(partOriVert) ) {
1265 theMoth = p;
1266 if (!theMoth) continue;
1267 MotherPDG = theMoth->pdg_id();
1268 MothOriVert = theMoth->production_vertex();
1269 if (MotherPDG == partPDG) break;
1270 }
1271 itr++;
1272 if (itr > 100) {
1273 break;
1274 }
1275 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1276 MothOriVert != partOriVert);
1277 return theMoth;
1278 }
1279
1281
1282 template <class C, class T> T findMatching(C TruthContainer, T p) {
1283 T ptrPart = nullptr;
1284 if (!p) return ptrPart;
1285 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1286 for (T truthParticle : *TruthContainer) {
1287 if (HepMC::is_sim_descendant(p,truthParticle)) {
1288 ptrPart = truthParticle;
1289 break;
1290 }
1291 }
1292 }
1293 else {
1294 for (T truthParticle : TruthContainer) {
1295 if (HepMC::is_sim_descendant(p,truthParticle)) {
1296 ptrPart = truthParticle;
1297 break;
1298 }
1299 }
1300 }
1301 return ptrPart;
1302 }
1304
1305 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1306 auto prodVtx = thePart->production_vertex();
1307 if (!prodVtx) return;
1308 for (const auto& theMother: prodVtx->particles_in()) {
1309 if (!theMother) continue;
1310 allancestors.insert(theMother);
1311 findParticleAncestors(theMother, allancestors);
1312 }
1313 }
1314
1316
1317 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1318 auto endVtx = thePart->end_vertex();
1319 if (!endVtx) return;
1320 for (const auto& theDaughter: endVtx->particles_out()) {
1321 if (!theDaughter) continue;
1322 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1323 allstabledescendants.insert(theDaughter);
1324 }
1325 findParticleStableDescendants(theDaughter, allstabledescendants);
1326 }
1327 }
1328
1332
1333 template <class T> bool isHardScatteringVertex(T pVert) {
1334 if (pVert == nullptr) return false;
1335 T pV = pVert;
1336 int numOfPartIn(0);
1337 int pdg(0);
1338
1339 do {
1340 pVert = pV;
1341 auto incoming = pVert->particles_in();
1342 numOfPartIn = incoming.size();
1343 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1344 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1345
1346 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1347
1348 if (numOfPartIn == 2) {
1349 auto incoming = pVert->particles_in();
1350 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1351 }
1352 return false;
1353}
1354
1358
1359 template <class T, class U>
1360 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1361 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1362 auto vtx = p->production_vertex();
1363 if (!vtx) return false;
1364 bool fromHad = false;
1365 for ( const auto& parent : particles_in(vtx) ) {
1366 if (!parent) continue;
1367 // should this really go into parton-level territory?
1368 // probably depends where BSM particles are being decayed
1369 fromBSM |= isBSM(parent);
1370 if (!isPhysical(parent)) return false;
1371 fromTau |= isTau(parent);
1372 if (isHadron(parent)&&!isBeam(parent)) {
1373 if (!hadron) hadron = parent; // assumes linear hadron parentage
1374 return true;
1375 }
1376 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1377 }
1378 return fromHad;
1379 }
1380
1383
1384 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1385 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1386 decltype(thePart->end_vertex()) pVert(nullptr);
1387 if (EndVert != nullptr) {
1388 do {
1389 bool samePart = false;
1390 pVert = nullptr;
1391 auto outgoing = EndVert->particles_out();
1392 auto incoming = EndVert->particles_in();
1393 for (const auto& itrDaug: outgoing) {
1394 if (!itrDaug) continue;
1395 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1396 // brem on generator level for tau
1397 (outgoing.size() == 1 && incoming.size() == 1 &&
1399 itrDaug->pdg_id() == thePart->pdg_id()) {
1400 samePart = true;
1401 pVert = itrDaug->end_vertex();
1402 }
1403 }
1404 if (samePart) EndVert = pVert;
1405 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1406 }
1407 return EndVert;
1408 }
1409
1411
1412 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1413 if (!theVert) return {};
1414 decltype(theVert->particles_out()) finalStatePart;
1415 auto outgoing = theVert->particles_out();
1416 for (const auto& thePart: outgoing) {
1417 if (!thePart) continue;
1418 finalStatePart.push_back(thePart);
1419 if (isStable(thePart)) continue;
1420 V pVert = findSimulatedEndVertex(thePart);
1421 if (pVert == theVert) break; // to prevent Sherpa loop
1422 if (pVert != nullptr) {
1423 auto vecPart = findFinalStateParticles<V>(pVert);
1424 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1425 }
1426 }
1427 return finalStatePart;
1428 }
1429#if !defined(XAOD_ANALYSIS)
1430#include "AtlasHepMC/GenEvent.h"
1431inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1432inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1433
1434#endif
1435}
1436#endif

◆ containedQuarks() [3/3]

template<class T>
std::vector< int > MC::containedQuarks ( const T & p)
inline

Definition at line 1159 of file HepMCHelpers.h.

1178{
1179 template <class VTX>
1180 auto particles_in (const VTX* p) { return p->particles_in(); }
1181 template <class VTX>
1182 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1183
1184 namespace Pythia8
1185 {
1187 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1188
1189 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1190
1191 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1192 }
1193
1194#include "AtlasPID.h"
1195
1197 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1198
1200 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1201
1203 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1204
1206 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1207
1209 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1210
1212 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1213
1215 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1216
1218 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1219
1221 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1222
1224 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1225
1229 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1230 const auto vertex = p->end_vertex();
1231 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1232 }
1233
1235 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1236
1238 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1239 const int apid = std::abs(p->pdg_id());
1240 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1241 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1242 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1243 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1244 return false;
1245 }
1246
1248
1249 template <class T> T findMother(T thePart) {
1250 auto partOriVert = thePart->production_vertex();
1251 if (!partOriVert) return nullptr;
1252
1253 long partPDG = thePart->pdg_id();
1254 long MotherPDG(0);
1255
1256 auto MothOriVert = partOriVert;
1257 MothOriVert = nullptr;
1258 T theMoth(nullptr);
1259
1260 size_t itr = 0;
1261 do {
1262 if (itr != 0) partOriVert = MothOriVert;
1263 for ( const auto& p : particles_in(partOriVert) ) {
1264 theMoth = p;
1265 if (!theMoth) continue;
1266 MotherPDG = theMoth->pdg_id();
1267 MothOriVert = theMoth->production_vertex();
1268 if (MotherPDG == partPDG) break;
1269 }
1270 itr++;
1271 if (itr > 100) {
1272 break;
1273 }
1274 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1275 MothOriVert != partOriVert);
1276 return theMoth;
1277 }
1278
1280
1281 template <class C, class T> T findMatching(C TruthContainer, T p) {
1282 T ptrPart = nullptr;
1283 if (!p) return ptrPart;
1284 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1285 for (T truthParticle : *TruthContainer) {
1286 if (HepMC::is_sim_descendant(p,truthParticle)) {
1287 ptrPart = truthParticle;
1288 break;
1289 }
1290 }
1291 }
1292 else {
1293 for (T truthParticle : TruthContainer) {
1294 if (HepMC::is_sim_descendant(p,truthParticle)) {
1295 ptrPart = truthParticle;
1296 break;
1297 }
1298 }
1299 }
1300 return ptrPart;
1301 }
1303
1304 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1305 auto prodVtx = thePart->production_vertex();
1306 if (!prodVtx) return;
1307 for (const auto& theMother: prodVtx->particles_in()) {
1308 if (!theMother) continue;
1309 allancestors.insert(theMother);
1310 findParticleAncestors(theMother, allancestors);
1311 }
1312 }
1313
1315
1316 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1317 auto endVtx = thePart->end_vertex();
1318 if (!endVtx) return;
1319 for (const auto& theDaughter: endVtx->particles_out()) {
1320 if (!theDaughter) continue;
1321 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1322 allstabledescendants.insert(theDaughter);
1323 }
1324 findParticleStableDescendants(theDaughter, allstabledescendants);
1325 }
1326 }
1327
1331
1332 template <class T> bool isHardScatteringVertex(T pVert) {
1333 if (pVert == nullptr) return false;
1334 T pV = pVert;
1335 int numOfPartIn(0);
1336 int pdg(0);
1337
1338 do {
1339 pVert = pV;
1340 auto incoming = pVert->particles_in();
1341 numOfPartIn = incoming.size();
1342 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1343 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1344
1345 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1346
1347 if (numOfPartIn == 2) {
1348 auto incoming = pVert->particles_in();
1349 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1350 }
1351 return false;
1352}
1353
1357
1358 template <class T, class U>
1359 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1360 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1361 auto vtx = p->production_vertex();
1362 if (!vtx) return false;
1363 bool fromHad = false;
1364 for ( const auto& parent : particles_in(vtx) ) {
1365 if (!parent) continue;
1366 // should this really go into parton-level territory?
1367 // probably depends where BSM particles are being decayed
1368 fromBSM |= isBSM(parent);
1369 if (!isPhysical(parent)) return false;
1370 fromTau |= isTau(parent);
1371 if (isHadron(parent)&&!isBeam(parent)) {
1372 if (!hadron) hadron = parent; // assumes linear hadron parentage
1373 return true;
1374 }
1375 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1376 }
1377 return fromHad;
1378 }
1379
1382
1383 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1384 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1385 decltype(thePart->end_vertex()) pVert(nullptr);
1386 if (EndVert != nullptr) {
1387 do {
1388 bool samePart = false;
1389 pVert = nullptr;
1390 auto outgoing = EndVert->particles_out();
1391 auto incoming = EndVert->particles_in();
1392 for (const auto& itrDaug: outgoing) {
1393 if (!itrDaug) continue;
1394 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1395 // brem on generator level for tau
1396 (outgoing.size() == 1 && incoming.size() == 1 &&
1398 itrDaug->pdg_id() == thePart->pdg_id()) {
1399 samePart = true;
1400 pVert = itrDaug->end_vertex();
1401 }
1402 }
1403 if (samePart) EndVert = pVert;
1404 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1405 }
1406 return EndVert;
1407 }
1408
1410
1411 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1412 if (!theVert) return {};
1413 decltype(theVert->particles_out()) finalStatePart;
1414 auto outgoing = theVert->particles_out();
1415 for (const auto& thePart: outgoing) {
1416 if (!thePart) continue;
1417 finalStatePart.push_back(thePart);
1418 if (isStable(thePart)) continue;
1419 V pVert = findSimulatedEndVertex(thePart);
1420 if (pVert == theVert) break; // to prevent Sherpa loop
1421 if (pVert != nullptr) {
1422 auto vecPart = findFinalStateParticles<V>(pVert);
1423 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1424 }
1425 }
1426 return finalStatePart;
1427 }
1428#if !defined(XAOD_ANALYSIS)
1429#include "AtlasHepMC/GenEvent.h"
1430inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1431inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1432
1433#endif
1434}
1435#endif

◆ findFinalStateParticles()

template<class V>
auto MC::findFinalStateParticles ( V theVert) -> decltype(theVert->particles_out())

Function to find the stable particle descendants of the given vertex..

This can be used for HepMC3::GenVertexPtr, HepMC3::ConstGenVertexPtr or xAOD::TruthVertex* and particle counterparts

Definition at line 253 of file HepMCHelpers.h.

253 {
254 if (!theVert) return {};
255 decltype(theVert->particles_out()) finalStatePart;
256 auto outgoing = theVert->particles_out();
257 for (const auto& thePart: outgoing) {
258 if (!thePart) continue;
259 finalStatePart.push_back(thePart);
260 if (isStable(thePart)) continue;
261 V pVert = findSimulatedEndVertex(thePart);
262 if (pVert == theVert) break; // to prevent Sherpa loop
263 if (pVert != nullptr) {
264 auto vecPart = findFinalStateParticles<V>(pVert);
265 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
266 }
267 }
268 return finalStatePart;
269 }

◆ findMatching()

template<class C, class T>
T MC::findMatching ( C TruthContainer,
T p )

Function to find a particle in container.

This can be used for HepMC3::GenVertexPtr, HepMC3::ConstGenVertexPtr or xAOD::TruthVertex*

Definition at line 123 of file HepMCHelpers.h.

123 {
124 T ptrPart = nullptr;
125 if (!p) return ptrPart;
126 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
127 for (T truthParticle : *TruthContainer) {
128 if (HepMC::is_sim_descendant(p,truthParticle)) {
129 ptrPart = truthParticle;
130 break;
131 }
132 }
133 }
134 else {
135 for (T truthParticle : TruthContainer) {
136 if (HepMC::is_sim_descendant(p,truthParticle)) {
137 ptrPart = truthParticle;
138 break;
139 }
140 }
141 }
142 return ptrPart;
143 }

◆ findMother()

template<class T>
T MC::findMother ( T thePart)

Function to get a mother of particle. MCTruthClassifier legacy.

This can be used for HepMC3::GenVertexPtr, HepMC3::ConstGenVertexPtr or xAOD::TruthVertex*

Definition at line 91 of file HepMCHelpers.h.

91 {
92 auto partOriVert = thePart->production_vertex();
93 if (!partOriVert) return nullptr;
94
95 long partPDG = thePart->pdg_id();
96 long MotherPDG(0);
97
98 auto MothOriVert = partOriVert;
99 MothOriVert = nullptr;
100 T theMoth(nullptr);
101
102 size_t itr = 0;
103 do {
104 if (itr != 0) partOriVert = MothOriVert;
105 for ( const auto& p : particles_in(partOriVert) ) {
106 theMoth = p;
107 if (!theMoth) continue;
108 MotherPDG = theMoth->pdg_id();
109 MothOriVert = theMoth->production_vertex();
110 if (MotherPDG == partPDG) break;
111 }
112 itr++;
113 if (itr > 100) {
114 break;
115 }
116 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
117 MothOriVert != partOriVert);
118 return theMoth;
119 }

◆ findParticleAncestors()

template<class T>
void MC::findParticleAncestors ( T thePart,
std::set< T > & allancestors )

Function to find all ancestors of the particle.

This can be used for HepMC3::GenParticlePtr, HepMC3::ConstGenParticlePtr or xAOD::TruthParticle*

Definition at line 146 of file HepMCHelpers.h.

146 {
147 auto prodVtx = thePart->production_vertex();
148 if (!prodVtx) return;
149 for (const auto& theMother: prodVtx->particles_in()) {
150 if (!theMother) continue;
151 allancestors.insert(theMother);
152 findParticleAncestors(theMother, allancestors);
153 }
154 }

◆ findParticleStableDescendants()

template<class T>
void MC::findParticleStableDescendants ( T thePart,
std::set< T > & allstabledescendants )

Function to get the particle stable MC daughters.

This can be used for HepMC3::GenParticlePtr, HepMC3::ConstGenParticlePtr or xAOD::TruthParticle*

Definition at line 158 of file HepMCHelpers.h.

158 {
159 auto endVtx = thePart->end_vertex();
160 if (!endVtx) return;
161 for (const auto& theDaughter: endVtx->particles_out()) {
162 if (!theDaughter) continue;
163 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
164 allstabledescendants.insert(theDaughter);
165 }
166 findParticleStableDescendants(theDaughter, allstabledescendants);
167 }
168 }

◆ findSimulatedEndVertex()

template<class T>
auto MC::findSimulatedEndVertex ( T thePart) -> decltype(thePart->end_vertex())

Function to find the end vertex of a particle.

This algorithm allows for 1->1 decays. This can be used for HepMC3::GenVertexPtr, HepMC3::ConstGenVertexPtr or xAOD::TruthVertex* and particle counterparts

Definition at line 225 of file HepMCHelpers.h.

225 {
226 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
227 decltype(thePart->end_vertex()) pVert(nullptr);
228 if (EndVert != nullptr) {
229 do {
230 bool samePart = false;
231 pVert = nullptr;
232 auto outgoing = EndVert->particles_out();
233 auto incoming = EndVert->particles_in();
234 for (const auto& itrDaug: outgoing) {
235 if (!itrDaug) continue;
236 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
237 // brem on generator level for tau
238 (outgoing.size() == 1 && incoming.size() == 1 &&
240 itrDaug->pdg_id() == thePart->pdg_id()) {
241 samePart = true;
242 pVert = itrDaug->end_vertex();
243 }
244 }
245 if (samePart) EndVert = pVert;
246 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
247 }
248 return EndVert;
249 }

◆ fractionalCharge() [1/3]

template<>
double MC::fractionalCharge ( const DecodedPID & p)
inline

Definition at line 1096 of file HepMCHelpers.h.

1115{
1116 template <class VTX>
1117 auto particles_in (const VTX* p) { return p->particles_in(); }
1118 template <class VTX>
1119 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1120
1121 namespace Pythia8
1122 {
1124 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1125
1126 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1127
1128 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1129 }
1130
1131#include "AtlasPID.h"
1132
1134 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1135
1137 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1138
1140 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1141
1143 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1144
1146 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1147
1149 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1150
1152 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1153
1155 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1156
1158 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1159
1161 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1162
1166 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1167 const auto vertex = p->end_vertex();
1168 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1169 }
1170
1172 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1173
1175 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1176 const int apid = std::abs(p->pdg_id());
1177 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1178 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1179 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1180 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1181 return false;
1182 }
1183
1185
1186 template <class T> T findMother(T thePart) {
1187 auto partOriVert = thePart->production_vertex();
1188 if (!partOriVert) return nullptr;
1189
1190 long partPDG = thePart->pdg_id();
1191 long MotherPDG(0);
1192
1193 auto MothOriVert = partOriVert;
1194 MothOriVert = nullptr;
1195 T theMoth(nullptr);
1196
1197 size_t itr = 0;
1198 do {
1199 if (itr != 0) partOriVert = MothOriVert;
1200 for ( const auto& p : particles_in(partOriVert) ) {
1201 theMoth = p;
1202 if (!theMoth) continue;
1203 MotherPDG = theMoth->pdg_id();
1204 MothOriVert = theMoth->production_vertex();
1205 if (MotherPDG == partPDG) break;
1206 }
1207 itr++;
1208 if (itr > 100) {
1209 break;
1210 }
1211 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1212 MothOriVert != partOriVert);
1213 return theMoth;
1214 }
1215
1217
1218 template <class C, class T> T findMatching(C TruthContainer, T p) {
1219 T ptrPart = nullptr;
1220 if (!p) return ptrPart;
1221 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1222 for (T truthParticle : *TruthContainer) {
1223 if (HepMC::is_sim_descendant(p,truthParticle)) {
1224 ptrPart = truthParticle;
1225 break;
1226 }
1227 }
1228 }
1229 else {
1230 for (T truthParticle : TruthContainer) {
1231 if (HepMC::is_sim_descendant(p,truthParticle)) {
1232 ptrPart = truthParticle;
1233 break;
1234 }
1235 }
1236 }
1237 return ptrPart;
1238 }
1240
1241 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1242 auto prodVtx = thePart->production_vertex();
1243 if (!prodVtx) return;
1244 for (const auto& theMother: prodVtx->particles_in()) {
1245 if (!theMother) continue;
1246 allancestors.insert(theMother);
1247 findParticleAncestors(theMother, allancestors);
1248 }
1249 }
1250
1252
1253 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1254 auto endVtx = thePart->end_vertex();
1255 if (!endVtx) return;
1256 for (const auto& theDaughter: endVtx->particles_out()) {
1257 if (!theDaughter) continue;
1258 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1259 allstabledescendants.insert(theDaughter);
1260 }
1261 findParticleStableDescendants(theDaughter, allstabledescendants);
1262 }
1263 }
1264
1268
1269 template <class T> bool isHardScatteringVertex(T pVert) {
1270 if (pVert == nullptr) return false;
1271 T pV = pVert;
1272 int numOfPartIn(0);
1273 int pdg(0);
1274
1275 do {
1276 pVert = pV;
1277 auto incoming = pVert->particles_in();
1278 numOfPartIn = incoming.size();
1279 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1280 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1281
1282 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1283
1284 if (numOfPartIn == 2) {
1285 auto incoming = pVert->particles_in();
1286 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1287 }
1288 return false;
1289}
1290
1294
1295 template <class T, class U>
1296 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1297 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1298 auto vtx = p->production_vertex();
1299 if (!vtx) return false;
1300 bool fromHad = false;
1301 for ( const auto& parent : particles_in(vtx) ) {
1302 if (!parent) continue;
1303 // should this really go into parton-level territory?
1304 // probably depends where BSM particles are being decayed
1305 fromBSM |= isBSM(parent);
1306 if (!isPhysical(parent)) return false;
1307 fromTau |= isTau(parent);
1308 if (isHadron(parent)&&!isBeam(parent)) {
1309 if (!hadron) hadron = parent; // assumes linear hadron parentage
1310 return true;
1311 }
1312 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1313 }
1314 return fromHad;
1315 }
1316
1319
1320 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1321 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1322 decltype(thePart->end_vertex()) pVert(nullptr);
1323 if (EndVert != nullptr) {
1324 do {
1325 bool samePart = false;
1326 pVert = nullptr;
1327 auto outgoing = EndVert->particles_out();
1328 auto incoming = EndVert->particles_in();
1329 for (const auto& itrDaug: outgoing) {
1330 if (!itrDaug) continue;
1331 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1332 // brem on generator level for tau
1333 (outgoing.size() == 1 && incoming.size() == 1 &&
1335 itrDaug->pdg_id() == thePart->pdg_id()) {
1336 samePart = true;
1337 pVert = itrDaug->end_vertex();
1338 }
1339 }
1340 if (samePart) EndVert = pVert;
1341 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1342 }
1343 return EndVert;
1344 }
1345
1347
1348 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1349 if (!theVert) return {};
1350 decltype(theVert->particles_out()) finalStatePart;
1351 auto outgoing = theVert->particles_out();
1352 for (const auto& thePart: outgoing) {
1353 if (!thePart) continue;
1354 finalStatePart.push_back(thePart);
1355 if (isStable(thePart)) continue;
1356 V pVert = findSimulatedEndVertex(thePart);
1357 if (pVert == theVert) break; // to prevent Sherpa loop
1358 if (pVert != nullptr) {
1359 auto vecPart = findFinalStateParticles<V>(pVert);
1360 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1361 }
1362 }
1363 return finalStatePart;
1364 }
1365#if !defined(XAOD_ANALYSIS)
1366#include "AtlasHepMC/GenEvent.h"
1367inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1368inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1369
1370#endif
1371}
1372#endif

◆ fractionalCharge() [2/3]

template<>
double MC::fractionalCharge ( const int & p)
inline

Definition at line 1103 of file HepMCHelpers.h.

1122{
1123 template <class VTX>
1124 auto particles_in (const VTX* p) { return p->particles_in(); }
1125 template <class VTX>
1126 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1127
1128 namespace Pythia8
1129 {
1131 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1132
1133 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1134
1135 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1136 }
1137
1138#include "AtlasPID.h"
1139
1141 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1142
1144 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1145
1147 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1148
1150 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1151
1153 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1154
1156 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1157
1159 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1160
1162 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1163
1165 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1166
1168 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1169
1173 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1174 const auto vertex = p->end_vertex();
1175 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1176 }
1177
1179 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1180
1182 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1183 const int apid = std::abs(p->pdg_id());
1184 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1185 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1186 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1187 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1188 return false;
1189 }
1190
1192
1193 template <class T> T findMother(T thePart) {
1194 auto partOriVert = thePart->production_vertex();
1195 if (!partOriVert) return nullptr;
1196
1197 long partPDG = thePart->pdg_id();
1198 long MotherPDG(0);
1199
1200 auto MothOriVert = partOriVert;
1201 MothOriVert = nullptr;
1202 T theMoth(nullptr);
1203
1204 size_t itr = 0;
1205 do {
1206 if (itr != 0) partOriVert = MothOriVert;
1207 for ( const auto& p : particles_in(partOriVert) ) {
1208 theMoth = p;
1209 if (!theMoth) continue;
1210 MotherPDG = theMoth->pdg_id();
1211 MothOriVert = theMoth->production_vertex();
1212 if (MotherPDG == partPDG) break;
1213 }
1214 itr++;
1215 if (itr > 100) {
1216 break;
1217 }
1218 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1219 MothOriVert != partOriVert);
1220 return theMoth;
1221 }
1222
1224
1225 template <class C, class T> T findMatching(C TruthContainer, T p) {
1226 T ptrPart = nullptr;
1227 if (!p) return ptrPart;
1228 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1229 for (T truthParticle : *TruthContainer) {
1230 if (HepMC::is_sim_descendant(p,truthParticle)) {
1231 ptrPart = truthParticle;
1232 break;
1233 }
1234 }
1235 }
1236 else {
1237 for (T truthParticle : TruthContainer) {
1238 if (HepMC::is_sim_descendant(p,truthParticle)) {
1239 ptrPart = truthParticle;
1240 break;
1241 }
1242 }
1243 }
1244 return ptrPart;
1245 }
1247
1248 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1249 auto prodVtx = thePart->production_vertex();
1250 if (!prodVtx) return;
1251 for (const auto& theMother: prodVtx->particles_in()) {
1252 if (!theMother) continue;
1253 allancestors.insert(theMother);
1254 findParticleAncestors(theMother, allancestors);
1255 }
1256 }
1257
1259
1260 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1261 auto endVtx = thePart->end_vertex();
1262 if (!endVtx) return;
1263 for (const auto& theDaughter: endVtx->particles_out()) {
1264 if (!theDaughter) continue;
1265 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1266 allstabledescendants.insert(theDaughter);
1267 }
1268 findParticleStableDescendants(theDaughter, allstabledescendants);
1269 }
1270 }
1271
1275
1276 template <class T> bool isHardScatteringVertex(T pVert) {
1277 if (pVert == nullptr) return false;
1278 T pV = pVert;
1279 int numOfPartIn(0);
1280 int pdg(0);
1281
1282 do {
1283 pVert = pV;
1284 auto incoming = pVert->particles_in();
1285 numOfPartIn = incoming.size();
1286 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1287 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1288
1289 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1290
1291 if (numOfPartIn == 2) {
1292 auto incoming = pVert->particles_in();
1293 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1294 }
1295 return false;
1296}
1297
1301
1302 template <class T, class U>
1303 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1304 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1305 auto vtx = p->production_vertex();
1306 if (!vtx) return false;
1307 bool fromHad = false;
1308 for ( const auto& parent : particles_in(vtx) ) {
1309 if (!parent) continue;
1310 // should this really go into parton-level territory?
1311 // probably depends where BSM particles are being decayed
1312 fromBSM |= isBSM(parent);
1313 if (!isPhysical(parent)) return false;
1314 fromTau |= isTau(parent);
1315 if (isHadron(parent)&&!isBeam(parent)) {
1316 if (!hadron) hadron = parent; // assumes linear hadron parentage
1317 return true;
1318 }
1319 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1320 }
1321 return fromHad;
1322 }
1323
1326
1327 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1328 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1329 decltype(thePart->end_vertex()) pVert(nullptr);
1330 if (EndVert != nullptr) {
1331 do {
1332 bool samePart = false;
1333 pVert = nullptr;
1334 auto outgoing = EndVert->particles_out();
1335 auto incoming = EndVert->particles_in();
1336 for (const auto& itrDaug: outgoing) {
1337 if (!itrDaug) continue;
1338 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1339 // brem on generator level for tau
1340 (outgoing.size() == 1 && incoming.size() == 1 &&
1342 itrDaug->pdg_id() == thePart->pdg_id()) {
1343 samePart = true;
1344 pVert = itrDaug->end_vertex();
1345 }
1346 }
1347 if (samePart) EndVert = pVert;
1348 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1349 }
1350 return EndVert;
1351 }
1352
1354
1355 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1356 if (!theVert) return {};
1357 decltype(theVert->particles_out()) finalStatePart;
1358 auto outgoing = theVert->particles_out();
1359 for (const auto& thePart: outgoing) {
1360 if (!thePart) continue;
1361 finalStatePart.push_back(thePart);
1362 if (isStable(thePart)) continue;
1363 V pVert = findSimulatedEndVertex(thePart);
1364 if (pVert == theVert) break; // to prevent Sherpa loop
1365 if (pVert != nullptr) {
1366 auto vecPart = findFinalStateParticles<V>(pVert);
1367 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1368 }
1369 }
1370 return finalStatePart;
1371 }
1372#if !defined(XAOD_ANALYSIS)
1373#include "AtlasHepMC/GenEvent.h"
1374inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1375inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1376
1377#endif
1378}
1379#endif

◆ fractionalCharge() [3/3]

template<class T>
double MC::fractionalCharge ( const T & p)
inline

Definition at line 997 of file HepMCHelpers.h.

1016{
1017 template <class VTX>
1018 auto particles_in (const VTX* p) { return p->particles_in(); }
1019 template <class VTX>
1020 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1021
1022 namespace Pythia8
1023 {
1025 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1026
1027 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1028
1029 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1030 }
1031
1032#include "AtlasPID.h"
1033
1035 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1036
1038 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1039
1041 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1042
1044 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1045
1047 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1048
1050 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1051
1053 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1054
1056 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1057
1059 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1060
1062 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1063
1067 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1068 const auto vertex = p->end_vertex();
1069 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1070 }
1071
1073 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1074
1076 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1077 const int apid = std::abs(p->pdg_id());
1078 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1079 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1080 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1081 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1082 return false;
1083 }
1084
1086
1087 template <class T> T findMother(T thePart) {
1088 auto partOriVert = thePart->production_vertex();
1089 if (!partOriVert) return nullptr;
1090
1091 long partPDG = thePart->pdg_id();
1092 long MotherPDG(0);
1093
1094 auto MothOriVert = partOriVert;
1095 MothOriVert = nullptr;
1096 T theMoth(nullptr);
1097
1098 size_t itr = 0;
1099 do {
1100 if (itr != 0) partOriVert = MothOriVert;
1101 for ( const auto& p : particles_in(partOriVert) ) {
1102 theMoth = p;
1103 if (!theMoth) continue;
1104 MotherPDG = theMoth->pdg_id();
1105 MothOriVert = theMoth->production_vertex();
1106 if (MotherPDG == partPDG) break;
1107 }
1108 itr++;
1109 if (itr > 100) {
1110 break;
1111 }
1112 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1113 MothOriVert != partOriVert);
1114 return theMoth;
1115 }
1116
1118
1119 template <class C, class T> T findMatching(C TruthContainer, T p) {
1120 T ptrPart = nullptr;
1121 if (!p) return ptrPart;
1122 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1123 for (T truthParticle : *TruthContainer) {
1124 if (HepMC::is_sim_descendant(p,truthParticle)) {
1125 ptrPart = truthParticle;
1126 break;
1127 }
1128 }
1129 }
1130 else {
1131 for (T truthParticle : TruthContainer) {
1132 if (HepMC::is_sim_descendant(p,truthParticle)) {
1133 ptrPart = truthParticle;
1134 break;
1135 }
1136 }
1137 }
1138 return ptrPart;
1139 }
1141
1142 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1143 auto prodVtx = thePart->production_vertex();
1144 if (!prodVtx) return;
1145 for (const auto& theMother: prodVtx->particles_in()) {
1146 if (!theMother) continue;
1147 allancestors.insert(theMother);
1148 findParticleAncestors(theMother, allancestors);
1149 }
1150 }
1151
1153
1154 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1155 auto endVtx = thePart->end_vertex();
1156 if (!endVtx) return;
1157 for (const auto& theDaughter: endVtx->particles_out()) {
1158 if (!theDaughter) continue;
1159 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1160 allstabledescendants.insert(theDaughter);
1161 }
1162 findParticleStableDescendants(theDaughter, allstabledescendants);
1163 }
1164 }
1165
1169
1170 template <class T> bool isHardScatteringVertex(T pVert) {
1171 if (pVert == nullptr) return false;
1172 T pV = pVert;
1173 int numOfPartIn(0);
1174 int pdg(0);
1175
1176 do {
1177 pVert = pV;
1178 auto incoming = pVert->particles_in();
1179 numOfPartIn = incoming.size();
1180 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1181 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1182
1183 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1184
1185 if (numOfPartIn == 2) {
1186 auto incoming = pVert->particles_in();
1187 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1188 }
1189 return false;
1190}
1191
1195
1196 template <class T, class U>
1197 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1198 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1199 auto vtx = p->production_vertex();
1200 if (!vtx) return false;
1201 bool fromHad = false;
1202 for ( const auto& parent : particles_in(vtx) ) {
1203 if (!parent) continue;
1204 // should this really go into parton-level territory?
1205 // probably depends where BSM particles are being decayed
1206 fromBSM |= isBSM(parent);
1207 if (!isPhysical(parent)) return false;
1208 fromTau |= isTau(parent);
1209 if (isHadron(parent)&&!isBeam(parent)) {
1210 if (!hadron) hadron = parent; // assumes linear hadron parentage
1211 return true;
1212 }
1213 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1214 }
1215 return fromHad;
1216 }
1217
1220
1221 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1222 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1223 decltype(thePart->end_vertex()) pVert(nullptr);
1224 if (EndVert != nullptr) {
1225 do {
1226 bool samePart = false;
1227 pVert = nullptr;
1228 auto outgoing = EndVert->particles_out();
1229 auto incoming = EndVert->particles_in();
1230 for (const auto& itrDaug: outgoing) {
1231 if (!itrDaug) continue;
1232 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1233 // brem on generator level for tau
1234 (outgoing.size() == 1 && incoming.size() == 1 &&
1236 itrDaug->pdg_id() == thePart->pdg_id()) {
1237 samePart = true;
1238 pVert = itrDaug->end_vertex();
1239 }
1240 }
1241 if (samePart) EndVert = pVert;
1242 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1243 }
1244 return EndVert;
1245 }
1246
1248
1249 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1250 if (!theVert) return {};
1251 decltype(theVert->particles_out()) finalStatePart;
1252 auto outgoing = theVert->particles_out();
1253 for (const auto& thePart: outgoing) {
1254 if (!thePart) continue;
1255 finalStatePart.push_back(thePart);
1256 if (isStable(thePart)) continue;
1257 V pVert = findSimulatedEndVertex(thePart);
1258 if (pVert == theVert) break; // to prevent Sherpa loop
1259 if (pVert != nullptr) {
1260 auto vecPart = findFinalStateParticles<V>(pVert);
1261 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1262 }
1263 }
1264 return finalStatePart;
1265 }
1266#if !defined(XAOD_ANALYSIS)
1267#include "AtlasHepMC/GenEvent.h"
1268inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1269inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1270
1271#endif
1272}
1273#endif

◆ GeVToMeV()

void MC::GeVToMeV ( HepMC::GenEvent * evt)
inline

Definition at line 272 of file HepMCHelpers.h.

272{ for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}

◆ hasBottom()

template<class T>
bool MC::hasBottom ( const T & p)
inline

Definition at line 739 of file HepMCHelpers.h.

758{
759 template <class VTX>
760 auto particles_in (const VTX* p) { return p->particles_in(); }
761 template <class VTX>
762 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
763
764 namespace Pythia8
765 {
767 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
768
769 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
770
771 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
772 }
773
774#include "AtlasPID.h"
775
777 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
778
780 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
781
783 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
784
786 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
787
789 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
790
792 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
793
795 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
796
798 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
799
801 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
802
804 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
805
809 template <class T> inline bool isStableOrSimDecayed(const T& p) {
810 const auto vertex = p->end_vertex();
811 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
812 }
813
815 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
816
818 template <class T> inline bool isSpecialNonInteracting(const T& p) {
819 const int apid = std::abs(p->pdg_id());
820 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
821 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
822 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
823 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
824 return false;
825 }
826
828
829 template <class T> T findMother(T thePart) {
830 auto partOriVert = thePart->production_vertex();
831 if (!partOriVert) return nullptr;
832
833 long partPDG = thePart->pdg_id();
834 long MotherPDG(0);
835
836 auto MothOriVert = partOriVert;
837 MothOriVert = nullptr;
838 T theMoth(nullptr);
839
840 size_t itr = 0;
841 do {
842 if (itr != 0) partOriVert = MothOriVert;
843 for ( const auto& p : particles_in(partOriVert) ) {
844 theMoth = p;
845 if (!theMoth) continue;
846 MotherPDG = theMoth->pdg_id();
847 MothOriVert = theMoth->production_vertex();
848 if (MotherPDG == partPDG) break;
849 }
850 itr++;
851 if (itr > 100) {
852 break;
853 }
854 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
855 MothOriVert != partOriVert);
856 return theMoth;
857 }
858
860
861 template <class C, class T> T findMatching(C TruthContainer, T p) {
862 T ptrPart = nullptr;
863 if (!p) return ptrPart;
864 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
865 for (T truthParticle : *TruthContainer) {
866 if (HepMC::is_sim_descendant(p,truthParticle)) {
867 ptrPart = truthParticle;
868 break;
869 }
870 }
871 }
872 else {
873 for (T truthParticle : TruthContainer) {
874 if (HepMC::is_sim_descendant(p,truthParticle)) {
875 ptrPart = truthParticle;
876 break;
877 }
878 }
879 }
880 return ptrPart;
881 }
883
884 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
885 auto prodVtx = thePart->production_vertex();
886 if (!prodVtx) return;
887 for (const auto& theMother: prodVtx->particles_in()) {
888 if (!theMother) continue;
889 allancestors.insert(theMother);
890 findParticleAncestors(theMother, allancestors);
891 }
892 }
893
895
896 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
897 auto endVtx = thePart->end_vertex();
898 if (!endVtx) return;
899 for (const auto& theDaughter: endVtx->particles_out()) {
900 if (!theDaughter) continue;
901 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
902 allstabledescendants.insert(theDaughter);
903 }
904 findParticleStableDescendants(theDaughter, allstabledescendants);
905 }
906 }
907
911
912 template <class T> bool isHardScatteringVertex(T pVert) {
913 if (pVert == nullptr) return false;
914 T pV = pVert;
915 int numOfPartIn(0);
916 int pdg(0);
917
918 do {
919 pVert = pV;
920 auto incoming = pVert->particles_in();
921 numOfPartIn = incoming.size();
922 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
923 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
924
925 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
926
927 if (numOfPartIn == 2) {
928 auto incoming = pVert->particles_in();
929 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
930 }
931 return false;
932}
933
937
938 template <class T, class U>
939 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
940 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
941 auto vtx = p->production_vertex();
942 if (!vtx) return false;
943 bool fromHad = false;
944 for ( const auto& parent : particles_in(vtx) ) {
945 if (!parent) continue;
946 // should this really go into parton-level territory?
947 // probably depends where BSM particles are being decayed
948 fromBSM |= isBSM(parent);
949 if (!isPhysical(parent)) return false;
950 fromTau |= isTau(parent);
951 if (isHadron(parent)&&!isBeam(parent)) {
952 if (!hadron) hadron = parent; // assumes linear hadron parentage
953 return true;
954 }
955 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
956 }
957 return fromHad;
958 }
959
962
963 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
964 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
965 decltype(thePart->end_vertex()) pVert(nullptr);
966 if (EndVert != nullptr) {
967 do {
968 bool samePart = false;
969 pVert = nullptr;
970 auto outgoing = EndVert->particles_out();
971 auto incoming = EndVert->particles_in();
972 for (const auto& itrDaug: outgoing) {
973 if (!itrDaug) continue;
974 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
975 // brem on generator level for tau
976 (outgoing.size() == 1 && incoming.size() == 1 &&
978 itrDaug->pdg_id() == thePart->pdg_id()) {
979 samePart = true;
980 pVert = itrDaug->end_vertex();
981 }
982 }
983 if (samePart) EndVert = pVert;
984 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
985 }
986 return EndVert;
987 }
988
990
991 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
992 if (!theVert) return {};
993 decltype(theVert->particles_out()) finalStatePart;
994 auto outgoing = theVert->particles_out();
995 for (const auto& thePart: outgoing) {
996 if (!thePart) continue;
997 finalStatePart.push_back(thePart);
998 if (isStable(thePart)) continue;
999 V pVert = findSimulatedEndVertex(thePart);
1000 if (pVert == theVert) break; // to prevent Sherpa loop
1001 if (pVert != nullptr) {
1002 auto vecPart = findFinalStateParticles<V>(pVert);
1003 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1004 }
1005 }
1006 return finalStatePart;
1007 }
1008#if !defined(XAOD_ANALYSIS)
1009#include "AtlasHepMC/GenEvent.h"
1010inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1011inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1012
1013#endif
1014}
1015#endif

◆ hasCharm()

template<class T>
bool MC::hasCharm ( const T & p)
inline

Definition at line 738 of file HepMCHelpers.h.

757{
758 template <class VTX>
759 auto particles_in (const VTX* p) { return p->particles_in(); }
760 template <class VTX>
761 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
762
763 namespace Pythia8
764 {
766 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
767
768 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
769
770 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
771 }
772
773#include "AtlasPID.h"
774
776 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
777
779 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
780
782 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
783
785 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
786
788 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
789
791 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
792
794 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
795
797 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
798
800 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
801
803 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
804
808 template <class T> inline bool isStableOrSimDecayed(const T& p) {
809 const auto vertex = p->end_vertex();
810 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
811 }
812
814 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
815
817 template <class T> inline bool isSpecialNonInteracting(const T& p) {
818 const int apid = std::abs(p->pdg_id());
819 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
820 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
821 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
822 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
823 return false;
824 }
825
827
828 template <class T> T findMother(T thePart) {
829 auto partOriVert = thePart->production_vertex();
830 if (!partOriVert) return nullptr;
831
832 long partPDG = thePart->pdg_id();
833 long MotherPDG(0);
834
835 auto MothOriVert = partOriVert;
836 MothOriVert = nullptr;
837 T theMoth(nullptr);
838
839 size_t itr = 0;
840 do {
841 if (itr != 0) partOriVert = MothOriVert;
842 for ( const auto& p : particles_in(partOriVert) ) {
843 theMoth = p;
844 if (!theMoth) continue;
845 MotherPDG = theMoth->pdg_id();
846 MothOriVert = theMoth->production_vertex();
847 if (MotherPDG == partPDG) break;
848 }
849 itr++;
850 if (itr > 100) {
851 break;
852 }
853 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
854 MothOriVert != partOriVert);
855 return theMoth;
856 }
857
859
860 template <class C, class T> T findMatching(C TruthContainer, T p) {
861 T ptrPart = nullptr;
862 if (!p) return ptrPart;
863 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
864 for (T truthParticle : *TruthContainer) {
865 if (HepMC::is_sim_descendant(p,truthParticle)) {
866 ptrPart = truthParticle;
867 break;
868 }
869 }
870 }
871 else {
872 for (T truthParticle : TruthContainer) {
873 if (HepMC::is_sim_descendant(p,truthParticle)) {
874 ptrPart = truthParticle;
875 break;
876 }
877 }
878 }
879 return ptrPart;
880 }
882
883 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
884 auto prodVtx = thePart->production_vertex();
885 if (!prodVtx) return;
886 for (const auto& theMother: prodVtx->particles_in()) {
887 if (!theMother) continue;
888 allancestors.insert(theMother);
889 findParticleAncestors(theMother, allancestors);
890 }
891 }
892
894
895 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
896 auto endVtx = thePart->end_vertex();
897 if (!endVtx) return;
898 for (const auto& theDaughter: endVtx->particles_out()) {
899 if (!theDaughter) continue;
900 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
901 allstabledescendants.insert(theDaughter);
902 }
903 findParticleStableDescendants(theDaughter, allstabledescendants);
904 }
905 }
906
910
911 template <class T> bool isHardScatteringVertex(T pVert) {
912 if (pVert == nullptr) return false;
913 T pV = pVert;
914 int numOfPartIn(0);
915 int pdg(0);
916
917 do {
918 pVert = pV;
919 auto incoming = pVert->particles_in();
920 numOfPartIn = incoming.size();
921 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
922 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
923
924 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
925
926 if (numOfPartIn == 2) {
927 auto incoming = pVert->particles_in();
928 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
929 }
930 return false;
931}
932
936
937 template <class T, class U>
938 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
939 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
940 auto vtx = p->production_vertex();
941 if (!vtx) return false;
942 bool fromHad = false;
943 for ( const auto& parent : particles_in(vtx) ) {
944 if (!parent) continue;
945 // should this really go into parton-level territory?
946 // probably depends where BSM particles are being decayed
947 fromBSM |= isBSM(parent);
948 if (!isPhysical(parent)) return false;
949 fromTau |= isTau(parent);
950 if (isHadron(parent)&&!isBeam(parent)) {
951 if (!hadron) hadron = parent; // assumes linear hadron parentage
952 return true;
953 }
954 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
955 }
956 return fromHad;
957 }
958
961
962 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
963 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
964 decltype(thePart->end_vertex()) pVert(nullptr);
965 if (EndVert != nullptr) {
966 do {
967 bool samePart = false;
968 pVert = nullptr;
969 auto outgoing = EndVert->particles_out();
970 auto incoming = EndVert->particles_in();
971 for (const auto& itrDaug: outgoing) {
972 if (!itrDaug) continue;
973 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
974 // brem on generator level for tau
975 (outgoing.size() == 1 && incoming.size() == 1 &&
977 itrDaug->pdg_id() == thePart->pdg_id()) {
978 samePart = true;
979 pVert = itrDaug->end_vertex();
980 }
981 }
982 if (samePart) EndVert = pVert;
983 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
984 }
985 return EndVert;
986 }
987
989
990 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
991 if (!theVert) return {};
992 decltype(theVert->particles_out()) finalStatePart;
993 auto outgoing = theVert->particles_out();
994 for (const auto& thePart: outgoing) {
995 if (!thePart) continue;
996 finalStatePart.push_back(thePart);
997 if (isStable(thePart)) continue;
998 V pVert = findSimulatedEndVertex(thePart);
999 if (pVert == theVert) break; // to prevent Sherpa loop
1000 if (pVert != nullptr) {
1001 auto vecPart = findFinalStateParticles<V>(pVert);
1002 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1003 }
1004 }
1005 return finalStatePart;
1006 }
1007#if !defined(XAOD_ANALYSIS)
1008#include "AtlasHepMC/GenEvent.h"
1009inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1010inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1011
1012#endif
1013}
1014#endif

◆ hasQuark() [1/3]

template<>
bool MC::hasQuark ( const DecodedPID & p,
const int & q )
inline

Definition at line 717 of file HepMCHelpers.h.

736{
737 template <class VTX>
738 auto particles_in (const VTX* p) { return p->particles_in(); }
739 template <class VTX>
740 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
741
742 namespace Pythia8
743 {
745 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
746
747 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
748
749 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
750 }
751
752#include "AtlasPID.h"
753
755 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
756
758 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
759
761 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
762
764 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
765
767 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
768
770 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
771
773 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
774
776 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
777
779 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
780
782 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
783
787 template <class T> inline bool isStableOrSimDecayed(const T& p) {
788 const auto vertex = p->end_vertex();
789 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
790 }
791
793 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
794
796 template <class T> inline bool isSpecialNonInteracting(const T& p) {
797 const int apid = std::abs(p->pdg_id());
798 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
799 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
800 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
801 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
802 return false;
803 }
804
806
807 template <class T> T findMother(T thePart) {
808 auto partOriVert = thePart->production_vertex();
809 if (!partOriVert) return nullptr;
810
811 long partPDG = thePart->pdg_id();
812 long MotherPDG(0);
813
814 auto MothOriVert = partOriVert;
815 MothOriVert = nullptr;
816 T theMoth(nullptr);
817
818 size_t itr = 0;
819 do {
820 if (itr != 0) partOriVert = MothOriVert;
821 for ( const auto& p : particles_in(partOriVert) ) {
822 theMoth = p;
823 if (!theMoth) continue;
824 MotherPDG = theMoth->pdg_id();
825 MothOriVert = theMoth->production_vertex();
826 if (MotherPDG == partPDG) break;
827 }
828 itr++;
829 if (itr > 100) {
830 break;
831 }
832 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
833 MothOriVert != partOriVert);
834 return theMoth;
835 }
836
838
839 template <class C, class T> T findMatching(C TruthContainer, T p) {
840 T ptrPart = nullptr;
841 if (!p) return ptrPart;
842 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
843 for (T truthParticle : *TruthContainer) {
844 if (HepMC::is_sim_descendant(p,truthParticle)) {
845 ptrPart = truthParticle;
846 break;
847 }
848 }
849 }
850 else {
851 for (T truthParticle : TruthContainer) {
852 if (HepMC::is_sim_descendant(p,truthParticle)) {
853 ptrPart = truthParticle;
854 break;
855 }
856 }
857 }
858 return ptrPart;
859 }
861
862 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
863 auto prodVtx = thePart->production_vertex();
864 if (!prodVtx) return;
865 for (const auto& theMother: prodVtx->particles_in()) {
866 if (!theMother) continue;
867 allancestors.insert(theMother);
868 findParticleAncestors(theMother, allancestors);
869 }
870 }
871
873
874 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
875 auto endVtx = thePart->end_vertex();
876 if (!endVtx) return;
877 for (const auto& theDaughter: endVtx->particles_out()) {
878 if (!theDaughter) continue;
879 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
880 allstabledescendants.insert(theDaughter);
881 }
882 findParticleStableDescendants(theDaughter, allstabledescendants);
883 }
884 }
885
889
890 template <class T> bool isHardScatteringVertex(T pVert) {
891 if (pVert == nullptr) return false;
892 T pV = pVert;
893 int numOfPartIn(0);
894 int pdg(0);
895
896 do {
897 pVert = pV;
898 auto incoming = pVert->particles_in();
899 numOfPartIn = incoming.size();
900 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
901 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
902
903 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
904
905 if (numOfPartIn == 2) {
906 auto incoming = pVert->particles_in();
907 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
908 }
909 return false;
910}
911
915
916 template <class T, class U>
917 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
918 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
919 auto vtx = p->production_vertex();
920 if (!vtx) return false;
921 bool fromHad = false;
922 for ( const auto& parent : particles_in(vtx) ) {
923 if (!parent) continue;
924 // should this really go into parton-level territory?
925 // probably depends where BSM particles are being decayed
926 fromBSM |= isBSM(parent);
927 if (!isPhysical(parent)) return false;
928 fromTau |= isTau(parent);
929 if (isHadron(parent)&&!isBeam(parent)) {
930 if (!hadron) hadron = parent; // assumes linear hadron parentage
931 return true;
932 }
933 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
934 }
935 return fromHad;
936 }
937
940
941 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
942 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
943 decltype(thePart->end_vertex()) pVert(nullptr);
944 if (EndVert != nullptr) {
945 do {
946 bool samePart = false;
947 pVert = nullptr;
948 auto outgoing = EndVert->particles_out();
949 auto incoming = EndVert->particles_in();
950 for (const auto& itrDaug: outgoing) {
951 if (!itrDaug) continue;
952 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
953 // brem on generator level for tau
954 (outgoing.size() == 1 && incoming.size() == 1 &&
956 itrDaug->pdg_id() == thePart->pdg_id()) {
957 samePart = true;
958 pVert = itrDaug->end_vertex();
959 }
960 }
961 if (samePart) EndVert = pVert;
962 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
963 }
964 return EndVert;
965 }
966
968
969 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
970 if (!theVert) return {};
971 decltype(theVert->particles_out()) finalStatePart;
972 auto outgoing = theVert->particles_out();
973 for (const auto& thePart: outgoing) {
974 if (!thePart) continue;
975 finalStatePart.push_back(thePart);
976 if (isStable(thePart)) continue;
977 V pVert = findSimulatedEndVertex(thePart);
978 if (pVert == theVert) break; // to prevent Sherpa loop
979 if (pVert != nullptr) {
980 auto vecPart = findFinalStateParticles<V>(pVert);
981 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
982 }
983 }
984 return finalStatePart;
985 }
986#if !defined(XAOD_ANALYSIS)
987#include "AtlasHepMC/GenEvent.h"
988inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
989inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
990
991#endif
992}
993#endif

◆ hasQuark() [2/3]

template<>
bool MC::hasQuark ( const int & p,
const int & q )
inline

Definition at line 735 of file HepMCHelpers.h.

754{
755 template <class VTX>
756 auto particles_in (const VTX* p) { return p->particles_in(); }
757 template <class VTX>
758 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
759
760 namespace Pythia8
761 {
763 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
764
765 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
766
767 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
768 }
769
770#include "AtlasPID.h"
771
773 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
774
776 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
777
779 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
780
782 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
783
785 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
786
788 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
789
791 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
792
794 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
795
797 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
798
800 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
801
805 template <class T> inline bool isStableOrSimDecayed(const T& p) {
806 const auto vertex = p->end_vertex();
807 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
808 }
809
811 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
812
814 template <class T> inline bool isSpecialNonInteracting(const T& p) {
815 const int apid = std::abs(p->pdg_id());
816 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
817 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
818 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
819 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
820 return false;
821 }
822
824
825 template <class T> T findMother(T thePart) {
826 auto partOriVert = thePart->production_vertex();
827 if (!partOriVert) return nullptr;
828
829 long partPDG = thePart->pdg_id();
830 long MotherPDG(0);
831
832 auto MothOriVert = partOriVert;
833 MothOriVert = nullptr;
834 T theMoth(nullptr);
835
836 size_t itr = 0;
837 do {
838 if (itr != 0) partOriVert = MothOriVert;
839 for ( const auto& p : particles_in(partOriVert) ) {
840 theMoth = p;
841 if (!theMoth) continue;
842 MotherPDG = theMoth->pdg_id();
843 MothOriVert = theMoth->production_vertex();
844 if (MotherPDG == partPDG) break;
845 }
846 itr++;
847 if (itr > 100) {
848 break;
849 }
850 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
851 MothOriVert != partOriVert);
852 return theMoth;
853 }
854
856
857 template <class C, class T> T findMatching(C TruthContainer, T p) {
858 T ptrPart = nullptr;
859 if (!p) return ptrPart;
860 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
861 for (T truthParticle : *TruthContainer) {
862 if (HepMC::is_sim_descendant(p,truthParticle)) {
863 ptrPart = truthParticle;
864 break;
865 }
866 }
867 }
868 else {
869 for (T truthParticle : TruthContainer) {
870 if (HepMC::is_sim_descendant(p,truthParticle)) {
871 ptrPart = truthParticle;
872 break;
873 }
874 }
875 }
876 return ptrPart;
877 }
879
880 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
881 auto prodVtx = thePart->production_vertex();
882 if (!prodVtx) return;
883 for (const auto& theMother: prodVtx->particles_in()) {
884 if (!theMother) continue;
885 allancestors.insert(theMother);
886 findParticleAncestors(theMother, allancestors);
887 }
888 }
889
891
892 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
893 auto endVtx = thePart->end_vertex();
894 if (!endVtx) return;
895 for (const auto& theDaughter: endVtx->particles_out()) {
896 if (!theDaughter) continue;
897 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
898 allstabledescendants.insert(theDaughter);
899 }
900 findParticleStableDescendants(theDaughter, allstabledescendants);
901 }
902 }
903
907
908 template <class T> bool isHardScatteringVertex(T pVert) {
909 if (pVert == nullptr) return false;
910 T pV = pVert;
911 int numOfPartIn(0);
912 int pdg(0);
913
914 do {
915 pVert = pV;
916 auto incoming = pVert->particles_in();
917 numOfPartIn = incoming.size();
918 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
919 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
920
921 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
922
923 if (numOfPartIn == 2) {
924 auto incoming = pVert->particles_in();
925 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
926 }
927 return false;
928}
929
933
934 template <class T, class U>
935 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
936 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
937 auto vtx = p->production_vertex();
938 if (!vtx) return false;
939 bool fromHad = false;
940 for ( const auto& parent : particles_in(vtx) ) {
941 if (!parent) continue;
942 // should this really go into parton-level territory?
943 // probably depends where BSM particles are being decayed
944 fromBSM |= isBSM(parent);
945 if (!isPhysical(parent)) return false;
946 fromTau |= isTau(parent);
947 if (isHadron(parent)&&!isBeam(parent)) {
948 if (!hadron) hadron = parent; // assumes linear hadron parentage
949 return true;
950 }
951 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
952 }
953 return fromHad;
954 }
955
958
959 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
960 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
961 decltype(thePart->end_vertex()) pVert(nullptr);
962 if (EndVert != nullptr) {
963 do {
964 bool samePart = false;
965 pVert = nullptr;
966 auto outgoing = EndVert->particles_out();
967 auto incoming = EndVert->particles_in();
968 for (const auto& itrDaug: outgoing) {
969 if (!itrDaug) continue;
970 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
971 // brem on generator level for tau
972 (outgoing.size() == 1 && incoming.size() == 1 &&
974 itrDaug->pdg_id() == thePart->pdg_id()) {
975 samePart = true;
976 pVert = itrDaug->end_vertex();
977 }
978 }
979 if (samePart) EndVert = pVert;
980 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
981 }
982 return EndVert;
983 }
984
986
987 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
988 if (!theVert) return {};
989 decltype(theVert->particles_out()) finalStatePart;
990 auto outgoing = theVert->particles_out();
991 for (const auto& thePart: outgoing) {
992 if (!thePart) continue;
993 finalStatePart.push_back(thePart);
994 if (isStable(thePart)) continue;
995 V pVert = findSimulatedEndVertex(thePart);
996 if (pVert == theVert) break; // to prevent Sherpa loop
997 if (pVert != nullptr) {
998 auto vecPart = findFinalStateParticles<V>(pVert);
999 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1000 }
1001 }
1002 return finalStatePart;
1003 }
1004#if !defined(XAOD_ANALYSIS)
1005#include "AtlasHepMC/GenEvent.h"
1006inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1007inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1008
1009#endif
1010}
1011#endif

◆ hasQuark() [3/3]

template<class T>
bool MC::hasQuark ( const T & p,
const int & q )
inline

◆ hasSquark() [1/3]

template<>
bool MC::hasSquark ( const DecodedPID & p,
const int & q )
inline

Definition at line 612 of file HepMCHelpers.h.

631{
632 template <class VTX>
633 auto particles_in (const VTX* p) { return p->particles_in(); }
634 template <class VTX>
635 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
636
637 namespace Pythia8
638 {
640 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
641
642 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
643
644 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
645 }
646
647#include "AtlasPID.h"
648
650 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
651
653 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
654
656 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
657
659 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
660
662 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
663
665 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
666
668 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
669
671 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
672
674 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
675
677 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
678
682 template <class T> inline bool isStableOrSimDecayed(const T& p) {
683 const auto vertex = p->end_vertex();
684 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
685 }
686
688 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
689
691 template <class T> inline bool isSpecialNonInteracting(const T& p) {
692 const int apid = std::abs(p->pdg_id());
693 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
694 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
695 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
696 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
697 return false;
698 }
699
701
702 template <class T> T findMother(T thePart) {
703 auto partOriVert = thePart->production_vertex();
704 if (!partOriVert) return nullptr;
705
706 long partPDG = thePart->pdg_id();
707 long MotherPDG(0);
708
709 auto MothOriVert = partOriVert;
710 MothOriVert = nullptr;
711 T theMoth(nullptr);
712
713 size_t itr = 0;
714 do {
715 if (itr != 0) partOriVert = MothOriVert;
716 for ( const auto& p : particles_in(partOriVert) ) {
717 theMoth = p;
718 if (!theMoth) continue;
719 MotherPDG = theMoth->pdg_id();
720 MothOriVert = theMoth->production_vertex();
721 if (MotherPDG == partPDG) break;
722 }
723 itr++;
724 if (itr > 100) {
725 break;
726 }
727 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
728 MothOriVert != partOriVert);
729 return theMoth;
730 }
731
733
734 template <class C, class T> T findMatching(C TruthContainer, T p) {
735 T ptrPart = nullptr;
736 if (!p) return ptrPart;
737 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
738 for (T truthParticle : *TruthContainer) {
739 if (HepMC::is_sim_descendant(p,truthParticle)) {
740 ptrPart = truthParticle;
741 break;
742 }
743 }
744 }
745 else {
746 for (T truthParticle : TruthContainer) {
747 if (HepMC::is_sim_descendant(p,truthParticle)) {
748 ptrPart = truthParticle;
749 break;
750 }
751 }
752 }
753 return ptrPart;
754 }
756
757 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
758 auto prodVtx = thePart->production_vertex();
759 if (!prodVtx) return;
760 for (const auto& theMother: prodVtx->particles_in()) {
761 if (!theMother) continue;
762 allancestors.insert(theMother);
763 findParticleAncestors(theMother, allancestors);
764 }
765 }
766
768
769 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
770 auto endVtx = thePart->end_vertex();
771 if (!endVtx) return;
772 for (const auto& theDaughter: endVtx->particles_out()) {
773 if (!theDaughter) continue;
774 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
775 allstabledescendants.insert(theDaughter);
776 }
777 findParticleStableDescendants(theDaughter, allstabledescendants);
778 }
779 }
780
784
785 template <class T> bool isHardScatteringVertex(T pVert) {
786 if (pVert == nullptr) return false;
787 T pV = pVert;
788 int numOfPartIn(0);
789 int pdg(0);
790
791 do {
792 pVert = pV;
793 auto incoming = pVert->particles_in();
794 numOfPartIn = incoming.size();
795 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
796 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
797
798 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
799
800 if (numOfPartIn == 2) {
801 auto incoming = pVert->particles_in();
802 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
803 }
804 return false;
805}
806
810
811 template <class T, class U>
812 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
813 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
814 auto vtx = p->production_vertex();
815 if (!vtx) return false;
816 bool fromHad = false;
817 for ( const auto& parent : particles_in(vtx) ) {
818 if (!parent) continue;
819 // should this really go into parton-level territory?
820 // probably depends where BSM particles are being decayed
821 fromBSM |= isBSM(parent);
822 if (!isPhysical(parent)) return false;
823 fromTau |= isTau(parent);
824 if (isHadron(parent)&&!isBeam(parent)) {
825 if (!hadron) hadron = parent; // assumes linear hadron parentage
826 return true;
827 }
828 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
829 }
830 return fromHad;
831 }
832
835
836 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
837 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
838 decltype(thePart->end_vertex()) pVert(nullptr);
839 if (EndVert != nullptr) {
840 do {
841 bool samePart = false;
842 pVert = nullptr;
843 auto outgoing = EndVert->particles_out();
844 auto incoming = EndVert->particles_in();
845 for (const auto& itrDaug: outgoing) {
846 if (!itrDaug) continue;
847 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
848 // brem on generator level for tau
849 (outgoing.size() == 1 && incoming.size() == 1 &&
851 itrDaug->pdg_id() == thePart->pdg_id()) {
852 samePart = true;
853 pVert = itrDaug->end_vertex();
854 }
855 }
856 if (samePart) EndVert = pVert;
857 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
858 }
859 return EndVert;
860 }
861
863
864 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
865 if (!theVert) return {};
866 decltype(theVert->particles_out()) finalStatePart;
867 auto outgoing = theVert->particles_out();
868 for (const auto& thePart: outgoing) {
869 if (!thePart) continue;
870 finalStatePart.push_back(thePart);
871 if (isStable(thePart)) continue;
872 V pVert = findSimulatedEndVertex(thePart);
873 if (pVert == theVert) break; // to prevent Sherpa loop
874 if (pVert != nullptr) {
875 auto vecPart = findFinalStateParticles<V>(pVert);
876 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
877 }
878 }
879 return finalStatePart;
880 }
881#if !defined(XAOD_ANALYSIS)
882#include "AtlasHepMC/GenEvent.h"
883inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
884inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
885
886#endif
887}
888#endif

◆ hasSquark() [2/3]

template<>
bool MC::hasSquark ( const int & p,
const int & q )
inline

Definition at line 619 of file HepMCHelpers.h.

638{
639 template <class VTX>
640 auto particles_in (const VTX* p) { return p->particles_in(); }
641 template <class VTX>
642 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
643
644 namespace Pythia8
645 {
647 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
648
649 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
650
651 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
652 }
653
654#include "AtlasPID.h"
655
657 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
658
660 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
661
663 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
664
666 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
667
669 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
670
672 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
673
675 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
676
678 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
679
681 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
682
684 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
685
689 template <class T> inline bool isStableOrSimDecayed(const T& p) {
690 const auto vertex = p->end_vertex();
691 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
692 }
693
695 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
696
698 template <class T> inline bool isSpecialNonInteracting(const T& p) {
699 const int apid = std::abs(p->pdg_id());
700 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
701 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
702 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
703 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
704 return false;
705 }
706
708
709 template <class T> T findMother(T thePart) {
710 auto partOriVert = thePart->production_vertex();
711 if (!partOriVert) return nullptr;
712
713 long partPDG = thePart->pdg_id();
714 long MotherPDG(0);
715
716 auto MothOriVert = partOriVert;
717 MothOriVert = nullptr;
718 T theMoth(nullptr);
719
720 size_t itr = 0;
721 do {
722 if (itr != 0) partOriVert = MothOriVert;
723 for ( const auto& p : particles_in(partOriVert) ) {
724 theMoth = p;
725 if (!theMoth) continue;
726 MotherPDG = theMoth->pdg_id();
727 MothOriVert = theMoth->production_vertex();
728 if (MotherPDG == partPDG) break;
729 }
730 itr++;
731 if (itr > 100) {
732 break;
733 }
734 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
735 MothOriVert != partOriVert);
736 return theMoth;
737 }
738
740
741 template <class C, class T> T findMatching(C TruthContainer, T p) {
742 T ptrPart = nullptr;
743 if (!p) return ptrPart;
744 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
745 for (T truthParticle : *TruthContainer) {
746 if (HepMC::is_sim_descendant(p,truthParticle)) {
747 ptrPart = truthParticle;
748 break;
749 }
750 }
751 }
752 else {
753 for (T truthParticle : TruthContainer) {
754 if (HepMC::is_sim_descendant(p,truthParticle)) {
755 ptrPart = truthParticle;
756 break;
757 }
758 }
759 }
760 return ptrPart;
761 }
763
764 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
765 auto prodVtx = thePart->production_vertex();
766 if (!prodVtx) return;
767 for (const auto& theMother: prodVtx->particles_in()) {
768 if (!theMother) continue;
769 allancestors.insert(theMother);
770 findParticleAncestors(theMother, allancestors);
771 }
772 }
773
775
776 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
777 auto endVtx = thePart->end_vertex();
778 if (!endVtx) return;
779 for (const auto& theDaughter: endVtx->particles_out()) {
780 if (!theDaughter) continue;
781 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
782 allstabledescendants.insert(theDaughter);
783 }
784 findParticleStableDescendants(theDaughter, allstabledescendants);
785 }
786 }
787
791
792 template <class T> bool isHardScatteringVertex(T pVert) {
793 if (pVert == nullptr) return false;
794 T pV = pVert;
795 int numOfPartIn(0);
796 int pdg(0);
797
798 do {
799 pVert = pV;
800 auto incoming = pVert->particles_in();
801 numOfPartIn = incoming.size();
802 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
803 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
804
805 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
806
807 if (numOfPartIn == 2) {
808 auto incoming = pVert->particles_in();
809 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
810 }
811 return false;
812}
813
817
818 template <class T, class U>
819 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
820 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
821 auto vtx = p->production_vertex();
822 if (!vtx) return false;
823 bool fromHad = false;
824 for ( const auto& parent : particles_in(vtx) ) {
825 if (!parent) continue;
826 // should this really go into parton-level territory?
827 // probably depends where BSM particles are being decayed
828 fromBSM |= isBSM(parent);
829 if (!isPhysical(parent)) return false;
830 fromTau |= isTau(parent);
831 if (isHadron(parent)&&!isBeam(parent)) {
832 if (!hadron) hadron = parent; // assumes linear hadron parentage
833 return true;
834 }
835 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
836 }
837 return fromHad;
838 }
839
842
843 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
844 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
845 decltype(thePart->end_vertex()) pVert(nullptr);
846 if (EndVert != nullptr) {
847 do {
848 bool samePart = false;
849 pVert = nullptr;
850 auto outgoing = EndVert->particles_out();
851 auto incoming = EndVert->particles_in();
852 for (const auto& itrDaug: outgoing) {
853 if (!itrDaug) continue;
854 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
855 // brem on generator level for tau
856 (outgoing.size() == 1 && incoming.size() == 1 &&
858 itrDaug->pdg_id() == thePart->pdg_id()) {
859 samePart = true;
860 pVert = itrDaug->end_vertex();
861 }
862 }
863 if (samePart) EndVert = pVert;
864 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
865 }
866 return EndVert;
867 }
868
870
871 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
872 if (!theVert) return {};
873 decltype(theVert->particles_out()) finalStatePart;
874 auto outgoing = theVert->particles_out();
875 for (const auto& thePart: outgoing) {
876 if (!thePart) continue;
877 finalStatePart.push_back(thePart);
878 if (isStable(thePart)) continue;
879 V pVert = findSimulatedEndVertex(thePart);
880 if (pVert == theVert) break; // to prevent Sherpa loop
881 if (pVert != nullptr) {
882 auto vecPart = findFinalStateParticles<V>(pVert);
883 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
884 }
885 }
886 return finalStatePart;
887 }
888#if !defined(XAOD_ANALYSIS)
889#include "AtlasHepMC/GenEvent.h"
890inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
891inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
892
893#endif
894}
895#endif

◆ hasSquark() [3/3]

template<class T>
bool MC::hasSquark ( const T & p,
const int & q )
inline

Definition at line 611 of file HepMCHelpers.h.

630{
631 template <class VTX>
632 auto particles_in (const VTX* p) { return p->particles_in(); }
633 template <class VTX>
634 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
635
636 namespace Pythia8
637 {
639 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
640
641 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
642
643 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
644 }
645
646#include "AtlasPID.h"
647
649 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
650
652 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
653
655 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
656
658 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
659
661 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
662
664 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
665
667 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
668
670 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
671
673 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
674
676 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
677
681 template <class T> inline bool isStableOrSimDecayed(const T& p) {
682 const auto vertex = p->end_vertex();
683 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
684 }
685
687 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
688
690 template <class T> inline bool isSpecialNonInteracting(const T& p) {
691 const int apid = std::abs(p->pdg_id());
692 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
693 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
694 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
695 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
696 return false;
697 }
698
700
701 template <class T> T findMother(T thePart) {
702 auto partOriVert = thePart->production_vertex();
703 if (!partOriVert) return nullptr;
704
705 long partPDG = thePart->pdg_id();
706 long MotherPDG(0);
707
708 auto MothOriVert = partOriVert;
709 MothOriVert = nullptr;
710 T theMoth(nullptr);
711
712 size_t itr = 0;
713 do {
714 if (itr != 0) partOriVert = MothOriVert;
715 for ( const auto& p : particles_in(partOriVert) ) {
716 theMoth = p;
717 if (!theMoth) continue;
718 MotherPDG = theMoth->pdg_id();
719 MothOriVert = theMoth->production_vertex();
720 if (MotherPDG == partPDG) break;
721 }
722 itr++;
723 if (itr > 100) {
724 break;
725 }
726 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
727 MothOriVert != partOriVert);
728 return theMoth;
729 }
730
732
733 template <class C, class T> T findMatching(C TruthContainer, T p) {
734 T ptrPart = nullptr;
735 if (!p) return ptrPart;
736 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
737 for (T truthParticle : *TruthContainer) {
738 if (HepMC::is_sim_descendant(p,truthParticle)) {
739 ptrPart = truthParticle;
740 break;
741 }
742 }
743 }
744 else {
745 for (T truthParticle : TruthContainer) {
746 if (HepMC::is_sim_descendant(p,truthParticle)) {
747 ptrPart = truthParticle;
748 break;
749 }
750 }
751 }
752 return ptrPart;
753 }
755
756 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
757 auto prodVtx = thePart->production_vertex();
758 if (!prodVtx) return;
759 for (const auto& theMother: prodVtx->particles_in()) {
760 if (!theMother) continue;
761 allancestors.insert(theMother);
762 findParticleAncestors(theMother, allancestors);
763 }
764 }
765
767
768 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
769 auto endVtx = thePart->end_vertex();
770 if (!endVtx) return;
771 for (const auto& theDaughter: endVtx->particles_out()) {
772 if (!theDaughter) continue;
773 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
774 allstabledescendants.insert(theDaughter);
775 }
776 findParticleStableDescendants(theDaughter, allstabledescendants);
777 }
778 }
779
783
784 template <class T> bool isHardScatteringVertex(T pVert) {
785 if (pVert == nullptr) return false;
786 T pV = pVert;
787 int numOfPartIn(0);
788 int pdg(0);
789
790 do {
791 pVert = pV;
792 auto incoming = pVert->particles_in();
793 numOfPartIn = incoming.size();
794 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
795 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
796
797 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
798
799 if (numOfPartIn == 2) {
800 auto incoming = pVert->particles_in();
801 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
802 }
803 return false;
804}
805
809
810 template <class T, class U>
811 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
812 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
813 auto vtx = p->production_vertex();
814 if (!vtx) return false;
815 bool fromHad = false;
816 for ( const auto& parent : particles_in(vtx) ) {
817 if (!parent) continue;
818 // should this really go into parton-level territory?
819 // probably depends where BSM particles are being decayed
820 fromBSM |= isBSM(parent);
821 if (!isPhysical(parent)) return false;
822 fromTau |= isTau(parent);
823 if (isHadron(parent)&&!isBeam(parent)) {
824 if (!hadron) hadron = parent; // assumes linear hadron parentage
825 return true;
826 }
827 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
828 }
829 return fromHad;
830 }
831
834
835 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
836 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
837 decltype(thePart->end_vertex()) pVert(nullptr);
838 if (EndVert != nullptr) {
839 do {
840 bool samePart = false;
841 pVert = nullptr;
842 auto outgoing = EndVert->particles_out();
843 auto incoming = EndVert->particles_in();
844 for (const auto& itrDaug: outgoing) {
845 if (!itrDaug) continue;
846 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
847 // brem on generator level for tau
848 (outgoing.size() == 1 && incoming.size() == 1 &&
850 itrDaug->pdg_id() == thePart->pdg_id()) {
851 samePart = true;
852 pVert = itrDaug->end_vertex();
853 }
854 }
855 if (samePart) EndVert = pVert;
856 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
857 }
858 return EndVert;
859 }
860
862
863 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
864 if (!theVert) return {};
865 decltype(theVert->particles_out()) finalStatePart;
866 auto outgoing = theVert->particles_out();
867 for (const auto& thePart: outgoing) {
868 if (!thePart) continue;
869 finalStatePart.push_back(thePart);
870 if (isStable(thePart)) continue;
871 V pVert = findSimulatedEndVertex(thePart);
872 if (pVert == theVert) break; // to prevent Sherpa loop
873 if (pVert != nullptr) {
874 auto vecPart = findFinalStateParticles<V>(pVert);
875 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
876 }
877 }
878 return finalStatePart;
879 }
880#if !defined(XAOD_ANALYSIS)
881#include "AtlasHepMC/GenEvent.h"
882inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
883inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
884
885#endif
886}
887#endif

◆ hasStrange()

template<class T>
bool MC::hasStrange ( const T & p)
inline

Definition at line 737 of file HepMCHelpers.h.

756{
757 template <class VTX>
758 auto particles_in (const VTX* p) { return p->particles_in(); }
759 template <class VTX>
760 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
761
762 namespace Pythia8
763 {
765 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
766
767 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
768
769 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
770 }
771
772#include "AtlasPID.h"
773
775 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
776
778 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
779
781 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
782
784 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
785
787 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
788
790 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
791
793 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
794
796 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
797
799 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
800
802 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
803
807 template <class T> inline bool isStableOrSimDecayed(const T& p) {
808 const auto vertex = p->end_vertex();
809 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
810 }
811
813 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
814
816 template <class T> inline bool isSpecialNonInteracting(const T& p) {
817 const int apid = std::abs(p->pdg_id());
818 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
819 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
820 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
821 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
822 return false;
823 }
824
826
827 template <class T> T findMother(T thePart) {
828 auto partOriVert = thePart->production_vertex();
829 if (!partOriVert) return nullptr;
830
831 long partPDG = thePart->pdg_id();
832 long MotherPDG(0);
833
834 auto MothOriVert = partOriVert;
835 MothOriVert = nullptr;
836 T theMoth(nullptr);
837
838 size_t itr = 0;
839 do {
840 if (itr != 0) partOriVert = MothOriVert;
841 for ( const auto& p : particles_in(partOriVert) ) {
842 theMoth = p;
843 if (!theMoth) continue;
844 MotherPDG = theMoth->pdg_id();
845 MothOriVert = theMoth->production_vertex();
846 if (MotherPDG == partPDG) break;
847 }
848 itr++;
849 if (itr > 100) {
850 break;
851 }
852 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
853 MothOriVert != partOriVert);
854 return theMoth;
855 }
856
858
859 template <class C, class T> T findMatching(C TruthContainer, T p) {
860 T ptrPart = nullptr;
861 if (!p) return ptrPart;
862 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
863 for (T truthParticle : *TruthContainer) {
864 if (HepMC::is_sim_descendant(p,truthParticle)) {
865 ptrPart = truthParticle;
866 break;
867 }
868 }
869 }
870 else {
871 for (T truthParticle : TruthContainer) {
872 if (HepMC::is_sim_descendant(p,truthParticle)) {
873 ptrPart = truthParticle;
874 break;
875 }
876 }
877 }
878 return ptrPart;
879 }
881
882 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
883 auto prodVtx = thePart->production_vertex();
884 if (!prodVtx) return;
885 for (const auto& theMother: prodVtx->particles_in()) {
886 if (!theMother) continue;
887 allancestors.insert(theMother);
888 findParticleAncestors(theMother, allancestors);
889 }
890 }
891
893
894 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
895 auto endVtx = thePart->end_vertex();
896 if (!endVtx) return;
897 for (const auto& theDaughter: endVtx->particles_out()) {
898 if (!theDaughter) continue;
899 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
900 allstabledescendants.insert(theDaughter);
901 }
902 findParticleStableDescendants(theDaughter, allstabledescendants);
903 }
904 }
905
909
910 template <class T> bool isHardScatteringVertex(T pVert) {
911 if (pVert == nullptr) return false;
912 T pV = pVert;
913 int numOfPartIn(0);
914 int pdg(0);
915
916 do {
917 pVert = pV;
918 auto incoming = pVert->particles_in();
919 numOfPartIn = incoming.size();
920 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
921 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
922
923 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
924
925 if (numOfPartIn == 2) {
926 auto incoming = pVert->particles_in();
927 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
928 }
929 return false;
930}
931
935
936 template <class T, class U>
937 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
938 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
939 auto vtx = p->production_vertex();
940 if (!vtx) return false;
941 bool fromHad = false;
942 for ( const auto& parent : particles_in(vtx) ) {
943 if (!parent) continue;
944 // should this really go into parton-level territory?
945 // probably depends where BSM particles are being decayed
946 fromBSM |= isBSM(parent);
947 if (!isPhysical(parent)) return false;
948 fromTau |= isTau(parent);
949 if (isHadron(parent)&&!isBeam(parent)) {
950 if (!hadron) hadron = parent; // assumes linear hadron parentage
951 return true;
952 }
953 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
954 }
955 return fromHad;
956 }
957
960
961 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
962 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
963 decltype(thePart->end_vertex()) pVert(nullptr);
964 if (EndVert != nullptr) {
965 do {
966 bool samePart = false;
967 pVert = nullptr;
968 auto outgoing = EndVert->particles_out();
969 auto incoming = EndVert->particles_in();
970 for (const auto& itrDaug: outgoing) {
971 if (!itrDaug) continue;
972 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
973 // brem on generator level for tau
974 (outgoing.size() == 1 && incoming.size() == 1 &&
976 itrDaug->pdg_id() == thePart->pdg_id()) {
977 samePart = true;
978 pVert = itrDaug->end_vertex();
979 }
980 }
981 if (samePart) EndVert = pVert;
982 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
983 }
984 return EndVert;
985 }
986
988
989 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
990 if (!theVert) return {};
991 decltype(theVert->particles_out()) finalStatePart;
992 auto outgoing = theVert->particles_out();
993 for (const auto& thePart: outgoing) {
994 if (!thePart) continue;
995 finalStatePart.push_back(thePart);
996 if (isStable(thePart)) continue;
997 V pVert = findSimulatedEndVertex(thePart);
998 if (pVert == theVert) break; // to prevent Sherpa loop
999 if (pVert != nullptr) {
1000 auto vecPart = findFinalStateParticles<V>(pVert);
1001 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1002 }
1003 }
1004 return finalStatePart;
1005 }
1006#if !defined(XAOD_ANALYSIS)
1007#include "AtlasHepMC/GenEvent.h"
1008inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1009inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1010
1011#endif
1012}
1013#endif

◆ hasTop()

template<class T>
bool MC::hasTop ( const T & p)
inline

Definition at line 740 of file HepMCHelpers.h.

759{
760 template <class VTX>
761 auto particles_in (const VTX* p) { return p->particles_in(); }
762 template <class VTX>
763 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
764
765 namespace Pythia8
766 {
768 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
769
770 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
771
772 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
773 }
774
775#include "AtlasPID.h"
776
778 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
779
781 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
782
784 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
785
787 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
788
790 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
791
793 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
794
796 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
797
799 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
800
802 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
803
805 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
806
810 template <class T> inline bool isStableOrSimDecayed(const T& p) {
811 const auto vertex = p->end_vertex();
812 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
813 }
814
816 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
817
819 template <class T> inline bool isSpecialNonInteracting(const T& p) {
820 const int apid = std::abs(p->pdg_id());
821 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
822 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
823 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
824 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
825 return false;
826 }
827
829
830 template <class T> T findMother(T thePart) {
831 auto partOriVert = thePart->production_vertex();
832 if (!partOriVert) return nullptr;
833
834 long partPDG = thePart->pdg_id();
835 long MotherPDG(0);
836
837 auto MothOriVert = partOriVert;
838 MothOriVert = nullptr;
839 T theMoth(nullptr);
840
841 size_t itr = 0;
842 do {
843 if (itr != 0) partOriVert = MothOriVert;
844 for ( const auto& p : particles_in(partOriVert) ) {
845 theMoth = p;
846 if (!theMoth) continue;
847 MotherPDG = theMoth->pdg_id();
848 MothOriVert = theMoth->production_vertex();
849 if (MotherPDG == partPDG) break;
850 }
851 itr++;
852 if (itr > 100) {
853 break;
854 }
855 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
856 MothOriVert != partOriVert);
857 return theMoth;
858 }
859
861
862 template <class C, class T> T findMatching(C TruthContainer, T p) {
863 T ptrPart = nullptr;
864 if (!p) return ptrPart;
865 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
866 for (T truthParticle : *TruthContainer) {
867 if (HepMC::is_sim_descendant(p,truthParticle)) {
868 ptrPart = truthParticle;
869 break;
870 }
871 }
872 }
873 else {
874 for (T truthParticle : TruthContainer) {
875 if (HepMC::is_sim_descendant(p,truthParticle)) {
876 ptrPart = truthParticle;
877 break;
878 }
879 }
880 }
881 return ptrPart;
882 }
884
885 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
886 auto prodVtx = thePart->production_vertex();
887 if (!prodVtx) return;
888 for (const auto& theMother: prodVtx->particles_in()) {
889 if (!theMother) continue;
890 allancestors.insert(theMother);
891 findParticleAncestors(theMother, allancestors);
892 }
893 }
894
896
897 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
898 auto endVtx = thePart->end_vertex();
899 if (!endVtx) return;
900 for (const auto& theDaughter: endVtx->particles_out()) {
901 if (!theDaughter) continue;
902 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
903 allstabledescendants.insert(theDaughter);
904 }
905 findParticleStableDescendants(theDaughter, allstabledescendants);
906 }
907 }
908
912
913 template <class T> bool isHardScatteringVertex(T pVert) {
914 if (pVert == nullptr) return false;
915 T pV = pVert;
916 int numOfPartIn(0);
917 int pdg(0);
918
919 do {
920 pVert = pV;
921 auto incoming = pVert->particles_in();
922 numOfPartIn = incoming.size();
923 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
924 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
925
926 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
927
928 if (numOfPartIn == 2) {
929 auto incoming = pVert->particles_in();
930 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
931 }
932 return false;
933}
934
938
939 template <class T, class U>
940 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
941 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
942 auto vtx = p->production_vertex();
943 if (!vtx) return false;
944 bool fromHad = false;
945 for ( const auto& parent : particles_in(vtx) ) {
946 if (!parent) continue;
947 // should this really go into parton-level territory?
948 // probably depends where BSM particles are being decayed
949 fromBSM |= isBSM(parent);
950 if (!isPhysical(parent)) return false;
951 fromTau |= isTau(parent);
952 if (isHadron(parent)&&!isBeam(parent)) {
953 if (!hadron) hadron = parent; // assumes linear hadron parentage
954 return true;
955 }
956 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
957 }
958 return fromHad;
959 }
960
963
964 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
965 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
966 decltype(thePart->end_vertex()) pVert(nullptr);
967 if (EndVert != nullptr) {
968 do {
969 bool samePart = false;
970 pVert = nullptr;
971 auto outgoing = EndVert->particles_out();
972 auto incoming = EndVert->particles_in();
973 for (const auto& itrDaug: outgoing) {
974 if (!itrDaug) continue;
975 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
976 // brem on generator level for tau
977 (outgoing.size() == 1 && incoming.size() == 1 &&
979 itrDaug->pdg_id() == thePart->pdg_id()) {
980 samePart = true;
981 pVert = itrDaug->end_vertex();
982 }
983 }
984 if (samePart) EndVert = pVert;
985 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
986 }
987 return EndVert;
988 }
989
991
992 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
993 if (!theVert) return {};
994 decltype(theVert->particles_out()) finalStatePart;
995 auto outgoing = theVert->particles_out();
996 for (const auto& thePart: outgoing) {
997 if (!thePart) continue;
998 finalStatePart.push_back(thePart);
999 if (isStable(thePart)) continue;
1000 V pVert = findSimulatedEndVertex(thePart);
1001 if (pVert == theVert) break; // to prevent Sherpa loop
1002 if (pVert != nullptr) {
1003 auto vecPart = findFinalStateParticles<V>(pVert);
1004 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1005 }
1006 }
1007 return finalStatePart;
1008 }
1009#if !defined(XAOD_ANALYSIS)
1010#include "AtlasHepMC/GenEvent.h"
1011inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1012inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1013
1014#endif
1015}
1016#endif

◆ isBaryon() [1/3]

template<>
bool MC::isBaryon ( const DecodedPID & p)
inline

Definition at line 284 of file HepMCHelpers.h.

303{
304 template <class VTX>
305 auto particles_in (const VTX* p) { return p->particles_in(); }
306 template <class VTX>
307 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
308
309 namespace Pythia8
310 {
312 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
313
314 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
315
316 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
317 }
318
319#include "AtlasPID.h"
320
322 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
323
325 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
326
328 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
329
331 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
332
334 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
335
337 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
338
340 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
341
343 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
344
346 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
347
349 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
350
354 template <class T> inline bool isStableOrSimDecayed(const T& p) {
355 const auto vertex = p->end_vertex();
356 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
357 }
358
360 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
361
363 template <class T> inline bool isSpecialNonInteracting(const T& p) {
364 const int apid = std::abs(p->pdg_id());
365 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
366 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
367 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
368 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
369 return false;
370 }
371
373
374 template <class T> T findMother(T thePart) {
375 auto partOriVert = thePart->production_vertex();
376 if (!partOriVert) return nullptr;
377
378 long partPDG = thePart->pdg_id();
379 long MotherPDG(0);
380
381 auto MothOriVert = partOriVert;
382 MothOriVert = nullptr;
383 T theMoth(nullptr);
384
385 size_t itr = 0;
386 do {
387 if (itr != 0) partOriVert = MothOriVert;
388 for ( const auto& p : particles_in(partOriVert) ) {
389 theMoth = p;
390 if (!theMoth) continue;
391 MotherPDG = theMoth->pdg_id();
392 MothOriVert = theMoth->production_vertex();
393 if (MotherPDG == partPDG) break;
394 }
395 itr++;
396 if (itr > 100) {
397 break;
398 }
399 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
400 MothOriVert != partOriVert);
401 return theMoth;
402 }
403
405
406 template <class C, class T> T findMatching(C TruthContainer, T p) {
407 T ptrPart = nullptr;
408 if (!p) return ptrPart;
409 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
410 for (T truthParticle : *TruthContainer) {
411 if (HepMC::is_sim_descendant(p,truthParticle)) {
412 ptrPart = truthParticle;
413 break;
414 }
415 }
416 }
417 else {
418 for (T truthParticle : TruthContainer) {
419 if (HepMC::is_sim_descendant(p,truthParticle)) {
420 ptrPart = truthParticle;
421 break;
422 }
423 }
424 }
425 return ptrPart;
426 }
428
429 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
430 auto prodVtx = thePart->production_vertex();
431 if (!prodVtx) return;
432 for (const auto& theMother: prodVtx->particles_in()) {
433 if (!theMother) continue;
434 allancestors.insert(theMother);
435 findParticleAncestors(theMother, allancestors);
436 }
437 }
438
440
441 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
442 auto endVtx = thePart->end_vertex();
443 if (!endVtx) return;
444 for (const auto& theDaughter: endVtx->particles_out()) {
445 if (!theDaughter) continue;
446 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
447 allstabledescendants.insert(theDaughter);
448 }
449 findParticleStableDescendants(theDaughter, allstabledescendants);
450 }
451 }
452
456
457 template <class T> bool isHardScatteringVertex(T pVert) {
458 if (pVert == nullptr) return false;
459 T pV = pVert;
460 int numOfPartIn(0);
461 int pdg(0);
462
463 do {
464 pVert = pV;
465 auto incoming = pVert->particles_in();
466 numOfPartIn = incoming.size();
467 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
468 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
469
470 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
471
472 if (numOfPartIn == 2) {
473 auto incoming = pVert->particles_in();
474 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
475 }
476 return false;
477}
478
482
483 template <class T, class U>
484 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
485 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
486 auto vtx = p->production_vertex();
487 if (!vtx) return false;
488 bool fromHad = false;
489 for ( const auto& parent : particles_in(vtx) ) {
490 if (!parent) continue;
491 // should this really go into parton-level territory?
492 // probably depends where BSM particles are being decayed
493 fromBSM |= isBSM(parent);
494 if (!isPhysical(parent)) return false;
495 fromTau |= isTau(parent);
496 if (isHadron(parent)&&!isBeam(parent)) {
497 if (!hadron) hadron = parent; // assumes linear hadron parentage
498 return true;
499 }
500 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
501 }
502 return fromHad;
503 }
504
507
508 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
509 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
510 decltype(thePart->end_vertex()) pVert(nullptr);
511 if (EndVert != nullptr) {
512 do {
513 bool samePart = false;
514 pVert = nullptr;
515 auto outgoing = EndVert->particles_out();
516 auto incoming = EndVert->particles_in();
517 for (const auto& itrDaug: outgoing) {
518 if (!itrDaug) continue;
519 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
520 // brem on generator level for tau
521 (outgoing.size() == 1 && incoming.size() == 1 &&
523 itrDaug->pdg_id() == thePart->pdg_id()) {
524 samePart = true;
525 pVert = itrDaug->end_vertex();
526 }
527 }
528 if (samePart) EndVert = pVert;
529 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
530 }
531 return EndVert;
532 }
533
535
536 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
537 if (!theVert) return {};
538 decltype(theVert->particles_out()) finalStatePart;
539 auto outgoing = theVert->particles_out();
540 for (const auto& thePart: outgoing) {
541 if (!thePart) continue;
542 finalStatePart.push_back(thePart);
543 if (isStable(thePart)) continue;
544 V pVert = findSimulatedEndVertex(thePart);
545 if (pVert == theVert) break; // to prevent Sherpa loop
546 if (pVert != nullptr) {
547 auto vecPart = findFinalStateParticles<V>(pVert);
548 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
549 }
550 }
551 return finalStatePart;
552 }
553#if !defined(XAOD_ANALYSIS)
554#include "AtlasHepMC/GenEvent.h"
555inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
556inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
557
558#endif
559}
560#endif

◆ isBaryon() [2/3]

template<>
bool MC::isBaryon ( const int & p)
inline

Definition at line 317 of file HepMCHelpers.h.

336{
337 template <class VTX>
338 auto particles_in (const VTX* p) { return p->particles_in(); }
339 template <class VTX>
340 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
341
342 namespace Pythia8
343 {
345 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
346
347 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
348
349 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
350 }
351
352#include "AtlasPID.h"
353
355 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
356
358 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
359
361 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
362
364 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
365
367 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
368
370 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
371
373 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
374
376 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
377
379 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
380
382 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
383
387 template <class T> inline bool isStableOrSimDecayed(const T& p) {
388 const auto vertex = p->end_vertex();
389 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
390 }
391
393 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
394
396 template <class T> inline bool isSpecialNonInteracting(const T& p) {
397 const int apid = std::abs(p->pdg_id());
398 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
399 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
400 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
401 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
402 return false;
403 }
404
406
407 template <class T> T findMother(T thePart) {
408 auto partOriVert = thePart->production_vertex();
409 if (!partOriVert) return nullptr;
410
411 long partPDG = thePart->pdg_id();
412 long MotherPDG(0);
413
414 auto MothOriVert = partOriVert;
415 MothOriVert = nullptr;
416 T theMoth(nullptr);
417
418 size_t itr = 0;
419 do {
420 if (itr != 0) partOriVert = MothOriVert;
421 for ( const auto& p : particles_in(partOriVert) ) {
422 theMoth = p;
423 if (!theMoth) continue;
424 MotherPDG = theMoth->pdg_id();
425 MothOriVert = theMoth->production_vertex();
426 if (MotherPDG == partPDG) break;
427 }
428 itr++;
429 if (itr > 100) {
430 break;
431 }
432 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
433 MothOriVert != partOriVert);
434 return theMoth;
435 }
436
438
439 template <class C, class T> T findMatching(C TruthContainer, T p) {
440 T ptrPart = nullptr;
441 if (!p) return ptrPart;
442 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
443 for (T truthParticle : *TruthContainer) {
444 if (HepMC::is_sim_descendant(p,truthParticle)) {
445 ptrPart = truthParticle;
446 break;
447 }
448 }
449 }
450 else {
451 for (T truthParticle : TruthContainer) {
452 if (HepMC::is_sim_descendant(p,truthParticle)) {
453 ptrPart = truthParticle;
454 break;
455 }
456 }
457 }
458 return ptrPart;
459 }
461
462 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
463 auto prodVtx = thePart->production_vertex();
464 if (!prodVtx) return;
465 for (const auto& theMother: prodVtx->particles_in()) {
466 if (!theMother) continue;
467 allancestors.insert(theMother);
468 findParticleAncestors(theMother, allancestors);
469 }
470 }
471
473
474 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
475 auto endVtx = thePart->end_vertex();
476 if (!endVtx) return;
477 for (const auto& theDaughter: endVtx->particles_out()) {
478 if (!theDaughter) continue;
479 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
480 allstabledescendants.insert(theDaughter);
481 }
482 findParticleStableDescendants(theDaughter, allstabledescendants);
483 }
484 }
485
489
490 template <class T> bool isHardScatteringVertex(T pVert) {
491 if (pVert == nullptr) return false;
492 T pV = pVert;
493 int numOfPartIn(0);
494 int pdg(0);
495
496 do {
497 pVert = pV;
498 auto incoming = pVert->particles_in();
499 numOfPartIn = incoming.size();
500 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
501 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
502
503 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
504
505 if (numOfPartIn == 2) {
506 auto incoming = pVert->particles_in();
507 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
508 }
509 return false;
510}
511
515
516 template <class T, class U>
517 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
518 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
519 auto vtx = p->production_vertex();
520 if (!vtx) return false;
521 bool fromHad = false;
522 for ( const auto& parent : particles_in(vtx) ) {
523 if (!parent) continue;
524 // should this really go into parton-level territory?
525 // probably depends where BSM particles are being decayed
526 fromBSM |= isBSM(parent);
527 if (!isPhysical(parent)) return false;
528 fromTau |= isTau(parent);
529 if (isHadron(parent)&&!isBeam(parent)) {
530 if (!hadron) hadron = parent; // assumes linear hadron parentage
531 return true;
532 }
533 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
534 }
535 return fromHad;
536 }
537
540
541 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
542 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
543 decltype(thePart->end_vertex()) pVert(nullptr);
544 if (EndVert != nullptr) {
545 do {
546 bool samePart = false;
547 pVert = nullptr;
548 auto outgoing = EndVert->particles_out();
549 auto incoming = EndVert->particles_in();
550 for (const auto& itrDaug: outgoing) {
551 if (!itrDaug) continue;
552 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
553 // brem on generator level for tau
554 (outgoing.size() == 1 && incoming.size() == 1 &&
556 itrDaug->pdg_id() == thePart->pdg_id()) {
557 samePart = true;
558 pVert = itrDaug->end_vertex();
559 }
560 }
561 if (samePart) EndVert = pVert;
562 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
563 }
564 return EndVert;
565 }
566
568
569 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
570 if (!theVert) return {};
571 decltype(theVert->particles_out()) finalStatePart;
572 auto outgoing = theVert->particles_out();
573 for (const auto& thePart: outgoing) {
574 if (!thePart) continue;
575 finalStatePart.push_back(thePart);
576 if (isStable(thePart)) continue;
577 V pVert = findSimulatedEndVertex(thePart);
578 if (pVert == theVert) break; // to prevent Sherpa loop
579 if (pVert != nullptr) {
580 auto vecPart = findFinalStateParticles<V>(pVert);
581 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
582 }
583 }
584 return finalStatePart;
585 }
586#if !defined(XAOD_ANALYSIS)
587#include "AtlasHepMC/GenEvent.h"
588inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
589inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
590
591#endif
592}
593#endif

◆ isBaryon() [3/3]

template<class T>
bool MC::isBaryon ( const T & p)
inline

Table 43.2 APID: states with fourth generation quarks are not baryons.

Definition at line 283 of file HepMCHelpers.h.

302{
303 template <class VTX>
304 auto particles_in (const VTX* p) { return p->particles_in(); }
305 template <class VTX>
306 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
307
308 namespace Pythia8
309 {
311 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
312
313 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
314
315 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
316 }
317
318#include "AtlasPID.h"
319
321 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
322
324 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
325
327 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
328
330 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
331
333 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
334
336 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
337
339 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
340
342 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
343
345 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
346
348 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
349
353 template <class T> inline bool isStableOrSimDecayed(const T& p) {
354 const auto vertex = p->end_vertex();
355 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
356 }
357
359 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
360
362 template <class T> inline bool isSpecialNonInteracting(const T& p) {
363 const int apid = std::abs(p->pdg_id());
364 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
365 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
366 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
367 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
368 return false;
369 }
370
372
373 template <class T> T findMother(T thePart) {
374 auto partOriVert = thePart->production_vertex();
375 if (!partOriVert) return nullptr;
376
377 long partPDG = thePart->pdg_id();
378 long MotherPDG(0);
379
380 auto MothOriVert = partOriVert;
381 MothOriVert = nullptr;
382 T theMoth(nullptr);
383
384 size_t itr = 0;
385 do {
386 if (itr != 0) partOriVert = MothOriVert;
387 for ( const auto& p : particles_in(partOriVert) ) {
388 theMoth = p;
389 if (!theMoth) continue;
390 MotherPDG = theMoth->pdg_id();
391 MothOriVert = theMoth->production_vertex();
392 if (MotherPDG == partPDG) break;
393 }
394 itr++;
395 if (itr > 100) {
396 break;
397 }
398 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
399 MothOriVert != partOriVert);
400 return theMoth;
401 }
402
404
405 template <class C, class T> T findMatching(C TruthContainer, T p) {
406 T ptrPart = nullptr;
407 if (!p) return ptrPart;
408 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
409 for (T truthParticle : *TruthContainer) {
410 if (HepMC::is_sim_descendant(p,truthParticle)) {
411 ptrPart = truthParticle;
412 break;
413 }
414 }
415 }
416 else {
417 for (T truthParticle : TruthContainer) {
418 if (HepMC::is_sim_descendant(p,truthParticle)) {
419 ptrPart = truthParticle;
420 break;
421 }
422 }
423 }
424 return ptrPart;
425 }
427
428 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
429 auto prodVtx = thePart->production_vertex();
430 if (!prodVtx) return;
431 for (const auto& theMother: prodVtx->particles_in()) {
432 if (!theMother) continue;
433 allancestors.insert(theMother);
434 findParticleAncestors(theMother, allancestors);
435 }
436 }
437
439
440 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
441 auto endVtx = thePart->end_vertex();
442 if (!endVtx) return;
443 for (const auto& theDaughter: endVtx->particles_out()) {
444 if (!theDaughter) continue;
445 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
446 allstabledescendants.insert(theDaughter);
447 }
448 findParticleStableDescendants(theDaughter, allstabledescendants);
449 }
450 }
451
455
456 template <class T> bool isHardScatteringVertex(T pVert) {
457 if (pVert == nullptr) return false;
458 T pV = pVert;
459 int numOfPartIn(0);
460 int pdg(0);
461
462 do {
463 pVert = pV;
464 auto incoming = pVert->particles_in();
465 numOfPartIn = incoming.size();
466 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
467 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
468
469 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
470
471 if (numOfPartIn == 2) {
472 auto incoming = pVert->particles_in();
473 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
474 }
475 return false;
476}
477
481
482 template <class T, class U>
483 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
484 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
485 auto vtx = p->production_vertex();
486 if (!vtx) return false;
487 bool fromHad = false;
488 for ( const auto& parent : particles_in(vtx) ) {
489 if (!parent) continue;
490 // should this really go into parton-level territory?
491 // probably depends where BSM particles are being decayed
492 fromBSM |= isBSM(parent);
493 if (!isPhysical(parent)) return false;
494 fromTau |= isTau(parent);
495 if (isHadron(parent)&&!isBeam(parent)) {
496 if (!hadron) hadron = parent; // assumes linear hadron parentage
497 return true;
498 }
499 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
500 }
501 return fromHad;
502 }
503
506
507 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
508 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
509 decltype(thePart->end_vertex()) pVert(nullptr);
510 if (EndVert != nullptr) {
511 do {
512 bool samePart = false;
513 pVert = nullptr;
514 auto outgoing = EndVert->particles_out();
515 auto incoming = EndVert->particles_in();
516 for (const auto& itrDaug: outgoing) {
517 if (!itrDaug) continue;
518 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
519 // brem on generator level for tau
520 (outgoing.size() == 1 && incoming.size() == 1 &&
522 itrDaug->pdg_id() == thePart->pdg_id()) {
523 samePart = true;
524 pVert = itrDaug->end_vertex();
525 }
526 }
527 if (samePart) EndVert = pVert;
528 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
529 }
530 return EndVert;
531 }
532
534
535 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
536 if (!theVert) return {};
537 decltype(theVert->particles_out()) finalStatePart;
538 auto outgoing = theVert->particles_out();
539 for (const auto& thePart: outgoing) {
540 if (!thePart) continue;
541 finalStatePart.push_back(thePart);
542 if (isStable(thePart)) continue;
543 V pVert = findSimulatedEndVertex(thePart);
544 if (pVert == theVert) break; // to prevent Sherpa loop
545 if (pVert != nullptr) {
546 auto vecPart = findFinalStateParticles<V>(pVert);
547 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
548 }
549 }
550 return finalStatePart;
551 }
552#if !defined(XAOD_ANALYSIS)
553#include "AtlasHepMC/GenEvent.h"
554inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
555inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
556
557#endif
558}
559#endif

◆ isBBbarMeson() [1/3]

template<>
bool MC::isBBbarMeson ( const DecodedPID & p)
inline

Definition at line 928 of file HepMCHelpers.h.

947{
948 template <class VTX>
949 auto particles_in (const VTX* p) { return p->particles_in(); }
950 template <class VTX>
951 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
952
953 namespace Pythia8
954 {
956 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
957
958 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
959
960 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
961 }
962
963#include "AtlasPID.h"
964
966 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
967
969 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
970
972 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
973
975 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
976
978 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
979
981 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
982
984 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
985
987 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
988
990 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
991
993 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
994
998 template <class T> inline bool isStableOrSimDecayed(const T& p) {
999 const auto vertex = p->end_vertex();
1000 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1001 }
1002
1004 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1005
1007 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1008 const int apid = std::abs(p->pdg_id());
1009 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1010 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1011 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1012 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1013 return false;
1014 }
1015
1017
1018 template <class T> T findMother(T thePart) {
1019 auto partOriVert = thePart->production_vertex();
1020 if (!partOriVert) return nullptr;
1021
1022 long partPDG = thePart->pdg_id();
1023 long MotherPDG(0);
1024
1025 auto MothOriVert = partOriVert;
1026 MothOriVert = nullptr;
1027 T theMoth(nullptr);
1028
1029 size_t itr = 0;
1030 do {
1031 if (itr != 0) partOriVert = MothOriVert;
1032 for ( const auto& p : particles_in(partOriVert) ) {
1033 theMoth = p;
1034 if (!theMoth) continue;
1035 MotherPDG = theMoth->pdg_id();
1036 MothOriVert = theMoth->production_vertex();
1037 if (MotherPDG == partPDG) break;
1038 }
1039 itr++;
1040 if (itr > 100) {
1041 break;
1042 }
1043 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1044 MothOriVert != partOriVert);
1045 return theMoth;
1046 }
1047
1049
1050 template <class C, class T> T findMatching(C TruthContainer, T p) {
1051 T ptrPart = nullptr;
1052 if (!p) return ptrPart;
1053 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1054 for (T truthParticle : *TruthContainer) {
1055 if (HepMC::is_sim_descendant(p,truthParticle)) {
1056 ptrPart = truthParticle;
1057 break;
1058 }
1059 }
1060 }
1061 else {
1062 for (T truthParticle : TruthContainer) {
1063 if (HepMC::is_sim_descendant(p,truthParticle)) {
1064 ptrPart = truthParticle;
1065 break;
1066 }
1067 }
1068 }
1069 return ptrPart;
1070 }
1072
1073 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1074 auto prodVtx = thePart->production_vertex();
1075 if (!prodVtx) return;
1076 for (const auto& theMother: prodVtx->particles_in()) {
1077 if (!theMother) continue;
1078 allancestors.insert(theMother);
1079 findParticleAncestors(theMother, allancestors);
1080 }
1081 }
1082
1084
1085 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1086 auto endVtx = thePart->end_vertex();
1087 if (!endVtx) return;
1088 for (const auto& theDaughter: endVtx->particles_out()) {
1089 if (!theDaughter) continue;
1090 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1091 allstabledescendants.insert(theDaughter);
1092 }
1093 findParticleStableDescendants(theDaughter, allstabledescendants);
1094 }
1095 }
1096
1100
1101 template <class T> bool isHardScatteringVertex(T pVert) {
1102 if (pVert == nullptr) return false;
1103 T pV = pVert;
1104 int numOfPartIn(0);
1105 int pdg(0);
1106
1107 do {
1108 pVert = pV;
1109 auto incoming = pVert->particles_in();
1110 numOfPartIn = incoming.size();
1111 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1112 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1113
1114 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1115
1116 if (numOfPartIn == 2) {
1117 auto incoming = pVert->particles_in();
1118 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1119 }
1120 return false;
1121}
1122
1126
1127 template <class T, class U>
1128 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1129 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1130 auto vtx = p->production_vertex();
1131 if (!vtx) return false;
1132 bool fromHad = false;
1133 for ( const auto& parent : particles_in(vtx) ) {
1134 if (!parent) continue;
1135 // should this really go into parton-level territory?
1136 // probably depends where BSM particles are being decayed
1137 fromBSM |= isBSM(parent);
1138 if (!isPhysical(parent)) return false;
1139 fromTau |= isTau(parent);
1140 if (isHadron(parent)&&!isBeam(parent)) {
1141 if (!hadron) hadron = parent; // assumes linear hadron parentage
1142 return true;
1143 }
1144 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1145 }
1146 return fromHad;
1147 }
1148
1151
1152 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1153 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1154 decltype(thePart->end_vertex()) pVert(nullptr);
1155 if (EndVert != nullptr) {
1156 do {
1157 bool samePart = false;
1158 pVert = nullptr;
1159 auto outgoing = EndVert->particles_out();
1160 auto incoming = EndVert->particles_in();
1161 for (const auto& itrDaug: outgoing) {
1162 if (!itrDaug) continue;
1163 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1164 // brem on generator level for tau
1165 (outgoing.size() == 1 && incoming.size() == 1 &&
1167 itrDaug->pdg_id() == thePart->pdg_id()) {
1168 samePart = true;
1169 pVert = itrDaug->end_vertex();
1170 }
1171 }
1172 if (samePart) EndVert = pVert;
1173 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1174 }
1175 return EndVert;
1176 }
1177
1179
1180 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1181 if (!theVert) return {};
1182 decltype(theVert->particles_out()) finalStatePart;
1183 auto outgoing = theVert->particles_out();
1184 for (const auto& thePart: outgoing) {
1185 if (!thePart) continue;
1186 finalStatePart.push_back(thePart);
1187 if (isStable(thePart)) continue;
1188 V pVert = findSimulatedEndVertex(thePart);
1189 if (pVert == theVert) break; // to prevent Sherpa loop
1190 if (pVert != nullptr) {
1191 auto vecPart = findFinalStateParticles<V>(pVert);
1192 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1193 }
1194 }
1195 return finalStatePart;
1196 }
1197#if !defined(XAOD_ANALYSIS)
1198#include "AtlasHepMC/GenEvent.h"
1199inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1200inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1201
1202#endif
1203}
1204#endif

◆ isBBbarMeson() [2/3]

template<>
bool MC::isBBbarMeson ( const int & p)
inline

Definition at line 929 of file HepMCHelpers.h.

948{
949 template <class VTX>
950 auto particles_in (const VTX* p) { return p->particles_in(); }
951 template <class VTX>
952 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
953
954 namespace Pythia8
955 {
957 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
958
959 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
960
961 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
962 }
963
964#include "AtlasPID.h"
965
967 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
968
970 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
971
973 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
974
976 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
977
979 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
980
982 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
983
985 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
986
988 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
989
991 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
992
994 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
995
999 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1000 const auto vertex = p->end_vertex();
1001 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1002 }
1003
1005 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1006
1008 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1009 const int apid = std::abs(p->pdg_id());
1010 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1011 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1012 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1013 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1014 return false;
1015 }
1016
1018
1019 template <class T> T findMother(T thePart) {
1020 auto partOriVert = thePart->production_vertex();
1021 if (!partOriVert) return nullptr;
1022
1023 long partPDG = thePart->pdg_id();
1024 long MotherPDG(0);
1025
1026 auto MothOriVert = partOriVert;
1027 MothOriVert = nullptr;
1028 T theMoth(nullptr);
1029
1030 size_t itr = 0;
1031 do {
1032 if (itr != 0) partOriVert = MothOriVert;
1033 for ( const auto& p : particles_in(partOriVert) ) {
1034 theMoth = p;
1035 if (!theMoth) continue;
1036 MotherPDG = theMoth->pdg_id();
1037 MothOriVert = theMoth->production_vertex();
1038 if (MotherPDG == partPDG) break;
1039 }
1040 itr++;
1041 if (itr > 100) {
1042 break;
1043 }
1044 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1045 MothOriVert != partOriVert);
1046 return theMoth;
1047 }
1048
1050
1051 template <class C, class T> T findMatching(C TruthContainer, T p) {
1052 T ptrPart = nullptr;
1053 if (!p) return ptrPart;
1054 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1055 for (T truthParticle : *TruthContainer) {
1056 if (HepMC::is_sim_descendant(p,truthParticle)) {
1057 ptrPart = truthParticle;
1058 break;
1059 }
1060 }
1061 }
1062 else {
1063 for (T truthParticle : TruthContainer) {
1064 if (HepMC::is_sim_descendant(p,truthParticle)) {
1065 ptrPart = truthParticle;
1066 break;
1067 }
1068 }
1069 }
1070 return ptrPart;
1071 }
1073
1074 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1075 auto prodVtx = thePart->production_vertex();
1076 if (!prodVtx) return;
1077 for (const auto& theMother: prodVtx->particles_in()) {
1078 if (!theMother) continue;
1079 allancestors.insert(theMother);
1080 findParticleAncestors(theMother, allancestors);
1081 }
1082 }
1083
1085
1086 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1087 auto endVtx = thePart->end_vertex();
1088 if (!endVtx) return;
1089 for (const auto& theDaughter: endVtx->particles_out()) {
1090 if (!theDaughter) continue;
1091 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1092 allstabledescendants.insert(theDaughter);
1093 }
1094 findParticleStableDescendants(theDaughter, allstabledescendants);
1095 }
1096 }
1097
1101
1102 template <class T> bool isHardScatteringVertex(T pVert) {
1103 if (pVert == nullptr) return false;
1104 T pV = pVert;
1105 int numOfPartIn(0);
1106 int pdg(0);
1107
1108 do {
1109 pVert = pV;
1110 auto incoming = pVert->particles_in();
1111 numOfPartIn = incoming.size();
1112 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1113 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1114
1115 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1116
1117 if (numOfPartIn == 2) {
1118 auto incoming = pVert->particles_in();
1119 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1120 }
1121 return false;
1122}
1123
1127
1128 template <class T, class U>
1129 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1130 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1131 auto vtx = p->production_vertex();
1132 if (!vtx) return false;
1133 bool fromHad = false;
1134 for ( const auto& parent : particles_in(vtx) ) {
1135 if (!parent) continue;
1136 // should this really go into parton-level territory?
1137 // probably depends where BSM particles are being decayed
1138 fromBSM |= isBSM(parent);
1139 if (!isPhysical(parent)) return false;
1140 fromTau |= isTau(parent);
1141 if (isHadron(parent)&&!isBeam(parent)) {
1142 if (!hadron) hadron = parent; // assumes linear hadron parentage
1143 return true;
1144 }
1145 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1146 }
1147 return fromHad;
1148 }
1149
1152
1153 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1154 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1155 decltype(thePart->end_vertex()) pVert(nullptr);
1156 if (EndVert != nullptr) {
1157 do {
1158 bool samePart = false;
1159 pVert = nullptr;
1160 auto outgoing = EndVert->particles_out();
1161 auto incoming = EndVert->particles_in();
1162 for (const auto& itrDaug: outgoing) {
1163 if (!itrDaug) continue;
1164 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1165 // brem on generator level for tau
1166 (outgoing.size() == 1 && incoming.size() == 1 &&
1168 itrDaug->pdg_id() == thePart->pdg_id()) {
1169 samePart = true;
1170 pVert = itrDaug->end_vertex();
1171 }
1172 }
1173 if (samePart) EndVert = pVert;
1174 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1175 }
1176 return EndVert;
1177 }
1178
1180
1181 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1182 if (!theVert) return {};
1183 decltype(theVert->particles_out()) finalStatePart;
1184 auto outgoing = theVert->particles_out();
1185 for (const auto& thePart: outgoing) {
1186 if (!thePart) continue;
1187 finalStatePart.push_back(thePart);
1188 if (isStable(thePart)) continue;
1189 V pVert = findSimulatedEndVertex(thePart);
1190 if (pVert == theVert) break; // to prevent Sherpa loop
1191 if (pVert != nullptr) {
1192 auto vecPart = findFinalStateParticles<V>(pVert);
1193 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1194 }
1195 }
1196 return finalStatePart;
1197 }
1198#if !defined(XAOD_ANALYSIS)
1199#include "AtlasHepMC/GenEvent.h"
1200inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1201inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1202
1203#endif
1204}
1205#endif

◆ isBBbarMeson() [3/3]

template<class T>
bool MC::isBBbarMeson ( const T & p)
inline

Definition at line 927 of file HepMCHelpers.h.

946{
947 template <class VTX>
948 auto particles_in (const VTX* p) { return p->particles_in(); }
949 template <class VTX>
950 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
951
952 namespace Pythia8
953 {
955 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
956
957 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
958
959 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
960 }
961
962#include "AtlasPID.h"
963
965 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
966
968 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
969
971 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
972
974 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
975
977 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
978
980 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
981
983 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
984
986 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
987
989 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
990
992 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
993
997 template <class T> inline bool isStableOrSimDecayed(const T& p) {
998 const auto vertex = p->end_vertex();
999 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1000 }
1001
1003 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1004
1006 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1007 const int apid = std::abs(p->pdg_id());
1008 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1009 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1010 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1011 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1012 return false;
1013 }
1014
1016
1017 template <class T> T findMother(T thePart) {
1018 auto partOriVert = thePart->production_vertex();
1019 if (!partOriVert) return nullptr;
1020
1021 long partPDG = thePart->pdg_id();
1022 long MotherPDG(0);
1023
1024 auto MothOriVert = partOriVert;
1025 MothOriVert = nullptr;
1026 T theMoth(nullptr);
1027
1028 size_t itr = 0;
1029 do {
1030 if (itr != 0) partOriVert = MothOriVert;
1031 for ( const auto& p : particles_in(partOriVert) ) {
1032 theMoth = p;
1033 if (!theMoth) continue;
1034 MotherPDG = theMoth->pdg_id();
1035 MothOriVert = theMoth->production_vertex();
1036 if (MotherPDG == partPDG) break;
1037 }
1038 itr++;
1039 if (itr > 100) {
1040 break;
1041 }
1042 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1043 MothOriVert != partOriVert);
1044 return theMoth;
1045 }
1046
1048
1049 template <class C, class T> T findMatching(C TruthContainer, T p) {
1050 T ptrPart = nullptr;
1051 if (!p) return ptrPart;
1052 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1053 for (T truthParticle : *TruthContainer) {
1054 if (HepMC::is_sim_descendant(p,truthParticle)) {
1055 ptrPart = truthParticle;
1056 break;
1057 }
1058 }
1059 }
1060 else {
1061 for (T truthParticle : TruthContainer) {
1062 if (HepMC::is_sim_descendant(p,truthParticle)) {
1063 ptrPart = truthParticle;
1064 break;
1065 }
1066 }
1067 }
1068 return ptrPart;
1069 }
1071
1072 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1073 auto prodVtx = thePart->production_vertex();
1074 if (!prodVtx) return;
1075 for (const auto& theMother: prodVtx->particles_in()) {
1076 if (!theMother) continue;
1077 allancestors.insert(theMother);
1078 findParticleAncestors(theMother, allancestors);
1079 }
1080 }
1081
1083
1084 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1085 auto endVtx = thePart->end_vertex();
1086 if (!endVtx) return;
1087 for (const auto& theDaughter: endVtx->particles_out()) {
1088 if (!theDaughter) continue;
1089 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1090 allstabledescendants.insert(theDaughter);
1091 }
1092 findParticleStableDescendants(theDaughter, allstabledescendants);
1093 }
1094 }
1095
1099
1100 template <class T> bool isHardScatteringVertex(T pVert) {
1101 if (pVert == nullptr) return false;
1102 T pV = pVert;
1103 int numOfPartIn(0);
1104 int pdg(0);
1105
1106 do {
1107 pVert = pV;
1108 auto incoming = pVert->particles_in();
1109 numOfPartIn = incoming.size();
1110 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1111 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1112
1113 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1114
1115 if (numOfPartIn == 2) {
1116 auto incoming = pVert->particles_in();
1117 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1118 }
1119 return false;
1120}
1121
1125
1126 template <class T, class U>
1127 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1128 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1129 auto vtx = p->production_vertex();
1130 if (!vtx) return false;
1131 bool fromHad = false;
1132 for ( const auto& parent : particles_in(vtx) ) {
1133 if (!parent) continue;
1134 // should this really go into parton-level territory?
1135 // probably depends where BSM particles are being decayed
1136 fromBSM |= isBSM(parent);
1137 if (!isPhysical(parent)) return false;
1138 fromTau |= isTau(parent);
1139 if (isHadron(parent)&&!isBeam(parent)) {
1140 if (!hadron) hadron = parent; // assumes linear hadron parentage
1141 return true;
1142 }
1143 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1144 }
1145 return fromHad;
1146 }
1147
1150
1151 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1152 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1153 decltype(thePart->end_vertex()) pVert(nullptr);
1154 if (EndVert != nullptr) {
1155 do {
1156 bool samePart = false;
1157 pVert = nullptr;
1158 auto outgoing = EndVert->particles_out();
1159 auto incoming = EndVert->particles_in();
1160 for (const auto& itrDaug: outgoing) {
1161 if (!itrDaug) continue;
1162 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1163 // brem on generator level for tau
1164 (outgoing.size() == 1 && incoming.size() == 1 &&
1166 itrDaug->pdg_id() == thePart->pdg_id()) {
1167 samePart = true;
1168 pVert = itrDaug->end_vertex();
1169 }
1170 }
1171 if (samePart) EndVert = pVert;
1172 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1173 }
1174 return EndVert;
1175 }
1176
1178
1179 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1180 if (!theVert) return {};
1181 decltype(theVert->particles_out()) finalStatePart;
1182 auto outgoing = theVert->particles_out();
1183 for (const auto& thePart: outgoing) {
1184 if (!thePart) continue;
1185 finalStatePart.push_back(thePart);
1186 if (isStable(thePart)) continue;
1187 V pVert = findSimulatedEndVertex(thePart);
1188 if (pVert == theVert) break; // to prevent Sherpa loop
1189 if (pVert != nullptr) {
1190 auto vecPart = findFinalStateParticles<V>(pVert);
1191 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1192 }
1193 }
1194 return finalStatePart;
1195 }
1196#if !defined(XAOD_ANALYSIS)
1197#include "AtlasHepMC/GenEvent.h"
1198inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1199inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1200
1201#endif
1202}
1203#endif

◆ isBeam()

template<class T>
bool MC::isBeam ( const T & p)
inline

Identify if the particle is beam particle.

Definition at line 45 of file HepMCHelpers.h.

◆ isBoson() [1/3]

template<>
bool MC::isBoson ( const DecodedPID & p)
inline

Definition at line 372 of file HepMCHelpers.h.

391{
392 template <class VTX>
393 auto particles_in (const VTX* p) { return p->particles_in(); }
394 template <class VTX>
395 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
396
397 namespace Pythia8
398 {
400 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
401
402 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
403
404 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
405 }
406
407#include "AtlasPID.h"
408
410 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
411
413 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
414
416 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
417
419 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
420
422 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
423
425 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
426
428 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
429
431 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
432
434 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
435
437 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
438
442 template <class T> inline bool isStableOrSimDecayed(const T& p) {
443 const auto vertex = p->end_vertex();
444 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
445 }
446
448 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
449
451 template <class T> inline bool isSpecialNonInteracting(const T& p) {
452 const int apid = std::abs(p->pdg_id());
453 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
454 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
455 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
456 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
457 return false;
458 }
459
461
462 template <class T> T findMother(T thePart) {
463 auto partOriVert = thePart->production_vertex();
464 if (!partOriVert) return nullptr;
465
466 long partPDG = thePart->pdg_id();
467 long MotherPDG(0);
468
469 auto MothOriVert = partOriVert;
470 MothOriVert = nullptr;
471 T theMoth(nullptr);
472
473 size_t itr = 0;
474 do {
475 if (itr != 0) partOriVert = MothOriVert;
476 for ( const auto& p : particles_in(partOriVert) ) {
477 theMoth = p;
478 if (!theMoth) continue;
479 MotherPDG = theMoth->pdg_id();
480 MothOriVert = theMoth->production_vertex();
481 if (MotherPDG == partPDG) break;
482 }
483 itr++;
484 if (itr > 100) {
485 break;
486 }
487 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
488 MothOriVert != partOriVert);
489 return theMoth;
490 }
491
493
494 template <class C, class T> T findMatching(C TruthContainer, T p) {
495 T ptrPart = nullptr;
496 if (!p) return ptrPart;
497 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
498 for (T truthParticle : *TruthContainer) {
499 if (HepMC::is_sim_descendant(p,truthParticle)) {
500 ptrPart = truthParticle;
501 break;
502 }
503 }
504 }
505 else {
506 for (T truthParticle : TruthContainer) {
507 if (HepMC::is_sim_descendant(p,truthParticle)) {
508 ptrPart = truthParticle;
509 break;
510 }
511 }
512 }
513 return ptrPart;
514 }
516
517 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
518 auto prodVtx = thePart->production_vertex();
519 if (!prodVtx) return;
520 for (const auto& theMother: prodVtx->particles_in()) {
521 if (!theMother) continue;
522 allancestors.insert(theMother);
523 findParticleAncestors(theMother, allancestors);
524 }
525 }
526
528
529 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
530 auto endVtx = thePart->end_vertex();
531 if (!endVtx) return;
532 for (const auto& theDaughter: endVtx->particles_out()) {
533 if (!theDaughter) continue;
534 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
535 allstabledescendants.insert(theDaughter);
536 }
537 findParticleStableDescendants(theDaughter, allstabledescendants);
538 }
539 }
540
544
545 template <class T> bool isHardScatteringVertex(T pVert) {
546 if (pVert == nullptr) return false;
547 T pV = pVert;
548 int numOfPartIn(0);
549 int pdg(0);
550
551 do {
552 pVert = pV;
553 auto incoming = pVert->particles_in();
554 numOfPartIn = incoming.size();
555 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
556 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
557
558 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
559
560 if (numOfPartIn == 2) {
561 auto incoming = pVert->particles_in();
562 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
563 }
564 return false;
565}
566
570
571 template <class T, class U>
572 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
573 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
574 auto vtx = p->production_vertex();
575 if (!vtx) return false;
576 bool fromHad = false;
577 for ( const auto& parent : particles_in(vtx) ) {
578 if (!parent) continue;
579 // should this really go into parton-level territory?
580 // probably depends where BSM particles are being decayed
581 fromBSM |= isBSM(parent);
582 if (!isPhysical(parent)) return false;
583 fromTau |= isTau(parent);
584 if (isHadron(parent)&&!isBeam(parent)) {
585 if (!hadron) hadron = parent; // assumes linear hadron parentage
586 return true;
587 }
588 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
589 }
590 return fromHad;
591 }
592
595
596 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
597 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
598 decltype(thePart->end_vertex()) pVert(nullptr);
599 if (EndVert != nullptr) {
600 do {
601 bool samePart = false;
602 pVert = nullptr;
603 auto outgoing = EndVert->particles_out();
604 auto incoming = EndVert->particles_in();
605 for (const auto& itrDaug: outgoing) {
606 if (!itrDaug) continue;
607 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
608 // brem on generator level for tau
609 (outgoing.size() == 1 && incoming.size() == 1 &&
611 itrDaug->pdg_id() == thePart->pdg_id()) {
612 samePart = true;
613 pVert = itrDaug->end_vertex();
614 }
615 }
616 if (samePart) EndVert = pVert;
617 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
618 }
619 return EndVert;
620 }
621
623
624 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
625 if (!theVert) return {};
626 decltype(theVert->particles_out()) finalStatePart;
627 auto outgoing = theVert->particles_out();
628 for (const auto& thePart: outgoing) {
629 if (!thePart) continue;
630 finalStatePart.push_back(thePart);
631 if (isStable(thePart)) continue;
632 V pVert = findSimulatedEndVertex(thePart);
633 if (pVert == theVert) break; // to prevent Sherpa loop
634 if (pVert != nullptr) {
635 auto vecPart = findFinalStateParticles<V>(pVert);
636 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
637 }
638 }
639 return finalStatePart;
640 }
641#if !defined(XAOD_ANALYSIS)
642#include "AtlasHepMC/GenEvent.h"
643inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
644inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
645
646#endif
647}
648#endif

◆ isBoson() [2/3]

template<>
bool MC::isBoson ( const int & p)
inline

Definition at line 371 of file HepMCHelpers.h.

390{
391 template <class VTX>
392 auto particles_in (const VTX* p) { return p->particles_in(); }
393 template <class VTX>
394 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
395
396 namespace Pythia8
397 {
399 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
400
401 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
402
403 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
404 }
405
406#include "AtlasPID.h"
407
409 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
410
412 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
413
415 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
416
418 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
419
421 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
422
424 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
425
427 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
428
430 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
431
433 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
434
436 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
437
441 template <class T> inline bool isStableOrSimDecayed(const T& p) {
442 const auto vertex = p->end_vertex();
443 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
444 }
445
447 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
448
450 template <class T> inline bool isSpecialNonInteracting(const T& p) {
451 const int apid = std::abs(p->pdg_id());
452 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
453 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
454 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
455 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
456 return false;
457 }
458
460
461 template <class T> T findMother(T thePart) {
462 auto partOriVert = thePart->production_vertex();
463 if (!partOriVert) return nullptr;
464
465 long partPDG = thePart->pdg_id();
466 long MotherPDG(0);
467
468 auto MothOriVert = partOriVert;
469 MothOriVert = nullptr;
470 T theMoth(nullptr);
471
472 size_t itr = 0;
473 do {
474 if (itr != 0) partOriVert = MothOriVert;
475 for ( const auto& p : particles_in(partOriVert) ) {
476 theMoth = p;
477 if (!theMoth) continue;
478 MotherPDG = theMoth->pdg_id();
479 MothOriVert = theMoth->production_vertex();
480 if (MotherPDG == partPDG) break;
481 }
482 itr++;
483 if (itr > 100) {
484 break;
485 }
486 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
487 MothOriVert != partOriVert);
488 return theMoth;
489 }
490
492
493 template <class C, class T> T findMatching(C TruthContainer, T p) {
494 T ptrPart = nullptr;
495 if (!p) return ptrPart;
496 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
497 for (T truthParticle : *TruthContainer) {
498 if (HepMC::is_sim_descendant(p,truthParticle)) {
499 ptrPart = truthParticle;
500 break;
501 }
502 }
503 }
504 else {
505 for (T truthParticle : TruthContainer) {
506 if (HepMC::is_sim_descendant(p,truthParticle)) {
507 ptrPart = truthParticle;
508 break;
509 }
510 }
511 }
512 return ptrPart;
513 }
515
516 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
517 auto prodVtx = thePart->production_vertex();
518 if (!prodVtx) return;
519 for (const auto& theMother: prodVtx->particles_in()) {
520 if (!theMother) continue;
521 allancestors.insert(theMother);
522 findParticleAncestors(theMother, allancestors);
523 }
524 }
525
527
528 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
529 auto endVtx = thePart->end_vertex();
530 if (!endVtx) return;
531 for (const auto& theDaughter: endVtx->particles_out()) {
532 if (!theDaughter) continue;
533 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
534 allstabledescendants.insert(theDaughter);
535 }
536 findParticleStableDescendants(theDaughter, allstabledescendants);
537 }
538 }
539
543
544 template <class T> bool isHardScatteringVertex(T pVert) {
545 if (pVert == nullptr) return false;
546 T pV = pVert;
547 int numOfPartIn(0);
548 int pdg(0);
549
550 do {
551 pVert = pV;
552 auto incoming = pVert->particles_in();
553 numOfPartIn = incoming.size();
554 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
555 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
556
557 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
558
559 if (numOfPartIn == 2) {
560 auto incoming = pVert->particles_in();
561 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
562 }
563 return false;
564}
565
569
570 template <class T, class U>
571 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
572 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
573 auto vtx = p->production_vertex();
574 if (!vtx) return false;
575 bool fromHad = false;
576 for ( const auto& parent : particles_in(vtx) ) {
577 if (!parent) continue;
578 // should this really go into parton-level territory?
579 // probably depends where BSM particles are being decayed
580 fromBSM |= isBSM(parent);
581 if (!isPhysical(parent)) return false;
582 fromTau |= isTau(parent);
583 if (isHadron(parent)&&!isBeam(parent)) {
584 if (!hadron) hadron = parent; // assumes linear hadron parentage
585 return true;
586 }
587 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
588 }
589 return fromHad;
590 }
591
594
595 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
596 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
597 decltype(thePart->end_vertex()) pVert(nullptr);
598 if (EndVert != nullptr) {
599 do {
600 bool samePart = false;
601 pVert = nullptr;
602 auto outgoing = EndVert->particles_out();
603 auto incoming = EndVert->particles_in();
604 for (const auto& itrDaug: outgoing) {
605 if (!itrDaug) continue;
606 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
607 // brem on generator level for tau
608 (outgoing.size() == 1 && incoming.size() == 1 &&
610 itrDaug->pdg_id() == thePart->pdg_id()) {
611 samePart = true;
612 pVert = itrDaug->end_vertex();
613 }
614 }
615 if (samePart) EndVert = pVert;
616 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
617 }
618 return EndVert;
619 }
620
622
623 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
624 if (!theVert) return {};
625 decltype(theVert->particles_out()) finalStatePart;
626 auto outgoing = theVert->particles_out();
627 for (const auto& thePart: outgoing) {
628 if (!thePart) continue;
629 finalStatePart.push_back(thePart);
630 if (isStable(thePart)) continue;
631 V pVert = findSimulatedEndVertex(thePart);
632 if (pVert == theVert) break; // to prevent Sherpa loop
633 if (pVert != nullptr) {
634 auto vecPart = findFinalStateParticles<V>(pVert);
635 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
636 }
637 }
638 return finalStatePart;
639 }
640#if !defined(XAOD_ANALYSIS)
641#include "AtlasHepMC/GenEvent.h"
642inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
643inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
644
645#endif
646}
647#endif

◆ isBoson() [3/3]

template<class T>
bool MC::isBoson ( const T & p)
inline

PDG rule 9: Two-digit numbers in the range 21–30 are provided for the Standard Model gauge and Higgs bosons.

PDG rule 11b: The graviton and the boson content of a two-Higgs-doublet scenario and of additional SU(2)×U(1) groups are found in the range 31–40.

Definition at line 370 of file HepMCHelpers.h.

389{
390 template <class VTX>
391 auto particles_in (const VTX* p) { return p->particles_in(); }
392 template <class VTX>
393 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
394
395 namespace Pythia8
396 {
398 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
399
400 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
401
402 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
403 }
404
405#include "AtlasPID.h"
406
408 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
409
411 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
412
414 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
415
417 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
418
420 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
421
423 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
424
426 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
427
429 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
430
432 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
433
435 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
436
440 template <class T> inline bool isStableOrSimDecayed(const T& p) {
441 const auto vertex = p->end_vertex();
442 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
443 }
444
446 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
447
449 template <class T> inline bool isSpecialNonInteracting(const T& p) {
450 const int apid = std::abs(p->pdg_id());
451 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
452 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
453 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
454 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
455 return false;
456 }
457
459
460 template <class T> T findMother(T thePart) {
461 auto partOriVert = thePart->production_vertex();
462 if (!partOriVert) return nullptr;
463
464 long partPDG = thePart->pdg_id();
465 long MotherPDG(0);
466
467 auto MothOriVert = partOriVert;
468 MothOriVert = nullptr;
469 T theMoth(nullptr);
470
471 size_t itr = 0;
472 do {
473 if (itr != 0) partOriVert = MothOriVert;
474 for ( const auto& p : particles_in(partOriVert) ) {
475 theMoth = p;
476 if (!theMoth) continue;
477 MotherPDG = theMoth->pdg_id();
478 MothOriVert = theMoth->production_vertex();
479 if (MotherPDG == partPDG) break;
480 }
481 itr++;
482 if (itr > 100) {
483 break;
484 }
485 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
486 MothOriVert != partOriVert);
487 return theMoth;
488 }
489
491
492 template <class C, class T> T findMatching(C TruthContainer, T p) {
493 T ptrPart = nullptr;
494 if (!p) return ptrPart;
495 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
496 for (T truthParticle : *TruthContainer) {
497 if (HepMC::is_sim_descendant(p,truthParticle)) {
498 ptrPart = truthParticle;
499 break;
500 }
501 }
502 }
503 else {
504 for (T truthParticle : TruthContainer) {
505 if (HepMC::is_sim_descendant(p,truthParticle)) {
506 ptrPart = truthParticle;
507 break;
508 }
509 }
510 }
511 return ptrPart;
512 }
514
515 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
516 auto prodVtx = thePart->production_vertex();
517 if (!prodVtx) return;
518 for (const auto& theMother: prodVtx->particles_in()) {
519 if (!theMother) continue;
520 allancestors.insert(theMother);
521 findParticleAncestors(theMother, allancestors);
522 }
523 }
524
526
527 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
528 auto endVtx = thePart->end_vertex();
529 if (!endVtx) return;
530 for (const auto& theDaughter: endVtx->particles_out()) {
531 if (!theDaughter) continue;
532 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
533 allstabledescendants.insert(theDaughter);
534 }
535 findParticleStableDescendants(theDaughter, allstabledescendants);
536 }
537 }
538
542
543 template <class T> bool isHardScatteringVertex(T pVert) {
544 if (pVert == nullptr) return false;
545 T pV = pVert;
546 int numOfPartIn(0);
547 int pdg(0);
548
549 do {
550 pVert = pV;
551 auto incoming = pVert->particles_in();
552 numOfPartIn = incoming.size();
553 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
554 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
555
556 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
557
558 if (numOfPartIn == 2) {
559 auto incoming = pVert->particles_in();
560 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
561 }
562 return false;
563}
564
568
569 template <class T, class U>
570 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
571 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
572 auto vtx = p->production_vertex();
573 if (!vtx) return false;
574 bool fromHad = false;
575 for ( const auto& parent : particles_in(vtx) ) {
576 if (!parent) continue;
577 // should this really go into parton-level territory?
578 // probably depends where BSM particles are being decayed
579 fromBSM |= isBSM(parent);
580 if (!isPhysical(parent)) return false;
581 fromTau |= isTau(parent);
582 if (isHadron(parent)&&!isBeam(parent)) {
583 if (!hadron) hadron = parent; // assumes linear hadron parentage
584 return true;
585 }
586 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
587 }
588 return fromHad;
589 }
590
593
594 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
595 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
596 decltype(thePart->end_vertex()) pVert(nullptr);
597 if (EndVert != nullptr) {
598 do {
599 bool samePart = false;
600 pVert = nullptr;
601 auto outgoing = EndVert->particles_out();
602 auto incoming = EndVert->particles_in();
603 for (const auto& itrDaug: outgoing) {
604 if (!itrDaug) continue;
605 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
606 // brem on generator level for tau
607 (outgoing.size() == 1 && incoming.size() == 1 &&
609 itrDaug->pdg_id() == thePart->pdg_id()) {
610 samePart = true;
611 pVert = itrDaug->end_vertex();
612 }
613 }
614 if (samePart) EndVert = pVert;
615 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
616 }
617 return EndVert;
618 }
619
621
622 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
623 if (!theVert) return {};
624 decltype(theVert->particles_out()) finalStatePart;
625 auto outgoing = theVert->particles_out();
626 for (const auto& thePart: outgoing) {
627 if (!thePart) continue;
628 finalStatePart.push_back(thePart);
629 if (isStable(thePart)) continue;
630 V pVert = findSimulatedEndVertex(thePart);
631 if (pVert == theVert) break; // to prevent Sherpa loop
632 if (pVert != nullptr) {
633 auto vecPart = findFinalStateParticles<V>(pVert);
634 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
635 }
636 }
637 return finalStatePart;
638 }
639#if !defined(XAOD_ANALYSIS)
640#include "AtlasHepMC/GenEvent.h"
641inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
642inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
643
644#endif
645}
646#endif

◆ isBottom() [1/2]

template<>
bool MC::isBottom ( const int & p)
inline

Definition at line 184 of file HepMCHelpers.h.

184: 0;

◆ isBottom() [2/2]

template<class T>
bool MC::isBottom ( const T & p)
inline

Definition at line 183 of file HepMCHelpers.h.

◆ isBottomBaryon()

template<class T>
bool MC::isBottomBaryon ( const T & p)
inline

Definition at line 936 of file HepMCHelpers.h.

955{
956 template <class VTX>
957 auto particles_in (const VTX* p) { return p->particles_in(); }
958 template <class VTX>
959 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
960
961 namespace Pythia8
962 {
964 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
965
966 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
967
968 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
969 }
970
971#include "AtlasPID.h"
972
974 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
975
977 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
978
980 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
981
983 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
984
986 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
987
989 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
990
992 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
993
995 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
996
998 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
999
1001 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1002
1006 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1007 const auto vertex = p->end_vertex();
1008 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1009 }
1010
1012 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1013
1015 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1016 const int apid = std::abs(p->pdg_id());
1017 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1018 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1019 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1020 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1021 return false;
1022 }
1023
1025
1026 template <class T> T findMother(T thePart) {
1027 auto partOriVert = thePart->production_vertex();
1028 if (!partOriVert) return nullptr;
1029
1030 long partPDG = thePart->pdg_id();
1031 long MotherPDG(0);
1032
1033 auto MothOriVert = partOriVert;
1034 MothOriVert = nullptr;
1035 T theMoth(nullptr);
1036
1037 size_t itr = 0;
1038 do {
1039 if (itr != 0) partOriVert = MothOriVert;
1040 for ( const auto& p : particles_in(partOriVert) ) {
1041 theMoth = p;
1042 if (!theMoth) continue;
1043 MotherPDG = theMoth->pdg_id();
1044 MothOriVert = theMoth->production_vertex();
1045 if (MotherPDG == partPDG) break;
1046 }
1047 itr++;
1048 if (itr > 100) {
1049 break;
1050 }
1051 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1052 MothOriVert != partOriVert);
1053 return theMoth;
1054 }
1055
1057
1058 template <class C, class T> T findMatching(C TruthContainer, T p) {
1059 T ptrPart = nullptr;
1060 if (!p) return ptrPart;
1061 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1062 for (T truthParticle : *TruthContainer) {
1063 if (HepMC::is_sim_descendant(p,truthParticle)) {
1064 ptrPart = truthParticle;
1065 break;
1066 }
1067 }
1068 }
1069 else {
1070 for (T truthParticle : TruthContainer) {
1071 if (HepMC::is_sim_descendant(p,truthParticle)) {
1072 ptrPart = truthParticle;
1073 break;
1074 }
1075 }
1076 }
1077 return ptrPart;
1078 }
1080
1081 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1082 auto prodVtx = thePart->production_vertex();
1083 if (!prodVtx) return;
1084 for (const auto& theMother: prodVtx->particles_in()) {
1085 if (!theMother) continue;
1086 allancestors.insert(theMother);
1087 findParticleAncestors(theMother, allancestors);
1088 }
1089 }
1090
1092
1093 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1094 auto endVtx = thePart->end_vertex();
1095 if (!endVtx) return;
1096 for (const auto& theDaughter: endVtx->particles_out()) {
1097 if (!theDaughter) continue;
1098 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1099 allstabledescendants.insert(theDaughter);
1100 }
1101 findParticleStableDescendants(theDaughter, allstabledescendants);
1102 }
1103 }
1104
1108
1109 template <class T> bool isHardScatteringVertex(T pVert) {
1110 if (pVert == nullptr) return false;
1111 T pV = pVert;
1112 int numOfPartIn(0);
1113 int pdg(0);
1114
1115 do {
1116 pVert = pV;
1117 auto incoming = pVert->particles_in();
1118 numOfPartIn = incoming.size();
1119 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1120 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1121
1122 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1123
1124 if (numOfPartIn == 2) {
1125 auto incoming = pVert->particles_in();
1126 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1127 }
1128 return false;
1129}
1130
1134
1135 template <class T, class U>
1136 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1137 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1138 auto vtx = p->production_vertex();
1139 if (!vtx) return false;
1140 bool fromHad = false;
1141 for ( const auto& parent : particles_in(vtx) ) {
1142 if (!parent) continue;
1143 // should this really go into parton-level territory?
1144 // probably depends where BSM particles are being decayed
1145 fromBSM |= isBSM(parent);
1146 if (!isPhysical(parent)) return false;
1147 fromTau |= isTau(parent);
1148 if (isHadron(parent)&&!isBeam(parent)) {
1149 if (!hadron) hadron = parent; // assumes linear hadron parentage
1150 return true;
1151 }
1152 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1153 }
1154 return fromHad;
1155 }
1156
1159
1160 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1161 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1162 decltype(thePart->end_vertex()) pVert(nullptr);
1163 if (EndVert != nullptr) {
1164 do {
1165 bool samePart = false;
1166 pVert = nullptr;
1167 auto outgoing = EndVert->particles_out();
1168 auto incoming = EndVert->particles_in();
1169 for (const auto& itrDaug: outgoing) {
1170 if (!itrDaug) continue;
1171 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1172 // brem on generator level for tau
1173 (outgoing.size() == 1 && incoming.size() == 1 &&
1175 itrDaug->pdg_id() == thePart->pdg_id()) {
1176 samePart = true;
1177 pVert = itrDaug->end_vertex();
1178 }
1179 }
1180 if (samePart) EndVert = pVert;
1181 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1182 }
1183 return EndVert;
1184 }
1185
1187
1188 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1189 if (!theVert) return {};
1190 decltype(theVert->particles_out()) finalStatePart;
1191 auto outgoing = theVert->particles_out();
1192 for (const auto& thePart: outgoing) {
1193 if (!thePart) continue;
1194 finalStatePart.push_back(thePart);
1195 if (isStable(thePart)) continue;
1196 V pVert = findSimulatedEndVertex(thePart);
1197 if (pVert == theVert) break; // to prevent Sherpa loop
1198 if (pVert != nullptr) {
1199 auto vecPart = findFinalStateParticles<V>(pVert);
1200 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1201 }
1202 }
1203 return finalStatePart;
1204 }
1205#if !defined(XAOD_ANALYSIS)
1206#include "AtlasHepMC/GenEvent.h"
1207inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1208inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1209
1210#endif
1211}
1212#endif

◆ isBottomHadron()

template<class T>
bool MC::isBottomHadron ( const T & p)
inline

Definition at line 913 of file HepMCHelpers.h.

932{
933 template <class VTX>
934 auto particles_in (const VTX* p) { return p->particles_in(); }
935 template <class VTX>
936 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
937
938 namespace Pythia8
939 {
941 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
942
943 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
944
945 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
946 }
947
948#include "AtlasPID.h"
949
951 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
952
954 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
955
957 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
958
960 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
961
963 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
964
966 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
967
969 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
970
972 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
973
975 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
976
978 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
979
983 template <class T> inline bool isStableOrSimDecayed(const T& p) {
984 const auto vertex = p->end_vertex();
985 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
986 }
987
989 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
990
992 template <class T> inline bool isSpecialNonInteracting(const T& p) {
993 const int apid = std::abs(p->pdg_id());
994 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
995 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
996 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
997 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
998 return false;
999 }
1000
1002
1003 template <class T> T findMother(T thePart) {
1004 auto partOriVert = thePart->production_vertex();
1005 if (!partOriVert) return nullptr;
1006
1007 long partPDG = thePart->pdg_id();
1008 long MotherPDG(0);
1009
1010 auto MothOriVert = partOriVert;
1011 MothOriVert = nullptr;
1012 T theMoth(nullptr);
1013
1014 size_t itr = 0;
1015 do {
1016 if (itr != 0) partOriVert = MothOriVert;
1017 for ( const auto& p : particles_in(partOriVert) ) {
1018 theMoth = p;
1019 if (!theMoth) continue;
1020 MotherPDG = theMoth->pdg_id();
1021 MothOriVert = theMoth->production_vertex();
1022 if (MotherPDG == partPDG) break;
1023 }
1024 itr++;
1025 if (itr > 100) {
1026 break;
1027 }
1028 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1029 MothOriVert != partOriVert);
1030 return theMoth;
1031 }
1032
1034
1035 template <class C, class T> T findMatching(C TruthContainer, T p) {
1036 T ptrPart = nullptr;
1037 if (!p) return ptrPart;
1038 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1039 for (T truthParticle : *TruthContainer) {
1040 if (HepMC::is_sim_descendant(p,truthParticle)) {
1041 ptrPart = truthParticle;
1042 break;
1043 }
1044 }
1045 }
1046 else {
1047 for (T truthParticle : TruthContainer) {
1048 if (HepMC::is_sim_descendant(p,truthParticle)) {
1049 ptrPart = truthParticle;
1050 break;
1051 }
1052 }
1053 }
1054 return ptrPart;
1055 }
1057
1058 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1059 auto prodVtx = thePart->production_vertex();
1060 if (!prodVtx) return;
1061 for (const auto& theMother: prodVtx->particles_in()) {
1062 if (!theMother) continue;
1063 allancestors.insert(theMother);
1064 findParticleAncestors(theMother, allancestors);
1065 }
1066 }
1067
1069
1070 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1071 auto endVtx = thePart->end_vertex();
1072 if (!endVtx) return;
1073 for (const auto& theDaughter: endVtx->particles_out()) {
1074 if (!theDaughter) continue;
1075 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1076 allstabledescendants.insert(theDaughter);
1077 }
1078 findParticleStableDescendants(theDaughter, allstabledescendants);
1079 }
1080 }
1081
1085
1086 template <class T> bool isHardScatteringVertex(T pVert) {
1087 if (pVert == nullptr) return false;
1088 T pV = pVert;
1089 int numOfPartIn(0);
1090 int pdg(0);
1091
1092 do {
1093 pVert = pV;
1094 auto incoming = pVert->particles_in();
1095 numOfPartIn = incoming.size();
1096 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1097 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1098
1099 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1100
1101 if (numOfPartIn == 2) {
1102 auto incoming = pVert->particles_in();
1103 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1104 }
1105 return false;
1106}
1107
1111
1112 template <class T, class U>
1113 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1114 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1115 auto vtx = p->production_vertex();
1116 if (!vtx) return false;
1117 bool fromHad = false;
1118 for ( const auto& parent : particles_in(vtx) ) {
1119 if (!parent) continue;
1120 // should this really go into parton-level territory?
1121 // probably depends where BSM particles are being decayed
1122 fromBSM |= isBSM(parent);
1123 if (!isPhysical(parent)) return false;
1124 fromTau |= isTau(parent);
1125 if (isHadron(parent)&&!isBeam(parent)) {
1126 if (!hadron) hadron = parent; // assumes linear hadron parentage
1127 return true;
1128 }
1129 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1130 }
1131 return fromHad;
1132 }
1133
1136
1137 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1138 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1139 decltype(thePart->end_vertex()) pVert(nullptr);
1140 if (EndVert != nullptr) {
1141 do {
1142 bool samePart = false;
1143 pVert = nullptr;
1144 auto outgoing = EndVert->particles_out();
1145 auto incoming = EndVert->particles_in();
1146 for (const auto& itrDaug: outgoing) {
1147 if (!itrDaug) continue;
1148 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1149 // brem on generator level for tau
1150 (outgoing.size() == 1 && incoming.size() == 1 &&
1152 itrDaug->pdg_id() == thePart->pdg_id()) {
1153 samePart = true;
1154 pVert = itrDaug->end_vertex();
1155 }
1156 }
1157 if (samePart) EndVert = pVert;
1158 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1159 }
1160 return EndVert;
1161 }
1162
1164
1165 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1166 if (!theVert) return {};
1167 decltype(theVert->particles_out()) finalStatePart;
1168 auto outgoing = theVert->particles_out();
1169 for (const auto& thePart: outgoing) {
1170 if (!thePart) continue;
1171 finalStatePart.push_back(thePart);
1172 if (isStable(thePart)) continue;
1173 V pVert = findSimulatedEndVertex(thePart);
1174 if (pVert == theVert) break; // to prevent Sherpa loop
1175 if (pVert != nullptr) {
1176 auto vecPart = findFinalStateParticles<V>(pVert);
1177 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1178 }
1179 }
1180 return finalStatePart;
1181 }
1182#if !defined(XAOD_ANALYSIS)
1183#include "AtlasHepMC/GenEvent.h"
1184inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1185inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1186
1187#endif
1188}
1189#endif

◆ isBottomMeson()

template<class T>
bool MC::isBottomMeson ( const T & p)
inline

Definition at line 920 of file HepMCHelpers.h.

939{
940 template <class VTX>
941 auto particles_in (const VTX* p) { return p->particles_in(); }
942 template <class VTX>
943 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
944
945 namespace Pythia8
946 {
948 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
949
950 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
951
952 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
953 }
954
955#include "AtlasPID.h"
956
958 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
959
961 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
962
964 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
965
967 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
968
970 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
971
973 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
974
976 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
977
979 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
980
982 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
983
985 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
986
990 template <class T> inline bool isStableOrSimDecayed(const T& p) {
991 const auto vertex = p->end_vertex();
992 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
993 }
994
996 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
997
999 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1000 const int apid = std::abs(p->pdg_id());
1001 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1002 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1003 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1004 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1005 return false;
1006 }
1007
1009
1010 template <class T> T findMother(T thePart) {
1011 auto partOriVert = thePart->production_vertex();
1012 if (!partOriVert) return nullptr;
1013
1014 long partPDG = thePart->pdg_id();
1015 long MotherPDG(0);
1016
1017 auto MothOriVert = partOriVert;
1018 MothOriVert = nullptr;
1019 T theMoth(nullptr);
1020
1021 size_t itr = 0;
1022 do {
1023 if (itr != 0) partOriVert = MothOriVert;
1024 for ( const auto& p : particles_in(partOriVert) ) {
1025 theMoth = p;
1026 if (!theMoth) continue;
1027 MotherPDG = theMoth->pdg_id();
1028 MothOriVert = theMoth->production_vertex();
1029 if (MotherPDG == partPDG) break;
1030 }
1031 itr++;
1032 if (itr > 100) {
1033 break;
1034 }
1035 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1036 MothOriVert != partOriVert);
1037 return theMoth;
1038 }
1039
1041
1042 template <class C, class T> T findMatching(C TruthContainer, T p) {
1043 T ptrPart = nullptr;
1044 if (!p) return ptrPart;
1045 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1046 for (T truthParticle : *TruthContainer) {
1047 if (HepMC::is_sim_descendant(p,truthParticle)) {
1048 ptrPart = truthParticle;
1049 break;
1050 }
1051 }
1052 }
1053 else {
1054 for (T truthParticle : TruthContainer) {
1055 if (HepMC::is_sim_descendant(p,truthParticle)) {
1056 ptrPart = truthParticle;
1057 break;
1058 }
1059 }
1060 }
1061 return ptrPart;
1062 }
1064
1065 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1066 auto prodVtx = thePart->production_vertex();
1067 if (!prodVtx) return;
1068 for (const auto& theMother: prodVtx->particles_in()) {
1069 if (!theMother) continue;
1070 allancestors.insert(theMother);
1071 findParticleAncestors(theMother, allancestors);
1072 }
1073 }
1074
1076
1077 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1078 auto endVtx = thePart->end_vertex();
1079 if (!endVtx) return;
1080 for (const auto& theDaughter: endVtx->particles_out()) {
1081 if (!theDaughter) continue;
1082 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1083 allstabledescendants.insert(theDaughter);
1084 }
1085 findParticleStableDescendants(theDaughter, allstabledescendants);
1086 }
1087 }
1088
1092
1093 template <class T> bool isHardScatteringVertex(T pVert) {
1094 if (pVert == nullptr) return false;
1095 T pV = pVert;
1096 int numOfPartIn(0);
1097 int pdg(0);
1098
1099 do {
1100 pVert = pV;
1101 auto incoming = pVert->particles_in();
1102 numOfPartIn = incoming.size();
1103 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1104 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1105
1106 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1107
1108 if (numOfPartIn == 2) {
1109 auto incoming = pVert->particles_in();
1110 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1111 }
1112 return false;
1113}
1114
1118
1119 template <class T, class U>
1120 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1121 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1122 auto vtx = p->production_vertex();
1123 if (!vtx) return false;
1124 bool fromHad = false;
1125 for ( const auto& parent : particles_in(vtx) ) {
1126 if (!parent) continue;
1127 // should this really go into parton-level territory?
1128 // probably depends where BSM particles are being decayed
1129 fromBSM |= isBSM(parent);
1130 if (!isPhysical(parent)) return false;
1131 fromTau |= isTau(parent);
1132 if (isHadron(parent)&&!isBeam(parent)) {
1133 if (!hadron) hadron = parent; // assumes linear hadron parentage
1134 return true;
1135 }
1136 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1137 }
1138 return fromHad;
1139 }
1140
1143
1144 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1145 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1146 decltype(thePart->end_vertex()) pVert(nullptr);
1147 if (EndVert != nullptr) {
1148 do {
1149 bool samePart = false;
1150 pVert = nullptr;
1151 auto outgoing = EndVert->particles_out();
1152 auto incoming = EndVert->particles_in();
1153 for (const auto& itrDaug: outgoing) {
1154 if (!itrDaug) continue;
1155 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1156 // brem on generator level for tau
1157 (outgoing.size() == 1 && incoming.size() == 1 &&
1159 itrDaug->pdg_id() == thePart->pdg_id()) {
1160 samePart = true;
1161 pVert = itrDaug->end_vertex();
1162 }
1163 }
1164 if (samePart) EndVert = pVert;
1165 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1166 }
1167 return EndVert;
1168 }
1169
1171
1172 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1173 if (!theVert) return {};
1174 decltype(theVert->particles_out()) finalStatePart;
1175 auto outgoing = theVert->particles_out();
1176 for (const auto& thePart: outgoing) {
1177 if (!thePart) continue;
1178 finalStatePart.push_back(thePart);
1179 if (isStable(thePart)) continue;
1180 V pVert = findSimulatedEndVertex(thePart);
1181 if (pVert == theVert) break; // to prevent Sherpa loop
1182 if (pVert != nullptr) {
1183 auto vecPart = findFinalStateParticles<V>(pVert);
1184 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1185 }
1186 }
1187 return finalStatePart;
1188 }
1189#if !defined(XAOD_ANALYSIS)
1190#include "AtlasHepMC/GenEvent.h"
1191inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1192inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1193
1194#endif
1195}
1196#endif

◆ isBSM() [1/3]

template<>
bool MC::isBSM ( const DecodedPID & p)
inline

Definition at line 848 of file HepMCHelpers.h.

867{
868 template <class VTX>
869 auto particles_in (const VTX* p) { return p->particles_in(); }
870 template <class VTX>
871 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
872
873 namespace Pythia8
874 {
876 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
877
878 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
879
880 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
881 }
882
883#include "AtlasPID.h"
884
886 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
887
889 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
890
892 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
893
895 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
896
898 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
899
901 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
902
904 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
905
907 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
908
910 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
911
913 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
914
918 template <class T> inline bool isStableOrSimDecayed(const T& p) {
919 const auto vertex = p->end_vertex();
920 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
921 }
922
924 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
925
927 template <class T> inline bool isSpecialNonInteracting(const T& p) {
928 const int apid = std::abs(p->pdg_id());
929 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
930 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
931 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
932 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
933 return false;
934 }
935
937
938 template <class T> T findMother(T thePart) {
939 auto partOriVert = thePart->production_vertex();
940 if (!partOriVert) return nullptr;
941
942 long partPDG = thePart->pdg_id();
943 long MotherPDG(0);
944
945 auto MothOriVert = partOriVert;
946 MothOriVert = nullptr;
947 T theMoth(nullptr);
948
949 size_t itr = 0;
950 do {
951 if (itr != 0) partOriVert = MothOriVert;
952 for ( const auto& p : particles_in(partOriVert) ) {
953 theMoth = p;
954 if (!theMoth) continue;
955 MotherPDG = theMoth->pdg_id();
956 MothOriVert = theMoth->production_vertex();
957 if (MotherPDG == partPDG) break;
958 }
959 itr++;
960 if (itr > 100) {
961 break;
962 }
963 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
964 MothOriVert != partOriVert);
965 return theMoth;
966 }
967
969
970 template <class C, class T> T findMatching(C TruthContainer, T p) {
971 T ptrPart = nullptr;
972 if (!p) return ptrPart;
973 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
974 for (T truthParticle : *TruthContainer) {
975 if (HepMC::is_sim_descendant(p,truthParticle)) {
976 ptrPart = truthParticle;
977 break;
978 }
979 }
980 }
981 else {
982 for (T truthParticle : TruthContainer) {
983 if (HepMC::is_sim_descendant(p,truthParticle)) {
984 ptrPart = truthParticle;
985 break;
986 }
987 }
988 }
989 return ptrPart;
990 }
992
993 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
994 auto prodVtx = thePart->production_vertex();
995 if (!prodVtx) return;
996 for (const auto& theMother: prodVtx->particles_in()) {
997 if (!theMother) continue;
998 allancestors.insert(theMother);
999 findParticleAncestors(theMother, allancestors);
1000 }
1001 }
1002
1004
1005 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1006 auto endVtx = thePart->end_vertex();
1007 if (!endVtx) return;
1008 for (const auto& theDaughter: endVtx->particles_out()) {
1009 if (!theDaughter) continue;
1010 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1011 allstabledescendants.insert(theDaughter);
1012 }
1013 findParticleStableDescendants(theDaughter, allstabledescendants);
1014 }
1015 }
1016
1020
1021 template <class T> bool isHardScatteringVertex(T pVert) {
1022 if (pVert == nullptr) return false;
1023 T pV = pVert;
1024 int numOfPartIn(0);
1025 int pdg(0);
1026
1027 do {
1028 pVert = pV;
1029 auto incoming = pVert->particles_in();
1030 numOfPartIn = incoming.size();
1031 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1032 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1033
1034 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1035
1036 if (numOfPartIn == 2) {
1037 auto incoming = pVert->particles_in();
1038 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1039 }
1040 return false;
1041}
1042
1046
1047 template <class T, class U>
1048 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1049 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1050 auto vtx = p->production_vertex();
1051 if (!vtx) return false;
1052 bool fromHad = false;
1053 for ( const auto& parent : particles_in(vtx) ) {
1054 if (!parent) continue;
1055 // should this really go into parton-level territory?
1056 // probably depends where BSM particles are being decayed
1057 fromBSM |= isBSM(parent);
1058 if (!isPhysical(parent)) return false;
1059 fromTau |= isTau(parent);
1060 if (isHadron(parent)&&!isBeam(parent)) {
1061 if (!hadron) hadron = parent; // assumes linear hadron parentage
1062 return true;
1063 }
1064 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1065 }
1066 return fromHad;
1067 }
1068
1071
1072 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1073 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1074 decltype(thePart->end_vertex()) pVert(nullptr);
1075 if (EndVert != nullptr) {
1076 do {
1077 bool samePart = false;
1078 pVert = nullptr;
1079 auto outgoing = EndVert->particles_out();
1080 auto incoming = EndVert->particles_in();
1081 for (const auto& itrDaug: outgoing) {
1082 if (!itrDaug) continue;
1083 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1084 // brem on generator level for tau
1085 (outgoing.size() == 1 && incoming.size() == 1 &&
1087 itrDaug->pdg_id() == thePart->pdg_id()) {
1088 samePart = true;
1089 pVert = itrDaug->end_vertex();
1090 }
1091 }
1092 if (samePart) EndVert = pVert;
1093 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1094 }
1095 return EndVert;
1096 }
1097
1099
1100 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1101 if (!theVert) return {};
1102 decltype(theVert->particles_out()) finalStatePart;
1103 auto outgoing = theVert->particles_out();
1104 for (const auto& thePart: outgoing) {
1105 if (!thePart) continue;
1106 finalStatePart.push_back(thePart);
1107 if (isStable(thePart)) continue;
1108 V pVert = findSimulatedEndVertex(thePart);
1109 if (pVert == theVert) break; // to prevent Sherpa loop
1110 if (pVert != nullptr) {
1111 auto vecPart = findFinalStateParticles<V>(pVert);
1112 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1113 }
1114 }
1115 return finalStatePart;
1116 }
1117#if !defined(XAOD_ANALYSIS)
1118#include "AtlasHepMC/GenEvent.h"
1119inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1120inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1121
1122#endif
1123}
1124#endif

◆ isBSM() [2/3]

template<>
bool MC::isBSM ( const int & p)
inline

Definition at line 865 of file HepMCHelpers.h.

884{
885 template <class VTX>
886 auto particles_in (const VTX* p) { return p->particles_in(); }
887 template <class VTX>
888 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
889
890 namespace Pythia8
891 {
893 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
894
895 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
896
897 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
898 }
899
900#include "AtlasPID.h"
901
903 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
904
906 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
907
909 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
910
912 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
913
915 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
916
918 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
919
921 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
922
924 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
925
927 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
928
930 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
931
935 template <class T> inline bool isStableOrSimDecayed(const T& p) {
936 const auto vertex = p->end_vertex();
937 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
938 }
939
941 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
942
944 template <class T> inline bool isSpecialNonInteracting(const T& p) {
945 const int apid = std::abs(p->pdg_id());
946 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
947 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
948 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
949 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
950 return false;
951 }
952
954
955 template <class T> T findMother(T thePart) {
956 auto partOriVert = thePart->production_vertex();
957 if (!partOriVert) return nullptr;
958
959 long partPDG = thePart->pdg_id();
960 long MotherPDG(0);
961
962 auto MothOriVert = partOriVert;
963 MothOriVert = nullptr;
964 T theMoth(nullptr);
965
966 size_t itr = 0;
967 do {
968 if (itr != 0) partOriVert = MothOriVert;
969 for ( const auto& p : particles_in(partOriVert) ) {
970 theMoth = p;
971 if (!theMoth) continue;
972 MotherPDG = theMoth->pdg_id();
973 MothOriVert = theMoth->production_vertex();
974 if (MotherPDG == partPDG) break;
975 }
976 itr++;
977 if (itr > 100) {
978 break;
979 }
980 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
981 MothOriVert != partOriVert);
982 return theMoth;
983 }
984
986
987 template <class C, class T> T findMatching(C TruthContainer, T p) {
988 T ptrPart = nullptr;
989 if (!p) return ptrPart;
990 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
991 for (T truthParticle : *TruthContainer) {
992 if (HepMC::is_sim_descendant(p,truthParticle)) {
993 ptrPart = truthParticle;
994 break;
995 }
996 }
997 }
998 else {
999 for (T truthParticle : TruthContainer) {
1000 if (HepMC::is_sim_descendant(p,truthParticle)) {
1001 ptrPart = truthParticle;
1002 break;
1003 }
1004 }
1005 }
1006 return ptrPart;
1007 }
1009
1010 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1011 auto prodVtx = thePart->production_vertex();
1012 if (!prodVtx) return;
1013 for (const auto& theMother: prodVtx->particles_in()) {
1014 if (!theMother) continue;
1015 allancestors.insert(theMother);
1016 findParticleAncestors(theMother, allancestors);
1017 }
1018 }
1019
1021
1022 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1023 auto endVtx = thePart->end_vertex();
1024 if (!endVtx) return;
1025 for (const auto& theDaughter: endVtx->particles_out()) {
1026 if (!theDaughter) continue;
1027 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1028 allstabledescendants.insert(theDaughter);
1029 }
1030 findParticleStableDescendants(theDaughter, allstabledescendants);
1031 }
1032 }
1033
1037
1038 template <class T> bool isHardScatteringVertex(T pVert) {
1039 if (pVert == nullptr) return false;
1040 T pV = pVert;
1041 int numOfPartIn(0);
1042 int pdg(0);
1043
1044 do {
1045 pVert = pV;
1046 auto incoming = pVert->particles_in();
1047 numOfPartIn = incoming.size();
1048 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1049 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1050
1051 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1052
1053 if (numOfPartIn == 2) {
1054 auto incoming = pVert->particles_in();
1055 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1056 }
1057 return false;
1058}
1059
1063
1064 template <class T, class U>
1065 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1066 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1067 auto vtx = p->production_vertex();
1068 if (!vtx) return false;
1069 bool fromHad = false;
1070 for ( const auto& parent : particles_in(vtx) ) {
1071 if (!parent) continue;
1072 // should this really go into parton-level territory?
1073 // probably depends where BSM particles are being decayed
1074 fromBSM |= isBSM(parent);
1075 if (!isPhysical(parent)) return false;
1076 fromTau |= isTau(parent);
1077 if (isHadron(parent)&&!isBeam(parent)) {
1078 if (!hadron) hadron = parent; // assumes linear hadron parentage
1079 return true;
1080 }
1081 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1082 }
1083 return fromHad;
1084 }
1085
1088
1089 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1090 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1091 decltype(thePart->end_vertex()) pVert(nullptr);
1092 if (EndVert != nullptr) {
1093 do {
1094 bool samePart = false;
1095 pVert = nullptr;
1096 auto outgoing = EndVert->particles_out();
1097 auto incoming = EndVert->particles_in();
1098 for (const auto& itrDaug: outgoing) {
1099 if (!itrDaug) continue;
1100 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1101 // brem on generator level for tau
1102 (outgoing.size() == 1 && incoming.size() == 1 &&
1104 itrDaug->pdg_id() == thePart->pdg_id()) {
1105 samePart = true;
1106 pVert = itrDaug->end_vertex();
1107 }
1108 }
1109 if (samePart) EndVert = pVert;
1110 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1111 }
1112 return EndVert;
1113 }
1114
1116
1117 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1118 if (!theVert) return {};
1119 decltype(theVert->particles_out()) finalStatePart;
1120 auto outgoing = theVert->particles_out();
1121 for (const auto& thePart: outgoing) {
1122 if (!thePart) continue;
1123 finalStatePart.push_back(thePart);
1124 if (isStable(thePart)) continue;
1125 V pVert = findSimulatedEndVertex(thePart);
1126 if (pVert == theVert) break; // to prevent Sherpa loop
1127 if (pVert != nullptr) {
1128 auto vecPart = findFinalStateParticles<V>(pVert);
1129 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1130 }
1131 }
1132 return finalStatePart;
1133 }
1134#if !defined(XAOD_ANALYSIS)
1135#include "AtlasHepMC/GenEvent.h"
1136inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1137inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1138
1139#endif
1140}
1141#endif

◆ isBSM() [3/3]

template<class T>
bool MC::isBSM ( const T & p)
inline

APID: graviton and all Higgs extensions are BSM.

Definition at line 847 of file HepMCHelpers.h.

866{
867 template <class VTX>
868 auto particles_in (const VTX* p) { return p->particles_in(); }
869 template <class VTX>
870 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
871
872 namespace Pythia8
873 {
875 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
876
877 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
878
879 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
880 }
881
882#include "AtlasPID.h"
883
885 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
886
888 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
889
891 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
892
894 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
895
897 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
898
900 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
901
903 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
904
906 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
907
909 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
910
912 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
913
917 template <class T> inline bool isStableOrSimDecayed(const T& p) {
918 const auto vertex = p->end_vertex();
919 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
920 }
921
923 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
924
926 template <class T> inline bool isSpecialNonInteracting(const T& p) {
927 const int apid = std::abs(p->pdg_id());
928 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
929 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
930 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
931 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
932 return false;
933 }
934
936
937 template <class T> T findMother(T thePart) {
938 auto partOriVert = thePart->production_vertex();
939 if (!partOriVert) return nullptr;
940
941 long partPDG = thePart->pdg_id();
942 long MotherPDG(0);
943
944 auto MothOriVert = partOriVert;
945 MothOriVert = nullptr;
946 T theMoth(nullptr);
947
948 size_t itr = 0;
949 do {
950 if (itr != 0) partOriVert = MothOriVert;
951 for ( const auto& p : particles_in(partOriVert) ) {
952 theMoth = p;
953 if (!theMoth) continue;
954 MotherPDG = theMoth->pdg_id();
955 MothOriVert = theMoth->production_vertex();
956 if (MotherPDG == partPDG) break;
957 }
958 itr++;
959 if (itr > 100) {
960 break;
961 }
962 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
963 MothOriVert != partOriVert);
964 return theMoth;
965 }
966
968
969 template <class C, class T> T findMatching(C TruthContainer, T p) {
970 T ptrPart = nullptr;
971 if (!p) return ptrPart;
972 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
973 for (T truthParticle : *TruthContainer) {
974 if (HepMC::is_sim_descendant(p,truthParticle)) {
975 ptrPart = truthParticle;
976 break;
977 }
978 }
979 }
980 else {
981 for (T truthParticle : TruthContainer) {
982 if (HepMC::is_sim_descendant(p,truthParticle)) {
983 ptrPart = truthParticle;
984 break;
985 }
986 }
987 }
988 return ptrPart;
989 }
991
992 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
993 auto prodVtx = thePart->production_vertex();
994 if (!prodVtx) return;
995 for (const auto& theMother: prodVtx->particles_in()) {
996 if (!theMother) continue;
997 allancestors.insert(theMother);
998 findParticleAncestors(theMother, allancestors);
999 }
1000 }
1001
1003
1004 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1005 auto endVtx = thePart->end_vertex();
1006 if (!endVtx) return;
1007 for (const auto& theDaughter: endVtx->particles_out()) {
1008 if (!theDaughter) continue;
1009 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1010 allstabledescendants.insert(theDaughter);
1011 }
1012 findParticleStableDescendants(theDaughter, allstabledescendants);
1013 }
1014 }
1015
1019
1020 template <class T> bool isHardScatteringVertex(T pVert) {
1021 if (pVert == nullptr) return false;
1022 T pV = pVert;
1023 int numOfPartIn(0);
1024 int pdg(0);
1025
1026 do {
1027 pVert = pV;
1028 auto incoming = pVert->particles_in();
1029 numOfPartIn = incoming.size();
1030 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1031 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1032
1033 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1034
1035 if (numOfPartIn == 2) {
1036 auto incoming = pVert->particles_in();
1037 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1038 }
1039 return false;
1040}
1041
1045
1046 template <class T, class U>
1047 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1048 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1049 auto vtx = p->production_vertex();
1050 if (!vtx) return false;
1051 bool fromHad = false;
1052 for ( const auto& parent : particles_in(vtx) ) {
1053 if (!parent) continue;
1054 // should this really go into parton-level territory?
1055 // probably depends where BSM particles are being decayed
1056 fromBSM |= isBSM(parent);
1057 if (!isPhysical(parent)) return false;
1058 fromTau |= isTau(parent);
1059 if (isHadron(parent)&&!isBeam(parent)) {
1060 if (!hadron) hadron = parent; // assumes linear hadron parentage
1061 return true;
1062 }
1063 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1064 }
1065 return fromHad;
1066 }
1067
1070
1071 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1072 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1073 decltype(thePart->end_vertex()) pVert(nullptr);
1074 if (EndVert != nullptr) {
1075 do {
1076 bool samePart = false;
1077 pVert = nullptr;
1078 auto outgoing = EndVert->particles_out();
1079 auto incoming = EndVert->particles_in();
1080 for (const auto& itrDaug: outgoing) {
1081 if (!itrDaug) continue;
1082 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1083 // brem on generator level for tau
1084 (outgoing.size() == 1 && incoming.size() == 1 &&
1086 itrDaug->pdg_id() == thePart->pdg_id()) {
1087 samePart = true;
1088 pVert = itrDaug->end_vertex();
1089 }
1090 }
1091 if (samePart) EndVert = pVert;
1092 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1093 }
1094 return EndVert;
1095 }
1096
1098
1099 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1100 if (!theVert) return {};
1101 decltype(theVert->particles_out()) finalStatePart;
1102 auto outgoing = theVert->particles_out();
1103 for (const auto& thePart: outgoing) {
1104 if (!thePart) continue;
1105 finalStatePart.push_back(thePart);
1106 if (isStable(thePart)) continue;
1107 V pVert = findSimulatedEndVertex(thePart);
1108 if (pVert == theVert) break; // to prevent Sherpa loop
1109 if (pVert != nullptr) {
1110 auto vecPart = findFinalStateParticles<V>(pVert);
1111 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1112 }
1113 }
1114 return finalStatePart;
1115 }
1116#if !defined(XAOD_ANALYSIS)
1117#include "AtlasHepMC/GenEvent.h"
1118inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1119inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1120
1121#endif
1122}
1123#endif

◆ isCCbarMeson() [1/3]

template<>
bool MC::isCCbarMeson ( const DecodedPID & p)
inline

Definition at line 924 of file HepMCHelpers.h.

943{
944 template <class VTX>
945 auto particles_in (const VTX* p) { return p->particles_in(); }
946 template <class VTX>
947 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
948
949 namespace Pythia8
950 {
952 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
953
954 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
955
956 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
957 }
958
959#include "AtlasPID.h"
960
962 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
963
965 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
966
968 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
969
971 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
972
974 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
975
977 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
978
980 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
981
983 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
984
986 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
987
989 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
990
994 template <class T> inline bool isStableOrSimDecayed(const T& p) {
995 const auto vertex = p->end_vertex();
996 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
997 }
998
1000 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1001
1003 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1004 const int apid = std::abs(p->pdg_id());
1005 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1006 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1007 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1008 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1009 return false;
1010 }
1011
1013
1014 template <class T> T findMother(T thePart) {
1015 auto partOriVert = thePart->production_vertex();
1016 if (!partOriVert) return nullptr;
1017
1018 long partPDG = thePart->pdg_id();
1019 long MotherPDG(0);
1020
1021 auto MothOriVert = partOriVert;
1022 MothOriVert = nullptr;
1023 T theMoth(nullptr);
1024
1025 size_t itr = 0;
1026 do {
1027 if (itr != 0) partOriVert = MothOriVert;
1028 for ( const auto& p : particles_in(partOriVert) ) {
1029 theMoth = p;
1030 if (!theMoth) continue;
1031 MotherPDG = theMoth->pdg_id();
1032 MothOriVert = theMoth->production_vertex();
1033 if (MotherPDG == partPDG) break;
1034 }
1035 itr++;
1036 if (itr > 100) {
1037 break;
1038 }
1039 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1040 MothOriVert != partOriVert);
1041 return theMoth;
1042 }
1043
1045
1046 template <class C, class T> T findMatching(C TruthContainer, T p) {
1047 T ptrPart = nullptr;
1048 if (!p) return ptrPart;
1049 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1050 for (T truthParticle : *TruthContainer) {
1051 if (HepMC::is_sim_descendant(p,truthParticle)) {
1052 ptrPart = truthParticle;
1053 break;
1054 }
1055 }
1056 }
1057 else {
1058 for (T truthParticle : TruthContainer) {
1059 if (HepMC::is_sim_descendant(p,truthParticle)) {
1060 ptrPart = truthParticle;
1061 break;
1062 }
1063 }
1064 }
1065 return ptrPart;
1066 }
1068
1069 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1070 auto prodVtx = thePart->production_vertex();
1071 if (!prodVtx) return;
1072 for (const auto& theMother: prodVtx->particles_in()) {
1073 if (!theMother) continue;
1074 allancestors.insert(theMother);
1075 findParticleAncestors(theMother, allancestors);
1076 }
1077 }
1078
1080
1081 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1082 auto endVtx = thePart->end_vertex();
1083 if (!endVtx) return;
1084 for (const auto& theDaughter: endVtx->particles_out()) {
1085 if (!theDaughter) continue;
1086 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1087 allstabledescendants.insert(theDaughter);
1088 }
1089 findParticleStableDescendants(theDaughter, allstabledescendants);
1090 }
1091 }
1092
1096
1097 template <class T> bool isHardScatteringVertex(T pVert) {
1098 if (pVert == nullptr) return false;
1099 T pV = pVert;
1100 int numOfPartIn(0);
1101 int pdg(0);
1102
1103 do {
1104 pVert = pV;
1105 auto incoming = pVert->particles_in();
1106 numOfPartIn = incoming.size();
1107 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1108 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1109
1110 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1111
1112 if (numOfPartIn == 2) {
1113 auto incoming = pVert->particles_in();
1114 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1115 }
1116 return false;
1117}
1118
1122
1123 template <class T, class U>
1124 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1125 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1126 auto vtx = p->production_vertex();
1127 if (!vtx) return false;
1128 bool fromHad = false;
1129 for ( const auto& parent : particles_in(vtx) ) {
1130 if (!parent) continue;
1131 // should this really go into parton-level territory?
1132 // probably depends where BSM particles are being decayed
1133 fromBSM |= isBSM(parent);
1134 if (!isPhysical(parent)) return false;
1135 fromTau |= isTau(parent);
1136 if (isHadron(parent)&&!isBeam(parent)) {
1137 if (!hadron) hadron = parent; // assumes linear hadron parentage
1138 return true;
1139 }
1140 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1141 }
1142 return fromHad;
1143 }
1144
1147
1148 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1149 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1150 decltype(thePart->end_vertex()) pVert(nullptr);
1151 if (EndVert != nullptr) {
1152 do {
1153 bool samePart = false;
1154 pVert = nullptr;
1155 auto outgoing = EndVert->particles_out();
1156 auto incoming = EndVert->particles_in();
1157 for (const auto& itrDaug: outgoing) {
1158 if (!itrDaug) continue;
1159 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1160 // brem on generator level for tau
1161 (outgoing.size() == 1 && incoming.size() == 1 &&
1163 itrDaug->pdg_id() == thePart->pdg_id()) {
1164 samePart = true;
1165 pVert = itrDaug->end_vertex();
1166 }
1167 }
1168 if (samePart) EndVert = pVert;
1169 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1170 }
1171 return EndVert;
1172 }
1173
1175
1176 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1177 if (!theVert) return {};
1178 decltype(theVert->particles_out()) finalStatePart;
1179 auto outgoing = theVert->particles_out();
1180 for (const auto& thePart: outgoing) {
1181 if (!thePart) continue;
1182 finalStatePart.push_back(thePart);
1183 if (isStable(thePart)) continue;
1184 V pVert = findSimulatedEndVertex(thePart);
1185 if (pVert == theVert) break; // to prevent Sherpa loop
1186 if (pVert != nullptr) {
1187 auto vecPart = findFinalStateParticles<V>(pVert);
1188 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1189 }
1190 }
1191 return finalStatePart;
1192 }
1193#if !defined(XAOD_ANALYSIS)
1194#include "AtlasHepMC/GenEvent.h"
1195inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1196inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1197
1198#endif
1199}
1200#endif

◆ isCCbarMeson() [2/3]

template<>
bool MC::isCCbarMeson ( const int & p)
inline

Definition at line 925 of file HepMCHelpers.h.

944{
945 template <class VTX>
946 auto particles_in (const VTX* p) { return p->particles_in(); }
947 template <class VTX>
948 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
949
950 namespace Pythia8
951 {
953 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
954
955 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
956
957 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
958 }
959
960#include "AtlasPID.h"
961
963 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
964
966 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
967
969 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
970
972 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
973
975 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
976
978 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
979
981 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
982
984 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
985
987 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
988
990 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
991
995 template <class T> inline bool isStableOrSimDecayed(const T& p) {
996 const auto vertex = p->end_vertex();
997 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
998 }
999
1001 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1002
1004 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1005 const int apid = std::abs(p->pdg_id());
1006 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1007 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1008 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1009 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1010 return false;
1011 }
1012
1014
1015 template <class T> T findMother(T thePart) {
1016 auto partOriVert = thePart->production_vertex();
1017 if (!partOriVert) return nullptr;
1018
1019 long partPDG = thePart->pdg_id();
1020 long MotherPDG(0);
1021
1022 auto MothOriVert = partOriVert;
1023 MothOriVert = nullptr;
1024 T theMoth(nullptr);
1025
1026 size_t itr = 0;
1027 do {
1028 if (itr != 0) partOriVert = MothOriVert;
1029 for ( const auto& p : particles_in(partOriVert) ) {
1030 theMoth = p;
1031 if (!theMoth) continue;
1032 MotherPDG = theMoth->pdg_id();
1033 MothOriVert = theMoth->production_vertex();
1034 if (MotherPDG == partPDG) break;
1035 }
1036 itr++;
1037 if (itr > 100) {
1038 break;
1039 }
1040 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1041 MothOriVert != partOriVert);
1042 return theMoth;
1043 }
1044
1046
1047 template <class C, class T> T findMatching(C TruthContainer, T p) {
1048 T ptrPart = nullptr;
1049 if (!p) return ptrPart;
1050 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1051 for (T truthParticle : *TruthContainer) {
1052 if (HepMC::is_sim_descendant(p,truthParticle)) {
1053 ptrPart = truthParticle;
1054 break;
1055 }
1056 }
1057 }
1058 else {
1059 for (T truthParticle : TruthContainer) {
1060 if (HepMC::is_sim_descendant(p,truthParticle)) {
1061 ptrPart = truthParticle;
1062 break;
1063 }
1064 }
1065 }
1066 return ptrPart;
1067 }
1069
1070 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1071 auto prodVtx = thePart->production_vertex();
1072 if (!prodVtx) return;
1073 for (const auto& theMother: prodVtx->particles_in()) {
1074 if (!theMother) continue;
1075 allancestors.insert(theMother);
1076 findParticleAncestors(theMother, allancestors);
1077 }
1078 }
1079
1081
1082 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1083 auto endVtx = thePart->end_vertex();
1084 if (!endVtx) return;
1085 for (const auto& theDaughter: endVtx->particles_out()) {
1086 if (!theDaughter) continue;
1087 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1088 allstabledescendants.insert(theDaughter);
1089 }
1090 findParticleStableDescendants(theDaughter, allstabledescendants);
1091 }
1092 }
1093
1097
1098 template <class T> bool isHardScatteringVertex(T pVert) {
1099 if (pVert == nullptr) return false;
1100 T pV = pVert;
1101 int numOfPartIn(0);
1102 int pdg(0);
1103
1104 do {
1105 pVert = pV;
1106 auto incoming = pVert->particles_in();
1107 numOfPartIn = incoming.size();
1108 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1109 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1110
1111 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1112
1113 if (numOfPartIn == 2) {
1114 auto incoming = pVert->particles_in();
1115 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1116 }
1117 return false;
1118}
1119
1123
1124 template <class T, class U>
1125 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1126 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1127 auto vtx = p->production_vertex();
1128 if (!vtx) return false;
1129 bool fromHad = false;
1130 for ( const auto& parent : particles_in(vtx) ) {
1131 if (!parent) continue;
1132 // should this really go into parton-level territory?
1133 // probably depends where BSM particles are being decayed
1134 fromBSM |= isBSM(parent);
1135 if (!isPhysical(parent)) return false;
1136 fromTau |= isTau(parent);
1137 if (isHadron(parent)&&!isBeam(parent)) {
1138 if (!hadron) hadron = parent; // assumes linear hadron parentage
1139 return true;
1140 }
1141 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1142 }
1143 return fromHad;
1144 }
1145
1148
1149 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1150 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1151 decltype(thePart->end_vertex()) pVert(nullptr);
1152 if (EndVert != nullptr) {
1153 do {
1154 bool samePart = false;
1155 pVert = nullptr;
1156 auto outgoing = EndVert->particles_out();
1157 auto incoming = EndVert->particles_in();
1158 for (const auto& itrDaug: outgoing) {
1159 if (!itrDaug) continue;
1160 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1161 // brem on generator level for tau
1162 (outgoing.size() == 1 && incoming.size() == 1 &&
1164 itrDaug->pdg_id() == thePart->pdg_id()) {
1165 samePart = true;
1166 pVert = itrDaug->end_vertex();
1167 }
1168 }
1169 if (samePart) EndVert = pVert;
1170 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1171 }
1172 return EndVert;
1173 }
1174
1176
1177 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1178 if (!theVert) return {};
1179 decltype(theVert->particles_out()) finalStatePart;
1180 auto outgoing = theVert->particles_out();
1181 for (const auto& thePart: outgoing) {
1182 if (!thePart) continue;
1183 finalStatePart.push_back(thePart);
1184 if (isStable(thePart)) continue;
1185 V pVert = findSimulatedEndVertex(thePart);
1186 if (pVert == theVert) break; // to prevent Sherpa loop
1187 if (pVert != nullptr) {
1188 auto vecPart = findFinalStateParticles<V>(pVert);
1189 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1190 }
1191 }
1192 return finalStatePart;
1193 }
1194#if !defined(XAOD_ANALYSIS)
1195#include "AtlasHepMC/GenEvent.h"
1196inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1197inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1198
1199#endif
1200}
1201#endif

◆ isCCbarMeson() [3/3]

template<class T>
bool MC::isCCbarMeson ( const T & p)
inline

Definition at line 923 of file HepMCHelpers.h.

942{
943 template <class VTX>
944 auto particles_in (const VTX* p) { return p->particles_in(); }
945 template <class VTX>
946 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
947
948 namespace Pythia8
949 {
951 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
952
953 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
954
955 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
956 }
957
958#include "AtlasPID.h"
959
961 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
962
964 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
965
967 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
968
970 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
971
973 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
974
976 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
977
979 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
980
982 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
983
985 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
986
988 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
989
993 template <class T> inline bool isStableOrSimDecayed(const T& p) {
994 const auto vertex = p->end_vertex();
995 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
996 }
997
999 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1000
1002 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1003 const int apid = std::abs(p->pdg_id());
1004 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1005 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1006 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1007 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1008 return false;
1009 }
1010
1012
1013 template <class T> T findMother(T thePart) {
1014 auto partOriVert = thePart->production_vertex();
1015 if (!partOriVert) return nullptr;
1016
1017 long partPDG = thePart->pdg_id();
1018 long MotherPDG(0);
1019
1020 auto MothOriVert = partOriVert;
1021 MothOriVert = nullptr;
1022 T theMoth(nullptr);
1023
1024 size_t itr = 0;
1025 do {
1026 if (itr != 0) partOriVert = MothOriVert;
1027 for ( const auto& p : particles_in(partOriVert) ) {
1028 theMoth = p;
1029 if (!theMoth) continue;
1030 MotherPDG = theMoth->pdg_id();
1031 MothOriVert = theMoth->production_vertex();
1032 if (MotherPDG == partPDG) break;
1033 }
1034 itr++;
1035 if (itr > 100) {
1036 break;
1037 }
1038 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1039 MothOriVert != partOriVert);
1040 return theMoth;
1041 }
1042
1044
1045 template <class C, class T> T findMatching(C TruthContainer, T p) {
1046 T ptrPart = nullptr;
1047 if (!p) return ptrPart;
1048 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1049 for (T truthParticle : *TruthContainer) {
1050 if (HepMC::is_sim_descendant(p,truthParticle)) {
1051 ptrPart = truthParticle;
1052 break;
1053 }
1054 }
1055 }
1056 else {
1057 for (T truthParticle : TruthContainer) {
1058 if (HepMC::is_sim_descendant(p,truthParticle)) {
1059 ptrPart = truthParticle;
1060 break;
1061 }
1062 }
1063 }
1064 return ptrPart;
1065 }
1067
1068 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1069 auto prodVtx = thePart->production_vertex();
1070 if (!prodVtx) return;
1071 for (const auto& theMother: prodVtx->particles_in()) {
1072 if (!theMother) continue;
1073 allancestors.insert(theMother);
1074 findParticleAncestors(theMother, allancestors);
1075 }
1076 }
1077
1079
1080 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1081 auto endVtx = thePart->end_vertex();
1082 if (!endVtx) return;
1083 for (const auto& theDaughter: endVtx->particles_out()) {
1084 if (!theDaughter) continue;
1085 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1086 allstabledescendants.insert(theDaughter);
1087 }
1088 findParticleStableDescendants(theDaughter, allstabledescendants);
1089 }
1090 }
1091
1095
1096 template <class T> bool isHardScatteringVertex(T pVert) {
1097 if (pVert == nullptr) return false;
1098 T pV = pVert;
1099 int numOfPartIn(0);
1100 int pdg(0);
1101
1102 do {
1103 pVert = pV;
1104 auto incoming = pVert->particles_in();
1105 numOfPartIn = incoming.size();
1106 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1107 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1108
1109 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1110
1111 if (numOfPartIn == 2) {
1112 auto incoming = pVert->particles_in();
1113 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1114 }
1115 return false;
1116}
1117
1121
1122 template <class T, class U>
1123 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1124 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1125 auto vtx = p->production_vertex();
1126 if (!vtx) return false;
1127 bool fromHad = false;
1128 for ( const auto& parent : particles_in(vtx) ) {
1129 if (!parent) continue;
1130 // should this really go into parton-level territory?
1131 // probably depends where BSM particles are being decayed
1132 fromBSM |= isBSM(parent);
1133 if (!isPhysical(parent)) return false;
1134 fromTau |= isTau(parent);
1135 if (isHadron(parent)&&!isBeam(parent)) {
1136 if (!hadron) hadron = parent; // assumes linear hadron parentage
1137 return true;
1138 }
1139 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1140 }
1141 return fromHad;
1142 }
1143
1146
1147 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1148 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1149 decltype(thePart->end_vertex()) pVert(nullptr);
1150 if (EndVert != nullptr) {
1151 do {
1152 bool samePart = false;
1153 pVert = nullptr;
1154 auto outgoing = EndVert->particles_out();
1155 auto incoming = EndVert->particles_in();
1156 for (const auto& itrDaug: outgoing) {
1157 if (!itrDaug) continue;
1158 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1159 // brem on generator level for tau
1160 (outgoing.size() == 1 && incoming.size() == 1 &&
1162 itrDaug->pdg_id() == thePart->pdg_id()) {
1163 samePart = true;
1164 pVert = itrDaug->end_vertex();
1165 }
1166 }
1167 if (samePart) EndVert = pVert;
1168 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1169 }
1170 return EndVert;
1171 }
1172
1174
1175 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1176 if (!theVert) return {};
1177 decltype(theVert->particles_out()) finalStatePart;
1178 auto outgoing = theVert->particles_out();
1179 for (const auto& thePart: outgoing) {
1180 if (!thePart) continue;
1181 finalStatePart.push_back(thePart);
1182 if (isStable(thePart)) continue;
1183 V pVert = findSimulatedEndVertex(thePart);
1184 if (pVert == theVert) break; // to prevent Sherpa loop
1185 if (pVert != nullptr) {
1186 auto vecPart = findFinalStateParticles<V>(pVert);
1187 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1188 }
1189 }
1190 return finalStatePart;
1191 }
1192#if !defined(XAOD_ANALYSIS)
1193#include "AtlasHepMC/GenEvent.h"
1194inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1195inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1196
1197#endif
1198}
1199#endif

◆ isCharged()

template<class T>
bool MC::isCharged ( const T & p)
inline

Definition at line 1005 of file HepMCHelpers.h.

1024{
1025 template <class VTX>
1026 auto particles_in (const VTX* p) { return p->particles_in(); }
1027 template <class VTX>
1028 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1029
1030 namespace Pythia8
1031 {
1033 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1034
1035 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1036
1037 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1038 }
1039
1040#include "AtlasPID.h"
1041
1043 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1044
1046 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1047
1049 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1050
1052 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1053
1055 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1056
1058 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1059
1061 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1062
1064 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1065
1067 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1068
1070 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1071
1075 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1076 const auto vertex = p->end_vertex();
1077 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1078 }
1079
1081 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1082
1084 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1085 const int apid = std::abs(p->pdg_id());
1086 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1087 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1088 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1089 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1090 return false;
1091 }
1092
1094
1095 template <class T> T findMother(T thePart) {
1096 auto partOriVert = thePart->production_vertex();
1097 if (!partOriVert) return nullptr;
1098
1099 long partPDG = thePart->pdg_id();
1100 long MotherPDG(0);
1101
1102 auto MothOriVert = partOriVert;
1103 MothOriVert = nullptr;
1104 T theMoth(nullptr);
1105
1106 size_t itr = 0;
1107 do {
1108 if (itr != 0) partOriVert = MothOriVert;
1109 for ( const auto& p : particles_in(partOriVert) ) {
1110 theMoth = p;
1111 if (!theMoth) continue;
1112 MotherPDG = theMoth->pdg_id();
1113 MothOriVert = theMoth->production_vertex();
1114 if (MotherPDG == partPDG) break;
1115 }
1116 itr++;
1117 if (itr > 100) {
1118 break;
1119 }
1120 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1121 MothOriVert != partOriVert);
1122 return theMoth;
1123 }
1124
1126
1127 template <class C, class T> T findMatching(C TruthContainer, T p) {
1128 T ptrPart = nullptr;
1129 if (!p) return ptrPart;
1130 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1131 for (T truthParticle : *TruthContainer) {
1132 if (HepMC::is_sim_descendant(p,truthParticle)) {
1133 ptrPart = truthParticle;
1134 break;
1135 }
1136 }
1137 }
1138 else {
1139 for (T truthParticle : TruthContainer) {
1140 if (HepMC::is_sim_descendant(p,truthParticle)) {
1141 ptrPart = truthParticle;
1142 break;
1143 }
1144 }
1145 }
1146 return ptrPart;
1147 }
1149
1150 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1151 auto prodVtx = thePart->production_vertex();
1152 if (!prodVtx) return;
1153 for (const auto& theMother: prodVtx->particles_in()) {
1154 if (!theMother) continue;
1155 allancestors.insert(theMother);
1156 findParticleAncestors(theMother, allancestors);
1157 }
1158 }
1159
1161
1162 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1163 auto endVtx = thePart->end_vertex();
1164 if (!endVtx) return;
1165 for (const auto& theDaughter: endVtx->particles_out()) {
1166 if (!theDaughter) continue;
1167 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1168 allstabledescendants.insert(theDaughter);
1169 }
1170 findParticleStableDescendants(theDaughter, allstabledescendants);
1171 }
1172 }
1173
1177
1178 template <class T> bool isHardScatteringVertex(T pVert) {
1179 if (pVert == nullptr) return false;
1180 T pV = pVert;
1181 int numOfPartIn(0);
1182 int pdg(0);
1183
1184 do {
1185 pVert = pV;
1186 auto incoming = pVert->particles_in();
1187 numOfPartIn = incoming.size();
1188 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1189 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1190
1191 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1192
1193 if (numOfPartIn == 2) {
1194 auto incoming = pVert->particles_in();
1195 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1196 }
1197 return false;
1198}
1199
1203
1204 template <class T, class U>
1205 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1206 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1207 auto vtx = p->production_vertex();
1208 if (!vtx) return false;
1209 bool fromHad = false;
1210 for ( const auto& parent : particles_in(vtx) ) {
1211 if (!parent) continue;
1212 // should this really go into parton-level territory?
1213 // probably depends where BSM particles are being decayed
1214 fromBSM |= isBSM(parent);
1215 if (!isPhysical(parent)) return false;
1216 fromTau |= isTau(parent);
1217 if (isHadron(parent)&&!isBeam(parent)) {
1218 if (!hadron) hadron = parent; // assumes linear hadron parentage
1219 return true;
1220 }
1221 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1222 }
1223 return fromHad;
1224 }
1225
1228
1229 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1230 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1231 decltype(thePart->end_vertex()) pVert(nullptr);
1232 if (EndVert != nullptr) {
1233 do {
1234 bool samePart = false;
1235 pVert = nullptr;
1236 auto outgoing = EndVert->particles_out();
1237 auto incoming = EndVert->particles_in();
1238 for (const auto& itrDaug: outgoing) {
1239 if (!itrDaug) continue;
1240 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1241 // brem on generator level for tau
1242 (outgoing.size() == 1 && incoming.size() == 1 &&
1244 itrDaug->pdg_id() == thePart->pdg_id()) {
1245 samePart = true;
1246 pVert = itrDaug->end_vertex();
1247 }
1248 }
1249 if (samePart) EndVert = pVert;
1250 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1251 }
1252 return EndVert;
1253 }
1254
1256
1257 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1258 if (!theVert) return {};
1259 decltype(theVert->particles_out()) finalStatePart;
1260 auto outgoing = theVert->particles_out();
1261 for (const auto& thePart: outgoing) {
1262 if (!thePart) continue;
1263 finalStatePart.push_back(thePart);
1264 if (isStable(thePart)) continue;
1265 V pVert = findSimulatedEndVertex(thePart);
1266 if (pVert == theVert) break; // to prevent Sherpa loop
1267 if (pVert != nullptr) {
1268 auto vecPart = findFinalStateParticles<V>(pVert);
1269 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1270 }
1271 }
1272 return finalStatePart;
1273 }
1274#if !defined(XAOD_ANALYSIS)
1275#include "AtlasHepMC/GenEvent.h"
1276inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1277inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1278
1279#endif
1280}
1281#endif

◆ isChargedNonShowering()

template<class T>
bool MC::isChargedNonShowering ( const T & p)
inline

Identify if the particle with given PDG ID would produce ID tracks but not shower in the detector if stable.

Definition at line 42 of file HepMCHelpers.h.

42{ return (isMuon<T>(p) || isSUSY<T>(p)); }

◆ isCharm() [1/2]

template<>
bool MC::isCharm ( const int & p)
inline

Definition at line 181 of file HepMCHelpers.h.

◆ isCharm() [2/2]

template<class T>
bool MC::isCharm ( const T & p)
inline

Definition at line 180 of file HepMCHelpers.h.

180{

◆ isCharmBaryon()

template<class T>
bool MC::isCharmBaryon ( const T & p)
inline

Definition at line 935 of file HepMCHelpers.h.

954{
955 template <class VTX>
956 auto particles_in (const VTX* p) { return p->particles_in(); }
957 template <class VTX>
958 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
959
960 namespace Pythia8
961 {
963 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
964
965 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
966
967 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
968 }
969
970#include "AtlasPID.h"
971
973 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
974
976 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
977
979 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
980
982 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
983
985 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
986
988 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
989
991 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
992
994 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
995
997 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
998
1000 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1001
1005 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1006 const auto vertex = p->end_vertex();
1007 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1008 }
1009
1011 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1012
1014 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1015 const int apid = std::abs(p->pdg_id());
1016 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1017 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1018 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1019 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1020 return false;
1021 }
1022
1024
1025 template <class T> T findMother(T thePart) {
1026 auto partOriVert = thePart->production_vertex();
1027 if (!partOriVert) return nullptr;
1028
1029 long partPDG = thePart->pdg_id();
1030 long MotherPDG(0);
1031
1032 auto MothOriVert = partOriVert;
1033 MothOriVert = nullptr;
1034 T theMoth(nullptr);
1035
1036 size_t itr = 0;
1037 do {
1038 if (itr != 0) partOriVert = MothOriVert;
1039 for ( const auto& p : particles_in(partOriVert) ) {
1040 theMoth = p;
1041 if (!theMoth) continue;
1042 MotherPDG = theMoth->pdg_id();
1043 MothOriVert = theMoth->production_vertex();
1044 if (MotherPDG == partPDG) break;
1045 }
1046 itr++;
1047 if (itr > 100) {
1048 break;
1049 }
1050 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1051 MothOriVert != partOriVert);
1052 return theMoth;
1053 }
1054
1056
1057 template <class C, class T> T findMatching(C TruthContainer, T p) {
1058 T ptrPart = nullptr;
1059 if (!p) return ptrPart;
1060 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1061 for (T truthParticle : *TruthContainer) {
1062 if (HepMC::is_sim_descendant(p,truthParticle)) {
1063 ptrPart = truthParticle;
1064 break;
1065 }
1066 }
1067 }
1068 else {
1069 for (T truthParticle : TruthContainer) {
1070 if (HepMC::is_sim_descendant(p,truthParticle)) {
1071 ptrPart = truthParticle;
1072 break;
1073 }
1074 }
1075 }
1076 return ptrPart;
1077 }
1079
1080 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1081 auto prodVtx = thePart->production_vertex();
1082 if (!prodVtx) return;
1083 for (const auto& theMother: prodVtx->particles_in()) {
1084 if (!theMother) continue;
1085 allancestors.insert(theMother);
1086 findParticleAncestors(theMother, allancestors);
1087 }
1088 }
1089
1091
1092 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1093 auto endVtx = thePart->end_vertex();
1094 if (!endVtx) return;
1095 for (const auto& theDaughter: endVtx->particles_out()) {
1096 if (!theDaughter) continue;
1097 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1098 allstabledescendants.insert(theDaughter);
1099 }
1100 findParticleStableDescendants(theDaughter, allstabledescendants);
1101 }
1102 }
1103
1107
1108 template <class T> bool isHardScatteringVertex(T pVert) {
1109 if (pVert == nullptr) return false;
1110 T pV = pVert;
1111 int numOfPartIn(0);
1112 int pdg(0);
1113
1114 do {
1115 pVert = pV;
1116 auto incoming = pVert->particles_in();
1117 numOfPartIn = incoming.size();
1118 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1119 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1120
1121 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1122
1123 if (numOfPartIn == 2) {
1124 auto incoming = pVert->particles_in();
1125 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1126 }
1127 return false;
1128}
1129
1133
1134 template <class T, class U>
1135 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1136 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1137 auto vtx = p->production_vertex();
1138 if (!vtx) return false;
1139 bool fromHad = false;
1140 for ( const auto& parent : particles_in(vtx) ) {
1141 if (!parent) continue;
1142 // should this really go into parton-level territory?
1143 // probably depends where BSM particles are being decayed
1144 fromBSM |= isBSM(parent);
1145 if (!isPhysical(parent)) return false;
1146 fromTau |= isTau(parent);
1147 if (isHadron(parent)&&!isBeam(parent)) {
1148 if (!hadron) hadron = parent; // assumes linear hadron parentage
1149 return true;
1150 }
1151 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1152 }
1153 return fromHad;
1154 }
1155
1158
1159 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1160 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1161 decltype(thePart->end_vertex()) pVert(nullptr);
1162 if (EndVert != nullptr) {
1163 do {
1164 bool samePart = false;
1165 pVert = nullptr;
1166 auto outgoing = EndVert->particles_out();
1167 auto incoming = EndVert->particles_in();
1168 for (const auto& itrDaug: outgoing) {
1169 if (!itrDaug) continue;
1170 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1171 // brem on generator level for tau
1172 (outgoing.size() == 1 && incoming.size() == 1 &&
1174 itrDaug->pdg_id() == thePart->pdg_id()) {
1175 samePart = true;
1176 pVert = itrDaug->end_vertex();
1177 }
1178 }
1179 if (samePart) EndVert = pVert;
1180 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1181 }
1182 return EndVert;
1183 }
1184
1186
1187 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1188 if (!theVert) return {};
1189 decltype(theVert->particles_out()) finalStatePart;
1190 auto outgoing = theVert->particles_out();
1191 for (const auto& thePart: outgoing) {
1192 if (!thePart) continue;
1193 finalStatePart.push_back(thePart);
1194 if (isStable(thePart)) continue;
1195 V pVert = findSimulatedEndVertex(thePart);
1196 if (pVert == theVert) break; // to prevent Sherpa loop
1197 if (pVert != nullptr) {
1198 auto vecPart = findFinalStateParticles<V>(pVert);
1199 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1200 }
1201 }
1202 return finalStatePart;
1203 }
1204#if !defined(XAOD_ANALYSIS)
1205#include "AtlasHepMC/GenEvent.h"
1206inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1207inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1208
1209#endif
1210}
1211#endif

◆ isCharmHadron()

template<class T>
bool MC::isCharmHadron ( const T & p)
inline

Definition at line 912 of file HepMCHelpers.h.

931{
932 template <class VTX>
933 auto particles_in (const VTX* p) { return p->particles_in(); }
934 template <class VTX>
935 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
936
937 namespace Pythia8
938 {
940 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
941
942 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
943
944 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
945 }
946
947#include "AtlasPID.h"
948
950 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
951
953 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
954
956 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
957
959 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
960
962 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
963
965 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
966
968 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
969
971 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
972
974 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
975
977 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
978
982 template <class T> inline bool isStableOrSimDecayed(const T& p) {
983 const auto vertex = p->end_vertex();
984 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
985 }
986
988 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
989
991 template <class T> inline bool isSpecialNonInteracting(const T& p) {
992 const int apid = std::abs(p->pdg_id());
993 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
994 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
995 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
996 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
997 return false;
998 }
999
1001
1002 template <class T> T findMother(T thePart) {
1003 auto partOriVert = thePart->production_vertex();
1004 if (!partOriVert) return nullptr;
1005
1006 long partPDG = thePart->pdg_id();
1007 long MotherPDG(0);
1008
1009 auto MothOriVert = partOriVert;
1010 MothOriVert = nullptr;
1011 T theMoth(nullptr);
1012
1013 size_t itr = 0;
1014 do {
1015 if (itr != 0) partOriVert = MothOriVert;
1016 for ( const auto& p : particles_in(partOriVert) ) {
1017 theMoth = p;
1018 if (!theMoth) continue;
1019 MotherPDG = theMoth->pdg_id();
1020 MothOriVert = theMoth->production_vertex();
1021 if (MotherPDG == partPDG) break;
1022 }
1023 itr++;
1024 if (itr > 100) {
1025 break;
1026 }
1027 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1028 MothOriVert != partOriVert);
1029 return theMoth;
1030 }
1031
1033
1034 template <class C, class T> T findMatching(C TruthContainer, T p) {
1035 T ptrPart = nullptr;
1036 if (!p) return ptrPart;
1037 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1038 for (T truthParticle : *TruthContainer) {
1039 if (HepMC::is_sim_descendant(p,truthParticle)) {
1040 ptrPart = truthParticle;
1041 break;
1042 }
1043 }
1044 }
1045 else {
1046 for (T truthParticle : TruthContainer) {
1047 if (HepMC::is_sim_descendant(p,truthParticle)) {
1048 ptrPart = truthParticle;
1049 break;
1050 }
1051 }
1052 }
1053 return ptrPart;
1054 }
1056
1057 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1058 auto prodVtx = thePart->production_vertex();
1059 if (!prodVtx) return;
1060 for (const auto& theMother: prodVtx->particles_in()) {
1061 if (!theMother) continue;
1062 allancestors.insert(theMother);
1063 findParticleAncestors(theMother, allancestors);
1064 }
1065 }
1066
1068
1069 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1070 auto endVtx = thePart->end_vertex();
1071 if (!endVtx) return;
1072 for (const auto& theDaughter: endVtx->particles_out()) {
1073 if (!theDaughter) continue;
1074 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1075 allstabledescendants.insert(theDaughter);
1076 }
1077 findParticleStableDescendants(theDaughter, allstabledescendants);
1078 }
1079 }
1080
1084
1085 template <class T> bool isHardScatteringVertex(T pVert) {
1086 if (pVert == nullptr) return false;
1087 T pV = pVert;
1088 int numOfPartIn(0);
1089 int pdg(0);
1090
1091 do {
1092 pVert = pV;
1093 auto incoming = pVert->particles_in();
1094 numOfPartIn = incoming.size();
1095 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1096 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1097
1098 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1099
1100 if (numOfPartIn == 2) {
1101 auto incoming = pVert->particles_in();
1102 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1103 }
1104 return false;
1105}
1106
1110
1111 template <class T, class U>
1112 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1113 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1114 auto vtx = p->production_vertex();
1115 if (!vtx) return false;
1116 bool fromHad = false;
1117 for ( const auto& parent : particles_in(vtx) ) {
1118 if (!parent) continue;
1119 // should this really go into parton-level territory?
1120 // probably depends where BSM particles are being decayed
1121 fromBSM |= isBSM(parent);
1122 if (!isPhysical(parent)) return false;
1123 fromTau |= isTau(parent);
1124 if (isHadron(parent)&&!isBeam(parent)) {
1125 if (!hadron) hadron = parent; // assumes linear hadron parentage
1126 return true;
1127 }
1128 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1129 }
1130 return fromHad;
1131 }
1132
1135
1136 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1137 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1138 decltype(thePart->end_vertex()) pVert(nullptr);
1139 if (EndVert != nullptr) {
1140 do {
1141 bool samePart = false;
1142 pVert = nullptr;
1143 auto outgoing = EndVert->particles_out();
1144 auto incoming = EndVert->particles_in();
1145 for (const auto& itrDaug: outgoing) {
1146 if (!itrDaug) continue;
1147 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1148 // brem on generator level for tau
1149 (outgoing.size() == 1 && incoming.size() == 1 &&
1151 itrDaug->pdg_id() == thePart->pdg_id()) {
1152 samePart = true;
1153 pVert = itrDaug->end_vertex();
1154 }
1155 }
1156 if (samePart) EndVert = pVert;
1157 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1158 }
1159 return EndVert;
1160 }
1161
1163
1164 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1165 if (!theVert) return {};
1166 decltype(theVert->particles_out()) finalStatePart;
1167 auto outgoing = theVert->particles_out();
1168 for (const auto& thePart: outgoing) {
1169 if (!thePart) continue;
1170 finalStatePart.push_back(thePart);
1171 if (isStable(thePart)) continue;
1172 V pVert = findSimulatedEndVertex(thePart);
1173 if (pVert == theVert) break; // to prevent Sherpa loop
1174 if (pVert != nullptr) {
1175 auto vecPart = findFinalStateParticles<V>(pVert);
1176 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1177 }
1178 }
1179 return finalStatePart;
1180 }
1181#if !defined(XAOD_ANALYSIS)
1182#include "AtlasHepMC/GenEvent.h"
1183inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1184inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1185
1186#endif
1187}
1188#endif

◆ isCharmMeson()

template<class T>
bool MC::isCharmMeson ( const T & p)
inline

Definition at line 919 of file HepMCHelpers.h.

938{
939 template <class VTX>
940 auto particles_in (const VTX* p) { return p->particles_in(); }
941 template <class VTX>
942 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
943
944 namespace Pythia8
945 {
947 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
948
949 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
950
951 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
952 }
953
954#include "AtlasPID.h"
955
957 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
958
960 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
961
963 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
964
966 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
967
969 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
970
972 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
973
975 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
976
978 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
979
981 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
982
984 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
985
989 template <class T> inline bool isStableOrSimDecayed(const T& p) {
990 const auto vertex = p->end_vertex();
991 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
992 }
993
995 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
996
998 template <class T> inline bool isSpecialNonInteracting(const T& p) {
999 const int apid = std::abs(p->pdg_id());
1000 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1001 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1002 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1003 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1004 return false;
1005 }
1006
1008
1009 template <class T> T findMother(T thePart) {
1010 auto partOriVert = thePart->production_vertex();
1011 if (!partOriVert) return nullptr;
1012
1013 long partPDG = thePart->pdg_id();
1014 long MotherPDG(0);
1015
1016 auto MothOriVert = partOriVert;
1017 MothOriVert = nullptr;
1018 T theMoth(nullptr);
1019
1020 size_t itr = 0;
1021 do {
1022 if (itr != 0) partOriVert = MothOriVert;
1023 for ( const auto& p : particles_in(partOriVert) ) {
1024 theMoth = p;
1025 if (!theMoth) continue;
1026 MotherPDG = theMoth->pdg_id();
1027 MothOriVert = theMoth->production_vertex();
1028 if (MotherPDG == partPDG) break;
1029 }
1030 itr++;
1031 if (itr > 100) {
1032 break;
1033 }
1034 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1035 MothOriVert != partOriVert);
1036 return theMoth;
1037 }
1038
1040
1041 template <class C, class T> T findMatching(C TruthContainer, T p) {
1042 T ptrPart = nullptr;
1043 if (!p) return ptrPart;
1044 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1045 for (T truthParticle : *TruthContainer) {
1046 if (HepMC::is_sim_descendant(p,truthParticle)) {
1047 ptrPart = truthParticle;
1048 break;
1049 }
1050 }
1051 }
1052 else {
1053 for (T truthParticle : TruthContainer) {
1054 if (HepMC::is_sim_descendant(p,truthParticle)) {
1055 ptrPart = truthParticle;
1056 break;
1057 }
1058 }
1059 }
1060 return ptrPart;
1061 }
1063
1064 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1065 auto prodVtx = thePart->production_vertex();
1066 if (!prodVtx) return;
1067 for (const auto& theMother: prodVtx->particles_in()) {
1068 if (!theMother) continue;
1069 allancestors.insert(theMother);
1070 findParticleAncestors(theMother, allancestors);
1071 }
1072 }
1073
1075
1076 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1077 auto endVtx = thePart->end_vertex();
1078 if (!endVtx) return;
1079 for (const auto& theDaughter: endVtx->particles_out()) {
1080 if (!theDaughter) continue;
1081 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1082 allstabledescendants.insert(theDaughter);
1083 }
1084 findParticleStableDescendants(theDaughter, allstabledescendants);
1085 }
1086 }
1087
1091
1092 template <class T> bool isHardScatteringVertex(T pVert) {
1093 if (pVert == nullptr) return false;
1094 T pV = pVert;
1095 int numOfPartIn(0);
1096 int pdg(0);
1097
1098 do {
1099 pVert = pV;
1100 auto incoming = pVert->particles_in();
1101 numOfPartIn = incoming.size();
1102 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1103 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1104
1105 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1106
1107 if (numOfPartIn == 2) {
1108 auto incoming = pVert->particles_in();
1109 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1110 }
1111 return false;
1112}
1113
1117
1118 template <class T, class U>
1119 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1120 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1121 auto vtx = p->production_vertex();
1122 if (!vtx) return false;
1123 bool fromHad = false;
1124 for ( const auto& parent : particles_in(vtx) ) {
1125 if (!parent) continue;
1126 // should this really go into parton-level territory?
1127 // probably depends where BSM particles are being decayed
1128 fromBSM |= isBSM(parent);
1129 if (!isPhysical(parent)) return false;
1130 fromTau |= isTau(parent);
1131 if (isHadron(parent)&&!isBeam(parent)) {
1132 if (!hadron) hadron = parent; // assumes linear hadron parentage
1133 return true;
1134 }
1135 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1136 }
1137 return fromHad;
1138 }
1139
1142
1143 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1144 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1145 decltype(thePart->end_vertex()) pVert(nullptr);
1146 if (EndVert != nullptr) {
1147 do {
1148 bool samePart = false;
1149 pVert = nullptr;
1150 auto outgoing = EndVert->particles_out();
1151 auto incoming = EndVert->particles_in();
1152 for (const auto& itrDaug: outgoing) {
1153 if (!itrDaug) continue;
1154 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1155 // brem on generator level for tau
1156 (outgoing.size() == 1 && incoming.size() == 1 &&
1158 itrDaug->pdg_id() == thePart->pdg_id()) {
1159 samePart = true;
1160 pVert = itrDaug->end_vertex();
1161 }
1162 }
1163 if (samePart) EndVert = pVert;
1164 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1165 }
1166 return EndVert;
1167 }
1168
1170
1171 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1172 if (!theVert) return {};
1173 decltype(theVert->particles_out()) finalStatePart;
1174 auto outgoing = theVert->particles_out();
1175 for (const auto& thePart: outgoing) {
1176 if (!thePart) continue;
1177 finalStatePart.push_back(thePart);
1178 if (isStable(thePart)) continue;
1179 V pVert = findSimulatedEndVertex(thePart);
1180 if (pVert == theVert) break; // to prevent Sherpa loop
1181 if (pVert != nullptr) {
1182 auto vecPart = findFinalStateParticles<V>(pVert);
1183 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1184 }
1185 }
1186 return finalStatePart;
1187 }
1188#if !defined(XAOD_ANALYSIS)
1189#include "AtlasHepMC/GenEvent.h"
1190inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1191inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1192
1193#endif
1194}
1195#endif

◆ isChLepton() [1/2]

template<>
bool MC::isChLepton ( const int & p)
inline

Definition at line 201 of file HepMCHelpers.h.

201{

◆ isChLepton() [2/2]

template<class T>
bool MC::isChLepton ( const T & p)
inline

APID: the fourth generation leptons are leptons.

Definition at line 200 of file HepMCHelpers.h.

◆ isDecayed()

template<class T>
bool MC::isDecayed ( const T & p)
inline

Identify if the particle decayed.

Definition at line 48 of file HepMCHelpers.h.

◆ isDiquark() [1/3]

template<>
bool MC::isDiquark ( const DecodedPID & p)
inline

Definition at line 229 of file HepMCHelpers.h.

229 {
230 bool samePart = false;
231 pVert = nullptr;
232 auto outgoing = EndVert->particles_out();
233 auto incoming = EndVert->particles_in();
234 for (const auto& itrDaug: outgoing) {

◆ isDiquark() [2/3]

template<>
bool MC::isDiquark ( const int & p)
inline

Definition at line 235 of file HepMCHelpers.h.

◆ isDiquark() [3/3]

template<class T>
bool MC::isDiquark ( const T & p)
inline

PDG rule 4 Diquarks have 4-digit numbers with nq1 >= nq2 and nq3 = 0 APID: states with top quarks are diquarks APID: states with fourth generation quarks are not diquarks.

Definition at line 228 of file HepMCHelpers.h.

228{

◆ isDM() [1/2]

template<>
bool MC::isDM ( const int & p)
inline

Definition at line 660 of file HepMCHelpers.h.

679{
680 template <class VTX>
681 auto particles_in (const VTX* p) { return p->particles_in(); }
682 template <class VTX>
683 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
684
685 namespace Pythia8
686 {
688 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
689
690 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
691
692 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
693 }
694
695#include "AtlasPID.h"
696
698 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
699
701 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
702
704 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
705
707 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
708
710 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
711
713 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
714
716 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
717
719 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
720
722 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
723
725 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
726
730 template <class T> inline bool isStableOrSimDecayed(const T& p) {
731 const auto vertex = p->end_vertex();
732 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
733 }
734
736 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
737
739 template <class T> inline bool isSpecialNonInteracting(const T& p) {
740 const int apid = std::abs(p->pdg_id());
741 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
742 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
743 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
744 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
745 return false;
746 }
747
749
750 template <class T> T findMother(T thePart) {
751 auto partOriVert = thePart->production_vertex();
752 if (!partOriVert) return nullptr;
753
754 long partPDG = thePart->pdg_id();
755 long MotherPDG(0);
756
757 auto MothOriVert = partOriVert;
758 MothOriVert = nullptr;
759 T theMoth(nullptr);
760
761 size_t itr = 0;
762 do {
763 if (itr != 0) partOriVert = MothOriVert;
764 for ( const auto& p : particles_in(partOriVert) ) {
765 theMoth = p;
766 if (!theMoth) continue;
767 MotherPDG = theMoth->pdg_id();
768 MothOriVert = theMoth->production_vertex();
769 if (MotherPDG == partPDG) break;
770 }
771 itr++;
772 if (itr > 100) {
773 break;
774 }
775 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
776 MothOriVert != partOriVert);
777 return theMoth;
778 }
779
781
782 template <class C, class T> T findMatching(C TruthContainer, T p) {
783 T ptrPart = nullptr;
784 if (!p) return ptrPart;
785 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
786 for (T truthParticle : *TruthContainer) {
787 if (HepMC::is_sim_descendant(p,truthParticle)) {
788 ptrPart = truthParticle;
789 break;
790 }
791 }
792 }
793 else {
794 for (T truthParticle : TruthContainer) {
795 if (HepMC::is_sim_descendant(p,truthParticle)) {
796 ptrPart = truthParticle;
797 break;
798 }
799 }
800 }
801 return ptrPart;
802 }
804
805 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
806 auto prodVtx = thePart->production_vertex();
807 if (!prodVtx) return;
808 for (const auto& theMother: prodVtx->particles_in()) {
809 if (!theMother) continue;
810 allancestors.insert(theMother);
811 findParticleAncestors(theMother, allancestors);
812 }
813 }
814
816
817 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
818 auto endVtx = thePart->end_vertex();
819 if (!endVtx) return;
820 for (const auto& theDaughter: endVtx->particles_out()) {
821 if (!theDaughter) continue;
822 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
823 allstabledescendants.insert(theDaughter);
824 }
825 findParticleStableDescendants(theDaughter, allstabledescendants);
826 }
827 }
828
832
833 template <class T> bool isHardScatteringVertex(T pVert) {
834 if (pVert == nullptr) return false;
835 T pV = pVert;
836 int numOfPartIn(0);
837 int pdg(0);
838
839 do {
840 pVert = pV;
841 auto incoming = pVert->particles_in();
842 numOfPartIn = incoming.size();
843 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
844 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
845
846 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
847
848 if (numOfPartIn == 2) {
849 auto incoming = pVert->particles_in();
850 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
851 }
852 return false;
853}
854
858
859 template <class T, class U>
860 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
861 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
862 auto vtx = p->production_vertex();
863 if (!vtx) return false;
864 bool fromHad = false;
865 for ( const auto& parent : particles_in(vtx) ) {
866 if (!parent) continue;
867 // should this really go into parton-level territory?
868 // probably depends where BSM particles are being decayed
869 fromBSM |= isBSM(parent);
870 if (!isPhysical(parent)) return false;
871 fromTau |= isTau(parent);
872 if (isHadron(parent)&&!isBeam(parent)) {
873 if (!hadron) hadron = parent; // assumes linear hadron parentage
874 return true;
875 }
876 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
877 }
878 return fromHad;
879 }
880
883
884 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
885 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
886 decltype(thePart->end_vertex()) pVert(nullptr);
887 if (EndVert != nullptr) {
888 do {
889 bool samePart = false;
890 pVert = nullptr;
891 auto outgoing = EndVert->particles_out();
892 auto incoming = EndVert->particles_in();
893 for (const auto& itrDaug: outgoing) {
894 if (!itrDaug) continue;
895 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
896 // brem on generator level for tau
897 (outgoing.size() == 1 && incoming.size() == 1 &&
899 itrDaug->pdg_id() == thePart->pdg_id()) {
900 samePart = true;
901 pVert = itrDaug->end_vertex();
902 }
903 }
904 if (samePart) EndVert = pVert;
905 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
906 }
907 return EndVert;
908 }
909
911
912 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
913 if (!theVert) return {};
914 decltype(theVert->particles_out()) finalStatePart;
915 auto outgoing = theVert->particles_out();
916 for (const auto& thePart: outgoing) {
917 if (!thePart) continue;
918 finalStatePart.push_back(thePart);
919 if (isStable(thePart)) continue;
920 V pVert = findSimulatedEndVertex(thePart);
921 if (pVert == theVert) break; // to prevent Sherpa loop
922 if (pVert != nullptr) {
923 auto vecPart = findFinalStateParticles<V>(pVert);
924 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
925 }
926 }
927 return finalStatePart;
928 }
929#if !defined(XAOD_ANALYSIS)
930#include "AtlasHepMC/GenEvent.h"
931inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
932inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
933
934#endif
935}
936#endif

◆ isDM() [2/2]

template<class T>
bool MC::isDM ( const T & p)
inline

PDG rule 11j: The nature of Dark Matter (DM) is not known, and therefore a definitive classificationis too early.

Candidates within specific scenarios are classified therein, such as 1000022 for the lightest neutralino. Generic fundamental states can be given temporary codes in the range 51 - 60, with 51, 52 and 53 reserved for spin 0, 1/2 and 1 ones (this could also be an axion state). Generic mediators of s-channel DM pair creation of annihilation can be given codes 54 and 55 for spin 0 or 1 ones. Separate antiparticles, with negativecodes, may or may not exist. More elaborate new scenarios should be constructed with n= 5 and nr = 9.

Definition at line 659 of file HepMCHelpers.h.

678{
679 template <class VTX>
680 auto particles_in (const VTX* p) { return p->particles_in(); }
681 template <class VTX>
682 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
683
684 namespace Pythia8
685 {
687 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
688
689 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
690
691 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
692 }
693
694#include "AtlasPID.h"
695
697 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
698
700 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
701
703 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
704
706 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
707
709 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
710
712 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
713
715 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
716
718 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
719
721 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
722
724 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
725
729 template <class T> inline bool isStableOrSimDecayed(const T& p) {
730 const auto vertex = p->end_vertex();
731 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
732 }
733
735 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
736
738 template <class T> inline bool isSpecialNonInteracting(const T& p) {
739 const int apid = std::abs(p->pdg_id());
740 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
741 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
742 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
743 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
744 return false;
745 }
746
748
749 template <class T> T findMother(T thePart) {
750 auto partOriVert = thePart->production_vertex();
751 if (!partOriVert) return nullptr;
752
753 long partPDG = thePart->pdg_id();
754 long MotherPDG(0);
755
756 auto MothOriVert = partOriVert;
757 MothOriVert = nullptr;
758 T theMoth(nullptr);
759
760 size_t itr = 0;
761 do {
762 if (itr != 0) partOriVert = MothOriVert;
763 for ( const auto& p : particles_in(partOriVert) ) {
764 theMoth = p;
765 if (!theMoth) continue;
766 MotherPDG = theMoth->pdg_id();
767 MothOriVert = theMoth->production_vertex();
768 if (MotherPDG == partPDG) break;
769 }
770 itr++;
771 if (itr > 100) {
772 break;
773 }
774 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
775 MothOriVert != partOriVert);
776 return theMoth;
777 }
778
780
781 template <class C, class T> T findMatching(C TruthContainer, T p) {
782 T ptrPart = nullptr;
783 if (!p) return ptrPart;
784 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
785 for (T truthParticle : *TruthContainer) {
786 if (HepMC::is_sim_descendant(p,truthParticle)) {
787 ptrPart = truthParticle;
788 break;
789 }
790 }
791 }
792 else {
793 for (T truthParticle : TruthContainer) {
794 if (HepMC::is_sim_descendant(p,truthParticle)) {
795 ptrPart = truthParticle;
796 break;
797 }
798 }
799 }
800 return ptrPart;
801 }
803
804 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
805 auto prodVtx = thePart->production_vertex();
806 if (!prodVtx) return;
807 for (const auto& theMother: prodVtx->particles_in()) {
808 if (!theMother) continue;
809 allancestors.insert(theMother);
810 findParticleAncestors(theMother, allancestors);
811 }
812 }
813
815
816 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
817 auto endVtx = thePart->end_vertex();
818 if (!endVtx) return;
819 for (const auto& theDaughter: endVtx->particles_out()) {
820 if (!theDaughter) continue;
821 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
822 allstabledescendants.insert(theDaughter);
823 }
824 findParticleStableDescendants(theDaughter, allstabledescendants);
825 }
826 }
827
831
832 template <class T> bool isHardScatteringVertex(T pVert) {
833 if (pVert == nullptr) return false;
834 T pV = pVert;
835 int numOfPartIn(0);
836 int pdg(0);
837
838 do {
839 pVert = pV;
840 auto incoming = pVert->particles_in();
841 numOfPartIn = incoming.size();
842 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
843 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
844
845 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
846
847 if (numOfPartIn == 2) {
848 auto incoming = pVert->particles_in();
849 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
850 }
851 return false;
852}
853
857
858 template <class T, class U>
859 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
860 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
861 auto vtx = p->production_vertex();
862 if (!vtx) return false;
863 bool fromHad = false;
864 for ( const auto& parent : particles_in(vtx) ) {
865 if (!parent) continue;
866 // should this really go into parton-level territory?
867 // probably depends where BSM particles are being decayed
868 fromBSM |= isBSM(parent);
869 if (!isPhysical(parent)) return false;
870 fromTau |= isTau(parent);
871 if (isHadron(parent)&&!isBeam(parent)) {
872 if (!hadron) hadron = parent; // assumes linear hadron parentage
873 return true;
874 }
875 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
876 }
877 return fromHad;
878 }
879
882
883 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
884 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
885 decltype(thePart->end_vertex()) pVert(nullptr);
886 if (EndVert != nullptr) {
887 do {
888 bool samePart = false;
889 pVert = nullptr;
890 auto outgoing = EndVert->particles_out();
891 auto incoming = EndVert->particles_in();
892 for (const auto& itrDaug: outgoing) {
893 if (!itrDaug) continue;
894 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
895 // brem on generator level for tau
896 (outgoing.size() == 1 && incoming.size() == 1 &&
898 itrDaug->pdg_id() == thePart->pdg_id()) {
899 samePart = true;
900 pVert = itrDaug->end_vertex();
901 }
902 }
903 if (samePart) EndVert = pVert;
904 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
905 }
906 return EndVert;
907 }
908
910
911 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
912 if (!theVert) return {};
913 decltype(theVert->particles_out()) finalStatePart;
914 auto outgoing = theVert->particles_out();
915 for (const auto& thePart: outgoing) {
916 if (!thePart) continue;
917 finalStatePart.push_back(thePart);
918 if (isStable(thePart)) continue;
919 V pVert = findSimulatedEndVertex(thePart);
920 if (pVert == theVert) break; // to prevent Sherpa loop
921 if (pVert != nullptr) {
922 auto vecPart = findFinalStateParticles<V>(pVert);
923 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
924 }
925 }
926 return finalStatePart;
927 }
928#if !defined(XAOD_ANALYSIS)
929#include "AtlasHepMC/GenEvent.h"
930inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
931inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
932
933#endif
934}
935#endif

◆ isElectron() [1/2]

template<>
bool MC::isElectron ( const int & p)
inline

Definition at line 204 of file HepMCHelpers.h.

◆ isElectron() [2/2]

template<class T>
bool MC::isElectron ( const T & p)
inline

Definition at line 203 of file HepMCHelpers.h.

◆ isEMInteracting() [1/2]

template<>
bool MC::isEMInteracting ( const int & p)
inline

Definition at line 1107 of file HepMCHelpers.h.

1126{
1127 template <class VTX>
1128 auto particles_in (const VTX* p) { return p->particles_in(); }
1129 template <class VTX>
1130 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1131
1132 namespace Pythia8
1133 {
1135 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1136
1137 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1138
1139 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1140 }
1141
1142#include "AtlasPID.h"
1143
1145 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1146
1148 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1149
1151 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1152
1154 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1155
1157 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1158
1160 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1161
1163 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1164
1166 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1167
1169 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1170
1172 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1173
1177 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1178 const auto vertex = p->end_vertex();
1179 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1180 }
1181
1183 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1184
1186 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1187 const int apid = std::abs(p->pdg_id());
1188 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1189 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1190 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1191 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1192 return false;
1193 }
1194
1196
1197 template <class T> T findMother(T thePart) {
1198 auto partOriVert = thePart->production_vertex();
1199 if (!partOriVert) return nullptr;
1200
1201 long partPDG = thePart->pdg_id();
1202 long MotherPDG(0);
1203
1204 auto MothOriVert = partOriVert;
1205 MothOriVert = nullptr;
1206 T theMoth(nullptr);
1207
1208 size_t itr = 0;
1209 do {
1210 if (itr != 0) partOriVert = MothOriVert;
1211 for ( const auto& p : particles_in(partOriVert) ) {
1212 theMoth = p;
1213 if (!theMoth) continue;
1214 MotherPDG = theMoth->pdg_id();
1215 MothOriVert = theMoth->production_vertex();
1216 if (MotherPDG == partPDG) break;
1217 }
1218 itr++;
1219 if (itr > 100) {
1220 break;
1221 }
1222 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1223 MothOriVert != partOriVert);
1224 return theMoth;
1225 }
1226
1228
1229 template <class C, class T> T findMatching(C TruthContainer, T p) {
1230 T ptrPart = nullptr;
1231 if (!p) return ptrPart;
1232 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1233 for (T truthParticle : *TruthContainer) {
1234 if (HepMC::is_sim_descendant(p,truthParticle)) {
1235 ptrPart = truthParticle;
1236 break;
1237 }
1238 }
1239 }
1240 else {
1241 for (T truthParticle : TruthContainer) {
1242 if (HepMC::is_sim_descendant(p,truthParticle)) {
1243 ptrPart = truthParticle;
1244 break;
1245 }
1246 }
1247 }
1248 return ptrPart;
1249 }
1251
1252 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1253 auto prodVtx = thePart->production_vertex();
1254 if (!prodVtx) return;
1255 for (const auto& theMother: prodVtx->particles_in()) {
1256 if (!theMother) continue;
1257 allancestors.insert(theMother);
1258 findParticleAncestors(theMother, allancestors);
1259 }
1260 }
1261
1263
1264 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1265 auto endVtx = thePart->end_vertex();
1266 if (!endVtx) return;
1267 for (const auto& theDaughter: endVtx->particles_out()) {
1268 if (!theDaughter) continue;
1269 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1270 allstabledescendants.insert(theDaughter);
1271 }
1272 findParticleStableDescendants(theDaughter, allstabledescendants);
1273 }
1274 }
1275
1279
1280 template <class T> bool isHardScatteringVertex(T pVert) {
1281 if (pVert == nullptr) return false;
1282 T pV = pVert;
1283 int numOfPartIn(0);
1284 int pdg(0);
1285
1286 do {
1287 pVert = pV;
1288 auto incoming = pVert->particles_in();
1289 numOfPartIn = incoming.size();
1290 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1291 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1292
1293 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1294
1295 if (numOfPartIn == 2) {
1296 auto incoming = pVert->particles_in();
1297 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1298 }
1299 return false;
1300}
1301
1305
1306 template <class T, class U>
1307 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1308 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1309 auto vtx = p->production_vertex();
1310 if (!vtx) return false;
1311 bool fromHad = false;
1312 for ( const auto& parent : particles_in(vtx) ) {
1313 if (!parent) continue;
1314 // should this really go into parton-level territory?
1315 // probably depends where BSM particles are being decayed
1316 fromBSM |= isBSM(parent);
1317 if (!isPhysical(parent)) return false;
1318 fromTau |= isTau(parent);
1319 if (isHadron(parent)&&!isBeam(parent)) {
1320 if (!hadron) hadron = parent; // assumes linear hadron parentage
1321 return true;
1322 }
1323 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1324 }
1325 return fromHad;
1326 }
1327
1330
1331 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1332 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1333 decltype(thePart->end_vertex()) pVert(nullptr);
1334 if (EndVert != nullptr) {
1335 do {
1336 bool samePart = false;
1337 pVert = nullptr;
1338 auto outgoing = EndVert->particles_out();
1339 auto incoming = EndVert->particles_in();
1340 for (const auto& itrDaug: outgoing) {
1341 if (!itrDaug) continue;
1342 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1343 // brem on generator level for tau
1344 (outgoing.size() == 1 && incoming.size() == 1 &&
1346 itrDaug->pdg_id() == thePart->pdg_id()) {
1347 samePart = true;
1348 pVert = itrDaug->end_vertex();
1349 }
1350 }
1351 if (samePart) EndVert = pVert;
1352 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1353 }
1354 return EndVert;
1355 }
1356
1358
1359 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1360 if (!theVert) return {};
1361 decltype(theVert->particles_out()) finalStatePart;
1362 auto outgoing = theVert->particles_out();
1363 for (const auto& thePart: outgoing) {
1364 if (!thePart) continue;
1365 finalStatePart.push_back(thePart);
1366 if (isStable(thePart)) continue;
1367 V pVert = findSimulatedEndVertex(thePart);
1368 if (pVert == theVert) break; // to prevent Sherpa loop
1369 if (pVert != nullptr) {
1370 auto vecPart = findFinalStateParticles<V>(pVert);
1371 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1372 }
1373 }
1374 return finalStatePart;
1375 }
1376#if !defined(XAOD_ANALYSIS)
1377#include "AtlasHepMC/GenEvent.h"
1378inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1379inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1380
1381#endif
1382}
1383#endif

◆ isEMInteracting() [2/2]

template<class T>
bool MC::isEMInteracting ( const T & p)
inline

Definition at line 1106 of file HepMCHelpers.h.

1125{
1126 template <class VTX>
1127 auto particles_in (const VTX* p) { return p->particles_in(); }
1128 template <class VTX>
1129 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1130
1131 namespace Pythia8
1132 {
1134 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1135
1136 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1137
1138 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1139 }
1140
1141#include "AtlasPID.h"
1142
1144 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1145
1147 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1148
1150 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1151
1153 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1154
1156 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1157
1159 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1160
1162 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1163
1165 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1166
1168 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1169
1171 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1172
1176 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1177 const auto vertex = p->end_vertex();
1178 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1179 }
1180
1182 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1183
1185 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1186 const int apid = std::abs(p->pdg_id());
1187 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1188 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1189 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1190 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1191 return false;
1192 }
1193
1195
1196 template <class T> T findMother(T thePart) {
1197 auto partOriVert = thePart->production_vertex();
1198 if (!partOriVert) return nullptr;
1199
1200 long partPDG = thePart->pdg_id();
1201 long MotherPDG(0);
1202
1203 auto MothOriVert = partOriVert;
1204 MothOriVert = nullptr;
1205 T theMoth(nullptr);
1206
1207 size_t itr = 0;
1208 do {
1209 if (itr != 0) partOriVert = MothOriVert;
1210 for ( const auto& p : particles_in(partOriVert) ) {
1211 theMoth = p;
1212 if (!theMoth) continue;
1213 MotherPDG = theMoth->pdg_id();
1214 MothOriVert = theMoth->production_vertex();
1215 if (MotherPDG == partPDG) break;
1216 }
1217 itr++;
1218 if (itr > 100) {
1219 break;
1220 }
1221 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1222 MothOriVert != partOriVert);
1223 return theMoth;
1224 }
1225
1227
1228 template <class C, class T> T findMatching(C TruthContainer, T p) {
1229 T ptrPart = nullptr;
1230 if (!p) return ptrPart;
1231 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1232 for (T truthParticle : *TruthContainer) {
1233 if (HepMC::is_sim_descendant(p,truthParticle)) {
1234 ptrPart = truthParticle;
1235 break;
1236 }
1237 }
1238 }
1239 else {
1240 for (T truthParticle : TruthContainer) {
1241 if (HepMC::is_sim_descendant(p,truthParticle)) {
1242 ptrPart = truthParticle;
1243 break;
1244 }
1245 }
1246 }
1247 return ptrPart;
1248 }
1250
1251 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1252 auto prodVtx = thePart->production_vertex();
1253 if (!prodVtx) return;
1254 for (const auto& theMother: prodVtx->particles_in()) {
1255 if (!theMother) continue;
1256 allancestors.insert(theMother);
1257 findParticleAncestors(theMother, allancestors);
1258 }
1259 }
1260
1262
1263 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1264 auto endVtx = thePart->end_vertex();
1265 if (!endVtx) return;
1266 for (const auto& theDaughter: endVtx->particles_out()) {
1267 if (!theDaughter) continue;
1268 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1269 allstabledescendants.insert(theDaughter);
1270 }
1271 findParticleStableDescendants(theDaughter, allstabledescendants);
1272 }
1273 }
1274
1278
1279 template <class T> bool isHardScatteringVertex(T pVert) {
1280 if (pVert == nullptr) return false;
1281 T pV = pVert;
1282 int numOfPartIn(0);
1283 int pdg(0);
1284
1285 do {
1286 pVert = pV;
1287 auto incoming = pVert->particles_in();
1288 numOfPartIn = incoming.size();
1289 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1290 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1291
1292 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1293
1294 if (numOfPartIn == 2) {
1295 auto incoming = pVert->particles_in();
1296 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1297 }
1298 return false;
1299}
1300
1304
1305 template <class T, class U>
1306 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1307 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1308 auto vtx = p->production_vertex();
1309 if (!vtx) return false;
1310 bool fromHad = false;
1311 for ( const auto& parent : particles_in(vtx) ) {
1312 if (!parent) continue;
1313 // should this really go into parton-level territory?
1314 // probably depends where BSM particles are being decayed
1315 fromBSM |= isBSM(parent);
1316 if (!isPhysical(parent)) return false;
1317 fromTau |= isTau(parent);
1318 if (isHadron(parent)&&!isBeam(parent)) {
1319 if (!hadron) hadron = parent; // assumes linear hadron parentage
1320 return true;
1321 }
1322 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1323 }
1324 return fromHad;
1325 }
1326
1329
1330 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1331 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1332 decltype(thePart->end_vertex()) pVert(nullptr);
1333 if (EndVert != nullptr) {
1334 do {
1335 bool samePart = false;
1336 pVert = nullptr;
1337 auto outgoing = EndVert->particles_out();
1338 auto incoming = EndVert->particles_in();
1339 for (const auto& itrDaug: outgoing) {
1340 if (!itrDaug) continue;
1341 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1342 // brem on generator level for tau
1343 (outgoing.size() == 1 && incoming.size() == 1 &&
1345 itrDaug->pdg_id() == thePart->pdg_id()) {
1346 samePart = true;
1347 pVert = itrDaug->end_vertex();
1348 }
1349 }
1350 if (samePart) EndVert = pVert;
1351 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1352 }
1353 return EndVert;
1354 }
1355
1357
1358 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1359 if (!theVert) return {};
1360 decltype(theVert->particles_out()) finalStatePart;
1361 auto outgoing = theVert->particles_out();
1362 for (const auto& thePart: outgoing) {
1363 if (!thePart) continue;
1364 finalStatePart.push_back(thePart);
1365 if (isStable(thePart)) continue;
1366 V pVert = findSimulatedEndVertex(thePart);
1367 if (pVert == theVert) break; // to prevent Sherpa loop
1368 if (pVert != nullptr) {
1369 auto vecPart = findFinalStateParticles<V>(pVert);
1370 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1371 }
1372 }
1373 return finalStatePart;
1374 }
1375#if !defined(XAOD_ANALYSIS)
1376#include "AtlasHepMC/GenEvent.h"
1377inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1378inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1379
1380#endif
1381}
1382#endif

◆ isExcited() [1/3]

template<>
bool MC::isExcited ( const DecodedPID & p)
inline

Definition at line 539 of file HepMCHelpers.h.

558{
559 template <class VTX>
560 auto particles_in (const VTX* p) { return p->particles_in(); }
561 template <class VTX>
562 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
563
564 namespace Pythia8
565 {
567 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
568
569 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
570
571 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
572 }
573
574#include "AtlasPID.h"
575
577 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
578
580 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
581
583 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
584
586 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
587
589 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
590
592 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
593
595 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
596
598 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
599
601 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
602
604 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
605
609 template <class T> inline bool isStableOrSimDecayed(const T& p) {
610 const auto vertex = p->end_vertex();
611 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
612 }
613
615 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
616
618 template <class T> inline bool isSpecialNonInteracting(const T& p) {
619 const int apid = std::abs(p->pdg_id());
620 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
621 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
622 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
623 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
624 return false;
625 }
626
628
629 template <class T> T findMother(T thePart) {
630 auto partOriVert = thePart->production_vertex();
631 if (!partOriVert) return nullptr;
632
633 long partPDG = thePart->pdg_id();
634 long MotherPDG(0);
635
636 auto MothOriVert = partOriVert;
637 MothOriVert = nullptr;
638 T theMoth(nullptr);
639
640 size_t itr = 0;
641 do {
642 if (itr != 0) partOriVert = MothOriVert;
643 for ( const auto& p : particles_in(partOriVert) ) {
644 theMoth = p;
645 if (!theMoth) continue;
646 MotherPDG = theMoth->pdg_id();
647 MothOriVert = theMoth->production_vertex();
648 if (MotherPDG == partPDG) break;
649 }
650 itr++;
651 if (itr > 100) {
652 break;
653 }
654 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
655 MothOriVert != partOriVert);
656 return theMoth;
657 }
658
660
661 template <class C, class T> T findMatching(C TruthContainer, T p) {
662 T ptrPart = nullptr;
663 if (!p) return ptrPart;
664 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
665 for (T truthParticle : *TruthContainer) {
666 if (HepMC::is_sim_descendant(p,truthParticle)) {
667 ptrPart = truthParticle;
668 break;
669 }
670 }
671 }
672 else {
673 for (T truthParticle : TruthContainer) {
674 if (HepMC::is_sim_descendant(p,truthParticle)) {
675 ptrPart = truthParticle;
676 break;
677 }
678 }
679 }
680 return ptrPart;
681 }
683
684 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
685 auto prodVtx = thePart->production_vertex();
686 if (!prodVtx) return;
687 for (const auto& theMother: prodVtx->particles_in()) {
688 if (!theMother) continue;
689 allancestors.insert(theMother);
690 findParticleAncestors(theMother, allancestors);
691 }
692 }
693
695
696 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
697 auto endVtx = thePart->end_vertex();
698 if (!endVtx) return;
699 for (const auto& theDaughter: endVtx->particles_out()) {
700 if (!theDaughter) continue;
701 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
702 allstabledescendants.insert(theDaughter);
703 }
704 findParticleStableDescendants(theDaughter, allstabledescendants);
705 }
706 }
707
711
712 template <class T> bool isHardScatteringVertex(T pVert) {
713 if (pVert == nullptr) return false;
714 T pV = pVert;
715 int numOfPartIn(0);
716 int pdg(0);
717
718 do {
719 pVert = pV;
720 auto incoming = pVert->particles_in();
721 numOfPartIn = incoming.size();
722 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
723 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
724
725 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
726
727 if (numOfPartIn == 2) {
728 auto incoming = pVert->particles_in();
729 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
730 }
731 return false;
732}
733
737
738 template <class T, class U>
739 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
740 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
741 auto vtx = p->production_vertex();
742 if (!vtx) return false;
743 bool fromHad = false;
744 for ( const auto& parent : particles_in(vtx) ) {
745 if (!parent) continue;
746 // should this really go into parton-level territory?
747 // probably depends where BSM particles are being decayed
748 fromBSM |= isBSM(parent);
749 if (!isPhysical(parent)) return false;
750 fromTau |= isTau(parent);
751 if (isHadron(parent)&&!isBeam(parent)) {
752 if (!hadron) hadron = parent; // assumes linear hadron parentage
753 return true;
754 }
755 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
756 }
757 return fromHad;
758 }
759
762
763 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
764 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
765 decltype(thePart->end_vertex()) pVert(nullptr);
766 if (EndVert != nullptr) {
767 do {
768 bool samePart = false;
769 pVert = nullptr;
770 auto outgoing = EndVert->particles_out();
771 auto incoming = EndVert->particles_in();
772 for (const auto& itrDaug: outgoing) {
773 if (!itrDaug) continue;
774 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
775 // brem on generator level for tau
776 (outgoing.size() == 1 && incoming.size() == 1 &&
778 itrDaug->pdg_id() == thePart->pdg_id()) {
779 samePart = true;
780 pVert = itrDaug->end_vertex();
781 }
782 }
783 if (samePart) EndVert = pVert;
784 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
785 }
786 return EndVert;
787 }
788
790
791 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
792 if (!theVert) return {};
793 decltype(theVert->particles_out()) finalStatePart;
794 auto outgoing = theVert->particles_out();
795 for (const auto& thePart: outgoing) {
796 if (!thePart) continue;
797 finalStatePart.push_back(thePart);
798 if (isStable(thePart)) continue;
799 V pVert = findSimulatedEndVertex(thePart);
800 if (pVert == theVert) break; // to prevent Sherpa loop
801 if (pVert != nullptr) {
802 auto vecPart = findFinalStateParticles<V>(pVert);
803 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
804 }
805 }
806 return finalStatePart;
807 }
808#if !defined(XAOD_ANALYSIS)
809#include "AtlasHepMC/GenEvent.h"
810inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
811inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
812
813#endif
814}
815#endif

◆ isExcited() [2/3]

template<>
bool MC::isExcited ( const int & p)
inline

Definition at line 544 of file HepMCHelpers.h.

563{
564 template <class VTX>
565 auto particles_in (const VTX* p) { return p->particles_in(); }
566 template <class VTX>
567 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
568
569 namespace Pythia8
570 {
572 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
573
574 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
575
576 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
577 }
578
579#include "AtlasPID.h"
580
582 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
583
585 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
586
588 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
589
591 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
592
594 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
595
597 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
598
600 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
601
603 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
604
606 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
607
609 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
610
614 template <class T> inline bool isStableOrSimDecayed(const T& p) {
615 const auto vertex = p->end_vertex();
616 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
617 }
618
620 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
621
623 template <class T> inline bool isSpecialNonInteracting(const T& p) {
624 const int apid = std::abs(p->pdg_id());
625 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
626 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
627 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
628 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
629 return false;
630 }
631
633
634 template <class T> T findMother(T thePart) {
635 auto partOriVert = thePart->production_vertex();
636 if (!partOriVert) return nullptr;
637
638 long partPDG = thePart->pdg_id();
639 long MotherPDG(0);
640
641 auto MothOriVert = partOriVert;
642 MothOriVert = nullptr;
643 T theMoth(nullptr);
644
645 size_t itr = 0;
646 do {
647 if (itr != 0) partOriVert = MothOriVert;
648 for ( const auto& p : particles_in(partOriVert) ) {
649 theMoth = p;
650 if (!theMoth) continue;
651 MotherPDG = theMoth->pdg_id();
652 MothOriVert = theMoth->production_vertex();
653 if (MotherPDG == partPDG) break;
654 }
655 itr++;
656 if (itr > 100) {
657 break;
658 }
659 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
660 MothOriVert != partOriVert);
661 return theMoth;
662 }
663
665
666 template <class C, class T> T findMatching(C TruthContainer, T p) {
667 T ptrPart = nullptr;
668 if (!p) return ptrPart;
669 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
670 for (T truthParticle : *TruthContainer) {
671 if (HepMC::is_sim_descendant(p,truthParticle)) {
672 ptrPart = truthParticle;
673 break;
674 }
675 }
676 }
677 else {
678 for (T truthParticle : TruthContainer) {
679 if (HepMC::is_sim_descendant(p,truthParticle)) {
680 ptrPart = truthParticle;
681 break;
682 }
683 }
684 }
685 return ptrPart;
686 }
688
689 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
690 auto prodVtx = thePart->production_vertex();
691 if (!prodVtx) return;
692 for (const auto& theMother: prodVtx->particles_in()) {
693 if (!theMother) continue;
694 allancestors.insert(theMother);
695 findParticleAncestors(theMother, allancestors);
696 }
697 }
698
700
701 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
702 auto endVtx = thePart->end_vertex();
703 if (!endVtx) return;
704 for (const auto& theDaughter: endVtx->particles_out()) {
705 if (!theDaughter) continue;
706 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
707 allstabledescendants.insert(theDaughter);
708 }
709 findParticleStableDescendants(theDaughter, allstabledescendants);
710 }
711 }
712
716
717 template <class T> bool isHardScatteringVertex(T pVert) {
718 if (pVert == nullptr) return false;
719 T pV = pVert;
720 int numOfPartIn(0);
721 int pdg(0);
722
723 do {
724 pVert = pV;
725 auto incoming = pVert->particles_in();
726 numOfPartIn = incoming.size();
727 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
728 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
729
730 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
731
732 if (numOfPartIn == 2) {
733 auto incoming = pVert->particles_in();
734 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
735 }
736 return false;
737}
738
742
743 template <class T, class U>
744 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
745 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
746 auto vtx = p->production_vertex();
747 if (!vtx) return false;
748 bool fromHad = false;
749 for ( const auto& parent : particles_in(vtx) ) {
750 if (!parent) continue;
751 // should this really go into parton-level territory?
752 // probably depends where BSM particles are being decayed
753 fromBSM |= isBSM(parent);
754 if (!isPhysical(parent)) return false;
755 fromTau |= isTau(parent);
756 if (isHadron(parent)&&!isBeam(parent)) {
757 if (!hadron) hadron = parent; // assumes linear hadron parentage
758 return true;
759 }
760 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
761 }
762 return fromHad;
763 }
764
767
768 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
769 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
770 decltype(thePart->end_vertex()) pVert(nullptr);
771 if (EndVert != nullptr) {
772 do {
773 bool samePart = false;
774 pVert = nullptr;
775 auto outgoing = EndVert->particles_out();
776 auto incoming = EndVert->particles_in();
777 for (const auto& itrDaug: outgoing) {
778 if (!itrDaug) continue;
779 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
780 // brem on generator level for tau
781 (outgoing.size() == 1 && incoming.size() == 1 &&
783 itrDaug->pdg_id() == thePart->pdg_id()) {
784 samePart = true;
785 pVert = itrDaug->end_vertex();
786 }
787 }
788 if (samePart) EndVert = pVert;
789 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
790 }
791 return EndVert;
792 }
793
795
796 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
797 if (!theVert) return {};
798 decltype(theVert->particles_out()) finalStatePart;
799 auto outgoing = theVert->particles_out();
800 for (const auto& thePart: outgoing) {
801 if (!thePart) continue;
802 finalStatePart.push_back(thePart);
803 if (isStable(thePart)) continue;
804 V pVert = findSimulatedEndVertex(thePart);
805 if (pVert == theVert) break; // to prevent Sherpa loop
806 if (pVert != nullptr) {
807 auto vecPart = findFinalStateParticles<V>(pVert);
808 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
809 }
810 }
811 return finalStatePart;
812 }
813#if !defined(XAOD_ANALYSIS)
814#include "AtlasHepMC/GenEvent.h"
815inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
816inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
817
818#endif
819}
820#endif

◆ isExcited() [3/3]

template<class T>
bool MC::isExcited ( const T & p)
inline

PDG rule 11f Excited (composite) quarks and leptons are identified by setting n= 4 and nr= 0.

Definition at line 537 of file HepMCHelpers.h.

556{
557 template <class VTX>
558 auto particles_in (const VTX* p) { return p->particles_in(); }
559 template <class VTX>
560 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
561
562 namespace Pythia8
563 {
565 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
566
567 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
568
569 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
570 }
571
572#include "AtlasPID.h"
573
575 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
576
578 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
579
581 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
582
584 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
585
587 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
588
590 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
591
593 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
594
596 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
597
599 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
600
602 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
603
607 template <class T> inline bool isStableOrSimDecayed(const T& p) {
608 const auto vertex = p->end_vertex();
609 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
610 }
611
613 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
614
616 template <class T> inline bool isSpecialNonInteracting(const T& p) {
617 const int apid = std::abs(p->pdg_id());
618 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
619 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
620 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
621 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
622 return false;
623 }
624
626
627 template <class T> T findMother(T thePart) {
628 auto partOriVert = thePart->production_vertex();
629 if (!partOriVert) return nullptr;
630
631 long partPDG = thePart->pdg_id();
632 long MotherPDG(0);
633
634 auto MothOriVert = partOriVert;
635 MothOriVert = nullptr;
636 T theMoth(nullptr);
637
638 size_t itr = 0;
639 do {
640 if (itr != 0) partOriVert = MothOriVert;
641 for ( const auto& p : particles_in(partOriVert) ) {
642 theMoth = p;
643 if (!theMoth) continue;
644 MotherPDG = theMoth->pdg_id();
645 MothOriVert = theMoth->production_vertex();
646 if (MotherPDG == partPDG) break;
647 }
648 itr++;
649 if (itr > 100) {
650 break;
651 }
652 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
653 MothOriVert != partOriVert);
654 return theMoth;
655 }
656
658
659 template <class C, class T> T findMatching(C TruthContainer, T p) {
660 T ptrPart = nullptr;
661 if (!p) return ptrPart;
662 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
663 for (T truthParticle : *TruthContainer) {
664 if (HepMC::is_sim_descendant(p,truthParticle)) {
665 ptrPart = truthParticle;
666 break;
667 }
668 }
669 }
670 else {
671 for (T truthParticle : TruthContainer) {
672 if (HepMC::is_sim_descendant(p,truthParticle)) {
673 ptrPart = truthParticle;
674 break;
675 }
676 }
677 }
678 return ptrPart;
679 }
681
682 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
683 auto prodVtx = thePart->production_vertex();
684 if (!prodVtx) return;
685 for (const auto& theMother: prodVtx->particles_in()) {
686 if (!theMother) continue;
687 allancestors.insert(theMother);
688 findParticleAncestors(theMother, allancestors);
689 }
690 }
691
693
694 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
695 auto endVtx = thePart->end_vertex();
696 if (!endVtx) return;
697 for (const auto& theDaughter: endVtx->particles_out()) {
698 if (!theDaughter) continue;
699 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
700 allstabledescendants.insert(theDaughter);
701 }
702 findParticleStableDescendants(theDaughter, allstabledescendants);
703 }
704 }
705
709
710 template <class T> bool isHardScatteringVertex(T pVert) {
711 if (pVert == nullptr) return false;
712 T pV = pVert;
713 int numOfPartIn(0);
714 int pdg(0);
715
716 do {
717 pVert = pV;
718 auto incoming = pVert->particles_in();
719 numOfPartIn = incoming.size();
720 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
721 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
722
723 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
724
725 if (numOfPartIn == 2) {
726 auto incoming = pVert->particles_in();
727 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
728 }
729 return false;
730}
731
735
736 template <class T, class U>
737 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
738 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
739 auto vtx = p->production_vertex();
740 if (!vtx) return false;
741 bool fromHad = false;
742 for ( const auto& parent : particles_in(vtx) ) {
743 if (!parent) continue;
744 // should this really go into parton-level territory?
745 // probably depends where BSM particles are being decayed
746 fromBSM |= isBSM(parent);
747 if (!isPhysical(parent)) return false;
748 fromTau |= isTau(parent);
749 if (isHadron(parent)&&!isBeam(parent)) {
750 if (!hadron) hadron = parent; // assumes linear hadron parentage
751 return true;
752 }
753 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
754 }
755 return fromHad;
756 }
757
760
761 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
762 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
763 decltype(thePart->end_vertex()) pVert(nullptr);
764 if (EndVert != nullptr) {
765 do {
766 bool samePart = false;
767 pVert = nullptr;
768 auto outgoing = EndVert->particles_out();
769 auto incoming = EndVert->particles_in();
770 for (const auto& itrDaug: outgoing) {
771 if (!itrDaug) continue;
772 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
773 // brem on generator level for tau
774 (outgoing.size() == 1 && incoming.size() == 1 &&
776 itrDaug->pdg_id() == thePart->pdg_id()) {
777 samePart = true;
778 pVert = itrDaug->end_vertex();
779 }
780 }
781 if (samePart) EndVert = pVert;
782 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
783 }
784 return EndVert;
785 }
786
788
789 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
790 if (!theVert) return {};
791 decltype(theVert->particles_out()) finalStatePart;
792 auto outgoing = theVert->particles_out();
793 for (const auto& thePart: outgoing) {
794 if (!thePart) continue;
795 finalStatePart.push_back(thePart);
796 if (isStable(thePart)) continue;
797 V pVert = findSimulatedEndVertex(thePart);
798 if (pVert == theVert) break; // to prevent Sherpa loop
799 if (pVert != nullptr) {
800 auto vecPart = findFinalStateParticles<V>(pVert);
801 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
802 }
803 }
804 return finalStatePart;
805 }
806#if !defined(XAOD_ANALYSIS)
807#include "AtlasHepMC/GenEvent.h"
808inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
809inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
810
811#endif
812}
813#endif

◆ isFinalState()

template<class T>
bool MC::isFinalState ( const T & p)
inline

Identify if the particle is final state particle.

Definition at line 54 of file HepMCHelpers.h.

54{ return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}

◆ isFourthGeneration() [1/2]

template<>
bool MC::isFourthGeneration ( const int & p)
inline

Definition at line 222 of file HepMCHelpers.h.

◆ isFourthGeneration() [2/2]

template<class T>
bool MC::isFourthGeneration ( const T & p)
inline

Is this a 4th generation fermion?

APID: 4th generation fermions are not standard model particles

Definition at line 221 of file HepMCHelpers.h.

◆ isFromHadron()

template<class T, class U>
bool MC::isFromHadron ( T p,
U hadron,
bool & fromTau,
bool & fromBSM )

Function to classify the particle.

AV: This is MCtruthClassifier legacy. The function should be improved in the future. This can be used for HepMC3::GenVertexPtr, HepMC3::ConstGenVertexPtr or xAOD::TruthVertex*

Definition at line 201 of file HepMCHelpers.h.

201 {
202 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
203 auto vtx = p->production_vertex();
204 if (!vtx) return false;
205 bool fromHad = false;
206 for ( const auto& parent : particles_in(vtx) ) {
207 if (!parent) continue;
208 // should this really go into parton-level territory?
209 // probably depends where BSM particles are being decayed
210 fromBSM |= isBSM(parent);
211 if (!isPhysical(parent)) return false;
212 fromTau |= isTau(parent);
213 if (isHadron(parent)&&!isBeam(parent)) {
214 if (!hadron) hadron = parent; // assumes linear hadron parentage
215 return true;
216 }
217 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
218 }
219 return fromHad;
220 }

◆ isGaugino() [1/3]

template<>
bool MC::isGaugino ( const DecodedPID & p)
inline

Definition at line 506 of file HepMCHelpers.h.

525{
526 template <class VTX>
527 auto particles_in (const VTX* p) { return p->particles_in(); }
528 template <class VTX>
529 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
530
531 namespace Pythia8
532 {
534 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
535
536 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
537
538 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
539 }
540
541#include "AtlasPID.h"
542
544 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
545
547 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
548
550 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
551
553 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
554
556 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
557
559 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
560
562 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
563
565 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
566
568 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
569
571 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
572
576 template <class T> inline bool isStableOrSimDecayed(const T& p) {
577 const auto vertex = p->end_vertex();
578 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
579 }
580
582 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
583
585 template <class T> inline bool isSpecialNonInteracting(const T& p) {
586 const int apid = std::abs(p->pdg_id());
587 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
588 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
589 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
590 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
591 return false;
592 }
593
595
596 template <class T> T findMother(T thePart) {
597 auto partOriVert = thePart->production_vertex();
598 if (!partOriVert) return nullptr;
599
600 long partPDG = thePart->pdg_id();
601 long MotherPDG(0);
602
603 auto MothOriVert = partOriVert;
604 MothOriVert = nullptr;
605 T theMoth(nullptr);
606
607 size_t itr = 0;
608 do {
609 if (itr != 0) partOriVert = MothOriVert;
610 for ( const auto& p : particles_in(partOriVert) ) {
611 theMoth = p;
612 if (!theMoth) continue;
613 MotherPDG = theMoth->pdg_id();
614 MothOriVert = theMoth->production_vertex();
615 if (MotherPDG == partPDG) break;
616 }
617 itr++;
618 if (itr > 100) {
619 break;
620 }
621 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
622 MothOriVert != partOriVert);
623 return theMoth;
624 }
625
627
628 template <class C, class T> T findMatching(C TruthContainer, T p) {
629 T ptrPart = nullptr;
630 if (!p) return ptrPart;
631 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
632 for (T truthParticle : *TruthContainer) {
633 if (HepMC::is_sim_descendant(p,truthParticle)) {
634 ptrPart = truthParticle;
635 break;
636 }
637 }
638 }
639 else {
640 for (T truthParticle : TruthContainer) {
641 if (HepMC::is_sim_descendant(p,truthParticle)) {
642 ptrPart = truthParticle;
643 break;
644 }
645 }
646 }
647 return ptrPart;
648 }
650
651 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
652 auto prodVtx = thePart->production_vertex();
653 if (!prodVtx) return;
654 for (const auto& theMother: prodVtx->particles_in()) {
655 if (!theMother) continue;
656 allancestors.insert(theMother);
657 findParticleAncestors(theMother, allancestors);
658 }
659 }
660
662
663 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
664 auto endVtx = thePart->end_vertex();
665 if (!endVtx) return;
666 for (const auto& theDaughter: endVtx->particles_out()) {
667 if (!theDaughter) continue;
668 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
669 allstabledescendants.insert(theDaughter);
670 }
671 findParticleStableDescendants(theDaughter, allstabledescendants);
672 }
673 }
674
678
679 template <class T> bool isHardScatteringVertex(T pVert) {
680 if (pVert == nullptr) return false;
681 T pV = pVert;
682 int numOfPartIn(0);
683 int pdg(0);
684
685 do {
686 pVert = pV;
687 auto incoming = pVert->particles_in();
688 numOfPartIn = incoming.size();
689 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
690 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
691
692 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
693
694 if (numOfPartIn == 2) {
695 auto incoming = pVert->particles_in();
696 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
697 }
698 return false;
699}
700
704
705 template <class T, class U>
706 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
707 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
708 auto vtx = p->production_vertex();
709 if (!vtx) return false;
710 bool fromHad = false;
711 for ( const auto& parent : particles_in(vtx) ) {
712 if (!parent) continue;
713 // should this really go into parton-level territory?
714 // probably depends where BSM particles are being decayed
715 fromBSM |= isBSM(parent);
716 if (!isPhysical(parent)) return false;
717 fromTau |= isTau(parent);
718 if (isHadron(parent)&&!isBeam(parent)) {
719 if (!hadron) hadron = parent; // assumes linear hadron parentage
720 return true;
721 }
722 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
723 }
724 return fromHad;
725 }
726
729
730 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
731 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
732 decltype(thePart->end_vertex()) pVert(nullptr);
733 if (EndVert != nullptr) {
734 do {
735 bool samePart = false;
736 pVert = nullptr;
737 auto outgoing = EndVert->particles_out();
738 auto incoming = EndVert->particles_in();
739 for (const auto& itrDaug: outgoing) {
740 if (!itrDaug) continue;
741 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
742 // brem on generator level for tau
743 (outgoing.size() == 1 && incoming.size() == 1 &&
745 itrDaug->pdg_id() == thePart->pdg_id()) {
746 samePart = true;
747 pVert = itrDaug->end_vertex();
748 }
749 }
750 if (samePart) EndVert = pVert;
751 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
752 }
753 return EndVert;
754 }
755
757
758 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
759 if (!theVert) return {};
760 decltype(theVert->particles_out()) finalStatePart;
761 auto outgoing = theVert->particles_out();
762 for (const auto& thePart: outgoing) {
763 if (!thePart) continue;
764 finalStatePart.push_back(thePart);
765 if (isStable(thePart)) continue;
766 V pVert = findSimulatedEndVertex(thePart);
767 if (pVert == theVert) break; // to prevent Sherpa loop
768 if (pVert != nullptr) {
769 auto vecPart = findFinalStateParticles<V>(pVert);
770 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
771 }
772 }
773 return finalStatePart;
774 }
775#if !defined(XAOD_ANALYSIS)
776#include "AtlasHepMC/GenEvent.h"
777inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
778inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
779
780#endif
781}
782#endif

◆ isGaugino() [2/3]

template<>
bool MC::isGaugino ( const int & p)
inline

Definition at line 509 of file HepMCHelpers.h.

528{
529 template <class VTX>
530 auto particles_in (const VTX* p) { return p->particles_in(); }
531 template <class VTX>
532 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
533
534 namespace Pythia8
535 {
537 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
538
539 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
540
541 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
542 }
543
544#include "AtlasPID.h"
545
547 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
548
550 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
551
553 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
554
556 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
557
559 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
560
562 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
563
565 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
566
568 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
569
571 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
572
574 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
575
579 template <class T> inline bool isStableOrSimDecayed(const T& p) {
580 const auto vertex = p->end_vertex();
581 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
582 }
583
585 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
586
588 template <class T> inline bool isSpecialNonInteracting(const T& p) {
589 const int apid = std::abs(p->pdg_id());
590 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
591 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
592 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
593 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
594 return false;
595 }
596
598
599 template <class T> T findMother(T thePart) {
600 auto partOriVert = thePart->production_vertex();
601 if (!partOriVert) return nullptr;
602
603 long partPDG = thePart->pdg_id();
604 long MotherPDG(0);
605
606 auto MothOriVert = partOriVert;
607 MothOriVert = nullptr;
608 T theMoth(nullptr);
609
610 size_t itr = 0;
611 do {
612 if (itr != 0) partOriVert = MothOriVert;
613 for ( const auto& p : particles_in(partOriVert) ) {
614 theMoth = p;
615 if (!theMoth) continue;
616 MotherPDG = theMoth->pdg_id();
617 MothOriVert = theMoth->production_vertex();
618 if (MotherPDG == partPDG) break;
619 }
620 itr++;
621 if (itr > 100) {
622 break;
623 }
624 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
625 MothOriVert != partOriVert);
626 return theMoth;
627 }
628
630
631 template <class C, class T> T findMatching(C TruthContainer, T p) {
632 T ptrPart = nullptr;
633 if (!p) return ptrPart;
634 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
635 for (T truthParticle : *TruthContainer) {
636 if (HepMC::is_sim_descendant(p,truthParticle)) {
637 ptrPart = truthParticle;
638 break;
639 }
640 }
641 }
642 else {
643 for (T truthParticle : TruthContainer) {
644 if (HepMC::is_sim_descendant(p,truthParticle)) {
645 ptrPart = truthParticle;
646 break;
647 }
648 }
649 }
650 return ptrPart;
651 }
653
654 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
655 auto prodVtx = thePart->production_vertex();
656 if (!prodVtx) return;
657 for (const auto& theMother: prodVtx->particles_in()) {
658 if (!theMother) continue;
659 allancestors.insert(theMother);
660 findParticleAncestors(theMother, allancestors);
661 }
662 }
663
665
666 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
667 auto endVtx = thePart->end_vertex();
668 if (!endVtx) return;
669 for (const auto& theDaughter: endVtx->particles_out()) {
670 if (!theDaughter) continue;
671 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
672 allstabledescendants.insert(theDaughter);
673 }
674 findParticleStableDescendants(theDaughter, allstabledescendants);
675 }
676 }
677
681
682 template <class T> bool isHardScatteringVertex(T pVert) {
683 if (pVert == nullptr) return false;
684 T pV = pVert;
685 int numOfPartIn(0);
686 int pdg(0);
687
688 do {
689 pVert = pV;
690 auto incoming = pVert->particles_in();
691 numOfPartIn = incoming.size();
692 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
693 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
694
695 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
696
697 if (numOfPartIn == 2) {
698 auto incoming = pVert->particles_in();
699 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
700 }
701 return false;
702}
703
707
708 template <class T, class U>
709 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
710 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
711 auto vtx = p->production_vertex();
712 if (!vtx) return false;
713 bool fromHad = false;
714 for ( const auto& parent : particles_in(vtx) ) {
715 if (!parent) continue;
716 // should this really go into parton-level territory?
717 // probably depends where BSM particles are being decayed
718 fromBSM |= isBSM(parent);
719 if (!isPhysical(parent)) return false;
720 fromTau |= isTau(parent);
721 if (isHadron(parent)&&!isBeam(parent)) {
722 if (!hadron) hadron = parent; // assumes linear hadron parentage
723 return true;
724 }
725 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
726 }
727 return fromHad;
728 }
729
732
733 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
734 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
735 decltype(thePart->end_vertex()) pVert(nullptr);
736 if (EndVert != nullptr) {
737 do {
738 bool samePart = false;
739 pVert = nullptr;
740 auto outgoing = EndVert->particles_out();
741 auto incoming = EndVert->particles_in();
742 for (const auto& itrDaug: outgoing) {
743 if (!itrDaug) continue;
744 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
745 // brem on generator level for tau
746 (outgoing.size() == 1 && incoming.size() == 1 &&
748 itrDaug->pdg_id() == thePart->pdg_id()) {
749 samePart = true;
750 pVert = itrDaug->end_vertex();
751 }
752 }
753 if (samePart) EndVert = pVert;
754 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
755 }
756 return EndVert;
757 }
758
760
761 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
762 if (!theVert) return {};
763 decltype(theVert->particles_out()) finalStatePart;
764 auto outgoing = theVert->particles_out();
765 for (const auto& thePart: outgoing) {
766 if (!thePart) continue;
767 finalStatePart.push_back(thePart);
768 if (isStable(thePart)) continue;
769 V pVert = findSimulatedEndVertex(thePart);
770 if (pVert == theVert) break; // to prevent Sherpa loop
771 if (pVert != nullptr) {
772 auto vecPart = findFinalStateParticles<V>(pVert);
773 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
774 }
775 }
776 return finalStatePart;
777 }
778#if !defined(XAOD_ANALYSIS)
779#include "AtlasHepMC/GenEvent.h"
780inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
781inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
782
783#endif
784}
785#endif

◆ isGaugino() [3/3]

template<class T>
bool MC::isGaugino ( const T & p)
inline

Definition at line 505 of file HepMCHelpers.h.

524{
525 template <class VTX>
526 auto particles_in (const VTX* p) { return p->particles_in(); }
527 template <class VTX>
528 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
529
530 namespace Pythia8
531 {
533 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
534
535 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
536
537 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
538 }
539
540#include "AtlasPID.h"
541
543 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
544
546 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
547
549 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
550
552 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
553
555 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
556
558 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
559
561 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
562
564 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
565
567 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
568
570 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
571
575 template <class T> inline bool isStableOrSimDecayed(const T& p) {
576 const auto vertex = p->end_vertex();
577 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
578 }
579
581 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
582
584 template <class T> inline bool isSpecialNonInteracting(const T& p) {
585 const int apid = std::abs(p->pdg_id());
586 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
587 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
588 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
589 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
590 return false;
591 }
592
594
595 template <class T> T findMother(T thePart) {
596 auto partOriVert = thePart->production_vertex();
597 if (!partOriVert) return nullptr;
598
599 long partPDG = thePart->pdg_id();
600 long MotherPDG(0);
601
602 auto MothOriVert = partOriVert;
603 MothOriVert = nullptr;
604 T theMoth(nullptr);
605
606 size_t itr = 0;
607 do {
608 if (itr != 0) partOriVert = MothOriVert;
609 for ( const auto& p : particles_in(partOriVert) ) {
610 theMoth = p;
611 if (!theMoth) continue;
612 MotherPDG = theMoth->pdg_id();
613 MothOriVert = theMoth->production_vertex();
614 if (MotherPDG == partPDG) break;
615 }
616 itr++;
617 if (itr > 100) {
618 break;
619 }
620 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
621 MothOriVert != partOriVert);
622 return theMoth;
623 }
624
626
627 template <class C, class T> T findMatching(C TruthContainer, T p) {
628 T ptrPart = nullptr;
629 if (!p) return ptrPart;
630 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
631 for (T truthParticle : *TruthContainer) {
632 if (HepMC::is_sim_descendant(p,truthParticle)) {
633 ptrPart = truthParticle;
634 break;
635 }
636 }
637 }
638 else {
639 for (T truthParticle : TruthContainer) {
640 if (HepMC::is_sim_descendant(p,truthParticle)) {
641 ptrPart = truthParticle;
642 break;
643 }
644 }
645 }
646 return ptrPart;
647 }
649
650 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
651 auto prodVtx = thePart->production_vertex();
652 if (!prodVtx) return;
653 for (const auto& theMother: prodVtx->particles_in()) {
654 if (!theMother) continue;
655 allancestors.insert(theMother);
656 findParticleAncestors(theMother, allancestors);
657 }
658 }
659
661
662 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
663 auto endVtx = thePart->end_vertex();
664 if (!endVtx) return;
665 for (const auto& theDaughter: endVtx->particles_out()) {
666 if (!theDaughter) continue;
667 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
668 allstabledescendants.insert(theDaughter);
669 }
670 findParticleStableDescendants(theDaughter, allstabledescendants);
671 }
672 }
673
677
678 template <class T> bool isHardScatteringVertex(T pVert) {
679 if (pVert == nullptr) return false;
680 T pV = pVert;
681 int numOfPartIn(0);
682 int pdg(0);
683
684 do {
685 pVert = pV;
686 auto incoming = pVert->particles_in();
687 numOfPartIn = incoming.size();
688 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
689 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
690
691 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
692
693 if (numOfPartIn == 2) {
694 auto incoming = pVert->particles_in();
695 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
696 }
697 return false;
698}
699
703
704 template <class T, class U>
705 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
706 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
707 auto vtx = p->production_vertex();
708 if (!vtx) return false;
709 bool fromHad = false;
710 for ( const auto& parent : particles_in(vtx) ) {
711 if (!parent) continue;
712 // should this really go into parton-level territory?
713 // probably depends where BSM particles are being decayed
714 fromBSM |= isBSM(parent);
715 if (!isPhysical(parent)) return false;
716 fromTau |= isTau(parent);
717 if (isHadron(parent)&&!isBeam(parent)) {
718 if (!hadron) hadron = parent; // assumes linear hadron parentage
719 return true;
720 }
721 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
722 }
723 return fromHad;
724 }
725
728
729 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
730 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
731 decltype(thePart->end_vertex()) pVert(nullptr);
732 if (EndVert != nullptr) {
733 do {
734 bool samePart = false;
735 pVert = nullptr;
736 auto outgoing = EndVert->particles_out();
737 auto incoming = EndVert->particles_in();
738 for (const auto& itrDaug: outgoing) {
739 if (!itrDaug) continue;
740 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
741 // brem on generator level for tau
742 (outgoing.size() == 1 && incoming.size() == 1 &&
744 itrDaug->pdg_id() == thePart->pdg_id()) {
745 samePart = true;
746 pVert = itrDaug->end_vertex();
747 }
748 }
749 if (samePart) EndVert = pVert;
750 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
751 }
752 return EndVert;
753 }
754
756
757 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
758 if (!theVert) return {};
759 decltype(theVert->particles_out()) finalStatePart;
760 auto outgoing = theVert->particles_out();
761 for (const auto& thePart: outgoing) {
762 if (!thePart) continue;
763 finalStatePart.push_back(thePart);
764 if (isStable(thePart)) continue;
765 V pVert = findSimulatedEndVertex(thePart);
766 if (pVert == theVert) break; // to prevent Sherpa loop
767 if (pVert != nullptr) {
768 auto vecPart = findFinalStateParticles<V>(pVert);
769 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
770 }
771 }
772 return finalStatePart;
773 }
774#if !defined(XAOD_ANALYSIS)
775#include "AtlasHepMC/GenEvent.h"
776inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
777inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
778
779#endif
780}
781#endif

◆ isGeantino() [1/2]

template<>
bool MC::isGeantino ( const int & p)
inline

Definition at line 439 of file HepMCHelpers.h.

458{
459 template <class VTX>
460 auto particles_in (const VTX* p) { return p->particles_in(); }
461 template <class VTX>
462 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
463
464 namespace Pythia8
465 {
467 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
468
469 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
470
471 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
472 }
473
474#include "AtlasPID.h"
475
477 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
478
480 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
481
483 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
484
486 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
487
489 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
490
492 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
493
495 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
496
498 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
499
501 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
502
504 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
505
509 template <class T> inline bool isStableOrSimDecayed(const T& p) {
510 const auto vertex = p->end_vertex();
511 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
512 }
513
515 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
516
518 template <class T> inline bool isSpecialNonInteracting(const T& p) {
519 const int apid = std::abs(p->pdg_id());
520 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
521 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
522 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
523 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
524 return false;
525 }
526
528
529 template <class T> T findMother(T thePart) {
530 auto partOriVert = thePart->production_vertex();
531 if (!partOriVert) return nullptr;
532
533 long partPDG = thePart->pdg_id();
534 long MotherPDG(0);
535
536 auto MothOriVert = partOriVert;
537 MothOriVert = nullptr;
538 T theMoth(nullptr);
539
540 size_t itr = 0;
541 do {
542 if (itr != 0) partOriVert = MothOriVert;
543 for ( const auto& p : particles_in(partOriVert) ) {
544 theMoth = p;
545 if (!theMoth) continue;
546 MotherPDG = theMoth->pdg_id();
547 MothOriVert = theMoth->production_vertex();
548 if (MotherPDG == partPDG) break;
549 }
550 itr++;
551 if (itr > 100) {
552 break;
553 }
554 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
555 MothOriVert != partOriVert);
556 return theMoth;
557 }
558
560
561 template <class C, class T> T findMatching(C TruthContainer, T p) {
562 T ptrPart = nullptr;
563 if (!p) return ptrPart;
564 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
565 for (T truthParticle : *TruthContainer) {
566 if (HepMC::is_sim_descendant(p,truthParticle)) {
567 ptrPart = truthParticle;
568 break;
569 }
570 }
571 }
572 else {
573 for (T truthParticle : TruthContainer) {
574 if (HepMC::is_sim_descendant(p,truthParticle)) {
575 ptrPart = truthParticle;
576 break;
577 }
578 }
579 }
580 return ptrPart;
581 }
583
584 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
585 auto prodVtx = thePart->production_vertex();
586 if (!prodVtx) return;
587 for (const auto& theMother: prodVtx->particles_in()) {
588 if (!theMother) continue;
589 allancestors.insert(theMother);
590 findParticleAncestors(theMother, allancestors);
591 }
592 }
593
595
596 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
597 auto endVtx = thePart->end_vertex();
598 if (!endVtx) return;
599 for (const auto& theDaughter: endVtx->particles_out()) {
600 if (!theDaughter) continue;
601 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
602 allstabledescendants.insert(theDaughter);
603 }
604 findParticleStableDescendants(theDaughter, allstabledescendants);
605 }
606 }
607
611
612 template <class T> bool isHardScatteringVertex(T pVert) {
613 if (pVert == nullptr) return false;
614 T pV = pVert;
615 int numOfPartIn(0);
616 int pdg(0);
617
618 do {
619 pVert = pV;
620 auto incoming = pVert->particles_in();
621 numOfPartIn = incoming.size();
622 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
623 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
624
625 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
626
627 if (numOfPartIn == 2) {
628 auto incoming = pVert->particles_in();
629 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
630 }
631 return false;
632}
633
637
638 template <class T, class U>
639 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
640 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
641 auto vtx = p->production_vertex();
642 if (!vtx) return false;
643 bool fromHad = false;
644 for ( const auto& parent : particles_in(vtx) ) {
645 if (!parent) continue;
646 // should this really go into parton-level territory?
647 // probably depends where BSM particles are being decayed
648 fromBSM |= isBSM(parent);
649 if (!isPhysical(parent)) return false;
650 fromTau |= isTau(parent);
651 if (isHadron(parent)&&!isBeam(parent)) {
652 if (!hadron) hadron = parent; // assumes linear hadron parentage
653 return true;
654 }
655 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
656 }
657 return fromHad;
658 }
659
662
663 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
664 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
665 decltype(thePart->end_vertex()) pVert(nullptr);
666 if (EndVert != nullptr) {
667 do {
668 bool samePart = false;
669 pVert = nullptr;
670 auto outgoing = EndVert->particles_out();
671 auto incoming = EndVert->particles_in();
672 for (const auto& itrDaug: outgoing) {
673 if (!itrDaug) continue;
674 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
675 // brem on generator level for tau
676 (outgoing.size() == 1 && incoming.size() == 1 &&
678 itrDaug->pdg_id() == thePart->pdg_id()) {
679 samePart = true;
680 pVert = itrDaug->end_vertex();
681 }
682 }
683 if (samePart) EndVert = pVert;
684 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
685 }
686 return EndVert;
687 }
688
690
691 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
692 if (!theVert) return {};
693 decltype(theVert->particles_out()) finalStatePart;
694 auto outgoing = theVert->particles_out();
695 for (const auto& thePart: outgoing) {
696 if (!thePart) continue;
697 finalStatePart.push_back(thePart);
698 if (isStable(thePart)) continue;
699 V pVert = findSimulatedEndVertex(thePart);
700 if (pVert == theVert) break; // to prevent Sherpa loop
701 if (pVert != nullptr) {
702 auto vecPart = findFinalStateParticles<V>(pVert);
703 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
704 }
705 }
706 return finalStatePart;
707 }
708#if !defined(XAOD_ANALYSIS)
709#include "AtlasHepMC/GenEvent.h"
710inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
711inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
712
713#endif
714}
715#endif

◆ isGeantino() [2/2]

template<class T>
bool MC::isGeantino ( const T & p)
inline

Definition at line 438 of file HepMCHelpers.h.

457{
458 template <class VTX>
459 auto particles_in (const VTX* p) { return p->particles_in(); }
460 template <class VTX>
461 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
462
463 namespace Pythia8
464 {
466 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
467
468 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
469
470 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
471 }
472
473#include "AtlasPID.h"
474
476 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
477
479 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
480
482 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
483
485 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
486
488 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
489
491 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
492
494 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
495
497 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
498
500 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
501
503 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
504
508 template <class T> inline bool isStableOrSimDecayed(const T& p) {
509 const auto vertex = p->end_vertex();
510 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
511 }
512
514 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
515
517 template <class T> inline bool isSpecialNonInteracting(const T& p) {
518 const int apid = std::abs(p->pdg_id());
519 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
520 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
521 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
522 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
523 return false;
524 }
525
527
528 template <class T> T findMother(T thePart) {
529 auto partOriVert = thePart->production_vertex();
530 if (!partOriVert) return nullptr;
531
532 long partPDG = thePart->pdg_id();
533 long MotherPDG(0);
534
535 auto MothOriVert = partOriVert;
536 MothOriVert = nullptr;
537 T theMoth(nullptr);
538
539 size_t itr = 0;
540 do {
541 if (itr != 0) partOriVert = MothOriVert;
542 for ( const auto& p : particles_in(partOriVert) ) {
543 theMoth = p;
544 if (!theMoth) continue;
545 MotherPDG = theMoth->pdg_id();
546 MothOriVert = theMoth->production_vertex();
547 if (MotherPDG == partPDG) break;
548 }
549 itr++;
550 if (itr > 100) {
551 break;
552 }
553 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
554 MothOriVert != partOriVert);
555 return theMoth;
556 }
557
559
560 template <class C, class T> T findMatching(C TruthContainer, T p) {
561 T ptrPart = nullptr;
562 if (!p) return ptrPart;
563 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
564 for (T truthParticle : *TruthContainer) {
565 if (HepMC::is_sim_descendant(p,truthParticle)) {
566 ptrPart = truthParticle;
567 break;
568 }
569 }
570 }
571 else {
572 for (T truthParticle : TruthContainer) {
573 if (HepMC::is_sim_descendant(p,truthParticle)) {
574 ptrPart = truthParticle;
575 break;
576 }
577 }
578 }
579 return ptrPart;
580 }
582
583 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
584 auto prodVtx = thePart->production_vertex();
585 if (!prodVtx) return;
586 for (const auto& theMother: prodVtx->particles_in()) {
587 if (!theMother) continue;
588 allancestors.insert(theMother);
589 findParticleAncestors(theMother, allancestors);
590 }
591 }
592
594
595 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
596 auto endVtx = thePart->end_vertex();
597 if (!endVtx) return;
598 for (const auto& theDaughter: endVtx->particles_out()) {
599 if (!theDaughter) continue;
600 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
601 allstabledescendants.insert(theDaughter);
602 }
603 findParticleStableDescendants(theDaughter, allstabledescendants);
604 }
605 }
606
610
611 template <class T> bool isHardScatteringVertex(T pVert) {
612 if (pVert == nullptr) return false;
613 T pV = pVert;
614 int numOfPartIn(0);
615 int pdg(0);
616
617 do {
618 pVert = pV;
619 auto incoming = pVert->particles_in();
620 numOfPartIn = incoming.size();
621 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
622 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
623
624 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
625
626 if (numOfPartIn == 2) {
627 auto incoming = pVert->particles_in();
628 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
629 }
630 return false;
631}
632
636
637 template <class T, class U>
638 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
639 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
640 auto vtx = p->production_vertex();
641 if (!vtx) return false;
642 bool fromHad = false;
643 for ( const auto& parent : particles_in(vtx) ) {
644 if (!parent) continue;
645 // should this really go into parton-level territory?
646 // probably depends where BSM particles are being decayed
647 fromBSM |= isBSM(parent);
648 if (!isPhysical(parent)) return false;
649 fromTau |= isTau(parent);
650 if (isHadron(parent)&&!isBeam(parent)) {
651 if (!hadron) hadron = parent; // assumes linear hadron parentage
652 return true;
653 }
654 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
655 }
656 return fromHad;
657 }
658
661
662 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
663 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
664 decltype(thePart->end_vertex()) pVert(nullptr);
665 if (EndVert != nullptr) {
666 do {
667 bool samePart = false;
668 pVert = nullptr;
669 auto outgoing = EndVert->particles_out();
670 auto incoming = EndVert->particles_in();
671 for (const auto& itrDaug: outgoing) {
672 if (!itrDaug) continue;
673 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
674 // brem on generator level for tau
675 (outgoing.size() == 1 && incoming.size() == 1 &&
677 itrDaug->pdg_id() == thePart->pdg_id()) {
678 samePart = true;
679 pVert = itrDaug->end_vertex();
680 }
681 }
682 if (samePart) EndVert = pVert;
683 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
684 }
685 return EndVert;
686 }
687
689
690 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
691 if (!theVert) return {};
692 decltype(theVert->particles_out()) finalStatePart;
693 auto outgoing = theVert->particles_out();
694 for (const auto& thePart: outgoing) {
695 if (!thePart) continue;
696 finalStatePart.push_back(thePart);
697 if (isStable(thePart)) continue;
698 V pVert = findSimulatedEndVertex(thePart);
699 if (pVert == theVert) break; // to prevent Sherpa loop
700 if (pVert != nullptr) {
701 auto vecPart = findFinalStateParticles<V>(pVert);
702 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
703 }
704 }
705 return finalStatePart;
706 }
707#if !defined(XAOD_ANALYSIS)
708#include "AtlasHepMC/GenEvent.h"
709inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
710inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
711
712#endif
713}
714#endif

◆ isGenericMultichargedParticle() [1/3]

template<>
bool MC::isGenericMultichargedParticle ( const DecodedPID & p)
inline

Definition at line 686 of file HepMCHelpers.h.

705{
706 template <class VTX>
707 auto particles_in (const VTX* p) { return p->particles_in(); }
708 template <class VTX>
709 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
710
711 namespace Pythia8
712 {
714 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
715
716 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
717
718 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
719 }
720
721#include "AtlasPID.h"
722
724 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
725
727 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
728
730 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
731
733 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
734
736 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
737
739 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
740
742 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
743
745 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
746
748 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
749
751 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
752
756 template <class T> inline bool isStableOrSimDecayed(const T& p) {
757 const auto vertex = p->end_vertex();
758 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
759 }
760
762 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
763
765 template <class T> inline bool isSpecialNonInteracting(const T& p) {
766 const int apid = std::abs(p->pdg_id());
767 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
768 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
769 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
770 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
771 return false;
772 }
773
775
776 template <class T> T findMother(T thePart) {
777 auto partOriVert = thePart->production_vertex();
778 if (!partOriVert) return nullptr;
779
780 long partPDG = thePart->pdg_id();
781 long MotherPDG(0);
782
783 auto MothOriVert = partOriVert;
784 MothOriVert = nullptr;
785 T theMoth(nullptr);
786
787 size_t itr = 0;
788 do {
789 if (itr != 0) partOriVert = MothOriVert;
790 for ( const auto& p : particles_in(partOriVert) ) {
791 theMoth = p;
792 if (!theMoth) continue;
793 MotherPDG = theMoth->pdg_id();
794 MothOriVert = theMoth->production_vertex();
795 if (MotherPDG == partPDG) break;
796 }
797 itr++;
798 if (itr > 100) {
799 break;
800 }
801 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
802 MothOriVert != partOriVert);
803 return theMoth;
804 }
805
807
808 template <class C, class T> T findMatching(C TruthContainer, T p) {
809 T ptrPart = nullptr;
810 if (!p) return ptrPart;
811 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
812 for (T truthParticle : *TruthContainer) {
813 if (HepMC::is_sim_descendant(p,truthParticle)) {
814 ptrPart = truthParticle;
815 break;
816 }
817 }
818 }
819 else {
820 for (T truthParticle : TruthContainer) {
821 if (HepMC::is_sim_descendant(p,truthParticle)) {
822 ptrPart = truthParticle;
823 break;
824 }
825 }
826 }
827 return ptrPart;
828 }
830
831 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
832 auto prodVtx = thePart->production_vertex();
833 if (!prodVtx) return;
834 for (const auto& theMother: prodVtx->particles_in()) {
835 if (!theMother) continue;
836 allancestors.insert(theMother);
837 findParticleAncestors(theMother, allancestors);
838 }
839 }
840
842
843 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
844 auto endVtx = thePart->end_vertex();
845 if (!endVtx) return;
846 for (const auto& theDaughter: endVtx->particles_out()) {
847 if (!theDaughter) continue;
848 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
849 allstabledescendants.insert(theDaughter);
850 }
851 findParticleStableDescendants(theDaughter, allstabledescendants);
852 }
853 }
854
858
859 template <class T> bool isHardScatteringVertex(T pVert) {
860 if (pVert == nullptr) return false;
861 T pV = pVert;
862 int numOfPartIn(0);
863 int pdg(0);
864
865 do {
866 pVert = pV;
867 auto incoming = pVert->particles_in();
868 numOfPartIn = incoming.size();
869 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
870 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
871
872 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
873
874 if (numOfPartIn == 2) {
875 auto incoming = pVert->particles_in();
876 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
877 }
878 return false;
879}
880
884
885 template <class T, class U>
886 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
887 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
888 auto vtx = p->production_vertex();
889 if (!vtx) return false;
890 bool fromHad = false;
891 for ( const auto& parent : particles_in(vtx) ) {
892 if (!parent) continue;
893 // should this really go into parton-level territory?
894 // probably depends where BSM particles are being decayed
895 fromBSM |= isBSM(parent);
896 if (!isPhysical(parent)) return false;
897 fromTau |= isTau(parent);
898 if (isHadron(parent)&&!isBeam(parent)) {
899 if (!hadron) hadron = parent; // assumes linear hadron parentage
900 return true;
901 }
902 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
903 }
904 return fromHad;
905 }
906
909
910 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
911 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
912 decltype(thePart->end_vertex()) pVert(nullptr);
913 if (EndVert != nullptr) {
914 do {
915 bool samePart = false;
916 pVert = nullptr;
917 auto outgoing = EndVert->particles_out();
918 auto incoming = EndVert->particles_in();
919 for (const auto& itrDaug: outgoing) {
920 if (!itrDaug) continue;
921 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
922 // brem on generator level for tau
923 (outgoing.size() == 1 && incoming.size() == 1 &&
925 itrDaug->pdg_id() == thePart->pdg_id()) {
926 samePart = true;
927 pVert = itrDaug->end_vertex();
928 }
929 }
930 if (samePart) EndVert = pVert;
931 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
932 }
933 return EndVert;
934 }
935
937
938 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
939 if (!theVert) return {};
940 decltype(theVert->particles_out()) finalStatePart;
941 auto outgoing = theVert->particles_out();
942 for (const auto& thePart: outgoing) {
943 if (!thePart) continue;
944 finalStatePart.push_back(thePart);
945 if (isStable(thePart)) continue;
946 V pVert = findSimulatedEndVertex(thePart);
947 if (pVert == theVert) break; // to prevent Sherpa loop
948 if (pVert != nullptr) {
949 auto vecPart = findFinalStateParticles<V>(pVert);
950 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
951 }
952 }
953 return finalStatePart;
954 }
955#if !defined(XAOD_ANALYSIS)
956#include "AtlasHepMC/GenEvent.h"
957inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
958inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
959
960#endif
961}
962#endif

◆ isGenericMultichargedParticle() [2/3]

template<>
bool MC::isGenericMultichargedParticle ( const int & p)
inline

Definition at line 687 of file HepMCHelpers.h.

706{
707 template <class VTX>
708 auto particles_in (const VTX* p) { return p->particles_in(); }
709 template <class VTX>
710 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
711
712 namespace Pythia8
713 {
715 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
716
717 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
718
719 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
720 }
721
722#include "AtlasPID.h"
723
725 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
726
728 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
729
731 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
732
734 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
735
737 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
738
740 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
741
743 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
744
746 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
747
749 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
750
752 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
753
757 template <class T> inline bool isStableOrSimDecayed(const T& p) {
758 const auto vertex = p->end_vertex();
759 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
760 }
761
763 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
764
766 template <class T> inline bool isSpecialNonInteracting(const T& p) {
767 const int apid = std::abs(p->pdg_id());
768 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
769 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
770 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
771 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
772 return false;
773 }
774
776
777 template <class T> T findMother(T thePart) {
778 auto partOriVert = thePart->production_vertex();
779 if (!partOriVert) return nullptr;
780
781 long partPDG = thePart->pdg_id();
782 long MotherPDG(0);
783
784 auto MothOriVert = partOriVert;
785 MothOriVert = nullptr;
786 T theMoth(nullptr);
787
788 size_t itr = 0;
789 do {
790 if (itr != 0) partOriVert = MothOriVert;
791 for ( const auto& p : particles_in(partOriVert) ) {
792 theMoth = p;
793 if (!theMoth) continue;
794 MotherPDG = theMoth->pdg_id();
795 MothOriVert = theMoth->production_vertex();
796 if (MotherPDG == partPDG) break;
797 }
798 itr++;
799 if (itr > 100) {
800 break;
801 }
802 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
803 MothOriVert != partOriVert);
804 return theMoth;
805 }
806
808
809 template <class C, class T> T findMatching(C TruthContainer, T p) {
810 T ptrPart = nullptr;
811 if (!p) return ptrPart;
812 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
813 for (T truthParticle : *TruthContainer) {
814 if (HepMC::is_sim_descendant(p,truthParticle)) {
815 ptrPart = truthParticle;
816 break;
817 }
818 }
819 }
820 else {
821 for (T truthParticle : TruthContainer) {
822 if (HepMC::is_sim_descendant(p,truthParticle)) {
823 ptrPart = truthParticle;
824 break;
825 }
826 }
827 }
828 return ptrPart;
829 }
831
832 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
833 auto prodVtx = thePart->production_vertex();
834 if (!prodVtx) return;
835 for (const auto& theMother: prodVtx->particles_in()) {
836 if (!theMother) continue;
837 allancestors.insert(theMother);
838 findParticleAncestors(theMother, allancestors);
839 }
840 }
841
843
844 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
845 auto endVtx = thePart->end_vertex();
846 if (!endVtx) return;
847 for (const auto& theDaughter: endVtx->particles_out()) {
848 if (!theDaughter) continue;
849 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
850 allstabledescendants.insert(theDaughter);
851 }
852 findParticleStableDescendants(theDaughter, allstabledescendants);
853 }
854 }
855
859
860 template <class T> bool isHardScatteringVertex(T pVert) {
861 if (pVert == nullptr) return false;
862 T pV = pVert;
863 int numOfPartIn(0);
864 int pdg(0);
865
866 do {
867 pVert = pV;
868 auto incoming = pVert->particles_in();
869 numOfPartIn = incoming.size();
870 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
871 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
872
873 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
874
875 if (numOfPartIn == 2) {
876 auto incoming = pVert->particles_in();
877 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
878 }
879 return false;
880}
881
885
886 template <class T, class U>
887 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
888 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
889 auto vtx = p->production_vertex();
890 if (!vtx) return false;
891 bool fromHad = false;
892 for ( const auto& parent : particles_in(vtx) ) {
893 if (!parent) continue;
894 // should this really go into parton-level territory?
895 // probably depends where BSM particles are being decayed
896 fromBSM |= isBSM(parent);
897 if (!isPhysical(parent)) return false;
898 fromTau |= isTau(parent);
899 if (isHadron(parent)&&!isBeam(parent)) {
900 if (!hadron) hadron = parent; // assumes linear hadron parentage
901 return true;
902 }
903 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
904 }
905 return fromHad;
906 }
907
910
911 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
912 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
913 decltype(thePart->end_vertex()) pVert(nullptr);
914 if (EndVert != nullptr) {
915 do {
916 bool samePart = false;
917 pVert = nullptr;
918 auto outgoing = EndVert->particles_out();
919 auto incoming = EndVert->particles_in();
920 for (const auto& itrDaug: outgoing) {
921 if (!itrDaug) continue;
922 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
923 // brem on generator level for tau
924 (outgoing.size() == 1 && incoming.size() == 1 &&
926 itrDaug->pdg_id() == thePart->pdg_id()) {
927 samePart = true;
928 pVert = itrDaug->end_vertex();
929 }
930 }
931 if (samePart) EndVert = pVert;
932 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
933 }
934 return EndVert;
935 }
936
938
939 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
940 if (!theVert) return {};
941 decltype(theVert->particles_out()) finalStatePart;
942 auto outgoing = theVert->particles_out();
943 for (const auto& thePart: outgoing) {
944 if (!thePart) continue;
945 finalStatePart.push_back(thePart);
946 if (isStable(thePart)) continue;
947 V pVert = findSimulatedEndVertex(thePart);
948 if (pVert == theVert) break; // to prevent Sherpa loop
949 if (pVert != nullptr) {
950 auto vecPart = findFinalStateParticles<V>(pVert);
951 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
952 }
953 }
954 return finalStatePart;
955 }
956#if !defined(XAOD_ANALYSIS)
957#include "AtlasHepMC/GenEvent.h"
958inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
959inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
960
961#endif
962}
963#endif

◆ isGenericMultichargedParticle() [3/3]

template<class T>
bool MC::isGenericMultichargedParticle ( const T & p)
inline

In addition, there is a need to identify ”Q-ball” and similar very exotic (multi-charged) particles which may have large, non-integer charge.

These particles are assigned the ad-hoc numbering +/-100XXXY0, where the charge is XXX.Y. or +/-200XXYY0, where the charge is XX/YY. The case of +/-200XXYY0 is legacy, see https://gitlab.cern.ch/atlas/athena/-/merge_requests/25862 Note that no other quantum numbers besides the charge are considered for these generic multi-charged particles (e.g. isSUSY() is false for them). Such a model was used in previous Run-1 (1301.5272,1504.04188) and Run-2 (1812.03673,2303.13613) ATLAS searches.

Definition at line 685 of file HepMCHelpers.h.

704{
705 template <class VTX>
706 auto particles_in (const VTX* p) { return p->particles_in(); }
707 template <class VTX>
708 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
709
710 namespace Pythia8
711 {
713 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
714
715 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
716
717 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
718 }
719
720#include "AtlasPID.h"
721
723 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
724
726 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
727
729 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
730
732 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
733
735 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
736
738 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
739
741 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
742
744 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
745
747 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
748
750 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
751
755 template <class T> inline bool isStableOrSimDecayed(const T& p) {
756 const auto vertex = p->end_vertex();
757 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
758 }
759
761 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
762
764 template <class T> inline bool isSpecialNonInteracting(const T& p) {
765 const int apid = std::abs(p->pdg_id());
766 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
767 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
768 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
769 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
770 return false;
771 }
772
774
775 template <class T> T findMother(T thePart) {
776 auto partOriVert = thePart->production_vertex();
777 if (!partOriVert) return nullptr;
778
779 long partPDG = thePart->pdg_id();
780 long MotherPDG(0);
781
782 auto MothOriVert = partOriVert;
783 MothOriVert = nullptr;
784 T theMoth(nullptr);
785
786 size_t itr = 0;
787 do {
788 if (itr != 0) partOriVert = MothOriVert;
789 for ( const auto& p : particles_in(partOriVert) ) {
790 theMoth = p;
791 if (!theMoth) continue;
792 MotherPDG = theMoth->pdg_id();
793 MothOriVert = theMoth->production_vertex();
794 if (MotherPDG == partPDG) break;
795 }
796 itr++;
797 if (itr > 100) {
798 break;
799 }
800 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
801 MothOriVert != partOriVert);
802 return theMoth;
803 }
804
806
807 template <class C, class T> T findMatching(C TruthContainer, T p) {
808 T ptrPart = nullptr;
809 if (!p) return ptrPart;
810 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
811 for (T truthParticle : *TruthContainer) {
812 if (HepMC::is_sim_descendant(p,truthParticle)) {
813 ptrPart = truthParticle;
814 break;
815 }
816 }
817 }
818 else {
819 for (T truthParticle : TruthContainer) {
820 if (HepMC::is_sim_descendant(p,truthParticle)) {
821 ptrPart = truthParticle;
822 break;
823 }
824 }
825 }
826 return ptrPart;
827 }
829
830 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
831 auto prodVtx = thePart->production_vertex();
832 if (!prodVtx) return;
833 for (const auto& theMother: prodVtx->particles_in()) {
834 if (!theMother) continue;
835 allancestors.insert(theMother);
836 findParticleAncestors(theMother, allancestors);
837 }
838 }
839
841
842 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
843 auto endVtx = thePart->end_vertex();
844 if (!endVtx) return;
845 for (const auto& theDaughter: endVtx->particles_out()) {
846 if (!theDaughter) continue;
847 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
848 allstabledescendants.insert(theDaughter);
849 }
850 findParticleStableDescendants(theDaughter, allstabledescendants);
851 }
852 }
853
857
858 template <class T> bool isHardScatteringVertex(T pVert) {
859 if (pVert == nullptr) return false;
860 T pV = pVert;
861 int numOfPartIn(0);
862 int pdg(0);
863
864 do {
865 pVert = pV;
866 auto incoming = pVert->particles_in();
867 numOfPartIn = incoming.size();
868 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
869 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
870
871 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
872
873 if (numOfPartIn == 2) {
874 auto incoming = pVert->particles_in();
875 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
876 }
877 return false;
878}
879
883
884 template <class T, class U>
885 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
886 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
887 auto vtx = p->production_vertex();
888 if (!vtx) return false;
889 bool fromHad = false;
890 for ( const auto& parent : particles_in(vtx) ) {
891 if (!parent) continue;
892 // should this really go into parton-level territory?
893 // probably depends where BSM particles are being decayed
894 fromBSM |= isBSM(parent);
895 if (!isPhysical(parent)) return false;
896 fromTau |= isTau(parent);
897 if (isHadron(parent)&&!isBeam(parent)) {
898 if (!hadron) hadron = parent; // assumes linear hadron parentage
899 return true;
900 }
901 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
902 }
903 return fromHad;
904 }
905
908
909 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
910 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
911 decltype(thePart->end_vertex()) pVert(nullptr);
912 if (EndVert != nullptr) {
913 do {
914 bool samePart = false;
915 pVert = nullptr;
916 auto outgoing = EndVert->particles_out();
917 auto incoming = EndVert->particles_in();
918 for (const auto& itrDaug: outgoing) {
919 if (!itrDaug) continue;
920 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
921 // brem on generator level for tau
922 (outgoing.size() == 1 && incoming.size() == 1 &&
924 itrDaug->pdg_id() == thePart->pdg_id()) {
925 samePart = true;
926 pVert = itrDaug->end_vertex();
927 }
928 }
929 if (samePart) EndVert = pVert;
930 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
931 }
932 return EndVert;
933 }
934
936
937 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
938 if (!theVert) return {};
939 decltype(theVert->particles_out()) finalStatePart;
940 auto outgoing = theVert->particles_out();
941 for (const auto& thePart: outgoing) {
942 if (!thePart) continue;
943 finalStatePart.push_back(thePart);
944 if (isStable(thePart)) continue;
945 V pVert = findSimulatedEndVertex(thePart);
946 if (pVert == theVert) break; // to prevent Sherpa loop
947 if (pVert != nullptr) {
948 auto vecPart = findFinalStateParticles<V>(pVert);
949 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
950 }
951 }
952 return finalStatePart;
953 }
954#if !defined(XAOD_ANALYSIS)
955#include "AtlasHepMC/GenEvent.h"
956inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
957inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
958
959#endif
960}
961#endif

◆ isGenSpecific() [1/2]

template<>
bool MC::isGenSpecific ( const int & p)
inline

Definition at line 427 of file HepMCHelpers.h.

446{
447 template <class VTX>
448 auto particles_in (const VTX* p) { return p->particles_in(); }
449 template <class VTX>
450 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
451
452 namespace Pythia8
453 {
455 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
456
457 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
458
459 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
460 }
461
462#include "AtlasPID.h"
463
465 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
466
468 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
469
471 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
472
474 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
475
477 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
478
480 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
481
483 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
484
486 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
487
489 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
490
492 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
493
497 template <class T> inline bool isStableOrSimDecayed(const T& p) {
498 const auto vertex = p->end_vertex();
499 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
500 }
501
503 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
504
506 template <class T> inline bool isSpecialNonInteracting(const T& p) {
507 const int apid = std::abs(p->pdg_id());
508 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
509 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
510 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
511 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
512 return false;
513 }
514
516
517 template <class T> T findMother(T thePart) {
518 auto partOriVert = thePart->production_vertex();
519 if (!partOriVert) return nullptr;
520
521 long partPDG = thePart->pdg_id();
522 long MotherPDG(0);
523
524 auto MothOriVert = partOriVert;
525 MothOriVert = nullptr;
526 T theMoth(nullptr);
527
528 size_t itr = 0;
529 do {
530 if (itr != 0) partOriVert = MothOriVert;
531 for ( const auto& p : particles_in(partOriVert) ) {
532 theMoth = p;
533 if (!theMoth) continue;
534 MotherPDG = theMoth->pdg_id();
535 MothOriVert = theMoth->production_vertex();
536 if (MotherPDG == partPDG) break;
537 }
538 itr++;
539 if (itr > 100) {
540 break;
541 }
542 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
543 MothOriVert != partOriVert);
544 return theMoth;
545 }
546
548
549 template <class C, class T> T findMatching(C TruthContainer, T p) {
550 T ptrPart = nullptr;
551 if (!p) return ptrPart;
552 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
553 for (T truthParticle : *TruthContainer) {
554 if (HepMC::is_sim_descendant(p,truthParticle)) {
555 ptrPart = truthParticle;
556 break;
557 }
558 }
559 }
560 else {
561 for (T truthParticle : TruthContainer) {
562 if (HepMC::is_sim_descendant(p,truthParticle)) {
563 ptrPart = truthParticle;
564 break;
565 }
566 }
567 }
568 return ptrPart;
569 }
571
572 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
573 auto prodVtx = thePart->production_vertex();
574 if (!prodVtx) return;
575 for (const auto& theMother: prodVtx->particles_in()) {
576 if (!theMother) continue;
577 allancestors.insert(theMother);
578 findParticleAncestors(theMother, allancestors);
579 }
580 }
581
583
584 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
585 auto endVtx = thePart->end_vertex();
586 if (!endVtx) return;
587 for (const auto& theDaughter: endVtx->particles_out()) {
588 if (!theDaughter) continue;
589 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
590 allstabledescendants.insert(theDaughter);
591 }
592 findParticleStableDescendants(theDaughter, allstabledescendants);
593 }
594 }
595
599
600 template <class T> bool isHardScatteringVertex(T pVert) {
601 if (pVert == nullptr) return false;
602 T pV = pVert;
603 int numOfPartIn(0);
604 int pdg(0);
605
606 do {
607 pVert = pV;
608 auto incoming = pVert->particles_in();
609 numOfPartIn = incoming.size();
610 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
611 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
612
613 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
614
615 if (numOfPartIn == 2) {
616 auto incoming = pVert->particles_in();
617 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
618 }
619 return false;
620}
621
625
626 template <class T, class U>
627 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
628 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
629 auto vtx = p->production_vertex();
630 if (!vtx) return false;
631 bool fromHad = false;
632 for ( const auto& parent : particles_in(vtx) ) {
633 if (!parent) continue;
634 // should this really go into parton-level territory?
635 // probably depends where BSM particles are being decayed
636 fromBSM |= isBSM(parent);
637 if (!isPhysical(parent)) return false;
638 fromTau |= isTau(parent);
639 if (isHadron(parent)&&!isBeam(parent)) {
640 if (!hadron) hadron = parent; // assumes linear hadron parentage
641 return true;
642 }
643 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
644 }
645 return fromHad;
646 }
647
650
651 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
652 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
653 decltype(thePart->end_vertex()) pVert(nullptr);
654 if (EndVert != nullptr) {
655 do {
656 bool samePart = false;
657 pVert = nullptr;
658 auto outgoing = EndVert->particles_out();
659 auto incoming = EndVert->particles_in();
660 for (const auto& itrDaug: outgoing) {
661 if (!itrDaug) continue;
662 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
663 // brem on generator level for tau
664 (outgoing.size() == 1 && incoming.size() == 1 &&
666 itrDaug->pdg_id() == thePart->pdg_id()) {
667 samePart = true;
668 pVert = itrDaug->end_vertex();
669 }
670 }
671 if (samePart) EndVert = pVert;
672 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
673 }
674 return EndVert;
675 }
676
678
679 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
680 if (!theVert) return {};
681 decltype(theVert->particles_out()) finalStatePart;
682 auto outgoing = theVert->particles_out();
683 for (const auto& thePart: outgoing) {
684 if (!thePart) continue;
685 finalStatePart.push_back(thePart);
686 if (isStable(thePart)) continue;
687 V pVert = findSimulatedEndVertex(thePart);
688 if (pVert == theVert) break; // to prevent Sherpa loop
689 if (pVert != nullptr) {
690 auto vecPart = findFinalStateParticles<V>(pVert);
691 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
692 }
693 }
694 return finalStatePart;
695 }
696#if !defined(XAOD_ANALYSIS)
697#include "AtlasHepMC/GenEvent.h"
698inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
699inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
700
701#endif
702}
703#endif

◆ isGenSpecific() [2/2]

template<class T>
bool MC::isGenSpecific ( const T & p)
inline

Main Table for MC internal use 81–100,901–930,998-999,1901–1930,2901–2930, and 3901–3930.

Definition at line 426 of file HepMCHelpers.h.

445{
446 template <class VTX>
447 auto particles_in (const VTX* p) { return p->particles_in(); }
448 template <class VTX>
449 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
450
451 namespace Pythia8
452 {
454 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
455
456 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
457
458 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
459 }
460
461#include "AtlasPID.h"
462
464 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
465
467 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
468
470 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
471
473 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
474
476 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
477
479 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
480
482 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
483
485 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
486
488 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
489
491 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
492
496 template <class T> inline bool isStableOrSimDecayed(const T& p) {
497 const auto vertex = p->end_vertex();
498 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
499 }
500
502 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
503
505 template <class T> inline bool isSpecialNonInteracting(const T& p) {
506 const int apid = std::abs(p->pdg_id());
507 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
508 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
509 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
510 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
511 return false;
512 }
513
515
516 template <class T> T findMother(T thePart) {
517 auto partOriVert = thePart->production_vertex();
518 if (!partOriVert) return nullptr;
519
520 long partPDG = thePart->pdg_id();
521 long MotherPDG(0);
522
523 auto MothOriVert = partOriVert;
524 MothOriVert = nullptr;
525 T theMoth(nullptr);
526
527 size_t itr = 0;
528 do {
529 if (itr != 0) partOriVert = MothOriVert;
530 for ( const auto& p : particles_in(partOriVert) ) {
531 theMoth = p;
532 if (!theMoth) continue;
533 MotherPDG = theMoth->pdg_id();
534 MothOriVert = theMoth->production_vertex();
535 if (MotherPDG == partPDG) break;
536 }
537 itr++;
538 if (itr > 100) {
539 break;
540 }
541 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
542 MothOriVert != partOriVert);
543 return theMoth;
544 }
545
547
548 template <class C, class T> T findMatching(C TruthContainer, T p) {
549 T ptrPart = nullptr;
550 if (!p) return ptrPart;
551 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
552 for (T truthParticle : *TruthContainer) {
553 if (HepMC::is_sim_descendant(p,truthParticle)) {
554 ptrPart = truthParticle;
555 break;
556 }
557 }
558 }
559 else {
560 for (T truthParticle : TruthContainer) {
561 if (HepMC::is_sim_descendant(p,truthParticle)) {
562 ptrPart = truthParticle;
563 break;
564 }
565 }
566 }
567 return ptrPart;
568 }
570
571 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
572 auto prodVtx = thePart->production_vertex();
573 if (!prodVtx) return;
574 for (const auto& theMother: prodVtx->particles_in()) {
575 if (!theMother) continue;
576 allancestors.insert(theMother);
577 findParticleAncestors(theMother, allancestors);
578 }
579 }
580
582
583 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
584 auto endVtx = thePart->end_vertex();
585 if (!endVtx) return;
586 for (const auto& theDaughter: endVtx->particles_out()) {
587 if (!theDaughter) continue;
588 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
589 allstabledescendants.insert(theDaughter);
590 }
591 findParticleStableDescendants(theDaughter, allstabledescendants);
592 }
593 }
594
598
599 template <class T> bool isHardScatteringVertex(T pVert) {
600 if (pVert == nullptr) return false;
601 T pV = pVert;
602 int numOfPartIn(0);
603 int pdg(0);
604
605 do {
606 pVert = pV;
607 auto incoming = pVert->particles_in();
608 numOfPartIn = incoming.size();
609 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
610 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
611
612 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
613
614 if (numOfPartIn == 2) {
615 auto incoming = pVert->particles_in();
616 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
617 }
618 return false;
619}
620
624
625 template <class T, class U>
626 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
627 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
628 auto vtx = p->production_vertex();
629 if (!vtx) return false;
630 bool fromHad = false;
631 for ( const auto& parent : particles_in(vtx) ) {
632 if (!parent) continue;
633 // should this really go into parton-level territory?
634 // probably depends where BSM particles are being decayed
635 fromBSM |= isBSM(parent);
636 if (!isPhysical(parent)) return false;
637 fromTau |= isTau(parent);
638 if (isHadron(parent)&&!isBeam(parent)) {
639 if (!hadron) hadron = parent; // assumes linear hadron parentage
640 return true;
641 }
642 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
643 }
644 return fromHad;
645 }
646
649
650 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
651 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
652 decltype(thePart->end_vertex()) pVert(nullptr);
653 if (EndVert != nullptr) {
654 do {
655 bool samePart = false;
656 pVert = nullptr;
657 auto outgoing = EndVert->particles_out();
658 auto incoming = EndVert->particles_in();
659 for (const auto& itrDaug: outgoing) {
660 if (!itrDaug) continue;
661 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
662 // brem on generator level for tau
663 (outgoing.size() == 1 && incoming.size() == 1 &&
665 itrDaug->pdg_id() == thePart->pdg_id()) {
666 samePart = true;
667 pVert = itrDaug->end_vertex();
668 }
669 }
670 if (samePart) EndVert = pVert;
671 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
672 }
673 return EndVert;
674 }
675
677
678 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
679 if (!theVert) return {};
680 decltype(theVert->particles_out()) finalStatePart;
681 auto outgoing = theVert->particles_out();
682 for (const auto& thePart: outgoing) {
683 if (!thePart) continue;
684 finalStatePart.push_back(thePart);
685 if (isStable(thePart)) continue;
686 V pVert = findSimulatedEndVertex(thePart);
687 if (pVert == theVert) break; // to prevent Sherpa loop
688 if (pVert != nullptr) {
689 auto vecPart = findFinalStateParticles<V>(pVert);
690 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
691 }
692 }
693 return finalStatePart;
694 }
695#if !defined(XAOD_ANALYSIS)
696#include "AtlasHepMC/GenEvent.h"
697inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
698inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
699
700#endif
701}
702#endif

◆ isGenStable()

template<class T>
bool MC::isGenStable ( const T & p)
inline

Determine if the particle is stable at the generator (not det-sim) level,.

Definition at line 60 of file HepMCHelpers.h.

◆ isGlueball() [1/3]

template<>
bool MC::isGlueball ( const DecodedPID & p)
inline

Definition at line 443 of file HepMCHelpers.h.

462{
463 template <class VTX>
464 auto particles_in (const VTX* p) { return p->particles_in(); }
465 template <class VTX>
466 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
467
468 namespace Pythia8
469 {
471 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
472
473 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
474
475 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
476 }
477
478#include "AtlasPID.h"
479
481 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
482
484 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
485
487 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
488
490 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
491
493 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
494
496 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
497
499 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
500
502 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
503
505 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
506
508 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
509
513 template <class T> inline bool isStableOrSimDecayed(const T& p) {
514 const auto vertex = p->end_vertex();
515 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
516 }
517
519 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
520
522 template <class T> inline bool isSpecialNonInteracting(const T& p) {
523 const int apid = std::abs(p->pdg_id());
524 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
525 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
526 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
527 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
528 return false;
529 }
530
532
533 template <class T> T findMother(T thePart) {
534 auto partOriVert = thePart->production_vertex();
535 if (!partOriVert) return nullptr;
536
537 long partPDG = thePart->pdg_id();
538 long MotherPDG(0);
539
540 auto MothOriVert = partOriVert;
541 MothOriVert = nullptr;
542 T theMoth(nullptr);
543
544 size_t itr = 0;
545 do {
546 if (itr != 0) partOriVert = MothOriVert;
547 for ( const auto& p : particles_in(partOriVert) ) {
548 theMoth = p;
549 if (!theMoth) continue;
550 MotherPDG = theMoth->pdg_id();
551 MothOriVert = theMoth->production_vertex();
552 if (MotherPDG == partPDG) break;
553 }
554 itr++;
555 if (itr > 100) {
556 break;
557 }
558 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
559 MothOriVert != partOriVert);
560 return theMoth;
561 }
562
564
565 template <class C, class T> T findMatching(C TruthContainer, T p) {
566 T ptrPart = nullptr;
567 if (!p) return ptrPart;
568 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
569 for (T truthParticle : *TruthContainer) {
570 if (HepMC::is_sim_descendant(p,truthParticle)) {
571 ptrPart = truthParticle;
572 break;
573 }
574 }
575 }
576 else {
577 for (T truthParticle : TruthContainer) {
578 if (HepMC::is_sim_descendant(p,truthParticle)) {
579 ptrPart = truthParticle;
580 break;
581 }
582 }
583 }
584 return ptrPart;
585 }
587
588 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
589 auto prodVtx = thePart->production_vertex();
590 if (!prodVtx) return;
591 for (const auto& theMother: prodVtx->particles_in()) {
592 if (!theMother) continue;
593 allancestors.insert(theMother);
594 findParticleAncestors(theMother, allancestors);
595 }
596 }
597
599
600 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
601 auto endVtx = thePart->end_vertex();
602 if (!endVtx) return;
603 for (const auto& theDaughter: endVtx->particles_out()) {
604 if (!theDaughter) continue;
605 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
606 allstabledescendants.insert(theDaughter);
607 }
608 findParticleStableDescendants(theDaughter, allstabledescendants);
609 }
610 }
611
615
616 template <class T> bool isHardScatteringVertex(T pVert) {
617 if (pVert == nullptr) return false;
618 T pV = pVert;
619 int numOfPartIn(0);
620 int pdg(0);
621
622 do {
623 pVert = pV;
624 auto incoming = pVert->particles_in();
625 numOfPartIn = incoming.size();
626 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
627 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
628
629 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
630
631 if (numOfPartIn == 2) {
632 auto incoming = pVert->particles_in();
633 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
634 }
635 return false;
636}
637
641
642 template <class T, class U>
643 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
644 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
645 auto vtx = p->production_vertex();
646 if (!vtx) return false;
647 bool fromHad = false;
648 for ( const auto& parent : particles_in(vtx) ) {
649 if (!parent) continue;
650 // should this really go into parton-level territory?
651 // probably depends where BSM particles are being decayed
652 fromBSM |= isBSM(parent);
653 if (!isPhysical(parent)) return false;
654 fromTau |= isTau(parent);
655 if (isHadron(parent)&&!isBeam(parent)) {
656 if (!hadron) hadron = parent; // assumes linear hadron parentage
657 return true;
658 }
659 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
660 }
661 return fromHad;
662 }
663
666
667 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
668 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
669 decltype(thePart->end_vertex()) pVert(nullptr);
670 if (EndVert != nullptr) {
671 do {
672 bool samePart = false;
673 pVert = nullptr;
674 auto outgoing = EndVert->particles_out();
675 auto incoming = EndVert->particles_in();
676 for (const auto& itrDaug: outgoing) {
677 if (!itrDaug) continue;
678 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
679 // brem on generator level for tau
680 (outgoing.size() == 1 && incoming.size() == 1 &&
682 itrDaug->pdg_id() == thePart->pdg_id()) {
683 samePart = true;
684 pVert = itrDaug->end_vertex();
685 }
686 }
687 if (samePart) EndVert = pVert;
688 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
689 }
690 return EndVert;
691 }
692
694
695 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
696 if (!theVert) return {};
697 decltype(theVert->particles_out()) finalStatePart;
698 auto outgoing = theVert->particles_out();
699 for (const auto& thePart: outgoing) {
700 if (!thePart) continue;
701 finalStatePart.push_back(thePart);
702 if (isStable(thePart)) continue;
703 V pVert = findSimulatedEndVertex(thePart);
704 if (pVert == theVert) break; // to prevent Sherpa loop
705 if (pVert != nullptr) {
706 auto vecPart = findFinalStateParticles<V>(pVert);
707 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
708 }
709 }
710 return finalStatePart;
711 }
712#if !defined(XAOD_ANALYSIS)
713#include "AtlasHepMC/GenEvent.h"
714inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
715inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
716
717#endif
718}
719#endif

◆ isGlueball() [2/3]

template<>
bool MC::isGlueball ( const int & p)
inline

Definition at line 449 of file HepMCHelpers.h.

468{
469 template <class VTX>
470 auto particles_in (const VTX* p) { return p->particles_in(); }
471 template <class VTX>
472 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
473
474 namespace Pythia8
475 {
477 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
478
479 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
480
481 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
482 }
483
484#include "AtlasPID.h"
485
487 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
488
490 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
491
493 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
494
496 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
497
499 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
500
502 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
503
505 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
506
508 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
509
511 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
512
514 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
515
519 template <class T> inline bool isStableOrSimDecayed(const T& p) {
520 const auto vertex = p->end_vertex();
521 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
522 }
523
525 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
526
528 template <class T> inline bool isSpecialNonInteracting(const T& p) {
529 const int apid = std::abs(p->pdg_id());
530 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
531 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
532 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
533 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
534 return false;
535 }
536
538
539 template <class T> T findMother(T thePart) {
540 auto partOriVert = thePart->production_vertex();
541 if (!partOriVert) return nullptr;
542
543 long partPDG = thePart->pdg_id();
544 long MotherPDG(0);
545
546 auto MothOriVert = partOriVert;
547 MothOriVert = nullptr;
548 T theMoth(nullptr);
549
550 size_t itr = 0;
551 do {
552 if (itr != 0) partOriVert = MothOriVert;
553 for ( const auto& p : particles_in(partOriVert) ) {
554 theMoth = p;
555 if (!theMoth) continue;
556 MotherPDG = theMoth->pdg_id();
557 MothOriVert = theMoth->production_vertex();
558 if (MotherPDG == partPDG) break;
559 }
560 itr++;
561 if (itr > 100) {
562 break;
563 }
564 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
565 MothOriVert != partOriVert);
566 return theMoth;
567 }
568
570
571 template <class C, class T> T findMatching(C TruthContainer, T p) {
572 T ptrPart = nullptr;
573 if (!p) return ptrPart;
574 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
575 for (T truthParticle : *TruthContainer) {
576 if (HepMC::is_sim_descendant(p,truthParticle)) {
577 ptrPart = truthParticle;
578 break;
579 }
580 }
581 }
582 else {
583 for (T truthParticle : TruthContainer) {
584 if (HepMC::is_sim_descendant(p,truthParticle)) {
585 ptrPart = truthParticle;
586 break;
587 }
588 }
589 }
590 return ptrPart;
591 }
593
594 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
595 auto prodVtx = thePart->production_vertex();
596 if (!prodVtx) return;
597 for (const auto& theMother: prodVtx->particles_in()) {
598 if (!theMother) continue;
599 allancestors.insert(theMother);
600 findParticleAncestors(theMother, allancestors);
601 }
602 }
603
605
606 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
607 auto endVtx = thePart->end_vertex();
608 if (!endVtx) return;
609 for (const auto& theDaughter: endVtx->particles_out()) {
610 if (!theDaughter) continue;
611 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
612 allstabledescendants.insert(theDaughter);
613 }
614 findParticleStableDescendants(theDaughter, allstabledescendants);
615 }
616 }
617
621
622 template <class T> bool isHardScatteringVertex(T pVert) {
623 if (pVert == nullptr) return false;
624 T pV = pVert;
625 int numOfPartIn(0);
626 int pdg(0);
627
628 do {
629 pVert = pV;
630 auto incoming = pVert->particles_in();
631 numOfPartIn = incoming.size();
632 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
633 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
634
635 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
636
637 if (numOfPartIn == 2) {
638 auto incoming = pVert->particles_in();
639 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
640 }
641 return false;
642}
643
647
648 template <class T, class U>
649 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
650 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
651 auto vtx = p->production_vertex();
652 if (!vtx) return false;
653 bool fromHad = false;
654 for ( const auto& parent : particles_in(vtx) ) {
655 if (!parent) continue;
656 // should this really go into parton-level territory?
657 // probably depends where BSM particles are being decayed
658 fromBSM |= isBSM(parent);
659 if (!isPhysical(parent)) return false;
660 fromTau |= isTau(parent);
661 if (isHadron(parent)&&!isBeam(parent)) {
662 if (!hadron) hadron = parent; // assumes linear hadron parentage
663 return true;
664 }
665 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
666 }
667 return fromHad;
668 }
669
672
673 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
674 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
675 decltype(thePart->end_vertex()) pVert(nullptr);
676 if (EndVert != nullptr) {
677 do {
678 bool samePart = false;
679 pVert = nullptr;
680 auto outgoing = EndVert->particles_out();
681 auto incoming = EndVert->particles_in();
682 for (const auto& itrDaug: outgoing) {
683 if (!itrDaug) continue;
684 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
685 // brem on generator level for tau
686 (outgoing.size() == 1 && incoming.size() == 1 &&
688 itrDaug->pdg_id() == thePart->pdg_id()) {
689 samePart = true;
690 pVert = itrDaug->end_vertex();
691 }
692 }
693 if (samePart) EndVert = pVert;
694 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
695 }
696 return EndVert;
697 }
698
700
701 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
702 if (!theVert) return {};
703 decltype(theVert->particles_out()) finalStatePart;
704 auto outgoing = theVert->particles_out();
705 for (const auto& thePart: outgoing) {
706 if (!thePart) continue;
707 finalStatePart.push_back(thePart);
708 if (isStable(thePart)) continue;
709 V pVert = findSimulatedEndVertex(thePart);
710 if (pVert == theVert) break; // to prevent Sherpa loop
711 if (pVert != nullptr) {
712 auto vecPart = findFinalStateParticles<V>(pVert);
713 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
714 }
715 }
716 return finalStatePart;
717 }
718#if !defined(XAOD_ANALYSIS)
719#include "AtlasHepMC/GenEvent.h"
720inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
721inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
722
723#endif
724}
725#endif

◆ isGlueball() [3/3]

template<class T>
bool MC::isGlueball ( const T & p)
inline

APID: Definition of Glueballs: SM glueballs 99X (X=1,5), 999Y (Y=3,7).

Definition at line 442 of file HepMCHelpers.h.

461{
462 template <class VTX>
463 auto particles_in (const VTX* p) { return p->particles_in(); }
464 template <class VTX>
465 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
466
467 namespace Pythia8
468 {
470 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
471
472 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
473
474 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
475 }
476
477#include "AtlasPID.h"
478
480 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
481
483 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
484
486 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
487
489 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
490
492 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
493
495 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
496
498 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
499
501 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
502
504 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
505
507 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
508
512 template <class T> inline bool isStableOrSimDecayed(const T& p) {
513 const auto vertex = p->end_vertex();
514 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
515 }
516
518 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
519
521 template <class T> inline bool isSpecialNonInteracting(const T& p) {
522 const int apid = std::abs(p->pdg_id());
523 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
524 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
525 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
526 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
527 return false;
528 }
529
531
532 template <class T> T findMother(T thePart) {
533 auto partOriVert = thePart->production_vertex();
534 if (!partOriVert) return nullptr;
535
536 long partPDG = thePart->pdg_id();
537 long MotherPDG(0);
538
539 auto MothOriVert = partOriVert;
540 MothOriVert = nullptr;
541 T theMoth(nullptr);
542
543 size_t itr = 0;
544 do {
545 if (itr != 0) partOriVert = MothOriVert;
546 for ( const auto& p : particles_in(partOriVert) ) {
547 theMoth = p;
548 if (!theMoth) continue;
549 MotherPDG = theMoth->pdg_id();
550 MothOriVert = theMoth->production_vertex();
551 if (MotherPDG == partPDG) break;
552 }
553 itr++;
554 if (itr > 100) {
555 break;
556 }
557 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
558 MothOriVert != partOriVert);
559 return theMoth;
560 }
561
563
564 template <class C, class T> T findMatching(C TruthContainer, T p) {
565 T ptrPart = nullptr;
566 if (!p) return ptrPart;
567 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
568 for (T truthParticle : *TruthContainer) {
569 if (HepMC::is_sim_descendant(p,truthParticle)) {
570 ptrPart = truthParticle;
571 break;
572 }
573 }
574 }
575 else {
576 for (T truthParticle : TruthContainer) {
577 if (HepMC::is_sim_descendant(p,truthParticle)) {
578 ptrPart = truthParticle;
579 break;
580 }
581 }
582 }
583 return ptrPart;
584 }
586
587 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
588 auto prodVtx = thePart->production_vertex();
589 if (!prodVtx) return;
590 for (const auto& theMother: prodVtx->particles_in()) {
591 if (!theMother) continue;
592 allancestors.insert(theMother);
593 findParticleAncestors(theMother, allancestors);
594 }
595 }
596
598
599 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
600 auto endVtx = thePart->end_vertex();
601 if (!endVtx) return;
602 for (const auto& theDaughter: endVtx->particles_out()) {
603 if (!theDaughter) continue;
604 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
605 allstabledescendants.insert(theDaughter);
606 }
607 findParticleStableDescendants(theDaughter, allstabledescendants);
608 }
609 }
610
614
615 template <class T> bool isHardScatteringVertex(T pVert) {
616 if (pVert == nullptr) return false;
617 T pV = pVert;
618 int numOfPartIn(0);
619 int pdg(0);
620
621 do {
622 pVert = pV;
623 auto incoming = pVert->particles_in();
624 numOfPartIn = incoming.size();
625 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
626 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
627
628 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
629
630 if (numOfPartIn == 2) {
631 auto incoming = pVert->particles_in();
632 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
633 }
634 return false;
635}
636
640
641 template <class T, class U>
642 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
643 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
644 auto vtx = p->production_vertex();
645 if (!vtx) return false;
646 bool fromHad = false;
647 for ( const auto& parent : particles_in(vtx) ) {
648 if (!parent) continue;
649 // should this really go into parton-level territory?
650 // probably depends where BSM particles are being decayed
651 fromBSM |= isBSM(parent);
652 if (!isPhysical(parent)) return false;
653 fromTau |= isTau(parent);
654 if (isHadron(parent)&&!isBeam(parent)) {
655 if (!hadron) hadron = parent; // assumes linear hadron parentage
656 return true;
657 }
658 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
659 }
660 return fromHad;
661 }
662
665
666 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
667 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
668 decltype(thePart->end_vertex()) pVert(nullptr);
669 if (EndVert != nullptr) {
670 do {
671 bool samePart = false;
672 pVert = nullptr;
673 auto outgoing = EndVert->particles_out();
674 auto incoming = EndVert->particles_in();
675 for (const auto& itrDaug: outgoing) {
676 if (!itrDaug) continue;
677 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
678 // brem on generator level for tau
679 (outgoing.size() == 1 && incoming.size() == 1 &&
681 itrDaug->pdg_id() == thePart->pdg_id()) {
682 samePart = true;
683 pVert = itrDaug->end_vertex();
684 }
685 }
686 if (samePart) EndVert = pVert;
687 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
688 }
689 return EndVert;
690 }
691
693
694 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
695 if (!theVert) return {};
696 decltype(theVert->particles_out()) finalStatePart;
697 auto outgoing = theVert->particles_out();
698 for (const auto& thePart: outgoing) {
699 if (!thePart) continue;
700 finalStatePart.push_back(thePart);
701 if (isStable(thePart)) continue;
702 V pVert = findSimulatedEndVertex(thePart);
703 if (pVert == theVert) break; // to prevent Sherpa loop
704 if (pVert != nullptr) {
705 auto vecPart = findFinalStateParticles<V>(pVert);
706 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
707 }
708 }
709 return finalStatePart;
710 }
711#if !defined(XAOD_ANALYSIS)
712#include "AtlasHepMC/GenEvent.h"
713inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
714inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
715
716#endif
717}
718#endif

◆ isGluon() [1/2]

template<>
bool MC::isGluon ( const int & p)
inline

Definition at line 375 of file HepMCHelpers.h.

394{
395 template <class VTX>
396 auto particles_in (const VTX* p) { return p->particles_in(); }
397 template <class VTX>
398 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
399
400 namespace Pythia8
401 {
403 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
404
405 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
406
407 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
408 }
409
410#include "AtlasPID.h"
411
413 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
414
416 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
417
419 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
420
422 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
423
425 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
426
428 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
429
431 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
432
434 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
435
437 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
438
440 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
441
445 template <class T> inline bool isStableOrSimDecayed(const T& p) {
446 const auto vertex = p->end_vertex();
447 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
448 }
449
451 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
452
454 template <class T> inline bool isSpecialNonInteracting(const T& p) {
455 const int apid = std::abs(p->pdg_id());
456 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
457 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
458 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
459 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
460 return false;
461 }
462
464
465 template <class T> T findMother(T thePart) {
466 auto partOriVert = thePart->production_vertex();
467 if (!partOriVert) return nullptr;
468
469 long partPDG = thePart->pdg_id();
470 long MotherPDG(0);
471
472 auto MothOriVert = partOriVert;
473 MothOriVert = nullptr;
474 T theMoth(nullptr);
475
476 size_t itr = 0;
477 do {
478 if (itr != 0) partOriVert = MothOriVert;
479 for ( const auto& p : particles_in(partOriVert) ) {
480 theMoth = p;
481 if (!theMoth) continue;
482 MotherPDG = theMoth->pdg_id();
483 MothOriVert = theMoth->production_vertex();
484 if (MotherPDG == partPDG) break;
485 }
486 itr++;
487 if (itr > 100) {
488 break;
489 }
490 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
491 MothOriVert != partOriVert);
492 return theMoth;
493 }
494
496
497 template <class C, class T> T findMatching(C TruthContainer, T p) {
498 T ptrPart = nullptr;
499 if (!p) return ptrPart;
500 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
501 for (T truthParticle : *TruthContainer) {
502 if (HepMC::is_sim_descendant(p,truthParticle)) {
503 ptrPart = truthParticle;
504 break;
505 }
506 }
507 }
508 else {
509 for (T truthParticle : TruthContainer) {
510 if (HepMC::is_sim_descendant(p,truthParticle)) {
511 ptrPart = truthParticle;
512 break;
513 }
514 }
515 }
516 return ptrPart;
517 }
519
520 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
521 auto prodVtx = thePart->production_vertex();
522 if (!prodVtx) return;
523 for (const auto& theMother: prodVtx->particles_in()) {
524 if (!theMother) continue;
525 allancestors.insert(theMother);
526 findParticleAncestors(theMother, allancestors);
527 }
528 }
529
531
532 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
533 auto endVtx = thePart->end_vertex();
534 if (!endVtx) return;
535 for (const auto& theDaughter: endVtx->particles_out()) {
536 if (!theDaughter) continue;
537 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
538 allstabledescendants.insert(theDaughter);
539 }
540 findParticleStableDescendants(theDaughter, allstabledescendants);
541 }
542 }
543
547
548 template <class T> bool isHardScatteringVertex(T pVert) {
549 if (pVert == nullptr) return false;
550 T pV = pVert;
551 int numOfPartIn(0);
552 int pdg(0);
553
554 do {
555 pVert = pV;
556 auto incoming = pVert->particles_in();
557 numOfPartIn = incoming.size();
558 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
559 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
560
561 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
562
563 if (numOfPartIn == 2) {
564 auto incoming = pVert->particles_in();
565 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
566 }
567 return false;
568}
569
573
574 template <class T, class U>
575 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
576 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
577 auto vtx = p->production_vertex();
578 if (!vtx) return false;
579 bool fromHad = false;
580 for ( const auto& parent : particles_in(vtx) ) {
581 if (!parent) continue;
582 // should this really go into parton-level territory?
583 // probably depends where BSM particles are being decayed
584 fromBSM |= isBSM(parent);
585 if (!isPhysical(parent)) return false;
586 fromTau |= isTau(parent);
587 if (isHadron(parent)&&!isBeam(parent)) {
588 if (!hadron) hadron = parent; // assumes linear hadron parentage
589 return true;
590 }
591 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
592 }
593 return fromHad;
594 }
595
598
599 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
600 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
601 decltype(thePart->end_vertex()) pVert(nullptr);
602 if (EndVert != nullptr) {
603 do {
604 bool samePart = false;
605 pVert = nullptr;
606 auto outgoing = EndVert->particles_out();
607 auto incoming = EndVert->particles_in();
608 for (const auto& itrDaug: outgoing) {
609 if (!itrDaug) continue;
610 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
611 // brem on generator level for tau
612 (outgoing.size() == 1 && incoming.size() == 1 &&
614 itrDaug->pdg_id() == thePart->pdg_id()) {
615 samePart = true;
616 pVert = itrDaug->end_vertex();
617 }
618 }
619 if (samePart) EndVert = pVert;
620 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
621 }
622 return EndVert;
623 }
624
626
627 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
628 if (!theVert) return {};
629 decltype(theVert->particles_out()) finalStatePart;
630 auto outgoing = theVert->particles_out();
631 for (const auto& thePart: outgoing) {
632 if (!thePart) continue;
633 finalStatePart.push_back(thePart);
634 if (isStable(thePart)) continue;
635 V pVert = findSimulatedEndVertex(thePart);
636 if (pVert == theVert) break; // to prevent Sherpa loop
637 if (pVert != nullptr) {
638 auto vecPart = findFinalStateParticles<V>(pVert);
639 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
640 }
641 }
642 return finalStatePart;
643 }
644#if !defined(XAOD_ANALYSIS)
645#include "AtlasHepMC/GenEvent.h"
646inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
647inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
648
649#endif
650}
651#endif

◆ isGluon() [2/2]

template<class T>
bool MC::isGluon ( const T & p)
inline

Definition at line 374 of file HepMCHelpers.h.

393{
394 template <class VTX>
395 auto particles_in (const VTX* p) { return p->particles_in(); }
396 template <class VTX>
397 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
398
399 namespace Pythia8
400 {
402 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
403
404 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
405
406 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
407 }
408
409#include "AtlasPID.h"
410
412 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
413
415 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
416
418 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
419
421 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
422
424 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
425
427 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
428
430 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
431
433 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
434
436 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
437
439 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
440
444 template <class T> inline bool isStableOrSimDecayed(const T& p) {
445 const auto vertex = p->end_vertex();
446 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
447 }
448
450 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
451
453 template <class T> inline bool isSpecialNonInteracting(const T& p) {
454 const int apid = std::abs(p->pdg_id());
455 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
456 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
457 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
458 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
459 return false;
460 }
461
463
464 template <class T> T findMother(T thePart) {
465 auto partOriVert = thePart->production_vertex();
466 if (!partOriVert) return nullptr;
467
468 long partPDG = thePart->pdg_id();
469 long MotherPDG(0);
470
471 auto MothOriVert = partOriVert;
472 MothOriVert = nullptr;
473 T theMoth(nullptr);
474
475 size_t itr = 0;
476 do {
477 if (itr != 0) partOriVert = MothOriVert;
478 for ( const auto& p : particles_in(partOriVert) ) {
479 theMoth = p;
480 if (!theMoth) continue;
481 MotherPDG = theMoth->pdg_id();
482 MothOriVert = theMoth->production_vertex();
483 if (MotherPDG == partPDG) break;
484 }
485 itr++;
486 if (itr > 100) {
487 break;
488 }
489 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
490 MothOriVert != partOriVert);
491 return theMoth;
492 }
493
495
496 template <class C, class T> T findMatching(C TruthContainer, T p) {
497 T ptrPart = nullptr;
498 if (!p) return ptrPart;
499 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
500 for (T truthParticle : *TruthContainer) {
501 if (HepMC::is_sim_descendant(p,truthParticle)) {
502 ptrPart = truthParticle;
503 break;
504 }
505 }
506 }
507 else {
508 for (T truthParticle : TruthContainer) {
509 if (HepMC::is_sim_descendant(p,truthParticle)) {
510 ptrPart = truthParticle;
511 break;
512 }
513 }
514 }
515 return ptrPart;
516 }
518
519 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
520 auto prodVtx = thePart->production_vertex();
521 if (!prodVtx) return;
522 for (const auto& theMother: prodVtx->particles_in()) {
523 if (!theMother) continue;
524 allancestors.insert(theMother);
525 findParticleAncestors(theMother, allancestors);
526 }
527 }
528
530
531 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
532 auto endVtx = thePart->end_vertex();
533 if (!endVtx) return;
534 for (const auto& theDaughter: endVtx->particles_out()) {
535 if (!theDaughter) continue;
536 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
537 allstabledescendants.insert(theDaughter);
538 }
539 findParticleStableDescendants(theDaughter, allstabledescendants);
540 }
541 }
542
546
547 template <class T> bool isHardScatteringVertex(T pVert) {
548 if (pVert == nullptr) return false;
549 T pV = pVert;
550 int numOfPartIn(0);
551 int pdg(0);
552
553 do {
554 pVert = pV;
555 auto incoming = pVert->particles_in();
556 numOfPartIn = incoming.size();
557 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
558 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
559
560 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
561
562 if (numOfPartIn == 2) {
563 auto incoming = pVert->particles_in();
564 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
565 }
566 return false;
567}
568
572
573 template <class T, class U>
574 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
575 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
576 auto vtx = p->production_vertex();
577 if (!vtx) return false;
578 bool fromHad = false;
579 for ( const auto& parent : particles_in(vtx) ) {
580 if (!parent) continue;
581 // should this really go into parton-level territory?
582 // probably depends where BSM particles are being decayed
583 fromBSM |= isBSM(parent);
584 if (!isPhysical(parent)) return false;
585 fromTau |= isTau(parent);
586 if (isHadron(parent)&&!isBeam(parent)) {
587 if (!hadron) hadron = parent; // assumes linear hadron parentage
588 return true;
589 }
590 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
591 }
592 return fromHad;
593 }
594
597
598 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
599 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
600 decltype(thePart->end_vertex()) pVert(nullptr);
601 if (EndVert != nullptr) {
602 do {
603 bool samePart = false;
604 pVert = nullptr;
605 auto outgoing = EndVert->particles_out();
606 auto incoming = EndVert->particles_in();
607 for (const auto& itrDaug: outgoing) {
608 if (!itrDaug) continue;
609 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
610 // brem on generator level for tau
611 (outgoing.size() == 1 && incoming.size() == 1 &&
613 itrDaug->pdg_id() == thePart->pdg_id()) {
614 samePart = true;
615 pVert = itrDaug->end_vertex();
616 }
617 }
618 if (samePart) EndVert = pVert;
619 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
620 }
621 return EndVert;
622 }
623
625
626 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
627 if (!theVert) return {};
628 decltype(theVert->particles_out()) finalStatePart;
629 auto outgoing = theVert->particles_out();
630 for (const auto& thePart: outgoing) {
631 if (!thePart) continue;
632 finalStatePart.push_back(thePart);
633 if (isStable(thePart)) continue;
634 V pVert = findSimulatedEndVertex(thePart);
635 if (pVert == theVert) break; // to prevent Sherpa loop
636 if (pVert != nullptr) {
637 auto vecPart = findFinalStateParticles<V>(pVert);
638 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
639 }
640 }
641 return finalStatePart;
642 }
643#if !defined(XAOD_ANALYSIS)
644#include "AtlasHepMC/GenEvent.h"
645inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
646inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
647
648#endif
649}
650#endif

◆ isGraviton() [1/2]

template<>
bool MC::isGraviton ( const int & p)
inline

Definition at line 399 of file HepMCHelpers.h.

418{
419 template <class VTX>
420 auto particles_in (const VTX* p) { return p->particles_in(); }
421 template <class VTX>
422 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
423
424 namespace Pythia8
425 {
427 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
428
429 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
430
431 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
432 }
433
434#include "AtlasPID.h"
435
437 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
438
440 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
441
443 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
444
446 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
447
449 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
450
452 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
453
455 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
456
458 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
459
461 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
462
464 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
465
469 template <class T> inline bool isStableOrSimDecayed(const T& p) {
470 const auto vertex = p->end_vertex();
471 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
472 }
473
475 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
476
478 template <class T> inline bool isSpecialNonInteracting(const T& p) {
479 const int apid = std::abs(p->pdg_id());
480 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
481 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
482 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
483 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
484 return false;
485 }
486
488
489 template <class T> T findMother(T thePart) {
490 auto partOriVert = thePart->production_vertex();
491 if (!partOriVert) return nullptr;
492
493 long partPDG = thePart->pdg_id();
494 long MotherPDG(0);
495
496 auto MothOriVert = partOriVert;
497 MothOriVert = nullptr;
498 T theMoth(nullptr);
499
500 size_t itr = 0;
501 do {
502 if (itr != 0) partOriVert = MothOriVert;
503 for ( const auto& p : particles_in(partOriVert) ) {
504 theMoth = p;
505 if (!theMoth) continue;
506 MotherPDG = theMoth->pdg_id();
507 MothOriVert = theMoth->production_vertex();
508 if (MotherPDG == partPDG) break;
509 }
510 itr++;
511 if (itr > 100) {
512 break;
513 }
514 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
515 MothOriVert != partOriVert);
516 return theMoth;
517 }
518
520
521 template <class C, class T> T findMatching(C TruthContainer, T p) {
522 T ptrPart = nullptr;
523 if (!p) return ptrPart;
524 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
525 for (T truthParticle : *TruthContainer) {
526 if (HepMC::is_sim_descendant(p,truthParticle)) {
527 ptrPart = truthParticle;
528 break;
529 }
530 }
531 }
532 else {
533 for (T truthParticle : TruthContainer) {
534 if (HepMC::is_sim_descendant(p,truthParticle)) {
535 ptrPart = truthParticle;
536 break;
537 }
538 }
539 }
540 return ptrPart;
541 }
543
544 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
545 auto prodVtx = thePart->production_vertex();
546 if (!prodVtx) return;
547 for (const auto& theMother: prodVtx->particles_in()) {
548 if (!theMother) continue;
549 allancestors.insert(theMother);
550 findParticleAncestors(theMother, allancestors);
551 }
552 }
553
555
556 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
557 auto endVtx = thePart->end_vertex();
558 if (!endVtx) return;
559 for (const auto& theDaughter: endVtx->particles_out()) {
560 if (!theDaughter) continue;
561 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
562 allstabledescendants.insert(theDaughter);
563 }
564 findParticleStableDescendants(theDaughter, allstabledescendants);
565 }
566 }
567
571
572 template <class T> bool isHardScatteringVertex(T pVert) {
573 if (pVert == nullptr) return false;
574 T pV = pVert;
575 int numOfPartIn(0);
576 int pdg(0);
577
578 do {
579 pVert = pV;
580 auto incoming = pVert->particles_in();
581 numOfPartIn = incoming.size();
582 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
583 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
584
585 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
586
587 if (numOfPartIn == 2) {
588 auto incoming = pVert->particles_in();
589 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
590 }
591 return false;
592}
593
597
598 template <class T, class U>
599 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
600 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
601 auto vtx = p->production_vertex();
602 if (!vtx) return false;
603 bool fromHad = false;
604 for ( const auto& parent : particles_in(vtx) ) {
605 if (!parent) continue;
606 // should this really go into parton-level territory?
607 // probably depends where BSM particles are being decayed
608 fromBSM |= isBSM(parent);
609 if (!isPhysical(parent)) return false;
610 fromTau |= isTau(parent);
611 if (isHadron(parent)&&!isBeam(parent)) {
612 if (!hadron) hadron = parent; // assumes linear hadron parentage
613 return true;
614 }
615 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
616 }
617 return fromHad;
618 }
619
622
623 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
624 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
625 decltype(thePart->end_vertex()) pVert(nullptr);
626 if (EndVert != nullptr) {
627 do {
628 bool samePart = false;
629 pVert = nullptr;
630 auto outgoing = EndVert->particles_out();
631 auto incoming = EndVert->particles_in();
632 for (const auto& itrDaug: outgoing) {
633 if (!itrDaug) continue;
634 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
635 // brem on generator level for tau
636 (outgoing.size() == 1 && incoming.size() == 1 &&
638 itrDaug->pdg_id() == thePart->pdg_id()) {
639 samePart = true;
640 pVert = itrDaug->end_vertex();
641 }
642 }
643 if (samePart) EndVert = pVert;
644 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
645 }
646 return EndVert;
647 }
648
650
651 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
652 if (!theVert) return {};
653 decltype(theVert->particles_out()) finalStatePart;
654 auto outgoing = theVert->particles_out();
655 for (const auto& thePart: outgoing) {
656 if (!thePart) continue;
657 finalStatePart.push_back(thePart);
658 if (isStable(thePart)) continue;
659 V pVert = findSimulatedEndVertex(thePart);
660 if (pVert == theVert) break; // to prevent Sherpa loop
661 if (pVert != nullptr) {
662 auto vecPart = findFinalStateParticles<V>(pVert);
663 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
664 }
665 }
666 return finalStatePart;
667 }
668#if !defined(XAOD_ANALYSIS)
669#include "AtlasHepMC/GenEvent.h"
670inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
671inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
672
673#endif
674}
675#endif

◆ isGraviton() [2/2]

template<class T>
bool MC::isGraviton ( const T & p)
inline

Definition at line 398 of file HepMCHelpers.h.

417{
418 template <class VTX>
419 auto particles_in (const VTX* p) { return p->particles_in(); }
420 template <class VTX>
421 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
422
423 namespace Pythia8
424 {
426 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
427
428 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
429
430 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
431 }
432
433#include "AtlasPID.h"
434
436 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
437
439 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
440
442 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
443
445 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
446
448 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
449
451 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
452
454 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
455
457 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
458
460 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
461
463 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
464
468 template <class T> inline bool isStableOrSimDecayed(const T& p) {
469 const auto vertex = p->end_vertex();
470 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
471 }
472
474 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
475
477 template <class T> inline bool isSpecialNonInteracting(const T& p) {
478 const int apid = std::abs(p->pdg_id());
479 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
480 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
481 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
482 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
483 return false;
484 }
485
487
488 template <class T> T findMother(T thePart) {
489 auto partOriVert = thePart->production_vertex();
490 if (!partOriVert) return nullptr;
491
492 long partPDG = thePart->pdg_id();
493 long MotherPDG(0);
494
495 auto MothOriVert = partOriVert;
496 MothOriVert = nullptr;
497 T theMoth(nullptr);
498
499 size_t itr = 0;
500 do {
501 if (itr != 0) partOriVert = MothOriVert;
502 for ( const auto& p : particles_in(partOriVert) ) {
503 theMoth = p;
504 if (!theMoth) continue;
505 MotherPDG = theMoth->pdg_id();
506 MothOriVert = theMoth->production_vertex();
507 if (MotherPDG == partPDG) break;
508 }
509 itr++;
510 if (itr > 100) {
511 break;
512 }
513 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
514 MothOriVert != partOriVert);
515 return theMoth;
516 }
517
519
520 template <class C, class T> T findMatching(C TruthContainer, T p) {
521 T ptrPart = nullptr;
522 if (!p) return ptrPart;
523 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
524 for (T truthParticle : *TruthContainer) {
525 if (HepMC::is_sim_descendant(p,truthParticle)) {
526 ptrPart = truthParticle;
527 break;
528 }
529 }
530 }
531 else {
532 for (T truthParticle : TruthContainer) {
533 if (HepMC::is_sim_descendant(p,truthParticle)) {
534 ptrPart = truthParticle;
535 break;
536 }
537 }
538 }
539 return ptrPart;
540 }
542
543 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
544 auto prodVtx = thePart->production_vertex();
545 if (!prodVtx) return;
546 for (const auto& theMother: prodVtx->particles_in()) {
547 if (!theMother) continue;
548 allancestors.insert(theMother);
549 findParticleAncestors(theMother, allancestors);
550 }
551 }
552
554
555 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
556 auto endVtx = thePart->end_vertex();
557 if (!endVtx) return;
558 for (const auto& theDaughter: endVtx->particles_out()) {
559 if (!theDaughter) continue;
560 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
561 allstabledescendants.insert(theDaughter);
562 }
563 findParticleStableDescendants(theDaughter, allstabledescendants);
564 }
565 }
566
570
571 template <class T> bool isHardScatteringVertex(T pVert) {
572 if (pVert == nullptr) return false;
573 T pV = pVert;
574 int numOfPartIn(0);
575 int pdg(0);
576
577 do {
578 pVert = pV;
579 auto incoming = pVert->particles_in();
580 numOfPartIn = incoming.size();
581 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
582 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
583
584 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
585
586 if (numOfPartIn == 2) {
587 auto incoming = pVert->particles_in();
588 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
589 }
590 return false;
591}
592
596
597 template <class T, class U>
598 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
599 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
600 auto vtx = p->production_vertex();
601 if (!vtx) return false;
602 bool fromHad = false;
603 for ( const auto& parent : particles_in(vtx) ) {
604 if (!parent) continue;
605 // should this really go into parton-level territory?
606 // probably depends where BSM particles are being decayed
607 fromBSM |= isBSM(parent);
608 if (!isPhysical(parent)) return false;
609 fromTau |= isTau(parent);
610 if (isHadron(parent)&&!isBeam(parent)) {
611 if (!hadron) hadron = parent; // assumes linear hadron parentage
612 return true;
613 }
614 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
615 }
616 return fromHad;
617 }
618
621
622 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
623 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
624 decltype(thePart->end_vertex()) pVert(nullptr);
625 if (EndVert != nullptr) {
626 do {
627 bool samePart = false;
628 pVert = nullptr;
629 auto outgoing = EndVert->particles_out();
630 auto incoming = EndVert->particles_in();
631 for (const auto& itrDaug: outgoing) {
632 if (!itrDaug) continue;
633 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
634 // brem on generator level for tau
635 (outgoing.size() == 1 && incoming.size() == 1 &&
637 itrDaug->pdg_id() == thePart->pdg_id()) {
638 samePart = true;
639 pVert = itrDaug->end_vertex();
640 }
641 }
642 if (samePart) EndVert = pVert;
643 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
644 }
645 return EndVert;
646 }
647
649
650 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
651 if (!theVert) return {};
652 decltype(theVert->particles_out()) finalStatePart;
653 auto outgoing = theVert->particles_out();
654 for (const auto& thePart: outgoing) {
655 if (!thePart) continue;
656 finalStatePart.push_back(thePart);
657 if (isStable(thePart)) continue;
658 V pVert = findSimulatedEndVertex(thePart);
659 if (pVert == theVert) break; // to prevent Sherpa loop
660 if (pVert != nullptr) {
661 auto vecPart = findFinalStateParticles<V>(pVert);
662 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
663 }
664 }
665 return finalStatePart;
666 }
667#if !defined(XAOD_ANALYSIS)
668#include "AtlasHepMC/GenEvent.h"
669inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
670inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
671
672#endif
673}
674#endif

◆ isHadron() [1/3]

template<>
bool MC::isHadron ( const DecodedPID & p)
inline

Definition at line 353 of file HepMCHelpers.h.

372{
373 template <class VTX>
374 auto particles_in (const VTX* p) { return p->particles_in(); }
375 template <class VTX>
376 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
377
378 namespace Pythia8
379 {
381 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
382
383 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
384
385 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
386 }
387
388#include "AtlasPID.h"
389
391 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
392
394 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
395
397 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
398
400 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
401
403 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
404
406 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
407
409 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
410
412 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
413
415 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
416
418 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
419
423 template <class T> inline bool isStableOrSimDecayed(const T& p) {
424 const auto vertex = p->end_vertex();
425 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
426 }
427
429 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
430
432 template <class T> inline bool isSpecialNonInteracting(const T& p) {
433 const int apid = std::abs(p->pdg_id());
434 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
435 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
436 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
437 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
438 return false;
439 }
440
442
443 template <class T> T findMother(T thePart) {
444 auto partOriVert = thePart->production_vertex();
445 if (!partOriVert) return nullptr;
446
447 long partPDG = thePart->pdg_id();
448 long MotherPDG(0);
449
450 auto MothOriVert = partOriVert;
451 MothOriVert = nullptr;
452 T theMoth(nullptr);
453
454 size_t itr = 0;
455 do {
456 if (itr != 0) partOriVert = MothOriVert;
457 for ( const auto& p : particles_in(partOriVert) ) {
458 theMoth = p;
459 if (!theMoth) continue;
460 MotherPDG = theMoth->pdg_id();
461 MothOriVert = theMoth->production_vertex();
462 if (MotherPDG == partPDG) break;
463 }
464 itr++;
465 if (itr > 100) {
466 break;
467 }
468 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
469 MothOriVert != partOriVert);
470 return theMoth;
471 }
472
474
475 template <class C, class T> T findMatching(C TruthContainer, T p) {
476 T ptrPart = nullptr;
477 if (!p) return ptrPart;
478 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
479 for (T truthParticle : *TruthContainer) {
480 if (HepMC::is_sim_descendant(p,truthParticle)) {
481 ptrPart = truthParticle;
482 break;
483 }
484 }
485 }
486 else {
487 for (T truthParticle : TruthContainer) {
488 if (HepMC::is_sim_descendant(p,truthParticle)) {
489 ptrPart = truthParticle;
490 break;
491 }
492 }
493 }
494 return ptrPart;
495 }
497
498 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
499 auto prodVtx = thePart->production_vertex();
500 if (!prodVtx) return;
501 for (const auto& theMother: prodVtx->particles_in()) {
502 if (!theMother) continue;
503 allancestors.insert(theMother);
504 findParticleAncestors(theMother, allancestors);
505 }
506 }
507
509
510 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
511 auto endVtx = thePart->end_vertex();
512 if (!endVtx) return;
513 for (const auto& theDaughter: endVtx->particles_out()) {
514 if (!theDaughter) continue;
515 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
516 allstabledescendants.insert(theDaughter);
517 }
518 findParticleStableDescendants(theDaughter, allstabledescendants);
519 }
520 }
521
525
526 template <class T> bool isHardScatteringVertex(T pVert) {
527 if (pVert == nullptr) return false;
528 T pV = pVert;
529 int numOfPartIn(0);
530 int pdg(0);
531
532 do {
533 pVert = pV;
534 auto incoming = pVert->particles_in();
535 numOfPartIn = incoming.size();
536 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
537 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
538
539 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
540
541 if (numOfPartIn == 2) {
542 auto incoming = pVert->particles_in();
543 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
544 }
545 return false;
546}
547
551
552 template <class T, class U>
553 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
554 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
555 auto vtx = p->production_vertex();
556 if (!vtx) return false;
557 bool fromHad = false;
558 for ( const auto& parent : particles_in(vtx) ) {
559 if (!parent) continue;
560 // should this really go into parton-level territory?
561 // probably depends where BSM particles are being decayed
562 fromBSM |= isBSM(parent);
563 if (!isPhysical(parent)) return false;
564 fromTau |= isTau(parent);
565 if (isHadron(parent)&&!isBeam(parent)) {
566 if (!hadron) hadron = parent; // assumes linear hadron parentage
567 return true;
568 }
569 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
570 }
571 return fromHad;
572 }
573
576
577 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
578 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
579 decltype(thePart->end_vertex()) pVert(nullptr);
580 if (EndVert != nullptr) {
581 do {
582 bool samePart = false;
583 pVert = nullptr;
584 auto outgoing = EndVert->particles_out();
585 auto incoming = EndVert->particles_in();
586 for (const auto& itrDaug: outgoing) {
587 if (!itrDaug) continue;
588 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
589 // brem on generator level for tau
590 (outgoing.size() == 1 && incoming.size() == 1 &&
592 itrDaug->pdg_id() == thePart->pdg_id()) {
593 samePart = true;
594 pVert = itrDaug->end_vertex();
595 }
596 }
597 if (samePart) EndVert = pVert;
598 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
599 }
600 return EndVert;
601 }
602
604
605 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
606 if (!theVert) return {};
607 decltype(theVert->particles_out()) finalStatePart;
608 auto outgoing = theVert->particles_out();
609 for (const auto& thePart: outgoing) {
610 if (!thePart) continue;
611 finalStatePart.push_back(thePart);
612 if (isStable(thePart)) continue;
613 V pVert = findSimulatedEndVertex(thePart);
614 if (pVert == theVert) break; // to prevent Sherpa loop
615 if (pVert != nullptr) {
616 auto vecPart = findFinalStateParticles<V>(pVert);
617 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
618 }
619 }
620 return finalStatePart;
621 }
622#if !defined(XAOD_ANALYSIS)
623#include "AtlasHepMC/GenEvent.h"
624inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
625inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
626
627#endif
628}
629#endif

◆ isHadron() [2/3]

template<>
bool MC::isHadron ( const int & p)
inline

Definition at line 354 of file HepMCHelpers.h.

373{
374 template <class VTX>
375 auto particles_in (const VTX* p) { return p->particles_in(); }
376 template <class VTX>
377 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
378
379 namespace Pythia8
380 {
382 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
383
384 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
385
386 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
387 }
388
389#include "AtlasPID.h"
390
392 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
393
395 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
396
398 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
399
401 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
402
404 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
405
407 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
408
410 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
411
413 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
414
416 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
417
419 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
420
424 template <class T> inline bool isStableOrSimDecayed(const T& p) {
425 const auto vertex = p->end_vertex();
426 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
427 }
428
430 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
431
433 template <class T> inline bool isSpecialNonInteracting(const T& p) {
434 const int apid = std::abs(p->pdg_id());
435 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
436 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
437 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
438 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
439 return false;
440 }
441
443
444 template <class T> T findMother(T thePart) {
445 auto partOriVert = thePart->production_vertex();
446 if (!partOriVert) return nullptr;
447
448 long partPDG = thePart->pdg_id();
449 long MotherPDG(0);
450
451 auto MothOriVert = partOriVert;
452 MothOriVert = nullptr;
453 T theMoth(nullptr);
454
455 size_t itr = 0;
456 do {
457 if (itr != 0) partOriVert = MothOriVert;
458 for ( const auto& p : particles_in(partOriVert) ) {
459 theMoth = p;
460 if (!theMoth) continue;
461 MotherPDG = theMoth->pdg_id();
462 MothOriVert = theMoth->production_vertex();
463 if (MotherPDG == partPDG) break;
464 }
465 itr++;
466 if (itr > 100) {
467 break;
468 }
469 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
470 MothOriVert != partOriVert);
471 return theMoth;
472 }
473
475
476 template <class C, class T> T findMatching(C TruthContainer, T p) {
477 T ptrPart = nullptr;
478 if (!p) return ptrPart;
479 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
480 for (T truthParticle : *TruthContainer) {
481 if (HepMC::is_sim_descendant(p,truthParticle)) {
482 ptrPart = truthParticle;
483 break;
484 }
485 }
486 }
487 else {
488 for (T truthParticle : TruthContainer) {
489 if (HepMC::is_sim_descendant(p,truthParticle)) {
490 ptrPart = truthParticle;
491 break;
492 }
493 }
494 }
495 return ptrPart;
496 }
498
499 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
500 auto prodVtx = thePart->production_vertex();
501 if (!prodVtx) return;
502 for (const auto& theMother: prodVtx->particles_in()) {
503 if (!theMother) continue;
504 allancestors.insert(theMother);
505 findParticleAncestors(theMother, allancestors);
506 }
507 }
508
510
511 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
512 auto endVtx = thePart->end_vertex();
513 if (!endVtx) return;
514 for (const auto& theDaughter: endVtx->particles_out()) {
515 if (!theDaughter) continue;
516 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
517 allstabledescendants.insert(theDaughter);
518 }
519 findParticleStableDescendants(theDaughter, allstabledescendants);
520 }
521 }
522
526
527 template <class T> bool isHardScatteringVertex(T pVert) {
528 if (pVert == nullptr) return false;
529 T pV = pVert;
530 int numOfPartIn(0);
531 int pdg(0);
532
533 do {
534 pVert = pV;
535 auto incoming = pVert->particles_in();
536 numOfPartIn = incoming.size();
537 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
538 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
539
540 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
541
542 if (numOfPartIn == 2) {
543 auto incoming = pVert->particles_in();
544 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
545 }
546 return false;
547}
548
552
553 template <class T, class U>
554 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
555 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
556 auto vtx = p->production_vertex();
557 if (!vtx) return false;
558 bool fromHad = false;
559 for ( const auto& parent : particles_in(vtx) ) {
560 if (!parent) continue;
561 // should this really go into parton-level territory?
562 // probably depends where BSM particles are being decayed
563 fromBSM |= isBSM(parent);
564 if (!isPhysical(parent)) return false;
565 fromTau |= isTau(parent);
566 if (isHadron(parent)&&!isBeam(parent)) {
567 if (!hadron) hadron = parent; // assumes linear hadron parentage
568 return true;
569 }
570 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
571 }
572 return fromHad;
573 }
574
577
578 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
579 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
580 decltype(thePart->end_vertex()) pVert(nullptr);
581 if (EndVert != nullptr) {
582 do {
583 bool samePart = false;
584 pVert = nullptr;
585 auto outgoing = EndVert->particles_out();
586 auto incoming = EndVert->particles_in();
587 for (const auto& itrDaug: outgoing) {
588 if (!itrDaug) continue;
589 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
590 // brem on generator level for tau
591 (outgoing.size() == 1 && incoming.size() == 1 &&
593 itrDaug->pdg_id() == thePart->pdg_id()) {
594 samePart = true;
595 pVert = itrDaug->end_vertex();
596 }
597 }
598 if (samePart) EndVert = pVert;
599 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
600 }
601 return EndVert;
602 }
603
605
606 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
607 if (!theVert) return {};
608 decltype(theVert->particles_out()) finalStatePart;
609 auto outgoing = theVert->particles_out();
610 for (const auto& thePart: outgoing) {
611 if (!thePart) continue;
612 finalStatePart.push_back(thePart);
613 if (isStable(thePart)) continue;
614 V pVert = findSimulatedEndVertex(thePart);
615 if (pVert == theVert) break; // to prevent Sherpa loop
616 if (pVert != nullptr) {
617 auto vecPart = findFinalStateParticles<V>(pVert);
618 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
619 }
620 }
621 return finalStatePart;
622 }
623#if !defined(XAOD_ANALYSIS)
624#include "AtlasHepMC/GenEvent.h"
625inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
626inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
627
628#endif
629}
630#endif

◆ isHadron() [3/3]

template<class T>
bool MC::isHadron ( const T & p)
inline

Definition at line 352 of file HepMCHelpers.h.

371{
372 template <class VTX>
373 auto particles_in (const VTX* p) { return p->particles_in(); }
374 template <class VTX>
375 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
376
377 namespace Pythia8
378 {
380 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
381
382 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
383
384 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
385 }
386
387#include "AtlasPID.h"
388
390 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
391
393 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
394
396 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
397
399 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
400
402 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
403
405 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
406
408 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
409
411 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
412
414 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
415
417 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
418
422 template <class T> inline bool isStableOrSimDecayed(const T& p) {
423 const auto vertex = p->end_vertex();
424 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
425 }
426
428 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
429
431 template <class T> inline bool isSpecialNonInteracting(const T& p) {
432 const int apid = std::abs(p->pdg_id());
433 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
434 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
435 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
436 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
437 return false;
438 }
439
441
442 template <class T> T findMother(T thePart) {
443 auto partOriVert = thePart->production_vertex();
444 if (!partOriVert) return nullptr;
445
446 long partPDG = thePart->pdg_id();
447 long MotherPDG(0);
448
449 auto MothOriVert = partOriVert;
450 MothOriVert = nullptr;
451 T theMoth(nullptr);
452
453 size_t itr = 0;
454 do {
455 if (itr != 0) partOriVert = MothOriVert;
456 for ( const auto& p : particles_in(partOriVert) ) {
457 theMoth = p;
458 if (!theMoth) continue;
459 MotherPDG = theMoth->pdg_id();
460 MothOriVert = theMoth->production_vertex();
461 if (MotherPDG == partPDG) break;
462 }
463 itr++;
464 if (itr > 100) {
465 break;
466 }
467 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
468 MothOriVert != partOriVert);
469 return theMoth;
470 }
471
473
474 template <class C, class T> T findMatching(C TruthContainer, T p) {
475 T ptrPart = nullptr;
476 if (!p) return ptrPart;
477 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
478 for (T truthParticle : *TruthContainer) {
479 if (HepMC::is_sim_descendant(p,truthParticle)) {
480 ptrPart = truthParticle;
481 break;
482 }
483 }
484 }
485 else {
486 for (T truthParticle : TruthContainer) {
487 if (HepMC::is_sim_descendant(p,truthParticle)) {
488 ptrPart = truthParticle;
489 break;
490 }
491 }
492 }
493 return ptrPart;
494 }
496
497 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
498 auto prodVtx = thePart->production_vertex();
499 if (!prodVtx) return;
500 for (const auto& theMother: prodVtx->particles_in()) {
501 if (!theMother) continue;
502 allancestors.insert(theMother);
503 findParticleAncestors(theMother, allancestors);
504 }
505 }
506
508
509 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
510 auto endVtx = thePart->end_vertex();
511 if (!endVtx) return;
512 for (const auto& theDaughter: endVtx->particles_out()) {
513 if (!theDaughter) continue;
514 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
515 allstabledescendants.insert(theDaughter);
516 }
517 findParticleStableDescendants(theDaughter, allstabledescendants);
518 }
519 }
520
524
525 template <class T> bool isHardScatteringVertex(T pVert) {
526 if (pVert == nullptr) return false;
527 T pV = pVert;
528 int numOfPartIn(0);
529 int pdg(0);
530
531 do {
532 pVert = pV;
533 auto incoming = pVert->particles_in();
534 numOfPartIn = incoming.size();
535 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
536 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
537
538 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
539
540 if (numOfPartIn == 2) {
541 auto incoming = pVert->particles_in();
542 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
543 }
544 return false;
545}
546
550
551 template <class T, class U>
552 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
553 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
554 auto vtx = p->production_vertex();
555 if (!vtx) return false;
556 bool fromHad = false;
557 for ( const auto& parent : particles_in(vtx) ) {
558 if (!parent) continue;
559 // should this really go into parton-level territory?
560 // probably depends where BSM particles are being decayed
561 fromBSM |= isBSM(parent);
562 if (!isPhysical(parent)) return false;
563 fromTau |= isTau(parent);
564 if (isHadron(parent)&&!isBeam(parent)) {
565 if (!hadron) hadron = parent; // assumes linear hadron parentage
566 return true;
567 }
568 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
569 }
570 return fromHad;
571 }
572
575
576 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
577 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
578 decltype(thePart->end_vertex()) pVert(nullptr);
579 if (EndVert != nullptr) {
580 do {
581 bool samePart = false;
582 pVert = nullptr;
583 auto outgoing = EndVert->particles_out();
584 auto incoming = EndVert->particles_in();
585 for (const auto& itrDaug: outgoing) {
586 if (!itrDaug) continue;
587 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
588 // brem on generator level for tau
589 (outgoing.size() == 1 && incoming.size() == 1 &&
591 itrDaug->pdg_id() == thePart->pdg_id()) {
592 samePart = true;
593 pVert = itrDaug->end_vertex();
594 }
595 }
596 if (samePart) EndVert = pVert;
597 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
598 }
599 return EndVert;
600 }
601
603
604 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
605 if (!theVert) return {};
606 decltype(theVert->particles_out()) finalStatePart;
607 auto outgoing = theVert->particles_out();
608 for (const auto& thePart: outgoing) {
609 if (!thePart) continue;
610 finalStatePart.push_back(thePart);
611 if (isStable(thePart)) continue;
612 V pVert = findSimulatedEndVertex(thePart);
613 if (pVert == theVert) break; // to prevent Sherpa loop
614 if (pVert != nullptr) {
615 auto vecPart = findFinalStateParticles<V>(pVert);
616 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
617 }
618 }
619 return finalStatePart;
620 }
621#if !defined(XAOD_ANALYSIS)
622#include "AtlasHepMC/GenEvent.h"
623inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
624inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
625
626#endif
627}
628#endif

◆ isHardScatteringVertex()

template<class T>
bool MC::isHardScatteringVertex ( T pVert)

Function to classify the vertex as hard scattering vertex.

AV: This is MCtruthClassifier legacy. Note that this function willnot capture some cases of the HardScattering vertices. The function should be improved in the future. This can be used for HepMC3::GenVertexPtr, HepMC3::ConstGenVertexPtr or xAOD::TruthVertex*

Definition at line 174 of file HepMCHelpers.h.

174 {
175 if (pVert == nullptr) return false;
176 T pV = pVert;
177 int numOfPartIn(0);
178 int pdg(0);
179
180 do {
181 pVert = pV;
182 auto incoming = pVert->particles_in();
183 numOfPartIn = incoming.size();
184 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
185 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
186
187 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
188
189 if (numOfPartIn == 2) {
190 auto incoming = pVert->particles_in();
191 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
192 }
193 return false;
194}

◆ isHeavyBaryon()

template<class T>
bool MC::isHeavyBaryon ( const T & p)
inline

Definition at line 933 of file HepMCHelpers.h.

952{
953 template <class VTX>
954 auto particles_in (const VTX* p) { return p->particles_in(); }
955 template <class VTX>
956 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
957
958 namespace Pythia8
959 {
961 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
962
963 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
964
965 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
966 }
967
968#include "AtlasPID.h"
969
971 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
972
974 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
975
977 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
978
980 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
981
983 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
984
986 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
987
989 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
990
992 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
993
995 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
996
998 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
999
1003 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1004 const auto vertex = p->end_vertex();
1005 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1006 }
1007
1009 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1010
1012 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1013 const int apid = std::abs(p->pdg_id());
1014 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1015 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1016 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1017 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1018 return false;
1019 }
1020
1022
1023 template <class T> T findMother(T thePart) {
1024 auto partOriVert = thePart->production_vertex();
1025 if (!partOriVert) return nullptr;
1026
1027 long partPDG = thePart->pdg_id();
1028 long MotherPDG(0);
1029
1030 auto MothOriVert = partOriVert;
1031 MothOriVert = nullptr;
1032 T theMoth(nullptr);
1033
1034 size_t itr = 0;
1035 do {
1036 if (itr != 0) partOriVert = MothOriVert;
1037 for ( const auto& p : particles_in(partOriVert) ) {
1038 theMoth = p;
1039 if (!theMoth) continue;
1040 MotherPDG = theMoth->pdg_id();
1041 MothOriVert = theMoth->production_vertex();
1042 if (MotherPDG == partPDG) break;
1043 }
1044 itr++;
1045 if (itr > 100) {
1046 break;
1047 }
1048 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1049 MothOriVert != partOriVert);
1050 return theMoth;
1051 }
1052
1054
1055 template <class C, class T> T findMatching(C TruthContainer, T p) {
1056 T ptrPart = nullptr;
1057 if (!p) return ptrPart;
1058 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1059 for (T truthParticle : *TruthContainer) {
1060 if (HepMC::is_sim_descendant(p,truthParticle)) {
1061 ptrPart = truthParticle;
1062 break;
1063 }
1064 }
1065 }
1066 else {
1067 for (T truthParticle : TruthContainer) {
1068 if (HepMC::is_sim_descendant(p,truthParticle)) {
1069 ptrPart = truthParticle;
1070 break;
1071 }
1072 }
1073 }
1074 return ptrPart;
1075 }
1077
1078 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1079 auto prodVtx = thePart->production_vertex();
1080 if (!prodVtx) return;
1081 for (const auto& theMother: prodVtx->particles_in()) {
1082 if (!theMother) continue;
1083 allancestors.insert(theMother);
1084 findParticleAncestors(theMother, allancestors);
1085 }
1086 }
1087
1089
1090 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1091 auto endVtx = thePart->end_vertex();
1092 if (!endVtx) return;
1093 for (const auto& theDaughter: endVtx->particles_out()) {
1094 if (!theDaughter) continue;
1095 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1096 allstabledescendants.insert(theDaughter);
1097 }
1098 findParticleStableDescendants(theDaughter, allstabledescendants);
1099 }
1100 }
1101
1105
1106 template <class T> bool isHardScatteringVertex(T pVert) {
1107 if (pVert == nullptr) return false;
1108 T pV = pVert;
1109 int numOfPartIn(0);
1110 int pdg(0);
1111
1112 do {
1113 pVert = pV;
1114 auto incoming = pVert->particles_in();
1115 numOfPartIn = incoming.size();
1116 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1117 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1118
1119 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1120
1121 if (numOfPartIn == 2) {
1122 auto incoming = pVert->particles_in();
1123 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1124 }
1125 return false;
1126}
1127
1131
1132 template <class T, class U>
1133 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1134 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1135 auto vtx = p->production_vertex();
1136 if (!vtx) return false;
1137 bool fromHad = false;
1138 for ( const auto& parent : particles_in(vtx) ) {
1139 if (!parent) continue;
1140 // should this really go into parton-level territory?
1141 // probably depends where BSM particles are being decayed
1142 fromBSM |= isBSM(parent);
1143 if (!isPhysical(parent)) return false;
1144 fromTau |= isTau(parent);
1145 if (isHadron(parent)&&!isBeam(parent)) {
1146 if (!hadron) hadron = parent; // assumes linear hadron parentage
1147 return true;
1148 }
1149 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1150 }
1151 return fromHad;
1152 }
1153
1156
1157 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1158 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1159 decltype(thePart->end_vertex()) pVert(nullptr);
1160 if (EndVert != nullptr) {
1161 do {
1162 bool samePart = false;
1163 pVert = nullptr;
1164 auto outgoing = EndVert->particles_out();
1165 auto incoming = EndVert->particles_in();
1166 for (const auto& itrDaug: outgoing) {
1167 if (!itrDaug) continue;
1168 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1169 // brem on generator level for tau
1170 (outgoing.size() == 1 && incoming.size() == 1 &&
1172 itrDaug->pdg_id() == thePart->pdg_id()) {
1173 samePart = true;
1174 pVert = itrDaug->end_vertex();
1175 }
1176 }
1177 if (samePart) EndVert = pVert;
1178 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1179 }
1180 return EndVert;
1181 }
1182
1184
1185 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1186 if (!theVert) return {};
1187 decltype(theVert->particles_out()) finalStatePart;
1188 auto outgoing = theVert->particles_out();
1189 for (const auto& thePart: outgoing) {
1190 if (!thePart) continue;
1191 finalStatePart.push_back(thePart);
1192 if (isStable(thePart)) continue;
1193 V pVert = findSimulatedEndVertex(thePart);
1194 if (pVert == theVert) break; // to prevent Sherpa loop
1195 if (pVert != nullptr) {
1196 auto vecPart = findFinalStateParticles<V>(pVert);
1197 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1198 }
1199 }
1200 return finalStatePart;
1201 }
1202#if !defined(XAOD_ANALYSIS)
1203#include "AtlasHepMC/GenEvent.h"
1204inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1205inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1206
1207#endif
1208}
1209#endif

◆ isHeavyBoson() [1/2]

template<>
bool MC::isHeavyBoson ( const int & p)
inline

Definition at line 388 of file HepMCHelpers.h.

407{
408 template <class VTX>
409 auto particles_in (const VTX* p) { return p->particles_in(); }
410 template <class VTX>
411 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
412
413 namespace Pythia8
414 {
416 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
417
418 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
419
420 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
421 }
422
423#include "AtlasPID.h"
424
426 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
427
429 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
430
432 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
433
435 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
436
438 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
439
441 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
442
444 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
445
447 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
448
450 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
451
453 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
454
458 template <class T> inline bool isStableOrSimDecayed(const T& p) {
459 const auto vertex = p->end_vertex();
460 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
461 }
462
464 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
465
467 template <class T> inline bool isSpecialNonInteracting(const T& p) {
468 const int apid = std::abs(p->pdg_id());
469 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
470 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
471 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
472 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
473 return false;
474 }
475
477
478 template <class T> T findMother(T thePart) {
479 auto partOriVert = thePart->production_vertex();
480 if (!partOriVert) return nullptr;
481
482 long partPDG = thePart->pdg_id();
483 long MotherPDG(0);
484
485 auto MothOriVert = partOriVert;
486 MothOriVert = nullptr;
487 T theMoth(nullptr);
488
489 size_t itr = 0;
490 do {
491 if (itr != 0) partOriVert = MothOriVert;
492 for ( const auto& p : particles_in(partOriVert) ) {
493 theMoth = p;
494 if (!theMoth) continue;
495 MotherPDG = theMoth->pdg_id();
496 MothOriVert = theMoth->production_vertex();
497 if (MotherPDG == partPDG) break;
498 }
499 itr++;
500 if (itr > 100) {
501 break;
502 }
503 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
504 MothOriVert != partOriVert);
505 return theMoth;
506 }
507
509
510 template <class C, class T> T findMatching(C TruthContainer, T p) {
511 T ptrPart = nullptr;
512 if (!p) return ptrPart;
513 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
514 for (T truthParticle : *TruthContainer) {
515 if (HepMC::is_sim_descendant(p,truthParticle)) {
516 ptrPart = truthParticle;
517 break;
518 }
519 }
520 }
521 else {
522 for (T truthParticle : TruthContainer) {
523 if (HepMC::is_sim_descendant(p,truthParticle)) {
524 ptrPart = truthParticle;
525 break;
526 }
527 }
528 }
529 return ptrPart;
530 }
532
533 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
534 auto prodVtx = thePart->production_vertex();
535 if (!prodVtx) return;
536 for (const auto& theMother: prodVtx->particles_in()) {
537 if (!theMother) continue;
538 allancestors.insert(theMother);
539 findParticleAncestors(theMother, allancestors);
540 }
541 }
542
544
545 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
546 auto endVtx = thePart->end_vertex();
547 if (!endVtx) return;
548 for (const auto& theDaughter: endVtx->particles_out()) {
549 if (!theDaughter) continue;
550 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
551 allstabledescendants.insert(theDaughter);
552 }
553 findParticleStableDescendants(theDaughter, allstabledescendants);
554 }
555 }
556
560
561 template <class T> bool isHardScatteringVertex(T pVert) {
562 if (pVert == nullptr) return false;
563 T pV = pVert;
564 int numOfPartIn(0);
565 int pdg(0);
566
567 do {
568 pVert = pV;
569 auto incoming = pVert->particles_in();
570 numOfPartIn = incoming.size();
571 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
572 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
573
574 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
575
576 if (numOfPartIn == 2) {
577 auto incoming = pVert->particles_in();
578 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
579 }
580 return false;
581}
582
586
587 template <class T, class U>
588 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
589 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
590 auto vtx = p->production_vertex();
591 if (!vtx) return false;
592 bool fromHad = false;
593 for ( const auto& parent : particles_in(vtx) ) {
594 if (!parent) continue;
595 // should this really go into parton-level territory?
596 // probably depends where BSM particles are being decayed
597 fromBSM |= isBSM(parent);
598 if (!isPhysical(parent)) return false;
599 fromTau |= isTau(parent);
600 if (isHadron(parent)&&!isBeam(parent)) {
601 if (!hadron) hadron = parent; // assumes linear hadron parentage
602 return true;
603 }
604 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
605 }
606 return fromHad;
607 }
608
611
612 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
613 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
614 decltype(thePart->end_vertex()) pVert(nullptr);
615 if (EndVert != nullptr) {
616 do {
617 bool samePart = false;
618 pVert = nullptr;
619 auto outgoing = EndVert->particles_out();
620 auto incoming = EndVert->particles_in();
621 for (const auto& itrDaug: outgoing) {
622 if (!itrDaug) continue;
623 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
624 // brem on generator level for tau
625 (outgoing.size() == 1 && incoming.size() == 1 &&
627 itrDaug->pdg_id() == thePart->pdg_id()) {
628 samePart = true;
629 pVert = itrDaug->end_vertex();
630 }
631 }
632 if (samePart) EndVert = pVert;
633 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
634 }
635 return EndVert;
636 }
637
639
640 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
641 if (!theVert) return {};
642 decltype(theVert->particles_out()) finalStatePart;
643 auto outgoing = theVert->particles_out();
644 for (const auto& thePart: outgoing) {
645 if (!thePart) continue;
646 finalStatePart.push_back(thePart);
647 if (isStable(thePart)) continue;
648 V pVert = findSimulatedEndVertex(thePart);
649 if (pVert == theVert) break; // to prevent Sherpa loop
650 if (pVert != nullptr) {
651 auto vecPart = findFinalStateParticles<V>(pVert);
652 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
653 }
654 }
655 return finalStatePart;
656 }
657#if !defined(XAOD_ANALYSIS)
658#include "AtlasHepMC/GenEvent.h"
659inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
660inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
661
662#endif
663}
664#endif

◆ isHeavyBoson() [2/2]

template<class T>
bool MC::isHeavyBoson ( const T & p)
inline

APID: Additional "Heavy"/"prime" versions of W and Z bosons (Used in MCTruthClassifier).

Definition at line 387 of file HepMCHelpers.h.

406{
407 template <class VTX>
408 auto particles_in (const VTX* p) { return p->particles_in(); }
409 template <class VTX>
410 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
411
412 namespace Pythia8
413 {
415 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
416
417 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
418
419 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
420 }
421
422#include "AtlasPID.h"
423
425 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
426
428 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
429
431 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
432
434 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
435
437 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
438
440 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
441
443 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
444
446 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
447
449 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
450
452 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
453
457 template <class T> inline bool isStableOrSimDecayed(const T& p) {
458 const auto vertex = p->end_vertex();
459 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
460 }
461
463 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
464
466 template <class T> inline bool isSpecialNonInteracting(const T& p) {
467 const int apid = std::abs(p->pdg_id());
468 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
469 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
470 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
471 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
472 return false;
473 }
474
476
477 template <class T> T findMother(T thePart) {
478 auto partOriVert = thePart->production_vertex();
479 if (!partOriVert) return nullptr;
480
481 long partPDG = thePart->pdg_id();
482 long MotherPDG(0);
483
484 auto MothOriVert = partOriVert;
485 MothOriVert = nullptr;
486 T theMoth(nullptr);
487
488 size_t itr = 0;
489 do {
490 if (itr != 0) partOriVert = MothOriVert;
491 for ( const auto& p : particles_in(partOriVert) ) {
492 theMoth = p;
493 if (!theMoth) continue;
494 MotherPDG = theMoth->pdg_id();
495 MothOriVert = theMoth->production_vertex();
496 if (MotherPDG == partPDG) break;
497 }
498 itr++;
499 if (itr > 100) {
500 break;
501 }
502 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
503 MothOriVert != partOriVert);
504 return theMoth;
505 }
506
508
509 template <class C, class T> T findMatching(C TruthContainer, T p) {
510 T ptrPart = nullptr;
511 if (!p) return ptrPart;
512 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
513 for (T truthParticle : *TruthContainer) {
514 if (HepMC::is_sim_descendant(p,truthParticle)) {
515 ptrPart = truthParticle;
516 break;
517 }
518 }
519 }
520 else {
521 for (T truthParticle : TruthContainer) {
522 if (HepMC::is_sim_descendant(p,truthParticle)) {
523 ptrPart = truthParticle;
524 break;
525 }
526 }
527 }
528 return ptrPart;
529 }
531
532 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
533 auto prodVtx = thePart->production_vertex();
534 if (!prodVtx) return;
535 for (const auto& theMother: prodVtx->particles_in()) {
536 if (!theMother) continue;
537 allancestors.insert(theMother);
538 findParticleAncestors(theMother, allancestors);
539 }
540 }
541
543
544 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
545 auto endVtx = thePart->end_vertex();
546 if (!endVtx) return;
547 for (const auto& theDaughter: endVtx->particles_out()) {
548 if (!theDaughter) continue;
549 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
550 allstabledescendants.insert(theDaughter);
551 }
552 findParticleStableDescendants(theDaughter, allstabledescendants);
553 }
554 }
555
559
560 template <class T> bool isHardScatteringVertex(T pVert) {
561 if (pVert == nullptr) return false;
562 T pV = pVert;
563 int numOfPartIn(0);
564 int pdg(0);
565
566 do {
567 pVert = pV;
568 auto incoming = pVert->particles_in();
569 numOfPartIn = incoming.size();
570 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
571 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
572
573 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
574
575 if (numOfPartIn == 2) {
576 auto incoming = pVert->particles_in();
577 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
578 }
579 return false;
580}
581
585
586 template <class T, class U>
587 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
588 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
589 auto vtx = p->production_vertex();
590 if (!vtx) return false;
591 bool fromHad = false;
592 for ( const auto& parent : particles_in(vtx) ) {
593 if (!parent) continue;
594 // should this really go into parton-level territory?
595 // probably depends where BSM particles are being decayed
596 fromBSM |= isBSM(parent);
597 if (!isPhysical(parent)) return false;
598 fromTau |= isTau(parent);
599 if (isHadron(parent)&&!isBeam(parent)) {
600 if (!hadron) hadron = parent; // assumes linear hadron parentage
601 return true;
602 }
603 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
604 }
605 return fromHad;
606 }
607
610
611 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
612 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
613 decltype(thePart->end_vertex()) pVert(nullptr);
614 if (EndVert != nullptr) {
615 do {
616 bool samePart = false;
617 pVert = nullptr;
618 auto outgoing = EndVert->particles_out();
619 auto incoming = EndVert->particles_in();
620 for (const auto& itrDaug: outgoing) {
621 if (!itrDaug) continue;
622 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
623 // brem on generator level for tau
624 (outgoing.size() == 1 && incoming.size() == 1 &&
626 itrDaug->pdg_id() == thePart->pdg_id()) {
627 samePart = true;
628 pVert = itrDaug->end_vertex();
629 }
630 }
631 if (samePart) EndVert = pVert;
632 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
633 }
634 return EndVert;
635 }
636
638
639 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
640 if (!theVert) return {};
641 decltype(theVert->particles_out()) finalStatePart;
642 auto outgoing = theVert->particles_out();
643 for (const auto& thePart: outgoing) {
644 if (!thePart) continue;
645 finalStatePart.push_back(thePart);
646 if (isStable(thePart)) continue;
647 V pVert = findSimulatedEndVertex(thePart);
648 if (pVert == theVert) break; // to prevent Sherpa loop
649 if (pVert != nullptr) {
650 auto vecPart = findFinalStateParticles<V>(pVert);
651 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
652 }
653 }
654 return finalStatePart;
655 }
656#if !defined(XAOD_ANALYSIS)
657#include "AtlasHepMC/GenEvent.h"
658inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
659inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
660
661#endif
662}
663#endif

◆ isHeavyHadron()

template<class T>
bool MC::isHeavyHadron ( const T & p)
inline

Definition at line 910 of file HepMCHelpers.h.

929{
930 template <class VTX>
931 auto particles_in (const VTX* p) { return p->particles_in(); }
932 template <class VTX>
933 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
934
935 namespace Pythia8
936 {
938 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
939
940 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
941
942 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
943 }
944
945#include "AtlasPID.h"
946
948 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
949
951 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
952
954 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
955
957 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
958
960 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
961
963 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
964
966 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
967
969 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
970
972 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
973
975 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
976
980 template <class T> inline bool isStableOrSimDecayed(const T& p) {
981 const auto vertex = p->end_vertex();
982 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
983 }
984
986 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
987
989 template <class T> inline bool isSpecialNonInteracting(const T& p) {
990 const int apid = std::abs(p->pdg_id());
991 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
992 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
993 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
994 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
995 return false;
996 }
997
999
1000 template <class T> T findMother(T thePart) {
1001 auto partOriVert = thePart->production_vertex();
1002 if (!partOriVert) return nullptr;
1003
1004 long partPDG = thePart->pdg_id();
1005 long MotherPDG(0);
1006
1007 auto MothOriVert = partOriVert;
1008 MothOriVert = nullptr;
1009 T theMoth(nullptr);
1010
1011 size_t itr = 0;
1012 do {
1013 if (itr != 0) partOriVert = MothOriVert;
1014 for ( const auto& p : particles_in(partOriVert) ) {
1015 theMoth = p;
1016 if (!theMoth) continue;
1017 MotherPDG = theMoth->pdg_id();
1018 MothOriVert = theMoth->production_vertex();
1019 if (MotherPDG == partPDG) break;
1020 }
1021 itr++;
1022 if (itr > 100) {
1023 break;
1024 }
1025 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1026 MothOriVert != partOriVert);
1027 return theMoth;
1028 }
1029
1031
1032 template <class C, class T> T findMatching(C TruthContainer, T p) {
1033 T ptrPart = nullptr;
1034 if (!p) return ptrPart;
1035 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1036 for (T truthParticle : *TruthContainer) {
1037 if (HepMC::is_sim_descendant(p,truthParticle)) {
1038 ptrPart = truthParticle;
1039 break;
1040 }
1041 }
1042 }
1043 else {
1044 for (T truthParticle : TruthContainer) {
1045 if (HepMC::is_sim_descendant(p,truthParticle)) {
1046 ptrPart = truthParticle;
1047 break;
1048 }
1049 }
1050 }
1051 return ptrPart;
1052 }
1054
1055 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1056 auto prodVtx = thePart->production_vertex();
1057 if (!prodVtx) return;
1058 for (const auto& theMother: prodVtx->particles_in()) {
1059 if (!theMother) continue;
1060 allancestors.insert(theMother);
1061 findParticleAncestors(theMother, allancestors);
1062 }
1063 }
1064
1066
1067 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1068 auto endVtx = thePart->end_vertex();
1069 if (!endVtx) return;
1070 for (const auto& theDaughter: endVtx->particles_out()) {
1071 if (!theDaughter) continue;
1072 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1073 allstabledescendants.insert(theDaughter);
1074 }
1075 findParticleStableDescendants(theDaughter, allstabledescendants);
1076 }
1077 }
1078
1082
1083 template <class T> bool isHardScatteringVertex(T pVert) {
1084 if (pVert == nullptr) return false;
1085 T pV = pVert;
1086 int numOfPartIn(0);
1087 int pdg(0);
1088
1089 do {
1090 pVert = pV;
1091 auto incoming = pVert->particles_in();
1092 numOfPartIn = incoming.size();
1093 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1094 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1095
1096 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1097
1098 if (numOfPartIn == 2) {
1099 auto incoming = pVert->particles_in();
1100 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1101 }
1102 return false;
1103}
1104
1108
1109 template <class T, class U>
1110 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1111 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1112 auto vtx = p->production_vertex();
1113 if (!vtx) return false;
1114 bool fromHad = false;
1115 for ( const auto& parent : particles_in(vtx) ) {
1116 if (!parent) continue;
1117 // should this really go into parton-level territory?
1118 // probably depends where BSM particles are being decayed
1119 fromBSM |= isBSM(parent);
1120 if (!isPhysical(parent)) return false;
1121 fromTau |= isTau(parent);
1122 if (isHadron(parent)&&!isBeam(parent)) {
1123 if (!hadron) hadron = parent; // assumes linear hadron parentage
1124 return true;
1125 }
1126 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1127 }
1128 return fromHad;
1129 }
1130
1133
1134 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1135 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1136 decltype(thePart->end_vertex()) pVert(nullptr);
1137 if (EndVert != nullptr) {
1138 do {
1139 bool samePart = false;
1140 pVert = nullptr;
1141 auto outgoing = EndVert->particles_out();
1142 auto incoming = EndVert->particles_in();
1143 for (const auto& itrDaug: outgoing) {
1144 if (!itrDaug) continue;
1145 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1146 // brem on generator level for tau
1147 (outgoing.size() == 1 && incoming.size() == 1 &&
1149 itrDaug->pdg_id() == thePart->pdg_id()) {
1150 samePart = true;
1151 pVert = itrDaug->end_vertex();
1152 }
1153 }
1154 if (samePart) EndVert = pVert;
1155 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1156 }
1157 return EndVert;
1158 }
1159
1161
1162 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1163 if (!theVert) return {};
1164 decltype(theVert->particles_out()) finalStatePart;
1165 auto outgoing = theVert->particles_out();
1166 for (const auto& thePart: outgoing) {
1167 if (!thePart) continue;
1168 finalStatePart.push_back(thePart);
1169 if (isStable(thePart)) continue;
1170 V pVert = findSimulatedEndVertex(thePart);
1171 if (pVert == theVert) break; // to prevent Sherpa loop
1172 if (pVert != nullptr) {
1173 auto vecPart = findFinalStateParticles<V>(pVert);
1174 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1175 }
1176 }
1177 return finalStatePart;
1178 }
1179#if !defined(XAOD_ANALYSIS)
1180#include "AtlasHepMC/GenEvent.h"
1181inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1182inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1183
1184#endif
1185}
1186#endif

◆ isHeavyMeson()

template<class T>
bool MC::isHeavyMeson ( const T & p)
inline

Definition at line 917 of file HepMCHelpers.h.

936{
937 template <class VTX>
938 auto particles_in (const VTX* p) { return p->particles_in(); }
939 template <class VTX>
940 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
941
942 namespace Pythia8
943 {
945 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
946
947 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
948
949 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
950 }
951
952#include "AtlasPID.h"
953
955 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
956
958 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
959
961 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
962
964 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
965
967 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
968
970 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
971
973 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
974
976 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
977
979 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
980
982 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
983
987 template <class T> inline bool isStableOrSimDecayed(const T& p) {
988 const auto vertex = p->end_vertex();
989 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
990 }
991
993 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
994
996 template <class T> inline bool isSpecialNonInteracting(const T& p) {
997 const int apid = std::abs(p->pdg_id());
998 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
999 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1000 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1001 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1002 return false;
1003 }
1004
1006
1007 template <class T> T findMother(T thePart) {
1008 auto partOriVert = thePart->production_vertex();
1009 if (!partOriVert) return nullptr;
1010
1011 long partPDG = thePart->pdg_id();
1012 long MotherPDG(0);
1013
1014 auto MothOriVert = partOriVert;
1015 MothOriVert = nullptr;
1016 T theMoth(nullptr);
1017
1018 size_t itr = 0;
1019 do {
1020 if (itr != 0) partOriVert = MothOriVert;
1021 for ( const auto& p : particles_in(partOriVert) ) {
1022 theMoth = p;
1023 if (!theMoth) continue;
1024 MotherPDG = theMoth->pdg_id();
1025 MothOriVert = theMoth->production_vertex();
1026 if (MotherPDG == partPDG) break;
1027 }
1028 itr++;
1029 if (itr > 100) {
1030 break;
1031 }
1032 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1033 MothOriVert != partOriVert);
1034 return theMoth;
1035 }
1036
1038
1039 template <class C, class T> T findMatching(C TruthContainer, T p) {
1040 T ptrPart = nullptr;
1041 if (!p) return ptrPart;
1042 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1043 for (T truthParticle : *TruthContainer) {
1044 if (HepMC::is_sim_descendant(p,truthParticle)) {
1045 ptrPart = truthParticle;
1046 break;
1047 }
1048 }
1049 }
1050 else {
1051 for (T truthParticle : TruthContainer) {
1052 if (HepMC::is_sim_descendant(p,truthParticle)) {
1053 ptrPart = truthParticle;
1054 break;
1055 }
1056 }
1057 }
1058 return ptrPart;
1059 }
1061
1062 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1063 auto prodVtx = thePart->production_vertex();
1064 if (!prodVtx) return;
1065 for (const auto& theMother: prodVtx->particles_in()) {
1066 if (!theMother) continue;
1067 allancestors.insert(theMother);
1068 findParticleAncestors(theMother, allancestors);
1069 }
1070 }
1071
1073
1074 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1075 auto endVtx = thePart->end_vertex();
1076 if (!endVtx) return;
1077 for (const auto& theDaughter: endVtx->particles_out()) {
1078 if (!theDaughter) continue;
1079 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1080 allstabledescendants.insert(theDaughter);
1081 }
1082 findParticleStableDescendants(theDaughter, allstabledescendants);
1083 }
1084 }
1085
1089
1090 template <class T> bool isHardScatteringVertex(T pVert) {
1091 if (pVert == nullptr) return false;
1092 T pV = pVert;
1093 int numOfPartIn(0);
1094 int pdg(0);
1095
1096 do {
1097 pVert = pV;
1098 auto incoming = pVert->particles_in();
1099 numOfPartIn = incoming.size();
1100 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1101 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1102
1103 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1104
1105 if (numOfPartIn == 2) {
1106 auto incoming = pVert->particles_in();
1107 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1108 }
1109 return false;
1110}
1111
1115
1116 template <class T, class U>
1117 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1118 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1119 auto vtx = p->production_vertex();
1120 if (!vtx) return false;
1121 bool fromHad = false;
1122 for ( const auto& parent : particles_in(vtx) ) {
1123 if (!parent) continue;
1124 // should this really go into parton-level territory?
1125 // probably depends where BSM particles are being decayed
1126 fromBSM |= isBSM(parent);
1127 if (!isPhysical(parent)) return false;
1128 fromTau |= isTau(parent);
1129 if (isHadron(parent)&&!isBeam(parent)) {
1130 if (!hadron) hadron = parent; // assumes linear hadron parentage
1131 return true;
1132 }
1133 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1134 }
1135 return fromHad;
1136 }
1137
1140
1141 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1142 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1143 decltype(thePart->end_vertex()) pVert(nullptr);
1144 if (EndVert != nullptr) {
1145 do {
1146 bool samePart = false;
1147 pVert = nullptr;
1148 auto outgoing = EndVert->particles_out();
1149 auto incoming = EndVert->particles_in();
1150 for (const auto& itrDaug: outgoing) {
1151 if (!itrDaug) continue;
1152 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1153 // brem on generator level for tau
1154 (outgoing.size() == 1 && incoming.size() == 1 &&
1156 itrDaug->pdg_id() == thePart->pdg_id()) {
1157 samePart = true;
1158 pVert = itrDaug->end_vertex();
1159 }
1160 }
1161 if (samePart) EndVert = pVert;
1162 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1163 }
1164 return EndVert;
1165 }
1166
1168
1169 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1170 if (!theVert) return {};
1171 decltype(theVert->particles_out()) finalStatePart;
1172 auto outgoing = theVert->particles_out();
1173 for (const auto& thePart: outgoing) {
1174 if (!thePart) continue;
1175 finalStatePart.push_back(thePart);
1176 if (isStable(thePart)) continue;
1177 V pVert = findSimulatedEndVertex(thePart);
1178 if (pVert == theVert) break; // to prevent Sherpa loop
1179 if (pVert != nullptr) {
1180 auto vecPart = findFinalStateParticles<V>(pVert);
1181 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1182 }
1183 }
1184 return finalStatePart;
1185 }
1186#if !defined(XAOD_ANALYSIS)
1187#include "AtlasHepMC/GenEvent.h"
1188inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1189inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1190
1191#endif
1192}
1193#endif

◆ isHiddenValley() [1/3]

template<>
bool MC::isHiddenValley ( const DecodedPID & p)
inline

Definition at line 671 of file HepMCHelpers.h.

690{
691 template <class VTX>
692 auto particles_in (const VTX* p) { return p->particles_in(); }
693 template <class VTX>
694 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
695
696 namespace Pythia8
697 {
699 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
700
701 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
702
703 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
704 }
705
706#include "AtlasPID.h"
707
709 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
710
712 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
713
715 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
716
718 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
719
721 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
722
724 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
725
727 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
728
730 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
731
733 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
734
736 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
737
741 template <class T> inline bool isStableOrSimDecayed(const T& p) {
742 const auto vertex = p->end_vertex();
743 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
744 }
745
747 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
748
750 template <class T> inline bool isSpecialNonInteracting(const T& p) {
751 const int apid = std::abs(p->pdg_id());
752 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
753 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
754 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
755 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
756 return false;
757 }
758
760
761 template <class T> T findMother(T thePart) {
762 auto partOriVert = thePart->production_vertex();
763 if (!partOriVert) return nullptr;
764
765 long partPDG = thePart->pdg_id();
766 long MotherPDG(0);
767
768 auto MothOriVert = partOriVert;
769 MothOriVert = nullptr;
770 T theMoth(nullptr);
771
772 size_t itr = 0;
773 do {
774 if (itr != 0) partOriVert = MothOriVert;
775 for ( const auto& p : particles_in(partOriVert) ) {
776 theMoth = p;
777 if (!theMoth) continue;
778 MotherPDG = theMoth->pdg_id();
779 MothOriVert = theMoth->production_vertex();
780 if (MotherPDG == partPDG) break;
781 }
782 itr++;
783 if (itr > 100) {
784 break;
785 }
786 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
787 MothOriVert != partOriVert);
788 return theMoth;
789 }
790
792
793 template <class C, class T> T findMatching(C TruthContainer, T p) {
794 T ptrPart = nullptr;
795 if (!p) return ptrPart;
796 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
797 for (T truthParticle : *TruthContainer) {
798 if (HepMC::is_sim_descendant(p,truthParticle)) {
799 ptrPart = truthParticle;
800 break;
801 }
802 }
803 }
804 else {
805 for (T truthParticle : TruthContainer) {
806 if (HepMC::is_sim_descendant(p,truthParticle)) {
807 ptrPart = truthParticle;
808 break;
809 }
810 }
811 }
812 return ptrPart;
813 }
815
816 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
817 auto prodVtx = thePart->production_vertex();
818 if (!prodVtx) return;
819 for (const auto& theMother: prodVtx->particles_in()) {
820 if (!theMother) continue;
821 allancestors.insert(theMother);
822 findParticleAncestors(theMother, allancestors);
823 }
824 }
825
827
828 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
829 auto endVtx = thePart->end_vertex();
830 if (!endVtx) return;
831 for (const auto& theDaughter: endVtx->particles_out()) {
832 if (!theDaughter) continue;
833 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
834 allstabledescendants.insert(theDaughter);
835 }
836 findParticleStableDescendants(theDaughter, allstabledescendants);
837 }
838 }
839
843
844 template <class T> bool isHardScatteringVertex(T pVert) {
845 if (pVert == nullptr) return false;
846 T pV = pVert;
847 int numOfPartIn(0);
848 int pdg(0);
849
850 do {
851 pVert = pV;
852 auto incoming = pVert->particles_in();
853 numOfPartIn = incoming.size();
854 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
855 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
856
857 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
858
859 if (numOfPartIn == 2) {
860 auto incoming = pVert->particles_in();
861 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
862 }
863 return false;
864}
865
869
870 template <class T, class U>
871 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
872 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
873 auto vtx = p->production_vertex();
874 if (!vtx) return false;
875 bool fromHad = false;
876 for ( const auto& parent : particles_in(vtx) ) {
877 if (!parent) continue;
878 // should this really go into parton-level territory?
879 // probably depends where BSM particles are being decayed
880 fromBSM |= isBSM(parent);
881 if (!isPhysical(parent)) return false;
882 fromTau |= isTau(parent);
883 if (isHadron(parent)&&!isBeam(parent)) {
884 if (!hadron) hadron = parent; // assumes linear hadron parentage
885 return true;
886 }
887 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
888 }
889 return fromHad;
890 }
891
894
895 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
896 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
897 decltype(thePart->end_vertex()) pVert(nullptr);
898 if (EndVert != nullptr) {
899 do {
900 bool samePart = false;
901 pVert = nullptr;
902 auto outgoing = EndVert->particles_out();
903 auto incoming = EndVert->particles_in();
904 for (const auto& itrDaug: outgoing) {
905 if (!itrDaug) continue;
906 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
907 // brem on generator level for tau
908 (outgoing.size() == 1 && incoming.size() == 1 &&
910 itrDaug->pdg_id() == thePart->pdg_id()) {
911 samePart = true;
912 pVert = itrDaug->end_vertex();
913 }
914 }
915 if (samePart) EndVert = pVert;
916 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
917 }
918 return EndVert;
919 }
920
922
923 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
924 if (!theVert) return {};
925 decltype(theVert->particles_out()) finalStatePart;
926 auto outgoing = theVert->particles_out();
927 for (const auto& thePart: outgoing) {
928 if (!thePart) continue;
929 finalStatePart.push_back(thePart);
930 if (isStable(thePart)) continue;
931 V pVert = findSimulatedEndVertex(thePart);
932 if (pVert == theVert) break; // to prevent Sherpa loop
933 if (pVert != nullptr) {
934 auto vecPart = findFinalStateParticles<V>(pVert);
935 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
936 }
937 }
938 return finalStatePart;
939 }
940#if !defined(XAOD_ANALYSIS)
941#include "AtlasHepMC/GenEvent.h"
942inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
943inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
944
945#endif
946}
947#endif

◆ isHiddenValley() [2/3]

template<>
bool MC::isHiddenValley ( const int & p)
inline

Definition at line 677 of file HepMCHelpers.h.

696{
697 template <class VTX>
698 auto particles_in (const VTX* p) { return p->particles_in(); }
699 template <class VTX>
700 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
701
702 namespace Pythia8
703 {
705 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
706
707 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
708
709 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
710 }
711
712#include "AtlasPID.h"
713
715 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
716
718 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
719
721 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
722
724 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
725
727 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
728
730 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
731
733 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
734
736 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
737
739 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
740
742 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
743
747 template <class T> inline bool isStableOrSimDecayed(const T& p) {
748 const auto vertex = p->end_vertex();
749 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
750 }
751
753 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
754
756 template <class T> inline bool isSpecialNonInteracting(const T& p) {
757 const int apid = std::abs(p->pdg_id());
758 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
759 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
760 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
761 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
762 return false;
763 }
764
766
767 template <class T> T findMother(T thePart) {
768 auto partOriVert = thePart->production_vertex();
769 if (!partOriVert) return nullptr;
770
771 long partPDG = thePart->pdg_id();
772 long MotherPDG(0);
773
774 auto MothOriVert = partOriVert;
775 MothOriVert = nullptr;
776 T theMoth(nullptr);
777
778 size_t itr = 0;
779 do {
780 if (itr != 0) partOriVert = MothOriVert;
781 for ( const auto& p : particles_in(partOriVert) ) {
782 theMoth = p;
783 if (!theMoth) continue;
784 MotherPDG = theMoth->pdg_id();
785 MothOriVert = theMoth->production_vertex();
786 if (MotherPDG == partPDG) break;
787 }
788 itr++;
789 if (itr > 100) {
790 break;
791 }
792 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
793 MothOriVert != partOriVert);
794 return theMoth;
795 }
796
798
799 template <class C, class T> T findMatching(C TruthContainer, T p) {
800 T ptrPart = nullptr;
801 if (!p) return ptrPart;
802 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
803 for (T truthParticle : *TruthContainer) {
804 if (HepMC::is_sim_descendant(p,truthParticle)) {
805 ptrPart = truthParticle;
806 break;
807 }
808 }
809 }
810 else {
811 for (T truthParticle : TruthContainer) {
812 if (HepMC::is_sim_descendant(p,truthParticle)) {
813 ptrPart = truthParticle;
814 break;
815 }
816 }
817 }
818 return ptrPart;
819 }
821
822 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
823 auto prodVtx = thePart->production_vertex();
824 if (!prodVtx) return;
825 for (const auto& theMother: prodVtx->particles_in()) {
826 if (!theMother) continue;
827 allancestors.insert(theMother);
828 findParticleAncestors(theMother, allancestors);
829 }
830 }
831
833
834 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
835 auto endVtx = thePart->end_vertex();
836 if (!endVtx) return;
837 for (const auto& theDaughter: endVtx->particles_out()) {
838 if (!theDaughter) continue;
839 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
840 allstabledescendants.insert(theDaughter);
841 }
842 findParticleStableDescendants(theDaughter, allstabledescendants);
843 }
844 }
845
849
850 template <class T> bool isHardScatteringVertex(T pVert) {
851 if (pVert == nullptr) return false;
852 T pV = pVert;
853 int numOfPartIn(0);
854 int pdg(0);
855
856 do {
857 pVert = pV;
858 auto incoming = pVert->particles_in();
859 numOfPartIn = incoming.size();
860 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
861 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
862
863 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
864
865 if (numOfPartIn == 2) {
866 auto incoming = pVert->particles_in();
867 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
868 }
869 return false;
870}
871
875
876 template <class T, class U>
877 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
878 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
879 auto vtx = p->production_vertex();
880 if (!vtx) return false;
881 bool fromHad = false;
882 for ( const auto& parent : particles_in(vtx) ) {
883 if (!parent) continue;
884 // should this really go into parton-level territory?
885 // probably depends where BSM particles are being decayed
886 fromBSM |= isBSM(parent);
887 if (!isPhysical(parent)) return false;
888 fromTau |= isTau(parent);
889 if (isHadron(parent)&&!isBeam(parent)) {
890 if (!hadron) hadron = parent; // assumes linear hadron parentage
891 return true;
892 }
893 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
894 }
895 return fromHad;
896 }
897
900
901 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
902 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
903 decltype(thePart->end_vertex()) pVert(nullptr);
904 if (EndVert != nullptr) {
905 do {
906 bool samePart = false;
907 pVert = nullptr;
908 auto outgoing = EndVert->particles_out();
909 auto incoming = EndVert->particles_in();
910 for (const auto& itrDaug: outgoing) {
911 if (!itrDaug) continue;
912 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
913 // brem on generator level for tau
914 (outgoing.size() == 1 && incoming.size() == 1 &&
916 itrDaug->pdg_id() == thePart->pdg_id()) {
917 samePart = true;
918 pVert = itrDaug->end_vertex();
919 }
920 }
921 if (samePart) EndVert = pVert;
922 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
923 }
924 return EndVert;
925 }
926
928
929 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
930 if (!theVert) return {};
931 decltype(theVert->particles_out()) finalStatePart;
932 auto outgoing = theVert->particles_out();
933 for (const auto& thePart: outgoing) {
934 if (!thePart) continue;
935 finalStatePart.push_back(thePart);
936 if (isStable(thePart)) continue;
937 V pVert = findSimulatedEndVertex(thePart);
938 if (pVert == theVert) break; // to prevent Sherpa loop
939 if (pVert != nullptr) {
940 auto vecPart = findFinalStateParticles<V>(pVert);
941 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
942 }
943 }
944 return finalStatePart;
945 }
946#if !defined(XAOD_ANALYSIS)
947#include "AtlasHepMC/GenEvent.h"
948inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
949inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
950
951#endif
952}
953#endif

◆ isHiddenValley() [3/3]

template<class T>
bool MC::isHiddenValley ( const T & p)
inline

PDG rule 11k Hidden Valley particles have n = 4 and n_r = 9, and trailing numbers in agreement with their nearest-analog standard particles, as far as possible.

Thus 4900021 is the gauge boson g_v of a confining gauge field, 490000n_{q_v} and 490001n_{l_v} fundamental constituents charged or not under this, 4900022 is the γ_v of a non-confining field, and 4900n_{q_{v1}}n_{q_{v2}}n_J a Hidden Valley meson.

Definition at line 669 of file HepMCHelpers.h.

688{
689 template <class VTX>
690 auto particles_in (const VTX* p) { return p->particles_in(); }
691 template <class VTX>
692 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
693
694 namespace Pythia8
695 {
697 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
698
699 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
700
701 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
702 }
703
704#include "AtlasPID.h"
705
707 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
708
710 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
711
713 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
714
716 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
717
719 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
720
722 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
723
725 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
726
728 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
729
731 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
732
734 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
735
739 template <class T> inline bool isStableOrSimDecayed(const T& p) {
740 const auto vertex = p->end_vertex();
741 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
742 }
743
745 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
746
748 template <class T> inline bool isSpecialNonInteracting(const T& p) {
749 const int apid = std::abs(p->pdg_id());
750 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
751 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
752 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
753 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
754 return false;
755 }
756
758
759 template <class T> T findMother(T thePart) {
760 auto partOriVert = thePart->production_vertex();
761 if (!partOriVert) return nullptr;
762
763 long partPDG = thePart->pdg_id();
764 long MotherPDG(0);
765
766 auto MothOriVert = partOriVert;
767 MothOriVert = nullptr;
768 T theMoth(nullptr);
769
770 size_t itr = 0;
771 do {
772 if (itr != 0) partOriVert = MothOriVert;
773 for ( const auto& p : particles_in(partOriVert) ) {
774 theMoth = p;
775 if (!theMoth) continue;
776 MotherPDG = theMoth->pdg_id();
777 MothOriVert = theMoth->production_vertex();
778 if (MotherPDG == partPDG) break;
779 }
780 itr++;
781 if (itr > 100) {
782 break;
783 }
784 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
785 MothOriVert != partOriVert);
786 return theMoth;
787 }
788
790
791 template <class C, class T> T findMatching(C TruthContainer, T p) {
792 T ptrPart = nullptr;
793 if (!p) return ptrPart;
794 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
795 for (T truthParticle : *TruthContainer) {
796 if (HepMC::is_sim_descendant(p,truthParticle)) {
797 ptrPart = truthParticle;
798 break;
799 }
800 }
801 }
802 else {
803 for (T truthParticle : TruthContainer) {
804 if (HepMC::is_sim_descendant(p,truthParticle)) {
805 ptrPart = truthParticle;
806 break;
807 }
808 }
809 }
810 return ptrPart;
811 }
813
814 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
815 auto prodVtx = thePart->production_vertex();
816 if (!prodVtx) return;
817 for (const auto& theMother: prodVtx->particles_in()) {
818 if (!theMother) continue;
819 allancestors.insert(theMother);
820 findParticleAncestors(theMother, allancestors);
821 }
822 }
823
825
826 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
827 auto endVtx = thePart->end_vertex();
828 if (!endVtx) return;
829 for (const auto& theDaughter: endVtx->particles_out()) {
830 if (!theDaughter) continue;
831 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
832 allstabledescendants.insert(theDaughter);
833 }
834 findParticleStableDescendants(theDaughter, allstabledescendants);
835 }
836 }
837
841
842 template <class T> bool isHardScatteringVertex(T pVert) {
843 if (pVert == nullptr) return false;
844 T pV = pVert;
845 int numOfPartIn(0);
846 int pdg(0);
847
848 do {
849 pVert = pV;
850 auto incoming = pVert->particles_in();
851 numOfPartIn = incoming.size();
852 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
853 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
854
855 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
856
857 if (numOfPartIn == 2) {
858 auto incoming = pVert->particles_in();
859 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
860 }
861 return false;
862}
863
867
868 template <class T, class U>
869 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
870 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
871 auto vtx = p->production_vertex();
872 if (!vtx) return false;
873 bool fromHad = false;
874 for ( const auto& parent : particles_in(vtx) ) {
875 if (!parent) continue;
876 // should this really go into parton-level territory?
877 // probably depends where BSM particles are being decayed
878 fromBSM |= isBSM(parent);
879 if (!isPhysical(parent)) return false;
880 fromTau |= isTau(parent);
881 if (isHadron(parent)&&!isBeam(parent)) {
882 if (!hadron) hadron = parent; // assumes linear hadron parentage
883 return true;
884 }
885 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
886 }
887 return fromHad;
888 }
889
892
893 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
894 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
895 decltype(thePart->end_vertex()) pVert(nullptr);
896 if (EndVert != nullptr) {
897 do {
898 bool samePart = false;
899 pVert = nullptr;
900 auto outgoing = EndVert->particles_out();
901 auto incoming = EndVert->particles_in();
902 for (const auto& itrDaug: outgoing) {
903 if (!itrDaug) continue;
904 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
905 // brem on generator level for tau
906 (outgoing.size() == 1 && incoming.size() == 1 &&
908 itrDaug->pdg_id() == thePart->pdg_id()) {
909 samePart = true;
910 pVert = itrDaug->end_vertex();
911 }
912 }
913 if (samePart) EndVert = pVert;
914 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
915 }
916 return EndVert;
917 }
918
920
921 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
922 if (!theVert) return {};
923 decltype(theVert->particles_out()) finalStatePart;
924 auto outgoing = theVert->particles_out();
925 for (const auto& thePart: outgoing) {
926 if (!thePart) continue;
927 finalStatePart.push_back(thePart);
928 if (isStable(thePart)) continue;
929 V pVert = findSimulatedEndVertex(thePart);
930 if (pVert == theVert) break; // to prevent Sherpa loop
931 if (pVert != nullptr) {
932 auto vecPart = findFinalStateParticles<V>(pVert);
933 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
934 }
935 }
936 return finalStatePart;
937 }
938#if !defined(XAOD_ANALYSIS)
939#include "AtlasHepMC/GenEvent.h"
940inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
941inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
942
943#endif
944}
945#endif

◆ isHiggs() [1/2]

template<>
bool MC::isHiggs ( const int & p)
inline

Definition at line 392 of file HepMCHelpers.h.

411{
412 template <class VTX>
413 auto particles_in (const VTX* p) { return p->particles_in(); }
414 template <class VTX>
415 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
416
417 namespace Pythia8
418 {
420 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
421
422 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
423
424 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
425 }
426
427#include "AtlasPID.h"
428
430 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
431
433 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
434
436 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
437
439 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
440
442 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
443
445 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
446
448 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
449
451 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
452
454 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
455
457 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
458
462 template <class T> inline bool isStableOrSimDecayed(const T& p) {
463 const auto vertex = p->end_vertex();
464 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
465 }
466
468 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
469
471 template <class T> inline bool isSpecialNonInteracting(const T& p) {
472 const int apid = std::abs(p->pdg_id());
473 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
474 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
475 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
476 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
477 return false;
478 }
479
481
482 template <class T> T findMother(T thePart) {
483 auto partOriVert = thePart->production_vertex();
484 if (!partOriVert) return nullptr;
485
486 long partPDG = thePart->pdg_id();
487 long MotherPDG(0);
488
489 auto MothOriVert = partOriVert;
490 MothOriVert = nullptr;
491 T theMoth(nullptr);
492
493 size_t itr = 0;
494 do {
495 if (itr != 0) partOriVert = MothOriVert;
496 for ( const auto& p : particles_in(partOriVert) ) {
497 theMoth = p;
498 if (!theMoth) continue;
499 MotherPDG = theMoth->pdg_id();
500 MothOriVert = theMoth->production_vertex();
501 if (MotherPDG == partPDG) break;
502 }
503 itr++;
504 if (itr > 100) {
505 break;
506 }
507 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
508 MothOriVert != partOriVert);
509 return theMoth;
510 }
511
513
514 template <class C, class T> T findMatching(C TruthContainer, T p) {
515 T ptrPart = nullptr;
516 if (!p) return ptrPart;
517 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
518 for (T truthParticle : *TruthContainer) {
519 if (HepMC::is_sim_descendant(p,truthParticle)) {
520 ptrPart = truthParticle;
521 break;
522 }
523 }
524 }
525 else {
526 for (T truthParticle : TruthContainer) {
527 if (HepMC::is_sim_descendant(p,truthParticle)) {
528 ptrPart = truthParticle;
529 break;
530 }
531 }
532 }
533 return ptrPart;
534 }
536
537 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
538 auto prodVtx = thePart->production_vertex();
539 if (!prodVtx) return;
540 for (const auto& theMother: prodVtx->particles_in()) {
541 if (!theMother) continue;
542 allancestors.insert(theMother);
543 findParticleAncestors(theMother, allancestors);
544 }
545 }
546
548
549 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
550 auto endVtx = thePart->end_vertex();
551 if (!endVtx) return;
552 for (const auto& theDaughter: endVtx->particles_out()) {
553 if (!theDaughter) continue;
554 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
555 allstabledescendants.insert(theDaughter);
556 }
557 findParticleStableDescendants(theDaughter, allstabledescendants);
558 }
559 }
560
564
565 template <class T> bool isHardScatteringVertex(T pVert) {
566 if (pVert == nullptr) return false;
567 T pV = pVert;
568 int numOfPartIn(0);
569 int pdg(0);
570
571 do {
572 pVert = pV;
573 auto incoming = pVert->particles_in();
574 numOfPartIn = incoming.size();
575 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
576 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
577
578 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
579
580 if (numOfPartIn == 2) {
581 auto incoming = pVert->particles_in();
582 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
583 }
584 return false;
585}
586
590
591 template <class T, class U>
592 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
593 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
594 auto vtx = p->production_vertex();
595 if (!vtx) return false;
596 bool fromHad = false;
597 for ( const auto& parent : particles_in(vtx) ) {
598 if (!parent) continue;
599 // should this really go into parton-level territory?
600 // probably depends where BSM particles are being decayed
601 fromBSM |= isBSM(parent);
602 if (!isPhysical(parent)) return false;
603 fromTau |= isTau(parent);
604 if (isHadron(parent)&&!isBeam(parent)) {
605 if (!hadron) hadron = parent; // assumes linear hadron parentage
606 return true;
607 }
608 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
609 }
610 return fromHad;
611 }
612
615
616 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
617 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
618 decltype(thePart->end_vertex()) pVert(nullptr);
619 if (EndVert != nullptr) {
620 do {
621 bool samePart = false;
622 pVert = nullptr;
623 auto outgoing = EndVert->particles_out();
624 auto incoming = EndVert->particles_in();
625 for (const auto& itrDaug: outgoing) {
626 if (!itrDaug) continue;
627 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
628 // brem on generator level for tau
629 (outgoing.size() == 1 && incoming.size() == 1 &&
631 itrDaug->pdg_id() == thePart->pdg_id()) {
632 samePart = true;
633 pVert = itrDaug->end_vertex();
634 }
635 }
636 if (samePart) EndVert = pVert;
637 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
638 }
639 return EndVert;
640 }
641
643
644 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
645 if (!theVert) return {};
646 decltype(theVert->particles_out()) finalStatePart;
647 auto outgoing = theVert->particles_out();
648 for (const auto& thePart: outgoing) {
649 if (!thePart) continue;
650 finalStatePart.push_back(thePart);
651 if (isStable(thePart)) continue;
652 V pVert = findSimulatedEndVertex(thePart);
653 if (pVert == theVert) break; // to prevent Sherpa loop
654 if (pVert != nullptr) {
655 auto vecPart = findFinalStateParticles<V>(pVert);
656 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
657 }
658 }
659 return finalStatePart;
660 }
661#if !defined(XAOD_ANALYSIS)
662#include "AtlasHepMC/GenEvent.h"
663inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
664inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
665
666#endif
667}
668#endif

◆ isHiggs() [2/2]

template<class T>
bool MC::isHiggs ( const T & p)
inline

APID: HIGGS boson is only one particle.

Definition at line 391 of file HepMCHelpers.h.

410{
411 template <class VTX>
412 auto particles_in (const VTX* p) { return p->particles_in(); }
413 template <class VTX>
414 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
415
416 namespace Pythia8
417 {
419 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
420
421 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
422
423 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
424 }
425
426#include "AtlasPID.h"
427
429 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
430
432 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
433
435 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
436
438 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
439
441 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
442
444 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
445
447 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
448
450 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
451
453 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
454
456 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
457
461 template <class T> inline bool isStableOrSimDecayed(const T& p) {
462 const auto vertex = p->end_vertex();
463 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
464 }
465
467 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
468
470 template <class T> inline bool isSpecialNonInteracting(const T& p) {
471 const int apid = std::abs(p->pdg_id());
472 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
473 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
474 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
475 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
476 return false;
477 }
478
480
481 template <class T> T findMother(T thePart) {
482 auto partOriVert = thePart->production_vertex();
483 if (!partOriVert) return nullptr;
484
485 long partPDG = thePart->pdg_id();
486 long MotherPDG(0);
487
488 auto MothOriVert = partOriVert;
489 MothOriVert = nullptr;
490 T theMoth(nullptr);
491
492 size_t itr = 0;
493 do {
494 if (itr != 0) partOriVert = MothOriVert;
495 for ( const auto& p : particles_in(partOriVert) ) {
496 theMoth = p;
497 if (!theMoth) continue;
498 MotherPDG = theMoth->pdg_id();
499 MothOriVert = theMoth->production_vertex();
500 if (MotherPDG == partPDG) break;
501 }
502 itr++;
503 if (itr > 100) {
504 break;
505 }
506 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
507 MothOriVert != partOriVert);
508 return theMoth;
509 }
510
512
513 template <class C, class T> T findMatching(C TruthContainer, T p) {
514 T ptrPart = nullptr;
515 if (!p) return ptrPart;
516 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
517 for (T truthParticle : *TruthContainer) {
518 if (HepMC::is_sim_descendant(p,truthParticle)) {
519 ptrPart = truthParticle;
520 break;
521 }
522 }
523 }
524 else {
525 for (T truthParticle : TruthContainer) {
526 if (HepMC::is_sim_descendant(p,truthParticle)) {
527 ptrPart = truthParticle;
528 break;
529 }
530 }
531 }
532 return ptrPart;
533 }
535
536 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
537 auto prodVtx = thePart->production_vertex();
538 if (!prodVtx) return;
539 for (const auto& theMother: prodVtx->particles_in()) {
540 if (!theMother) continue;
541 allancestors.insert(theMother);
542 findParticleAncestors(theMother, allancestors);
543 }
544 }
545
547
548 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
549 auto endVtx = thePart->end_vertex();
550 if (!endVtx) return;
551 for (const auto& theDaughter: endVtx->particles_out()) {
552 if (!theDaughter) continue;
553 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
554 allstabledescendants.insert(theDaughter);
555 }
556 findParticleStableDescendants(theDaughter, allstabledescendants);
557 }
558 }
559
563
564 template <class T> bool isHardScatteringVertex(T pVert) {
565 if (pVert == nullptr) return false;
566 T pV = pVert;
567 int numOfPartIn(0);
568 int pdg(0);
569
570 do {
571 pVert = pV;
572 auto incoming = pVert->particles_in();
573 numOfPartIn = incoming.size();
574 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
575 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
576
577 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
578
579 if (numOfPartIn == 2) {
580 auto incoming = pVert->particles_in();
581 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
582 }
583 return false;
584}
585
589
590 template <class T, class U>
591 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
592 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
593 auto vtx = p->production_vertex();
594 if (!vtx) return false;
595 bool fromHad = false;
596 for ( const auto& parent : particles_in(vtx) ) {
597 if (!parent) continue;
598 // should this really go into parton-level territory?
599 // probably depends where BSM particles are being decayed
600 fromBSM |= isBSM(parent);
601 if (!isPhysical(parent)) return false;
602 fromTau |= isTau(parent);
603 if (isHadron(parent)&&!isBeam(parent)) {
604 if (!hadron) hadron = parent; // assumes linear hadron parentage
605 return true;
606 }
607 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
608 }
609 return fromHad;
610 }
611
614
615 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
616 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
617 decltype(thePart->end_vertex()) pVert(nullptr);
618 if (EndVert != nullptr) {
619 do {
620 bool samePart = false;
621 pVert = nullptr;
622 auto outgoing = EndVert->particles_out();
623 auto incoming = EndVert->particles_in();
624 for (const auto& itrDaug: outgoing) {
625 if (!itrDaug) continue;
626 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
627 // brem on generator level for tau
628 (outgoing.size() == 1 && incoming.size() == 1 &&
630 itrDaug->pdg_id() == thePart->pdg_id()) {
631 samePart = true;
632 pVert = itrDaug->end_vertex();
633 }
634 }
635 if (samePart) EndVert = pVert;
636 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
637 }
638 return EndVert;
639 }
640
642
643 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
644 if (!theVert) return {};
645 decltype(theVert->particles_out()) finalStatePart;
646 auto outgoing = theVert->particles_out();
647 for (const auto& thePart: outgoing) {
648 if (!thePart) continue;
649 finalStatePart.push_back(thePart);
650 if (isStable(thePart)) continue;
651 V pVert = findSimulatedEndVertex(thePart);
652 if (pVert == theVert) break; // to prevent Sherpa loop
653 if (pVert != nullptr) {
654 auto vecPart = findFinalStateParticles<V>(pVert);
655 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
656 }
657 }
658 return finalStatePart;
659 }
660#if !defined(XAOD_ANALYSIS)
661#include "AtlasHepMC/GenEvent.h"
662inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
663inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
664
665#endif
666}
667#endif

◆ isInteracting()

template<class T>
bool MC::isInteracting ( const T & p)
inline

Identify if the particle with given PDG ID would not interact with the detector, i.e. not a neutrino or WIMP.

Definition at line 39 of file HepMCHelpers.h.

◆ isKK() [1/3]

template<>
bool MC::isKK ( const DecodedPID & p)
inline

Definition at line 637 of file HepMCHelpers.h.

656{
657 template <class VTX>
658 auto particles_in (const VTX* p) { return p->particles_in(); }
659 template <class VTX>
660 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
661
662 namespace Pythia8
663 {
665 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
666
667 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
668
669 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
670 }
671
672#include "AtlasPID.h"
673
675 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
676
678 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
679
681 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
682
684 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
685
687 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
688
690 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
691
693 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
694
696 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
697
699 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
700
702 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
703
707 template <class T> inline bool isStableOrSimDecayed(const T& p) {
708 const auto vertex = p->end_vertex();
709 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
710 }
711
713 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
714
716 template <class T> inline bool isSpecialNonInteracting(const T& p) {
717 const int apid = std::abs(p->pdg_id());
718 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
719 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
720 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
721 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
722 return false;
723 }
724
726
727 template <class T> T findMother(T thePart) {
728 auto partOriVert = thePart->production_vertex();
729 if (!partOriVert) return nullptr;
730
731 long partPDG = thePart->pdg_id();
732 long MotherPDG(0);
733
734 auto MothOriVert = partOriVert;
735 MothOriVert = nullptr;
736 T theMoth(nullptr);
737
738 size_t itr = 0;
739 do {
740 if (itr != 0) partOriVert = MothOriVert;
741 for ( const auto& p : particles_in(partOriVert) ) {
742 theMoth = p;
743 if (!theMoth) continue;
744 MotherPDG = theMoth->pdg_id();
745 MothOriVert = theMoth->production_vertex();
746 if (MotherPDG == partPDG) break;
747 }
748 itr++;
749 if (itr > 100) {
750 break;
751 }
752 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
753 MothOriVert != partOriVert);
754 return theMoth;
755 }
756
758
759 template <class C, class T> T findMatching(C TruthContainer, T p) {
760 T ptrPart = nullptr;
761 if (!p) return ptrPart;
762 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
763 for (T truthParticle : *TruthContainer) {
764 if (HepMC::is_sim_descendant(p,truthParticle)) {
765 ptrPart = truthParticle;
766 break;
767 }
768 }
769 }
770 else {
771 for (T truthParticle : TruthContainer) {
772 if (HepMC::is_sim_descendant(p,truthParticle)) {
773 ptrPart = truthParticle;
774 break;
775 }
776 }
777 }
778 return ptrPart;
779 }
781
782 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
783 auto prodVtx = thePart->production_vertex();
784 if (!prodVtx) return;
785 for (const auto& theMother: prodVtx->particles_in()) {
786 if (!theMother) continue;
787 allancestors.insert(theMother);
788 findParticleAncestors(theMother, allancestors);
789 }
790 }
791
793
794 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
795 auto endVtx = thePart->end_vertex();
796 if (!endVtx) return;
797 for (const auto& theDaughter: endVtx->particles_out()) {
798 if (!theDaughter) continue;
799 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
800 allstabledescendants.insert(theDaughter);
801 }
802 findParticleStableDescendants(theDaughter, allstabledescendants);
803 }
804 }
805
809
810 template <class T> bool isHardScatteringVertex(T pVert) {
811 if (pVert == nullptr) return false;
812 T pV = pVert;
813 int numOfPartIn(0);
814 int pdg(0);
815
816 do {
817 pVert = pV;
818 auto incoming = pVert->particles_in();
819 numOfPartIn = incoming.size();
820 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
821 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
822
823 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
824
825 if (numOfPartIn == 2) {
826 auto incoming = pVert->particles_in();
827 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
828 }
829 return false;
830}
831
835
836 template <class T, class U>
837 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
838 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
839 auto vtx = p->production_vertex();
840 if (!vtx) return false;
841 bool fromHad = false;
842 for ( const auto& parent : particles_in(vtx) ) {
843 if (!parent) continue;
844 // should this really go into parton-level territory?
845 // probably depends where BSM particles are being decayed
846 fromBSM |= isBSM(parent);
847 if (!isPhysical(parent)) return false;
848 fromTau |= isTau(parent);
849 if (isHadron(parent)&&!isBeam(parent)) {
850 if (!hadron) hadron = parent; // assumes linear hadron parentage
851 return true;
852 }
853 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
854 }
855 return fromHad;
856 }
857
860
861 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
862 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
863 decltype(thePart->end_vertex()) pVert(nullptr);
864 if (EndVert != nullptr) {
865 do {
866 bool samePart = false;
867 pVert = nullptr;
868 auto outgoing = EndVert->particles_out();
869 auto incoming = EndVert->particles_in();
870 for (const auto& itrDaug: outgoing) {
871 if (!itrDaug) continue;
872 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
873 // brem on generator level for tau
874 (outgoing.size() == 1 && incoming.size() == 1 &&
876 itrDaug->pdg_id() == thePart->pdg_id()) {
877 samePart = true;
878 pVert = itrDaug->end_vertex();
879 }
880 }
881 if (samePart) EndVert = pVert;
882 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
883 }
884 return EndVert;
885 }
886
888
889 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
890 if (!theVert) return {};
891 decltype(theVert->particles_out()) finalStatePart;
892 auto outgoing = theVert->particles_out();
893 for (const auto& thePart: outgoing) {
894 if (!thePart) continue;
895 finalStatePart.push_back(thePart);
896 if (isStable(thePart)) continue;
897 V pVert = findSimulatedEndVertex(thePart);
898 if (pVert == theVert) break; // to prevent Sherpa loop
899 if (pVert != nullptr) {
900 auto vecPart = findFinalStateParticles<V>(pVert);
901 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
902 }
903 }
904 return finalStatePart;
905 }
906#if !defined(XAOD_ANALYSIS)
907#include "AtlasHepMC/GenEvent.h"
908inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
909inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
910
911#endif
912}
913#endif

◆ isKK() [2/3]

template<>
bool MC::isKK ( const int & p)
inline

Definition at line 638 of file HepMCHelpers.h.

657{
658 template <class VTX>
659 auto particles_in (const VTX* p) { return p->particles_in(); }
660 template <class VTX>
661 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
662
663 namespace Pythia8
664 {
666 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
667
668 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
669
670 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
671 }
672
673#include "AtlasPID.h"
674
676 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
677
679 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
680
682 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
683
685 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
686
688 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
689
691 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
692
694 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
695
697 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
698
700 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
701
703 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
704
708 template <class T> inline bool isStableOrSimDecayed(const T& p) {
709 const auto vertex = p->end_vertex();
710 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
711 }
712
714 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
715
717 template <class T> inline bool isSpecialNonInteracting(const T& p) {
718 const int apid = std::abs(p->pdg_id());
719 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
720 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
721 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
722 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
723 return false;
724 }
725
727
728 template <class T> T findMother(T thePart) {
729 auto partOriVert = thePart->production_vertex();
730 if (!partOriVert) return nullptr;
731
732 long partPDG = thePart->pdg_id();
733 long MotherPDG(0);
734
735 auto MothOriVert = partOriVert;
736 MothOriVert = nullptr;
737 T theMoth(nullptr);
738
739 size_t itr = 0;
740 do {
741 if (itr != 0) partOriVert = MothOriVert;
742 for ( const auto& p : particles_in(partOriVert) ) {
743 theMoth = p;
744 if (!theMoth) continue;
745 MotherPDG = theMoth->pdg_id();
746 MothOriVert = theMoth->production_vertex();
747 if (MotherPDG == partPDG) break;
748 }
749 itr++;
750 if (itr > 100) {
751 break;
752 }
753 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
754 MothOriVert != partOriVert);
755 return theMoth;
756 }
757
759
760 template <class C, class T> T findMatching(C TruthContainer, T p) {
761 T ptrPart = nullptr;
762 if (!p) return ptrPart;
763 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
764 for (T truthParticle : *TruthContainer) {
765 if (HepMC::is_sim_descendant(p,truthParticle)) {
766 ptrPart = truthParticle;
767 break;
768 }
769 }
770 }
771 else {
772 for (T truthParticle : TruthContainer) {
773 if (HepMC::is_sim_descendant(p,truthParticle)) {
774 ptrPart = truthParticle;
775 break;
776 }
777 }
778 }
779 return ptrPart;
780 }
782
783 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
784 auto prodVtx = thePart->production_vertex();
785 if (!prodVtx) return;
786 for (const auto& theMother: prodVtx->particles_in()) {
787 if (!theMother) continue;
788 allancestors.insert(theMother);
789 findParticleAncestors(theMother, allancestors);
790 }
791 }
792
794
795 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
796 auto endVtx = thePart->end_vertex();
797 if (!endVtx) return;
798 for (const auto& theDaughter: endVtx->particles_out()) {
799 if (!theDaughter) continue;
800 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
801 allstabledescendants.insert(theDaughter);
802 }
803 findParticleStableDescendants(theDaughter, allstabledescendants);
804 }
805 }
806
810
811 template <class T> bool isHardScatteringVertex(T pVert) {
812 if (pVert == nullptr) return false;
813 T pV = pVert;
814 int numOfPartIn(0);
815 int pdg(0);
816
817 do {
818 pVert = pV;
819 auto incoming = pVert->particles_in();
820 numOfPartIn = incoming.size();
821 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
822 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
823
824 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
825
826 if (numOfPartIn == 2) {
827 auto incoming = pVert->particles_in();
828 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
829 }
830 return false;
831}
832
836
837 template <class T, class U>
838 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
839 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
840 auto vtx = p->production_vertex();
841 if (!vtx) return false;
842 bool fromHad = false;
843 for ( const auto& parent : particles_in(vtx) ) {
844 if (!parent) continue;
845 // should this really go into parton-level territory?
846 // probably depends where BSM particles are being decayed
847 fromBSM |= isBSM(parent);
848 if (!isPhysical(parent)) return false;
849 fromTau |= isTau(parent);
850 if (isHadron(parent)&&!isBeam(parent)) {
851 if (!hadron) hadron = parent; // assumes linear hadron parentage
852 return true;
853 }
854 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
855 }
856 return fromHad;
857 }
858
861
862 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
863 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
864 decltype(thePart->end_vertex()) pVert(nullptr);
865 if (EndVert != nullptr) {
866 do {
867 bool samePart = false;
868 pVert = nullptr;
869 auto outgoing = EndVert->particles_out();
870 auto incoming = EndVert->particles_in();
871 for (const auto& itrDaug: outgoing) {
872 if (!itrDaug) continue;
873 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
874 // brem on generator level for tau
875 (outgoing.size() == 1 && incoming.size() == 1 &&
877 itrDaug->pdg_id() == thePart->pdg_id()) {
878 samePart = true;
879 pVert = itrDaug->end_vertex();
880 }
881 }
882 if (samePart) EndVert = pVert;
883 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
884 }
885 return EndVert;
886 }
887
889
890 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
891 if (!theVert) return {};
892 decltype(theVert->particles_out()) finalStatePart;
893 auto outgoing = theVert->particles_out();
894 for (const auto& thePart: outgoing) {
895 if (!thePart) continue;
896 finalStatePart.push_back(thePart);
897 if (isStable(thePart)) continue;
898 V pVert = findSimulatedEndVertex(thePart);
899 if (pVert == theVert) break; // to prevent Sherpa loop
900 if (pVert != nullptr) {
901 auto vecPart = findFinalStateParticles<V>(pVert);
902 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
903 }
904 }
905 return finalStatePart;
906 }
907#if !defined(XAOD_ANALYSIS)
908#include "AtlasHepMC/GenEvent.h"
909inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
910inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
911
912#endif
913}
914#endif

◆ isKK() [3/3]

template<class T>
bool MC::isKK ( const T & p)
inline

PDG rule 11h A black hole in models with extra dimensions has code 5000040.

Kaluza-Klein excitations in models with extra dimensions have n = 5 or n = 6, to distinguish excitations of left-or right-handed fermions or, in case of mixing, the lighter or heavier state (cf. 11d). The non zero nr digit gives the radial excitation number, in scenarios where the level spacing allows these to be distinguished. Should the model also contain supersymmetry, excited SUSY states would be denoted by a nn_r > 0, with n = 1 or 2 as usual. Should some colored states be long-lived enough that hadrons would form around them, the coding strategy of 11g applies, with the initial two nnr digits preserved in the combined code.

Definition at line 636 of file HepMCHelpers.h.

655{
656 template <class VTX>
657 auto particles_in (const VTX* p) { return p->particles_in(); }
658 template <class VTX>
659 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
660
661 namespace Pythia8
662 {
664 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
665
666 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
667
668 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
669 }
670
671#include "AtlasPID.h"
672
674 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
675
677 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
678
680 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
681
683 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
684
686 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
687
689 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
690
692 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
693
695 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
696
698 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
699
701 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
702
706 template <class T> inline bool isStableOrSimDecayed(const T& p) {
707 const auto vertex = p->end_vertex();
708 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
709 }
710
712 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
713
715 template <class T> inline bool isSpecialNonInteracting(const T& p) {
716 const int apid = std::abs(p->pdg_id());
717 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
718 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
719 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
720 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
721 return false;
722 }
723
725
726 template <class T> T findMother(T thePart) {
727 auto partOriVert = thePart->production_vertex();
728 if (!partOriVert) return nullptr;
729
730 long partPDG = thePart->pdg_id();
731 long MotherPDG(0);
732
733 auto MothOriVert = partOriVert;
734 MothOriVert = nullptr;
735 T theMoth(nullptr);
736
737 size_t itr = 0;
738 do {
739 if (itr != 0) partOriVert = MothOriVert;
740 for ( const auto& p : particles_in(partOriVert) ) {
741 theMoth = p;
742 if (!theMoth) continue;
743 MotherPDG = theMoth->pdg_id();
744 MothOriVert = theMoth->production_vertex();
745 if (MotherPDG == partPDG) break;
746 }
747 itr++;
748 if (itr > 100) {
749 break;
750 }
751 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
752 MothOriVert != partOriVert);
753 return theMoth;
754 }
755
757
758 template <class C, class T> T findMatching(C TruthContainer, T p) {
759 T ptrPart = nullptr;
760 if (!p) return ptrPart;
761 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
762 for (T truthParticle : *TruthContainer) {
763 if (HepMC::is_sim_descendant(p,truthParticle)) {
764 ptrPart = truthParticle;
765 break;
766 }
767 }
768 }
769 else {
770 for (T truthParticle : TruthContainer) {
771 if (HepMC::is_sim_descendant(p,truthParticle)) {
772 ptrPart = truthParticle;
773 break;
774 }
775 }
776 }
777 return ptrPart;
778 }
780
781 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
782 auto prodVtx = thePart->production_vertex();
783 if (!prodVtx) return;
784 for (const auto& theMother: prodVtx->particles_in()) {
785 if (!theMother) continue;
786 allancestors.insert(theMother);
787 findParticleAncestors(theMother, allancestors);
788 }
789 }
790
792
793 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
794 auto endVtx = thePart->end_vertex();
795 if (!endVtx) return;
796 for (const auto& theDaughter: endVtx->particles_out()) {
797 if (!theDaughter) continue;
798 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
799 allstabledescendants.insert(theDaughter);
800 }
801 findParticleStableDescendants(theDaughter, allstabledescendants);
802 }
803 }
804
808
809 template <class T> bool isHardScatteringVertex(T pVert) {
810 if (pVert == nullptr) return false;
811 T pV = pVert;
812 int numOfPartIn(0);
813 int pdg(0);
814
815 do {
816 pVert = pV;
817 auto incoming = pVert->particles_in();
818 numOfPartIn = incoming.size();
819 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
820 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
821
822 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
823
824 if (numOfPartIn == 2) {
825 auto incoming = pVert->particles_in();
826 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
827 }
828 return false;
829}
830
834
835 template <class T, class U>
836 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
837 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
838 auto vtx = p->production_vertex();
839 if (!vtx) return false;
840 bool fromHad = false;
841 for ( const auto& parent : particles_in(vtx) ) {
842 if (!parent) continue;
843 // should this really go into parton-level territory?
844 // probably depends where BSM particles are being decayed
845 fromBSM |= isBSM(parent);
846 if (!isPhysical(parent)) return false;
847 fromTau |= isTau(parent);
848 if (isHadron(parent)&&!isBeam(parent)) {
849 if (!hadron) hadron = parent; // assumes linear hadron parentage
850 return true;
851 }
852 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
853 }
854 return fromHad;
855 }
856
859
860 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
861 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
862 decltype(thePart->end_vertex()) pVert(nullptr);
863 if (EndVert != nullptr) {
864 do {
865 bool samePart = false;
866 pVert = nullptr;
867 auto outgoing = EndVert->particles_out();
868 auto incoming = EndVert->particles_in();
869 for (const auto& itrDaug: outgoing) {
870 if (!itrDaug) continue;
871 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
872 // brem on generator level for tau
873 (outgoing.size() == 1 && incoming.size() == 1 &&
875 itrDaug->pdg_id() == thePart->pdg_id()) {
876 samePart = true;
877 pVert = itrDaug->end_vertex();
878 }
879 }
880 if (samePart) EndVert = pVert;
881 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
882 }
883 return EndVert;
884 }
885
887
888 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
889 if (!theVert) return {};
890 decltype(theVert->particles_out()) finalStatePart;
891 auto outgoing = theVert->particles_out();
892 for (const auto& thePart: outgoing) {
893 if (!thePart) continue;
894 finalStatePart.push_back(thePart);
895 if (isStable(thePart)) continue;
896 V pVert = findSimulatedEndVertex(thePart);
897 if (pVert == theVert) break; // to prevent Sherpa loop
898 if (pVert != nullptr) {
899 auto vecPart = findFinalStateParticles<V>(pVert);
900 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
901 }
902 }
903 return finalStatePart;
904 }
905#if !defined(XAOD_ANALYSIS)
906#include "AtlasHepMC/GenEvent.h"
907inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
908inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
909
910#endif
911}
912#endif

◆ isLepton() [1/3]

template<>
bool MC::isLepton ( const DecodedPID & p)
inline

Definition at line 192 of file HepMCHelpers.h.

◆ isLepton() [2/3]

template<>
bool MC::isLepton ( const int & p)
inline

Definition at line 191 of file HepMCHelpers.h.

◆ isLepton() [3/3]

template<class T>
bool MC::isLepton ( const T & p)
inline

APID: the fourth generation leptons are leptons.

Definition at line 190 of file HepMCHelpers.h.

◆ isLeptoQuark() [1/2]

template<>
bool MC::isLeptoQuark ( const int & p)
inline

Definition at line 410 of file HepMCHelpers.h.

429{
430 template <class VTX>
431 auto particles_in (const VTX* p) { return p->particles_in(); }
432 template <class VTX>
433 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
434
435 namespace Pythia8
436 {
438 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
439
440 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
441
442 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
443 }
444
445#include "AtlasPID.h"
446
448 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
449
451 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
452
454 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
455
457 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
458
460 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
461
463 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
464
466 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
467
469 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
470
472 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
473
475 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
476
480 template <class T> inline bool isStableOrSimDecayed(const T& p) {
481 const auto vertex = p->end_vertex();
482 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
483 }
484
486 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
487
489 template <class T> inline bool isSpecialNonInteracting(const T& p) {
490 const int apid = std::abs(p->pdg_id());
491 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
492 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
493 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
494 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
495 return false;
496 }
497
499
500 template <class T> T findMother(T thePart) {
501 auto partOriVert = thePart->production_vertex();
502 if (!partOriVert) return nullptr;
503
504 long partPDG = thePart->pdg_id();
505 long MotherPDG(0);
506
507 auto MothOriVert = partOriVert;
508 MothOriVert = nullptr;
509 T theMoth(nullptr);
510
511 size_t itr = 0;
512 do {
513 if (itr != 0) partOriVert = MothOriVert;
514 for ( const auto& p : particles_in(partOriVert) ) {
515 theMoth = p;
516 if (!theMoth) continue;
517 MotherPDG = theMoth->pdg_id();
518 MothOriVert = theMoth->production_vertex();
519 if (MotherPDG == partPDG) break;
520 }
521 itr++;
522 if (itr > 100) {
523 break;
524 }
525 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
526 MothOriVert != partOriVert);
527 return theMoth;
528 }
529
531
532 template <class C, class T> T findMatching(C TruthContainer, T p) {
533 T ptrPart = nullptr;
534 if (!p) return ptrPart;
535 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
536 for (T truthParticle : *TruthContainer) {
537 if (HepMC::is_sim_descendant(p,truthParticle)) {
538 ptrPart = truthParticle;
539 break;
540 }
541 }
542 }
543 else {
544 for (T truthParticle : TruthContainer) {
545 if (HepMC::is_sim_descendant(p,truthParticle)) {
546 ptrPart = truthParticle;
547 break;
548 }
549 }
550 }
551 return ptrPart;
552 }
554
555 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
556 auto prodVtx = thePart->production_vertex();
557 if (!prodVtx) return;
558 for (const auto& theMother: prodVtx->particles_in()) {
559 if (!theMother) continue;
560 allancestors.insert(theMother);
561 findParticleAncestors(theMother, allancestors);
562 }
563 }
564
566
567 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
568 auto endVtx = thePart->end_vertex();
569 if (!endVtx) return;
570 for (const auto& theDaughter: endVtx->particles_out()) {
571 if (!theDaughter) continue;
572 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
573 allstabledescendants.insert(theDaughter);
574 }
575 findParticleStableDescendants(theDaughter, allstabledescendants);
576 }
577 }
578
582
583 template <class T> bool isHardScatteringVertex(T pVert) {
584 if (pVert == nullptr) return false;
585 T pV = pVert;
586 int numOfPartIn(0);
587 int pdg(0);
588
589 do {
590 pVert = pV;
591 auto incoming = pVert->particles_in();
592 numOfPartIn = incoming.size();
593 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
594 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
595
596 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
597
598 if (numOfPartIn == 2) {
599 auto incoming = pVert->particles_in();
600 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
601 }
602 return false;
603}
604
608
609 template <class T, class U>
610 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
611 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
612 auto vtx = p->production_vertex();
613 if (!vtx) return false;
614 bool fromHad = false;
615 for ( const auto& parent : particles_in(vtx) ) {
616 if (!parent) continue;
617 // should this really go into parton-level territory?
618 // probably depends where BSM particles are being decayed
619 fromBSM |= isBSM(parent);
620 if (!isPhysical(parent)) return false;
621 fromTau |= isTau(parent);
622 if (isHadron(parent)&&!isBeam(parent)) {
623 if (!hadron) hadron = parent; // assumes linear hadron parentage
624 return true;
625 }
626 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
627 }
628 return fromHad;
629 }
630
633
634 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
635 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
636 decltype(thePart->end_vertex()) pVert(nullptr);
637 if (EndVert != nullptr) {
638 do {
639 bool samePart = false;
640 pVert = nullptr;
641 auto outgoing = EndVert->particles_out();
642 auto incoming = EndVert->particles_in();
643 for (const auto& itrDaug: outgoing) {
644 if (!itrDaug) continue;
645 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
646 // brem on generator level for tau
647 (outgoing.size() == 1 && incoming.size() == 1 &&
649 itrDaug->pdg_id() == thePart->pdg_id()) {
650 samePart = true;
651 pVert = itrDaug->end_vertex();
652 }
653 }
654 if (samePart) EndVert = pVert;
655 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
656 }
657 return EndVert;
658 }
659
661
662 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
663 if (!theVert) return {};
664 decltype(theVert->particles_out()) finalStatePart;
665 auto outgoing = theVert->particles_out();
666 for (const auto& thePart: outgoing) {
667 if (!thePart) continue;
668 finalStatePart.push_back(thePart);
669 if (isStable(thePart)) continue;
670 V pVert = findSimulatedEndVertex(thePart);
671 if (pVert == theVert) break; // to prevent Sherpa loop
672 if (pVert != nullptr) {
673 auto vecPart = findFinalStateParticles<V>(pVert);
674 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
675 }
676 }
677 return finalStatePart;
678 }
679#if !defined(XAOD_ANALYSIS)
680#include "AtlasHepMC/GenEvent.h"
681inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
682inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
683
684#endif
685}
686#endif

◆ isLeptoQuark() [2/2]

template<class T>
bool MC::isLeptoQuark ( const T & p)
inline

PDG rule 11c: “One-of-a-kind” exotic particles are assigned numbers in the range 41–80.

The subrange 61-80 can be used for new heavier fermions in generic models, where partners to the SM fermions would have codes offset by 60. If required, however, other assignments could be made.

Definition at line 409 of file HepMCHelpers.h.

428{
429 template <class VTX>
430 auto particles_in (const VTX* p) { return p->particles_in(); }
431 template <class VTX>
432 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
433
434 namespace Pythia8
435 {
437 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
438
439 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
440
441 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
442 }
443
444#include "AtlasPID.h"
445
447 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
448
450 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
451
453 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
454
456 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
457
459 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
460
462 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
463
465 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
466
468 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
469
471 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
472
474 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
475
479 template <class T> inline bool isStableOrSimDecayed(const T& p) {
480 const auto vertex = p->end_vertex();
481 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
482 }
483
485 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
486
488 template <class T> inline bool isSpecialNonInteracting(const T& p) {
489 const int apid = std::abs(p->pdg_id());
490 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
491 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
492 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
493 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
494 return false;
495 }
496
498
499 template <class T> T findMother(T thePart) {
500 auto partOriVert = thePart->production_vertex();
501 if (!partOriVert) return nullptr;
502
503 long partPDG = thePart->pdg_id();
504 long MotherPDG(0);
505
506 auto MothOriVert = partOriVert;
507 MothOriVert = nullptr;
508 T theMoth(nullptr);
509
510 size_t itr = 0;
511 do {
512 if (itr != 0) partOriVert = MothOriVert;
513 for ( const auto& p : particles_in(partOriVert) ) {
514 theMoth = p;
515 if (!theMoth) continue;
516 MotherPDG = theMoth->pdg_id();
517 MothOriVert = theMoth->production_vertex();
518 if (MotherPDG == partPDG) break;
519 }
520 itr++;
521 if (itr > 100) {
522 break;
523 }
524 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
525 MothOriVert != partOriVert);
526 return theMoth;
527 }
528
530
531 template <class C, class T> T findMatching(C TruthContainer, T p) {
532 T ptrPart = nullptr;
533 if (!p) return ptrPart;
534 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
535 for (T truthParticle : *TruthContainer) {
536 if (HepMC::is_sim_descendant(p,truthParticle)) {
537 ptrPart = truthParticle;
538 break;
539 }
540 }
541 }
542 else {
543 for (T truthParticle : TruthContainer) {
544 if (HepMC::is_sim_descendant(p,truthParticle)) {
545 ptrPart = truthParticle;
546 break;
547 }
548 }
549 }
550 return ptrPart;
551 }
553
554 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
555 auto prodVtx = thePart->production_vertex();
556 if (!prodVtx) return;
557 for (const auto& theMother: prodVtx->particles_in()) {
558 if (!theMother) continue;
559 allancestors.insert(theMother);
560 findParticleAncestors(theMother, allancestors);
561 }
562 }
563
565
566 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
567 auto endVtx = thePart->end_vertex();
568 if (!endVtx) return;
569 for (const auto& theDaughter: endVtx->particles_out()) {
570 if (!theDaughter) continue;
571 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
572 allstabledescendants.insert(theDaughter);
573 }
574 findParticleStableDescendants(theDaughter, allstabledescendants);
575 }
576 }
577
581
582 template <class T> bool isHardScatteringVertex(T pVert) {
583 if (pVert == nullptr) return false;
584 T pV = pVert;
585 int numOfPartIn(0);
586 int pdg(0);
587
588 do {
589 pVert = pV;
590 auto incoming = pVert->particles_in();
591 numOfPartIn = incoming.size();
592 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
593 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
594
595 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
596
597 if (numOfPartIn == 2) {
598 auto incoming = pVert->particles_in();
599 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
600 }
601 return false;
602}
603
607
608 template <class T, class U>
609 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
610 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
611 auto vtx = p->production_vertex();
612 if (!vtx) return false;
613 bool fromHad = false;
614 for ( const auto& parent : particles_in(vtx) ) {
615 if (!parent) continue;
616 // should this really go into parton-level territory?
617 // probably depends where BSM particles are being decayed
618 fromBSM |= isBSM(parent);
619 if (!isPhysical(parent)) return false;
620 fromTau |= isTau(parent);
621 if (isHadron(parent)&&!isBeam(parent)) {
622 if (!hadron) hadron = parent; // assumes linear hadron parentage
623 return true;
624 }
625 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
626 }
627 return fromHad;
628 }
629
632
633 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
634 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
635 decltype(thePart->end_vertex()) pVert(nullptr);
636 if (EndVert != nullptr) {
637 do {
638 bool samePart = false;
639 pVert = nullptr;
640 auto outgoing = EndVert->particles_out();
641 auto incoming = EndVert->particles_in();
642 for (const auto& itrDaug: outgoing) {
643 if (!itrDaug) continue;
644 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
645 // brem on generator level for tau
646 (outgoing.size() == 1 && incoming.size() == 1 &&
648 itrDaug->pdg_id() == thePart->pdg_id()) {
649 samePart = true;
650 pVert = itrDaug->end_vertex();
651 }
652 }
653 if (samePart) EndVert = pVert;
654 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
655 }
656 return EndVert;
657 }
658
660
661 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
662 if (!theVert) return {};
663 decltype(theVert->particles_out()) finalStatePart;
664 auto outgoing = theVert->particles_out();
665 for (const auto& thePart: outgoing) {
666 if (!thePart) continue;
667 finalStatePart.push_back(thePart);
668 if (isStable(thePart)) continue;
669 V pVert = findSimulatedEndVertex(thePart);
670 if (pVert == theVert) break; // to prevent Sherpa loop
671 if (pVert != nullptr) {
672 auto vecPart = findFinalStateParticles<V>(pVert);
673 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
674 }
675 }
676 return finalStatePart;
677 }
678#if !defined(XAOD_ANALYSIS)
679#include "AtlasHepMC/GenEvent.h"
680inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
681inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
682
683#endif
684}
685#endif

◆ isLightBaryon()

template<class T>
bool MC::isLightBaryon ( const T & p)
inline

Definition at line 932 of file HepMCHelpers.h.

951{
952 template <class VTX>
953 auto particles_in (const VTX* p) { return p->particles_in(); }
954 template <class VTX>
955 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
956
957 namespace Pythia8
958 {
960 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
961
962 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
963
964 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
965 }
966
967#include "AtlasPID.h"
968
970 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
971
973 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
974
976 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
977
979 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
980
982 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
983
985 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
986
988 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
989
991 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
992
994 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
995
997 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
998
1002 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1003 const auto vertex = p->end_vertex();
1004 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1005 }
1006
1008 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1009
1011 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1012 const int apid = std::abs(p->pdg_id());
1013 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1014 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1015 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1016 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1017 return false;
1018 }
1019
1021
1022 template <class T> T findMother(T thePart) {
1023 auto partOriVert = thePart->production_vertex();
1024 if (!partOriVert) return nullptr;
1025
1026 long partPDG = thePart->pdg_id();
1027 long MotherPDG(0);
1028
1029 auto MothOriVert = partOriVert;
1030 MothOriVert = nullptr;
1031 T theMoth(nullptr);
1032
1033 size_t itr = 0;
1034 do {
1035 if (itr != 0) partOriVert = MothOriVert;
1036 for ( const auto& p : particles_in(partOriVert) ) {
1037 theMoth = p;
1038 if (!theMoth) continue;
1039 MotherPDG = theMoth->pdg_id();
1040 MothOriVert = theMoth->production_vertex();
1041 if (MotherPDG == partPDG) break;
1042 }
1043 itr++;
1044 if (itr > 100) {
1045 break;
1046 }
1047 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1048 MothOriVert != partOriVert);
1049 return theMoth;
1050 }
1051
1053
1054 template <class C, class T> T findMatching(C TruthContainer, T p) {
1055 T ptrPart = nullptr;
1056 if (!p) return ptrPart;
1057 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1058 for (T truthParticle : *TruthContainer) {
1059 if (HepMC::is_sim_descendant(p,truthParticle)) {
1060 ptrPart = truthParticle;
1061 break;
1062 }
1063 }
1064 }
1065 else {
1066 for (T truthParticle : TruthContainer) {
1067 if (HepMC::is_sim_descendant(p,truthParticle)) {
1068 ptrPart = truthParticle;
1069 break;
1070 }
1071 }
1072 }
1073 return ptrPart;
1074 }
1076
1077 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1078 auto prodVtx = thePart->production_vertex();
1079 if (!prodVtx) return;
1080 for (const auto& theMother: prodVtx->particles_in()) {
1081 if (!theMother) continue;
1082 allancestors.insert(theMother);
1083 findParticleAncestors(theMother, allancestors);
1084 }
1085 }
1086
1088
1089 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1090 auto endVtx = thePart->end_vertex();
1091 if (!endVtx) return;
1092 for (const auto& theDaughter: endVtx->particles_out()) {
1093 if (!theDaughter) continue;
1094 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1095 allstabledescendants.insert(theDaughter);
1096 }
1097 findParticleStableDescendants(theDaughter, allstabledescendants);
1098 }
1099 }
1100
1104
1105 template <class T> bool isHardScatteringVertex(T pVert) {
1106 if (pVert == nullptr) return false;
1107 T pV = pVert;
1108 int numOfPartIn(0);
1109 int pdg(0);
1110
1111 do {
1112 pVert = pV;
1113 auto incoming = pVert->particles_in();
1114 numOfPartIn = incoming.size();
1115 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1116 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1117
1118 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1119
1120 if (numOfPartIn == 2) {
1121 auto incoming = pVert->particles_in();
1122 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1123 }
1124 return false;
1125}
1126
1130
1131 template <class T, class U>
1132 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1133 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1134 auto vtx = p->production_vertex();
1135 if (!vtx) return false;
1136 bool fromHad = false;
1137 for ( const auto& parent : particles_in(vtx) ) {
1138 if (!parent) continue;
1139 // should this really go into parton-level territory?
1140 // probably depends where BSM particles are being decayed
1141 fromBSM |= isBSM(parent);
1142 if (!isPhysical(parent)) return false;
1143 fromTau |= isTau(parent);
1144 if (isHadron(parent)&&!isBeam(parent)) {
1145 if (!hadron) hadron = parent; // assumes linear hadron parentage
1146 return true;
1147 }
1148 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1149 }
1150 return fromHad;
1151 }
1152
1155
1156 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1157 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1158 decltype(thePart->end_vertex()) pVert(nullptr);
1159 if (EndVert != nullptr) {
1160 do {
1161 bool samePart = false;
1162 pVert = nullptr;
1163 auto outgoing = EndVert->particles_out();
1164 auto incoming = EndVert->particles_in();
1165 for (const auto& itrDaug: outgoing) {
1166 if (!itrDaug) continue;
1167 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1168 // brem on generator level for tau
1169 (outgoing.size() == 1 && incoming.size() == 1 &&
1171 itrDaug->pdg_id() == thePart->pdg_id()) {
1172 samePart = true;
1173 pVert = itrDaug->end_vertex();
1174 }
1175 }
1176 if (samePart) EndVert = pVert;
1177 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1178 }
1179 return EndVert;
1180 }
1181
1183
1184 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1185 if (!theVert) return {};
1186 decltype(theVert->particles_out()) finalStatePart;
1187 auto outgoing = theVert->particles_out();
1188 for (const auto& thePart: outgoing) {
1189 if (!thePart) continue;
1190 finalStatePart.push_back(thePart);
1191 if (isStable(thePart)) continue;
1192 V pVert = findSimulatedEndVertex(thePart);
1193 if (pVert == theVert) break; // to prevent Sherpa loop
1194 if (pVert != nullptr) {
1195 auto vecPart = findFinalStateParticles<V>(pVert);
1196 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1197 }
1198 }
1199 return finalStatePart;
1200 }
1201#if !defined(XAOD_ANALYSIS)
1202#include "AtlasHepMC/GenEvent.h"
1203inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1204inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1205
1206#endif
1207}
1208#endif

◆ isLightHadron()

template<class T>
bool MC::isLightHadron ( const T & p)
inline

Definition at line 909 of file HepMCHelpers.h.

928{
929 template <class VTX>
930 auto particles_in (const VTX* p) { return p->particles_in(); }
931 template <class VTX>
932 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
933
934 namespace Pythia8
935 {
937 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
938
939 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
940
941 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
942 }
943
944#include "AtlasPID.h"
945
947 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
948
950 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
951
953 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
954
956 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
957
959 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
960
962 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
963
965 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
966
968 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
969
971 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
972
974 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
975
979 template <class T> inline bool isStableOrSimDecayed(const T& p) {
980 const auto vertex = p->end_vertex();
981 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
982 }
983
985 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
986
988 template <class T> inline bool isSpecialNonInteracting(const T& p) {
989 const int apid = std::abs(p->pdg_id());
990 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
991 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
992 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
993 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
994 return false;
995 }
996
998
999 template <class T> T findMother(T thePart) {
1000 auto partOriVert = thePart->production_vertex();
1001 if (!partOriVert) return nullptr;
1002
1003 long partPDG = thePart->pdg_id();
1004 long MotherPDG(0);
1005
1006 auto MothOriVert = partOriVert;
1007 MothOriVert = nullptr;
1008 T theMoth(nullptr);
1009
1010 size_t itr = 0;
1011 do {
1012 if (itr != 0) partOriVert = MothOriVert;
1013 for ( const auto& p : particles_in(partOriVert) ) {
1014 theMoth = p;
1015 if (!theMoth) continue;
1016 MotherPDG = theMoth->pdg_id();
1017 MothOriVert = theMoth->production_vertex();
1018 if (MotherPDG == partPDG) break;
1019 }
1020 itr++;
1021 if (itr > 100) {
1022 break;
1023 }
1024 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1025 MothOriVert != partOriVert);
1026 return theMoth;
1027 }
1028
1030
1031 template <class C, class T> T findMatching(C TruthContainer, T p) {
1032 T ptrPart = nullptr;
1033 if (!p) return ptrPart;
1034 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1035 for (T truthParticle : *TruthContainer) {
1036 if (HepMC::is_sim_descendant(p,truthParticle)) {
1037 ptrPart = truthParticle;
1038 break;
1039 }
1040 }
1041 }
1042 else {
1043 for (T truthParticle : TruthContainer) {
1044 if (HepMC::is_sim_descendant(p,truthParticle)) {
1045 ptrPart = truthParticle;
1046 break;
1047 }
1048 }
1049 }
1050 return ptrPart;
1051 }
1053
1054 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1055 auto prodVtx = thePart->production_vertex();
1056 if (!prodVtx) return;
1057 for (const auto& theMother: prodVtx->particles_in()) {
1058 if (!theMother) continue;
1059 allancestors.insert(theMother);
1060 findParticleAncestors(theMother, allancestors);
1061 }
1062 }
1063
1065
1066 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1067 auto endVtx = thePart->end_vertex();
1068 if (!endVtx) return;
1069 for (const auto& theDaughter: endVtx->particles_out()) {
1070 if (!theDaughter) continue;
1071 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1072 allstabledescendants.insert(theDaughter);
1073 }
1074 findParticleStableDescendants(theDaughter, allstabledescendants);
1075 }
1076 }
1077
1081
1082 template <class T> bool isHardScatteringVertex(T pVert) {
1083 if (pVert == nullptr) return false;
1084 T pV = pVert;
1085 int numOfPartIn(0);
1086 int pdg(0);
1087
1088 do {
1089 pVert = pV;
1090 auto incoming = pVert->particles_in();
1091 numOfPartIn = incoming.size();
1092 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1093 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1094
1095 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1096
1097 if (numOfPartIn == 2) {
1098 auto incoming = pVert->particles_in();
1099 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1100 }
1101 return false;
1102}
1103
1107
1108 template <class T, class U>
1109 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1110 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1111 auto vtx = p->production_vertex();
1112 if (!vtx) return false;
1113 bool fromHad = false;
1114 for ( const auto& parent : particles_in(vtx) ) {
1115 if (!parent) continue;
1116 // should this really go into parton-level territory?
1117 // probably depends where BSM particles are being decayed
1118 fromBSM |= isBSM(parent);
1119 if (!isPhysical(parent)) return false;
1120 fromTau |= isTau(parent);
1121 if (isHadron(parent)&&!isBeam(parent)) {
1122 if (!hadron) hadron = parent; // assumes linear hadron parentage
1123 return true;
1124 }
1125 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1126 }
1127 return fromHad;
1128 }
1129
1132
1133 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1134 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1135 decltype(thePart->end_vertex()) pVert(nullptr);
1136 if (EndVert != nullptr) {
1137 do {
1138 bool samePart = false;
1139 pVert = nullptr;
1140 auto outgoing = EndVert->particles_out();
1141 auto incoming = EndVert->particles_in();
1142 for (const auto& itrDaug: outgoing) {
1143 if (!itrDaug) continue;
1144 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1145 // brem on generator level for tau
1146 (outgoing.size() == 1 && incoming.size() == 1 &&
1148 itrDaug->pdg_id() == thePart->pdg_id()) {
1149 samePart = true;
1150 pVert = itrDaug->end_vertex();
1151 }
1152 }
1153 if (samePart) EndVert = pVert;
1154 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1155 }
1156 return EndVert;
1157 }
1158
1160
1161 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1162 if (!theVert) return {};
1163 decltype(theVert->particles_out()) finalStatePart;
1164 auto outgoing = theVert->particles_out();
1165 for (const auto& thePart: outgoing) {
1166 if (!thePart) continue;
1167 finalStatePart.push_back(thePart);
1168 if (isStable(thePart)) continue;
1169 V pVert = findSimulatedEndVertex(thePart);
1170 if (pVert == theVert) break; // to prevent Sherpa loop
1171 if (pVert != nullptr) {
1172 auto vecPart = findFinalStateParticles<V>(pVert);
1173 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1174 }
1175 }
1176 return finalStatePart;
1177 }
1178#if !defined(XAOD_ANALYSIS)
1179#include "AtlasHepMC/GenEvent.h"
1180inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1181inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1182
1183#endif
1184}
1185#endif

◆ isLightMeson()

template<class T>
bool MC::isLightMeson ( const T & p)
inline

Definition at line 916 of file HepMCHelpers.h.

935{
936 template <class VTX>
937 auto particles_in (const VTX* p) { return p->particles_in(); }
938 template <class VTX>
939 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
940
941 namespace Pythia8
942 {
944 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
945
946 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
947
948 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
949 }
950
951#include "AtlasPID.h"
952
954 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
955
957 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
958
960 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
961
963 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
964
966 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
967
969 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
970
972 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
973
975 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
976
978 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
979
981 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
982
986 template <class T> inline bool isStableOrSimDecayed(const T& p) {
987 const auto vertex = p->end_vertex();
988 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
989 }
990
992 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
993
995 template <class T> inline bool isSpecialNonInteracting(const T& p) {
996 const int apid = std::abs(p->pdg_id());
997 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
998 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
999 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1000 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1001 return false;
1002 }
1003
1005
1006 template <class T> T findMother(T thePart) {
1007 auto partOriVert = thePart->production_vertex();
1008 if (!partOriVert) return nullptr;
1009
1010 long partPDG = thePart->pdg_id();
1011 long MotherPDG(0);
1012
1013 auto MothOriVert = partOriVert;
1014 MothOriVert = nullptr;
1015 T theMoth(nullptr);
1016
1017 size_t itr = 0;
1018 do {
1019 if (itr != 0) partOriVert = MothOriVert;
1020 for ( const auto& p : particles_in(partOriVert) ) {
1021 theMoth = p;
1022 if (!theMoth) continue;
1023 MotherPDG = theMoth->pdg_id();
1024 MothOriVert = theMoth->production_vertex();
1025 if (MotherPDG == partPDG) break;
1026 }
1027 itr++;
1028 if (itr > 100) {
1029 break;
1030 }
1031 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1032 MothOriVert != partOriVert);
1033 return theMoth;
1034 }
1035
1037
1038 template <class C, class T> T findMatching(C TruthContainer, T p) {
1039 T ptrPart = nullptr;
1040 if (!p) return ptrPart;
1041 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1042 for (T truthParticle : *TruthContainer) {
1043 if (HepMC::is_sim_descendant(p,truthParticle)) {
1044 ptrPart = truthParticle;
1045 break;
1046 }
1047 }
1048 }
1049 else {
1050 for (T truthParticle : TruthContainer) {
1051 if (HepMC::is_sim_descendant(p,truthParticle)) {
1052 ptrPart = truthParticle;
1053 break;
1054 }
1055 }
1056 }
1057 return ptrPart;
1058 }
1060
1061 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1062 auto prodVtx = thePart->production_vertex();
1063 if (!prodVtx) return;
1064 for (const auto& theMother: prodVtx->particles_in()) {
1065 if (!theMother) continue;
1066 allancestors.insert(theMother);
1067 findParticleAncestors(theMother, allancestors);
1068 }
1069 }
1070
1072
1073 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1074 auto endVtx = thePart->end_vertex();
1075 if (!endVtx) return;
1076 for (const auto& theDaughter: endVtx->particles_out()) {
1077 if (!theDaughter) continue;
1078 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1079 allstabledescendants.insert(theDaughter);
1080 }
1081 findParticleStableDescendants(theDaughter, allstabledescendants);
1082 }
1083 }
1084
1088
1089 template <class T> bool isHardScatteringVertex(T pVert) {
1090 if (pVert == nullptr) return false;
1091 T pV = pVert;
1092 int numOfPartIn(0);
1093 int pdg(0);
1094
1095 do {
1096 pVert = pV;
1097 auto incoming = pVert->particles_in();
1098 numOfPartIn = incoming.size();
1099 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1100 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1101
1102 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1103
1104 if (numOfPartIn == 2) {
1105 auto incoming = pVert->particles_in();
1106 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1107 }
1108 return false;
1109}
1110
1114
1115 template <class T, class U>
1116 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1117 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1118 auto vtx = p->production_vertex();
1119 if (!vtx) return false;
1120 bool fromHad = false;
1121 for ( const auto& parent : particles_in(vtx) ) {
1122 if (!parent) continue;
1123 // should this really go into parton-level territory?
1124 // probably depends where BSM particles are being decayed
1125 fromBSM |= isBSM(parent);
1126 if (!isPhysical(parent)) return false;
1127 fromTau |= isTau(parent);
1128 if (isHadron(parent)&&!isBeam(parent)) {
1129 if (!hadron) hadron = parent; // assumes linear hadron parentage
1130 return true;
1131 }
1132 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1133 }
1134 return fromHad;
1135 }
1136
1139
1140 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1141 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1142 decltype(thePart->end_vertex()) pVert(nullptr);
1143 if (EndVert != nullptr) {
1144 do {
1145 bool samePart = false;
1146 pVert = nullptr;
1147 auto outgoing = EndVert->particles_out();
1148 auto incoming = EndVert->particles_in();
1149 for (const auto& itrDaug: outgoing) {
1150 if (!itrDaug) continue;
1151 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1152 // brem on generator level for tau
1153 (outgoing.size() == 1 && incoming.size() == 1 &&
1155 itrDaug->pdg_id() == thePart->pdg_id()) {
1156 samePart = true;
1157 pVert = itrDaug->end_vertex();
1158 }
1159 }
1160 if (samePart) EndVert = pVert;
1161 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1162 }
1163 return EndVert;
1164 }
1165
1167
1168 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1169 if (!theVert) return {};
1170 decltype(theVert->particles_out()) finalStatePart;
1171 auto outgoing = theVert->particles_out();
1172 for (const auto& thePart: outgoing) {
1173 if (!thePart) continue;
1174 finalStatePart.push_back(thePart);
1175 if (isStable(thePart)) continue;
1176 V pVert = findSimulatedEndVertex(thePart);
1177 if (pVert == theVert) break; // to prevent Sherpa loop
1178 if (pVert != nullptr) {
1179 auto vecPart = findFinalStateParticles<V>(pVert);
1180 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1181 }
1182 }
1183 return finalStatePart;
1184 }
1185#if !defined(XAOD_ANALYSIS)
1186#include "AtlasHepMC/GenEvent.h"
1187inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1188inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1189
1190#endif
1191}
1192#endif

◆ isMeson() [1/3]

template<>
bool MC::isMeson ( const DecodedPID & p)
inline

Definition at line 246 of file HepMCHelpers.h.

253 {
254 if (!theVert) return {};
255 decltype(theVert->particles_out()) finalStatePart;
256 auto outgoing = theVert->particles_out();
257 for (const auto& thePart: outgoing) {
258 if (!thePart) continue;
259 finalStatePart.push_back(thePart);
260 if (isStable(thePart)) continue;
261 V pVert = findSimulatedEndVertex(thePart);
262 if (pVert == theVert) break; // to prevent Sherpa loop
263 if (pVert != nullptr) {
264 auto vecPart = findFinalStateParticles<V>(pVert);
265 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
266 }

◆ isMeson() [2/3]

template<>
bool MC::isMeson ( const int & p)
inline

Definition at line 267 of file HepMCHelpers.h.

◆ isMeson() [3/3]

template<class T>
bool MC::isMeson ( const T & p)
inline

Table 43.1 PDG rule 5a: The numbers specifying the meson’s quark content conform to the convention nq1= 0 and nq2 >= nq3.

The special case K0L is the sole exception to this rule. PDG rule 5C: The special numbers 310 and 130 are given to the K0S and K0L respectively. APID: The special code K0 is used when a generator uses K0S/K0L APID: states with fourth generation quarks are not mesons

Definition at line 245 of file HepMCHelpers.h.

◆ isMonopole() [1/3]

template<>
bool MC::isMonopole ( const DecodedPID & p)
inline

Definition at line 647 of file HepMCHelpers.h.

666{
667 template <class VTX>
668 auto particles_in (const VTX* p) { return p->particles_in(); }
669 template <class VTX>
670 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
671
672 namespace Pythia8
673 {
675 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
676
677 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
678
679 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
680 }
681
682#include "AtlasPID.h"
683
685 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
686
688 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
689
691 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
692
694 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
695
697 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
698
700 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
701
703 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
704
706 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
707
709 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
710
712 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
713
717 template <class T> inline bool isStableOrSimDecayed(const T& p) {
718 const auto vertex = p->end_vertex();
719 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
720 }
721
723 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
724
726 template <class T> inline bool isSpecialNonInteracting(const T& p) {
727 const int apid = std::abs(p->pdg_id());
728 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
729 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
730 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
731 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
732 return false;
733 }
734
736
737 template <class T> T findMother(T thePart) {
738 auto partOriVert = thePart->production_vertex();
739 if (!partOriVert) return nullptr;
740
741 long partPDG = thePart->pdg_id();
742 long MotherPDG(0);
743
744 auto MothOriVert = partOriVert;
745 MothOriVert = nullptr;
746 T theMoth(nullptr);
747
748 size_t itr = 0;
749 do {
750 if (itr != 0) partOriVert = MothOriVert;
751 for ( const auto& p : particles_in(partOriVert) ) {
752 theMoth = p;
753 if (!theMoth) continue;
754 MotherPDG = theMoth->pdg_id();
755 MothOriVert = theMoth->production_vertex();
756 if (MotherPDG == partPDG) break;
757 }
758 itr++;
759 if (itr > 100) {
760 break;
761 }
762 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
763 MothOriVert != partOriVert);
764 return theMoth;
765 }
766
768
769 template <class C, class T> T findMatching(C TruthContainer, T p) {
770 T ptrPart = nullptr;
771 if (!p) return ptrPart;
772 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
773 for (T truthParticle : *TruthContainer) {
774 if (HepMC::is_sim_descendant(p,truthParticle)) {
775 ptrPart = truthParticle;
776 break;
777 }
778 }
779 }
780 else {
781 for (T truthParticle : TruthContainer) {
782 if (HepMC::is_sim_descendant(p,truthParticle)) {
783 ptrPart = truthParticle;
784 break;
785 }
786 }
787 }
788 return ptrPart;
789 }
791
792 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
793 auto prodVtx = thePart->production_vertex();
794 if (!prodVtx) return;
795 for (const auto& theMother: prodVtx->particles_in()) {
796 if (!theMother) continue;
797 allancestors.insert(theMother);
798 findParticleAncestors(theMother, allancestors);
799 }
800 }
801
803
804 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
805 auto endVtx = thePart->end_vertex();
806 if (!endVtx) return;
807 for (const auto& theDaughter: endVtx->particles_out()) {
808 if (!theDaughter) continue;
809 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
810 allstabledescendants.insert(theDaughter);
811 }
812 findParticleStableDescendants(theDaughter, allstabledescendants);
813 }
814 }
815
819
820 template <class T> bool isHardScatteringVertex(T pVert) {
821 if (pVert == nullptr) return false;
822 T pV = pVert;
823 int numOfPartIn(0);
824 int pdg(0);
825
826 do {
827 pVert = pV;
828 auto incoming = pVert->particles_in();
829 numOfPartIn = incoming.size();
830 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
831 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
832
833 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
834
835 if (numOfPartIn == 2) {
836 auto incoming = pVert->particles_in();
837 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
838 }
839 return false;
840}
841
845
846 template <class T, class U>
847 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
848 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
849 auto vtx = p->production_vertex();
850 if (!vtx) return false;
851 bool fromHad = false;
852 for ( const auto& parent : particles_in(vtx) ) {
853 if (!parent) continue;
854 // should this really go into parton-level territory?
855 // probably depends where BSM particles are being decayed
856 fromBSM |= isBSM(parent);
857 if (!isPhysical(parent)) return false;
858 fromTau |= isTau(parent);
859 if (isHadron(parent)&&!isBeam(parent)) {
860 if (!hadron) hadron = parent; // assumes linear hadron parentage
861 return true;
862 }
863 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
864 }
865 return fromHad;
866 }
867
870
871 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
872 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
873 decltype(thePart->end_vertex()) pVert(nullptr);
874 if (EndVert != nullptr) {
875 do {
876 bool samePart = false;
877 pVert = nullptr;
878 auto outgoing = EndVert->particles_out();
879 auto incoming = EndVert->particles_in();
880 for (const auto& itrDaug: outgoing) {
881 if (!itrDaug) continue;
882 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
883 // brem on generator level for tau
884 (outgoing.size() == 1 && incoming.size() == 1 &&
886 itrDaug->pdg_id() == thePart->pdg_id()) {
887 samePart = true;
888 pVert = itrDaug->end_vertex();
889 }
890 }
891 if (samePart) EndVert = pVert;
892 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
893 }
894 return EndVert;
895 }
896
898
899 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
900 if (!theVert) return {};
901 decltype(theVert->particles_out()) finalStatePart;
902 auto outgoing = theVert->particles_out();
903 for (const auto& thePart: outgoing) {
904 if (!thePart) continue;
905 finalStatePart.push_back(thePart);
906 if (isStable(thePart)) continue;
907 V pVert = findSimulatedEndVertex(thePart);
908 if (pVert == theVert) break; // to prevent Sherpa loop
909 if (pVert != nullptr) {
910 auto vecPart = findFinalStateParticles<V>(pVert);
911 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
912 }
913 }
914 return finalStatePart;
915 }
916#if !defined(XAOD_ANALYSIS)
917#include "AtlasHepMC/GenEvent.h"
918inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
919inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
920
921#endif
922}
923#endif

◆ isMonopole() [2/3]

template<>
bool MC::isMonopole ( const int & p)
inline

Definition at line 648 of file HepMCHelpers.h.

667{
668 template <class VTX>
669 auto particles_in (const VTX* p) { return p->particles_in(); }
670 template <class VTX>
671 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
672
673 namespace Pythia8
674 {
676 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
677
678 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
679
680 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
681 }
682
683#include "AtlasPID.h"
684
686 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
687
689 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
690
692 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
693
695 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
696
698 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
699
701 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
702
704 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
705
707 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
708
710 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
711
713 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
714
718 template <class T> inline bool isStableOrSimDecayed(const T& p) {
719 const auto vertex = p->end_vertex();
720 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
721 }
722
724 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
725
727 template <class T> inline bool isSpecialNonInteracting(const T& p) {
728 const int apid = std::abs(p->pdg_id());
729 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
730 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
731 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
732 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
733 return false;
734 }
735
737
738 template <class T> T findMother(T thePart) {
739 auto partOriVert = thePart->production_vertex();
740 if (!partOriVert) return nullptr;
741
742 long partPDG = thePart->pdg_id();
743 long MotherPDG(0);
744
745 auto MothOriVert = partOriVert;
746 MothOriVert = nullptr;
747 T theMoth(nullptr);
748
749 size_t itr = 0;
750 do {
751 if (itr != 0) partOriVert = MothOriVert;
752 for ( const auto& p : particles_in(partOriVert) ) {
753 theMoth = p;
754 if (!theMoth) continue;
755 MotherPDG = theMoth->pdg_id();
756 MothOriVert = theMoth->production_vertex();
757 if (MotherPDG == partPDG) break;
758 }
759 itr++;
760 if (itr > 100) {
761 break;
762 }
763 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
764 MothOriVert != partOriVert);
765 return theMoth;
766 }
767
769
770 template <class C, class T> T findMatching(C TruthContainer, T p) {
771 T ptrPart = nullptr;
772 if (!p) return ptrPart;
773 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
774 for (T truthParticle : *TruthContainer) {
775 if (HepMC::is_sim_descendant(p,truthParticle)) {
776 ptrPart = truthParticle;
777 break;
778 }
779 }
780 }
781 else {
782 for (T truthParticle : TruthContainer) {
783 if (HepMC::is_sim_descendant(p,truthParticle)) {
784 ptrPart = truthParticle;
785 break;
786 }
787 }
788 }
789 return ptrPart;
790 }
792
793 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
794 auto prodVtx = thePart->production_vertex();
795 if (!prodVtx) return;
796 for (const auto& theMother: prodVtx->particles_in()) {
797 if (!theMother) continue;
798 allancestors.insert(theMother);
799 findParticleAncestors(theMother, allancestors);
800 }
801 }
802
804
805 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
806 auto endVtx = thePart->end_vertex();
807 if (!endVtx) return;
808 for (const auto& theDaughter: endVtx->particles_out()) {
809 if (!theDaughter) continue;
810 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
811 allstabledescendants.insert(theDaughter);
812 }
813 findParticleStableDescendants(theDaughter, allstabledescendants);
814 }
815 }
816
820
821 template <class T> bool isHardScatteringVertex(T pVert) {
822 if (pVert == nullptr) return false;
823 T pV = pVert;
824 int numOfPartIn(0);
825 int pdg(0);
826
827 do {
828 pVert = pV;
829 auto incoming = pVert->particles_in();
830 numOfPartIn = incoming.size();
831 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
832 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
833
834 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
835
836 if (numOfPartIn == 2) {
837 auto incoming = pVert->particles_in();
838 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
839 }
840 return false;
841}
842
846
847 template <class T, class U>
848 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
849 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
850 auto vtx = p->production_vertex();
851 if (!vtx) return false;
852 bool fromHad = false;
853 for ( const auto& parent : particles_in(vtx) ) {
854 if (!parent) continue;
855 // should this really go into parton-level territory?
856 // probably depends where BSM particles are being decayed
857 fromBSM |= isBSM(parent);
858 if (!isPhysical(parent)) return false;
859 fromTau |= isTau(parent);
860 if (isHadron(parent)&&!isBeam(parent)) {
861 if (!hadron) hadron = parent; // assumes linear hadron parentage
862 return true;
863 }
864 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
865 }
866 return fromHad;
867 }
868
871
872 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
873 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
874 decltype(thePart->end_vertex()) pVert(nullptr);
875 if (EndVert != nullptr) {
876 do {
877 bool samePart = false;
878 pVert = nullptr;
879 auto outgoing = EndVert->particles_out();
880 auto incoming = EndVert->particles_in();
881 for (const auto& itrDaug: outgoing) {
882 if (!itrDaug) continue;
883 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
884 // brem on generator level for tau
885 (outgoing.size() == 1 && incoming.size() == 1 &&
887 itrDaug->pdg_id() == thePart->pdg_id()) {
888 samePart = true;
889 pVert = itrDaug->end_vertex();
890 }
891 }
892 if (samePart) EndVert = pVert;
893 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
894 }
895 return EndVert;
896 }
897
899
900 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
901 if (!theVert) return {};
902 decltype(theVert->particles_out()) finalStatePart;
903 auto outgoing = theVert->particles_out();
904 for (const auto& thePart: outgoing) {
905 if (!thePart) continue;
906 finalStatePart.push_back(thePart);
907 if (isStable(thePart)) continue;
908 V pVert = findSimulatedEndVertex(thePart);
909 if (pVert == theVert) break; // to prevent Sherpa loop
910 if (pVert != nullptr) {
911 auto vecPart = findFinalStateParticles<V>(pVert);
912 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
913 }
914 }
915 return finalStatePart;
916 }
917#if !defined(XAOD_ANALYSIS)
918#include "AtlasHepMC/GenEvent.h"
919inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
920inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
921
922#endif
923}
924#endif

◆ isMonopole() [3/3]

template<class T>
bool MC::isMonopole ( const T & p)
inline

PDG rule 11i Magnetic monopoles and dyons are assumed to have one unit of Dirac monopole charge and a variable integer number nq1nq2 nq3 units of electric charge.

Codes 411nq1nq2 nq3 0 are then used when the magnetic and electrical charge sign agree and 412nq1nq2 nq3 0 when they disagree, with the overall sign of the particle set by the magnetic charge. For now no spin information is provided.

Definition at line 646 of file HepMCHelpers.h.

665{
666 template <class VTX>
667 auto particles_in (const VTX* p) { return p->particles_in(); }
668 template <class VTX>
669 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
670
671 namespace Pythia8
672 {
674 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
675
676 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
677
678 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
679 }
680
681#include "AtlasPID.h"
682
684 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
685
687 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
688
690 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
691
693 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
694
696 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
697
699 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
700
702 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
703
705 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
706
708 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
709
711 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
712
716 template <class T> inline bool isStableOrSimDecayed(const T& p) {
717 const auto vertex = p->end_vertex();
718 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
719 }
720
722 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
723
725 template <class T> inline bool isSpecialNonInteracting(const T& p) {
726 const int apid = std::abs(p->pdg_id());
727 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
728 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
729 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
730 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
731 return false;
732 }
733
735
736 template <class T> T findMother(T thePart) {
737 auto partOriVert = thePart->production_vertex();
738 if (!partOriVert) return nullptr;
739
740 long partPDG = thePart->pdg_id();
741 long MotherPDG(0);
742
743 auto MothOriVert = partOriVert;
744 MothOriVert = nullptr;
745 T theMoth(nullptr);
746
747 size_t itr = 0;
748 do {
749 if (itr != 0) partOriVert = MothOriVert;
750 for ( const auto& p : particles_in(partOriVert) ) {
751 theMoth = p;
752 if (!theMoth) continue;
753 MotherPDG = theMoth->pdg_id();
754 MothOriVert = theMoth->production_vertex();
755 if (MotherPDG == partPDG) break;
756 }
757 itr++;
758 if (itr > 100) {
759 break;
760 }
761 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
762 MothOriVert != partOriVert);
763 return theMoth;
764 }
765
767
768 template <class C, class T> T findMatching(C TruthContainer, T p) {
769 T ptrPart = nullptr;
770 if (!p) return ptrPart;
771 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
772 for (T truthParticle : *TruthContainer) {
773 if (HepMC::is_sim_descendant(p,truthParticle)) {
774 ptrPart = truthParticle;
775 break;
776 }
777 }
778 }
779 else {
780 for (T truthParticle : TruthContainer) {
781 if (HepMC::is_sim_descendant(p,truthParticle)) {
782 ptrPart = truthParticle;
783 break;
784 }
785 }
786 }
787 return ptrPart;
788 }
790
791 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
792 auto prodVtx = thePart->production_vertex();
793 if (!prodVtx) return;
794 for (const auto& theMother: prodVtx->particles_in()) {
795 if (!theMother) continue;
796 allancestors.insert(theMother);
797 findParticleAncestors(theMother, allancestors);
798 }
799 }
800
802
803 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
804 auto endVtx = thePart->end_vertex();
805 if (!endVtx) return;
806 for (const auto& theDaughter: endVtx->particles_out()) {
807 if (!theDaughter) continue;
808 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
809 allstabledescendants.insert(theDaughter);
810 }
811 findParticleStableDescendants(theDaughter, allstabledescendants);
812 }
813 }
814
818
819 template <class T> bool isHardScatteringVertex(T pVert) {
820 if (pVert == nullptr) return false;
821 T pV = pVert;
822 int numOfPartIn(0);
823 int pdg(0);
824
825 do {
826 pVert = pV;
827 auto incoming = pVert->particles_in();
828 numOfPartIn = incoming.size();
829 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
830 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
831
832 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
833
834 if (numOfPartIn == 2) {
835 auto incoming = pVert->particles_in();
836 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
837 }
838 return false;
839}
840
844
845 template <class T, class U>
846 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
847 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
848 auto vtx = p->production_vertex();
849 if (!vtx) return false;
850 bool fromHad = false;
851 for ( const auto& parent : particles_in(vtx) ) {
852 if (!parent) continue;
853 // should this really go into parton-level territory?
854 // probably depends where BSM particles are being decayed
855 fromBSM |= isBSM(parent);
856 if (!isPhysical(parent)) return false;
857 fromTau |= isTau(parent);
858 if (isHadron(parent)&&!isBeam(parent)) {
859 if (!hadron) hadron = parent; // assumes linear hadron parentage
860 return true;
861 }
862 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
863 }
864 return fromHad;
865 }
866
869
870 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
871 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
872 decltype(thePart->end_vertex()) pVert(nullptr);
873 if (EndVert != nullptr) {
874 do {
875 bool samePart = false;
876 pVert = nullptr;
877 auto outgoing = EndVert->particles_out();
878 auto incoming = EndVert->particles_in();
879 for (const auto& itrDaug: outgoing) {
880 if (!itrDaug) continue;
881 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
882 // brem on generator level for tau
883 (outgoing.size() == 1 && incoming.size() == 1 &&
885 itrDaug->pdg_id() == thePart->pdg_id()) {
886 samePart = true;
887 pVert = itrDaug->end_vertex();
888 }
889 }
890 if (samePart) EndVert = pVert;
891 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
892 }
893 return EndVert;
894 }
895
897
898 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
899 if (!theVert) return {};
900 decltype(theVert->particles_out()) finalStatePart;
901 auto outgoing = theVert->particles_out();
902 for (const auto& thePart: outgoing) {
903 if (!thePart) continue;
904 finalStatePart.push_back(thePart);
905 if (isStable(thePart)) continue;
906 V pVert = findSimulatedEndVertex(thePart);
907 if (pVert == theVert) break; // to prevent Sherpa loop
908 if (pVert != nullptr) {
909 auto vecPart = findFinalStateParticles<V>(pVert);
910 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
911 }
912 }
913 return finalStatePart;
914 }
915#if !defined(XAOD_ANALYSIS)
916#include "AtlasHepMC/GenEvent.h"
917inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
918inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
919
920#endif
921}
922#endif

◆ isMSSMHiggs() [1/2]

template<>
bool MC::isMSSMHiggs ( const int & p)
inline

Definition at line 396 of file HepMCHelpers.h.

415{
416 template <class VTX>
417 auto particles_in (const VTX* p) { return p->particles_in(); }
418 template <class VTX>
419 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
420
421 namespace Pythia8
422 {
424 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
425
426 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
427
428 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
429 }
430
431#include "AtlasPID.h"
432
434 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
435
437 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
438
440 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
441
443 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
444
446 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
447
449 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
450
452 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
453
455 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
456
458 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
459
461 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
462
466 template <class T> inline bool isStableOrSimDecayed(const T& p) {
467 const auto vertex = p->end_vertex();
468 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
469 }
470
472 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
473
475 template <class T> inline bool isSpecialNonInteracting(const T& p) {
476 const int apid = std::abs(p->pdg_id());
477 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
478 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
479 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
480 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
481 return false;
482 }
483
485
486 template <class T> T findMother(T thePart) {
487 auto partOriVert = thePart->production_vertex();
488 if (!partOriVert) return nullptr;
489
490 long partPDG = thePart->pdg_id();
491 long MotherPDG(0);
492
493 auto MothOriVert = partOriVert;
494 MothOriVert = nullptr;
495 T theMoth(nullptr);
496
497 size_t itr = 0;
498 do {
499 if (itr != 0) partOriVert = MothOriVert;
500 for ( const auto& p : particles_in(partOriVert) ) {
501 theMoth = p;
502 if (!theMoth) continue;
503 MotherPDG = theMoth->pdg_id();
504 MothOriVert = theMoth->production_vertex();
505 if (MotherPDG == partPDG) break;
506 }
507 itr++;
508 if (itr > 100) {
509 break;
510 }
511 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
512 MothOriVert != partOriVert);
513 return theMoth;
514 }
515
517
518 template <class C, class T> T findMatching(C TruthContainer, T p) {
519 T ptrPart = nullptr;
520 if (!p) return ptrPart;
521 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
522 for (T truthParticle : *TruthContainer) {
523 if (HepMC::is_sim_descendant(p,truthParticle)) {
524 ptrPart = truthParticle;
525 break;
526 }
527 }
528 }
529 else {
530 for (T truthParticle : TruthContainer) {
531 if (HepMC::is_sim_descendant(p,truthParticle)) {
532 ptrPart = truthParticle;
533 break;
534 }
535 }
536 }
537 return ptrPart;
538 }
540
541 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
542 auto prodVtx = thePart->production_vertex();
543 if (!prodVtx) return;
544 for (const auto& theMother: prodVtx->particles_in()) {
545 if (!theMother) continue;
546 allancestors.insert(theMother);
547 findParticleAncestors(theMother, allancestors);
548 }
549 }
550
552
553 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
554 auto endVtx = thePart->end_vertex();
555 if (!endVtx) return;
556 for (const auto& theDaughter: endVtx->particles_out()) {
557 if (!theDaughter) continue;
558 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
559 allstabledescendants.insert(theDaughter);
560 }
561 findParticleStableDescendants(theDaughter, allstabledescendants);
562 }
563 }
564
568
569 template <class T> bool isHardScatteringVertex(T pVert) {
570 if (pVert == nullptr) return false;
571 T pV = pVert;
572 int numOfPartIn(0);
573 int pdg(0);
574
575 do {
576 pVert = pV;
577 auto incoming = pVert->particles_in();
578 numOfPartIn = incoming.size();
579 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
580 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
581
582 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
583
584 if (numOfPartIn == 2) {
585 auto incoming = pVert->particles_in();
586 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
587 }
588 return false;
589}
590
594
595 template <class T, class U>
596 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
597 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
598 auto vtx = p->production_vertex();
599 if (!vtx) return false;
600 bool fromHad = false;
601 for ( const auto& parent : particles_in(vtx) ) {
602 if (!parent) continue;
603 // should this really go into parton-level territory?
604 // probably depends where BSM particles are being decayed
605 fromBSM |= isBSM(parent);
606 if (!isPhysical(parent)) return false;
607 fromTau |= isTau(parent);
608 if (isHadron(parent)&&!isBeam(parent)) {
609 if (!hadron) hadron = parent; // assumes linear hadron parentage
610 return true;
611 }
612 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
613 }
614 return fromHad;
615 }
616
619
620 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
621 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
622 decltype(thePart->end_vertex()) pVert(nullptr);
623 if (EndVert != nullptr) {
624 do {
625 bool samePart = false;
626 pVert = nullptr;
627 auto outgoing = EndVert->particles_out();
628 auto incoming = EndVert->particles_in();
629 for (const auto& itrDaug: outgoing) {
630 if (!itrDaug) continue;
631 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
632 // brem on generator level for tau
633 (outgoing.size() == 1 && incoming.size() == 1 &&
635 itrDaug->pdg_id() == thePart->pdg_id()) {
636 samePart = true;
637 pVert = itrDaug->end_vertex();
638 }
639 }
640 if (samePart) EndVert = pVert;
641 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
642 }
643 return EndVert;
644 }
645
647
648 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
649 if (!theVert) return {};
650 decltype(theVert->particles_out()) finalStatePart;
651 auto outgoing = theVert->particles_out();
652 for (const auto& thePart: outgoing) {
653 if (!thePart) continue;
654 finalStatePart.push_back(thePart);
655 if (isStable(thePart)) continue;
656 V pVert = findSimulatedEndVertex(thePart);
657 if (pVert == theVert) break; // to prevent Sherpa loop
658 if (pVert != nullptr) {
659 auto vecPart = findFinalStateParticles<V>(pVert);
660 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
661 }
662 }
663 return finalStatePart;
664 }
665#if !defined(XAOD_ANALYSIS)
666#include "AtlasHepMC/GenEvent.h"
667inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
668inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
669
670#endif
671}
672#endif

◆ isMSSMHiggs() [2/2]

template<class T>
bool MC::isMSSMHiggs ( const T & p)
inline

APID: Additional Higgs bosons for MSSM (Used in MCTruthClassifier).

Definition at line 395 of file HepMCHelpers.h.

414{
415 template <class VTX>
416 auto particles_in (const VTX* p) { return p->particles_in(); }
417 template <class VTX>
418 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
419
420 namespace Pythia8
421 {
423 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
424
425 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
426
427 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
428 }
429
430#include "AtlasPID.h"
431
433 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
434
436 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
437
439 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
440
442 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
443
445 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
446
448 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
449
451 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
452
454 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
455
457 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
458
460 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
461
465 template <class T> inline bool isStableOrSimDecayed(const T& p) {
466 const auto vertex = p->end_vertex();
467 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
468 }
469
471 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
472
474 template <class T> inline bool isSpecialNonInteracting(const T& p) {
475 const int apid = std::abs(p->pdg_id());
476 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
477 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
478 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
479 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
480 return false;
481 }
482
484
485 template <class T> T findMother(T thePart) {
486 auto partOriVert = thePart->production_vertex();
487 if (!partOriVert) return nullptr;
488
489 long partPDG = thePart->pdg_id();
490 long MotherPDG(0);
491
492 auto MothOriVert = partOriVert;
493 MothOriVert = nullptr;
494 T theMoth(nullptr);
495
496 size_t itr = 0;
497 do {
498 if (itr != 0) partOriVert = MothOriVert;
499 for ( const auto& p : particles_in(partOriVert) ) {
500 theMoth = p;
501 if (!theMoth) continue;
502 MotherPDG = theMoth->pdg_id();
503 MothOriVert = theMoth->production_vertex();
504 if (MotherPDG == partPDG) break;
505 }
506 itr++;
507 if (itr > 100) {
508 break;
509 }
510 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
511 MothOriVert != partOriVert);
512 return theMoth;
513 }
514
516
517 template <class C, class T> T findMatching(C TruthContainer, T p) {
518 T ptrPart = nullptr;
519 if (!p) return ptrPart;
520 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
521 for (T truthParticle : *TruthContainer) {
522 if (HepMC::is_sim_descendant(p,truthParticle)) {
523 ptrPart = truthParticle;
524 break;
525 }
526 }
527 }
528 else {
529 for (T truthParticle : TruthContainer) {
530 if (HepMC::is_sim_descendant(p,truthParticle)) {
531 ptrPart = truthParticle;
532 break;
533 }
534 }
535 }
536 return ptrPart;
537 }
539
540 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
541 auto prodVtx = thePart->production_vertex();
542 if (!prodVtx) return;
543 for (const auto& theMother: prodVtx->particles_in()) {
544 if (!theMother) continue;
545 allancestors.insert(theMother);
546 findParticleAncestors(theMother, allancestors);
547 }
548 }
549
551
552 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
553 auto endVtx = thePart->end_vertex();
554 if (!endVtx) return;
555 for (const auto& theDaughter: endVtx->particles_out()) {
556 if (!theDaughter) continue;
557 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
558 allstabledescendants.insert(theDaughter);
559 }
560 findParticleStableDescendants(theDaughter, allstabledescendants);
561 }
562 }
563
567
568 template <class T> bool isHardScatteringVertex(T pVert) {
569 if (pVert == nullptr) return false;
570 T pV = pVert;
571 int numOfPartIn(0);
572 int pdg(0);
573
574 do {
575 pVert = pV;
576 auto incoming = pVert->particles_in();
577 numOfPartIn = incoming.size();
578 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
579 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
580
581 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
582
583 if (numOfPartIn == 2) {
584 auto incoming = pVert->particles_in();
585 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
586 }
587 return false;
588}
589
593
594 template <class T, class U>
595 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
596 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
597 auto vtx = p->production_vertex();
598 if (!vtx) return false;
599 bool fromHad = false;
600 for ( const auto& parent : particles_in(vtx) ) {
601 if (!parent) continue;
602 // should this really go into parton-level territory?
603 // probably depends where BSM particles are being decayed
604 fromBSM |= isBSM(parent);
605 if (!isPhysical(parent)) return false;
606 fromTau |= isTau(parent);
607 if (isHadron(parent)&&!isBeam(parent)) {
608 if (!hadron) hadron = parent; // assumes linear hadron parentage
609 return true;
610 }
611 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
612 }
613 return fromHad;
614 }
615
618
619 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
620 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
621 decltype(thePart->end_vertex()) pVert(nullptr);
622 if (EndVert != nullptr) {
623 do {
624 bool samePart = false;
625 pVert = nullptr;
626 auto outgoing = EndVert->particles_out();
627 auto incoming = EndVert->particles_in();
628 for (const auto& itrDaug: outgoing) {
629 if (!itrDaug) continue;
630 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
631 // brem on generator level for tau
632 (outgoing.size() == 1 && incoming.size() == 1 &&
634 itrDaug->pdg_id() == thePart->pdg_id()) {
635 samePart = true;
636 pVert = itrDaug->end_vertex();
637 }
638 }
639 if (samePart) EndVert = pVert;
640 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
641 }
642 return EndVert;
643 }
644
646
647 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
648 if (!theVert) return {};
649 decltype(theVert->particles_out()) finalStatePart;
650 auto outgoing = theVert->particles_out();
651 for (const auto& thePart: outgoing) {
652 if (!thePart) continue;
653 finalStatePart.push_back(thePart);
654 if (isStable(thePart)) continue;
655 V pVert = findSimulatedEndVertex(thePart);
656 if (pVert == theVert) break; // to prevent Sherpa loop
657 if (pVert != nullptr) {
658 auto vecPart = findFinalStateParticles<V>(pVert);
659 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
660 }
661 }
662 return finalStatePart;
663 }
664#if !defined(XAOD_ANALYSIS)
665#include "AtlasHepMC/GenEvent.h"
666inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
667inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
668
669#endif
670}
671#endif

◆ isMuon() [1/2]

template<>
bool MC::isMuon ( const int & p)
inline

Definition at line 207 of file HepMCHelpers.h.

◆ isMuon() [2/2]

template<class T>
bool MC::isMuon ( const T & p)
inline

Definition at line 206 of file HepMCHelpers.h.

206: particles_in(vtx) ) {

◆ isNeutral() [1/3]

template<>
bool MC::isNeutral ( const DecodedPID & p)
inline

Definition at line 1092 of file HepMCHelpers.h.

1111{
1112 template <class VTX>
1113 auto particles_in (const VTX* p) { return p->particles_in(); }
1114 template <class VTX>
1115 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1116
1117 namespace Pythia8
1118 {
1120 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1121
1122 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1123
1124 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1125 }
1126
1127#include "AtlasPID.h"
1128
1130 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1131
1133 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1134
1136 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1137
1139 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1140
1142 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1143
1145 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1146
1148 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1149
1151 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1152
1154 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1155
1157 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1158
1162 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1163 const auto vertex = p->end_vertex();
1164 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1165 }
1166
1168 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1169
1171 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1172 const int apid = std::abs(p->pdg_id());
1173 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1174 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1175 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1176 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1177 return false;
1178 }
1179
1181
1182 template <class T> T findMother(T thePart) {
1183 auto partOriVert = thePart->production_vertex();
1184 if (!partOriVert) return nullptr;
1185
1186 long partPDG = thePart->pdg_id();
1187 long MotherPDG(0);
1188
1189 auto MothOriVert = partOriVert;
1190 MothOriVert = nullptr;
1191 T theMoth(nullptr);
1192
1193 size_t itr = 0;
1194 do {
1195 if (itr != 0) partOriVert = MothOriVert;
1196 for ( const auto& p : particles_in(partOriVert) ) {
1197 theMoth = p;
1198 if (!theMoth) continue;
1199 MotherPDG = theMoth->pdg_id();
1200 MothOriVert = theMoth->production_vertex();
1201 if (MotherPDG == partPDG) break;
1202 }
1203 itr++;
1204 if (itr > 100) {
1205 break;
1206 }
1207 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1208 MothOriVert != partOriVert);
1209 return theMoth;
1210 }
1211
1213
1214 template <class C, class T> T findMatching(C TruthContainer, T p) {
1215 T ptrPart = nullptr;
1216 if (!p) return ptrPart;
1217 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1218 for (T truthParticle : *TruthContainer) {
1219 if (HepMC::is_sim_descendant(p,truthParticle)) {
1220 ptrPart = truthParticle;
1221 break;
1222 }
1223 }
1224 }
1225 else {
1226 for (T truthParticle : TruthContainer) {
1227 if (HepMC::is_sim_descendant(p,truthParticle)) {
1228 ptrPart = truthParticle;
1229 break;
1230 }
1231 }
1232 }
1233 return ptrPart;
1234 }
1236
1237 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1238 auto prodVtx = thePart->production_vertex();
1239 if (!prodVtx) return;
1240 for (const auto& theMother: prodVtx->particles_in()) {
1241 if (!theMother) continue;
1242 allancestors.insert(theMother);
1243 findParticleAncestors(theMother, allancestors);
1244 }
1245 }
1246
1248
1249 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1250 auto endVtx = thePart->end_vertex();
1251 if (!endVtx) return;
1252 for (const auto& theDaughter: endVtx->particles_out()) {
1253 if (!theDaughter) continue;
1254 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1255 allstabledescendants.insert(theDaughter);
1256 }
1257 findParticleStableDescendants(theDaughter, allstabledescendants);
1258 }
1259 }
1260
1264
1265 template <class T> bool isHardScatteringVertex(T pVert) {
1266 if (pVert == nullptr) return false;
1267 T pV = pVert;
1268 int numOfPartIn(0);
1269 int pdg(0);
1270
1271 do {
1272 pVert = pV;
1273 auto incoming = pVert->particles_in();
1274 numOfPartIn = incoming.size();
1275 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1276 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1277
1278 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1279
1280 if (numOfPartIn == 2) {
1281 auto incoming = pVert->particles_in();
1282 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1283 }
1284 return false;
1285}
1286
1290
1291 template <class T, class U>
1292 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1293 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1294 auto vtx = p->production_vertex();
1295 if (!vtx) return false;
1296 bool fromHad = false;
1297 for ( const auto& parent : particles_in(vtx) ) {
1298 if (!parent) continue;
1299 // should this really go into parton-level territory?
1300 // probably depends where BSM particles are being decayed
1301 fromBSM |= isBSM(parent);
1302 if (!isPhysical(parent)) return false;
1303 fromTau |= isTau(parent);
1304 if (isHadron(parent)&&!isBeam(parent)) {
1305 if (!hadron) hadron = parent; // assumes linear hadron parentage
1306 return true;
1307 }
1308 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1309 }
1310 return fromHad;
1311 }
1312
1315
1316 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1317 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1318 decltype(thePart->end_vertex()) pVert(nullptr);
1319 if (EndVert != nullptr) {
1320 do {
1321 bool samePart = false;
1322 pVert = nullptr;
1323 auto outgoing = EndVert->particles_out();
1324 auto incoming = EndVert->particles_in();
1325 for (const auto& itrDaug: outgoing) {
1326 if (!itrDaug) continue;
1327 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1328 // brem on generator level for tau
1329 (outgoing.size() == 1 && incoming.size() == 1 &&
1331 itrDaug->pdg_id() == thePart->pdg_id()) {
1332 samePart = true;
1333 pVert = itrDaug->end_vertex();
1334 }
1335 }
1336 if (samePart) EndVert = pVert;
1337 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1338 }
1339 return EndVert;
1340 }
1341
1343
1344 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1345 if (!theVert) return {};
1346 decltype(theVert->particles_out()) finalStatePart;
1347 auto outgoing = theVert->particles_out();
1348 for (const auto& thePart: outgoing) {
1349 if (!thePart) continue;
1350 finalStatePart.push_back(thePart);
1351 if (isStable(thePart)) continue;
1352 V pVert = findSimulatedEndVertex(thePart);
1353 if (pVert == theVert) break; // to prevent Sherpa loop
1354 if (pVert != nullptr) {
1355 auto vecPart = findFinalStateParticles<V>(pVert);
1356 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1357 }
1358 }
1359 return finalStatePart;
1360 }
1361#if !defined(XAOD_ANALYSIS)
1362#include "AtlasHepMC/GenEvent.h"
1363inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1364inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1365
1366#endif
1367}
1368#endif

◆ isNeutral() [2/3]

template<>
bool MC::isNeutral ( const int & p)
inline

Definition at line 1093 of file HepMCHelpers.h.

1112{
1113 template <class VTX>
1114 auto particles_in (const VTX* p) { return p->particles_in(); }
1115 template <class VTX>
1116 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1117
1118 namespace Pythia8
1119 {
1121 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1122
1123 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1124
1125 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1126 }
1127
1128#include "AtlasPID.h"
1129
1131 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1132
1134 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1135
1137 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1138
1140 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1141
1143 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1144
1146 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1147
1149 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1150
1152 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1153
1155 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1156
1158 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1159
1163 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1164 const auto vertex = p->end_vertex();
1165 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1166 }
1167
1169 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1170
1172 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1173 const int apid = std::abs(p->pdg_id());
1174 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1175 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1176 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1177 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1178 return false;
1179 }
1180
1182
1183 template <class T> T findMother(T thePart) {
1184 auto partOriVert = thePart->production_vertex();
1185 if (!partOriVert) return nullptr;
1186
1187 long partPDG = thePart->pdg_id();
1188 long MotherPDG(0);
1189
1190 auto MothOriVert = partOriVert;
1191 MothOriVert = nullptr;
1192 T theMoth(nullptr);
1193
1194 size_t itr = 0;
1195 do {
1196 if (itr != 0) partOriVert = MothOriVert;
1197 for ( const auto& p : particles_in(partOriVert) ) {
1198 theMoth = p;
1199 if (!theMoth) continue;
1200 MotherPDG = theMoth->pdg_id();
1201 MothOriVert = theMoth->production_vertex();
1202 if (MotherPDG == partPDG) break;
1203 }
1204 itr++;
1205 if (itr > 100) {
1206 break;
1207 }
1208 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1209 MothOriVert != partOriVert);
1210 return theMoth;
1211 }
1212
1214
1215 template <class C, class T> T findMatching(C TruthContainer, T p) {
1216 T ptrPart = nullptr;
1217 if (!p) return ptrPart;
1218 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1219 for (T truthParticle : *TruthContainer) {
1220 if (HepMC::is_sim_descendant(p,truthParticle)) {
1221 ptrPart = truthParticle;
1222 break;
1223 }
1224 }
1225 }
1226 else {
1227 for (T truthParticle : TruthContainer) {
1228 if (HepMC::is_sim_descendant(p,truthParticle)) {
1229 ptrPart = truthParticle;
1230 break;
1231 }
1232 }
1233 }
1234 return ptrPart;
1235 }
1237
1238 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1239 auto prodVtx = thePart->production_vertex();
1240 if (!prodVtx) return;
1241 for (const auto& theMother: prodVtx->particles_in()) {
1242 if (!theMother) continue;
1243 allancestors.insert(theMother);
1244 findParticleAncestors(theMother, allancestors);
1245 }
1246 }
1247
1249
1250 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1251 auto endVtx = thePart->end_vertex();
1252 if (!endVtx) return;
1253 for (const auto& theDaughter: endVtx->particles_out()) {
1254 if (!theDaughter) continue;
1255 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1256 allstabledescendants.insert(theDaughter);
1257 }
1258 findParticleStableDescendants(theDaughter, allstabledescendants);
1259 }
1260 }
1261
1265
1266 template <class T> bool isHardScatteringVertex(T pVert) {
1267 if (pVert == nullptr) return false;
1268 T pV = pVert;
1269 int numOfPartIn(0);
1270 int pdg(0);
1271
1272 do {
1273 pVert = pV;
1274 auto incoming = pVert->particles_in();
1275 numOfPartIn = incoming.size();
1276 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1277 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1278
1279 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1280
1281 if (numOfPartIn == 2) {
1282 auto incoming = pVert->particles_in();
1283 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1284 }
1285 return false;
1286}
1287
1291
1292 template <class T, class U>
1293 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1294 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1295 auto vtx = p->production_vertex();
1296 if (!vtx) return false;
1297 bool fromHad = false;
1298 for ( const auto& parent : particles_in(vtx) ) {
1299 if (!parent) continue;
1300 // should this really go into parton-level territory?
1301 // probably depends where BSM particles are being decayed
1302 fromBSM |= isBSM(parent);
1303 if (!isPhysical(parent)) return false;
1304 fromTau |= isTau(parent);
1305 if (isHadron(parent)&&!isBeam(parent)) {
1306 if (!hadron) hadron = parent; // assumes linear hadron parentage
1307 return true;
1308 }
1309 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1310 }
1311 return fromHad;
1312 }
1313
1316
1317 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1318 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1319 decltype(thePart->end_vertex()) pVert(nullptr);
1320 if (EndVert != nullptr) {
1321 do {
1322 bool samePart = false;
1323 pVert = nullptr;
1324 auto outgoing = EndVert->particles_out();
1325 auto incoming = EndVert->particles_in();
1326 for (const auto& itrDaug: outgoing) {
1327 if (!itrDaug) continue;
1328 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1329 // brem on generator level for tau
1330 (outgoing.size() == 1 && incoming.size() == 1 &&
1332 itrDaug->pdg_id() == thePart->pdg_id()) {
1333 samePart = true;
1334 pVert = itrDaug->end_vertex();
1335 }
1336 }
1337 if (samePart) EndVert = pVert;
1338 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1339 }
1340 return EndVert;
1341 }
1342
1344
1345 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1346 if (!theVert) return {};
1347 decltype(theVert->particles_out()) finalStatePart;
1348 auto outgoing = theVert->particles_out();
1349 for (const auto& thePart: outgoing) {
1350 if (!thePart) continue;
1351 finalStatePart.push_back(thePart);
1352 if (isStable(thePart)) continue;
1353 V pVert = findSimulatedEndVertex(thePart);
1354 if (pVert == theVert) break; // to prevent Sherpa loop
1355 if (pVert != nullptr) {
1356 auto vecPart = findFinalStateParticles<V>(pVert);
1357 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1358 }
1359 }
1360 return finalStatePart;
1361 }
1362#if !defined(XAOD_ANALYSIS)
1363#include "AtlasHepMC/GenEvent.h"
1364inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1365inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1366
1367#endif
1368}
1369#endif

◆ isNeutral() [3/3]

template<class T>
bool MC::isNeutral ( const T & p)
inline

Definition at line 1091 of file HepMCHelpers.h.

1110{
1111 template <class VTX>
1112 auto particles_in (const VTX* p) { return p->particles_in(); }
1113 template <class VTX>
1114 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1115
1116 namespace Pythia8
1117 {
1119 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1120
1121 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1122
1123 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1124 }
1125
1126#include "AtlasPID.h"
1127
1129 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1130
1132 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1133
1135 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1136
1138 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1139
1141 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1142
1144 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1145
1147 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1148
1150 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1151
1153 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1154
1156 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1157
1161 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1162 const auto vertex = p->end_vertex();
1163 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1164 }
1165
1167 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1168
1170 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1171 const int apid = std::abs(p->pdg_id());
1172 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1173 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1174 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1175 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1176 return false;
1177 }
1178
1180
1181 template <class T> T findMother(T thePart) {
1182 auto partOriVert = thePart->production_vertex();
1183 if (!partOriVert) return nullptr;
1184
1185 long partPDG = thePart->pdg_id();
1186 long MotherPDG(0);
1187
1188 auto MothOriVert = partOriVert;
1189 MothOriVert = nullptr;
1190 T theMoth(nullptr);
1191
1192 size_t itr = 0;
1193 do {
1194 if (itr != 0) partOriVert = MothOriVert;
1195 for ( const auto& p : particles_in(partOriVert) ) {
1196 theMoth = p;
1197 if (!theMoth) continue;
1198 MotherPDG = theMoth->pdg_id();
1199 MothOriVert = theMoth->production_vertex();
1200 if (MotherPDG == partPDG) break;
1201 }
1202 itr++;
1203 if (itr > 100) {
1204 break;
1205 }
1206 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1207 MothOriVert != partOriVert);
1208 return theMoth;
1209 }
1210
1212
1213 template <class C, class T> T findMatching(C TruthContainer, T p) {
1214 T ptrPart = nullptr;
1215 if (!p) return ptrPart;
1216 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1217 for (T truthParticle : *TruthContainer) {
1218 if (HepMC::is_sim_descendant(p,truthParticle)) {
1219 ptrPart = truthParticle;
1220 break;
1221 }
1222 }
1223 }
1224 else {
1225 for (T truthParticle : TruthContainer) {
1226 if (HepMC::is_sim_descendant(p,truthParticle)) {
1227 ptrPart = truthParticle;
1228 break;
1229 }
1230 }
1231 }
1232 return ptrPart;
1233 }
1235
1236 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1237 auto prodVtx = thePart->production_vertex();
1238 if (!prodVtx) return;
1239 for (const auto& theMother: prodVtx->particles_in()) {
1240 if (!theMother) continue;
1241 allancestors.insert(theMother);
1242 findParticleAncestors(theMother, allancestors);
1243 }
1244 }
1245
1247
1248 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1249 auto endVtx = thePart->end_vertex();
1250 if (!endVtx) return;
1251 for (const auto& theDaughter: endVtx->particles_out()) {
1252 if (!theDaughter) continue;
1253 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1254 allstabledescendants.insert(theDaughter);
1255 }
1256 findParticleStableDescendants(theDaughter, allstabledescendants);
1257 }
1258 }
1259
1263
1264 template <class T> bool isHardScatteringVertex(T pVert) {
1265 if (pVert == nullptr) return false;
1266 T pV = pVert;
1267 int numOfPartIn(0);
1268 int pdg(0);
1269
1270 do {
1271 pVert = pV;
1272 auto incoming = pVert->particles_in();
1273 numOfPartIn = incoming.size();
1274 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1275 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1276
1277 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1278
1279 if (numOfPartIn == 2) {
1280 auto incoming = pVert->particles_in();
1281 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1282 }
1283 return false;
1284}
1285
1289
1290 template <class T, class U>
1291 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1292 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1293 auto vtx = p->production_vertex();
1294 if (!vtx) return false;
1295 bool fromHad = false;
1296 for ( const auto& parent : particles_in(vtx) ) {
1297 if (!parent) continue;
1298 // should this really go into parton-level territory?
1299 // probably depends where BSM particles are being decayed
1300 fromBSM |= isBSM(parent);
1301 if (!isPhysical(parent)) return false;
1302 fromTau |= isTau(parent);
1303 if (isHadron(parent)&&!isBeam(parent)) {
1304 if (!hadron) hadron = parent; // assumes linear hadron parentage
1305 return true;
1306 }
1307 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1308 }
1309 return fromHad;
1310 }
1311
1314
1315 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1316 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1317 decltype(thePart->end_vertex()) pVert(nullptr);
1318 if (EndVert != nullptr) {
1319 do {
1320 bool samePart = false;
1321 pVert = nullptr;
1322 auto outgoing = EndVert->particles_out();
1323 auto incoming = EndVert->particles_in();
1324 for (const auto& itrDaug: outgoing) {
1325 if (!itrDaug) continue;
1326 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1327 // brem on generator level for tau
1328 (outgoing.size() == 1 && incoming.size() == 1 &&
1330 itrDaug->pdg_id() == thePart->pdg_id()) {
1331 samePart = true;
1332 pVert = itrDaug->end_vertex();
1333 }
1334 }
1335 if (samePart) EndVert = pVert;
1336 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1337 }
1338 return EndVert;
1339 }
1340
1342
1343 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1344 if (!theVert) return {};
1345 decltype(theVert->particles_out()) finalStatePart;
1346 auto outgoing = theVert->particles_out();
1347 for (const auto& thePart: outgoing) {
1348 if (!thePart) continue;
1349 finalStatePart.push_back(thePart);
1350 if (isStable(thePart)) continue;
1351 V pVert = findSimulatedEndVertex(thePart);
1352 if (pVert == theVert) break; // to prevent Sherpa loop
1353 if (pVert != nullptr) {
1354 auto vecPart = findFinalStateParticles<V>(pVert);
1355 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1356 }
1357 }
1358 return finalStatePart;
1359 }
1360#if !defined(XAOD_ANALYSIS)
1361#include "AtlasHepMC/GenEvent.h"
1362inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1363inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1364
1365#endif
1366}
1367#endif

◆ isNeutrino() [1/2]

template<>
bool MC::isNeutrino ( const int & p)
inline

Definition at line 214 of file HepMCHelpers.h.

◆ isNeutrino() [2/2]

template<class T>
bool MC::isNeutrino ( const T & p)
inline

APID: the fourth generation neutrinos are neutrinos.

Definition at line 213 of file HepMCHelpers.h.

213{

◆ isNeutrinoRH() [1/2]

template<>
bool MC::isNeutrinoRH ( const int & p)
inline

Definition at line 422 of file HepMCHelpers.h.

441{
442 template <class VTX>
443 auto particles_in (const VTX* p) { return p->particles_in(); }
444 template <class VTX>
445 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
446
447 namespace Pythia8
448 {
450 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
451
452 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
453
454 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
455 }
456
457#include "AtlasPID.h"
458
460 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
461
463 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
464
466 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
467
469 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
470
472 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
473
475 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
476
478 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
479
481 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
482
484 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
485
487 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
488
492 template <class T> inline bool isStableOrSimDecayed(const T& p) {
493 const auto vertex = p->end_vertex();
494 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
495 }
496
498 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
499
501 template <class T> inline bool isSpecialNonInteracting(const T& p) {
502 const int apid = std::abs(p->pdg_id());
503 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
504 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
505 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
506 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
507 return false;
508 }
509
511
512 template <class T> T findMother(T thePart) {
513 auto partOriVert = thePart->production_vertex();
514 if (!partOriVert) return nullptr;
515
516 long partPDG = thePart->pdg_id();
517 long MotherPDG(0);
518
519 auto MothOriVert = partOriVert;
520 MothOriVert = nullptr;
521 T theMoth(nullptr);
522
523 size_t itr = 0;
524 do {
525 if (itr != 0) partOriVert = MothOriVert;
526 for ( const auto& p : particles_in(partOriVert) ) {
527 theMoth = p;
528 if (!theMoth) continue;
529 MotherPDG = theMoth->pdg_id();
530 MothOriVert = theMoth->production_vertex();
531 if (MotherPDG == partPDG) break;
532 }
533 itr++;
534 if (itr > 100) {
535 break;
536 }
537 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
538 MothOriVert != partOriVert);
539 return theMoth;
540 }
541
543
544 template <class C, class T> T findMatching(C TruthContainer, T p) {
545 T ptrPart = nullptr;
546 if (!p) return ptrPart;
547 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
548 for (T truthParticle : *TruthContainer) {
549 if (HepMC::is_sim_descendant(p,truthParticle)) {
550 ptrPart = truthParticle;
551 break;
552 }
553 }
554 }
555 else {
556 for (T truthParticle : TruthContainer) {
557 if (HepMC::is_sim_descendant(p,truthParticle)) {
558 ptrPart = truthParticle;
559 break;
560 }
561 }
562 }
563 return ptrPart;
564 }
566
567 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
568 auto prodVtx = thePart->production_vertex();
569 if (!prodVtx) return;
570 for (const auto& theMother: prodVtx->particles_in()) {
571 if (!theMother) continue;
572 allancestors.insert(theMother);
573 findParticleAncestors(theMother, allancestors);
574 }
575 }
576
578
579 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
580 auto endVtx = thePart->end_vertex();
581 if (!endVtx) return;
582 for (const auto& theDaughter: endVtx->particles_out()) {
583 if (!theDaughter) continue;
584 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
585 allstabledescendants.insert(theDaughter);
586 }
587 findParticleStableDescendants(theDaughter, allstabledescendants);
588 }
589 }
590
594
595 template <class T> bool isHardScatteringVertex(T pVert) {
596 if (pVert == nullptr) return false;
597 T pV = pVert;
598 int numOfPartIn(0);
599 int pdg(0);
600
601 do {
602 pVert = pV;
603 auto incoming = pVert->particles_in();
604 numOfPartIn = incoming.size();
605 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
606 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
607
608 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
609
610 if (numOfPartIn == 2) {
611 auto incoming = pVert->particles_in();
612 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
613 }
614 return false;
615}
616
620
621 template <class T, class U>
622 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
623 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
624 auto vtx = p->production_vertex();
625 if (!vtx) return false;
626 bool fromHad = false;
627 for ( const auto& parent : particles_in(vtx) ) {
628 if (!parent) continue;
629 // should this really go into parton-level territory?
630 // probably depends where BSM particles are being decayed
631 fromBSM |= isBSM(parent);
632 if (!isPhysical(parent)) return false;
633 fromTau |= isTau(parent);
634 if (isHadron(parent)&&!isBeam(parent)) {
635 if (!hadron) hadron = parent; // assumes linear hadron parentage
636 return true;
637 }
638 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
639 }
640 return fromHad;
641 }
642
645
646 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
647 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
648 decltype(thePart->end_vertex()) pVert(nullptr);
649 if (EndVert != nullptr) {
650 do {
651 bool samePart = false;
652 pVert = nullptr;
653 auto outgoing = EndVert->particles_out();
654 auto incoming = EndVert->particles_in();
655 for (const auto& itrDaug: outgoing) {
656 if (!itrDaug) continue;
657 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
658 // brem on generator level for tau
659 (outgoing.size() == 1 && incoming.size() == 1 &&
661 itrDaug->pdg_id() == thePart->pdg_id()) {
662 samePart = true;
663 pVert = itrDaug->end_vertex();
664 }
665 }
666 if (samePart) EndVert = pVert;
667 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
668 }
669 return EndVert;
670 }
671
673
674 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
675 if (!theVert) return {};
676 decltype(theVert->particles_out()) finalStatePart;
677 auto outgoing = theVert->particles_out();
678 for (const auto& thePart: outgoing) {
679 if (!thePart) continue;
680 finalStatePart.push_back(thePart);
681 if (isStable(thePart)) continue;
682 V pVert = findSimulatedEndVertex(thePart);
683 if (pVert == theVert) break; // to prevent Sherpa loop
684 if (pVert != nullptr) {
685 auto vecPart = findFinalStateParticles<V>(pVert);
686 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
687 }
688 }
689 return finalStatePart;
690 }
691#if !defined(XAOD_ANALYSIS)
692#include "AtlasHepMC/GenEvent.h"
693inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
694inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
695
696#endif
697}
698#endif

◆ isNeutrinoRH() [2/2]

template<class T>
bool MC::isNeutrinoRH ( const T & p)
inline

PDG Rule 12: APID: Helper function for right-handed neutrino states These are generator defined PDG ID values for right handed neutrinos.

(Defined for some MadGraph+Pythia8 samples and referenced in MCTruthClassifierGen.cxx)

Definition at line 421 of file HepMCHelpers.h.

440{
441 template <class VTX>
442 auto particles_in (const VTX* p) { return p->particles_in(); }
443 template <class VTX>
444 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
445
446 namespace Pythia8
447 {
449 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
450
451 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
452
453 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
454 }
455
456#include "AtlasPID.h"
457
459 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
460
462 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
463
465 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
466
468 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
469
471 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
472
474 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
475
477 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
478
480 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
481
483 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
484
486 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
487
491 template <class T> inline bool isStableOrSimDecayed(const T& p) {
492 const auto vertex = p->end_vertex();
493 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
494 }
495
497 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
498
500 template <class T> inline bool isSpecialNonInteracting(const T& p) {
501 const int apid = std::abs(p->pdg_id());
502 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
503 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
504 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
505 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
506 return false;
507 }
508
510
511 template <class T> T findMother(T thePart) {
512 auto partOriVert = thePart->production_vertex();
513 if (!partOriVert) return nullptr;
514
515 long partPDG = thePart->pdg_id();
516 long MotherPDG(0);
517
518 auto MothOriVert = partOriVert;
519 MothOriVert = nullptr;
520 T theMoth(nullptr);
521
522 size_t itr = 0;
523 do {
524 if (itr != 0) partOriVert = MothOriVert;
525 for ( const auto& p : particles_in(partOriVert) ) {
526 theMoth = p;
527 if (!theMoth) continue;
528 MotherPDG = theMoth->pdg_id();
529 MothOriVert = theMoth->production_vertex();
530 if (MotherPDG == partPDG) break;
531 }
532 itr++;
533 if (itr > 100) {
534 break;
535 }
536 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
537 MothOriVert != partOriVert);
538 return theMoth;
539 }
540
542
543 template <class C, class T> T findMatching(C TruthContainer, T p) {
544 T ptrPart = nullptr;
545 if (!p) return ptrPart;
546 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
547 for (T truthParticle : *TruthContainer) {
548 if (HepMC::is_sim_descendant(p,truthParticle)) {
549 ptrPart = truthParticle;
550 break;
551 }
552 }
553 }
554 else {
555 for (T truthParticle : TruthContainer) {
556 if (HepMC::is_sim_descendant(p,truthParticle)) {
557 ptrPart = truthParticle;
558 break;
559 }
560 }
561 }
562 return ptrPart;
563 }
565
566 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
567 auto prodVtx = thePart->production_vertex();
568 if (!prodVtx) return;
569 for (const auto& theMother: prodVtx->particles_in()) {
570 if (!theMother) continue;
571 allancestors.insert(theMother);
572 findParticleAncestors(theMother, allancestors);
573 }
574 }
575
577
578 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
579 auto endVtx = thePart->end_vertex();
580 if (!endVtx) return;
581 for (const auto& theDaughter: endVtx->particles_out()) {
582 if (!theDaughter) continue;
583 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
584 allstabledescendants.insert(theDaughter);
585 }
586 findParticleStableDescendants(theDaughter, allstabledescendants);
587 }
588 }
589
593
594 template <class T> bool isHardScatteringVertex(T pVert) {
595 if (pVert == nullptr) return false;
596 T pV = pVert;
597 int numOfPartIn(0);
598 int pdg(0);
599
600 do {
601 pVert = pV;
602 auto incoming = pVert->particles_in();
603 numOfPartIn = incoming.size();
604 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
605 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
606
607 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
608
609 if (numOfPartIn == 2) {
610 auto incoming = pVert->particles_in();
611 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
612 }
613 return false;
614}
615
619
620 template <class T, class U>
621 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
622 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
623 auto vtx = p->production_vertex();
624 if (!vtx) return false;
625 bool fromHad = false;
626 for ( const auto& parent : particles_in(vtx) ) {
627 if (!parent) continue;
628 // should this really go into parton-level territory?
629 // probably depends where BSM particles are being decayed
630 fromBSM |= isBSM(parent);
631 if (!isPhysical(parent)) return false;
632 fromTau |= isTau(parent);
633 if (isHadron(parent)&&!isBeam(parent)) {
634 if (!hadron) hadron = parent; // assumes linear hadron parentage
635 return true;
636 }
637 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
638 }
639 return fromHad;
640 }
641
644
645 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
646 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
647 decltype(thePart->end_vertex()) pVert(nullptr);
648 if (EndVert != nullptr) {
649 do {
650 bool samePart = false;
651 pVert = nullptr;
652 auto outgoing = EndVert->particles_out();
653 auto incoming = EndVert->particles_in();
654 for (const auto& itrDaug: outgoing) {
655 if (!itrDaug) continue;
656 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
657 // brem on generator level for tau
658 (outgoing.size() == 1 && incoming.size() == 1 &&
660 itrDaug->pdg_id() == thePart->pdg_id()) {
661 samePart = true;
662 pVert = itrDaug->end_vertex();
663 }
664 }
665 if (samePart) EndVert = pVert;
666 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
667 }
668 return EndVert;
669 }
670
672
673 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
674 if (!theVert) return {};
675 decltype(theVert->particles_out()) finalStatePart;
676 auto outgoing = theVert->particles_out();
677 for (const auto& thePart: outgoing) {
678 if (!thePart) continue;
679 finalStatePart.push_back(thePart);
680 if (isStable(thePart)) continue;
681 V pVert = findSimulatedEndVertex(thePart);
682 if (pVert == theVert) break; // to prevent Sherpa loop
683 if (pVert != nullptr) {
684 auto vecPart = findFinalStateParticles<V>(pVert);
685 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
686 }
687 }
688 return finalStatePart;
689 }
690#if !defined(XAOD_ANALYSIS)
691#include "AtlasHepMC/GenEvent.h"
692inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
693inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
694
695#endif
696}
697#endif

◆ isNucleus() [1/3]

template<>
bool MC::isNucleus ( const DecodedPID & p)
inline

Definition at line 704 of file HepMCHelpers.h.

723{
724 template <class VTX>
725 auto particles_in (const VTX* p) { return p->particles_in(); }
726 template <class VTX>
727 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
728
729 namespace Pythia8
730 {
732 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
733
734 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
735
736 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
737 }
738
739#include "AtlasPID.h"
740
742 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
743
745 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
746
748 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
749
751 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
752
754 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
755
757 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
758
760 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
761
763 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
764
766 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
767
769 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
770
774 template <class T> inline bool isStableOrSimDecayed(const T& p) {
775 const auto vertex = p->end_vertex();
776 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
777 }
778
780 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
781
783 template <class T> inline bool isSpecialNonInteracting(const T& p) {
784 const int apid = std::abs(p->pdg_id());
785 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
786 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
787 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
788 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
789 return false;
790 }
791
793
794 template <class T> T findMother(T thePart) {
795 auto partOriVert = thePart->production_vertex();
796 if (!partOriVert) return nullptr;
797
798 long partPDG = thePart->pdg_id();
799 long MotherPDG(0);
800
801 auto MothOriVert = partOriVert;
802 MothOriVert = nullptr;
803 T theMoth(nullptr);
804
805 size_t itr = 0;
806 do {
807 if (itr != 0) partOriVert = MothOriVert;
808 for ( const auto& p : particles_in(partOriVert) ) {
809 theMoth = p;
810 if (!theMoth) continue;
811 MotherPDG = theMoth->pdg_id();
812 MothOriVert = theMoth->production_vertex();
813 if (MotherPDG == partPDG) break;
814 }
815 itr++;
816 if (itr > 100) {
817 break;
818 }
819 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
820 MothOriVert != partOriVert);
821 return theMoth;
822 }
823
825
826 template <class C, class T> T findMatching(C TruthContainer, T p) {
827 T ptrPart = nullptr;
828 if (!p) return ptrPart;
829 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
830 for (T truthParticle : *TruthContainer) {
831 if (HepMC::is_sim_descendant(p,truthParticle)) {
832 ptrPart = truthParticle;
833 break;
834 }
835 }
836 }
837 else {
838 for (T truthParticle : TruthContainer) {
839 if (HepMC::is_sim_descendant(p,truthParticle)) {
840 ptrPart = truthParticle;
841 break;
842 }
843 }
844 }
845 return ptrPart;
846 }
848
849 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
850 auto prodVtx = thePart->production_vertex();
851 if (!prodVtx) return;
852 for (const auto& theMother: prodVtx->particles_in()) {
853 if (!theMother) continue;
854 allancestors.insert(theMother);
855 findParticleAncestors(theMother, allancestors);
856 }
857 }
858
860
861 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
862 auto endVtx = thePart->end_vertex();
863 if (!endVtx) return;
864 for (const auto& theDaughter: endVtx->particles_out()) {
865 if (!theDaughter) continue;
866 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
867 allstabledescendants.insert(theDaughter);
868 }
869 findParticleStableDescendants(theDaughter, allstabledescendants);
870 }
871 }
872
876
877 template <class T> bool isHardScatteringVertex(T pVert) {
878 if (pVert == nullptr) return false;
879 T pV = pVert;
880 int numOfPartIn(0);
881 int pdg(0);
882
883 do {
884 pVert = pV;
885 auto incoming = pVert->particles_in();
886 numOfPartIn = incoming.size();
887 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
888 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
889
890 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
891
892 if (numOfPartIn == 2) {
893 auto incoming = pVert->particles_in();
894 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
895 }
896 return false;
897}
898
902
903 template <class T, class U>
904 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
905 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
906 auto vtx = p->production_vertex();
907 if (!vtx) return false;
908 bool fromHad = false;
909 for ( const auto& parent : particles_in(vtx) ) {
910 if (!parent) continue;
911 // should this really go into parton-level territory?
912 // probably depends where BSM particles are being decayed
913 fromBSM |= isBSM(parent);
914 if (!isPhysical(parent)) return false;
915 fromTau |= isTau(parent);
916 if (isHadron(parent)&&!isBeam(parent)) {
917 if (!hadron) hadron = parent; // assumes linear hadron parentage
918 return true;
919 }
920 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
921 }
922 return fromHad;
923 }
924
927
928 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
929 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
930 decltype(thePart->end_vertex()) pVert(nullptr);
931 if (EndVert != nullptr) {
932 do {
933 bool samePart = false;
934 pVert = nullptr;
935 auto outgoing = EndVert->particles_out();
936 auto incoming = EndVert->particles_in();
937 for (const auto& itrDaug: outgoing) {
938 if (!itrDaug) continue;
939 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
940 // brem on generator level for tau
941 (outgoing.size() == 1 && incoming.size() == 1 &&
943 itrDaug->pdg_id() == thePart->pdg_id()) {
944 samePart = true;
945 pVert = itrDaug->end_vertex();
946 }
947 }
948 if (samePart) EndVert = pVert;
949 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
950 }
951 return EndVert;
952 }
953
955
956 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
957 if (!theVert) return {};
958 decltype(theVert->particles_out()) finalStatePart;
959 auto outgoing = theVert->particles_out();
960 for (const auto& thePart: outgoing) {
961 if (!thePart) continue;
962 finalStatePart.push_back(thePart);
963 if (isStable(thePart)) continue;
964 V pVert = findSimulatedEndVertex(thePart);
965 if (pVert == theVert) break; // to prevent Sherpa loop
966 if (pVert != nullptr) {
967 auto vecPart = findFinalStateParticles<V>(pVert);
968 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
969 }
970 }
971 return finalStatePart;
972 }
973#if !defined(XAOD_ANALYSIS)
974#include "AtlasHepMC/GenEvent.h"
975inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
976inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
977
978#endif
979}
980#endif

◆ isNucleus() [2/3]

template<>
bool MC::isNucleus ( const int & p)
inline

Definition at line 713 of file HepMCHelpers.h.

732{
733 template <class VTX>
734 auto particles_in (const VTX* p) { return p->particles_in(); }
735 template <class VTX>
736 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
737
738 namespace Pythia8
739 {
741 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
742
743 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
744
745 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
746 }
747
748#include "AtlasPID.h"
749
751 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
752
754 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
755
757 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
758
760 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
761
763 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
764
766 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
767
769 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
770
772 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
773
775 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
776
778 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
779
783 template <class T> inline bool isStableOrSimDecayed(const T& p) {
784 const auto vertex = p->end_vertex();
785 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
786 }
787
789 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
790
792 template <class T> inline bool isSpecialNonInteracting(const T& p) {
793 const int apid = std::abs(p->pdg_id());
794 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
795 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
796 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
797 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
798 return false;
799 }
800
802
803 template <class T> T findMother(T thePart) {
804 auto partOriVert = thePart->production_vertex();
805 if (!partOriVert) return nullptr;
806
807 long partPDG = thePart->pdg_id();
808 long MotherPDG(0);
809
810 auto MothOriVert = partOriVert;
811 MothOriVert = nullptr;
812 T theMoth(nullptr);
813
814 size_t itr = 0;
815 do {
816 if (itr != 0) partOriVert = MothOriVert;
817 for ( const auto& p : particles_in(partOriVert) ) {
818 theMoth = p;
819 if (!theMoth) continue;
820 MotherPDG = theMoth->pdg_id();
821 MothOriVert = theMoth->production_vertex();
822 if (MotherPDG == partPDG) break;
823 }
824 itr++;
825 if (itr > 100) {
826 break;
827 }
828 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
829 MothOriVert != partOriVert);
830 return theMoth;
831 }
832
834
835 template <class C, class T> T findMatching(C TruthContainer, T p) {
836 T ptrPart = nullptr;
837 if (!p) return ptrPart;
838 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
839 for (T truthParticle : *TruthContainer) {
840 if (HepMC::is_sim_descendant(p,truthParticle)) {
841 ptrPart = truthParticle;
842 break;
843 }
844 }
845 }
846 else {
847 for (T truthParticle : TruthContainer) {
848 if (HepMC::is_sim_descendant(p,truthParticle)) {
849 ptrPart = truthParticle;
850 break;
851 }
852 }
853 }
854 return ptrPart;
855 }
857
858 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
859 auto prodVtx = thePart->production_vertex();
860 if (!prodVtx) return;
861 for (const auto& theMother: prodVtx->particles_in()) {
862 if (!theMother) continue;
863 allancestors.insert(theMother);
864 findParticleAncestors(theMother, allancestors);
865 }
866 }
867
869
870 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
871 auto endVtx = thePart->end_vertex();
872 if (!endVtx) return;
873 for (const auto& theDaughter: endVtx->particles_out()) {
874 if (!theDaughter) continue;
875 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
876 allstabledescendants.insert(theDaughter);
877 }
878 findParticleStableDescendants(theDaughter, allstabledescendants);
879 }
880 }
881
885
886 template <class T> bool isHardScatteringVertex(T pVert) {
887 if (pVert == nullptr) return false;
888 T pV = pVert;
889 int numOfPartIn(0);
890 int pdg(0);
891
892 do {
893 pVert = pV;
894 auto incoming = pVert->particles_in();
895 numOfPartIn = incoming.size();
896 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
897 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
898
899 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
900
901 if (numOfPartIn == 2) {
902 auto incoming = pVert->particles_in();
903 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
904 }
905 return false;
906}
907
911
912 template <class T, class U>
913 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
914 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
915 auto vtx = p->production_vertex();
916 if (!vtx) return false;
917 bool fromHad = false;
918 for ( const auto& parent : particles_in(vtx) ) {
919 if (!parent) continue;
920 // should this really go into parton-level territory?
921 // probably depends where BSM particles are being decayed
922 fromBSM |= isBSM(parent);
923 if (!isPhysical(parent)) return false;
924 fromTau |= isTau(parent);
925 if (isHadron(parent)&&!isBeam(parent)) {
926 if (!hadron) hadron = parent; // assumes linear hadron parentage
927 return true;
928 }
929 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
930 }
931 return fromHad;
932 }
933
936
937 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
938 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
939 decltype(thePart->end_vertex()) pVert(nullptr);
940 if (EndVert != nullptr) {
941 do {
942 bool samePart = false;
943 pVert = nullptr;
944 auto outgoing = EndVert->particles_out();
945 auto incoming = EndVert->particles_in();
946 for (const auto& itrDaug: outgoing) {
947 if (!itrDaug) continue;
948 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
949 // brem on generator level for tau
950 (outgoing.size() == 1 && incoming.size() == 1 &&
952 itrDaug->pdg_id() == thePart->pdg_id()) {
953 samePart = true;
954 pVert = itrDaug->end_vertex();
955 }
956 }
957 if (samePart) EndVert = pVert;
958 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
959 }
960 return EndVert;
961 }
962
964
965 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
966 if (!theVert) return {};
967 decltype(theVert->particles_out()) finalStatePart;
968 auto outgoing = theVert->particles_out();
969 for (const auto& thePart: outgoing) {
970 if (!thePart) continue;
971 finalStatePart.push_back(thePart);
972 if (isStable(thePart)) continue;
973 V pVert = findSimulatedEndVertex(thePart);
974 if (pVert == theVert) break; // to prevent Sherpa loop
975 if (pVert != nullptr) {
976 auto vecPart = findFinalStateParticles<V>(pVert);
977 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
978 }
979 }
980 return finalStatePart;
981 }
982#if !defined(XAOD_ANALYSIS)
983#include "AtlasHepMC/GenEvent.h"
984inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
985inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
986
987#endif
988}
989#endif

◆ isNucleus() [3/3]

template<class T>
bool MC::isNucleus ( const T & p)
inline

PDG rule 16 Nuclear codes are given as 10-digit numbers ±10LZZZAAAI.

For a (hyper)nucleus consisting of n_p protons, n_n neutrons and n_Λ Λ’s: A = n_p + n_n + n_Λ gives the total baryon number, Z = n_p gives the total charge, L = n_Λ gives the total number of strange quarks. I gives the isomer level, with I= 0 corresponding to the ground state and I > 0 to excitations, see [http://www.nndc.bnl.gov/amdc/web/nubase en.html], where states denoted m, n, p ,q translate to I= 1–4. As examples, the deuteron is 1000010020 and 235U is 1000922350. To avoid ambiguities, nuclear codes should not be applied to a single hadron, like p, n or Λ^0, where quark-contents-based codes already exist.

Definition at line 703 of file HepMCHelpers.h.

722{
723 template <class VTX>
724 auto particles_in (const VTX* p) { return p->particles_in(); }
725 template <class VTX>
726 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
727
728 namespace Pythia8
729 {
731 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
732
733 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
734
735 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
736 }
737
738#include "AtlasPID.h"
739
741 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
742
744 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
745
747 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
748
750 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
751
753 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
754
756 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
757
759 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
760
762 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
763
765 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
766
768 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
769
773 template <class T> inline bool isStableOrSimDecayed(const T& p) {
774 const auto vertex = p->end_vertex();
775 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
776 }
777
779 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
780
782 template <class T> inline bool isSpecialNonInteracting(const T& p) {
783 const int apid = std::abs(p->pdg_id());
784 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
785 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
786 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
787 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
788 return false;
789 }
790
792
793 template <class T> T findMother(T thePart) {
794 auto partOriVert = thePart->production_vertex();
795 if (!partOriVert) return nullptr;
796
797 long partPDG = thePart->pdg_id();
798 long MotherPDG(0);
799
800 auto MothOriVert = partOriVert;
801 MothOriVert = nullptr;
802 T theMoth(nullptr);
803
804 size_t itr = 0;
805 do {
806 if (itr != 0) partOriVert = MothOriVert;
807 for ( const auto& p : particles_in(partOriVert) ) {
808 theMoth = p;
809 if (!theMoth) continue;
810 MotherPDG = theMoth->pdg_id();
811 MothOriVert = theMoth->production_vertex();
812 if (MotherPDG == partPDG) break;
813 }
814 itr++;
815 if (itr > 100) {
816 break;
817 }
818 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
819 MothOriVert != partOriVert);
820 return theMoth;
821 }
822
824
825 template <class C, class T> T findMatching(C TruthContainer, T p) {
826 T ptrPart = nullptr;
827 if (!p) return ptrPart;
828 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
829 for (T truthParticle : *TruthContainer) {
830 if (HepMC::is_sim_descendant(p,truthParticle)) {
831 ptrPart = truthParticle;
832 break;
833 }
834 }
835 }
836 else {
837 for (T truthParticle : TruthContainer) {
838 if (HepMC::is_sim_descendant(p,truthParticle)) {
839 ptrPart = truthParticle;
840 break;
841 }
842 }
843 }
844 return ptrPart;
845 }
847
848 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
849 auto prodVtx = thePart->production_vertex();
850 if (!prodVtx) return;
851 for (const auto& theMother: prodVtx->particles_in()) {
852 if (!theMother) continue;
853 allancestors.insert(theMother);
854 findParticleAncestors(theMother, allancestors);
855 }
856 }
857
859
860 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
861 auto endVtx = thePart->end_vertex();
862 if (!endVtx) return;
863 for (const auto& theDaughter: endVtx->particles_out()) {
864 if (!theDaughter) continue;
865 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
866 allstabledescendants.insert(theDaughter);
867 }
868 findParticleStableDescendants(theDaughter, allstabledescendants);
869 }
870 }
871
875
876 template <class T> bool isHardScatteringVertex(T pVert) {
877 if (pVert == nullptr) return false;
878 T pV = pVert;
879 int numOfPartIn(0);
880 int pdg(0);
881
882 do {
883 pVert = pV;
884 auto incoming = pVert->particles_in();
885 numOfPartIn = incoming.size();
886 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
887 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
888
889 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
890
891 if (numOfPartIn == 2) {
892 auto incoming = pVert->particles_in();
893 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
894 }
895 return false;
896}
897
901
902 template <class T, class U>
903 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
904 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
905 auto vtx = p->production_vertex();
906 if (!vtx) return false;
907 bool fromHad = false;
908 for ( const auto& parent : particles_in(vtx) ) {
909 if (!parent) continue;
910 // should this really go into parton-level territory?
911 // probably depends where BSM particles are being decayed
912 fromBSM |= isBSM(parent);
913 if (!isPhysical(parent)) return false;
914 fromTau |= isTau(parent);
915 if (isHadron(parent)&&!isBeam(parent)) {
916 if (!hadron) hadron = parent; // assumes linear hadron parentage
917 return true;
918 }
919 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
920 }
921 return fromHad;
922 }
923
926
927 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
928 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
929 decltype(thePart->end_vertex()) pVert(nullptr);
930 if (EndVert != nullptr) {
931 do {
932 bool samePart = false;
933 pVert = nullptr;
934 auto outgoing = EndVert->particles_out();
935 auto incoming = EndVert->particles_in();
936 for (const auto& itrDaug: outgoing) {
937 if (!itrDaug) continue;
938 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
939 // brem on generator level for tau
940 (outgoing.size() == 1 && incoming.size() == 1 &&
942 itrDaug->pdg_id() == thePart->pdg_id()) {
943 samePart = true;
944 pVert = itrDaug->end_vertex();
945 }
946 }
947 if (samePart) EndVert = pVert;
948 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
949 }
950 return EndVert;
951 }
952
954
955 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
956 if (!theVert) return {};
957 decltype(theVert->particles_out()) finalStatePart;
958 auto outgoing = theVert->particles_out();
959 for (const auto& thePart: outgoing) {
960 if (!thePart) continue;
961 finalStatePart.push_back(thePart);
962 if (isStable(thePart)) continue;
963 V pVert = findSimulatedEndVertex(thePart);
964 if (pVert == theVert) break; // to prevent Sherpa loop
965 if (pVert != nullptr) {
966 auto vecPart = findFinalStateParticles<V>(pVert);
967 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
968 }
969 }
970 return finalStatePart;
971 }
972#if !defined(XAOD_ANALYSIS)
973#include "AtlasHepMC/GenEvent.h"
974inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
975inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
976
977#endif
978}
979#endif

◆ isParton()

template<class T>
bool MC::isParton ( const T & p)
inline

Definition at line 1109 of file HepMCHelpers.h.

1128{
1129 template <class VTX>
1130 auto particles_in (const VTX* p) { return p->particles_in(); }
1131 template <class VTX>
1132 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1133
1134 namespace Pythia8
1135 {
1137 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1138
1139 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1140
1141 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1142 }
1143
1144#include "AtlasPID.h"
1145
1147 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1148
1150 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1151
1153 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1154
1156 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1157
1159 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1160
1162 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1163
1165 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1166
1168 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1169
1171 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1172
1174 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1175
1179 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1180 const auto vertex = p->end_vertex();
1181 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1182 }
1183
1185 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1186
1188 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1189 const int apid = std::abs(p->pdg_id());
1190 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1191 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1192 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1193 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1194 return false;
1195 }
1196
1198
1199 template <class T> T findMother(T thePart) {
1200 auto partOriVert = thePart->production_vertex();
1201 if (!partOriVert) return nullptr;
1202
1203 long partPDG = thePart->pdg_id();
1204 long MotherPDG(0);
1205
1206 auto MothOriVert = partOriVert;
1207 MothOriVert = nullptr;
1208 T theMoth(nullptr);
1209
1210 size_t itr = 0;
1211 do {
1212 if (itr != 0) partOriVert = MothOriVert;
1213 for ( const auto& p : particles_in(partOriVert) ) {
1214 theMoth = p;
1215 if (!theMoth) continue;
1216 MotherPDG = theMoth->pdg_id();
1217 MothOriVert = theMoth->production_vertex();
1218 if (MotherPDG == partPDG) break;
1219 }
1220 itr++;
1221 if (itr > 100) {
1222 break;
1223 }
1224 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1225 MothOriVert != partOriVert);
1226 return theMoth;
1227 }
1228
1230
1231 template <class C, class T> T findMatching(C TruthContainer, T p) {
1232 T ptrPart = nullptr;
1233 if (!p) return ptrPart;
1234 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1235 for (T truthParticle : *TruthContainer) {
1236 if (HepMC::is_sim_descendant(p,truthParticle)) {
1237 ptrPart = truthParticle;
1238 break;
1239 }
1240 }
1241 }
1242 else {
1243 for (T truthParticle : TruthContainer) {
1244 if (HepMC::is_sim_descendant(p,truthParticle)) {
1245 ptrPart = truthParticle;
1246 break;
1247 }
1248 }
1249 }
1250 return ptrPart;
1251 }
1253
1254 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1255 auto prodVtx = thePart->production_vertex();
1256 if (!prodVtx) return;
1257 for (const auto& theMother: prodVtx->particles_in()) {
1258 if (!theMother) continue;
1259 allancestors.insert(theMother);
1260 findParticleAncestors(theMother, allancestors);
1261 }
1262 }
1263
1265
1266 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1267 auto endVtx = thePart->end_vertex();
1268 if (!endVtx) return;
1269 for (const auto& theDaughter: endVtx->particles_out()) {
1270 if (!theDaughter) continue;
1271 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1272 allstabledescendants.insert(theDaughter);
1273 }
1274 findParticleStableDescendants(theDaughter, allstabledescendants);
1275 }
1276 }
1277
1281
1282 template <class T> bool isHardScatteringVertex(T pVert) {
1283 if (pVert == nullptr) return false;
1284 T pV = pVert;
1285 int numOfPartIn(0);
1286 int pdg(0);
1287
1288 do {
1289 pVert = pV;
1290 auto incoming = pVert->particles_in();
1291 numOfPartIn = incoming.size();
1292 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1293 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1294
1295 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1296
1297 if (numOfPartIn == 2) {
1298 auto incoming = pVert->particles_in();
1299 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1300 }
1301 return false;
1302}
1303
1307
1308 template <class T, class U>
1309 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1310 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1311 auto vtx = p->production_vertex();
1312 if (!vtx) return false;
1313 bool fromHad = false;
1314 for ( const auto& parent : particles_in(vtx) ) {
1315 if (!parent) continue;
1316 // should this really go into parton-level territory?
1317 // probably depends where BSM particles are being decayed
1318 fromBSM |= isBSM(parent);
1319 if (!isPhysical(parent)) return false;
1320 fromTau |= isTau(parent);
1321 if (isHadron(parent)&&!isBeam(parent)) {
1322 if (!hadron) hadron = parent; // assumes linear hadron parentage
1323 return true;
1324 }
1325 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1326 }
1327 return fromHad;
1328 }
1329
1332
1333 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1334 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1335 decltype(thePart->end_vertex()) pVert(nullptr);
1336 if (EndVert != nullptr) {
1337 do {
1338 bool samePart = false;
1339 pVert = nullptr;
1340 auto outgoing = EndVert->particles_out();
1341 auto incoming = EndVert->particles_in();
1342 for (const auto& itrDaug: outgoing) {
1343 if (!itrDaug) continue;
1344 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1345 // brem on generator level for tau
1346 (outgoing.size() == 1 && incoming.size() == 1 &&
1348 itrDaug->pdg_id() == thePart->pdg_id()) {
1349 samePart = true;
1350 pVert = itrDaug->end_vertex();
1351 }
1352 }
1353 if (samePart) EndVert = pVert;
1354 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1355 }
1356 return EndVert;
1357 }
1358
1360
1361 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1362 if (!theVert) return {};
1363 decltype(theVert->particles_out()) finalStatePart;
1364 auto outgoing = theVert->particles_out();
1365 for (const auto& thePart: outgoing) {
1366 if (!thePart) continue;
1367 finalStatePart.push_back(thePart);
1368 if (isStable(thePart)) continue;
1369 V pVert = findSimulatedEndVertex(thePart);
1370 if (pVert == theVert) break; // to prevent Sherpa loop
1371 if (pVert != nullptr) {
1372 auto vecPart = findFinalStateParticles<V>(pVert);
1373 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1374 }
1375 }
1376 return finalStatePart;
1377 }
1378#if !defined(XAOD_ANALYSIS)
1379#include "AtlasHepMC/GenEvent.h"
1380inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1381inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1382
1383#endif
1384}
1385#endif

◆ isPentaquark() [1/3]

template<>
bool MC::isPentaquark ( const DecodedPID & p)
inline

Definition at line 344 of file HepMCHelpers.h.

363{
364 template <class VTX>
365 auto particles_in (const VTX* p) { return p->particles_in(); }
366 template <class VTX>
367 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
368
369 namespace Pythia8
370 {
372 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
373
374 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
375
376 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
377 }
378
379#include "AtlasPID.h"
380
382 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
383
385 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
386
388 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
389
391 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
392
394 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
395
397 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
398
400 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
401
403 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
404
406 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
407
409 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
410
414 template <class T> inline bool isStableOrSimDecayed(const T& p) {
415 const auto vertex = p->end_vertex();
416 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
417 }
418
420 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
421
423 template <class T> inline bool isSpecialNonInteracting(const T& p) {
424 const int apid = std::abs(p->pdg_id());
425 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
426 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
427 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
428 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
429 return false;
430 }
431
433
434 template <class T> T findMother(T thePart) {
435 auto partOriVert = thePart->production_vertex();
436 if (!partOriVert) return nullptr;
437
438 long partPDG = thePart->pdg_id();
439 long MotherPDG(0);
440
441 auto MothOriVert = partOriVert;
442 MothOriVert = nullptr;
443 T theMoth(nullptr);
444
445 size_t itr = 0;
446 do {
447 if (itr != 0) partOriVert = MothOriVert;
448 for ( const auto& p : particles_in(partOriVert) ) {
449 theMoth = p;
450 if (!theMoth) continue;
451 MotherPDG = theMoth->pdg_id();
452 MothOriVert = theMoth->production_vertex();
453 if (MotherPDG == partPDG) break;
454 }
455 itr++;
456 if (itr > 100) {
457 break;
458 }
459 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
460 MothOriVert != partOriVert);
461 return theMoth;
462 }
463
465
466 template <class C, class T> T findMatching(C TruthContainer, T p) {
467 T ptrPart = nullptr;
468 if (!p) return ptrPart;
469 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
470 for (T truthParticle : *TruthContainer) {
471 if (HepMC::is_sim_descendant(p,truthParticle)) {
472 ptrPart = truthParticle;
473 break;
474 }
475 }
476 }
477 else {
478 for (T truthParticle : TruthContainer) {
479 if (HepMC::is_sim_descendant(p,truthParticle)) {
480 ptrPart = truthParticle;
481 break;
482 }
483 }
484 }
485 return ptrPart;
486 }
488
489 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
490 auto prodVtx = thePart->production_vertex();
491 if (!prodVtx) return;
492 for (const auto& theMother: prodVtx->particles_in()) {
493 if (!theMother) continue;
494 allancestors.insert(theMother);
495 findParticleAncestors(theMother, allancestors);
496 }
497 }
498
500
501 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
502 auto endVtx = thePart->end_vertex();
503 if (!endVtx) return;
504 for (const auto& theDaughter: endVtx->particles_out()) {
505 if (!theDaughter) continue;
506 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
507 allstabledescendants.insert(theDaughter);
508 }
509 findParticleStableDescendants(theDaughter, allstabledescendants);
510 }
511 }
512
516
517 template <class T> bool isHardScatteringVertex(T pVert) {
518 if (pVert == nullptr) return false;
519 T pV = pVert;
520 int numOfPartIn(0);
521 int pdg(0);
522
523 do {
524 pVert = pV;
525 auto incoming = pVert->particles_in();
526 numOfPartIn = incoming.size();
527 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
528 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
529
530 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
531
532 if (numOfPartIn == 2) {
533 auto incoming = pVert->particles_in();
534 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
535 }
536 return false;
537}
538
542
543 template <class T, class U>
544 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
545 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
546 auto vtx = p->production_vertex();
547 if (!vtx) return false;
548 bool fromHad = false;
549 for ( const auto& parent : particles_in(vtx) ) {
550 if (!parent) continue;
551 // should this really go into parton-level territory?
552 // probably depends where BSM particles are being decayed
553 fromBSM |= isBSM(parent);
554 if (!isPhysical(parent)) return false;
555 fromTau |= isTau(parent);
556 if (isHadron(parent)&&!isBeam(parent)) {
557 if (!hadron) hadron = parent; // assumes linear hadron parentage
558 return true;
559 }
560 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
561 }
562 return fromHad;
563 }
564
567
568 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
569 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
570 decltype(thePart->end_vertex()) pVert(nullptr);
571 if (EndVert != nullptr) {
572 do {
573 bool samePart = false;
574 pVert = nullptr;
575 auto outgoing = EndVert->particles_out();
576 auto incoming = EndVert->particles_in();
577 for (const auto& itrDaug: outgoing) {
578 if (!itrDaug) continue;
579 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
580 // brem on generator level for tau
581 (outgoing.size() == 1 && incoming.size() == 1 &&
583 itrDaug->pdg_id() == thePart->pdg_id()) {
584 samePart = true;
585 pVert = itrDaug->end_vertex();
586 }
587 }
588 if (samePart) EndVert = pVert;
589 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
590 }
591 return EndVert;
592 }
593
595
596 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
597 if (!theVert) return {};
598 decltype(theVert->particles_out()) finalStatePart;
599 auto outgoing = theVert->particles_out();
600 for (const auto& thePart: outgoing) {
601 if (!thePart) continue;
602 finalStatePart.push_back(thePart);
603 if (isStable(thePart)) continue;
604 V pVert = findSimulatedEndVertex(thePart);
605 if (pVert == theVert) break; // to prevent Sherpa loop
606 if (pVert != nullptr) {
607 auto vecPart = findFinalStateParticles<V>(pVert);
608 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
609 }
610 }
611 return finalStatePart;
612 }
613#if !defined(XAOD_ANALYSIS)
614#include "AtlasHepMC/GenEvent.h"
615inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
616inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
617
618#endif
619}
620#endif

◆ isPentaquark() [2/3]

template<>
bool MC::isPentaquark ( const int & p)
inline

Definition at line 349 of file HepMCHelpers.h.

368{
369 template <class VTX>
370 auto particles_in (const VTX* p) { return p->particles_in(); }
371 template <class VTX>
372 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
373
374 namespace Pythia8
375 {
377 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
378
379 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
380
381 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
382 }
383
384#include "AtlasPID.h"
385
387 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
388
390 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
391
393 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
394
396 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
397
399 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
400
402 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
403
405 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
406
408 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
409
411 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
412
414 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
415
419 template <class T> inline bool isStableOrSimDecayed(const T& p) {
420 const auto vertex = p->end_vertex();
421 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
422 }
423
425 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
426
428 template <class T> inline bool isSpecialNonInteracting(const T& p) {
429 const int apid = std::abs(p->pdg_id());
430 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
431 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
432 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
433 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
434 return false;
435 }
436
438
439 template <class T> T findMother(T thePart) {
440 auto partOriVert = thePart->production_vertex();
441 if (!partOriVert) return nullptr;
442
443 long partPDG = thePart->pdg_id();
444 long MotherPDG(0);
445
446 auto MothOriVert = partOriVert;
447 MothOriVert = nullptr;
448 T theMoth(nullptr);
449
450 size_t itr = 0;
451 do {
452 if (itr != 0) partOriVert = MothOriVert;
453 for ( const auto& p : particles_in(partOriVert) ) {
454 theMoth = p;
455 if (!theMoth) continue;
456 MotherPDG = theMoth->pdg_id();
457 MothOriVert = theMoth->production_vertex();
458 if (MotherPDG == partPDG) break;
459 }
460 itr++;
461 if (itr > 100) {
462 break;
463 }
464 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
465 MothOriVert != partOriVert);
466 return theMoth;
467 }
468
470
471 template <class C, class T> T findMatching(C TruthContainer, T p) {
472 T ptrPart = nullptr;
473 if (!p) return ptrPart;
474 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
475 for (T truthParticle : *TruthContainer) {
476 if (HepMC::is_sim_descendant(p,truthParticle)) {
477 ptrPart = truthParticle;
478 break;
479 }
480 }
481 }
482 else {
483 for (T truthParticle : TruthContainer) {
484 if (HepMC::is_sim_descendant(p,truthParticle)) {
485 ptrPart = truthParticle;
486 break;
487 }
488 }
489 }
490 return ptrPart;
491 }
493
494 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
495 auto prodVtx = thePart->production_vertex();
496 if (!prodVtx) return;
497 for (const auto& theMother: prodVtx->particles_in()) {
498 if (!theMother) continue;
499 allancestors.insert(theMother);
500 findParticleAncestors(theMother, allancestors);
501 }
502 }
503
505
506 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
507 auto endVtx = thePart->end_vertex();
508 if (!endVtx) return;
509 for (const auto& theDaughter: endVtx->particles_out()) {
510 if (!theDaughter) continue;
511 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
512 allstabledescendants.insert(theDaughter);
513 }
514 findParticleStableDescendants(theDaughter, allstabledescendants);
515 }
516 }
517
521
522 template <class T> bool isHardScatteringVertex(T pVert) {
523 if (pVert == nullptr) return false;
524 T pV = pVert;
525 int numOfPartIn(0);
526 int pdg(0);
527
528 do {
529 pVert = pV;
530 auto incoming = pVert->particles_in();
531 numOfPartIn = incoming.size();
532 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
533 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
534
535 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
536
537 if (numOfPartIn == 2) {
538 auto incoming = pVert->particles_in();
539 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
540 }
541 return false;
542}
543
547
548 template <class T, class U>
549 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
550 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
551 auto vtx = p->production_vertex();
552 if (!vtx) return false;
553 bool fromHad = false;
554 for ( const auto& parent : particles_in(vtx) ) {
555 if (!parent) continue;
556 // should this really go into parton-level territory?
557 // probably depends where BSM particles are being decayed
558 fromBSM |= isBSM(parent);
559 if (!isPhysical(parent)) return false;
560 fromTau |= isTau(parent);
561 if (isHadron(parent)&&!isBeam(parent)) {
562 if (!hadron) hadron = parent; // assumes linear hadron parentage
563 return true;
564 }
565 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
566 }
567 return fromHad;
568 }
569
572
573 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
574 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
575 decltype(thePart->end_vertex()) pVert(nullptr);
576 if (EndVert != nullptr) {
577 do {
578 bool samePart = false;
579 pVert = nullptr;
580 auto outgoing = EndVert->particles_out();
581 auto incoming = EndVert->particles_in();
582 for (const auto& itrDaug: outgoing) {
583 if (!itrDaug) continue;
584 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
585 // brem on generator level for tau
586 (outgoing.size() == 1 && incoming.size() == 1 &&
588 itrDaug->pdg_id() == thePart->pdg_id()) {
589 samePart = true;
590 pVert = itrDaug->end_vertex();
591 }
592 }
593 if (samePart) EndVert = pVert;
594 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
595 }
596 return EndVert;
597 }
598
600
601 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
602 if (!theVert) return {};
603 decltype(theVert->particles_out()) finalStatePart;
604 auto outgoing = theVert->particles_out();
605 for (const auto& thePart: outgoing) {
606 if (!thePart) continue;
607 finalStatePart.push_back(thePart);
608 if (isStable(thePart)) continue;
609 V pVert = findSimulatedEndVertex(thePart);
610 if (pVert == theVert) break; // to prevent Sherpa loop
611 if (pVert != nullptr) {
612 auto vecPart = findFinalStateParticles<V>(pVert);
613 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
614 }
615 }
616 return finalStatePart;
617 }
618#if !defined(XAOD_ANALYSIS)
619#include "AtlasHepMC/GenEvent.h"
620inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
621inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
622
623#endif
624}
625#endif

◆ isPentaquark() [3/3]

template<class T>
bool MC::isPentaquark ( const T & p)
inline

PDG rule 15 The 9-digit penta-quark codes are ±1nrnLnq1nq2nq3nq4nq5nJ, sorted such that nq1≥nq2≥nq3≥nq4.

In the particle the first four are quarks and the fifth an antiquark while the opposite holds in the antiparticle, which is given with a negative sign. The nr, nL, and nJ numbers have the same meaning as for ordinary hadrons.

Definition at line 343 of file HepMCHelpers.h.

362{
363 template <class VTX>
364 auto particles_in (const VTX* p) { return p->particles_in(); }
365 template <class VTX>
366 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
367
368 namespace Pythia8
369 {
371 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
372
373 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
374
375 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
376 }
377
378#include "AtlasPID.h"
379
381 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
382
384 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
385
387 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
388
390 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
391
393 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
394
396 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
397
399 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
400
402 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
403
405 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
406
408 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
409
413 template <class T> inline bool isStableOrSimDecayed(const T& p) {
414 const auto vertex = p->end_vertex();
415 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
416 }
417
419 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
420
422 template <class T> inline bool isSpecialNonInteracting(const T& p) {
423 const int apid = std::abs(p->pdg_id());
424 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
425 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
426 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
427 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
428 return false;
429 }
430
432
433 template <class T> T findMother(T thePart) {
434 auto partOriVert = thePart->production_vertex();
435 if (!partOriVert) return nullptr;
436
437 long partPDG = thePart->pdg_id();
438 long MotherPDG(0);
439
440 auto MothOriVert = partOriVert;
441 MothOriVert = nullptr;
442 T theMoth(nullptr);
443
444 size_t itr = 0;
445 do {
446 if (itr != 0) partOriVert = MothOriVert;
447 for ( const auto& p : particles_in(partOriVert) ) {
448 theMoth = p;
449 if (!theMoth) continue;
450 MotherPDG = theMoth->pdg_id();
451 MothOriVert = theMoth->production_vertex();
452 if (MotherPDG == partPDG) break;
453 }
454 itr++;
455 if (itr > 100) {
456 break;
457 }
458 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
459 MothOriVert != partOriVert);
460 return theMoth;
461 }
462
464
465 template <class C, class T> T findMatching(C TruthContainer, T p) {
466 T ptrPart = nullptr;
467 if (!p) return ptrPart;
468 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
469 for (T truthParticle : *TruthContainer) {
470 if (HepMC::is_sim_descendant(p,truthParticle)) {
471 ptrPart = truthParticle;
472 break;
473 }
474 }
475 }
476 else {
477 for (T truthParticle : TruthContainer) {
478 if (HepMC::is_sim_descendant(p,truthParticle)) {
479 ptrPart = truthParticle;
480 break;
481 }
482 }
483 }
484 return ptrPart;
485 }
487
488 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
489 auto prodVtx = thePart->production_vertex();
490 if (!prodVtx) return;
491 for (const auto& theMother: prodVtx->particles_in()) {
492 if (!theMother) continue;
493 allancestors.insert(theMother);
494 findParticleAncestors(theMother, allancestors);
495 }
496 }
497
499
500 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
501 auto endVtx = thePart->end_vertex();
502 if (!endVtx) return;
503 for (const auto& theDaughter: endVtx->particles_out()) {
504 if (!theDaughter) continue;
505 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
506 allstabledescendants.insert(theDaughter);
507 }
508 findParticleStableDescendants(theDaughter, allstabledescendants);
509 }
510 }
511
515
516 template <class T> bool isHardScatteringVertex(T pVert) {
517 if (pVert == nullptr) return false;
518 T pV = pVert;
519 int numOfPartIn(0);
520 int pdg(0);
521
522 do {
523 pVert = pV;
524 auto incoming = pVert->particles_in();
525 numOfPartIn = incoming.size();
526 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
527 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
528
529 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
530
531 if (numOfPartIn == 2) {
532 auto incoming = pVert->particles_in();
533 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
534 }
535 return false;
536}
537
541
542 template <class T, class U>
543 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
544 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
545 auto vtx = p->production_vertex();
546 if (!vtx) return false;
547 bool fromHad = false;
548 for ( const auto& parent : particles_in(vtx) ) {
549 if (!parent) continue;
550 // should this really go into parton-level territory?
551 // probably depends where BSM particles are being decayed
552 fromBSM |= isBSM(parent);
553 if (!isPhysical(parent)) return false;
554 fromTau |= isTau(parent);
555 if (isHadron(parent)&&!isBeam(parent)) {
556 if (!hadron) hadron = parent; // assumes linear hadron parentage
557 return true;
558 }
559 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
560 }
561 return fromHad;
562 }
563
566
567 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
568 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
569 decltype(thePart->end_vertex()) pVert(nullptr);
570 if (EndVert != nullptr) {
571 do {
572 bool samePart = false;
573 pVert = nullptr;
574 auto outgoing = EndVert->particles_out();
575 auto incoming = EndVert->particles_in();
576 for (const auto& itrDaug: outgoing) {
577 if (!itrDaug) continue;
578 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
579 // brem on generator level for tau
580 (outgoing.size() == 1 && incoming.size() == 1 &&
582 itrDaug->pdg_id() == thePart->pdg_id()) {
583 samePart = true;
584 pVert = itrDaug->end_vertex();
585 }
586 }
587 if (samePart) EndVert = pVert;
588 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
589 }
590 return EndVert;
591 }
592
594
595 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
596 if (!theVert) return {};
597 decltype(theVert->particles_out()) finalStatePart;
598 auto outgoing = theVert->particles_out();
599 for (const auto& thePart: outgoing) {
600 if (!thePart) continue;
601 finalStatePart.push_back(thePart);
602 if (isStable(thePart)) continue;
603 V pVert = findSimulatedEndVertex(thePart);
604 if (pVert == theVert) break; // to prevent Sherpa loop
605 if (pVert != nullptr) {
606 auto vecPart = findFinalStateParticles<V>(pVert);
607 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
608 }
609 }
610 return finalStatePart;
611 }
612#if !defined(XAOD_ANALYSIS)
613#include "AtlasHepMC/GenEvent.h"
614inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
615inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
616
617#endif
618}
619#endif

◆ isPhoton() [1/2]

template<>
bool MC::isPhoton ( const int & p)
inline

Definition at line 378 of file HepMCHelpers.h.

397{
398 template <class VTX>
399 auto particles_in (const VTX* p) { return p->particles_in(); }
400 template <class VTX>
401 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
402
403 namespace Pythia8
404 {
406 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
407
408 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
409
410 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
411 }
412
413#include "AtlasPID.h"
414
416 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
417
419 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
420
422 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
423
425 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
426
428 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
429
431 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
432
434 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
435
437 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
438
440 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
441
443 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
444
448 template <class T> inline bool isStableOrSimDecayed(const T& p) {
449 const auto vertex = p->end_vertex();
450 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
451 }
452
454 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
455
457 template <class T> inline bool isSpecialNonInteracting(const T& p) {
458 const int apid = std::abs(p->pdg_id());
459 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
460 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
461 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
462 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
463 return false;
464 }
465
467
468 template <class T> T findMother(T thePart) {
469 auto partOriVert = thePart->production_vertex();
470 if (!partOriVert) return nullptr;
471
472 long partPDG = thePart->pdg_id();
473 long MotherPDG(0);
474
475 auto MothOriVert = partOriVert;
476 MothOriVert = nullptr;
477 T theMoth(nullptr);
478
479 size_t itr = 0;
480 do {
481 if (itr != 0) partOriVert = MothOriVert;
482 for ( const auto& p : particles_in(partOriVert) ) {
483 theMoth = p;
484 if (!theMoth) continue;
485 MotherPDG = theMoth->pdg_id();
486 MothOriVert = theMoth->production_vertex();
487 if (MotherPDG == partPDG) break;
488 }
489 itr++;
490 if (itr > 100) {
491 break;
492 }
493 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
494 MothOriVert != partOriVert);
495 return theMoth;
496 }
497
499
500 template <class C, class T> T findMatching(C TruthContainer, T p) {
501 T ptrPart = nullptr;
502 if (!p) return ptrPart;
503 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
504 for (T truthParticle : *TruthContainer) {
505 if (HepMC::is_sim_descendant(p,truthParticle)) {
506 ptrPart = truthParticle;
507 break;
508 }
509 }
510 }
511 else {
512 for (T truthParticle : TruthContainer) {
513 if (HepMC::is_sim_descendant(p,truthParticle)) {
514 ptrPart = truthParticle;
515 break;
516 }
517 }
518 }
519 return ptrPart;
520 }
522
523 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
524 auto prodVtx = thePart->production_vertex();
525 if (!prodVtx) return;
526 for (const auto& theMother: prodVtx->particles_in()) {
527 if (!theMother) continue;
528 allancestors.insert(theMother);
529 findParticleAncestors(theMother, allancestors);
530 }
531 }
532
534
535 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
536 auto endVtx = thePart->end_vertex();
537 if (!endVtx) return;
538 for (const auto& theDaughter: endVtx->particles_out()) {
539 if (!theDaughter) continue;
540 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
541 allstabledescendants.insert(theDaughter);
542 }
543 findParticleStableDescendants(theDaughter, allstabledescendants);
544 }
545 }
546
550
551 template <class T> bool isHardScatteringVertex(T pVert) {
552 if (pVert == nullptr) return false;
553 T pV = pVert;
554 int numOfPartIn(0);
555 int pdg(0);
556
557 do {
558 pVert = pV;
559 auto incoming = pVert->particles_in();
560 numOfPartIn = incoming.size();
561 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
562 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
563
564 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
565
566 if (numOfPartIn == 2) {
567 auto incoming = pVert->particles_in();
568 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
569 }
570 return false;
571}
572
576
577 template <class T, class U>
578 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
579 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
580 auto vtx = p->production_vertex();
581 if (!vtx) return false;
582 bool fromHad = false;
583 for ( const auto& parent : particles_in(vtx) ) {
584 if (!parent) continue;
585 // should this really go into parton-level territory?
586 // probably depends where BSM particles are being decayed
587 fromBSM |= isBSM(parent);
588 if (!isPhysical(parent)) return false;
589 fromTau |= isTau(parent);
590 if (isHadron(parent)&&!isBeam(parent)) {
591 if (!hadron) hadron = parent; // assumes linear hadron parentage
592 return true;
593 }
594 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
595 }
596 return fromHad;
597 }
598
601
602 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
603 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
604 decltype(thePart->end_vertex()) pVert(nullptr);
605 if (EndVert != nullptr) {
606 do {
607 bool samePart = false;
608 pVert = nullptr;
609 auto outgoing = EndVert->particles_out();
610 auto incoming = EndVert->particles_in();
611 for (const auto& itrDaug: outgoing) {
612 if (!itrDaug) continue;
613 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
614 // brem on generator level for tau
615 (outgoing.size() == 1 && incoming.size() == 1 &&
617 itrDaug->pdg_id() == thePart->pdg_id()) {
618 samePart = true;
619 pVert = itrDaug->end_vertex();
620 }
621 }
622 if (samePart) EndVert = pVert;
623 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
624 }
625 return EndVert;
626 }
627
629
630 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
631 if (!theVert) return {};
632 decltype(theVert->particles_out()) finalStatePart;
633 auto outgoing = theVert->particles_out();
634 for (const auto& thePart: outgoing) {
635 if (!thePart) continue;
636 finalStatePart.push_back(thePart);
637 if (isStable(thePart)) continue;
638 V pVert = findSimulatedEndVertex(thePart);
639 if (pVert == theVert) break; // to prevent Sherpa loop
640 if (pVert != nullptr) {
641 auto vecPart = findFinalStateParticles<V>(pVert);
642 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
643 }
644 }
645 return finalStatePart;
646 }
647#if !defined(XAOD_ANALYSIS)
648#include "AtlasHepMC/GenEvent.h"
649inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
650inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
651
652#endif
653}
654#endif

◆ isPhoton() [2/2]

template<class T>
bool MC::isPhoton ( const T & p)
inline

Definition at line 377 of file HepMCHelpers.h.

396{
397 template <class VTX>
398 auto particles_in (const VTX* p) { return p->particles_in(); }
399 template <class VTX>
400 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
401
402 namespace Pythia8
403 {
405 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
406
407 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
408
409 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
410 }
411
412#include "AtlasPID.h"
413
415 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
416
418 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
419
421 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
422
424 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
425
427 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
428
430 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
431
433 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
434
436 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
437
439 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
440
442 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
443
447 template <class T> inline bool isStableOrSimDecayed(const T& p) {
448 const auto vertex = p->end_vertex();
449 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
450 }
451
453 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
454
456 template <class T> inline bool isSpecialNonInteracting(const T& p) {
457 const int apid = std::abs(p->pdg_id());
458 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
459 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
460 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
461 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
462 return false;
463 }
464
466
467 template <class T> T findMother(T thePart) {
468 auto partOriVert = thePart->production_vertex();
469 if (!partOriVert) return nullptr;
470
471 long partPDG = thePart->pdg_id();
472 long MotherPDG(0);
473
474 auto MothOriVert = partOriVert;
475 MothOriVert = nullptr;
476 T theMoth(nullptr);
477
478 size_t itr = 0;
479 do {
480 if (itr != 0) partOriVert = MothOriVert;
481 for ( const auto& p : particles_in(partOriVert) ) {
482 theMoth = p;
483 if (!theMoth) continue;
484 MotherPDG = theMoth->pdg_id();
485 MothOriVert = theMoth->production_vertex();
486 if (MotherPDG == partPDG) break;
487 }
488 itr++;
489 if (itr > 100) {
490 break;
491 }
492 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
493 MothOriVert != partOriVert);
494 return theMoth;
495 }
496
498
499 template <class C, class T> T findMatching(C TruthContainer, T p) {
500 T ptrPart = nullptr;
501 if (!p) return ptrPart;
502 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
503 for (T truthParticle : *TruthContainer) {
504 if (HepMC::is_sim_descendant(p,truthParticle)) {
505 ptrPart = truthParticle;
506 break;
507 }
508 }
509 }
510 else {
511 for (T truthParticle : TruthContainer) {
512 if (HepMC::is_sim_descendant(p,truthParticle)) {
513 ptrPart = truthParticle;
514 break;
515 }
516 }
517 }
518 return ptrPart;
519 }
521
522 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
523 auto prodVtx = thePart->production_vertex();
524 if (!prodVtx) return;
525 for (const auto& theMother: prodVtx->particles_in()) {
526 if (!theMother) continue;
527 allancestors.insert(theMother);
528 findParticleAncestors(theMother, allancestors);
529 }
530 }
531
533
534 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
535 auto endVtx = thePart->end_vertex();
536 if (!endVtx) return;
537 for (const auto& theDaughter: endVtx->particles_out()) {
538 if (!theDaughter) continue;
539 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
540 allstabledescendants.insert(theDaughter);
541 }
542 findParticleStableDescendants(theDaughter, allstabledescendants);
543 }
544 }
545
549
550 template <class T> bool isHardScatteringVertex(T pVert) {
551 if (pVert == nullptr) return false;
552 T pV = pVert;
553 int numOfPartIn(0);
554 int pdg(0);
555
556 do {
557 pVert = pV;
558 auto incoming = pVert->particles_in();
559 numOfPartIn = incoming.size();
560 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
561 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
562
563 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
564
565 if (numOfPartIn == 2) {
566 auto incoming = pVert->particles_in();
567 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
568 }
569 return false;
570}
571
575
576 template <class T, class U>
577 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
578 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
579 auto vtx = p->production_vertex();
580 if (!vtx) return false;
581 bool fromHad = false;
582 for ( const auto& parent : particles_in(vtx) ) {
583 if (!parent) continue;
584 // should this really go into parton-level territory?
585 // probably depends where BSM particles are being decayed
586 fromBSM |= isBSM(parent);
587 if (!isPhysical(parent)) return false;
588 fromTau |= isTau(parent);
589 if (isHadron(parent)&&!isBeam(parent)) {
590 if (!hadron) hadron = parent; // assumes linear hadron parentage
591 return true;
592 }
593 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
594 }
595 return fromHad;
596 }
597
600
601 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
<