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 if (pVert == nullptr) return false;
733 T pV = pVert;
734 int numOfPartIn(0);
735 int pdg(0);
736
737 do {
738 pVert = pV;
739 auto incoming = pVert->particles_in();
740 numOfPartIn = incoming.size();
741 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
742 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
743
744 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
745
746 if (numOfPartIn == 2) {
747 auto incoming = pVert->particles_in();
748 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;
749 }
750 return false;
751}
752
756
757 template <class T> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
758 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
759 auto vtx = p->production_vertex();
760 if (!vtx) return false;
761 bool fromHad = false;
762 auto incoming = vtx->particles_in();
763 for (auto parent: incoming) {
764 if (!parent) continue;
765 // should this really go into parton-level territory?
766 // probably depends where BSM particles are being decayed
767 fromBSM |= isBSM(parent);
768 if (!isPhysical(parent)) return false;
769 fromTau |= isTau(parent);
770 if (isHadron(parent)&&!isBeam(parent)) {
771 if (!hadron) hadron = parent; // assumes linear hadron parentage
772 return true;
773 }
774 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
775 }
776 return fromHad;
777 }
778
781
782 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
783 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
784 decltype(thePart->end_vertex()) pVert(nullptr);
785 if (EndVert != nullptr) {
786 do {
787 bool samePart = false;
788 pVert = nullptr;
789 auto outgoing = EndVert->particles_out();
790 auto incoming = EndVert->particles_in();
791 for (const auto& itrDaug: outgoing) {
792 if (!itrDaug) continue;
793 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
794 // brem on generator level for tau
795 (outgoing.size() == 1 && incoming.size() == 1 &&
797 itrDaug->pdg_id() == thePart->pdg_id()) {
798 samePart = true;
799 pVert = itrDaug->end_vertex();
800 }
801 }
802 if (samePart) EndVert = pVert;
803 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
804 }
805 return EndVert;
806 }
807
809
810 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
811 if (!theVert) return {};
812 decltype(theVert->particles_out()) finalStatePart;
813 auto outgoing = theVert->particles_out();
814 for (const auto& thePart: outgoing) {
815 if (!thePart) continue;
816 finalStatePart.push_back(thePart);
817 if (isStable(thePart)) continue;
818 V pVert = findSimulatedEndVertex(thePart);
819 if (pVert == theVert) break; // to prevent Sherpa loop
820 if (pVert != nullptr) {
821 auto vecPart = findFinalStateParticles<V>(pVert);
822 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
823 }
824 }
825 return finalStatePart;
826 }
827
828}
829#endif

◆ isRHadron() [1/3]

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

Definition at line 605 of file HepMCHelpers.h.

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

◆ isRHadron() [2/3]

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

Definition at line 608 of file HepMCHelpers.h.

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

◆ isRHadron() [3/3]

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

Definition at line 604 of file HepMCHelpers.h.

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

◆ isRMeson() [1/3]

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

Definition at line 576 of file HepMCHelpers.h.

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

◆ isRMeson() [2/3]

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

Definition at line 586 of file HepMCHelpers.h.

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

◆ isRMeson() [3/3]

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

Definition at line 575 of file HepMCHelpers.h.

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

◆ isSimInteracting()

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

Identify if the particle could interact with the detector during the simulation, e.g. not a neutrino or WIMP.

Definition at line 60 of file HepMCHelpers.h.

60{ return isGenStable<T>(p) && isInteracting<T>(p);}

◆ isSimStable()

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

Identify if the particle is considered stable at the post-detector-sim stage.

Definition at line 57 of file HepMCHelpers.h.

57{ return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}

◆ isSlepton() [1/3]

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

Definition at line 484 of file HepMCHelpers.h.

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

◆ isSlepton() [2/3]

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

Definition at line 485 of file HepMCHelpers.h.

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

◆ isSlepton() [3/3]

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

Definition at line 483 of file HepMCHelpers.h.

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

◆ isSleptonLH() [1/3]

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

Definition at line 490 of file HepMCHelpers.h.

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

◆ isSleptonLH() [2/3]

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

