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

Namespaces

namespace  Pythia8

Classes

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

Functions

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>
bool isFromHadron (T p, T 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..

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.

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

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

◆ baryonNumber3() [1/3]

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

Definition at line 750 of file HepMCHelpers.h.

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

◆ baryonNumber3() [2/3]

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

Definition at line 772 of file HepMCHelpers.h.

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

◆ baryonNumber3() [3/3]

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

Definition at line 749 of file HepMCHelpers.h.

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

◆ charge()

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

Definition at line 998 of file HepMCHelpers.h.

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

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

◆ charge3() [2/3]

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

Definition at line 1078 of file HepMCHelpers.h.

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

◆ charge3() [3/3]

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

Definition at line 996 of file HepMCHelpers.h.

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

◆ containedQuarks() [1/3]

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

Definition at line 1177 of file HepMCHelpers.h.

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

◆ containedQuarks() [2/3]

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

Definition at line 1155 of file HepMCHelpers.h.

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

◆ containedQuarks() [3/3]

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

Definition at line 1154 of file HepMCHelpers.h.

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

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

◆ 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 118 of file HepMCHelpers.h.

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

◆ 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 85 of file HepMCHelpers.h.

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

◆ 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 141 of file HepMCHelpers.h.

141 {
142 auto prodVtx = thePart->production_vertex();
143 if (!prodVtx) return;
144 for (auto theMother: prodVtx->particles_in()) {
145 if (!theMother) continue;
146 allancestors.insert(theMother);
147 findParticleAncestors(theMother, allancestors);
148 }
149 }

◆ 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 153 of file HepMCHelpers.h.

153 {
154 auto endVtx = thePart->end_vertex();
155 if (!endVtx) return;
156 for (auto theDaughter: endVtx->particles_out()) {
157 if (!theDaughter) continue;
158 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
159 allstabledescendants.insert(theDaughter);
160 }
161 findParticleStableDescendants(theDaughter, allstabledescendants);
162 }
163 }

◆ 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 220 of file HepMCHelpers.h.

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

◆ fractionalCharge() [1/3]

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

Definition at line 1091 of file HepMCHelpers.h.

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

◆ fractionalCharge() [2/3]

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

Definition at line 1098 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
1197 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
1298 for (auto parent: incoming) {
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
1363}
1364#endif

◆ fractionalCharge() [3/3]

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

Definition at line 997 of file HepMCHelpers.h.

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

◆ hasBottom()

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

Definition at line 739 of file HepMCHelpers.h.

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

◆ hasCharm()

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

Definition at line 738 of file HepMCHelpers.h.

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

◆ hasQuark() [1/3]

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

Definition at line 717 of file HepMCHelpers.h.

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

◆ hasQuark() [2/3]

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

Definition at line 735 of file HepMCHelpers.h.

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

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

◆ hasSquark() [2/3]

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

Definition at line 619 of file HepMCHelpers.h.

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

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

◆ hasStrange()

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

Definition at line 737 of file HepMCHelpers.h.

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

◆ hasTop()

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

Definition at line 740 of file HepMCHelpers.h.

758{
759 namespace Pythia8
760 {
762 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
763
764 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
765
766 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
767 }
768
769#include "AtlasPID.h"
770
772 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
773
775 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
776
778 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
779
781 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
782
784 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
785
787 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
788
790 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
791
793 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
794
796 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
797
799 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
800
804 template <class T> inline bool isStableOrSimDecayed(const T& p) {
805 const auto vertex = p->end_vertex();
806 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
807 }
808
810 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
811
813 template <class T> inline bool isSpecialNonInteracting(const T& p) {
814 const int apid = std::abs(p->pdg_id());
815 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
816 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
817 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
818 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
819 return false;
820 }
821
823
824 template <class T> T findMother(T thePart) {
825 auto partOriVert = thePart->production_vertex();
826 if (!partOriVert) return nullptr;
827
828 long partPDG = thePart->pdg_id();
829 long MotherPDG(0);
830
831 auto MothOriVert = partOriVert;
832 MothOriVert = nullptr;
833 T theMoth(nullptr);
834
835 size_t itr = 0;
836 do {
837 if (itr != 0) partOriVert = MothOriVert;
838 auto incoming = partOriVert->particles_in();
839 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
935 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
936 auto vtx = p->production_vertex();
937 if (!vtx) return false;
938 bool fromHad = false;
939 auto incoming = vtx->particles_in();
940 for (auto parent: incoming) {
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
1005}
1006#endif

◆ isBaryon() [1/3]

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

Definition at line 284 of file HepMCHelpers.h.

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

◆ isBaryon() [2/3]

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

Definition at line 317 of file HepMCHelpers.h.

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

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

◆ isBBbarMeson() [1/3]

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

Definition at line 928 of file HepMCHelpers.h.

946{
947 namespace Pythia8
948 {
950 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
951
952 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
953
954 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
955 }
956
957#include "AtlasPID.h"
958
960 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
961
963 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
964
966 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
967
969 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
970
972 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
973
975 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
976
978 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
979
981 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
982
984 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
985
987 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
988
992 template <class T> inline bool isStableOrSimDecayed(const T& p) {
993 const auto vertex = p->end_vertex();
994 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
995 }
996
998 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
999
1001 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1002 const int apid = std::abs(p->pdg_id());
1003 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1004 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1005 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1006 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1007 return false;
1008 }
1009
1011
1012 template <class T> T findMother(T thePart) {
1013 auto partOriVert = thePart->production_vertex();
1014 if (!partOriVert) return nullptr;
1015
1016 long partPDG = thePart->pdg_id();
1017 long MotherPDG(0);
1018
1019 auto MothOriVert = partOriVert;
1020 MothOriVert = nullptr;
1021 T theMoth(nullptr);
1022
1023 size_t itr = 0;
1024 do {
1025 if (itr != 0) partOriVert = MothOriVert;
1026 auto incoming = partOriVert->particles_in();
1027 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
1123 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1124 auto vtx = p->production_vertex();
1125 if (!vtx) return false;
1126 bool fromHad = false;
1127 auto incoming = vtx->particles_in();
1128 for (auto parent: incoming) {
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
1193}
1194#endif

◆ isBBbarMeson() [2/3]

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

Definition at line 929 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
1028 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
1129 for (auto parent: incoming) {
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
1194}
1195#endif

◆ isBBbarMeson() [3/3]

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

Definition at line 927 of file HepMCHelpers.h.

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

◆ isBeam()

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

Identify if the particle is beam particle.

Definition at line 39 of file HepMCHelpers.h.

◆ isBoson() [1/3]

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

Definition at line 372 of file HepMCHelpers.h.

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

◆ isBoson() [2/3]

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

Definition at line 371 of file HepMCHelpers.h.

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

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

◆ isBottom() [1/2]

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

Definition at line 184 of file HepMCHelpers.h.

184{

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

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

◆ isBottomHadron()

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

Definition at line 913 of file HepMCHelpers.h.

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

◆ isBottomMeson()

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

Definition at line 920 of file HepMCHelpers.h.

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

◆ isBSM() [1/3]

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

Definition at line 848 of file HepMCHelpers.h.

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

◆ isBSM() [2/3]

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

Definition at line 865 of file HepMCHelpers.h.

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

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

◆ isCCbarMeson() [1/3]

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

Definition at line 924 of file HepMCHelpers.h.

942{
943 namespace Pythia8
944 {
946 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
947
948 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
949
950 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
951 }
952
953#include "AtlasPID.h"
954
956 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
957
959 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
960
962 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
963
965 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
966
968 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
969
971 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
972
974 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
975
977 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
978
980 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
981
983 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
984
988 template <class T> inline bool isStableOrSimDecayed(const T& p) {
989 const auto vertex = p->end_vertex();
990 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
991 }
992
994 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
995
997 template <class T> inline bool isSpecialNonInteracting(const T& p) {
998 const int apid = std::abs(p->pdg_id());
999 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1000 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1001 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1002 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1003 return false;
1004 }
1005
1007
1008 template <class T> T findMother(T thePart) {
1009 auto partOriVert = thePart->production_vertex();
1010 if (!partOriVert) return nullptr;
1011
1012 long partPDG = thePart->pdg_id();
1013 long MotherPDG(0);
1014
1015 auto MothOriVert = partOriVert;
1016 MothOriVert = nullptr;
1017 T theMoth(nullptr);
1018
1019 size_t itr = 0;
1020 do {
1021 if (itr != 0) partOriVert = MothOriVert;
1022 auto incoming = partOriVert->particles_in();
1023 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
1119 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1120 auto vtx = p->production_vertex();
1121 if (!vtx) return false;
1122 bool fromHad = false;
1123 auto incoming = vtx->particles_in();
1124 for (auto parent: incoming) {
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
1189}
1190#endif

◆ isCCbarMeson() [2/3]

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

Definition at line 925 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
1024 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
1125 for (auto parent: incoming) {
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
1190}
1191#endif

◆ isCCbarMeson() [3/3]

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

Definition at line 923 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
1022 for ( auto p: incoming) {
1023 theMoth = p;
1024 if (!theMoth) continue;
1025 MotherPDG = theMoth->pdg_id();
1026 MothOriVert = theMoth->production_vertex();
1027 if (MotherPDG == partPDG) break;
1028 }
1029 itr++;
1030 if (itr > 100) {
1031 break;
1032 }
1033 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1034 MothOriVert != partOriVert);
1035 return theMoth;
1036 }
1037
1039
1040 template <class C, class T> T findMatching(C TruthContainer, T p) {
1041 T ptrPart = nullptr;
1042 if (!p) return ptrPart;
1043 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1044 for (T truthParticle : *TruthContainer) {
1045 if (HepMC::is_sim_descendant(p,truthParticle)) {
1046 ptrPart = truthParticle;
1047 break;
1048 }
1049 }
1050 }
1051 else {
1052 for (T truthParticle : TruthContainer) {
1053 if (HepMC::is_sim_descendant(p,truthParticle)) {
1054 ptrPart = truthParticle;
1055 break;
1056 }
1057 }
1058 }
1059 return ptrPart;
1060 }
1062
1063 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1064 auto prodVtx = thePart->production_vertex();
1065 if (!prodVtx) return;
1066 for (auto theMother: prodVtx->particles_in()) {
1067 if (!theMother) continue;
1068 allancestors.insert(theMother);
1069 findParticleAncestors(theMother, allancestors);
1070 }
1071 }
1072
1074
1075 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1076 auto endVtx = thePart->end_vertex();
1077 if (!endVtx) return;
1078 for (auto theDaughter: endVtx->particles_out()) {
1079 if (!theDaughter) continue;
1080 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1081 allstabledescendants.insert(theDaughter);
1082 }
1083 findParticleStableDescendants(theDaughter, allstabledescendants);
1084 }
1085 }
1086
1090
1091 template <class T> bool isHardScatteringVertex(T pVert) {
1092 if (pVert == nullptr) return false;
1093 T pV = pVert;
1094 int numOfPartIn(0);
1095 int pdg(0);
1096
1097 do {
1098 pVert = pV;
1099 auto incoming = pVert->particles_in();
1100 numOfPartIn = incoming.size();
1101 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1102 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1103
1104 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1105
1106 if (numOfPartIn == 2) {
1107 auto incoming = pVert->particles_in();
1108 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;
1109 }
1110 return false;
1111}
1112
1116
1117 template <class T> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
1123 for (auto parent: incoming) {
1124 if (!parent) continue;
1125 // should this really go into parton-level territory?
1126 // probably depends where BSM particles are being decayed
1127 fromBSM |= isBSM(parent);
1128 if (!isPhysical(parent)) return false;
1129 fromTau |= isTau(parent);
1130 if (isHadron(parent)&&!isBeam(parent)) {
1131 if (!hadron) hadron = parent; // assumes linear hadron parentage
1132 return true;
1133 }
1134 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1135 }
1136 return fromHad;
1137 }
1138
1141
1142 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1143 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1144 decltype(thePart->end_vertex()) pVert(nullptr);
1145 if (EndVert != nullptr) {
1146 do {
1147 bool samePart = false;
1148 pVert = nullptr;
1149 auto outgoing = EndVert->particles_out();
1150 auto incoming = EndVert->particles_in();
1151 for (const auto& itrDaug: outgoing) {
1152 if (!itrDaug) continue;
1153 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1154 // brem on generator level for tau
1155 (outgoing.size() == 1 && incoming.size() == 1 &&
1157 itrDaug->pdg_id() == thePart->pdg_id()) {
1158 samePart = true;
1159 pVert = itrDaug->end_vertex();
1160 }
1161 }
1162 if (samePart) EndVert = pVert;
1163 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1164 }
1165 return EndVert;
1166 }
1167
1169
1170 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1171 if (!theVert) return {};
1172 decltype(theVert->particles_out()) finalStatePart;
1173 auto outgoing = theVert->particles_out();
1174 for (const auto& thePart: outgoing) {
1175 if (!thePart) continue;
1176 finalStatePart.push_back(thePart);
1177 if (isStable(thePart)) continue;
1178 V pVert = findSimulatedEndVertex(thePart);
1179 if (pVert == theVert) break; // to prevent Sherpa loop
1180 if (pVert != nullptr) {
1181 auto vecPart = findFinalStateParticles<V>(pVert);
1182 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1183 }
1184 }
1185 return finalStatePart;
1186 }
1187
1188}
1189#endif

◆ isCharged()

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

Definition at line 1005 of file HepMCHelpers.h.

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

36{ 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: nullptr;

◆ isCharmBaryon()

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

Definition at line 935 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
1034 for ( auto p: incoming) {
1035 theMoth = p;
1036 if (!theMoth) continue;
1037 MotherPDG = theMoth->pdg_id();
1038 MothOriVert = theMoth->production_vertex();
1039 if (MotherPDG == partPDG) break;
1040 }
1041 itr++;
1042 if (itr > 100) {
1043 break;
1044 }
1045 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1046 MothOriVert != partOriVert);
1047 return theMoth;
1048 }
1049
1051
1052 template <class C, class T> T findMatching(C TruthContainer, T p) {
1053 T ptrPart = nullptr;
1054 if (!p) return ptrPart;
1055 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1056 for (T truthParticle : *TruthContainer) {
1057 if (HepMC::is_sim_descendant(p,truthParticle)) {
1058 ptrPart = truthParticle;
1059 break;
1060 }
1061 }
1062 }
1063 else {
1064 for (T truthParticle : TruthContainer) {
1065 if (HepMC::is_sim_descendant(p,truthParticle)) {
1066 ptrPart = truthParticle;
1067 break;
1068 }
1069 }
1070 }
1071 return ptrPart;
1072 }
1074
1075 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1076 auto prodVtx = thePart->production_vertex();
1077 if (!prodVtx) return;
1078 for (auto theMother: prodVtx->particles_in()) {
1079 if (!theMother) continue;
1080 allancestors.insert(theMother);
1081 findParticleAncestors(theMother, allancestors);
1082 }
1083 }
1084
1086
1087 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1088 auto endVtx = thePart->end_vertex();
1089 if (!endVtx) return;
1090 for (auto theDaughter: endVtx->particles_out()) {
1091 if (!theDaughter) continue;
1092 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1093 allstabledescendants.insert(theDaughter);
1094 }
1095 findParticleStableDescendants(theDaughter, allstabledescendants);
1096 }
1097 }
1098
1102
1103 template <class T> bool isHardScatteringVertex(T pVert) {
1104 if (pVert == nullptr) return false;
1105 T pV = pVert;
1106 int numOfPartIn(0);
1107 int pdg(0);
1108
1109 do {
1110 pVert = pV;
1111 auto incoming = pVert->particles_in();
1112 numOfPartIn = incoming.size();
1113 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1114 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1115
1116 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1117
1118 if (numOfPartIn == 2) {
1119 auto incoming = pVert->particles_in();
1120 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;
1121 }
1122 return false;
1123}
1124
1128
1129 template <class T> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
1135 for (auto parent: incoming) {
1136 if (!parent) continue;
1137 // should this really go into parton-level territory?
1138 // probably depends where BSM particles are being decayed
1139 fromBSM |= isBSM(parent);
1140 if (!isPhysical(parent)) return false;
1141 fromTau |= isTau(parent);
1142 if (isHadron(parent)&&!isBeam(parent)) {
1143 if (!hadron) hadron = parent; // assumes linear hadron parentage
1144 return true;
1145 }
1146 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1147 }
1148 return fromHad;
1149 }
1150
1153
1154 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1155 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1156 decltype(thePart->end_vertex()) pVert(nullptr);
1157 if (EndVert != nullptr) {
1158 do {
1159 bool samePart = false;
1160 pVert = nullptr;
1161 auto outgoing = EndVert->particles_out();
1162 auto incoming = EndVert->particles_in();
1163 for (const auto& itrDaug: outgoing) {
1164 if (!itrDaug) continue;
1165 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1166 // brem on generator level for tau
1167 (outgoing.size() == 1 && incoming.size() == 1 &&
1169 itrDaug->pdg_id() == thePart->pdg_id()) {
1170 samePart = true;
1171 pVert = itrDaug->end_vertex();
1172 }
1173 }
1174 if (samePart) EndVert = pVert;
1175 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1176 }
1177 return EndVert;
1178 }
1179
1181
1182 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1183 if (!theVert) return {};
1184 decltype(theVert->particles_out()) finalStatePart;
1185 auto outgoing = theVert->particles_out();
1186 for (const auto& thePart: outgoing) {
1187 if (!thePart) continue;
1188 finalStatePart.push_back(thePart);
1189 if (isStable(thePart)) continue;
1190 V pVert = findSimulatedEndVertex(thePart);
1191 if (pVert == theVert) break; // to prevent Sherpa loop
1192 if (pVert != nullptr) {
1193 auto vecPart = findFinalStateParticles<V>(pVert);
1194 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1195 }
1196 }
1197 return finalStatePart;
1198 }
1199
1200}
1201#endif