Definition at line 493 of file HepMCHelpers.h.

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

◆ isSleptonLH() [3/3]

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

Definition at line 489 of file HepMCHelpers.h.

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

◆ isSleptonRH() [1/3]

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

Definition at line 498 of file HepMCHelpers.h.

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

◆ isSleptonRH() [2/3]

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

Definition at line 501 of file HepMCHelpers.h.

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

◆ isSleptonRH() [3/3]

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

Definition at line 497 of file HepMCHelpers.h.

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

◆ isSMLepton() [1/3]

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

Definition at line 197 of file HepMCHelpers.h.

◆ isSMLepton() [2/3]

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

Definition at line 196 of file HepMCHelpers.h.

◆ isSMLepton() [3/3]

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

APID: the fourth generation leptons are not standard model leptons.

Definition at line 195 of file HepMCHelpers.h.

195{

◆ isSMNeutrino() [1/2]

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

Definition at line 217 of file HepMCHelpers.h.

◆ isSMNeutrino() [2/2]

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

Definition at line 216 of file HepMCHelpers.h.

◆ isSMQuark() [1/3]

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

Definition at line 175 of file HepMCHelpers.h.

175{

◆ isSMQuark() [2/3]

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

Definition at line 174 of file HepMCHelpers.h.

◆ isSMQuark() [3/3]

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

Definition at line 173 of file HepMCHelpers.h.

◆ isSpecialNonInteracting()

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

Identify a special non-interacting particles.

Definition at line 74 of file HepMCHelpers.h.

74 {
75 const int apid = std::abs(p->pdg_id());
76 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
77 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
78 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
79 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
80 return false;
81 }

◆ isSquark() [1/3]

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

Definition at line 460 of file HepMCHelpers.h.

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

◆ isSquark() [2/3]

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

Definition at line 463 of file HepMCHelpers.h.

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

◆ isSquark() [3/3]

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

PDG rule 11d Fundamental supersymmetric particles are identified by adding a nonzero n to the particle number.

The superpartner of a boson or a left-handed fermion has n = 1 while the superpartner of a right-handed fermion has n = 2. When mixing occurs, such as between the winos and charged Higgsinos to give charginos, or between left and right sfermions, the lighter physical state is given the smaller basis state number.

Definition at line 459 of file HepMCHelpers.h.

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

◆ isSquarkLH() [1/3]

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

Definition at line 468 of file HepMCHelpers.h.

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

◆ isSquarkLH() [2/3]

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

Definition at line 471 of file HepMCHelpers.h.

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

◆ isSquarkLH() [3/3]

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

Definition at line 467 of file HepMCHelpers.h.

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

◆ isSquarkRH() [1/3]

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

Definition at line 476 of file HepMCHelpers.h.

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

◆ isSquarkRH() [2/3]

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

Definition at line 479 of file HepMCHelpers.h.

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

◆ isSquarkRH() [3/3]

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

Definition at line 475 of file HepMCHelpers.h.

493{
494 namespace Pythia8
495 {
497 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
498
499 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
500
501 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
502 }
503
504#include "AtlasPID.h"
505
507 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
508
510 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
511
513 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
514
516 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
517
519 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
520
522 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
523
525 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
526
528 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
529
531 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
532
534 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
535
539 template <class T> inline bool isStableOrSimDecayed(const T& p) {
540 const auto vertex = p->end_vertex();
541 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
542 }
543
545 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
546
548 template <class T> inline bool isSpecialNonInteracting(const T& p) {
549 const int apid = std::abs(p->pdg_id());
550 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
551 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
552 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
553 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
554 return false;
555 }
556
558
559 template <class T> T findMother(T thePart) {
560 auto partOriVert = thePart->production_vertex();
561 if (!partOriVert) return nullptr;
562
563 long partPDG = thePart->pdg_id();
564 long MotherPDG(0);
565
566 auto MothOriVert = partOriVert;
567 MothOriVert = nullptr;
568 T theMoth(nullptr);
569
570 size_t itr = 0;
571 do {
572 if (itr != 0) partOriVert = MothOriVert;
573 auto incoming = partOriVert->particles_in();
574 for ( auto p: incoming) {
575 theMoth = p;
576 if (!theMoth) continue;
577 MotherPDG = theMoth->pdg_id();
578 MothOriVert = theMoth->production_vertex();
579 if (MotherPDG == partPDG) break;
580 }
581 itr++;
582 if (itr > 100) {
583 break;
584 }
585 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
586 MothOriVert != partOriVert);
587 return theMoth;
588 }
589
591
592 template <class C, class T> T findMatching(C TruthContainer, T p) {
593 T ptrPart = nullptr;
594 if (!p) return ptrPart;
595 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
596 for (T truthParticle : *TruthContainer) {
597 if (HepMC::is_sim_descendant(p,truthParticle)) {
598 ptrPart = truthParticle;
599 break;
600 }
601 }
602 }
603 else {
604 for (T truthParticle : TruthContainer) {
605 if (HepMC::is_sim_descendant(p,truthParticle)) {
606 ptrPart = truthParticle;
607 break;
608 }
609 }
610 }
611 return ptrPart;
612 }
614
615 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
616 auto prodVtx = thePart->production_vertex();
617 if (!prodVtx) return;
618 for (auto theMother: prodVtx->particles_in()) {
619 if (!theMother) continue;
620 allancestors.insert(theMother);
621 findParticleAncestors(theMother, allancestors);
622 }
623 }
624
626
627 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
628 auto endVtx = thePart->end_vertex();
629 if (!endVtx) return;
630 for (auto theDaughter: endVtx->particles_out()) {
631 if (!theDaughter) continue;
632 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
633 allstabledescendants.insert(theDaughter);
634 }
635 findParticleStableDescendants(theDaughter, allstabledescendants);
636 }
637 }
638
642
643 template <class T> bool isHardScatteringVertex(T pVert) {
644 if (pVert == nullptr) return false;
645 T pV = pVert;
646 int numOfPartIn(0);
647 int pdg(0);
648
649 do {
650 pVert = pV;
651 auto incoming = pVert->particles_in();
652 numOfPartIn = incoming.size();
653 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
654 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
655
656 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
657
658 if (numOfPartIn == 2) {
659 auto incoming = pVert->particles_in();
660 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;
661 }
662 return false;
663}
664
668
669 template <class T> bool isFromHadron(T p, T hadron, bool &fromTau, bool &fromBSM) {
670 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
671 auto vtx = p->production_vertex();
672 if (!vtx) return false;
673 bool fromHad = false;
674 auto incoming = vtx->particles_in();
675 for (auto parent: incoming) {
676 if (!parent) continue;
677 // should this really go into parton-level territory?
678 // probably depends where BSM particles are being decayed
679 fromBSM |= isBSM(parent);
680 if (!isPhysical(parent)) return false;
681 fromTau |= isTau(parent);
682 if (isHadron(parent)&&!isBeam(parent)) {
683 if (!hadron) hadron = parent; // assumes linear hadron parentage
684 return true;
685 }
686 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
687 }
688 return fromHad;
689 }
690
693
694 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
695 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
696 decltype(thePart->end_vertex()) pVert(nullptr);
697 if (EndVert != nullptr) {
698 do {
699 bool samePart = false;
700 pVert = nullptr;
701 auto outgoing = EndVert->particles_out();
702 auto incoming = EndVert->particles_in();
703 for (const auto& itrDaug: outgoing) {
704 if (!itrDaug) continue;
705 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
706 // brem on generator level for tau
707 (outgoing.size() == 1 && incoming.size() == 1 &&
709 itrDaug->pdg_id() == thePart->pdg_id()) {
710 samePart = true;
711 pVert = itrDaug->end_vertex();
712 }
713 }
714 if (samePart) EndVert = pVert;
715 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
716 }
717 return EndVert;
718 }
719
721
722 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
723 if (!theVert) return {};
724 decltype(theVert->particles_out()) finalStatePart;
725 auto outgoing = theVert->particles_out();
726 for (const auto& thePart: outgoing) {
727 if (!thePart) continue;
728 finalStatePart.push_back(thePart);
729 if (isStable(thePart)) continue;
730 V pVert = findSimulatedEndVertex(thePart);
731 if (pVert == theVert) break; // to prevent Sherpa loop
732 if (pVert != nullptr) {
733 auto vecPart = findFinalStateParticles<V>(pVert);
734 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
735 }
736 }
737 return finalStatePart;
738 }
739
740}
741#endif

◆ isStable()

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

Identify if the particle is stable, i.e. has not decayed.

Definition at line 45 of file HepMCHelpers.h.

◆ isStableOrSimDecayed()

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

Identify if particle is satble or decayed in simulation.

  • a pathological case of decayed particle w/o end vertex. The decayed particles w/o end vertex might occur in case of simulation of long lived particles in Geant stripped off the decay products. I.e. those particles should be re-decayed later.

Definition at line 65 of file HepMCHelpers.h.

65 {
66 const auto vertex = p->end_vertex();
67 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
68 }

◆ isStrange() [1/2]

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

Definition at line 178 of file HepMCHelpers.h.

◆ isStrange() [2/2]

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

Definition at line 177 of file HepMCHelpers.h.

◆ isStrangeBaryon()

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

Definition at line 934 of file HepMCHelpers.h.

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

◆ isStrangeHadron()

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

Definition at line 911 of file HepMCHelpers.h.

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

◆ isStrangeMeson()

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

Definition at line 918 of file HepMCHelpers.h.

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

◆ isStrongInteracting() [1/2]

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

Definition at line 1180 of file HepMCHelpers.h.

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

◆ isStrongInteracting() [2/2]

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

Definition at line 1179 of file HepMCHelpers.h.

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

◆ isSuperpartner() [1/3]

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