◆ isCharmHadron()

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

Definition at line 912 of file HepMCHelpers.h.

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

◆ isCharmMeson()

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

Definition at line 919 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
1018 for ( auto p: incoming) {
1019 theMoth = p;
1020 if (!theMoth) continue;
1021 MotherPDG = theMoth->pdg_id();
1022 MothOriVert = theMoth->production_vertex();
1023 if (MotherPDG == partPDG) break;
1024 }
1025 itr++;
1026 if (itr > 100) {
1027 break;
1028 }
1029 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1030 MothOriVert != partOriVert);
1031 return theMoth;
1032 }
1033
1035
1036 template <class C, class T> T findMatching(C TruthContainer, T p) {
1037 T ptrPart = nullptr;
1038 if (!p) return ptrPart;
1039 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1040 for (T truthParticle : *TruthContainer) {
1041 if (HepMC::is_sim_descendant(p,truthParticle)) {
1042 ptrPart = truthParticle;
1043 break;
1044 }
1045 }
1046 }
1047 else {
1048 for (T truthParticle : TruthContainer) {
1049 if (HepMC::is_sim_descendant(p,truthParticle)) {
1050 ptrPart = truthParticle;
1051 break;
1052 }
1053 }
1054 }
1055 return ptrPart;
1056 }
1058
1059 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1060 auto prodVtx = thePart->production_vertex();
1061 if (!prodVtx) return;
1062 for (auto theMother: prodVtx->particles_in()) {
1063 if (!theMother) continue;
1064 allancestors.insert(theMother);
1065 findParticleAncestors(theMother, allancestors);
1066 }
1067 }
1068
1070
1071 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1072 auto endVtx = thePart->end_vertex();
1073 if (!endVtx) return;
1074 for (auto theDaughter: endVtx->particles_out()) {
1075 if (!theDaughter) continue;
1076 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1077 allstabledescendants.insert(theDaughter);
1078 }
1079 findParticleStableDescendants(theDaughter, allstabledescendants);
1080 }
1081 }
1082
1086
1087 template <class T> bool isHardScatteringVertex(T pVert) {
1088 if (pVert == nullptr) return false;
1089 T pV = pVert;
1090 int numOfPartIn(0);
1091 int pdg(0);
1092
1093 do {
1094 pVert = pV;
1095 auto incoming = pVert->particles_in();
1096 numOfPartIn = incoming.size();
1097 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1098 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1099
1100 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1101
1102 if (numOfPartIn == 2) {
1103 auto incoming = pVert->particles_in();
1104 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;
1105 }
1106 return false;
1107}
1108
1112
1113 template <class T> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
1119 for (auto parent: incoming) {
1120 if (!parent) continue;
1121 // should this really go into parton-level territory?
1122 // probably depends where BSM particles are being decayed
1123 fromBSM |= isBSM(parent);
1124 if (!isPhysical(parent)) return false;
1125 fromTau |= isTau(parent);
1126 if (isHadron(parent)&&!isBeam(parent)) {
1127 if (!hadron) hadron = parent; // assumes linear hadron parentage
1128 return true;
1129 }
1130 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1131 }
1132 return fromHad;
1133 }
1134
1137
1138 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1139 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1140 decltype(thePart->end_vertex()) pVert(nullptr);
1141 if (EndVert != nullptr) {
1142 do {
1143 bool samePart = false;
1144 pVert = nullptr;
1145 auto outgoing = EndVert->particles_out();
1146 auto incoming = EndVert->particles_in();
1147 for (const auto& itrDaug: outgoing) {
1148 if (!itrDaug) continue;
1149 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1150 // brem on generator level for tau
1151 (outgoing.size() == 1 && incoming.size() == 1 &&
1153 itrDaug->pdg_id() == thePart->pdg_id()) {
1154 samePart = true;
1155 pVert = itrDaug->end_vertex();
1156 }
1157 }
1158 if (samePart) EndVert = pVert;
1159 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1160 }
1161 return EndVert;
1162 }
1163
1165
1166 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1167 if (!theVert) return {};
1168 decltype(theVert->particles_out()) finalStatePart;
1169 auto outgoing = theVert->particles_out();
1170 for (const auto& thePart: outgoing) {
1171 if (!thePart) continue;
1172 finalStatePart.push_back(thePart);
1173 if (isStable(thePart)) continue;
1174 V pVert = findSimulatedEndVertex(thePart);
1175 if (pVert == theVert) break; // to prevent Sherpa loop
1176 if (pVert != nullptr) {
1177 auto vecPart = findFinalStateParticles<V>(pVert);
1178 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1179 }
1180 }
1181 return finalStatePart;
1182 }
1183
1184}
1185#endif

◆ isChLepton() [1/2]

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

Definition at line 201 of file HepMCHelpers.h.