Definition at line 514 of file HepMCHelpers.h.

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

◆ isSuperpartner() [2/3]

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

Definition at line 517 of file HepMCHelpers.h.

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

◆ isSuperpartner() [3/3]

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

Definition at line 513 of file HepMCHelpers.h.

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

◆ isSUSY() [1/3]

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

Definition at line 625 of file HepMCHelpers.h.

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

◆ isSUSY() [2/3]

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

Definition at line 626 of file HepMCHelpers.h.

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

◆ isSUSY() [3/3]

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

Definition at line 624 of file HepMCHelpers.h.

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

◆ isTau() [1/2]

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

Definition at line 210 of file HepMCHelpers.h.

◆ isTau() [2/2]

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

Definition at line 209 of file HepMCHelpers.h.

◆ isTechnicolor() [1/3]

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

Definition at line 527 of file HepMCHelpers.h.

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

◆ isTechnicolor() [2/3]

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

Definition at line 533 of file HepMCHelpers.h.

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

◆ isTechnicolor() [3/3]

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

PDG rule 11e Technicolor states have n = 3, with technifermions treated like ordinary fermions.

States which are ordinary color singlets have n_r = 0. Color octets have n_r = 1. If a state has non-trivial quantum numbers under the topcolor groups SU(3)1×SU(3)2, the quantum numbers are specified by tech, ij, where i and j are 1 or 2. nLis then 2i+j. The coloron V8, is a heavy gluon color octet and thus is 3100021

Definition at line 525 of file HepMCHelpers.h.

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

◆ isTetraquark() [1/3]

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

Definition at line 327 of file HepMCHelpers.h.

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

◆ isTetraquark() [2/3]

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

Definition at line 334 of file HepMCHelpers.h.

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

◆ isTetraquark() [3/3]

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

PDG rule 14 The 9-digit tetra-quark codes are ±1nrnLnq1nq20nq3nq4nJ.

For the particle q1q2 is a diquark and ̄q3 ̄q4 an antidiquark, sorted such that nq1≥nq2, nq3≥nq4, nq1≥nq3, and nq2≥nq4 if nq1=nq3. For the antiparticle, given with a negative sign, ̄q1 ̄q2 is an antidiquark and q3q4 a diquark, with the same sorting except that either nq1>nq3 or nq2>nq4 (so that flavour-diagonal states are particles). The nr, nL, and nJ numbers have the same meaning as for ordinary hadrons. APID: states with fourth generation quarks are not tetraquarks