201: incoming) {

◆ 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 42 of file HepMCHelpers.h.

◆ isDiquark() [1/3]

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

Definition at line 229 of file HepMCHelpers.h.

229 : outgoing) {
230 if (!itrDaug) continue;
231 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
232 // brem on generator level for tau
233 (outgoing.size() == 1 && incoming.size() == 1 &&

◆ isDiquark() [2/3]

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

Definition at line 235 of file HepMCHelpers.h.

235{

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

◆ isDM() [1/2]

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

Definition at line 660 of file HepMCHelpers.h.

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

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

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 auto incoming = partOriVert->particles_in();
1201 for ( auto p: incoming) {
1202 theMoth = p;
1203 if (!theMoth) continue;
1204 MotherPDG = theMoth->pdg_id();
1205 MothOriVert = theMoth->production_vertex();
1206 if (MotherPDG == partPDG) break;
1207 }
1208 itr++;
1209 if (itr > 100) {
1210 break;
1211 }
1212 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1213 MothOriVert != partOriVert);
1214 return theMoth;
1215 }
1216
1218
1219 template <class C, class T> T findMatching(C TruthContainer, T p) {
1220 T ptrPart = nullptr;
1221 if (!p) return ptrPart;
1222 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1223 for (T truthParticle : *TruthContainer) {
1224 if (HepMC::is_sim_descendant(p,truthParticle)) {
1225 ptrPart = truthParticle;
1226 break;
1227 }
1228 }
1229 }
1230 else {
1231 for (T truthParticle : TruthContainer) {
1232 if (HepMC::is_sim_descendant(p,truthParticle)) {
1233 ptrPart = truthParticle;
1234 break;
1235 }
1236 }
1237 }
1238 return ptrPart;
1239 }
1241
1242 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1243 auto prodVtx = thePart->production_vertex();
1244 if (!prodVtx) return;
1245 for (auto theMother: prodVtx->particles_in()) {
1246 if (!theMother) continue;
1247 allancestors.insert(theMother);
1248 findParticleAncestors(theMother, allancestors);
1249 }
1250 }
1251
1253
1254 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1255 auto endVtx = thePart->end_vertex();
1256 if (!endVtx) return;
1257 for (auto theDaughter: endVtx->particles_out()) {
1258 if (!theDaughter) continue;
1259 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1260 allstabledescendants.insert(theDaughter);
1261 }
1262 findParticleStableDescendants(theDaughter, allstabledescendants);
1263 }
1264 }
1265
1269
1270 template <class T> bool isHardScatteringVertex(T pVert) {
1271 if (pVert == nullptr) return false;
1272 T pV = pVert;
1273 int numOfPartIn(0);
1274 int pdg(0);
1275
1276 do {
1277 pVert = pV;
1278 auto incoming = pVert->particles_in();
1279 numOfPartIn = incoming.size();
1280 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1281 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1282
1283 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1284
1285 if (numOfPartIn == 2) {
1286 auto incoming = pVert->particles_in();
1287 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;
1288 }
1289 return false;
1290}
1291
1295
1296 template <class T> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
1302 for (auto parent: incoming) {
1303 if (!parent) continue;
1304 // should this really go into parton-level territory?
1305 // probably depends where BSM particles are being decayed
1306 fromBSM |= isBSM(parent);
1307 if (!isPhysical(parent)) return false;
1308 fromTau |= isTau(parent);
1309 if (isHadron(parent)&&!isBeam(parent)) {
1310 if (!hadron) hadron = parent; // assumes linear hadron parentage
1311 return true;
1312 }
1313 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1314 }
1315 return fromHad;
1316 }
1317
1320
1321 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1322 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1323 decltype(thePart->end_vertex()) pVert(nullptr);
1324 if (EndVert != nullptr) {
1325 do {
1326 bool samePart = false;
1327 pVert = nullptr;
1328 auto outgoing = EndVert->particles_out();
1329 auto incoming = EndVert->particles_in();
1330 for (const auto& itrDaug: outgoing) {
1331 if (!itrDaug) continue;
1332 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1333 // brem on generator level for tau
1334 (outgoing.size() == 1 && incoming.size() == 1 &&
1336 itrDaug->pdg_id() == thePart->pdg_id()) {
1337 samePart = true;
1338 pVert = itrDaug->end_vertex();
1339 }
1340 }
1341 if (samePart) EndVert = pVert;
1342 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1343 }
1344 return EndVert;
1345 }
1346
1348
1349 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1350 if (!theVert) return {};
1351 decltype(theVert->particles_out()) finalStatePart;
1352 auto outgoing = theVert->particles_out();
1353 for (const auto& thePart: outgoing) {
1354 if (!thePart) continue;
1355 finalStatePart.push_back(thePart);
1356 if (isStable(thePart)) continue;
1357 V pVert = findSimulatedEndVertex(thePart);
1358 if (pVert == theVert) break; // to prevent Sherpa loop
1359 if (pVert != nullptr) {
1360 auto vecPart = findFinalStateParticles<V>(pVert);
1361 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1362 }
1363 }
1364 return finalStatePart;
1365 }
1366
1367}
1368#endif

◆ isEMInteracting() [2/2]

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

Definition at line 1101 of file HepMCHelpers.h.