Definition at line 326 of file HepMCHelpers.h.

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

◆ isTop() [1/2]

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

Definition at line 187 of file HepMCHelpers.h.

◆ isTop() [2/2]

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

Definition at line 186 of file HepMCHelpers.h.

◆ isTopBaryon()

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

Definition at line 937 of file HepMCHelpers.h.

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

◆ isTopHadron()

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

Definition at line 914 of file HepMCHelpers.h.

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

◆ isTopMeson()

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

Definition at line 921 of file HepMCHelpers.h.

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

◆ isTrajectory() [1/2]

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

Definition at line 361 of file HepMCHelpers.h.

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

◆ isTrajectory() [2/2]

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

PDG rule 8: The pomeron and odderon trajectories and a generic reggeon trajectory of states in QCD areassigned codes 990, 9990, and 110 respectively.

Definition at line 360 of file HepMCHelpers.h.

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

◆ isTransportable() [1/3]

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

Definition at line 875 of file HepMCHelpers.h.

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

◆ isTransportable() [2/3]

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

Definition at line 876 of file HepMCHelpers.h.

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

◆ isTransportable() [3/3]

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

Definition at line 874 of file HepMCHelpers.h.

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

◆ isValid() [1/3]

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

Definition at line 880 of file HepMCHelpers.h.

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

◆ isValid() [2/3]

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

Definition at line 885 of file HepMCHelpers.h.

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

◆ isValid() [3/3]

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

Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.

Definition at line 879 of file HepMCHelpers.h.

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

◆ isW() [1/2]

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

Definition at line 384 of file HepMCHelpers.h.

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

◆ isW() [2/2]

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

Definition at line 383 of file HepMCHelpers.h.

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

◆ isWeaklyDecayingBHadron() [1/3]

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

Definition at line 969 of file HepMCHelpers.h.

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

◆ isWeaklyDecayingBHadron() [2/3]

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

Definition at line 944 of file HepMCHelpers.h.

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

◆ isWeaklyDecayingBHadron() [3/3]

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

Definition at line 943 of file HepMCHelpers.h.

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

◆ isWeaklyDecayingCHadron() [1/3]

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

Definition at line 993 of file HepMCHelpers.h.

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

◆ isWeaklyDecayingCHadron() [2/3]

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

Definition at line 979 of file HepMCHelpers.h.

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

◆ isWeaklyDecayingCHadron() [3/3]

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

Definition at line 978 of file HepMCHelpers.h.

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

◆ isZ() [1/2]

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

Definition at line 381 of file HepMCHelpers.h.

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

◆ isZ() [2/2]

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

Definition at line 380 of file HepMCHelpers.h.

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

◆ isZeroEnergyPhoton()

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

Identify a photon with zero energy. Probably a workaround for a generator bug.

Definition at line 71 of file HepMCHelpers.h.

71{ return isPhoton<T>(p) && p->e() == 0;}

◆ leadingQuark() [1/3]

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

Definition at line 891 of file HepMCHelpers.h.

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

◆ leadingQuark() [2/3]

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

Definition at line 907 of file HepMCHelpers.h.

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

◆ leadingQuark() [3/3]

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

Definition at line 890 of file HepMCHelpers.h.

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

◆ numberOfLambdas() [1/3]

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

Definition at line 826 of file HepMCHelpers.h.

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

◆ numberOfLambdas() [2/3]

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

Definition at line 831 of file HepMCHelpers.h.

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

◆ numberOfLambdas() [3/3]

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

Definition at line 825 of file HepMCHelpers.h.

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

◆ numberOfProtons() [1/3]

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

Definition at line 835 of file HepMCHelpers.h.

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

◆ numberOfProtons() [2/3]

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

Definition at line 843 of file HepMCHelpers.h.

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

◆ numberOfProtons() [3/3]

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

Definition at line 834 of file HepMCHelpers.h.

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