1119{
1120 namespace Pythia8
1121 {
1123 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1124
1125 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1126
1127 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1128 }
1129
1130#include "AtlasPID.h"
1131
1133 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1134
1136 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1137
1139 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1140
1142 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1143
1145 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1146
1148 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1149
1151 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1152
1154 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1155
1157 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1158
1160 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1161
1165 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1166 const auto vertex = p->end_vertex();
1167 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1168 }
1169
1171 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1172
1174 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1175 const int apid = std::abs(p->pdg_id());
1176 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1177 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1178 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1179 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1180 return false;
1181 }
1182
1184
1185 template <class T> T findMother(T thePart) {
1186 auto partOriVert = thePart->production_vertex();
1187 if (!partOriVert) return nullptr;
1188
1189 long partPDG = thePart->pdg_id();
1190 long MotherPDG(0);
1191
1192 auto MothOriVert = partOriVert;
1193 MothOriVert = nullptr;
1194 T theMoth(nullptr);
1195
1196 size_t itr = 0;
1197 do {
1198 if (itr != 0) partOriVert = MothOriVert;
1199 auto incoming = partOriVert->particles_in();
1200 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
1296 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1297 auto vtx = p->production_vertex();
1298 if (!vtx) return false;
1299 bool fromHad = false;
1300 auto incoming = vtx->particles_in();
1301 for (auto parent: incoming) {
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
1366}
1367#endif

◆ isExcited() [1/3]

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

Definition at line 539 of file HepMCHelpers.h.

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

◆ isExcited() [2/3]

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

Definition at line 544 of file HepMCHelpers.h.

562{
563 namespace Pythia8
564 {
566 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
567
568 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
569
570 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
571 }
572
573#include "AtlasPID.h"
574
576 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
577
579 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
580
582 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
583
585 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
586
588 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
589
591 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
592
594 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
595
597 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
598
600 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
601
603 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
604
608 template <class T> inline bool isStableOrSimDecayed(const T& p) {
609 const auto vertex = p->end_vertex();
610 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
611 }
612
614 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
615
617 template <class T> inline bool isSpecialNonInteracting(const T& p) {
618 const int apid = std::abs(p->pdg_id());
619 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
620 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
621 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
622 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
623 return false;
624 }
625
627
628 template <class T> T findMother(T thePart) {
629 auto partOriVert = thePart->production_vertex();
630 if (!partOriVert) return nullptr;
631
632 long partPDG = thePart->pdg_id();
633 long MotherPDG(0);
634
635 auto MothOriVert = partOriVert;
636 MothOriVert = nullptr;
637 T theMoth(nullptr);
638
639 size_t itr = 0;
640 do {
641 if (itr != 0) partOriVert = MothOriVert;
642 auto incoming = partOriVert->particles_in();
643 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
739 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
740 auto vtx = p->production_vertex();
741 if (!vtx) return false;
742 bool fromHad = false;
743 auto incoming = vtx->particles_in();
744 for (auto parent: incoming) {
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
809}
810#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.

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

◆ isFinalState()

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

Identify if the particle is final state particle.

Definition at line 48 of file HepMCHelpers.h.

48{ 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>
bool MC::isFromHadron ( T p,
T 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 195 of file HepMCHelpers.h.

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

◆ isGaugino() [1/3]

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

Definition at line 506 of file HepMCHelpers.h.

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

◆ isGaugino() [2/3]

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

Definition at line 509 of file HepMCHelpers.h.

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

◆ isGaugino() [3/3]

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

Definition at line 505 of file HepMCHelpers.h.

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

◆ isGeantino() [1/2]

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

Definition at line 439 of file HepMCHelpers.h.

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

◆ isGeantino() [2/2]

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

Definition at line 438 of file HepMCHelpers.h.

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

◆ isGenericMultichargedParticle() [1/3]

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

Definition at line 686 of file HepMCHelpers.h.

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

◆ isGenericMultichargedParticle() [2/3]

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

Definition at line 687 of file HepMCHelpers.h.

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

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

◆ isGenSpecific() [1/2]

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

Definition at line 427 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
526 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
627 for (auto parent: incoming) {
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
692}
693#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.

444{
445 namespace Pythia8
446 {
448 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
449
450 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
451
452 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
453 }
454
455#include "AtlasPID.h"
456
458 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
459
461 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
462
464 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
465
467 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
468
470 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
471
473 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
474
476 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
477
479 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
480
482 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
483
485 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
486
490 template <class T> inline bool isStableOrSimDecayed(const T& p) {
491 const auto vertex = p->end_vertex();
492 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
493 }
494
496 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
497
499 template <class T> inline bool isSpecialNonInteracting(const T& p) {
500 const int apid = std::abs(p->pdg_id());
501 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
502 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
503 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
504 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
505 return false;
506 }
507
509
510 template <class T> T findMother(T thePart) {
511 auto partOriVert = thePart->production_vertex();
512 if (!partOriVert) return nullptr;
513
514 long partPDG = thePart->pdg_id();
515 long MotherPDG(0);
516
517 auto MothOriVert = partOriVert;
518 MothOriVert = nullptr;
519 T theMoth(nullptr);
520
521 size_t itr = 0;
522 do {
523 if (itr != 0) partOriVert = MothOriVert;
524 auto incoming = partOriVert->particles_in();
525 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
621 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
622 auto vtx = p->production_vertex();
623 if (!vtx) return false;
624 bool fromHad = false;
625 auto incoming = vtx->particles_in();
626 for (auto parent: incoming) {
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
691}
692#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 54 of file HepMCHelpers.h.

◆ isGlueball() [1/3]

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

Definition at line 443 of file HepMCHelpers.h.

461{
462 namespace Pythia8
463 {
465 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
466
467 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
468
469 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
470 }
471
472#include "AtlasPID.h"
473
475 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
476
478 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
479
481 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
482
484 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
485
487 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
488
490 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
491
493 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
494
496 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
497
499 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
500
502 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
503
507 template <class T> inline bool isStableOrSimDecayed(const T& p) {
508 const auto vertex = p->end_vertex();
509 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
510 }
511
513 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
514
516 template <class T> inline bool isSpecialNonInteracting(const T& p) {
517 const int apid = std::abs(p->pdg_id());
518 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
519 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
520 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
521 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
522 return false;
523 }
524
526
527 template <class T> T findMother(T thePart) {
528 auto partOriVert = thePart->production_vertex();
529 if (!partOriVert) return nullptr;
530
531 long partPDG = thePart->pdg_id();
532 long MotherPDG(0);
533
534 auto MothOriVert = partOriVert;
535 MothOriVert = nullptr;
536 T theMoth(nullptr);
537
538 size_t itr = 0;
539 do {
540 if (itr != 0) partOriVert = MothOriVert;
541 auto incoming = partOriVert->particles_in();
542 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
638 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
639 auto vtx = p->production_vertex();
640 if (!vtx) return false;
641 bool fromHad = false;
642 auto incoming = vtx->particles_in();
643 for (auto parent: incoming) {
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
708}
709#endif

◆ isGlueball() [2/3]

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

Definition at line 449 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
548 for ( auto p: incoming) {
549 theMoth = p;
550 if (!theMoth) continue;
551 MotherPDG = theMoth->pdg_id();
552 MothOriVert = theMoth->production_vertex();
553 if (MotherPDG == partPDG) break;
554 }
555 itr++;
556 if (itr > 100) {
557 break;
558 }
559 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
560 MothOriVert != partOriVert);
561 return theMoth;
562 }
563
565
566 template <class C, class T> T findMatching(C TruthContainer, T p) {
567 T ptrPart = nullptr;
568 if (!p) return ptrPart;
569 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
570 for (T truthParticle : *TruthContainer) {
571 if (HepMC::is_sim_descendant(p,truthParticle)) {
572 ptrPart = truthParticle;
573 break;
574 }
575 }
576 }
577 else {
578 for (T truthParticle : TruthContainer) {
579 if (HepMC::is_sim_descendant(p,truthParticle)) {
580 ptrPart = truthParticle;
581 break;
582 }
583 }
584 }
585 return ptrPart;
586 }
588
589 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
590 auto prodVtx = thePart->production_vertex();
591 if (!prodVtx) return;
592 for (auto theMother: prodVtx->particles_in()) {
593 if (!theMother) continue;
594 allancestors.insert(theMother);
595 findParticleAncestors(theMother, allancestors);
596 }
597 }
598
600
601 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
602 auto endVtx = thePart->end_vertex();
603 if (!endVtx) return;
604 for (auto theDaughter: endVtx->particles_out()) {
605 if (!theDaughter) continue;
606 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
607 allstabledescendants.insert(theDaughter);
608 }
609 findParticleStableDescendants(theDaughter, allstabledescendants);
610 }
611 }
612
616
617 template <class T> bool isHardScatteringVertex(T pVert) {
618 if (pVert == nullptr) return false;
619 T pV = pVert;
620 int numOfPartIn(0);
621 int pdg(0);
622
623 do {
624 pVert = pV;
625 auto incoming = pVert->particles_in();
626 numOfPartIn = incoming.size();
627 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
628 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
629
630 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
631
632 if (numOfPartIn == 2) {
633 auto incoming = pVert->particles_in();
634 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;
635 }
636 return false;
637}
638
642
643 template <class T> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
649 for (auto parent: incoming) {
650 if (!parent) continue;
651 // should this really go into parton-level territory?
652 // probably depends where BSM particles are being decayed
653 fromBSM |= isBSM(parent);
654 if (!isPhysical(parent)) return false;
655 fromTau |= isTau(parent);
656 if (isHadron(parent)&&!isBeam(parent)) {
657 if (!hadron) hadron = parent; // assumes linear hadron parentage
658 return true;
659 }
660 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
661 }
662 return fromHad;
663 }
664
667
668 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
669 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
670 decltype(thePart->end_vertex()) pVert(nullptr);
671 if (EndVert != nullptr) {
672 do {
673 bool samePart = false;
674 pVert = nullptr;
675 auto outgoing = EndVert->particles_out();
676 auto incoming = EndVert->particles_in();
677 for (const auto& itrDaug: outgoing) {
678 if (!itrDaug) continue;
679 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
680 // brem on generator level for tau
681 (outgoing.size() == 1 && incoming.size() == 1 &&
683 itrDaug->pdg_id() == thePart->pdg_id()) {
684 samePart = true;
685 pVert = itrDaug->end_vertex();
686 }
687 }
688 if (samePart) EndVert = pVert;
689 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
690 }
691 return EndVert;
692 }
693
695
696 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
697 if (!theVert) return {};
698 decltype(theVert->particles_out()) finalStatePart;
699 auto outgoing = theVert->particles_out();
700 for (const auto& thePart: outgoing) {
701 if (!thePart) continue;
702 finalStatePart.push_back(thePart);
703 if (isStable(thePart)) continue;
704 V pVert = findSimulatedEndVertex(thePart);
705 if (pVert == theVert) break; // to prevent Sherpa loop
706 if (pVert != nullptr) {
707 auto vecPart = findFinalStateParticles<V>(pVert);
708 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
709 }
710 }
711 return finalStatePart;
712 }
713
714}
715#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.

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

◆ isGluon() [1/2]

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

Definition at line 375 of file HepMCHelpers.h.

393{
394 namespace Pythia8
395 {
397 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
398
399 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
400
401 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
402 }
403
404#include "AtlasPID.h"
405
407 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
408
410 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
411
413 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
414
416 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
417
419 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
420
422 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
423
425 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
426
428 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
429
431 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
432
434 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
435
439 template <class T> inline bool isStableOrSimDecayed(const T& p) {
440 const auto vertex = p->end_vertex();
441 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
442 }
443
445 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
446
448 template <class T> inline bool isSpecialNonInteracting(const T& p) {
449 const int apid = std::abs(p->pdg_id());
450 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
451 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
452 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
453 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
454 return false;
455 }
456
458
459 template <class T> T findMother(T thePart) {
460 auto partOriVert = thePart->production_vertex();
461 if (!partOriVert) return nullptr;
462
463 long partPDG = thePart->pdg_id();
464 long MotherPDG(0);
465
466 auto MothOriVert = partOriVert;
467 MothOriVert = nullptr;
468 T theMoth(nullptr);
469
470 size_t itr = 0;
471 do {
472 if (itr != 0) partOriVert = MothOriVert;
473 auto incoming = partOriVert->particles_in();
474 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
570 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
571 auto vtx = p->production_vertex();
572 if (!vtx) return false;
573 bool fromHad = false;
574 auto incoming = vtx->particles_in();
575 for (auto parent: incoming) {
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
640}
641#endif

◆ isGluon() [2/2]

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

Definition at line 374 of file HepMCHelpers.h.

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

◆ isGraviton() [1/2]

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

Definition at line 399 of file HepMCHelpers.h.

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

◆ isGraviton() [2/2]

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

Definition at line 398 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
497 for ( auto p: incoming) {
498 theMoth = p;
499 if (!theMoth) continue;
500 MotherPDG = theMoth->pdg_id();
501 MothOriVert = theMoth->production_vertex();
502 if (MotherPDG == partPDG) break;
503 }
504 itr++;
505 if (itr > 100) {
506 break;
507 }
508 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
509 MothOriVert != partOriVert);
510 return theMoth;
511 }
512
514
515 template <class C, class T> T findMatching(C TruthContainer, T p) {
516 T ptrPart = nullptr;
517 if (!p) return ptrPart;
518 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
519 for (T truthParticle : *TruthContainer) {
520 if (HepMC::is_sim_descendant(p,truthParticle)) {
521 ptrPart = truthParticle;
522 break;
523 }
524 }
525 }
526 else {
527 for (T truthParticle : TruthContainer) {
528 if (HepMC::is_sim_descendant(p,truthParticle)) {
529 ptrPart = truthParticle;
530 break;
531 }
532 }
533 }
534 return ptrPart;
535 }
537
538 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
539 auto prodVtx = thePart->production_vertex();
540 if (!prodVtx) return;
541 for (auto theMother: prodVtx->particles_in()) {
542 if (!theMother) continue;
543 allancestors.insert(theMother);
544 findParticleAncestors(theMother, allancestors);
545 }
546 }
547
549
550 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
551 auto endVtx = thePart->end_vertex();
552 if (!endVtx) return;
553 for (auto theDaughter: endVtx->particles_out()) {
554 if (!theDaughter) continue;
555 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
556 allstabledescendants.insert(theDaughter);
557 }
558 findParticleStableDescendants(theDaughter, allstabledescendants);
559 }
560 }
561
565
566 template <class T> bool isHardScatteringVertex(T pVert) {
567 if (pVert == nullptr) return false;
568 T pV = pVert;
569 int numOfPartIn(0);
570 int pdg(0);
571
572 do {
573 pVert = pV;
574 auto incoming = pVert->particles_in();
575 numOfPartIn = incoming.size();
576 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
577 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
578
579 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
580
581 if (numOfPartIn == 2) {
582 auto incoming = pVert->particles_in();
583 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;
584 }
585 return false;
586}
587
591
592 template <class T> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
598 for (auto parent: incoming) {
599 if (!parent) continue;
600 // should this really go into parton-level territory?
601 // probably depends where BSM particles are being decayed
602 fromBSM |= isBSM(parent);
603 if (!isPhysical(parent)) return false;
604 fromTau |= isTau(parent);
605 if (isHadron(parent)&&!isBeam(parent)) {
606 if (!hadron) hadron = parent; // assumes linear hadron parentage
607 return true;
608 }
609 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
610 }
611 return fromHad;
612 }
613
616
617 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
618 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
619 decltype(thePart->end_vertex()) pVert(nullptr);
620 if (EndVert != nullptr) {
621 do {
622 bool samePart = false;
623 pVert = nullptr;
624 auto outgoing = EndVert->particles_out();
625 auto incoming = EndVert->particles_in();
626 for (const auto& itrDaug: outgoing) {
627 if (!itrDaug) continue;
628 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
629 // brem on generator level for tau
630 (outgoing.size() == 1 && incoming.size() == 1 &&
632 itrDaug->pdg_id() == thePart->pdg_id()) {
633 samePart = true;
634 pVert = itrDaug->end_vertex();
635 }
636 }
637 if (samePart) EndVert = pVert;
638 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
639 }
640 return EndVert;
641 }
642
644
645 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
646 if (!theVert) return {};
647 decltype(theVert->particles_out()) finalStatePart;
648 auto outgoing = theVert->particles_out();
649 for (const auto& thePart: outgoing) {
650 if (!thePart) continue;
651 finalStatePart.push_back(thePart);
652 if (isStable(thePart)) continue;
653 V pVert = findSimulatedEndVertex(thePart);
654 if (pVert == theVert) break; // to prevent Sherpa loop
655 if (pVert != nullptr) {
656 auto vecPart = findFinalStateParticles<V>(pVert);
657 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
658 }
659 }
660 return finalStatePart;
661 }
662
663}
664#endif

◆ isHadron() [1/3]

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

Definition at line 353 of file HepMCHelpers.h.

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

◆ isHadron() [2/3]

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

Definition at line 354 of file HepMCHelpers.h.

372{
373 namespace Pythia8
374 {
376 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
377
378 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
379
380 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
381 }
382
383#include "AtlasPID.h"
384
386 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
387
389 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
390
392 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
393
395 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
396
398 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
399
401 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
402
404 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
405
407 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
408
410 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
411
413 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
414
418 template <class T> inline bool isStableOrSimDecayed(const T& p) {
419 const auto vertex = p->end_vertex();
420 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
421 }
422
424 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
425
427 template <class T> inline bool isSpecialNonInteracting(const T& p) {
428 const int apid = std::abs(p->pdg_id());
429 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
430 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
431 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
432 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
433 return false;
434 }
435
437
438 template <class T> T findMother(T thePart) {
439 auto partOriVert = thePart->production_vertex();
440 if (!partOriVert) return nullptr;
441
442 long partPDG = thePart->pdg_id();
443 long MotherPDG(0);
444
445 auto MothOriVert = partOriVert;
446 MothOriVert = nullptr;
447 T theMoth(nullptr);
448
449 size_t itr = 0;
450 do {
451 if (itr != 0) partOriVert = MothOriVert;
452 auto incoming = partOriVert->particles_in();
453 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
549 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
550 auto vtx = p->production_vertex();
551 if (!vtx) return false;
552 bool fromHad = false;
553 auto incoming = vtx->particles_in();
554 for (auto parent: incoming) {
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
619}
620#endif

◆ isHadron() [3/3]

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

Definition at line 352 of file HepMCHelpers.h.

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

169 {
170 if (pVert == nullptr) return false;
171 T pV = pVert;
172 int numOfPartIn(0);
173 int pdg(0);
174
175 do {
176 pVert = pV;
177 auto incoming = pVert->particles_in();
178 numOfPartIn = incoming.size();
179 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
180 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
181
182 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
183
184 if (numOfPartIn == 2) {
185 auto incoming = pVert->particles_in();
186 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;
187 }
188 return false;
189}

◆ isHeavyBaryon()

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

Definition at line 933 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
1032 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
1133 for (auto parent: incoming) {
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
1198}
1199#endif

◆ isHeavyBoson() [1/2]

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

Definition at line 388 of file HepMCHelpers.h.

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

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

◆ isHeavyHadron()

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

Definition at line 910 of file HepMCHelpers.h.

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

◆ isHeavyMeson()

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

Definition at line 917 of file HepMCHelpers.h.

935{
936 namespace Pythia8
937 {
939 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
940
941 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
942
943 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
944 }
945
946#include "AtlasPID.h"
947
949 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
950
952 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
953
955 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
956
958 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
959
961 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
962
964 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
965
967 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
968
970 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
971
973 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
974
976 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
977
981 template <class T> inline bool isStableOrSimDecayed(const T& p) {
982 const auto vertex = p->end_vertex();
983 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
984 }
985
987 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
988
990 template <class T> inline bool isSpecialNonInteracting(const T& p) {
991 const int apid = std::abs(p->pdg_id());
992 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
993 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
994 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
995 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
996 return false;
997 }
998
1000
1001 template <class T> T findMother(T thePart) {
1002 auto partOriVert = thePart->production_vertex();
1003 if (!partOriVert) return nullptr;
1004
1005 long partPDG = thePart->pdg_id();
1006 long MotherPDG(0);
1007
1008 auto MothOriVert = partOriVert;
1009 MothOriVert = nullptr;
1010 T theMoth(nullptr);
1011
1012 size_t itr = 0;
1013 do {
1014 if (itr != 0) partOriVert = MothOriVert;
1015 auto incoming = partOriVert->particles_in();
1016 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
1112 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1113 auto vtx = p->production_vertex();
1114 if (!vtx) return false;
1115 bool fromHad = false;
1116 auto incoming = vtx->particles_in();
1117 for (auto parent: incoming) {
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
1182}
1183#endif

◆ isHiddenValley() [1/3]

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

Definition at line 671 of file HepMCHelpers.h.

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

◆ isHiddenValley() [2/3]

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

Definition at line 677 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
776 for ( auto p: incoming) {
777 theMoth = p;
778 if (!theMoth) continue;
779 MotherPDG = theMoth->pdg_id();
780 MothOriVert = theMoth->production_vertex();
781 if (MotherPDG == partPDG) break;
782 }
783 itr++;
784 if (itr > 100) {
785 break;
786 }
787 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
788 MothOriVert != partOriVert);
789 return theMoth;
790 }
791
793
794 template <class C, class T> T findMatching(C TruthContainer, T p) {
795 T ptrPart = nullptr;
796 if (!p) return ptrPart;
797 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
798 for (T truthParticle : *TruthContainer) {
799 if (HepMC::is_sim_descendant(p,truthParticle)) {
800 ptrPart = truthParticle;
801 break;
802 }
803 }
804 }
805 else {
806 for (T truthParticle : TruthContainer) {
807 if (HepMC::is_sim_descendant(p,truthParticle)) {
808 ptrPart = truthParticle;
809 break;
810 }
811 }
812 }
813 return ptrPart;
814 }
816
817 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
818 auto prodVtx = thePart->production_vertex();
819 if (!prodVtx) return;
820 for (auto theMother: prodVtx->particles_in()) {
821 if (!theMother) continue;
822 allancestors.insert(theMother);
823 findParticleAncestors(theMother, allancestors);
824 }
825 }
826
828
829 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
830 auto endVtx = thePart->end_vertex();
831 if (!endVtx) return;
832 for (auto theDaughter: endVtx->particles_out()) {
833 if (!theDaughter) continue;
834 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
835 allstabledescendants.insert(theDaughter);
836 }
837 findParticleStableDescendants(theDaughter, allstabledescendants);
838 }
839 }
840
844
845 template <class T> bool isHardScatteringVertex(T pVert) {
846 if (pVert == nullptr) return false;
847 T pV = pVert;
848 int numOfPartIn(0);
849 int pdg(0);
850
851 do {
852 pVert = pV;
853 auto incoming = pVert->particles_in();
854 numOfPartIn = incoming.size();
855 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
856 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
857
858 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
859
860 if (numOfPartIn == 2) {
861 auto incoming = pVert->particles_in();
862 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;
863 }
864 return false;
865}
866
870
871 template <class T> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
877 for (auto parent: incoming) {
878 if (!parent) continue;
879 // should this really go into parton-level territory?
880 // probably depends where BSM particles are being decayed
881 fromBSM |= isBSM(parent);
882 if (!isPhysical(parent)) return false;
883 fromTau |= isTau(parent);
884 if (isHadron(parent)&&!isBeam(parent)) {
885 if (!hadron) hadron = parent; // assumes linear hadron parentage
886 return true;
887 }
888 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
889 }
890 return fromHad;
891 }
892
895
896 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
897 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
898 decltype(thePart->end_vertex()) pVert(nullptr);
899 if (EndVert != nullptr) {
900 do {
901 bool samePart = false;
902 pVert = nullptr;
903 auto outgoing = EndVert->particles_out();
904 auto incoming = EndVert->particles_in();
905 for (const auto& itrDaug: outgoing) {
906 if (!itrDaug) continue;
907 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
908 // brem on generator level for tau
909 (outgoing.size() == 1 && incoming.size() == 1 &&
911 itrDaug->pdg_id() == thePart->pdg_id()) {
912 samePart = true;
913 pVert = itrDaug->end_vertex();
914 }
915 }
916 if (samePart) EndVert = pVert;
917 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
918 }
919 return EndVert;
920 }
921
923
924 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
925 if (!theVert) return {};
926 decltype(theVert->particles_out()) finalStatePart;
927 auto outgoing = theVert->particles_out();
928 for (const auto& thePart: outgoing) {
929 if (!thePart) continue;
930 finalStatePart.push_back(thePart);
931 if (isStable(thePart)) continue;
932 V pVert = findSimulatedEndVertex(thePart);
933 if (pVert == theVert) break; // to prevent Sherpa loop
934 if (pVert != nullptr) {
935 auto vecPart = findFinalStateParticles<V>(pVert);
936 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
937 }
938 }
939 return finalStatePart;
940 }
941
942}
943#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.

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

◆ isHiggs() [1/2]

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

Definition at line 392 of file HepMCHelpers.h.

410{
411 namespace Pythia8
412 {
414 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
415
416 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
417
418 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
419 }
420
421#include "AtlasPID.h"
422
424 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
425
427 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
428
430 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
431
433 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
434
436 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
437
439 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
440
442 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
443
445 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
446
448 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
449
451 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
452
456 template <class T> inline bool isStableOrSimDecayed(const T& p) {
457 const auto vertex = p->end_vertex();
458 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
459 }
460
462 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
463
465 template <class T> inline bool isSpecialNonInteracting(const T& p) {
466 const int apid = std::abs(p->pdg_id());
467 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
468 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
469 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
470 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
471 return false;
472 }
473
475
476 template <class T> T findMother(T thePart) {
477 auto partOriVert = thePart->production_vertex();
478 if (!partOriVert) return nullptr;
479
480 long partPDG = thePart->pdg_id();
481 long MotherPDG(0);
482
483 auto MothOriVert = partOriVert;
484 MothOriVert = nullptr;
485 T theMoth(nullptr);
486
487 size_t itr = 0;
488 do {
489 if (itr != 0) partOriVert = MothOriVert;
490 auto incoming = partOriVert->particles_in();
491 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
587 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
588 auto vtx = p->production_vertex();
589 if (!vtx) return false;
590 bool fromHad = false;
591 auto incoming = vtx->particles_in();
592 for (auto parent: incoming) {
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
657}
658#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.

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

◆ isKK() [1/3]

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

Definition at line 637 of file HepMCHelpers.h.

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

◆ isKK() [2/3]

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

Definition at line 638 of file HepMCHelpers.h.

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

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

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

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

◆ isLightBaryon()

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

Definition at line 932 of file HepMCHelpers.h.

950{
951 namespace Pythia8
952 {
954 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
955
956 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
957
958 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
959 }
960
961#include "AtlasPID.h"
962
964 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
965
967 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
968
970 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
971
973 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
974
976 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
977
979 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
980
982 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
983
985 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
986
988 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
989
991 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
992
996 template <class T> inline bool isStableOrSimDecayed(const T& p) {
997 const auto vertex = p->end_vertex();
998 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
999 }
1000
1002 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1003
1005 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1006 const int apid = std::abs(p->pdg_id());
1007 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1008 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1009 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1010 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1011 return false;
1012 }
1013
1015
1016 template <class T> T findMother(T thePart) {
1017 auto partOriVert = thePart->production_vertex();
1018 if (!partOriVert) return nullptr;
1019
1020 long partPDG = thePart->pdg_id();
1021 long MotherPDG(0);
1022
1023 auto MothOriVert = partOriVert;
1024 MothOriVert = nullptr;
1025 T theMoth(nullptr);
1026
1027 size_t itr = 0;
1028 do {
1029 if (itr != 0) partOriVert = MothOriVert;
1030 auto incoming = partOriVert->particles_in();
1031 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
1127 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1128 auto vtx = p->production_vertex();
1129 if (!vtx) return false;
1130 bool fromHad = false;
1131 auto incoming = vtx->particles_in();
1132 for (auto parent: incoming) {
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
1197}
1198#endif

◆ isLightHadron()

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

Definition at line 909 of file HepMCHelpers.h.

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

◆ isLightMeson()

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

Definition at line 916 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
1015 for ( auto p: incoming) {
1016 theMoth = p;
1017 if (!theMoth) continue;
1018 MotherPDG = theMoth->pdg_id();
1019 MothOriVert = theMoth->production_vertex();
1020 if (MotherPDG == partPDG) break;
1021 }
1022 itr++;
1023 if (itr > 100) {
1024 break;
1025 }
1026 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1027 MothOriVert != partOriVert);
1028 return theMoth;
1029 }
1030
1032
1033 template <class C, class T> T findMatching(C TruthContainer, T p) {
1034 T ptrPart = nullptr;
1035 if (!p) return ptrPart;
1036 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1037 for (T truthParticle : *TruthContainer) {
1038 if (HepMC::is_sim_descendant(p,truthParticle)) {
1039 ptrPart = truthParticle;
1040 break;
1041 }
1042 }
1043 }
1044 else {
1045 for (T truthParticle : TruthContainer) {
1046 if (HepMC::is_sim_descendant(p,truthParticle)) {
1047 ptrPart = truthParticle;
1048 break;
1049 }
1050 }
1051 }
1052 return ptrPart;
1053 }
1055
1056 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1057 auto prodVtx = thePart->production_vertex();
1058 if (!prodVtx) return;
1059 for (auto theMother: prodVtx->particles_in()) {
1060 if (!theMother) continue;
1061 allancestors.insert(theMother);
1062 findParticleAncestors(theMother, allancestors);
1063 }
1064 }
1065
1067
1068 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1069 auto endVtx = thePart->end_vertex();
1070 if (!endVtx) return;
1071 for (auto theDaughter: endVtx->particles_out()) {
1072 if (!theDaughter) continue;
1073 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1074 allstabledescendants.insert(theDaughter);
1075 }
1076 findParticleStableDescendants(theDaughter, allstabledescendants);
1077 }
1078 }
1079
1083
1084 template <class T> bool isHardScatteringVertex(T pVert) {
1085 if (pVert == nullptr) return false;
1086 T pV = pVert;
1087 int numOfPartIn(0);
1088 int pdg(0);
1089
1090 do {
1091 pVert = pV;
1092 auto incoming = pVert->particles_in();
1093 numOfPartIn = incoming.size();
1094 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1095 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1096
1097 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1098
1099 if (numOfPartIn == 2) {
1100 auto incoming = pVert->particles_in();
1101 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;
1102 }
1103 return false;
1104}
1105
1109
1110 template <class T> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
1116 for (auto parent: incoming) {
1117 if (!parent) continue;
1118 // should this really go into parton-level territory?
1119 // probably depends where BSM particles are being decayed
1120 fromBSM |= isBSM(parent);
1121 if (!isPhysical(parent)) return false;
1122 fromTau |= isTau(parent);
1123 if (isHadron(parent)&&!isBeam(parent)) {
1124 if (!hadron) hadron = parent; // assumes linear hadron parentage
1125 return true;
1126 }
1127 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1128 }
1129 return fromHad;
1130 }
1131
1134
1135 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1136 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1137 decltype(thePart->end_vertex()) pVert(nullptr);
1138 if (EndVert != nullptr) {
1139 do {
1140 bool samePart = false;
1141 pVert = nullptr;
1142 auto outgoing = EndVert->particles_out();
1143 auto incoming = EndVert->particles_in();
1144 for (const auto& itrDaug: outgoing) {
1145 if (!itrDaug) continue;
1146 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1147 // brem on generator level for tau
1148 (outgoing.size() == 1 && incoming.size() == 1 &&
1150 itrDaug->pdg_id() == thePart->pdg_id()) {
1151 samePart = true;
1152 pVert = itrDaug->end_vertex();
1153 }
1154 }
1155 if (samePart) EndVert = pVert;
1156 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1157 }
1158 return EndVert;
1159 }
1160
1162
1163 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1164 if (!theVert) return {};
1165 decltype(theVert->particles_out()) finalStatePart;
1166 auto outgoing = theVert->particles_out();
1167 for (const auto& thePart: outgoing) {
1168 if (!thePart) continue;
1169 finalStatePart.push_back(thePart);
1170 if (isStable(thePart)) continue;
1171 V pVert = findSimulatedEndVertex(thePart);
1172 if (pVert == theVert) break; // to prevent Sherpa loop
1173 if (pVert != nullptr) {
1174 auto vecPart = findFinalStateParticles<V>(pVert);
1175 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1176 }
1177 }
1178 return finalStatePart;
1179 }
1180
1181}
1182#endif