◆ spin() [1/3]

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

Definition at line 1149 of file HepMCHelpers.h.

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

◆ spin() [2/3]

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

Definition at line 1150 of file HepMCHelpers.h.

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

◆ spin() [3/3]

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

Definition at line 1148 of file HepMCHelpers.h.

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

◆ spin2() [1/3]

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

Definition at line 1109 of file HepMCHelpers.h.

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

◆ spin2() [2/3]

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

Definition at line 1146 of file HepMCHelpers.h.

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

◆ spin2() [3/3]

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

Definition at line 1108 of file HepMCHelpers.h.

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

◆ strangeness() [1/3]

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

Definition at line 788 of file HepMCHelpers.h.

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

◆ strangeness() [2/3]

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

Definition at line 822 of file HepMCHelpers.h.

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

◆ strangeness() [3/3]

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

Definition at line 787 of file HepMCHelpers.h.

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

◆ threeCharge()

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

Definition at line 1004 of file HepMCHelpers.h.

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

Variable Documentation

◆ B0

const int MC::B0 = 511
static

Definition at line 123 of file HepMCHelpers.h.

◆ BCPLUS

const int MC::BCPLUS = 541
static

Definition at line 124 of file HepMCHelpers.h.

◆ BPRIME

const int MC::BPRIME = 7
static

Definition at line 71 of file HepMCHelpers.h.

◆ BQUARK

const int MC::BQUARK = 5
static

Definition at line 69 of file HepMCHelpers.h.

◆ COMPOSITEGLUON

const int MC::COMPOSITEGLUON = 9
static

Definition at line 87 of file HepMCHelpers.h.

◆ CQUARK

const int MC::CQUARK = 4
static

Definition at line 68 of file HepMCHelpers.h.

◆ D0

const int MC::D0 = 421
static

Definition at line 120 of file HepMCHelpers.h.

◆ DARKPHOTON

const int MC::DARKPHOTON = 60000
static

PDG Ids for Mavtop madgraph UFO model found under DarkX.

The mavtop is a vector-like top partner with coupling to a dark photon. Theory paper: https://arxiv.org/abs/1904.05893 Pheno paper: https://arxiv.org/pdf/2112.08425

Definition at line 107 of file HepMCHelpers.h.

◆ double_spin

const std::array<int,TABLESIZE> MC::double_spin
static
Initial value:
= {
+0, +1, +1, +1, +1, +1, +1, +1, +1, +0,
+0, +1, +1, +1, +1, +1, +1, +1, +1, +0,
+2, +2, +2, +2, +2, +0, +0, +0, +0, +0,
+0, +0, +2, +2, +2, +0, +0, +0, +0, +4,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +1, +2, +0, +2, +0, +1, +2, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0
}

Definition at line 51 of file HepMCHelpers.h.

51 { return isStable<T>(p) || isDecayed<T>(p); }
52
54 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
55
57 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
58
60 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
61

◆ DPLUS

const int MC::DPLUS = 411
static

Definition at line 118 of file HepMCHelpers.h.

◆ DQUARK

const int MC::DQUARK = 1
static

Definition at line 65 of file HepMCHelpers.h.

◆ DSPLUS

const int MC::DSPLUS = 431
static

Definition at line 121 of file HepMCHelpers.h.

◆ DSTAR

const int MC::DSTAR = 413
static

Definition at line 119 of file HepMCHelpers.h.

◆ ELECTRON

const int MC::ELECTRON = 11
static

Definition at line 75 of file HepMCHelpers.h.

◆ GEANTINO0

const int MC::GEANTINO0 = 999
static

Definition at line 160 of file HepMCHelpers.h.

◆ GEANTINOPLUS

const int MC::GEANTINOPLUS = 998
static

PDG rule 10: Codes 81–100 are reserved for generator-specific pseudoparticles and concepts.

Codes 901–930, 1901–1930, 2901–2930, and 3901–3930 are for additional components of Standard Modelparton distribution functions, where the latter three ranges are intended to distinguish left/right/ longitudinal components. Codes 998 and 999 are reserved for GEANT tracking purposes.