◆ isMeson() [1/3]

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

Definition at line 246 of file HepMCHelpers.h.

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

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

◆ isMonopole() [2/3]

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

Definition at line 648 of file HepMCHelpers.h.

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

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

◆ isMSSMHiggs() [1/2]

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

Definition at line 396 of file HepMCHelpers.h.

414{
415 namespace Pythia8
416 {
418 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
419
420 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
421
422 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
423 }
424
425#include "AtlasPID.h"
426
428 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
429
431 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
432
434 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
435
437 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
438
440 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
441
443 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
444
446 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
447
449 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
450
452 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
453
455 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
456
460 template <class T> inline bool isStableOrSimDecayed(const T& p) {
461 const auto vertex = p->end_vertex();
462 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
463 }
464
466 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
467
469 template <class T> inline bool isSpecialNonInteracting(const T& p) {
470 const int apid = std::abs(p->pdg_id());
471 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
472 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
473 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
474 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
475 return false;
476 }
477
479
480 template <class T> T findMother(T thePart) {
481 auto partOriVert = thePart->production_vertex();
482 if (!partOriVert) return nullptr;
483
484 long partPDG = thePart->pdg_id();
485 long MotherPDG(0);
486
487 auto MothOriVert = partOriVert;
488 MothOriVert = nullptr;
489 T theMoth(nullptr);
490
491 size_t itr = 0;
492 do {
493 if (itr != 0) partOriVert = MothOriVert;
494 auto incoming = partOriVert->particles_in();
495 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
591 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
592 auto vtx = p->production_vertex();
593 if (!vtx) return false;
594 bool fromHad = false;
595 auto incoming = vtx->particles_in();
596 for (auto parent: incoming) {
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
661}
662#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.

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

◆ isNeutral() [1/3]

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

Definition at line 1087 of file HepMCHelpers.h.

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

◆ isNeutral() [2/3]

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

Definition at line 1088 of file HepMCHelpers.h.

1106{
1107 namespace Pythia8
1108 {
1110 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1111
1112 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1113
1114 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1115 }
1116
1117#include "AtlasPID.h"
1118
1120 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1121
1123 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1124
1126 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1127
1129 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1130
1132 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1133
1135 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1136
1138 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1139
1141 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1142
1144 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1145
1147 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1148
1152 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1153 const auto vertex = p->end_vertex();
1154 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1155 }
1156
1158 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1159
1161 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1162 const int apid = std::abs(p->pdg_id());
1163 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1164 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1165 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1166 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1167 return false;
1168 }
1169
1171
1172 template <class T> T findMother(T thePart) {
1173 auto partOriVert = thePart->production_vertex();
1174 if (!partOriVert) return nullptr;
1175
1176 long partPDG = thePart->pdg_id();
1177 long MotherPDG(0);
1178
1179 auto MothOriVert = partOriVert;
1180 MothOriVert = nullptr;
1181 T theMoth(nullptr);
1182
1183 size_t itr = 0;
1184 do {
1185 if (itr != 0) partOriVert = MothOriVert;
1186 auto incoming = partOriVert->particles_in();
1187 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
1283 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1284 auto vtx = p->production_vertex();
1285 if (!vtx) return false;
1286 bool fromHad = false;
1287 auto incoming = vtx->particles_in();
1288 for (auto parent: incoming) {
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
1353}
1354#endif

◆ isNeutral() [3/3]

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

Definition at line 1086 of file HepMCHelpers.h.

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

◆ isNeutrinoRH() [1/2]

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

Definition at line 422 of file HepMCHelpers.h.

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

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

◆ isNucleus() [1/3]

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

Definition at line 704 of file HepMCHelpers.h.

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

◆ isNucleus() [2/3]

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

Definition at line 713 of file HepMCHelpers.h.

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

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

◆ isParton()

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

Definition at line 1104 of file HepMCHelpers.h.

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

◆ isPentaquark() [1/3]

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

Definition at line 344 of file HepMCHelpers.h.

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

◆ isPentaquark() [2/3]

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

Definition at line 349 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
448 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
549 for (auto parent: incoming) {
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
614}
615#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.

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

◆ isPhoton() [1/2]

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

Definition at line 378 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
477 for ( auto p: incoming) {
478 theMoth = p;
479 if (!theMoth) continue;
480 MotherPDG = theMoth->pdg_id();
481 MothOriVert = theMoth->production_vertex();
482 if (MotherPDG == partPDG) break;
483 }
484 itr++;
485 if (itr > 100) {
486 break;
487 }
488 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
489 MothOriVert != partOriVert);
490 return theMoth;
491 }
492
494
495 template <class C, class T> T findMatching(C TruthContainer, T p) {
496 T ptrPart = nullptr;
497 if (!p) return ptrPart;
498 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
499 for (T truthParticle : *TruthContainer) {
500 if (HepMC::is_sim_descendant(p,truthParticle)) {
501 ptrPart = truthParticle;
502 break;
503 }
504 }
505 }
506 else {
507 for (T truthParticle : TruthContainer) {
508 if (HepMC::is_sim_descendant(p,truthParticle)) {
509 ptrPart = truthParticle;
510 break;
511 }
512 }
513 }
514 return ptrPart;
515 }
517
518 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
519 auto prodVtx = thePart->production_vertex();
520 if (!prodVtx) return;
521 for (auto theMother: prodVtx->particles_in()) {
522 if (!theMother) continue;
523 allancestors.insert(theMother);
524 findParticleAncestors(theMother, allancestors);
525 }
526 }
527
529
530 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
531 auto endVtx = thePart->end_vertex();
532 if (!endVtx) return;
533 for (auto theDaughter: endVtx->particles_out()) {
534 if (!theDaughter) continue;
535 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
536 allstabledescendants.insert(theDaughter);
537 }
538 findParticleStableDescendants(theDaughter, allstabledescendants);
539 }
540 }
541
545
546 template <class T> bool isHardScatteringVertex(T pVert) {
547 if (pVert == nullptr) return false;
548 T pV = pVert;
549 int numOfPartIn(0);
550 int pdg(0);
551
552 do {
553 pVert = pV;
554 auto incoming = pVert->particles_in();
555 numOfPartIn = incoming.size();
556 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
557 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
558
559 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
560
561 if (numOfPartIn == 2) {
562 auto incoming = pVert->particles_in();
563 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;
564 }
565 return false;
566}
567
571
572 template <class T> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
578 for (auto parent: incoming) {
579 if (!parent) continue;
580 // should this really go into parton-level territory?
581 // probably depends where BSM particles are being decayed
582 fromBSM |= isBSM(parent);
583 if (!isPhysical(parent)) return false;
584 fromTau |= isTau(parent);
585 if (isHadron(parent)&&!isBeam(parent)) {
586 if (!hadron) hadron = parent; // assumes linear hadron parentage
587 return true;
588 }
589 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
590 }
591 return fromHad;
592 }
593
596
597 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
598 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
599 decltype(thePart->end_vertex()) pVert(nullptr);
600 if (EndVert != nullptr) {
601 do {
602 bool samePart = false;
603 pVert = nullptr;
604 auto outgoing = EndVert->particles_out();
605 auto incoming = EndVert->particles_in();
606 for (const auto& itrDaug: outgoing) {
607 if (!itrDaug) continue;
608 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
609 // brem on generator level for tau
610 (outgoing.size() == 1 && incoming.size() == 1 &&
612 itrDaug->pdg_id() == thePart->pdg_id()) {
613 samePart = true;
614 pVert = itrDaug->end_vertex();
615 }
616 }
617 if (samePart) EndVert = pVert;
618 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
619 }
620 return EndVert;
621 }
622
624
625 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
626 if (!theVert) return {};
627 decltype(theVert->particles_out()) finalStatePart;
628 auto outgoing = theVert->particles_out();
629 for (const auto& thePart: outgoing) {
630 if (!thePart) continue;
631 finalStatePart.push_back(thePart);
632 if (isStable(thePart)) continue;
633 V pVert = findSimulatedEndVertex(thePart);
634 if (pVert == theVert) break; // to prevent Sherpa loop
635 if (pVert != nullptr) {
636 auto vecPart = findFinalStateParticles<V>(pVert);
637 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
638 }
639 }
640 return finalStatePart;
641 }
642
643}
644#endif

◆ isPhoton() [2/2]

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

Definition at line 377 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
476 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
577 for (auto parent: incoming) {
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
642}
643#endif

◆ isPhysical()

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

Identify if the particle is physical, i.e. is stable or decayed.

Definition at line 51 of file HepMCHelpers.h.

51{ return isStable<T>(p) || isDecayed<T>(p); }

◆ isPythia8Specific() [1/3]

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

Definition at line 413 of file HepMCHelpers.h.

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

◆ isPythia8Specific() [2/3]

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

Definition at line 414 of file HepMCHelpers.h.