Definition at line 159 of file HepMCHelpers.h.

◆ GLUON

const int MC::GLUON = 21
static

Definition at line 85 of file HepMCHelpers.h.

◆ GRAVITON

const int MC::GRAVITON = 39
static

Definition at line 99 of file HepMCHelpers.h.

◆ HELIUM

const int MC::HELIUM = 1000020040
static

Definition at line 145 of file HepMCHelpers.h.

◆ HIGGS2

const int MC::HIGGS2 = 35
static

Definition at line 95 of file HepMCHelpers.h.

◆ HIGGS3

const int MC::HIGGS3 = 36
static

Definition at line 96 of file HepMCHelpers.h.

◆ HIGGS4

const int MC::HIGGS4 = 40
static

Definition at line 100 of file HepMCHelpers.h.

◆ HIGGSBOSON

const int MC::HIGGSBOSON = 25
static

Definition at line 91 of file HepMCHelpers.h.

◆ HIGGSPLUS

const int MC::HIGGSPLUS = 37
static

Definition at line 97 of file HepMCHelpers.h.

◆ HIGGSPLUSPLUS

const int MC::HIGGSPLUSPLUS = 38
static

Definition at line 98 of file HepMCHelpers.h.

◆ is_strange

const std::array<int,10> MC::is_strange
static
Initial value:
= {
+0, +0, +0, -1, +0, +0, +0, +0, +0, +0 }

Definition at line 785 of file HepMCHelpers.h.

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

◆ JPSI

const int MC::JPSI = 443
static

Definition at line 122 of file HepMCHelpers.h.

◆ K0

const int MC::K0 = 311
static

Definition at line 116 of file HepMCHelpers.h.

◆ K0L

const int MC::K0L = 130
static

Definition at line 113 of file HepMCHelpers.h.

◆ K0S

const int MC::K0S = 310
static

Definition at line 115 of file HepMCHelpers.h.

◆ KPLUS

const int MC::KPLUS = 321
static

Definition at line 117 of file HepMCHelpers.h.

◆ LAMBDA0

const int MC::LAMBDA0 = 3122
static

Definition at line 127 of file HepMCHelpers.h.

◆ LAMBDAB0

const int MC::LAMBDAB0 = 5122
static

Definition at line 129 of file HepMCHelpers.h.

◆ LAMBDACPLUS

const int MC::LAMBDACPLUS = 4122
static

Definition at line 128 of file HepMCHelpers.h.

◆ LEAD

const int MC::LEAD = 1000822080
static

Definition at line 142 of file HepMCHelpers.h.

◆ LEPTOQUARK

const int MC::LEPTOQUARK = 42
static

Definition at line 101 of file HepMCHelpers.h.

◆ LPRIME

const int MC::LPRIME = 17
static

Definition at line 82 of file HepMCHelpers.h.

◆ MAVTOP

const int MC::MAVTOP = 60001
static

Definition at line 108 of file HepMCHelpers.h.

◆ MUON

const int MC::MUON = 13
static

Definition at line 78 of file HepMCHelpers.h.

◆ NEON

const int MC::NEON = 1000100200
static

Definition at line 144 of file HepMCHelpers.h.

◆ NEUTRON

const int MC::NEUTRON = 2112
static

Definition at line 126 of file HepMCHelpers.h.

◆ NU_E

const int MC::NU_E = 12
static

Definition at line 77 of file HepMCHelpers.h.

◆ NU_MU

const int MC::NU_MU = 14
static

Definition at line 79 of file HepMCHelpers.h.

◆ NU_TAU

const int MC::NU_TAU = 16
static

Definition at line 81 of file HepMCHelpers.h.

◆ NUPRIME

const int MC::NUPRIME = 18
static

Definition at line 83 of file HepMCHelpers.h.

◆ ODDERON

const int MC::ODDERON = 9990
static

Definition at line 151 of file HepMCHelpers.h.

◆ OXYGEN

const int MC::OXYGEN = 1000080160
static

Definition at line 143 of file HepMCHelpers.h.

◆ PHOTON

const int MC::PHOTON = 22
static

Definition at line 88 of file HepMCHelpers.h.

◆ PI0

const int MC::PI0 = 111
static

Definition at line 112 of file HepMCHelpers.h.

◆ PIMINUS

const int MC::PIMINUS = -PIPLUS
static

Definition at line 111 of file HepMCHelpers.h.

◆ PIPLUS

const int MC::PIPLUS = 211
static

Definition at line 110 of file HepMCHelpers.h.

◆ POMERON

const int MC::POMERON = 990
static

PDG rule 8: The pomeron and odderon trajectories and a generic reggeon trajectory of states in QCD areassigned codes 990, 9990, and 110 respectively.

Definition at line 150 of file HepMCHelpers.h.

◆ POSITRON

const int MC::POSITRON = -ELECTRON
static

Definition at line 76 of file HepMCHelpers.h.

◆ PROTON

const int MC::PROTON = 2212
static

Definition at line 125 of file HepMCHelpers.h.

◆ PSI2S

const int MC::PSI2S = 20443
static

Definition at line 130 of file HepMCHelpers.h.

◆ QUARK_LIMIT

const int MC::QUARK_LIMIT = BPRIME
static

Definition at line 73 of file HepMCHelpers.h.

◆ REGGEON

const int MC::REGGEON = 110
static

Definition at line 152 of file HepMCHelpers.h.

◆ RH_NU_E

const int MC::RH_NU_E = 9900012
static

PDG Rule 12: Generator defined PDG ID values for right handed neutrinos and corresponding W+ boson from a Left-Right symmetric Standard Model extension.

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

Definition at line 137 of file HepMCHelpers.h.

◆ RH_NU_MU

const int MC::RH_NU_MU = 9900014
static

Definition at line 138 of file HepMCHelpers.h.

◆ RH_NU_TAU

const int MC::RH_NU_TAU = 9900016
static

Definition at line 139 of file HepMCHelpers.h.

◆ SQUARK

const int MC::SQUARK = 3
static

Definition at line 67 of file HepMCHelpers.h.

◆ TABLESIZE

const int MC::TABLESIZE = 100
static

Definition at line 35 of file HepMCHelpers.h.

◆ TAU

const int MC::TAU = 15
static

Definition at line 80 of file HepMCHelpers.h.

◆ TPRIME

const int MC::TPRIME = 8
static

Definition at line 72 of file HepMCHelpers.h.

◆ TQUARK

const int MC::TQUARK = 6
static

Definition at line 70 of file HepMCHelpers.h.

◆ triple_charge

const std::array<int,TABLESIZE> MC::triple_charge
static
Initial value:
= {
+0, -1, +2, -1, +2, -1, +2, -1, +2, +0,
+0, -3, +0, -3, +0, -3, +0, -3, +0, +0,
+0, +0, +0, +0, +3, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +3, +0, +0, +3, +6, +0,
+0, +0, -1, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0
}

Definition at line 36 of file HepMCHelpers.h.

36 { return (isMuon<T>(p) || isSUSY<T>(p)); }
37
39 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
40
42 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
43
45 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
46

◆ UQUARK

const int MC::UQUARK = 2
static

Definition at line 66 of file HepMCHelpers.h.

◆ WBOSON_LRSM

const int MC::WBOSON_LRSM = 9900024
static

Definition at line 140 of file HepMCHelpers.h.

◆ WPLUSBOSON

const int MC::WPLUSBOSON = 24
static

Definition at line 90 of file HepMCHelpers.h.

◆ WPLUSPRIME

const int MC::WPLUSPRIME = 34
static

Definition at line 94 of file HepMCHelpers.h.

◆ Z0BOSON

const int MC::Z0BOSON = 23
static

Definition at line 89 of file HepMCHelpers.h.

◆ ZDBLPRIME

const int MC::ZDBLPRIME = 33
static

Definition at line 93 of file HepMCHelpers.h.

◆ ZPRIME

const int MC::ZPRIME = 32
static

Definition at line 92 of file HepMCHelpers.h.