432{
433 namespace Pythia8
434 {
436 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
437
438 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
439
440 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
441 }
442
443#include "AtlasPID.h"
444
446 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
447
449 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
450
452 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
453
455 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
456
458 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
459
461 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
462
464 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
465
467 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
468
470 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
471
473 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
474
478 template <class T> inline bool isStableOrSimDecayed(const T& p) {
479 const auto vertex = p->end_vertex();
480 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
481 }
482
484 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
485
487 template <class T> inline bool isSpecialNonInteracting(const T& p) {
488 const int apid = std::abs(p->pdg_id());
489 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
490 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
491 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
492 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
493 return false;
494 }
495
497
498 template <class T> T findMother(T thePart) {
499 auto partOriVert = thePart->production_vertex();
500 if (!partOriVert) return nullptr;
501
502 long partPDG = thePart->pdg_id();
503 long MotherPDG(0);
504
505 auto MothOriVert = partOriVert;
506 MothOriVert = nullptr;
507 T theMoth(nullptr);
508
509 size_t itr = 0;
510 do {
511 if (itr != 0) partOriVert = MothOriVert;
512 auto incoming = partOriVert->particles_in();
513 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
609 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
610 auto vtx = p->production_vertex();
611 if (!vtx) return false;
612 bool fromHad = false;
613 auto incoming = vtx->particles_in();
614 for (auto parent: incoming) {
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
679}
680#endif

◆ isPythia8Specific() [3/3]

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

Definition at line 412 of file HepMCHelpers.h.

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

◆ isQuark() [1/3]

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

Definition at line 170 of file HepMCHelpers.h.

◆ isQuark() [2/3]

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

Definition at line 169 of file HepMCHelpers.h.

169{

◆ isQuark() [3/3]

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

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.

APID: the fourth generation quarks are quarks.

Definition at line 168 of file HepMCHelpers.h.

◆ isQuarkonium() [1/3]

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

Definition at line 275 of file HepMCHelpers.h.

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

◆ isQuarkonium() [2/3]

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

Definition at line 279 of file HepMCHelpers.h.

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

◆ isQuarkonium() [3/3]

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

Is this a heavy-flavour quarkonium meson?

Note
Original by LHCb in Rivet analysis LHCB_2016_I1504058
phi = s,sbar is not considered quarkonium

Definition at line 274 of file HepMCHelpers.h.

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

◆ isRBaryon() [1/3]

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

Definition at line 591 of file HepMCHelpers.h.

609{
610 namespace Pythia8
611 {
613 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
614
615 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
616
617 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
618 }
619
620#include "AtlasPID.h"
621
623 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
624
626 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
627
629 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
630
632 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
633
635 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
636
638 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
639
641 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
642
644 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
645
647 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
648
650 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
651
655 template <class T> inline bool isStableOrSimDecayed(const T& p) {
656 const auto vertex = p->end_vertex();
657 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
658 }
659
661 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
662
664 template <class T> inline bool isSpecialNonInteracting(const T& p) {
665 const int apid = std::abs(p->pdg_id());
666 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
667 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
668 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
669 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
670 return false;
671 }
672
674
675 template <class T> T findMother(T thePart) {
676 auto partOriVert = thePart->production_vertex();
677 if (!partOriVert) return nullptr;
678
679 long partPDG = thePart->pdg_id();
680 long MotherPDG(0);
681
682 auto MothOriVert = partOriVert;
683 MothOriVert = nullptr;
684 T theMoth(nullptr);
685
686 size_t itr = 0;
687 do {
688 if (itr != 0) partOriVert = MothOriVert;
689 auto incoming = partOriVert->particles_in();
690 for ( auto p: incoming) {
691 theMoth = p;
692 if (!theMoth) continue;
693 MotherPDG = theMoth->pdg_id();
694 MothOriVert = theMoth->production_vertex();
695 if (MotherPDG == partPDG) break;
696 }
697 itr++;
698 if (itr > 100) {
699 break;
700 }
701 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
702 MothOriVert != partOriVert);
703 return theMoth;
704 }
705
707
708 template <class C, class T> T findMatching(C TruthContainer, T p) {
709 T ptrPart = nullptr;
710 if (!p) return ptrPart;
711 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
712 for (T truthParticle : *TruthContainer) {
713 if (HepMC::is_sim_descendant(p,truthParticle)) {
714 ptrPart = truthParticle;
715 break;
716 }
717 }
718 }
719 else {
720 for (T truthParticle : TruthContainer) {
721 if (HepMC::is_sim_descendant(p,truthParticle)) {
722 ptrPart = truthParticle;
723 break;
724 }
725 }
726 }
727 return ptrPart;
728 }
730
731 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
732 auto prodVtx = thePart->production_vertex();
733 if (!prodVtx) return;
734 for (auto theMother: prodVtx->particles_in()) {
735 if (!theMother) continue;
736 allancestors.insert(theMother);
737 findParticleAncestors(theMother, allancestors);
738 }
739 }
740
742
743 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
744 auto endVtx = thePart->end_vertex();
745 if (!endVtx) return;
746 for (auto theDaughter: endVtx->particles_out()) {
747 if (!theDaughter) continue;
748 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
749 allstabledescendants.insert(theDaughter);
750 }
751 findParticleStableDescendants(theDaughter, allstabledescendants);
752 }
753 }
754
758
759 template <class T> bool isHardScatteringVertex(T pVert) {
760 if (pVert == nullptr) return false;
761 T pV = pVert;
762 int numOfPartIn(0);
763 int pdg(0);
764
765 do {
766 pVert = pV;
767 auto incoming = pVert->particles_in();
768 numOfPartIn = incoming.size();
769 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
770 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
771
772 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
773
774 if (numOfPartIn == 2) {
775 auto incoming = pVert->particles_in();
776 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;
777 }
778 return false;
779}
780
784
785 template <class T> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
786 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
787 auto vtx = p->production_vertex();
788 if (!vtx) return false;
789 bool fromHad = false;
790 auto incoming = vtx->particles_in();
791 for (auto parent: incoming) {
792 if (!parent) continue;
793 // should this really go into parton-level territory?
794 // probably depends where BSM particles are being decayed
795 fromBSM |= isBSM(parent);
796 if (!isPhysical(parent)) return false;
797 fromTau |= isTau(parent);
798 if (isHadron(parent)&&!isBeam(parent)) {
799 if (!hadron) hadron = parent; // assumes linear hadron parentage
800 return true;
801 }
802 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
803 }
804 return fromHad;
805 }
806
809
810 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
811 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
812 decltype(thePart->end_vertex()) pVert(nullptr);
813 if (EndVert != nullptr) {
814 do {
815 bool samePart = false;
816 pVert = nullptr;
817 auto outgoing = EndVert->particles_out();
818 auto incoming = EndVert->particles_in();
819 for (const auto& itrDaug: outgoing) {
820 if (!itrDaug) continue;
821 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
822 // brem on generator level for tau
823 (outgoing.size() == 1 && incoming.size() == 1 &&
825 itrDaug->pdg_id() == thePart->pdg_id()) {
826 samePart = true;
827 pVert = itrDaug->end_vertex();
828 }
829 }
830 if (samePart) EndVert = pVert;
831 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
832 }
833 return EndVert;
834 }
835
837
838 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
839 if (!theVert) return {};
840 decltype(theVert->particles_out()) finalStatePart;
841 auto outgoing = theVert->particles_out();
842 for (const auto& thePart: outgoing) {
843 if (!thePart) continue;
844 finalStatePart.push_back(thePart);
845 if (isStable(thePart)) continue;
846 V pVert = findSimulatedEndVertex(thePart);
847 if (pVert == theVert) break; // to prevent Sherpa loop
848 if (pVert != nullptr) {
849 auto vecPart = findFinalStateParticles<V>(pVert);
850 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
851 }
852 }
853 return finalStatePart;
854 }
855
856}
857#endif

◆ isRBaryon() [2/3]

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

Definition at line 601 of file HepMCHelpers.h.

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

◆ isRBaryon() [3/3]

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

Definition at line 590 of file HepMCHelpers.h.

608{
609 namespace Pythia8
610 {
612 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
613
614 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
615
616 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
617 }
618
619#include "AtlasPID.h"
620
622 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
623
625 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
626
628 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
629
631 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
632
634 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
635
637 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
638
640 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
641
643 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
644
646 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
647
649 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
650
654 template <class T> inline bool isStableOrSimDecayed(const T& p) {
655 const auto vertex = p->end_vertex();
656 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
657 }
658
660 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
661
663 template <class T> inline bool isSpecialNonInteracting(const T& p) {
664 const int apid = std::abs(p->pdg_id());
665 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
666 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
667 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
668 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
669 return false;
670 }
671
673
674 template <class T> T findMother(T thePart) {
675 auto partOriVert = thePart->production_vertex();
676 if (!partOriVert) return nullptr;
677
678 long partPDG = thePart->pdg_id();
679 long MotherPDG(0);
680
681 auto MothOriVert = partOriVert;
682 MothOriVert = nullptr;
683 T theMoth(nullptr);
684
685 size_t itr = 0;
686 do {
687 if (itr != 0) partOriVert = MothOriVert;
688 auto incoming = partOriVert->particles_in();
689 for ( auto p: incoming) {
690 theMoth = p;
691 if (!theMoth) continue;
692 MotherPDG = theMoth->pdg_id();
693 MothOriVert = theMoth->production_vertex();
694 if (MotherPDG == partPDG) break;
695 }
696 itr++;
697 if (itr > 100) {
698 break;
699 }
700 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
701 MothOriVert != partOriVert);
702 return theMoth;
703 }
704
706
707 template <class C, class T> T findMatching(C TruthContainer, T p) {
708 T ptrPart = nullptr;
709 if (!p) return ptrPart;
710 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
711 for (T truthParticle : *TruthContainer) {
712 if (HepMC::is_sim_descendant(p,truthParticle)) {
713 ptrPart = truthParticle;
714 break;
715 }
716 }
717 }
718 else {
719 for (T truthParticle : TruthContainer) {
720 if (HepMC::is_sim_descendant(p,truthParticle)) {
721 ptrPart = truthParticle;
722 break;
723 }
724 }
725 }
726 return ptrPart;
727 }
729
730 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
731 auto prodVtx = thePart->production_vertex();
732 if (!prodVtx) return;
733 for (auto theMother: prodVtx->particles_in()) {
734 if (!theMother) continue;
735 allancestors.insert(theMother);
736 findParticleAncestors(theMother, allancestors);
737 }
738 }
739
741
742 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
743 auto endVtx = thePart->end_vertex();
744 if (!endVtx) return;
745 for (auto theDaughter: endVtx->particles_out()) {
746 if (!theDaughter) continue;
747 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
748 allstabledescendants.insert(theDaughter);
749 }
750 findParticleStableDescendants(theDaughter, allstabledescendants);
751 }
752 }
753
757
758 template <class T> bool isHardScatteringVertex(T pVert) {
759 if (pVert == nullptr) return false;
760 T pV = pVert;
761 int numOfPartIn(0);
762 int pdg(0);
763
764 do {
765 pVert = pV;
766 auto incoming = pVert->particles_in();
767 numOfPartIn = incoming.size();
768 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
769 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
770
771 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
772
773 if (numOfPartIn == 2) {
774 auto incoming = pVert->particles_in();
775 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;
776 }
777 return false;
778}
779
783
784 template <class T> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
785 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
786 auto vtx = p->production_vertex();
787 if (!vtx) return false;
788 bool fromHad = false;
789 auto incoming = vtx->particles_in();
790 for (auto parent: incoming) {
791 if (!parent) continue;
792 // should this really go into parton-level territory?
793 // probably depends where BSM particles are being decayed
794 fromBSM |= isBSM(parent);
795 if (!isPhysical(parent)) return false;
796 fromTau |= isTau(parent);
797 if (isHadron(parent)&&!isBeam(parent)) {
798 if (!hadron) hadron = parent; // assumes linear hadron parentage
799 return true;
800 }
801 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
802 }
803 return fromHad;
804 }
805
808
809 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
810 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
811 decltype(thePart->end_vertex()) pVert(nullptr);
812 if (EndVert != nullptr) {
813 do {
814 bool samePart = false;
815 pVert = nullptr;
816 auto outgoing = EndVert->particles_out();
817 auto incoming = EndVert->particles_in();
818 for (const auto& itrDaug: outgoing) {
819 if (!itrDaug) continue;
820 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
821 // brem on generator level for tau
822 (outgoing.size() == 1 && incoming.size() == 1 &&
824 itrDaug->pdg_id() == thePart->pdg_id()) {
825 samePart = true;
826 pVert = itrDaug->end_vertex();
827 }
828 }
829 if (samePart) EndVert = pVert;
830 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
831 }
832 return EndVert;
833 }
834
836
837 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
838 if (!theVert) return {};
839 decltype(theVert->particles_out()) finalStatePart;
840 auto outgoing = theVert->particles_out();
841 for (const auto& thePart: outgoing) {
842 if (!thePart) continue;
843 finalStatePart.push_back(thePart);
844 if (isStable(thePart)) continue;
845 V pVert = findSimulatedEndVertex(thePart);
846 if (pVert == theVert) break; // to prevent Sherpa loop
847 if (pVert != nullptr) {
848 auto vecPart = findFinalStateParticles<V>(pVert);
849 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
850 }
851 }
852 return finalStatePart;
853 }
854
855}
856#endif

◆ isResonance()

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

Definition at line 401 of file HepMCHelpers.h.

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 auto incoming = partOriVert->particles_in();
500 for ( auto p: incoming) {
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 (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 (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> bool isFromHadron(T p, T 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 auto incoming = vtx->particles_in();
601 for (auto parent: incoming) {
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
666}
667#endif

◆ isRGlueball() [1/3]

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

Definition at line 564 of file HepMCHelpers.h.

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

◆ isRGlueball() [2/3]

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

Definition at line 571 of file HepMCHelpers.h.

589{
590 namespace Pythia8
591 {
593 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
594
595 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
596
597 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
598 }
599
600#include "AtlasPID.h"
601
603 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
604
606 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
607
609 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
610
612 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
613
615 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
616
618 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
619
621 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
622
624 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
625
627 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
628
630 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
631
635 template <class T> inline bool isStableOrSimDecayed(const T& p) {
636 const auto vertex = p->end_vertex();
637 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
638 }
639
641 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
642
644 template <class T> inline bool isSpecialNonInteracting(const T& p) {
645 const int apid = std::abs(p->pdg_id());
646 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
647 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
648 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
649 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
650 return false;
651 }
652
654
655 template <class T> T findMother(T thePart) {
656 auto partOriVert = thePart->production_vertex();
657 if (!partOriVert) return nullptr;
658
659 long partPDG = thePart->pdg_id();
660 long MotherPDG(0);
661
662 auto MothOriVert = partOriVert;
663 MothOriVert = nullptr;
664 T theMoth(nullptr);
665
666 size_t itr = 0;
667 do {
668 if (itr != 0) partOriVert = MothOriVert;
669 auto incoming = partOriVert->particles_in();
670 for ( auto p: incoming) {
671 theMoth = p;
672 if (!theMoth) continue;
673 MotherPDG = theMoth->pdg_id();
674 MothOriVert = theMoth->production_vertex();
675 if (MotherPDG == partPDG) break;
676 }
677 itr++;
678 if (itr > 100) {
679 break;
680 }
681 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
682 MothOriVert != partOriVert);
683 return theMoth;
684 }
685
687
688 template <class C, class T> T findMatching(C TruthContainer, T p) {
689 T ptrPart = nullptr;
690 if (!p) return ptrPart;
691 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
692 for (T truthParticle : *TruthContainer) {
693 if (HepMC::is_sim_descendant(p,truthParticle)) {
694 ptrPart = truthParticle;
695 break;
696 }
697 }
698 }
699 else {
700 for (T truthParticle : TruthContainer) {
701 if (HepMC::is_sim_descendant(p,truthParticle)) {
702 ptrPart = truthParticle;
703 break;
704 }
705 }
706 }
707 return ptrPart;
708 }
710
711 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
712 auto prodVtx = thePart->production_vertex();
713 if (!prodVtx) return;
714 for (auto theMother: prodVtx->particles_in()) {
715 if (!theMother) continue;
716 allancestors.insert(theMother);
717 findParticleAncestors(theMother, allancestors);
718 }
719 }
720
722
723 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
724 auto endVtx = thePart->end_vertex();
725 if (!endVtx) return;
726 for (auto theDaughter: endVtx->particles_out()) {
727 if (!theDaughter) continue;
728 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
729 allstabledescendants.insert(theDaughter);
730 }
731 findParticleStableDescendants(theDaughter, allstabledescendants);
732 }
733 }
734
738
739 template <class T> bool isHardScatteringVertex(T pVert) {
740 if (pVert == nullptr) return false;
741 T pV = pVert;
742 int numOfPartIn(0);
743 int pdg(0);
744
745 do {
746 pVert = pV;
747 auto incoming = pVert->particles_in();
748 numOfPartIn = incoming.size();
749 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
750 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
751
752 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
753
754 if (numOfPartIn == 2) {
755 auto incoming = pVert->particles_in();
756 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;
757 }
758 return false;
759}
760
764
765 template <class T> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
766 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
767 auto vtx = p->production_vertex();
768 if (!vtx) return false;
769 bool fromHad = false;
770 auto incoming = vtx->particles_in();
771 for (auto parent: incoming) {
772 if (!parent) continue;
773 // should this really go into parton-level territory?
774 // probably depends where BSM particles are being decayed
775 fromBSM |= isBSM(parent);
776 if (!isPhysical(parent)) return false;
777 fromTau |= isTau(parent);
778 if (isHadron(parent)&&!isBeam(parent)) {
779 if (!hadron) hadron = parent; // assumes linear hadron parentage
780 return true;
781 }
782 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
783 }
784 return fromHad;
785 }
786
789
790 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
791 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
792 decltype(thePart->end_vertex()) pVert(nullptr);
793 if (EndVert != nullptr) {
794 do {
795 bool samePart = false;
796 pVert = nullptr;
797 auto outgoing = EndVert->particles_out();
798 auto incoming = EndVert->particles_in();
799 for (const auto& itrDaug: outgoing) {
800 if (!itrDaug) continue;
801 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
802 // brem on generator level for tau
803 (outgoing.size() == 1 && incoming.size() == 1 &&
805 itrDaug->pdg_id() == thePart->pdg_id()) {
806 samePart = true;
807 pVert = itrDaug->end_vertex();
808 }
809 }
810 if (samePart) EndVert = pVert;
811 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
812 }
813 return EndVert;
814 }
815
817
818 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
819 if (!theVert) return {};
820 decltype(theVert->particles_out()) finalStatePart;
821 auto outgoing = theVert->particles_out();
822 for (const auto& thePart: outgoing) {
823 if (!thePart) continue;
824 finalStatePart.push_back(thePart);
825 if (isStable(thePart)) continue;
826 V pVert = findSimulatedEndVertex(thePart);
827 if (pVert == theVert) break; // to prevent Sherpa loop
828 if (pVert != nullptr) {
829 auto vecPart = findFinalStateParticles<V>(pVert);
830 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
831 }
832 }
833 return finalStatePart;
834 }
835
836}
837#endif

◆ isRGlueball() [3/3]

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

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.

In the context of supersymmetric scenarios, these states are called R-hadrons, since they carry odd R- parity. R-hadron codes, defined here, should be viewed as templates for corresponding codes also in other scenarios, for any long-lived particle that is either an unflavored color octet or a flavored color triplet. The R-hadron code is obtained by combining the SUSY particle code with a code for the light degrees of freedom, with as many intermediate zeros removed from the former as required to make place for the latter at the end. (To exemplify, a sparticle n00000n˜q combined with quarks q1 and q2 obtains code n00n˜qnq1 nq2 nJ .) Specifically, the new-particle spin decouples in the limit of large masses, so that the final nJ digit is defined by the spin state of the light-quark system alone. An appropriate number of nq digits is used to define the ordinary-quark content. As usual, 9 rather than 21 is used to denote a gluon/gluino in composite states. The sign of the hadron agrees with that of the constituent new particle (a color triplet) where there is a distinct new antiparticle, and else is defined as for normal hadrons. Particle names are R with the flavor content as lower index. APID: Definition of R-Glueballs: 100099X (X=1,3), 100999Y (Y=1,5) APID: NB In the current numbering scheme, some states with 2 gluinos + gluon or 2 gluons + gluino could have degenerate PDG_IDs.

Definition at line 563 of file HepMCHelpers.h.

581{
582 namespace Pythia8
583 {
585 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
586
587 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
588
589 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
590 }
591
592#include "AtlasPID.h"
593
595 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
596
598 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
599
601 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
602
604 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
605
607 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
608
610 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
611
613 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
614
616 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
617
619 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
620
622 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
623
627 template <class T> inline bool isStableOrSimDecayed(const T& p) {
628 const auto vertex = p->end_vertex();
629 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
630 }
631
633 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
634
636 template <class T> inline bool isSpecialNonInteracting(const T& p) {
637 const int apid = std::abs(p->pdg_id());
638 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
639 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
640 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
641 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
642 return false;
643 }
644
646
647 template <class T> T findMother(T thePart) {
648 auto partOriVert = thePart->production_vertex();
649 if (!partOriVert) return nullptr;
650
651 long partPDG = thePart->pdg_id();
652 long MotherPDG(0);
653
654 auto MothOriVert = partOriVert;
655 MothOriVert = nullptr;
656 T theMoth(nullptr);
657
658 size_t itr = 0;
659 do {
660 if (itr != 0) partOriVert = MothOriVert;
661 auto incoming = partOriVert->particles_in();
662 for ( auto p: incoming) {
663 theMoth = p;
664 if (!theMoth) continue;
665 MotherPDG = theMoth->pdg_id();
666 MothOriVert = theMoth->production_vertex();
667 if (MotherPDG == partPDG) break;
668 }
669 itr++;
670 if (itr > 100) {
671 break;
672 }
673 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
674 MothOriVert != partOriVert);
675 return theMoth;
676 }
677
679
680 template <class C, class T> T findMatching(C TruthContainer, T p) {
681 T ptrPart = nullptr;
682 if (!p) return ptrPart;
683 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
684 for (T truthParticle : *TruthContainer) {
685 if (HepMC::is_sim_descendant(p,truthParticle)) {
686 ptrPart = truthParticle;
687 break;
688 }
689 }
690 }
691 else {
692 for (T truthParticle : TruthContainer) {
693 if (HepMC::is_sim_descendant(p,truthParticle)) {
694 ptrPart = truthParticle;
695 break;
696 }
697 }
698 }
699 return ptrPart;
700 }
702
703 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
704 auto prodVtx = thePart->production_vertex();
705 if (!prodVtx) return;
706 for (auto theMother: prodVtx->particles_in()) {
707 if (!theMother) continue;
708 allancestors.insert(theMother);
709 findParticleAncestors(theMother, allancestors);
710 }
711 }
712
714
715 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
716 auto endVtx = thePart->end_vertex();
717 if (!endVtx) return;
718 for (auto theDaughter: endVtx->particles_out()) {
719 if (!theDaughter) continue;
720 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
721 allstabledescendants.insert(theDaughter);
722 }
723 findParticleStableDescendants(theDaughter, allstabledescendants);
724 }
725 }
726
730
731 template <class T> bool isHardScatteringVertex(T pVert) {
732