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

Namespaces

namespace  HepMC
namespace  HepMC3
namespace  HepMCStr
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>
T findMother (T thePart)
 Function to get a mother of particle. MCTruthClassifier legacy.
template<class C, class T>
T findMatching (C TruthContainer, T p)
 Function to find a particle in container.
template<class T>
void findParticleAncestors (T thePart, std::set< T > &allancestors)
 Function to find all ancestors of the particle.
template<class T>
void findParticleStableDescendants (T thePart, std::set< T > &allstabledescendants)
 Function to get the particle stable MC daughters.
template<class T>
bool isHardScatteringVertex (T pVert)
 Function to classify the vertex as hard scattering vertex.
template<class T, class U>
bool isFromHadron (T p, U hadron, bool &fromTau, bool &fromBSM)
 Function to classify the particle.
template<class T>
auto findSimulatedEndVertex (T thePart) -> decltype(thePart->end_vertex())
 Function to find the end vertex of a particle.
template<class V>
auto findFinalStateParticles (V theVert) -> decltype(theVert->particles_out())
 Function to find the stable particle descendants of the given vertex..
void GeVToMeV (HepMC::GenEvent *evt)
void MeVToGeV (HepMC::GenEvent *evt)

Variables

static const int TABLESIZE = 100
static const std::array< int, TABLESIZE > triple_charge
static const std::array< int, TABLESIZE > double_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 INDIUM = 1000491150
static const int KRYPTON = 1000360840
static const int CALCIUM = 1000200400
static const int ARGON = 1000180400
static const int MAGNESIUM = 1000120240
static const int NEON = 1000100200
static const int OXYGEN = 1000080160
static const int BORON = 1000050110
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 781 of file HepMCHelpers.h.

◆ baryonNumber() [2/3]

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

Definition at line 782 of file HepMCHelpers.h.

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

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

◆ baryonNumber3() [1/3]

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

Definition at line 756 of file HepMCHelpers.h.

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

◆ baryonNumber3() [2/3]

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

Definition at line 778 of file HepMCHelpers.h.

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

◆ baryonNumber3() [3/3]

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

Definition at line 755 of file HepMCHelpers.h.

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

◆ charge()

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

Definition at line 1004 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1199 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1200 auto vtx = p->production_vertex();
1201 if (!vtx) return false;
1202 bool fromHad = false;
1203 for ( const auto& parent : vtx->particles_in() ) {
1204 if (!parent) continue;
1205 // should this really go into parton-level territory?
1206 // probably depends where BSM particles are being decayed
1207 fromBSM |= isBSM(parent);
1208 if (!isPhysical(parent)) return false;
1209 fromTau |= isTau(parent);
1210 if (isHadron(parent)&&!isBeam(parent)) {
1211 if (!hadron) hadron = parent; // assumes linear hadron parentage
1212 return true;
1213 }
1214 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1215 }
1216 return fromHad;
1217 }
1218
1221
1222 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1223 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1224 decltype(thePart->end_vertex()) pVert(nullptr);
1225 if (EndVert != nullptr) {
1226 do {
1227 bool samePart = false;
1228 pVert = nullptr;
1229 auto outgoing = EndVert->particles_out();
1230 auto incoming = EndVert->particles_in();
1231 for (const auto& itrDaug: outgoing) {
1232 if (!itrDaug) continue;
1233 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1234 // brem on generator level for tau
1235 (outgoing.size() == 1 && incoming.size() == 1 &&
1237 itrDaug->pdg_id() == thePart->pdg_id()) {
1238 samePart = true;
1239 pVert = itrDaug->end_vertex();
1240 }
1241 }
1242 if (samePart) EndVert = pVert;
1243 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1244 }
1245 return EndVert;
1246 }
1247
1249
1250 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1251 if (!theVert) return {};
1252 decltype(theVert->particles_out()) finalStatePart;
1253 auto outgoing = theVert->particles_out();
1254 for (const auto& thePart: outgoing) {
1255 if (!thePart) continue;
1256 finalStatePart.push_back(thePart);
1257 if (isStable(thePart)) continue;
1258 V pVert = findSimulatedEndVertex(thePart);
1259 if (pVert == theVert) break; // to prevent Sherpa loop
1260 if (pVert != nullptr) {
1261 auto vecPart = findFinalStateParticles<V>(pVert);
1262 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1263 }
1264 }
1265 return finalStatePart;
1266 }
1267#if !defined(XAOD_ANALYSIS)
1268#include "AtlasHepMC/GenEvent.h"
1269inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1270inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1271
1272#endif
1273}
1274#endif

◆ charge3() [1/3]

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

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

Definition at line 1014 of file HepMCHelpers.h.

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

◆ charge3() [2/3]

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

Definition at line 1088 of file HepMCHelpers.h.

1107{
1108 namespace Pythia8
1109 {
1111 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1112
1113 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1114
1115 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1116 }
1117
1118#include "AtlasPID.h"
1119
1121 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1122
1124 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1125
1127 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1128
1130 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1131
1133 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1134
1136 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1137
1139 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1140
1142 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1143
1145 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1146
1148 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1149
1153 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1154 const auto vertex = p->end_vertex();
1155 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1156 }
1157
1159 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1160
1162 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1163 const int apid = std::abs(p->pdg_id());
1164 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1165 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1166 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1167 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1168 return false;
1169 }
1170
1172
1173 template <class T> T findMother(T thePart) {
1174 auto partOriVert = thePart->production_vertex();
1175 if (!partOriVert) return nullptr;
1176
1177 long partPDG = thePart->pdg_id();
1178 long MotherPDG(0);
1179
1180 auto MothOriVert = partOriVert;
1181 MothOriVert = nullptr;
1182 T theMoth(nullptr);
1183
1184 size_t itr = 0;
1185 do {
1186 if (itr != 0) partOriVert = MothOriVert;
1187 for ( const auto& p : partOriVert->particles_in() ) {
1188 theMoth = p;
1189 if (!theMoth) continue;
1190 MotherPDG = theMoth->pdg_id();
1191 MothOriVert = theMoth->production_vertex();
1192 if (MotherPDG == partPDG) break;
1193 }
1194 itr++;
1195 if (itr > 100) {
1196 break;
1197 }
1198 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1199 MothOriVert != partOriVert);
1200 return theMoth;
1201 }
1202
1204
1205 template <class C, class T> T findMatching(C TruthContainer, T p) {
1206 T ptrPart = nullptr;
1207 if (!p) return ptrPart;
1208 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1209 for (T truthParticle : *TruthContainer) {
1210 if (HepMC::is_sim_descendant(p,truthParticle)) {
1211 ptrPart = truthParticle;
1212 break;
1213 }
1214 }
1215 }
1216 else {
1217 for (T truthParticle : TruthContainer) {
1218 if (HepMC::is_sim_descendant(p,truthParticle)) {
1219 ptrPart = truthParticle;
1220 break;
1221 }
1222 }
1223 }
1224 return ptrPart;
1225 }
1227
1228 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1229 auto prodVtx = thePart->production_vertex();
1230 if (!prodVtx) return;
1231 for (const auto& theMother: prodVtx->particles_in()) {
1232 if (!theMother) continue;
1233 allancestors.insert(theMother);
1234 findParticleAncestors(theMother, allancestors);
1235 }
1236 }
1237
1239
1240 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1241 auto endVtx = thePart->end_vertex();
1242 if (!endVtx) return;
1243 for (const auto& theDaughter: endVtx->particles_out()) {
1244 if (!theDaughter) continue;
1245 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1246 allstabledescendants.insert(theDaughter);
1247 }
1248 findParticleStableDescendants(theDaughter, allstabledescendants);
1249 }
1250 }
1251
1255
1256 template <class T> bool isHardScatteringVertex(T pVert) {
1257 if (pVert == nullptr) return false;
1258 T pV = pVert;
1259 int numOfPartIn(0);
1260 int pdg(0);
1261
1262 do {
1263 pVert = pV;
1264 auto incoming = pVert->particles_in();
1265 numOfPartIn = incoming.size();
1266 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1267 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1268
1269 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1270
1271 if (numOfPartIn == 2) {
1272 auto incoming = pVert->particles_in();
1273 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1274 }
1275 return false;
1276}
1277
1281
1282 template <class T, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1352#include "AtlasHepMC/GenEvent.h"
1353inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1354inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1355
1356#endif
1357}
1358#endif

◆ charge3() [3/3]

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

Definition at line 1002 of file HepMCHelpers.h.

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

◆ containedQuarks() [1/3]

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

Definition at line 1187 of file HepMCHelpers.h.

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

◆ containedQuarks() [2/3]

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

Definition at line 1165 of file HepMCHelpers.h.

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

◆ containedQuarks() [3/3]

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

Definition at line 1164 of file HepMCHelpers.h.

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

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

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

86 {
87 auto partOriVert = thePart->production_vertex();
88 if (!partOriVert) return nullptr;
89
90 long partPDG = thePart->pdg_id();
91 long MotherPDG(0);
92
93 auto MothOriVert = partOriVert;
94 MothOriVert = nullptr;
95 T theMoth(nullptr);
96
97 size_t itr = 0;
98 do {
99 if (itr != 0) partOriVert = MothOriVert;
100 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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 219 of file HepMCHelpers.h.

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

◆ fractionalCharge() [1/3]

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

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

◆ fractionalCharge() [2/3]

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

Definition at line 1108 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 for ( const auto& p : partOriVert->particles_in() ) {
1208 theMoth = p;
1209 if (!theMoth) continue;
1210 MotherPDG = theMoth->pdg_id();
1211 MothOriVert = theMoth->production_vertex();
1212 if (MotherPDG == partPDG) break;
1213 }
1214 itr++;
1215 if (itr > 100) {
1216 break;
1217 }
1218 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1219 MothOriVert != partOriVert);
1220 return theMoth;
1221 }
1222
1224
1225 template <class C, class T> T findMatching(C TruthContainer, T p) {
1226 T ptrPart = nullptr;
1227 if (!p) return ptrPart;
1228 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1229 for (T truthParticle : *TruthContainer) {
1230 if (HepMC::is_sim_descendant(p,truthParticle)) {
1231 ptrPart = truthParticle;
1232 break;
1233 }
1234 }
1235 }
1236 else {
1237 for (T truthParticle : TruthContainer) {
1238 if (HepMC::is_sim_descendant(p,truthParticle)) {
1239 ptrPart = truthParticle;
1240 break;
1241 }
1242 }
1243 }
1244 return ptrPart;
1245 }
1247
1248 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1249 auto prodVtx = thePart->production_vertex();
1250 if (!prodVtx) return;
1251 for (const auto& theMother: prodVtx->particles_in()) {
1252 if (!theMother) continue;
1253 allancestors.insert(theMother);
1254 findParticleAncestors(theMother, allancestors);
1255 }
1256 }
1257
1259
1260 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1261 auto endVtx = thePart->end_vertex();
1262 if (!endVtx) return;
1263 for (const auto& theDaughter: endVtx->particles_out()) {
1264 if (!theDaughter) continue;
1265 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1266 allstabledescendants.insert(theDaughter);
1267 }
1268 findParticleStableDescendants(theDaughter, allstabledescendants);
1269 }
1270 }
1271
1275
1276 template <class T> bool isHardScatteringVertex(T pVert) {
1277 if (pVert == nullptr) return false;
1278 T pV = pVert;
1279 int numOfPartIn(0);
1280 int pdg(0);
1281
1282 do {
1283 pVert = pV;
1284 auto incoming = pVert->particles_in();
1285 numOfPartIn = incoming.size();
1286 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1287 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1288
1289 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1290
1291 if (numOfPartIn == 2) {
1292 auto incoming = pVert->particles_in();
1293 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1294 }
1295 return false;
1296}
1297
1301
1302 template <class T, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
1308 if (!parent) continue;
1309 // should this really go into parton-level territory?
1310 // probably depends where BSM particles are being decayed
1311 fromBSM |= isBSM(parent);
1312 if (!isPhysical(parent)) return false;
1313 fromTau |= isTau(parent);
1314 if (isHadron(parent)&&!isBeam(parent)) {
1315 if (!hadron) hadron = parent; // assumes linear hadron parentage
1316 return true;
1317 }
1318 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1319 }
1320 return fromHad;
1321 }
1322
1325
1326 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1327 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1328 decltype(thePart->end_vertex()) pVert(nullptr);
1329 if (EndVert != nullptr) {
1330 do {
1331 bool samePart = false;
1332 pVert = nullptr;
1333 auto outgoing = EndVert->particles_out();
1334 auto incoming = EndVert->particles_in();
1335 for (const auto& itrDaug: outgoing) {
1336 if (!itrDaug) continue;
1337 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1338 // brem on generator level for tau
1339 (outgoing.size() == 1 && incoming.size() == 1 &&
1341 itrDaug->pdg_id() == thePart->pdg_id()) {
1342 samePart = true;
1343 pVert = itrDaug->end_vertex();
1344 }
1345 }
1346 if (samePart) EndVert = pVert;
1347 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1348 }
1349 return EndVert;
1350 }
1351
1353
1354 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1355 if (!theVert) return {};
1356 decltype(theVert->particles_out()) finalStatePart;
1357 auto outgoing = theVert->particles_out();
1358 for (const auto& thePart: outgoing) {
1359 if (!thePart) continue;
1360 finalStatePart.push_back(thePart);
1361 if (isStable(thePart)) continue;
1362 V pVert = findSimulatedEndVertex(thePart);
1363 if (pVert == theVert) break; // to prevent Sherpa loop
1364 if (pVert != nullptr) {
1365 auto vecPart = findFinalStateParticles<V>(pVert);
1366 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1367 }
1368 }
1369 return finalStatePart;
1370 }
1371#if !defined(XAOD_ANALYSIS)
1372#include "AtlasHepMC/GenEvent.h"
1373inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1374inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1375
1376#endif
1377}
1378#endif

◆ fractionalCharge() [3/3]

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

Definition at line 1003 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 for ( const auto& p : partOriVert->particles_in() ) {
1103 theMoth = p;
1104 if (!theMoth) continue;
1105 MotherPDG = theMoth->pdg_id();
1106 MothOriVert = theMoth->production_vertex();
1107 if (MotherPDG == partPDG) break;
1108 }
1109 itr++;
1110 if (itr > 100) {
1111 break;
1112 }
1113 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1114 MothOriVert != partOriVert);
1115 return theMoth;
1116 }
1117
1119
1120 template <class C, class T> T findMatching(C TruthContainer, T p) {
1121 T ptrPart = nullptr;
1122 if (!p) return ptrPart;
1123 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1124 for (T truthParticle : *TruthContainer) {
1125 if (HepMC::is_sim_descendant(p,truthParticle)) {
1126 ptrPart = truthParticle;
1127 break;
1128 }
1129 }
1130 }
1131 else {
1132 for (T truthParticle : TruthContainer) {
1133 if (HepMC::is_sim_descendant(p,truthParticle)) {
1134 ptrPart = truthParticle;
1135 break;
1136 }
1137 }
1138 }
1139 return ptrPart;
1140 }
1142
1143 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1144 auto prodVtx = thePart->production_vertex();
1145 if (!prodVtx) return;
1146 for (const auto& theMother: prodVtx->particles_in()) {
1147 if (!theMother) continue;
1148 allancestors.insert(theMother);
1149 findParticleAncestors(theMother, allancestors);
1150 }
1151 }
1152
1154
1155 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1156 auto endVtx = thePart->end_vertex();
1157 if (!endVtx) return;
1158 for (const auto& theDaughter: endVtx->particles_out()) {
1159 if (!theDaughter) continue;
1160 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1161 allstabledescendants.insert(theDaughter);
1162 }
1163 findParticleStableDescendants(theDaughter, allstabledescendants);
1164 }
1165 }
1166
1170
1171 template <class T> bool isHardScatteringVertex(T pVert) {
1172 if (pVert == nullptr) return false;
1173 T pV = pVert;
1174 int numOfPartIn(0);
1175 int pdg(0);
1176
1177 do {
1178 pVert = pV;
1179 auto incoming = pVert->particles_in();
1180 numOfPartIn = incoming.size();
1181 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1182 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1183
1184 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1185
1186 if (numOfPartIn == 2) {
1187 auto incoming = pVert->particles_in();
1188 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1189 }
1190 return false;
1191}
1192
1196
1197 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1198 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1199 auto vtx = p->production_vertex();
1200 if (!vtx) return false;
1201 bool fromHad = false;
1202 for ( const auto& parent : vtx->particles_in() ) {
1203 if (!parent) continue;
1204 // should this really go into parton-level territory?
1205 // probably depends where BSM particles are being decayed
1206 fromBSM |= isBSM(parent);
1207 if (!isPhysical(parent)) return false;
1208 fromTau |= isTau(parent);
1209 if (isHadron(parent)&&!isBeam(parent)) {
1210 if (!hadron) hadron = parent; // assumes linear hadron parentage
1211 return true;
1212 }
1213 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1214 }
1215 return fromHad;
1216 }
1217
1220
1221 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1222 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1223 decltype(thePart->end_vertex()) pVert(nullptr);
1224 if (EndVert != nullptr) {
1225 do {
1226 bool samePart = false;
1227 pVert = nullptr;
1228 auto outgoing = EndVert->particles_out();
1229 auto incoming = EndVert->particles_in();
1230 for (const auto& itrDaug: outgoing) {
1231 if (!itrDaug) continue;
1232 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1233 // brem on generator level for tau
1234 (outgoing.size() == 1 && incoming.size() == 1 &&
1236 itrDaug->pdg_id() == thePart->pdg_id()) {
1237 samePart = true;
1238 pVert = itrDaug->end_vertex();
1239 }
1240 }
1241 if (samePart) EndVert = pVert;
1242 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1243 }
1244 return EndVert;
1245 }
1246
1248
1249 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1250 if (!theVert) return {};
1251 decltype(theVert->particles_out()) finalStatePart;
1252 auto outgoing = theVert->particles_out();
1253 for (const auto& thePart: outgoing) {
1254 if (!thePart) continue;
1255 finalStatePart.push_back(thePart);
1256 if (isStable(thePart)) continue;
1257 V pVert = findSimulatedEndVertex(thePart);
1258 if (pVert == theVert) break; // to prevent Sherpa loop
1259 if (pVert != nullptr) {
1260 auto vecPart = findFinalStateParticles<V>(pVert);
1261 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1262 }
1263 }
1264 return finalStatePart;
1265 }
1266#if !defined(XAOD_ANALYSIS)
1267#include "AtlasHepMC/GenEvent.h"
1268inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1269inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1270
1271#endif
1272}
1273#endif

◆ GeVToMeV()

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

Definition at line 266 of file HepMCHelpers.h.

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

◆ hasBottom()

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

Definition at line 745 of file HepMCHelpers.h.

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

◆ hasCharm()

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

Definition at line 744 of file HepMCHelpers.h.

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

◆ hasQuark() [1/3]

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

Definition at line 723 of file HepMCHelpers.h.

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

◆ hasQuark() [2/3]

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

Definition at line 741 of file HepMCHelpers.h.

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

◆ hasQuark() [3/3]

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

◆ hasSquark() [1/3]

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

Definition at line 618 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 for ( const auto& p : partOriVert->particles_in() ) {
718 theMoth = p;
719 if (!theMoth) continue;
720 MotherPDG = theMoth->pdg_id();
721 MothOriVert = theMoth->production_vertex();
722 if (MotherPDG == partPDG) break;
723 }
724 itr++;
725 if (itr > 100) {
726 break;
727 }
728 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
729 MothOriVert != partOriVert);
730 return theMoth;
731 }
732
734
735 template <class C, class T> T findMatching(C TruthContainer, T p) {
736 T ptrPart = nullptr;
737 if (!p) return ptrPart;
738 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
739 for (T truthParticle : *TruthContainer) {
740 if (HepMC::is_sim_descendant(p,truthParticle)) {
741 ptrPart = truthParticle;
742 break;
743 }
744 }
745 }
746 else {
747 for (T truthParticle : TruthContainer) {
748 if (HepMC::is_sim_descendant(p,truthParticle)) {
749 ptrPart = truthParticle;
750 break;
751 }
752 }
753 }
754 return ptrPart;
755 }
757
758 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
759 auto prodVtx = thePart->production_vertex();
760 if (!prodVtx) return;
761 for (const auto& theMother: prodVtx->particles_in()) {
762 if (!theMother) continue;
763 allancestors.insert(theMother);
764 findParticleAncestors(theMother, allancestors);
765 }
766 }
767
769
770 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
771 auto endVtx = thePart->end_vertex();
772 if (!endVtx) return;
773 for (const auto& theDaughter: endVtx->particles_out()) {
774 if (!theDaughter) continue;
775 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
776 allstabledescendants.insert(theDaughter);
777 }
778 findParticleStableDescendants(theDaughter, allstabledescendants);
779 }
780 }
781
785
786 template <class T> bool isHardScatteringVertex(T pVert) {
787 if (pVert == nullptr) return false;
788 T pV = pVert;
789 int numOfPartIn(0);
790 int pdg(0);
791
792 do {
793 pVert = pV;
794 auto incoming = pVert->particles_in();
795 numOfPartIn = incoming.size();
796 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
797 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
798
799 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
800
801 if (numOfPartIn == 2) {
802 auto incoming = pVert->particles_in();
803 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
804 }
805 return false;
806}
807
811
812 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
813 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
814 auto vtx = p->production_vertex();
815 if (!vtx) return false;
816 bool fromHad = false;
817 for ( const auto& parent : vtx->particles_in() ) {
818 if (!parent) continue;
819 // should this really go into parton-level territory?
820 // probably depends where BSM particles are being decayed
821 fromBSM |= isBSM(parent);
822 if (!isPhysical(parent)) return false;
823 fromTau |= isTau(parent);
824 if (isHadron(parent)&&!isBeam(parent)) {
825 if (!hadron) hadron = parent; // assumes linear hadron parentage
826 return true;
827 }
828 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
829 }
830 return fromHad;
831 }
832
835
836 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
837 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
838 decltype(thePart->end_vertex()) pVert(nullptr);
839 if (EndVert != nullptr) {
840 do {
841 bool samePart = false;
842 pVert = nullptr;
843 auto outgoing = EndVert->particles_out();
844 auto incoming = EndVert->particles_in();
845 for (const auto& itrDaug: outgoing) {
846 if (!itrDaug) continue;
847 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
848 // brem on generator level for tau
849 (outgoing.size() == 1 && incoming.size() == 1 &&
851 itrDaug->pdg_id() == thePart->pdg_id()) {
852 samePart = true;
853 pVert = itrDaug->end_vertex();
854 }
855 }
856 if (samePart) EndVert = pVert;
857 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
858 }
859 return EndVert;
860 }
861
863
864 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
865 if (!theVert) return {};
866 decltype(theVert->particles_out()) finalStatePart;
867 auto outgoing = theVert->particles_out();
868 for (const auto& thePart: outgoing) {
869 if (!thePart) continue;
870 finalStatePart.push_back(thePart);
871 if (isStable(thePart)) continue;
872 V pVert = findSimulatedEndVertex(thePart);
873 if (pVert == theVert) break; // to prevent Sherpa loop
874 if (pVert != nullptr) {
875 auto vecPart = findFinalStateParticles<V>(pVert);
876 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
877 }
878 }
879 return finalStatePart;
880 }
881#if !defined(XAOD_ANALYSIS)
882#include "AtlasHepMC/GenEvent.h"
883inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
884inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
885
886#endif
887}
888#endif

◆ hasSquark() [2/3]

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

Definition at line 625 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
820 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
821 auto vtx = p->production_vertex();
822 if (!vtx) return false;
823 bool fromHad = false;
824 for ( const auto& parent : vtx->particles_in() ) {
825 if (!parent) continue;
826 // should this really go into parton-level territory?
827 // probably depends where BSM particles are being decayed
828 fromBSM |= isBSM(parent);
829 if (!isPhysical(parent)) return false;
830 fromTau |= isTau(parent);
831 if (isHadron(parent)&&!isBeam(parent)) {
832 if (!hadron) hadron = parent; // assumes linear hadron parentage
833 return true;
834 }
835 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
836 }
837 return fromHad;
838 }
839
842
843 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
844 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
845 decltype(thePart->end_vertex()) pVert(nullptr);
846 if (EndVert != nullptr) {
847 do {
848 bool samePart = false;
849 pVert = nullptr;
850 auto outgoing = EndVert->particles_out();
851 auto incoming = EndVert->particles_in();
852 for (const auto& itrDaug: outgoing) {
853 if (!itrDaug) continue;
854 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
855 // brem on generator level for tau
856 (outgoing.size() == 1 && incoming.size() == 1 &&
858 itrDaug->pdg_id() == thePart->pdg_id()) {
859 samePart = true;
860 pVert = itrDaug->end_vertex();
861 }
862 }
863 if (samePart) EndVert = pVert;
864 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
865 }
866 return EndVert;
867 }
868
870
871 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
872 if (!theVert) return {};
873 decltype(theVert->particles_out()) finalStatePart;
874 auto outgoing = theVert->particles_out();
875 for (const auto& thePart: outgoing) {
876 if (!thePart) continue;
877 finalStatePart.push_back(thePart);
878 if (isStable(thePart)) continue;
879 V pVert = findSimulatedEndVertex(thePart);
880 if (pVert == theVert) break; // to prevent Sherpa loop
881 if (pVert != nullptr) {
882 auto vecPart = findFinalStateParticles<V>(pVert);
883 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
884 }
885 }
886 return finalStatePart;
887 }
888#if !defined(XAOD_ANALYSIS)
889#include "AtlasHepMC/GenEvent.h"
890inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
891inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
892
893#endif
894}
895#endif

◆ hasSquark() [3/3]

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

Definition at line 617 of file HepMCHelpers.h.

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

◆ hasStrange()

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

Definition at line 743 of file HepMCHelpers.h.

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

◆ hasTop()

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

Definition at line 746 of file HepMCHelpers.h.

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

◆ isBaryon() [1/3]

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

Definition at line 290 of file HepMCHelpers.h.

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

◆ isBaryon() [2/3]

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

Definition at line 323 of file HepMCHelpers.h.

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

◆ isBaryon() [3/3]

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

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

Definition at line 289 of file HepMCHelpers.h.

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

◆ isBBbarMeson() [1/3]

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

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

◆ isBBbarMeson() [2/3]

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

Definition at line 935 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1130 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1131 auto vtx = p->production_vertex();
1132 if (!vtx) return false;
1133 bool fromHad = false;
1134 for ( const auto& parent : vtx->particles_in() ) {
1135 if (!parent) continue;
1136 // should this really go into parton-level territory?
1137 // probably depends where BSM particles are being decayed
1138 fromBSM |= isBSM(parent);
1139 if (!isPhysical(parent)) return false;
1140 fromTau |= isTau(parent);
1141 if (isHadron(parent)&&!isBeam(parent)) {
1142 if (!hadron) hadron = parent; // assumes linear hadron parentage
1143 return true;
1144 }
1145 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1146 }
1147 return fromHad;
1148 }
1149
1152
1153 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1154 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1155 decltype(thePart->end_vertex()) pVert(nullptr);
1156 if (EndVert != nullptr) {
1157 do {
1158 bool samePart = false;
1159 pVert = nullptr;
1160 auto outgoing = EndVert->particles_out();
1161 auto incoming = EndVert->particles_in();
1162 for (const auto& itrDaug: outgoing) {
1163 if (!itrDaug) continue;
1164 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1165 // brem on generator level for tau
1166 (outgoing.size() == 1 && incoming.size() == 1 &&
1168 itrDaug->pdg_id() == thePart->pdg_id()) {
1169 samePart = true;
1170 pVert = itrDaug->end_vertex();
1171 }
1172 }
1173 if (samePart) EndVert = pVert;
1174 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1175 }
1176 return EndVert;
1177 }
1178
1180
1181 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1182 if (!theVert) return {};
1183 decltype(theVert->particles_out()) finalStatePart;
1184 auto outgoing = theVert->particles_out();
1185 for (const auto& thePart: outgoing) {
1186 if (!thePart) continue;
1187 finalStatePart.push_back(thePart);
1188 if (isStable(thePart)) continue;
1189 V pVert = findSimulatedEndVertex(thePart);
1190 if (pVert == theVert) break; // to prevent Sherpa loop
1191 if (pVert != nullptr) {
1192 auto vecPart = findFinalStateParticles<V>(pVert);
1193 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1194 }
1195 }
1196 return finalStatePart;
1197 }
1198#if !defined(XAOD_ANALYSIS)
1199#include "AtlasHepMC/GenEvent.h"
1200inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1201inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1202
1203#endif
1204}
1205#endif

◆ isBBbarMeson() [3/3]

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

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

◆ isBeam()

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

Identify if the particle is beam particle.

Definition at line 40 of file HepMCHelpers.h.

◆ isBoson() [1/3]

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

Definition at line 378 of file HepMCHelpers.h.

397{
398 namespace Pythia8
399 {
401 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
402
403 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
404
405 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
406 }
407
408#include "AtlasPID.h"
409
411 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
412
414 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
415
417 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
418
420 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
421
423 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
424
426 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
427
429 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
430
432 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
433
435 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
436
438 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
439
443 template <class T> inline bool isStableOrSimDecayed(const T& p) {
444 const auto vertex = p->end_vertex();
445 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
446 }
447
449 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
450
452 template <class T> inline bool isSpecialNonInteracting(const T& p) {
453 const int apid = std::abs(p->pdg_id());
454 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
455 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
456 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
457 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
458 return false;
459 }
460
462
463 template <class T> T findMother(T thePart) {
464 auto partOriVert = thePart->production_vertex();
465 if (!partOriVert) return nullptr;
466
467 long partPDG = thePart->pdg_id();
468 long MotherPDG(0);
469
470 auto MothOriVert = partOriVert;
471 MothOriVert = nullptr;
472 T theMoth(nullptr);
473
474 size_t itr = 0;
475 do {
476 if (itr != 0) partOriVert = MothOriVert;
477 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
573 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
574 auto vtx = p->production_vertex();
575 if (!vtx) return false;
576 bool fromHad = false;
577 for ( const auto& parent : vtx->particles_in() ) {
578 if (!parent) continue;
579 // should this really go into parton-level territory?
580 // probably depends where BSM particles are being decayed
581 fromBSM |= isBSM(parent);
582 if (!isPhysical(parent)) return false;
583 fromTau |= isTau(parent);
584 if (isHadron(parent)&&!isBeam(parent)) {
585 if (!hadron) hadron = parent; // assumes linear hadron parentage
586 return true;
587 }
588 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
589 }
590 return fromHad;
591 }
592
595
596 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
597 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
598 decltype(thePart->end_vertex()) pVert(nullptr);
599 if (EndVert != nullptr) {
600 do {
601 bool samePart = false;
602 pVert = nullptr;
603 auto outgoing = EndVert->particles_out();
604 auto incoming = EndVert->particles_in();
605 for (const auto& itrDaug: outgoing) {
606 if (!itrDaug) continue;
607 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
608 // brem on generator level for tau
609 (outgoing.size() == 1 && incoming.size() == 1 &&
611 itrDaug->pdg_id() == thePart->pdg_id()) {
612 samePart = true;
613 pVert = itrDaug->end_vertex();
614 }
615 }
616 if (samePart) EndVert = pVert;
617 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
618 }
619 return EndVert;
620 }
621
623
624 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
625 if (!theVert) return {};
626 decltype(theVert->particles_out()) finalStatePart;
627 auto outgoing = theVert->particles_out();
628 for (const auto& thePart: outgoing) {
629 if (!thePart) continue;
630 finalStatePart.push_back(thePart);
631 if (isStable(thePart)) continue;
632 V pVert = findSimulatedEndVertex(thePart);
633 if (pVert == theVert) break; // to prevent Sherpa loop
634 if (pVert != nullptr) {
635 auto vecPart = findFinalStateParticles<V>(pVert);
636 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
637 }
638 }
639 return finalStatePart;
640 }
641#if !defined(XAOD_ANALYSIS)
642#include "AtlasHepMC/GenEvent.h"
643inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
644inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
645
646#endif
647}
648#endif

◆ isBoson() [2/3]

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

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

◆ isBoson() [3/3]

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

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

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

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

◆ isBottom() [1/2]

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

Definition at line 190 of file HepMCHelpers.h.

◆ isBottom() [2/2]

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

Definition at line 189 of file HepMCHelpers.h.

◆ isBottomBaryon()

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

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

◆ isBottomHadron()

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

Definition at line 919 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1114 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1115 auto vtx = p->production_vertex();
1116 if (!vtx) return false;
1117 bool fromHad = false;
1118 for ( const auto& parent : vtx->particles_in() ) {
1119 if (!parent) continue;
1120 // should this really go into parton-level territory?
1121 // probably depends where BSM particles are being decayed
1122 fromBSM |= isBSM(parent);
1123 if (!isPhysical(parent)) return false;
1124 fromTau |= isTau(parent);
1125 if (isHadron(parent)&&!isBeam(parent)) {
1126 if (!hadron) hadron = parent; // assumes linear hadron parentage
1127 return true;
1128 }
1129 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1130 }
1131 return fromHad;
1132 }
1133
1136
1137 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1138 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1139 decltype(thePart->end_vertex()) pVert(nullptr);
1140 if (EndVert != nullptr) {
1141 do {
1142 bool samePart = false;
1143 pVert = nullptr;
1144 auto outgoing = EndVert->particles_out();
1145 auto incoming = EndVert->particles_in();
1146 for (const auto& itrDaug: outgoing) {
1147 if (!itrDaug) continue;
1148 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1149 // brem on generator level for tau
1150 (outgoing.size() == 1 && incoming.size() == 1 &&
1152 itrDaug->pdg_id() == thePart->pdg_id()) {
1153 samePart = true;
1154 pVert = itrDaug->end_vertex();
1155 }
1156 }
1157 if (samePart) EndVert = pVert;
1158 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1159 }
1160 return EndVert;
1161 }
1162
1164
1165 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1166 if (!theVert) return {};
1167 decltype(theVert->particles_out()) finalStatePart;
1168 auto outgoing = theVert->particles_out();
1169 for (const auto& thePart: outgoing) {
1170 if (!thePart) continue;
1171 finalStatePart.push_back(thePart);
1172 if (isStable(thePart)) continue;
1173 V pVert = findSimulatedEndVertex(thePart);
1174 if (pVert == theVert) break; // to prevent Sherpa loop
1175 if (pVert != nullptr) {
1176 auto vecPart = findFinalStateParticles<V>(pVert);
1177 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1178 }
1179 }
1180 return finalStatePart;
1181 }
1182#if !defined(XAOD_ANALYSIS)
1183#include "AtlasHepMC/GenEvent.h"
1184inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1185inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1186
1187#endif
1188}
1189#endif

◆ isBottomMeson()

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

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

◆ isBSM() [1/3]

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

Definition at line 854 of file HepMCHelpers.h.

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

◆ isBSM() [2/3]

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

Definition at line 871 of file HepMCHelpers.h.

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

◆ isBSM() [3/3]

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

APID: graviton and all Higgs extensions are BSM.

Definition at line 853 of file HepMCHelpers.h.

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

◆ isCCbarMeson() [1/3]

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

Definition at line 930 of file HepMCHelpers.h.

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

◆ isCCbarMeson() [2/3]

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

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

◆ isCCbarMeson() [3/3]

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

Definition at line 929 of file HepMCHelpers.h.

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

◆ isCharged()

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

Definition at line 1011 of file HepMCHelpers.h.

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

◆ isChargedNonShowering()

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

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

Definition at line 37 of file HepMCHelpers.h.

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

◆ isCharm() [1/2]

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

Definition at line 187 of file HepMCHelpers.h.

◆ isCharm() [2/2]

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

Definition at line 186 of file HepMCHelpers.h.

◆ isCharmBaryon()

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

Definition at line 941 of file HepMCHelpers.h.

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

◆ isCharmHadron()

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

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

◆ isCharmMeson()

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

Definition at line 925 of file HepMCHelpers.h.

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

◆ isChLepton() [1/2]

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

Definition at line 207 of file HepMCHelpers.h.

207{

◆ isChLepton() [2/2]

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

APID: the fourth generation leptons are leptons.

Definition at line 206 of file HepMCHelpers.h.

◆ isDecayed()

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

Identify if the particle decayed.

Definition at line 43 of file HepMCHelpers.h.

◆ isDiquark() [1/3]

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

Definition at line 235 of file HepMCHelpers.h.

◆ isDiquark() [2/3]

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

Definition at line 241 of file HepMCHelpers.h.

◆ isDiquark() [3/3]

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

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

Definition at line 234 of file HepMCHelpers.h.

234{

◆ isDM() [1/2]

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

Definition at line 666 of file HepMCHelpers.h.

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

◆ isDM() [2/2]

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

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

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

Definition at line 665 of file HepMCHelpers.h.

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

◆ isElectron() [1/2]

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

Definition at line 210 of file HepMCHelpers.h.

◆ isElectron() [2/2]

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

Definition at line 209 of file HepMCHelpers.h.

◆ isEMInteracting() [1/2]

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

Definition at line 1112 of file HepMCHelpers.h.

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

◆ isEMInteracting() [2/2]

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

Definition at line 1111 of file HepMCHelpers.h.

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

◆ isExcited() [1/3]

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

Definition at line 545 of file HepMCHelpers.h.

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

◆ isExcited() [2/3]

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

Definition at line 550 of file HepMCHelpers.h.

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

◆ isExcited() [3/3]

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

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

Definition at line 543 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 for ( const auto& p : partOriVert->particles_in() ) {
643 theMoth = p;
644 if (!theMoth) continue;
645 MotherPDG = theMoth->pdg_id();
646 MothOriVert = theMoth->production_vertex();
647 if (MotherPDG == partPDG) break;
648 }
649 itr++;
650 if (itr > 100) {
651 break;
652 }
653 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
654 MothOriVert != partOriVert);
655 return theMoth;
656 }
657
659
660 template <class C, class T> T findMatching(C TruthContainer, T p) {
661 T ptrPart = nullptr;
662 if (!p) return ptrPart;
663 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
664 for (T truthParticle : *TruthContainer) {
665 if (HepMC::is_sim_descendant(p,truthParticle)) {
666 ptrPart = truthParticle;
667 break;
668 }
669 }
670 }
671 else {
672 for (T truthParticle : TruthContainer) {
673 if (HepMC::is_sim_descendant(p,truthParticle)) {
674 ptrPart = truthParticle;
675 break;
676 }
677 }
678 }
679 return ptrPart;
680 }
682
683 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
684 auto prodVtx = thePart->production_vertex();
685 if (!prodVtx) return;
686 for (const auto& theMother: prodVtx->particles_in()) {
687 if (!theMother) continue;
688 allancestors.insert(theMother);
689 findParticleAncestors(theMother, allancestors);
690 }
691 }
692
694
695 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
696 auto endVtx = thePart->end_vertex();
697 if (!endVtx) return;
698 for (const auto& theDaughter: endVtx->particles_out()) {
699 if (!theDaughter) continue;
700 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
701 allstabledescendants.insert(theDaughter);
702 }
703 findParticleStableDescendants(theDaughter, allstabledescendants);
704 }
705 }
706
710
711 template <class T> bool isHardScatteringVertex(T pVert) {
712 if (pVert == nullptr) return false;
713 T pV = pVert;
714 int numOfPartIn(0);
715 int pdg(0);
716
717 do {
718 pVert = pV;
719 auto incoming = pVert->particles_in();
720 numOfPartIn = incoming.size();
721 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
722 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
723
724 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
725
726 if (numOfPartIn == 2) {
727 auto incoming = pVert->particles_in();
728 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
729 }
730 return false;
731}
732
736
737 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
738 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
739 auto vtx = p->production_vertex();
740 if (!vtx) return false;
741 bool fromHad = false;
742 for ( const auto& parent : vtx->particles_in() ) {
743 if (!parent) continue;
744 // should this really go into parton-level territory?
745 // probably depends where BSM particles are being decayed
746 fromBSM |= isBSM(parent);
747 if (!isPhysical(parent)) return false;
748 fromTau |= isTau(parent);
749 if (isHadron(parent)&&!isBeam(parent)) {
750 if (!hadron) hadron = parent; // assumes linear hadron parentage
751 return true;
752 }
753 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
754 }
755 return fromHad;
756 }
757
760
761 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
762 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
763 decltype(thePart->end_vertex()) pVert(nullptr);
764 if (EndVert != nullptr) {
765 do {
766 bool samePart = false;
767 pVert = nullptr;
768 auto outgoing = EndVert->particles_out();
769 auto incoming = EndVert->particles_in();
770 for (const auto& itrDaug: outgoing) {
771 if (!itrDaug) continue;
772 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
773 // brem on generator level for tau
774 (outgoing.size() == 1 && incoming.size() == 1 &&
776 itrDaug->pdg_id() == thePart->pdg_id()) {
777 samePart = true;
778 pVert = itrDaug->end_vertex();
779 }
780 }
781 if (samePart) EndVert = pVert;
782 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
783 }
784 return EndVert;
785 }
786
788
789 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
790 if (!theVert) return {};
791 decltype(theVert->particles_out()) finalStatePart;
792 auto outgoing = theVert->particles_out();
793 for (const auto& thePart: outgoing) {
794 if (!thePart) continue;
795 finalStatePart.push_back(thePart);
796 if (isStable(thePart)) continue;
797 V pVert = findSimulatedEndVertex(thePart);
798 if (pVert == theVert) break; // to prevent Sherpa loop
799 if (pVert != nullptr) {
800 auto vecPart = findFinalStateParticles<V>(pVert);
801 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
802 }
803 }
804 return finalStatePart;
805 }
806#if !defined(XAOD_ANALYSIS)
807#include "AtlasHepMC/GenEvent.h"
808inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
809inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
810
811#endif
812}
813#endif

◆ isFinalState()

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

Identify if the particle is final state particle.

Definition at line 49 of file HepMCHelpers.h.

49{ 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 228 of file HepMCHelpers.h.

228: outgoing) {

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

◆ isFromHadron()

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

Function to classify the particle.

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

Definition at line 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 for ( const auto& parent : vtx->particles_in() ) {
201 if (!parent) continue;
202 // should this really go into parton-level territory?
203 // probably depends where BSM particles are being decayed
204 fromBSM |= isBSM(parent);
205 if (!isPhysical(parent)) return false;
206 fromTau |= isTau(parent);
207 if (isHadron(parent)&&!isBeam(parent)) {
208 if (!hadron) hadron = parent; // assumes linear hadron parentage
209 return true;
210 }
211 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
212 }
213 return fromHad;
214 }

◆ isGaugino() [1/3]

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

Definition at line 512 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 for ( const auto& p : partOriVert->particles_in() ) {
612 theMoth = p;
613 if (!theMoth) continue;
614 MotherPDG = theMoth->pdg_id();
615 MothOriVert = theMoth->production_vertex();
616 if (MotherPDG == partPDG) break;
617 }
618 itr++;
619 if (itr > 100) {
620 break;
621 }
622 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
623 MothOriVert != partOriVert);
624 return theMoth;
625 }
626
628
629 template <class C, class T> T findMatching(C TruthContainer, T p) {
630 T ptrPart = nullptr;
631 if (!p) return ptrPart;
632 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
633 for (T truthParticle : *TruthContainer) {
634 if (HepMC::is_sim_descendant(p,truthParticle)) {
635 ptrPart = truthParticle;
636 break;
637 }
638 }
639 }
640 else {
641 for (T truthParticle : TruthContainer) {
642 if (HepMC::is_sim_descendant(p,truthParticle)) {
643 ptrPart = truthParticle;
644 break;
645 }
646 }
647 }
648 return ptrPart;
649 }
651
652 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
653 auto prodVtx = thePart->production_vertex();
654 if (!prodVtx) return;
655 for (const auto& theMother: prodVtx->particles_in()) {
656 if (!theMother) continue;
657 allancestors.insert(theMother);
658 findParticleAncestors(theMother, allancestors);
659 }
660 }
661
663
664 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
665 auto endVtx = thePart->end_vertex();
666 if (!endVtx) return;
667 for (const auto& theDaughter: endVtx->particles_out()) {
668 if (!theDaughter) continue;
669 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
670 allstabledescendants.insert(theDaughter);
671 }
672 findParticleStableDescendants(theDaughter, allstabledescendants);
673 }
674 }
675
679
680 template <class T> bool isHardScatteringVertex(T pVert) {
681 if (pVert == nullptr) return false;
682 T pV = pVert;
683 int numOfPartIn(0);
684 int pdg(0);
685
686 do {
687 pVert = pV;
688 auto incoming = pVert->particles_in();
689 numOfPartIn = incoming.size();
690 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
691 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
692
693 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
694
695 if (numOfPartIn == 2) {
696 auto incoming = pVert->particles_in();
697 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
698 }
699 return false;
700}
701
705
706 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
707 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
708 auto vtx = p->production_vertex();
709 if (!vtx) return false;
710 bool fromHad = false;
711 for ( const auto& parent : vtx->particles_in() ) {
712 if (!parent) continue;
713 // should this really go into parton-level territory?
714 // probably depends where BSM particles are being decayed
715 fromBSM |= isBSM(parent);
716 if (!isPhysical(parent)) return false;
717 fromTau |= isTau(parent);
718 if (isHadron(parent)&&!isBeam(parent)) {
719 if (!hadron) hadron = parent; // assumes linear hadron parentage
720 return true;
721 }
722 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
723 }
724 return fromHad;
725 }
726
729
730 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
731 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
732 decltype(thePart->end_vertex()) pVert(nullptr);
733 if (EndVert != nullptr) {
734 do {
735 bool samePart = false;
736 pVert = nullptr;
737 auto outgoing = EndVert->particles_out();
738 auto incoming = EndVert->particles_in();
739 for (const auto& itrDaug: outgoing) {
740 if (!itrDaug) continue;
741 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
742 // brem on generator level for tau
743 (outgoing.size() == 1 && incoming.size() == 1 &&
745 itrDaug->pdg_id() == thePart->pdg_id()) {
746 samePart = true;
747 pVert = itrDaug->end_vertex();
748 }
749 }
750 if (samePart) EndVert = pVert;
751 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
752 }
753 return EndVert;
754 }
755
757
758 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
759 if (!theVert) return {};
760 decltype(theVert->particles_out()) finalStatePart;
761 auto outgoing = theVert->particles_out();
762 for (const auto& thePart: outgoing) {
763 if (!thePart) continue;
764 finalStatePart.push_back(thePart);
765 if (isStable(thePart)) continue;
766 V pVert = findSimulatedEndVertex(thePart);
767 if (pVert == theVert) break; // to prevent Sherpa loop
768 if (pVert != nullptr) {
769 auto vecPart = findFinalStateParticles<V>(pVert);
770 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
771 }
772 }
773 return finalStatePart;
774 }
775#if !defined(XAOD_ANALYSIS)
776#include "AtlasHepMC/GenEvent.h"
777inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
778inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
779
780#endif
781}
782#endif

◆ isGaugino() [2/3]

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

Definition at line 515 of file HepMCHelpers.h.

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

◆ isGaugino() [3/3]

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

Definition at line 511 of file HepMCHelpers.h.

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

◆ isGeantino() [1/2]

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

Definition at line 445 of file HepMCHelpers.h.

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

◆ isGeantino() [2/2]

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

Definition at line 444 of file HepMCHelpers.h.

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

◆ isGenericMultichargedParticle() [1/3]

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

Definition at line 692 of file HepMCHelpers.h.

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

◆ isGenericMultichargedParticle() [2/3]

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

Definition at line 693 of file HepMCHelpers.h.

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

◆ isGenericMultichargedParticle() [3/3]

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

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

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

Definition at line 691 of file HepMCHelpers.h.

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

◆ isGenSpecific() [1/2]

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

Definition at line 433 of file HepMCHelpers.h.

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

◆ isGenSpecific() [2/2]

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

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

Definition at line 432 of file HepMCHelpers.h.

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

◆ isGenStable()

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

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

Definition at line 55 of file HepMCHelpers.h.

◆ isGlueball() [1/3]

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

Definition at line 449 of file HepMCHelpers.h.

468{
469 namespace Pythia8
470 {
472 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
473
474 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
475
476 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
477 }
478
479#include "AtlasPID.h"
480
482 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
483
485 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
486
488 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
489
491 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
492
494 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
495
497 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
498
500 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
501
503 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
504
506 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
507
509 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
510
514 template <class T> inline bool isStableOrSimDecayed(const T& p) {
515 const auto vertex = p->end_vertex();
516 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
517 }
518
520 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
521
523 template <class T> inline bool isSpecialNonInteracting(const T& p) {
524 const int apid = std::abs(p->pdg_id());
525 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
526 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
527 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
528 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
529 return false;
530 }
531
533
534 template <class T> T findMother(T thePart) {
535 auto partOriVert = thePart->production_vertex();
536 if (!partOriVert) return nullptr;
537
538 long partPDG = thePart->pdg_id();
539 long MotherPDG(0);
540
541 auto MothOriVert = partOriVert;
542 MothOriVert = nullptr;
543 T theMoth(nullptr);
544
545 size_t itr = 0;
546 do {
547 if (itr != 0) partOriVert = MothOriVert;
548 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
644 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
645 auto vtx = p->production_vertex();
646 if (!vtx) return false;
647 bool fromHad = false;
648 for ( const auto& parent : vtx->particles_in() ) {
649 if (!parent) continue;
650 // should this really go into parton-level territory?
651 // probably depends where BSM particles are being decayed
652 fromBSM |= isBSM(parent);
653 if (!isPhysical(parent)) return false;
654 fromTau |= isTau(parent);
655 if (isHadron(parent)&&!isBeam(parent)) {
656 if (!hadron) hadron = parent; // assumes linear hadron parentage
657 return true;
658 }
659 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
660 }
661 return fromHad;
662 }
663
666
667 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
668 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
669 decltype(thePart->end_vertex()) pVert(nullptr);
670 if (EndVert != nullptr) {
671 do {
672 bool samePart = false;
673 pVert = nullptr;
674 auto outgoing = EndVert->particles_out();
675 auto incoming = EndVert->particles_in();
676 for (const auto& itrDaug: outgoing) {
677 if (!itrDaug) continue;
678 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
679 // brem on generator level for tau
680 (outgoing.size() == 1 && incoming.size() == 1 &&
682 itrDaug->pdg_id() == thePart->pdg_id()) {
683 samePart = true;
684 pVert = itrDaug->end_vertex();
685 }
686 }
687 if (samePart) EndVert = pVert;
688 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
689 }
690 return EndVert;
691 }
692
694
695 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
696 if (!theVert) return {};
697 decltype(theVert->particles_out()) finalStatePart;
698 auto outgoing = theVert->particles_out();
699 for (const auto& thePart: outgoing) {
700 if (!thePart) continue;
701 finalStatePart.push_back(thePart);
702 if (isStable(thePart)) continue;
703 V pVert = findSimulatedEndVertex(thePart);
704 if (pVert == theVert) break; // to prevent Sherpa loop
705 if (pVert != nullptr) {
706 auto vecPart = findFinalStateParticles<V>(pVert);
707 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
708 }
709 }
710 return finalStatePart;
711 }
712#if !defined(XAOD_ANALYSIS)
713#include "AtlasHepMC/GenEvent.h"
714inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
715inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
716
717#endif
718}
719#endif

◆ isGlueball() [2/3]

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

Definition at line 455 of file HepMCHelpers.h.

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

◆ isGlueball() [3/3]

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

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

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

◆ isGluon() [1/2]

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

Definition at line 381 of file HepMCHelpers.h.

400{
401 namespace Pythia8
402 {
404 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
405
406 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
407
408 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
409 }
410
411#include "AtlasPID.h"
412
414 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
415
417 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
418
420 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
421
423 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
424
426 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
427
429 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
430
432 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
433
435 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
436
438 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
439
441 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
442
446 template <class T> inline bool isStableOrSimDecayed(const T& p) {
447 const auto vertex = p->end_vertex();
448 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
449 }
450
452 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
453
455 template <class T> inline bool isSpecialNonInteracting(const T& p) {
456 const int apid = std::abs(p->pdg_id());
457 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
458 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
459 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
460 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
461 return false;
462 }
463
465
466 template <class T> T findMother(T thePart) {
467 auto partOriVert = thePart->production_vertex();
468 if (!partOriVert) return nullptr;
469
470 long partPDG = thePart->pdg_id();
471 long MotherPDG(0);
472
473 auto MothOriVert = partOriVert;
474 MothOriVert = nullptr;
475 T theMoth(nullptr);
476
477 size_t itr = 0;
478 do {
479 if (itr != 0) partOriVert = MothOriVert;
480 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
576 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
577 auto vtx = p->production_vertex();
578 if (!vtx) return false;
579 bool fromHad = false;
580 for ( const auto& parent : vtx->particles_in() ) {
581 if (!parent) continue;
582 // should this really go into parton-level territory?
583 // probably depends where BSM particles are being decayed
584 fromBSM |= isBSM(parent);
585 if (!isPhysical(parent)) return false;
586 fromTau |= isTau(parent);
587 if (isHadron(parent)&&!isBeam(parent)) {
588 if (!hadron) hadron = parent; // assumes linear hadron parentage
589 return true;
590 }
591 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
592 }
593 return fromHad;
594 }
595
598
599 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
600 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
601 decltype(thePart->end_vertex()) pVert(nullptr);
602 if (EndVert != nullptr) {
603 do {
604 bool samePart = false;
605 pVert = nullptr;
606 auto outgoing = EndVert->particles_out();
607 auto incoming = EndVert->particles_in();
608 for (const auto& itrDaug: outgoing) {
609 if (!itrDaug) continue;
610 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
611 // brem on generator level for tau
612 (outgoing.size() == 1 && incoming.size() == 1 &&
614 itrDaug->pdg_id() == thePart->pdg_id()) {
615 samePart = true;
616 pVert = itrDaug->end_vertex();
617 }
618 }
619 if (samePart) EndVert = pVert;
620 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
621 }
622 return EndVert;
623 }
624
626
627 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
628 if (!theVert) return {};
629 decltype(theVert->particles_out()) finalStatePart;
630 auto outgoing = theVert->particles_out();
631 for (const auto& thePart: outgoing) {
632 if (!thePart) continue;
633 finalStatePart.push_back(thePart);
634 if (isStable(thePart)) continue;
635 V pVert = findSimulatedEndVertex(thePart);
636 if (pVert == theVert) break; // to prevent Sherpa loop
637 if (pVert != nullptr) {
638 auto vecPart = findFinalStateParticles<V>(pVert);
639 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
640 }
641 }
642 return finalStatePart;
643 }
644#if !defined(XAOD_ANALYSIS)
645#include "AtlasHepMC/GenEvent.h"
646inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
647inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
648
649#endif
650}
651#endif

◆ isGluon() [2/2]

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

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

◆ isGraviton() [1/2]

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

Definition at line 405 of file HepMCHelpers.h.

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

◆ isGraviton() [2/2]

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

Definition at line 404 of file HepMCHelpers.h.

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

◆ isHadron() [1/3]

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

Definition at line 359 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 for ( const auto& p : partOriVert->particles_in() ) {
459 theMoth = p;
460 if (!theMoth) continue;
461 MotherPDG = theMoth->pdg_id();
462 MothOriVert = theMoth->production_vertex();
463 if (MotherPDG == partPDG) break;
464 }
465 itr++;
466 if (itr > 100) {
467 break;
468 }
469 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
470 MothOriVert != partOriVert);
471 return theMoth;
472 }
473
475
476 template <class C, class T> T findMatching(C TruthContainer, T p) {
477 T ptrPart = nullptr;
478 if (!p) return ptrPart;
479 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
480 for (T truthParticle : *TruthContainer) {
481 if (HepMC::is_sim_descendant(p,truthParticle)) {
482 ptrPart = truthParticle;
483 break;
484 }
485 }
486 }
487 else {
488 for (T truthParticle : TruthContainer) {
489 if (HepMC::is_sim_descendant(p,truthParticle)) {
490 ptrPart = truthParticle;
491 break;
492 }
493 }
494 }
495 return ptrPart;
496 }
498
499 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
500 auto prodVtx = thePart->production_vertex();
501 if (!prodVtx) return;
502 for (const auto& theMother: prodVtx->particles_in()) {
503 if (!theMother) continue;
504 allancestors.insert(theMother);
505 findParticleAncestors(theMother, allancestors);
506 }
507 }
508
510
511 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
512 auto endVtx = thePart->end_vertex();
513 if (!endVtx) return;
514 for (const auto& theDaughter: endVtx->particles_out()) {
515 if (!theDaughter) continue;
516 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
517 allstabledescendants.insert(theDaughter);
518 }
519 findParticleStableDescendants(theDaughter, allstabledescendants);
520 }
521 }
522
526
527 template <class T> bool isHardScatteringVertex(T pVert) {
528 if (pVert == nullptr) return false;
529 T pV = pVert;
530 int numOfPartIn(0);
531 int pdg(0);
532
533 do {
534 pVert = pV;
535 auto incoming = pVert->particles_in();
536 numOfPartIn = incoming.size();
537 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
538 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
539
540 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
541
542 if (numOfPartIn == 2) {
543 auto incoming = pVert->particles_in();
544 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
545 }
546 return false;
547}
548
552
553 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
554 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
555 auto vtx = p->production_vertex();
556 if (!vtx) return false;
557 bool fromHad = false;
558 for ( const auto& parent : vtx->particles_in() ) {
559 if (!parent) continue;
560 // should this really go into parton-level territory?
561 // probably depends where BSM particles are being decayed
562 fromBSM |= isBSM(parent);
563 if (!isPhysical(parent)) return false;
564 fromTau |= isTau(parent);
565 if (isHadron(parent)&&!isBeam(parent)) {
566 if (!hadron) hadron = parent; // assumes linear hadron parentage
567 return true;
568 }
569 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
570 }
571 return fromHad;
572 }
573
576
577 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
578 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
579 decltype(thePart->end_vertex()) pVert(nullptr);
580 if (EndVert != nullptr) {
581 do {
582 bool samePart = false;
583 pVert = nullptr;
584 auto outgoing = EndVert->particles_out();
585 auto incoming = EndVert->particles_in();
586 for (const auto& itrDaug: outgoing) {
587 if (!itrDaug) continue;
588 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
589 // brem on generator level for tau
590 (outgoing.size() == 1 && incoming.size() == 1 &&
592 itrDaug->pdg_id() == thePart->pdg_id()) {
593 samePart = true;
594 pVert = itrDaug->end_vertex();
595 }
596 }
597 if (samePart) EndVert = pVert;
598 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
599 }
600 return EndVert;
601 }
602
604
605 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
606 if (!theVert) return {};
607 decltype(theVert->particles_out()) finalStatePart;
608 auto outgoing = theVert->particles_out();
609 for (const auto& thePart: outgoing) {
610 if (!thePart) continue;
611 finalStatePart.push_back(thePart);
612 if (isStable(thePart)) continue;
613 V pVert = findSimulatedEndVertex(thePart);
614 if (pVert == theVert) break; // to prevent Sherpa loop
615 if (pVert != nullptr) {
616 auto vecPart = findFinalStateParticles<V>(pVert);
617 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
618 }
619 }
620 return finalStatePart;
621 }
622#if !defined(XAOD_ANALYSIS)
623#include "AtlasHepMC/GenEvent.h"
624inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
625inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
626
627#endif
628}
629#endif

◆ isHadron() [2/3]

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

Definition at line 360 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
555 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
556 auto vtx = p->production_vertex();
557 if (!vtx) return false;
558 bool fromHad = false;
559 for ( const auto& parent : vtx->particles_in() ) {
560 if (!parent) continue;
561 // should this really go into parton-level territory?
562 // probably depends where BSM particles are being decayed
563 fromBSM |= isBSM(parent);
564 if (!isPhysical(parent)) return false;
565 fromTau |= isTau(parent);
566 if (isHadron(parent)&&!isBeam(parent)) {
567 if (!hadron) hadron = parent; // assumes linear hadron parentage
568 return true;
569 }
570 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
571 }
572 return fromHad;
573 }
574
577
578 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
579 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
580 decltype(thePart->end_vertex()) pVert(nullptr);
581 if (EndVert != nullptr) {
582 do {
583 bool samePart = false;
584 pVert = nullptr;
585 auto outgoing = EndVert->particles_out();
586 auto incoming = EndVert->particles_in();
587 for (const auto& itrDaug: outgoing) {
588 if (!itrDaug) continue;
589 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
590 // brem on generator level for tau
591 (outgoing.size() == 1 && incoming.size() == 1 &&
593 itrDaug->pdg_id() == thePart->pdg_id()) {
594 samePart = true;
595 pVert = itrDaug->end_vertex();
596 }
597 }
598 if (samePart) EndVert = pVert;
599 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
600 }
601 return EndVert;
602 }
603
605
606 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
607 if (!theVert) return {};
608 decltype(theVert->particles_out()) finalStatePart;
609 auto outgoing = theVert->particles_out();
610 for (const auto& thePart: outgoing) {
611 if (!thePart) continue;
612 finalStatePart.push_back(thePart);
613 if (isStable(thePart)) continue;
614 V pVert = findSimulatedEndVertex(thePart);
615 if (pVert == theVert) break; // to prevent Sherpa loop
616 if (pVert != nullptr) {
617 auto vecPart = findFinalStateParticles<V>(pVert);
618 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
619 }
620 }
621 return finalStatePart;
622 }
623#if !defined(XAOD_ANALYSIS)
624#include "AtlasHepMC/GenEvent.h"
625inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
626inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
627
628#endif
629}
630#endif

◆ isHadron() [3/3]

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

Definition at line 358 of file HepMCHelpers.h.

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

◆ isHardScatteringVertex()

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

Function to classify the vertex as hard scattering vertex.

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

Definition at line 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 939 of file HepMCHelpers.h.

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

◆ isHeavyBoson() [1/2]

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

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

◆ isHeavyBoson() [2/2]

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

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

Definition at line 393 of file HepMCHelpers.h.

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

◆ isHeavyHadron()

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

Definition at line 916 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1111 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1112 auto vtx = p->production_vertex();
1113 if (!vtx) return false;
1114 bool fromHad = false;
1115 for ( const auto& parent : vtx->particles_in() ) {
1116 if (!parent) continue;
1117 // should this really go into parton-level territory?
1118 // probably depends where BSM particles are being decayed
1119 fromBSM |= isBSM(parent);
1120 if (!isPhysical(parent)) return false;
1121 fromTau |= isTau(parent);
1122 if (isHadron(parent)&&!isBeam(parent)) {
1123 if (!hadron) hadron = parent; // assumes linear hadron parentage
1124 return true;
1125 }
1126 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1127 }
1128 return fromHad;
1129 }
1130
1133
1134 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1135 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1136 decltype(thePart->end_vertex()) pVert(nullptr);
1137 if (EndVert != nullptr) {
1138 do {
1139 bool samePart = false;
1140 pVert = nullptr;
1141 auto outgoing = EndVert->particles_out();
1142 auto incoming = EndVert->particles_in();
1143 for (const auto& itrDaug: outgoing) {
1144 if (!itrDaug) continue;
1145 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1146 // brem on generator level for tau
1147 (outgoing.size() == 1 && incoming.size() == 1 &&
1149 itrDaug->pdg_id() == thePart->pdg_id()) {
1150 samePart = true;
1151 pVert = itrDaug->end_vertex();
1152 }
1153 }
1154 if (samePart) EndVert = pVert;
1155 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1156 }
1157 return EndVert;
1158 }
1159
1161
1162 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1163 if (!theVert) return {};
1164 decltype(theVert->particles_out()) finalStatePart;
1165 auto outgoing = theVert->particles_out();
1166 for (const auto& thePart: outgoing) {
1167 if (!thePart) continue;
1168 finalStatePart.push_back(thePart);
1169 if (isStable(thePart)) continue;
1170 V pVert = findSimulatedEndVertex(thePart);
1171 if (pVert == theVert) break; // to prevent Sherpa loop
1172 if (pVert != nullptr) {
1173 auto vecPart = findFinalStateParticles<V>(pVert);
1174 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1175 }
1176 }
1177 return finalStatePart;
1178 }
1179#if !defined(XAOD_ANALYSIS)
1180#include "AtlasHepMC/GenEvent.h"
1181inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1182inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1183
1184#endif
1185}
1186#endif

◆ isHeavyMeson()

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

Definition at line 923 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1118 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1119 auto vtx = p->production_vertex();
1120 if (!vtx) return false;
1121 bool fromHad = false;
1122 for ( const auto& parent : vtx->particles_in() ) {
1123 if (!parent) continue;
1124 // should this really go into parton-level territory?
1125 // probably depends where BSM particles are being decayed
1126 fromBSM |= isBSM(parent);
1127 if (!isPhysical(parent)) return false;
1128 fromTau |= isTau(parent);
1129 if (isHadron(parent)&&!isBeam(parent)) {
1130 if (!hadron) hadron = parent; // assumes linear hadron parentage
1131 return true;
1132 }
1133 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1134 }
1135 return fromHad;
1136 }
1137
1140
1141 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1142 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1143 decltype(thePart->end_vertex()) pVert(nullptr);
1144 if (EndVert != nullptr) {
1145 do {
1146 bool samePart = false;
1147 pVert = nullptr;
1148 auto outgoing = EndVert->particles_out();
1149 auto incoming = EndVert->particles_in();
1150 for (const auto& itrDaug: outgoing) {
1151 if (!itrDaug) continue;
1152 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1153 // brem on generator level for tau
1154 (outgoing.size() == 1 && incoming.size() == 1 &&
1156 itrDaug->pdg_id() == thePart->pdg_id()) {
1157 samePart = true;
1158 pVert = itrDaug->end_vertex();
1159 }
1160 }
1161 if (samePart) EndVert = pVert;
1162 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1163 }
1164 return EndVert;
1165 }
1166
1168
1169 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1170 if (!theVert) return {};
1171 decltype(theVert->particles_out()) finalStatePart;
1172 auto outgoing = theVert->particles_out();
1173 for (const auto& thePart: outgoing) {
1174 if (!thePart) continue;
1175 finalStatePart.push_back(thePart);
1176 if (isStable(thePart)) continue;
1177 V pVert = findSimulatedEndVertex(thePart);
1178 if (pVert == theVert) break; // to prevent Sherpa loop
1179 if (pVert != nullptr) {
1180 auto vecPart = findFinalStateParticles<V>(pVert);
1181 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1182 }
1183 }
1184 return finalStatePart;
1185 }
1186#if !defined(XAOD_ANALYSIS)
1187#include "AtlasHepMC/GenEvent.h"
1188inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1189inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1190
1191#endif
1192}
1193#endif

◆ isHiddenValley() [1/3]

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

Definition at line 677 of file HepMCHelpers.h.

696{
697 namespace Pythia8
698 {
700 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
701
702 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
703
704 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
705 }
706
707#include "AtlasPID.h"
708
710 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
711
713 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
714
716 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
717
719 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
720
722 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
723
725 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
726
728 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
729
731 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
732
734 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
735
737 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
738
742 template <class T> inline bool isStableOrSimDecayed(const T& p) {
743 const auto vertex = p->end_vertex();
744 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
745 }
746
748 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
749
751 template <class T> inline bool isSpecialNonInteracting(const T& p) {
752 const int apid = std::abs(p->pdg_id());
753 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
754 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
755 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
756 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
757 return false;
758 }
759
761
762 template <class T> T findMother(T thePart) {
763 auto partOriVert = thePart->production_vertex();
764 if (!partOriVert) return nullptr;
765
766 long partPDG = thePart->pdg_id();
767 long MotherPDG(0);
768
769 auto MothOriVert = partOriVert;
770 MothOriVert = nullptr;
771 T theMoth(nullptr);
772
773 size_t itr = 0;
774 do {
775 if (itr != 0) partOriVert = MothOriVert;
776 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
872 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
873 auto vtx = p->production_vertex();
874 if (!vtx) return false;
875 bool fromHad = false;
876 for ( const auto& parent : vtx->particles_in() ) {
877 if (!parent) continue;
878 // should this really go into parton-level territory?
879 // probably depends where BSM particles are being decayed
880 fromBSM |= isBSM(parent);
881 if (!isPhysical(parent)) return false;
882 fromTau |= isTau(parent);
883 if (isHadron(parent)&&!isBeam(parent)) {
884 if (!hadron) hadron = parent; // assumes linear hadron parentage
885 return true;
886 }
887 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
888 }
889 return fromHad;
890 }
891
894
895 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
896 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
897 decltype(thePart->end_vertex()) pVert(nullptr);
898 if (EndVert != nullptr) {
899 do {
900 bool samePart = false;
901 pVert = nullptr;
902 auto outgoing = EndVert->particles_out();
903 auto incoming = EndVert->particles_in();
904 for (const auto& itrDaug: outgoing) {
905 if (!itrDaug) continue;
906 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
907 // brem on generator level for tau
908 (outgoing.size() == 1 && incoming.size() == 1 &&
910 itrDaug->pdg_id() == thePart->pdg_id()) {
911 samePart = true;
912 pVert = itrDaug->end_vertex();
913 }
914 }
915 if (samePart) EndVert = pVert;
916 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
917 }
918 return EndVert;
919 }
920
922
923 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
924 if (!theVert) return {};
925 decltype(theVert->particles_out()) finalStatePart;
926 auto outgoing = theVert->particles_out();
927 for (const auto& thePart: outgoing) {
928 if (!thePart) continue;
929 finalStatePart.push_back(thePart);
930 if (isStable(thePart)) continue;
931 V pVert = findSimulatedEndVertex(thePart);
932 if (pVert == theVert) break; // to prevent Sherpa loop
933 if (pVert != nullptr) {
934 auto vecPart = findFinalStateParticles<V>(pVert);
935 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
936 }
937 }
938 return finalStatePart;
939 }
940#if !defined(XAOD_ANALYSIS)
941#include "AtlasHepMC/GenEvent.h"
942inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
943inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
944
945#endif
946}
947#endif

◆ isHiddenValley() [2/3]

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

Definition at line 683 of file HepMCHelpers.h.

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

◆ isHiddenValley() [3/3]

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

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

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

Definition at line 675 of file HepMCHelpers.h.

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

◆ isHiggs() [1/2]

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

Definition at line 398 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
593 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
594 auto vtx = p->production_vertex();
595 if (!vtx) return false;
596 bool fromHad = false;
597 for ( const auto& parent : vtx->particles_in() ) {
598 if (!parent) continue;
599 // should this really go into parton-level territory?
600 // probably depends where BSM particles are being decayed
601 fromBSM |= isBSM(parent);
602 if (!isPhysical(parent)) return false;
603 fromTau |= isTau(parent);
604 if (isHadron(parent)&&!isBeam(parent)) {
605 if (!hadron) hadron = parent; // assumes linear hadron parentage
606 return true;
607 }
608 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
609 }
610 return fromHad;
611 }
612
615
616 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
617 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
618 decltype(thePart->end_vertex()) pVert(nullptr);
619 if (EndVert != nullptr) {
620 do {
621 bool samePart = false;
622 pVert = nullptr;
623 auto outgoing = EndVert->particles_out();
624 auto incoming = EndVert->particles_in();
625 for (const auto& itrDaug: outgoing) {
626 if (!itrDaug) continue;
627 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
628 // brem on generator level for tau
629 (outgoing.size() == 1 && incoming.size() == 1 &&
631 itrDaug->pdg_id() == thePart->pdg_id()) {
632 samePart = true;
633 pVert = itrDaug->end_vertex();
634 }
635 }
636 if (samePart) EndVert = pVert;
637 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
638 }
639 return EndVert;
640 }
641
643
644 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
645 if (!theVert) return {};
646 decltype(theVert->particles_out()) finalStatePart;
647 auto outgoing = theVert->particles_out();
648 for (const auto& thePart: outgoing) {
649 if (!thePart) continue;
650 finalStatePart.push_back(thePart);
651 if (isStable(thePart)) continue;
652 V pVert = findSimulatedEndVertex(thePart);
653 if (pVert == theVert) break; // to prevent Sherpa loop
654 if (pVert != nullptr) {
655 auto vecPart = findFinalStateParticles<V>(pVert);
656 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
657 }
658 }
659 return finalStatePart;
660 }
661#if !defined(XAOD_ANALYSIS)
662#include "AtlasHepMC/GenEvent.h"
663inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
664inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
665
666#endif
667}
668#endif

◆ isHiggs() [2/2]

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

APID: HIGGS boson is only one particle.

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

◆ isInteracting()

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

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

Definition at line 34 of file HepMCHelpers.h.

◆ isKK() [1/3]

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

Definition at line 643 of file HepMCHelpers.h.

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

◆ isKK() [2/3]

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

Definition at line 644 of file HepMCHelpers.h.

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

◆ isKK() [3/3]

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

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

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

Definition at line 642 of file HepMCHelpers.h.

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

◆ isLepton() [1/3]

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

Definition at line 198 of file HepMCHelpers.h.

◆ isLepton() [2/3]

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

Definition at line 197 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 196 of file HepMCHelpers.h.

◆ isLeptoQuark() [1/2]

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

Definition at line 416 of file HepMCHelpers.h.

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

◆ isLeptoQuark() [2/2]

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

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

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

Definition at line 415 of file HepMCHelpers.h.

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

◆ isLightBaryon()

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

Definition at line 938 of file HepMCHelpers.h.

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

◆ isLightHadron()

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

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

◆ isLightMeson()

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

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

◆ isMeson() [1/3]

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

Definition at line 252 of file HepMCHelpers.h.

257 {
258 auto vecPart = findFinalStateParticles<V>(pVert);
259 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
260 }
261 }
262 return finalStatePart;
263 }
264#if !defined(XAOD_ANALYSIS)
265#include "AtlasHepMC/GenEvent.h"
266inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
267inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
268
269#endif
270}
271#endif

◆ isMeson() [2/3]

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

Definition at line 273 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 for ( const auto& p : partOriVert->particles_in() ) {
373 theMoth = p;
374 if (!theMoth) continue;
375 MotherPDG = theMoth->pdg_id();
376 MothOriVert = theMoth->production_vertex();
377 if (MotherPDG == partPDG) break;
378 }
379 itr++;
380 if (itr > 100) {
381 break;
382 }
383 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
384 MothOriVert != partOriVert);
385 return theMoth;
386 }
387
389
390 template <class C, class T> T findMatching(C TruthContainer, T p) {
391 T ptrPart = nullptr;
392 if (!p) return ptrPart;
393 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
394 for (T truthParticle : *TruthContainer) {
395 if (HepMC::is_sim_descendant(p,truthParticle)) {
396 ptrPart = truthParticle;
397 break;
398 }
399 }
400 }
401 else {
402 for (T truthParticle : TruthContainer) {
403 if (HepMC::is_sim_descendant(p,truthParticle)) {
404 ptrPart = truthParticle;
405 break;
406 }
407 }
408 }
409 return ptrPart;
410 }
412
413 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
414 auto prodVtx = thePart->production_vertex();
415 if (!prodVtx) return;
416 for (const auto& theMother: prodVtx->particles_in()) {
417 if (!theMother) continue;
418 allancestors.insert(theMother);
419 findParticleAncestors(theMother, allancestors);
420 }
421 }
422
424
425 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
426 auto endVtx = thePart->end_vertex();
427 if (!endVtx) return;
428 for (const auto& theDaughter: endVtx->particles_out()) {
429 if (!theDaughter) continue;
430 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
431 allstabledescendants.insert(theDaughter);
432 }
433 findParticleStableDescendants(theDaughter, allstabledescendants);
434 }
435 }
436
440
441 template <class T> bool isHardScatteringVertex(T pVert) {
442 if (pVert == nullptr) return false;
443 T pV = pVert;
444 int numOfPartIn(0);
445 int pdg(0);
446
447 do {
448 pVert = pV;
449 auto incoming = pVert->particles_in();
450 numOfPartIn = incoming.size();
451 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
452 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
453
454 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
455
456 if (numOfPartIn == 2) {
457 auto incoming = pVert->particles_in();
458 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
459 }
460 return false;
461}
462
466
467 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
468 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
469 auto vtx = p->production_vertex();
470 if (!vtx) return false;
471 bool fromHad = false;
472 for ( const auto& parent : vtx->particles_in() ) {
473 if (!parent) continue;
474 // should this really go into parton-level territory?
475 // probably depends where BSM particles are being decayed
476 fromBSM |= isBSM(parent);
477 if (!isPhysical(parent)) return false;
478 fromTau |= isTau(parent);
479 if (isHadron(parent)&&!isBeam(parent)) {
480 if (!hadron) hadron = parent; // assumes linear hadron parentage
481 return true;
482 }
483 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
484 }
485 return fromHad;
486 }
487
490
491 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
492 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
493 decltype(thePart->end_vertex()) pVert(nullptr);
494 if (EndVert != nullptr) {
495 do {
496 bool samePart = false;
497 pVert = nullptr;
498 auto outgoing = EndVert->particles_out();
499 auto incoming = EndVert->particles_in();
500 for (const auto& itrDaug: outgoing) {
501 if (!itrDaug) continue;
502 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
503 // brem on generator level for tau
504 (outgoing.size() == 1 && incoming.size() == 1 &&
506 itrDaug->pdg_id() == thePart->pdg_id()) {
507 samePart = true;
508 pVert = itrDaug->end_vertex();
509 }
510 }
511 if (samePart) EndVert = pVert;
512 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
513 }
514 return EndVert;
515 }
516
518
519 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
520 if (!theVert) return {};
521 decltype(theVert->particles_out()) finalStatePart;
522 auto outgoing = theVert->particles_out();
523 for (const auto& thePart: outgoing) {
524 if (!thePart) continue;
525 finalStatePart.push_back(thePart);
526 if (isStable(thePart)) continue;
527 V pVert = findSimulatedEndVertex(thePart);
528 if (pVert == theVert) break; // to prevent Sherpa loop
529 if (pVert != nullptr) {
530 auto vecPart = findFinalStateParticles<V>(pVert);
531 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
532 }
533 }
534 return finalStatePart;
535 }
536#if !defined(XAOD_ANALYSIS)
537#include "AtlasHepMC/GenEvent.h"
538inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
539inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
540
541#endif
542}
543#endif

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

251: outgoing) {

◆ isMonopole() [1/3]

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

Definition at line 653 of file HepMCHelpers.h.

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

◆ isMonopole() [2/3]

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

Definition at line 654 of file HepMCHelpers.h.

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

◆ isMonopole() [3/3]

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

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

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

Definition at line 652 of file HepMCHelpers.h.

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

◆ isMSSMHiggs() [1/2]

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

Definition at line 402 of file HepMCHelpers.h.

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

◆ isMSSMHiggs() [2/2]

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

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

Definition at line 401 of file HepMCHelpers.h.

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

◆ isMuon() [1/2]

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

Definition at line 213 of file HepMCHelpers.h.

◆ isMuon() [2/2]

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

Definition at line 212 of file HepMCHelpers.h.

◆ isNeutral() [1/3]

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

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

◆ isNeutral() [2/3]

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

Definition at line 1098 of file HepMCHelpers.h.

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

◆ isNeutral() [3/3]

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

Definition at line 1096 of file HepMCHelpers.h.

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

◆ isNeutrino() [1/2]

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

Definition at line 220 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 219 of file HepMCHelpers.h.

219{

◆ isNeutrinoRH() [1/2]

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

Definition at line 428 of file HepMCHelpers.h.

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

◆ isNeutrinoRH() [2/2]

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

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

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

Definition at line 427 of file HepMCHelpers.h.

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

◆ isNucleus() [1/3]

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

Definition at line 710 of file HepMCHelpers.h.

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

◆ isNucleus() [2/3]

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

Definition at line 719 of file HepMCHelpers.h.

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

◆ isNucleus() [3/3]

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

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

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

Definition at line 709 of file HepMCHelpers.h.

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

◆ isParton()

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

Definition at line 1114 of file HepMCHelpers.h.

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

◆ isPentaquark() [1/3]

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

Definition at line 350 of file HepMCHelpers.h.

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

◆ isPentaquark() [2/3]

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

Definition at line 355 of file HepMCHelpers.h.

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

◆ isPentaquark() [3/3]

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

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

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

Definition at line 349 of file HepMCHelpers.h.

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

◆ isPhoton() [1/2]

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

Definition at line 384 of file HepMCHelpers.h.

403{
404 namespace Pythia8
405 {
407 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
408
409 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
410
411 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
412 }
413
414#include "AtlasPID.h"
415
417 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
418
420 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
421
423 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
424
426 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
427
429 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
430
432 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
433
435 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
436
438 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
439
441 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
442
444 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
445
449 template <class T> inline bool isStableOrSimDecayed(const T& p) {
450 const auto vertex = p->end_vertex();
451 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
452 }
453
455 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
456
458 template <class T> inline bool isSpecialNonInteracting(const T& p) {
459 const int apid = std::abs(p->pdg_id());
460 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
461 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
462 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
463 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
464 return false;
465 }
466
468
469 template <class T> T findMother(T thePart) {
470 auto partOriVert = thePart->production_vertex();
471 if (!partOriVert) return nullptr;
472
473 long partPDG = thePart->pdg_id();
474 long MotherPDG(0);
475
476 auto MothOriVert = partOriVert;
477 MothOriVert = nullptr;
478 T theMoth(nullptr);
479
480 size_t itr = 0;
481 do {
482 if (itr != 0) partOriVert = MothOriVert;
483 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
579 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
580 auto vtx = p->production_vertex();
581 if (!vtx) return false;
582 bool fromHad = false;
583 for ( const auto& parent : vtx->particles_in() ) {
584 if (!parent) continue;
585 // should this really go into parton-level territory?
586 // probably depends where BSM particles are being decayed
587 fromBSM |= isBSM(parent);
588 if (!isPhysical(parent)) return false;
589 fromTau |= isTau(parent);
590 if (isHadron(parent)&&!isBeam(parent)) {
591 if (!hadron) hadron = parent; // assumes linear hadron parentage
592 return true;
593 }
594 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
595 }
596 return fromHad;
597 }
598
601
602 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
603 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
604 decltype(thePart->end_vertex()) pVert(nullptr);
605 if (EndVert != nullptr) {
606 do {
607 bool samePart = false;
608 pVert = nullptr;
609 auto outgoing = EndVert->particles_out();
610 auto incoming = EndVert->particles_in();
611 for (const auto& itrDaug: outgoing) {
612 if (!itrDaug) continue;
613 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
614 // brem on generator level for tau
615 (outgoing.size() == 1 && incoming.size() == 1 &&
617 itrDaug->pdg_id() == thePart->pdg_id()) {
618 samePart = true;
619 pVert = itrDaug->end_vertex();
620 }
621 }
622 if (samePart) EndVert = pVert;
623 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
624 }
625 return EndVert;
626 }
627
629
630 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
631 if (!theVert) return {};
632 decltype(theVert->particles_out()) finalStatePart;
633 auto outgoing = theVert->particles_out();
634 for (const auto& thePart: outgoing) {
635 if (!thePart) continue;
636 finalStatePart.push_back(thePart);
637 if (isStable(thePart)) continue;
638 V pVert = findSimulatedEndVertex(thePart);
639 if (pVert == theVert) break; // to prevent Sherpa loop
640 if (pVert != nullptr) {
641 auto vecPart = findFinalStateParticles<V>(pVert);
642 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
643 }
644 }
645 return finalStatePart;
646 }
647#if !defined(XAOD_ANALYSIS)
648#include "AtlasHepMC/GenEvent.h"
649inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
650inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
651
652#endif
653}
654#endif

◆ isPhoton() [2/2]

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

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

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

◆ isPythia8Specific() [1/3]

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

Definition at line 419 of file HepMCHelpers.h.

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

◆ isPythia8Specific() [2/3]

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

Definition at line 420 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 for ( const auto& p : partOriVert->particles_in() ) {
520 theMoth = p;
521 if (!theMoth) continue;
522 MotherPDG = theMoth->pdg_id();
523 MothOriVert = theMoth->production_vertex();
524 if (MotherPDG == partPDG) break;
525 }
526 itr++;
527 if (itr > 100) {
528 break;
529 }
530 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
531 MothOriVert != partOriVert);
532 return theMoth;
533 }
534
536
537 template <class C, class T> T findMatching(C TruthContainer, T p) {
538 T ptrPart = nullptr;
539 if (!p) return ptrPart;
540 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
541 for (T truthParticle : *TruthContainer) {
542 if (HepMC::is_sim_descendant(p,truthParticle)) {
543 ptrPart = truthParticle;
544 break;
545 }
546 }
547 }
548 else {
549 for (T truthParticle : TruthContainer) {
550 if (HepMC::is_sim_descendant(p,truthParticle)) {
551 ptrPart = truthParticle;
552 break;
553 }
554 }
555 }
556 return ptrPart;
557 }
559
560 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
561 auto prodVtx = thePart->production_vertex();
562 if (!prodVtx) return;
563 for (const auto& theMother: prodVtx->particles_in()) {
564 if (!theMother) continue;
565 allancestors.insert(theMother);
566 findParticleAncestors(theMother, allancestors);
567 }
568 }
569
571
572 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
573 auto endVtx = thePart->end_vertex();
574 if (!endVtx) return;
575 for (const auto& theDaughter: endVtx->particles_out()) {
576 if (!theDaughter) continue;
577 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
578 allstabledescendants.insert(theDaughter);
579 }
580 findParticleStableDescendants(theDaughter, allstabledescendants);
581 }
582 }
583
587
588 template <class T> bool isHardScatteringVertex(T pVert) {
589 if (pVert == nullptr) return false;
590 T pV = pVert;
591 int numOfPartIn(0);
592 int pdg(0);
593
594 do {
595 pVert = pV;
596 auto incoming = pVert->particles_in();
597 numOfPartIn = incoming.size();
598 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
599 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
600
601 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
602
603 if (numOfPartIn == 2) {
604 auto incoming = pVert->particles_in();
605 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
606 }
607 return false;
608}
609
613
614 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
615 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
616 auto vtx = p->production_vertex();
617 if (!vtx) return false;
618 bool fromHad = false;
619 for ( const auto& parent : vtx->particles_in() ) {
620 if (!parent) continue;
621 // should this really go into parton-level territory?
622 // probably depends where BSM particles are being decayed
623 fromBSM |= isBSM(parent);
624 if (!isPhysical(parent)) return false;
625 fromTau |= isTau(parent);
626 if (isHadron(parent)&&!isBeam(parent)) {
627 if (!hadron) hadron = parent; // assumes linear hadron parentage
628 return true;
629 }
630 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
631 }
632 return fromHad;
633 }
634
637
638 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
639 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
640 decltype(thePart->end_vertex()) pVert(nullptr);
641 if (EndVert != nullptr) {
642 do {
643 bool samePart = false;
644 pVert = nullptr;
645 auto outgoing = EndVert->particles_out();
646 auto incoming = EndVert->particles_in();
647 for (const auto& itrDaug: outgoing) {
648 if (!itrDaug) continue;
649 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
650 // brem on generator level for tau
651 (outgoing.size() == 1 && incoming.size() == 1 &&
653 itrDaug->pdg_id() == thePart->pdg_id()) {
654 samePart = true;
655 pVert = itrDaug->end_vertex();
656 }
657 }
658 if (samePart) EndVert = pVert;
659 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
660 }
661 return EndVert;
662 }
663
665
666 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
667 if (!theVert) return {};
668 decltype(theVert->particles_out()) finalStatePart;
669 auto outgoing = theVert->particles_out();
670 for (const auto& thePart: outgoing) {
671 if (!thePart) continue;
672 finalStatePart.push_back(thePart);
673 if (isStable(thePart)) continue;
674 V pVert = findSimulatedEndVertex(thePart);
675 if (pVert == theVert) break; // to prevent Sherpa loop
676 if (pVert != nullptr) {
677 auto vecPart = findFinalStateParticles<V>(pVert);
678 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
679 }
680 }
681 return finalStatePart;
682 }
683#if !defined(XAOD_ANALYSIS)
684#include "AtlasHepMC/GenEvent.h"
685inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
686inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
687
688#endif
689}
690#endif

◆ isPythia8Specific() [3/3]

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

Definition at line 418 of file HepMCHelpers.h.

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

◆ isQuark() [1/3]

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

Definition at line 176 of file HepMCHelpers.h.

◆ isQuark() [2/3]

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

Definition at line 175 of file HepMCHelpers.h.

175{

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

◆ isQuarkonium() [1/3]

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

Definition at line 281 of file HepMCHelpers.h.

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

◆ isQuarkonium() [2/3]

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

Definition at line 285 of file HepMCHelpers.h.

304{
305 namespace Pythia8
306 {
308 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
309
310 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
311
312 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
313 }
314
315#include "AtlasPID.h"
316
318 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
319
321 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
322
324 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
325
327 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
328
330 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
331
333 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
334
336 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
337
339 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
340
342 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
343
345 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
346
350 template <class T> inline bool isStableOrSimDecayed(const T& p) {
351 const auto vertex = p->end_vertex();
352 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
353 }
354
356 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
357
359 template <class T> inline bool isSpecialNonInteracting(const T& p) {
360 const int apid = std::abs(p->pdg_id());
361 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
362 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
363 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
364 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
365 return false;
366 }
367
369
370 template <class T> T findMother(T thePart) {
371 auto partOriVert = thePart->production_vertex();
372 if (!partOriVert) return nullptr;
373
374 long partPDG = thePart->pdg_id();
375 long MotherPDG(0);
376
377 auto MothOriVert = partOriVert;
378 MothOriVert = nullptr;
379 T theMoth(nullptr);
380
381 size_t itr = 0;
382 do {
383 if (itr != 0) partOriVert = MothOriVert;
384 for ( const auto& p : partOriVert->particles_in() ) {
385 theMoth = p;
386 if (!theMoth) continue;
387 MotherPDG = theMoth->pdg_id();
388 MothOriVert = theMoth->production_vertex();
389 if (MotherPDG == partPDG) break;
390 }
391 itr++;
392 if (itr > 100) {
393 break;
394 }
395 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
396 MothOriVert != partOriVert);
397 return theMoth;
398 }
399
401
402 template <class C, class T> T findMatching(C TruthContainer, T p) {
403 T ptrPart = nullptr;
404 if (!p) return ptrPart;
405 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
406 for (T truthParticle : *TruthContainer) {
407 if (HepMC::is_sim_descendant(p,truthParticle)) {
408 ptrPart = truthParticle;
409 break;
410 }
411 }
412 }
413 else {
414 for (T truthParticle : TruthContainer) {
415 if (HepMC::is_sim_descendant(p,truthParticle)) {
416 ptrPart = truthParticle;
417 break;
418 }
419 }
420 }
421 return ptrPart;
422 }
424
425 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
426 auto prodVtx = thePart->production_vertex();
427 if (!prodVtx) return;
428 for (const auto& theMother: prodVtx->particles_in()) {
429 if (!theMother) continue;
430 allancestors.insert(theMother);
431 findParticleAncestors(theMother, allancestors);
432 }
433 }
434
436
437 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
438 auto endVtx = thePart->end_vertex();
439 if (!endVtx) return;
440 for (const auto& theDaughter: endVtx->particles_out()) {
441 if (!theDaughter) continue;
442 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
443 allstabledescendants.insert(theDaughter);
444 }
445 findParticleStableDescendants(theDaughter, allstabledescendants);
446 }
447 }
448
452
453 template <class T> bool isHardScatteringVertex(T pVert) {
454 if (pVert == nullptr) return false;
455 T pV = pVert;
456 int numOfPartIn(0);
457 int pdg(0);
458
459 do {
460 pVert = pV;
461 auto incoming = pVert->particles_in();
462 numOfPartIn = incoming.size();
463 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
464 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
465
466 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
467
468 if (numOfPartIn == 2) {
469 auto incoming = pVert->particles_in();
470 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
471 }
472 return false;
473}
474
478
479 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
480 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
481 auto vtx = p->production_vertex();
482 if (!vtx) return false;
483 bool fromHad = false;
484 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
549#include "AtlasHepMC/GenEvent.h"
550inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
551inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
552
553#endif
554}
555#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 280 of file HepMCHelpers.h.

299{
300 namespace Pythia8
301 {
303 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
304
305 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
306
307 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
308 }
309
310#include "AtlasPID.h"
311
313 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
314
316 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
317
319 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
320
322 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
323
325 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
326
328 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
329
331 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
332
334 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
335
337 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
338
340 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
341
345 template <class T> inline bool isStableOrSimDecayed(const T& p) {
346 const auto vertex = p->end_vertex();
347 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
348 }
349
351 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
352
354 template <class T> inline bool isSpecialNonInteracting(const T& p) {
355 const int apid = std::abs(p->pdg_id());
356 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
357 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
358 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
359 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
360 return false;
361 }
362
364
365 template <class T> T findMother(T thePart) {
366 auto partOriVert = thePart->production_vertex();
367 if (!partOriVert) return nullptr;
368
369 long partPDG = thePart->pdg_id();
370 long MotherPDG(0);
371
372 auto MothOriVert = partOriVert;
373 MothOriVert = nullptr;
374 T theMoth(nullptr);
375
376 size_t itr = 0;
377 do {
378 if (itr != 0) partOriVert = MothOriVert;
379 for ( const auto& p : partOriVert->particles_in() ) {
380 theMoth = p;
381 if (!theMoth) continue;
382 MotherPDG = theMoth->pdg_id();
383 MothOriVert = theMoth->production_vertex();
384 if (MotherPDG == partPDG) break;
385 }
386 itr++;
387 if (itr > 100) {
388 break;
389 }
390 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
391 MothOriVert != partOriVert);
392 return theMoth;
393 }
394
396
397 template <class C, class T> T findMatching(C TruthContainer, T p) {
398 T ptrPart = nullptr;
399 if (!p) return ptrPart;
400 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
401 for (T truthParticle : *TruthContainer) {
402 if (HepMC::is_sim_descendant(p,truthParticle)) {
403 ptrPart = truthParticle;
404 break;
405 }
406 }
407 }
408 else {
409 for (T truthParticle : TruthContainer) {
410 if (HepMC::is_sim_descendant(p,truthParticle)) {
411 ptrPart = truthParticle;
412 break;
413 }
414 }
415 }
416 return ptrPart;
417 }
419
420 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
421 auto prodVtx = thePart->production_vertex();
422 if (!prodVtx) return;
423 for (const auto& theMother: prodVtx->particles_in()) {
424 if (!theMother) continue;
425 allancestors.insert(theMother);
426 findParticleAncestors(theMother, allancestors);
427 }
428 }
429
431
432 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
433 auto endVtx = thePart->end_vertex();
434 if (!endVtx) return;
435 for (const auto& theDaughter: endVtx->particles_out()) {
436 if (!theDaughter) continue;
437 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
438 allstabledescendants.insert(theDaughter);
439 }
440 findParticleStableDescendants(theDaughter, allstabledescendants);
441 }
442 }
443
447
448 template <class T> bool isHardScatteringVertex(T pVert) {
449 if (pVert == nullptr) return false;
450 T pV = pVert;
451 int numOfPartIn(0);
452 int pdg(0);
453
454 do {
455 pVert = pV;
456 auto incoming = pVert->particles_in();
457 numOfPartIn = incoming.size();
458 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
459 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
460
461 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
462
463 if (numOfPartIn == 2) {
464 auto incoming = pVert->particles_in();
465 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
466 }
467 return false;
468}
469
473
474 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
475 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
476 auto vtx = p->production_vertex();
477 if (!vtx) return false;
478 bool fromHad = false;
479 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
544#include "AtlasHepMC/GenEvent.h"
545inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
546inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
547
548#endif
549}
550#endif

◆ isRBaryon() [1/3]

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

Definition at line 597 of file HepMCHelpers.h.

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

◆ isRBaryon() [2/3]

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

Definition at line 607 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 for ( const auto& p : partOriVert->particles_in() ) {
707 theMoth = p;
708 if (!theMoth) continue;
709 MotherPDG = theMoth->pdg_id();
710 MothOriVert = theMoth->production_vertex();
711 if (MotherPDG == partPDG) break;
712 }
713 itr++;
714 if (itr > 100) {
715 break;
716 }
717 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
718 MothOriVert != partOriVert);
719 return theMoth;
720 }
721
723
724 template <class C, class T> T findMatching(C TruthContainer, T p) {
725 T ptrPart = nullptr;
726 if (!p) return ptrPart;
727 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
728 for (T truthParticle : *TruthContainer) {
729 if (HepMC::is_sim_descendant(p,truthParticle)) {
730 ptrPart = truthParticle;
731 break;
732 }
733 }
734 }
735 else {
736 for (T truthParticle : TruthContainer) {
737 if (HepMC::is_sim_descendant(p,truthParticle)) {
738 ptrPart = truthParticle;
739 break;
740 }
741 }
742 }
743 return ptrPart;
744 }
746
747 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
748 auto prodVtx = thePart->production_vertex();
749 if (!prodVtx) return;
750 for (const auto& theMother: prodVtx->particles_in()) {
751 if (!theMother) continue;
752 allancestors.insert(theMother);
753 findParticleAncestors(theMother, allancestors);
754 }
755 }
756
758
759 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
760 auto endVtx = thePart->end_vertex();
761 if (!endVtx) return;
762 for (const auto& theDaughter: endVtx->particles_out()) {
763 if (!theDaughter) continue;
764 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
765 allstabledescendants.insert(theDaughter);
766 }
767 findParticleStableDescendants(theDaughter, allstabledescendants);
768 }
769 }
770
774
775 template <class T> bool isHardScatteringVertex(T pVert) {
776 if (pVert == nullptr) return false;
777 T pV = pVert;
778 int numOfPartIn(0);
779 int pdg(0);
780
781 do {
782 pVert = pV;
783 auto incoming = pVert->particles_in();
784 numOfPartIn = incoming.size();
785 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
786 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
787
788 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
789
790 if (numOfPartIn == 2) {
791 auto incoming = pVert->particles_in();
792 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
793 }
794 return false;
795}
796
800
801 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
802 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
803 auto vtx = p->production_vertex();
804 if (!vtx) return false;
805 bool fromHad = false;
806 for ( const auto& parent : vtx->particles_in() ) {
807 if (!parent) continue;
808 // should this really go into parton-level territory?
809 // probably depends where BSM particles are being decayed
810 fromBSM |= isBSM(parent);
811 if (!isPhysical(parent)) return false;
812 fromTau |= isTau(parent);
813 if (isHadron(parent)&&!isBeam(parent)) {
814 if (!hadron) hadron = parent; // assumes linear hadron parentage
815 return true;
816 }
817 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
818 }
819 return fromHad;
820 }
821
824
825 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
826 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
827 decltype(thePart->end_vertex()) pVert(nullptr);
828 if (EndVert != nullptr) {
829 do {
830 bool samePart = false;
831 pVert = nullptr;
832 auto outgoing = EndVert->particles_out();
833 auto incoming = EndVert->particles_in();
834 for (const auto& itrDaug: outgoing) {
835 if (!itrDaug) continue;
836 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
837 // brem on generator level for tau
838 (outgoing.size() == 1 && incoming.size() == 1 &&
840 itrDaug->pdg_id() == thePart->pdg_id()) {
841 samePart = true;
842 pVert = itrDaug->end_vertex();
843 }
844 }
845 if (samePart) EndVert = pVert;
846 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
847 }
848 return EndVert;
849 }
850
852
853 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
854 if (!theVert) return {};
855 decltype(theVert->particles_out()) finalStatePart;
856 auto outgoing = theVert->particles_out();
857 for (const auto& thePart: outgoing) {
858 if (!thePart) continue;
859 finalStatePart.push_back(thePart);
860 if (isStable(thePart)) continue;
861 V pVert = findSimulatedEndVertex(thePart);
862 if (pVert == theVert) break; // to prevent Sherpa loop
863 if (pVert != nullptr) {
864 auto vecPart = findFinalStateParticles<V>(pVert);
865 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
866 }
867 }
868 return finalStatePart;
869 }
870#if !defined(XAOD_ANALYSIS)
871#include "AtlasHepMC/GenEvent.h"
872inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
873inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
874
875#endif
876}
877#endif

◆ isRBaryon() [3/3]

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

Definition at line 596 of file HepMCHelpers.h.

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

◆ isResonance()

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

Definition at line 407 of file HepMCHelpers.h.

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

◆ isRGlueball() [1/3]

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

Definition at line 570 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 for ( const auto& p : partOriVert->particles_in() ) {
670 theMoth = p;
671 if (!theMoth) continue;
672 MotherPDG = theMoth->pdg_id();
673 MothOriVert = theMoth->production_vertex();
674 if (MotherPDG == partPDG) break;
675 }
676 itr++;
677 if (itr > 100) {
678 break;
679 }
680 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
681 MothOriVert != partOriVert);
682 return theMoth;
683 }
684
686
687 template <class C, class T> T findMatching(C TruthContainer, T p) {
688 T ptrPart = nullptr;
689 if (!p) return ptrPart;
690 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
691 for (T truthParticle : *TruthContainer) {
692 if (HepMC::is_sim_descendant(p,truthParticle)) {
693 ptrPart = truthParticle;
694 break;
695 }
696 }
697 }
698 else {
699 for (T truthParticle : TruthContainer) {
700 if (HepMC::is_sim_descendant(p,truthParticle)) {
701 ptrPart = truthParticle;
702 break;
703 }
704 }
705 }
706 return ptrPart;
707 }
709
710 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
711 auto prodVtx = thePart->production_vertex();
712 if (!prodVtx) return;
713 for (const auto& theMother: prodVtx->particles_in()) {
714 if (!theMother) continue;
715 allancestors.insert(theMother);
716 findParticleAncestors(theMother, allancestors);
717 }
718 }
719
721
722 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
723 auto endVtx = thePart->end_vertex();
724 if (!endVtx) return;
725 for (const auto& theDaughter: endVtx->particles_out()) {
726 if (!theDaughter) continue;
727 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
728 allstabledescendants.insert(theDaughter);
729 }
730 findParticleStableDescendants(theDaughter, allstabledescendants);
731 }
732 }
733
737
738 template <class T> bool isHardScatteringVertex(T pVert) {
739 if (pVert == nullptr) return false;
740 T pV = pVert;
741 int numOfPartIn(0);
742 int pdg(0);
743
744 do {
745 pVert = pV;
746 auto incoming = pVert->particles_in();
747 numOfPartIn = incoming.size();
748 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
749 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
750
751 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
752
753 if (numOfPartIn == 2) {
754 auto incoming = pVert->particles_in();
755 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
756 }
757 return false;
758}
759
763
764 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
765 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
766 auto vtx = p->production_vertex();
767 if (!vtx) return false;
768 bool fromHad = false;
769 for ( const auto& parent : vtx->particles_in() ) {
770 if (!parent) continue;
771 // should this really go into parton-level territory?
772 // probably depends where BSM particles are being decayed
773 fromBSM |= isBSM(parent);
774 if (!isPhysical(parent)) return false;
775 fromTau |= isTau(parent);
776 if (isHadron(parent)&&!isBeam(parent)) {
777 if (!hadron) hadron = parent; // assumes linear hadron parentage
778 return true;
779 }
780 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
781 }
782 return fromHad;
783 }
784
787
788 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
789 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
790 decltype(thePart->end_vertex()) pVert(nullptr);
791 if (EndVert != nullptr) {
792 do {
793 bool samePart = false;
794 pVert = nullptr;
795 auto outgoing = EndVert->particles_out();
796 auto incoming = EndVert->particles_in();
797 for (const auto& itrDaug: outgoing) {
798 if (!itrDaug) continue;
799 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
800 // brem on generator level for tau
801 (outgoing.size() == 1 && incoming.size() == 1 &&
803 itrDaug->pdg_id() == thePart->pdg_id()) {
804 samePart = true;
805 pVert = itrDaug->end_vertex();
806 }
807 }
808 if (samePart) EndVert = pVert;
809 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
810 }
811 return EndVert;
812 }
813
815
816 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
817 if (!theVert) return {};
818 decltype(theVert->particles_out()) finalStatePart;
819 auto outgoing = theVert->particles_out();
820 for (const auto& thePart: outgoing) {
821 if (!thePart) continue;
822 finalStatePart.push_back(thePart);
823 if (isStable(thePart)) continue;
824 V pVert = findSimulatedEndVertex(thePart);
825 if (pVert == theVert) break; // to prevent Sherpa loop
826 if (pVert != nullptr) {
827 auto vecPart = findFinalStateParticles<V>(pVert);
828 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
829 }
830 }
831 return finalStatePart;
832 }
833#if !defined(XAOD_ANALYSIS)
834#include "AtlasHepMC/GenEvent.h"
835inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
836inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
837
838#endif
839}
840#endif

◆ isRGlueball() [2/3]

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

Definition at line 577 of file HepMCHelpers.h.

596{
597 namespace Pythia8
598 {
600 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
601
602 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
603
604 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
605 }
606
607#include "AtlasPID.h"
608
610 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
611
613 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
614
616 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
617
619 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
620
622 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
623
625 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
626
628 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
629
631 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
632
634 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
635
637 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
638
642 template <class T> inline bool isStableOrSimDecayed(const T& p) {
643 const auto vertex = p->end_vertex();
644 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
645 }
646
648 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
649
651 template <class T> inline bool isSpecialNonInteracting(const T& p) {
652 const int apid = std::abs(p->pdg_id());
653 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
654 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
655 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
656 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
657 return false;
658 }
659
661
662 template <class T> T findMother(T thePart) {
663 auto partOriVert = thePart->production_vertex();
664 if (!partOriVert) return nullptr;
665
666 long partPDG = thePart->pdg_id();
667 long MotherPDG(0);
668
669 auto MothOriVert = partOriVert;
670 MothOriVert = nullptr;
671 T theMoth(nullptr);
672
673 size_t itr = 0;
674 do {
675 if (itr != 0) partOriVert = MothOriVert;
676 for ( const auto& p : partOriVert->particles_in() ) {
677 theMoth = p;
678 if (!theMoth) continue;
679 MotherPDG = theMoth->pdg_id();
680 MothOriVert = theMoth->production_vertex();
681 if (MotherPDG == partPDG) break;
682 }
683 itr++;
684 if (itr > 100) {
685 break;
686 }
687 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
688 MothOriVert != partOriVert);
689 return theMoth;
690 }
691
693
694 template <class C, class T> T findMatching(C TruthContainer, T p) {
695 T ptrPart = nullptr;
696 if (!p) return ptrPart;
697 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
698 for (T truthParticle : *TruthContainer) {
699 if (HepMC::is_sim_descendant(p,truthParticle)) {
700 ptrPart = truthParticle;
701 break;
702 }
703 }
704 }
705 else {
706 for (T truthParticle : TruthContainer) {
707 if (HepMC::is_sim_descendant(p,truthParticle)) {
708 ptrPart = truthParticle;
709 break;
710 }
711 }
712 }
713 return ptrPart;
714 }
716
717 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
718 auto prodVtx = thePart->production_vertex();
719 if (!prodVtx) return;
720 for (const auto& theMother: prodVtx->particles_in()) {
721 if (!theMother) continue;
722 allancestors.insert(theMother);
723 findParticleAncestors(theMother, allancestors);
724 }
725 }
726
728
729 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
730 auto endVtx = thePart->end_vertex();
731 if (!endVtx) return;
732 for (const auto& theDaughter: endVtx->particles_out()) {
733 if (!theDaughter) continue;
734 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
735 allstabledescendants.insert(theDaughter);
736 }
737 findParticleStableDescendants(theDaughter, allstabledescendants);
738 }
739 }
740
744
745 template <class T> bool isHardScatteringVertex(T pVert) {
746 if (pVert == nullptr) return false;
747 T pV = pVert;
748 int numOfPartIn(0);
749 int pdg(0);
750
751 do {
752 pVert = pV;
753 auto incoming = pVert->particles_in();
754 numOfPartIn = incoming.size();
755 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
756 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
757
758 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
759
760 if (numOfPartIn == 2) {
761 auto incoming = pVert->particles_in();
762 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
763 }
764 return false;
765}
766
770
771 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
772 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
773 auto vtx = p->production_vertex();
774 if (!vtx) return false;
775 bool fromHad = false;
776 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
841#include "AtlasHepMC/GenEvent.h"
842inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
843inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
844
845#endif
846}
847#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 569 of file HepMCHelpers.h.

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

◆ isRHadron() [1/3]

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

Definition at line 611 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
811 if (!parent) continue;
812 // should this really go into parton-level territory?
813 // probably depends where BSM particles are being decayed
814 fromBSM |= isBSM(parent);
815 if (!isPhysical(parent)) return false;
816 fromTau |= isTau(parent);
817 if (isHadron(parent)&&!isBeam(parent)) {
818 if (!hadron) hadron = parent; // assumes linear hadron parentage
819 return true;
820 }
821 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
822 }
823 return fromHad;
824 }
825
828
829 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
830 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
831 decltype(thePart->end_vertex()) pVert(nullptr);
832 if (EndVert != nullptr) {
833 do {
834 bool samePart = false;
835 pVert = nullptr;
836 auto outgoing = EndVert->particles_out();
837 auto incoming = EndVert->particles_in();
838 for (const auto& itrDaug: outgoing) {
839 if (!itrDaug) continue;
840 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
841 // brem on generator level for tau
842 (outgoing.size() == 1 && incoming.size() == 1 &&
844 itrDaug->pdg_id() == thePart->pdg_id()) {
845 samePart = true;
846 pVert = itrDaug->end_vertex();
847 }
848 }
849 if (samePart) EndVert = pVert;
850 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
851 }
852 return EndVert;
853 }
854
856
857 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
858 if (!theVert) return {};
859 decltype(theVert->particles_out()) finalStatePart;
860 auto outgoing = theVert->particles_out();
861 for (const auto& thePart: outgoing) {
862 if (!thePart) continue;
863 finalStatePart.push_back(thePart);
864 if (isStable(thePart)) continue;
865 V pVert = findSimulatedEndVertex(thePart);
866 if (pVert == theVert) break; // to prevent Sherpa loop
867 if (pVert != nullptr) {
868 auto vecPart = findFinalStateParticles<V>(pVert);
869 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
870 }
871 }
872 return finalStatePart;
873 }
874#if !defined(XAOD_ANALYSIS)
875#include "AtlasHepMC/GenEvent.h"
876inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
877inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
878
879#endif
880}
881#endif

◆ isRHadron() [2/3]

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

Definition at line 614 of file HepMCHelpers.h.

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

◆ isRHadron() [3/3]

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

Definition at line 610 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 for ( const auto& p : partOriVert->particles_in() ) {
710 theMoth = p;
711 if (!theMoth) continue;
712 MotherPDG = theMoth->pdg_id();
713 MothOriVert = theMoth->production_vertex();
714 if (MotherPDG == partPDG) break;
715 }
716 itr++;
717 if (itr > 100) {
718 break;
719 }
720 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
721 MothOriVert != partOriVert);
722 return theMoth;
723 }
724
726
727 template <class C, class T> T findMatching(C TruthContainer, T p) {
728 T ptrPart = nullptr;
729 if (!p) return ptrPart;
730 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
731 for (T truthParticle : *TruthContainer) {
732 if (HepMC::is_sim_descendant(p,truthParticle)) {
733 ptrPart = truthParticle;
734 break;
735 }
736 }
737 }
738 else {
739 for (T truthParticle : TruthContainer) {
740 if (HepMC::is_sim_descendant(p,truthParticle)) {
741 ptrPart = truthParticle;
742 break;
743 }
744 }
745 }
746 return ptrPart;
747 }
749
750 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
751 auto prodVtx = thePart->production_vertex();
752 if (!prodVtx) return;
753 for (const auto& theMother: prodVtx->particles_in()) {
754 if (!theMother) continue;
755 allancestors.insert(theMother);
756 findParticleAncestors(theMother, allancestors);
757 }
758 }
759
761
762 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
763 auto endVtx = thePart->end_vertex();
764 if (!endVtx) return;
765 for (const auto& theDaughter: endVtx->particles_out()) {
766 if (!theDaughter) continue;
767 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
768 allstabledescendants.insert(theDaughter);
769 }
770 findParticleStableDescendants(theDaughter, allstabledescendants);
771 }
772 }
773
777
778 template <class T> bool isHardScatteringVertex(T pVert) {
779 if (pVert == nullptr) return false;
780 T pV = pVert;
781 int numOfPartIn(0);
782 int pdg(0);
783
784 do {
785 pVert = pV;
786 auto incoming = pVert->particles_in();
787 numOfPartIn = incoming.size();
788 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
789 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
790
791 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
792
793 if (numOfPartIn == 2) {
794 auto incoming = pVert->particles_in();
795 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
796 }
797 return false;
798}
799
803
804 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
805 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
806 auto vtx = p->production_vertex();
807 if (!vtx) return false;
808 bool fromHad = false;
809 for ( const auto& parent : vtx->particles_in() ) {
810 if (!parent) continue;
811 // should this really go into parton-level territory?
812 // probably depends where BSM particles are being decayed
813 fromBSM |= isBSM(parent);
814 if (!isPhysical(parent)) return false;
815 fromTau |= isTau(parent);
816 if (isHadron(parent)&&!isBeam(parent)) {
817 if (!hadron) hadron = parent; // assumes linear hadron parentage
818 return true;
819 }
820 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
821 }
822 return fromHad;
823 }
824
827
828 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
829 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
830 decltype(thePart->end_vertex()) pVert(nullptr);
831 if (EndVert != nullptr) {
832 do {
833 bool samePart = false;
834 pVert = nullptr;
835 auto outgoing = EndVert->particles_out();
836 auto incoming = EndVert->particles_in();
837 for (const auto& itrDaug: outgoing) {
838 if (!itrDaug) continue;
839 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
840 // brem on generator level for tau
841 (outgoing.size() == 1 && incoming.size() == 1 &&
843 itrDaug->pdg_id() == thePart->pdg_id()) {
844 samePart = true;
845 pVert = itrDaug->end_vertex();
846 }
847 }
848 if (samePart) EndVert = pVert;
849 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
850 }
851 return EndVert;
852 }
853
855
856 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
857 if (!theVert) return {};
858 decltype(theVert->particles_out()) finalStatePart;
859 auto outgoing = theVert->particles_out();
860 for (const auto& thePart: outgoing) {
861 if (!thePart) continue;
862 finalStatePart.push_back(thePart);
863 if (isStable(thePart)) continue;
864 V pVert = findSimulatedEndVertex(thePart);
865 if (pVert == theVert) break; // to prevent Sherpa loop
866 if (pVert != nullptr) {
867 auto vecPart = findFinalStateParticles<V>(pVert);
868 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
869 }
870 }
871 return finalStatePart;
872 }
873#if !defined(XAOD_ANALYSIS)
874#include "AtlasHepMC/GenEvent.h"
875inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
876inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
877
878#endif
879}
880#endif

◆ isRMeson() [1/3]

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

Definition at line 582 of file HepMCHelpers.h.

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

◆ isRMeson() [2/3]

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

Definition at line 592 of file HepMCHelpers.h.

611{
612 namespace Pythia8
613 {
615 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
616
617 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
618
619 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
620 }
621
622#include "AtlasPID.h"
623
625 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
626
628 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
629
631 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
632
634 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
635
637 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
638
640 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
641
643 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
644
646 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
647
649 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
650
652 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
653
657 template <class T> inline bool isStableOrSimDecayed(const T& p) {
658 const auto vertex = p->end_vertex();
659 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
660 }
661
663 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
664
666 template <class T> inline bool isSpecialNonInteracting(const T& p) {
667 const int apid = std::abs(p->pdg_id());
668 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
669 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
670 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
671 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
672 return false;
673 }
674
676
677 template <class T> T findMother(T thePart) {
678 auto partOriVert = thePart->production_vertex();
679 if (!partOriVert) return nullptr;
680
681 long partPDG = thePart->pdg_id();
682 long MotherPDG(0);
683
684 auto MothOriVert = partOriVert;
685 MothOriVert = nullptr;
686 T theMoth(nullptr);
687
688 size_t itr = 0;
689 do {
690 if (itr != 0) partOriVert = MothOriVert;
691 for ( const auto& p : partOriVert->particles_in() ) {
692 theMoth = p;
693 if (!theMoth) continue;
694 MotherPDG = theMoth->pdg_id();
695 MothOriVert = theMoth->production_vertex();
696 if (MotherPDG == partPDG) break;
697 }
698 itr++;
699 if (itr > 100) {
700 break;
701 }
702 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
703 MothOriVert != partOriVert);
704 return theMoth;
705 }
706
708
709 template <class C, class T> T findMatching(C TruthContainer, T p) {
710 T ptrPart = nullptr;
711 if (!p) return ptrPart;
712 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
713 for (T truthParticle : *TruthContainer) {
714 if (HepMC::is_sim_descendant(p,truthParticle)) {
715 ptrPart = truthParticle;
716 break;
717 }
718 }
719 }
720 else {
721 for (T truthParticle : TruthContainer) {
722 if (HepMC::is_sim_descendant(p,truthParticle)) {
723 ptrPart = truthParticle;
724 break;
725 }
726 }
727 }
728 return ptrPart;
729 }
731
732 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
733 auto prodVtx = thePart->production_vertex();
734 if (!prodVtx) return;
735 for (const auto& theMother: prodVtx->particles_in()) {
736 if (!theMother) continue;
737 allancestors.insert(theMother);
738 findParticleAncestors(theMother, allancestors);
739 }
740 }
741
743
744 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
745 auto endVtx = thePart->end_vertex();
746 if (!endVtx) return;
747 for (const auto& theDaughter: endVtx->particles_out()) {
748 if (!theDaughter) continue;
749 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
750 allstabledescendants.insert(theDaughter);
751 }
752 findParticleStableDescendants(theDaughter, allstabledescendants);
753 }
754 }
755
759
760 template <class T> bool isHardScatteringVertex(T pVert) {
761 if (pVert == nullptr) return false;
762 T pV = pVert;
763 int numOfPartIn(0);
764 int pdg(0);
765
766 do {
767 pVert = pV;
768 auto incoming = pVert->particles_in();
769 numOfPartIn = incoming.size();
770 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
771 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
772
773 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
774
775 if (numOfPartIn == 2) {
776 auto incoming = pVert->particles_in();
777 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
778 }
779 return false;
780}
781
785
786 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
787 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
788 auto vtx = p->production_vertex();
789 if (!vtx) return false;
790 bool fromHad = false;
791 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
856#include "AtlasHepMC/GenEvent.h"
857inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
858inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
859
860#endif
861}
862#endif

◆ isRMeson() [3/3]

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

Definition at line 581 of file HepMCHelpers.h.

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

61{ 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 58 of file HepMCHelpers.h.

58{ 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 490 of file HepMCHelpers.h.

509{
510 namespace Pythia8
511 {
513 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
514
515 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
516
517 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
518 }
519
520#include "AtlasPID.h"
521
523 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
524
526 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
527
529 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
530
532 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
533
535 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
536
538 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
539
541 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
542
544 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
545
547 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
548
550 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
551
555 template <class T> inline bool isStableOrSimDecayed(const T& p) {
556 const auto vertex = p->end_vertex();
557 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
558 }
559
561 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
562
564 template <class T> inline bool isSpecialNonInteracting(const T& p) {
565 const int apid = std::abs(p->pdg_id());
566 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
567 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
568 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
569 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
570 return false;
571 }
572
574
575 template <class T> T findMother(T thePart) {
576 auto partOriVert = thePart->production_vertex();
577 if (!partOriVert) return nullptr;
578
579 long partPDG = thePart->pdg_id();
580 long MotherPDG(0);
581
582 auto MothOriVert = partOriVert;
583 MothOriVert = nullptr;
584 T theMoth(nullptr);
585
586 size_t itr = 0;
587 do {
588 if (itr != 0) partOriVert = MothOriVert;
589 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
754#include "AtlasHepMC/GenEvent.h"
755inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
756inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
757
758#endif
759}
760#endif

◆ isSlepton() [2/3]

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

Definition at line 491 of file HepMCHelpers.h.

510{
511 namespace Pythia8
512 {
514 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
515
516 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
517
518 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
519 }
520
521#include "AtlasPID.h"
522
524 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
525
527 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
528
530 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
531
533 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
534
536 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
537
539 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
540
542 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
543
545 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
546
548 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
549
551 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
552
556 template <class T> inline bool isStableOrSimDecayed(const T& p) {
557 const auto vertex = p->end_vertex();
558 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
559 }
560
562 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
563
565 template <class T> inline bool isSpecialNonInteracting(const T& p) {
566 const int apid = std::abs(p->pdg_id());
567 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
568 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
569 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
570 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
571 return false;
572 }
573
575
576 template <class T> T findMother(T thePart) {
577 auto partOriVert = thePart->production_vertex();
578 if (!partOriVert) return nullptr;
579
580 long partPDG = thePart->pdg_id();
581 long MotherPDG(0);
582
583 auto MothOriVert = partOriVert;
584 MothOriVert = nullptr;
585 T theMoth(nullptr);
586
587 size_t itr = 0;
588 do {
589 if (itr != 0) partOriVert = MothOriVert;
590 for ( const auto& p : partOriVert->particles_in() ) {
591 theMoth = p;
592 if (!theMoth) continue;
593 MotherPDG = theMoth->pdg_id();
594 MothOriVert = theMoth->production_vertex();
595 if (MotherPDG == partPDG) break;
596 }
597 itr++;
598 if (itr > 100) {
599 break;
600 }
601 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
602 MothOriVert != partOriVert);
603 return theMoth;
604 }
605
607
608 template <class C, class T> T findMatching(C TruthContainer, T p) {
609 T ptrPart = nullptr;
610 if (!p) return ptrPart;
611 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
612 for (T truthParticle : *TruthContainer) {
613 if (HepMC::is_sim_descendant(p,truthParticle)) {
614 ptrPart = truthParticle;
615 break;
616 }
617 }
618 }
619 else {
620 for (T truthParticle : TruthContainer) {
621 if (HepMC::is_sim_descendant(p,truthParticle)) {
622 ptrPart = truthParticle;
623 break;
624 }
625 }
626 }
627 return ptrPart;
628 }
630
631 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
632 auto prodVtx = thePart->production_vertex();
633 if (!prodVtx) return;
634 for (const auto& theMother: prodVtx->particles_in()) {
635 if (!theMother) continue;
636 allancestors.insert(theMother);
637 findParticleAncestors(theMother, allancestors);
638 }
639 }
640
642
643 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
644 auto endVtx = thePart->end_vertex();
645 if (!endVtx) return;
646 for (const auto& theDaughter: endVtx->particles_out()) {
647 if (!theDaughter) continue;
648 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
649 allstabledescendants.insert(theDaughter);
650 }
651 findParticleStableDescendants(theDaughter, allstabledescendants);
652 }
653 }
654
658
659 template <class T> bool isHardScatteringVertex(T pVert) {
660 if (pVert == nullptr) return false;
661 T pV = pVert;
662 int numOfPartIn(0);
663 int pdg(0);
664
665 do {
666 pVert = pV;
667 auto incoming = pVert->particles_in();
668 numOfPartIn = incoming.size();
669 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
670 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
671
672 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
673
674 if (numOfPartIn == 2) {
675 auto incoming = pVert->particles_in();
676 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
677 }
678 return false;
679}
680
684
685 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
686 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
687 auto vtx = p->production_vertex();
688 if (!vtx) return false;
689 bool fromHad = false;
690 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
755#include "AtlasHepMC/GenEvent.h"
756inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
757inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
758
759#endif
760}
761#endif

◆ isSlepton() [3/3]

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

Definition at line 489 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
689 if (!parent) continue;
690 // should this really go into parton-level territory?
691 // probably depends where BSM particles are being decayed
692 fromBSM |= isBSM(parent);
693 if (!isPhysical(parent)) return false;
694 fromTau |= isTau(parent);
695 if (isHadron(parent)&&!isBeam(parent)) {
696 if (!hadron) hadron = parent; // assumes linear hadron parentage
697 return true;
698 }
699 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
700 }
701 return fromHad;
702 }
703
706
707 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
708 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
709 decltype(thePart->end_vertex()) pVert(nullptr);
710 if (EndVert != nullptr) {
711 do {
712 bool samePart = false;
713 pVert = nullptr;
714 auto outgoing = EndVert->particles_out();
715 auto incoming = EndVert->particles_in();
716 for (const auto& itrDaug: outgoing) {
717 if (!itrDaug) continue;
718 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
719 // brem on generator level for tau
720 (outgoing.size() == 1 && incoming.size() == 1 &&
722 itrDaug->pdg_id() == thePart->pdg_id()) {
723 samePart = true;
724 pVert = itrDaug->end_vertex();
725 }
726 }
727 if (samePart) EndVert = pVert;
728 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
729 }
730 return EndVert;
731 }
732
734
735 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
736 if (!theVert) return {};
737 decltype(theVert->particles_out()) finalStatePart;
738 auto outgoing = theVert->particles_out();
739 for (const auto& thePart: outgoing) {
740 if (!thePart) continue;
741 finalStatePart.push_back(thePart);
742 if (isStable(thePart)) continue;
743 V pVert = findSimulatedEndVertex(thePart);
744 if (pVert == theVert) break; // to prevent Sherpa loop
745 if (pVert != nullptr) {
746 auto vecPart = findFinalStateParticles<V>(pVert);
747 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
748 }
749 }
750 return finalStatePart;
751 }
752#if !defined(XAOD_ANALYSIS)
753#include "AtlasHepMC/GenEvent.h"
754inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
755inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
756
757#endif
758}
759#endif

◆ isSleptonLH() [1/3]

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

Definition at line 496 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 for ( const auto& p : partOriVert->particles_in() ) {
596 theMoth = p;
597 if (!theMoth) continue;
598 MotherPDG = theMoth->pdg_id();
599 MothOriVert = theMoth->production_vertex();
600 if (MotherPDG == partPDG) break;
601 }
602 itr++;
603 if (itr > 100) {
604 break;
605 }
606 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
607 MothOriVert != partOriVert);
608 return theMoth;
609 }
610
612
613 template <class C, class T> T findMatching(C TruthContainer, T p) {
614 T ptrPart = nullptr;
615 if (!p) return ptrPart;
616 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
617 for (T truthParticle : *TruthContainer) {
618 if (HepMC::is_sim_descendant(p,truthParticle)) {
619 ptrPart = truthParticle;
620 break;
621 }
622 }
623 }
624 else {
625 for (T truthParticle : TruthContainer) {
626 if (HepMC::is_sim_descendant(p,truthParticle)) {
627 ptrPart = truthParticle;
628 break;
629 }
630 }
631 }
632 return ptrPart;
633 }
635
636 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
637 auto prodVtx = thePart->production_vertex();
638 if (!prodVtx) return;
639 for (const auto& theMother: prodVtx->particles_in()) {
640 if (!theMother) continue;
641 allancestors.insert(theMother);
642 findParticleAncestors(theMother, allancestors);
643 }
644 }
645
647
648 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
649 auto endVtx = thePart->end_vertex();
650 if (!endVtx) return;
651 for (const auto& theDaughter: endVtx->particles_out()) {
652 if (!theDaughter) continue;
653 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
654 allstabledescendants.insert(theDaughter);
655 }
656 findParticleStableDescendants(theDaughter, allstabledescendants);
657 }
658 }
659
663
664 template <class T> bool isHardScatteringVertex(T pVert) {
665 if (pVert == nullptr) return false;
666 T pV = pVert;
667 int numOfPartIn(0);
668 int pdg(0);
669
670 do {
671 pVert = pV;
672 auto incoming = pVert->particles_in();
673 numOfPartIn = incoming.size();
674 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
675 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
676
677 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
678
679 if (numOfPartIn == 2) {
680 auto incoming = pVert->particles_in();
681 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
682 }
683 return false;
684}
685
689
690 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
691 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
692 auto vtx = p->production_vertex();
693 if (!vtx) return false;
694 bool fromHad = false;
695 for ( const auto& parent : vtx->particles_in() ) {
696 if (!parent) continue;
697 // should this really go into parton-level territory?
698 // probably depends where BSM particles are being decayed
699 fromBSM |= isBSM(parent);
700 if (!isPhysical(parent)) return false;
701 fromTau |= isTau(parent);
702 if (isHadron(parent)&&!isBeam(parent)) {
703 if (!hadron) hadron = parent; // assumes linear hadron parentage
704 return true;
705 }
706 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
707 }
708 return fromHad;
709 }
710
713
714 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
715 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
716 decltype(thePart->end_vertex()) pVert(nullptr);
717 if (EndVert != nullptr) {
718 do {
719 bool samePart = false;
720 pVert = nullptr;
721 auto outgoing = EndVert->particles_out();
722 auto incoming = EndVert->particles_in();
723 for (const auto& itrDaug: outgoing) {
724 if (!itrDaug) continue;
725 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
726 // brem on generator level for tau
727 (outgoing.size() == 1 && incoming.size() == 1 &&
729 itrDaug->pdg_id() == thePart->pdg_id()) {
730 samePart = true;
731 pVert = itrDaug->end_vertex();
732 }
733 }
734 if (samePart) EndVert = pVert;
735 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
736 }
737 return EndVert;
738 }
739
741
742 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
743 if (!theVert) return {};
744 decltype(theVert->particles_out()) finalStatePart;
745 auto outgoing = theVert->particles_out();
746 for (const auto& thePart: outgoing) {
747 if (!thePart) continue;
748 finalStatePart.push_back(thePart);
749 if (isStable(thePart)) continue;
750 V pVert = findSimulatedEndVertex(thePart);
751 if (pVert == theVert) break; // to prevent Sherpa loop
752 if (pVert != nullptr) {
753 auto vecPart = findFinalStateParticles<V>(pVert);
754 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
755 }
756 }
757 return finalStatePart;
758 }
759#if !defined(XAOD_ANALYSIS)
760#include "AtlasHepMC/GenEvent.h"
761inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
762inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
763
764#endif
765}
766#endif

◆ isSleptonLH() [2/3]

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

Definition at line 499 of file HepMCHelpers.h.

518{
519 namespace Pythia8
520 {
522 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
523
524 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
525
526 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
527 }
528
529#include "AtlasPID.h"
530
532 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
533
535 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
536
538 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
539
541 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
542
544 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
545
547 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
548
550 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
551
553 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
554
556 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
557
559 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
560
564 template <class T> inline bool isStableOrSimDecayed(const T& p) {
565 const auto vertex = p->end_vertex();
566 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
567 }
568
570 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
571
573 template <class T> inline bool isSpecialNonInteracting(const T& p) {
574 const int apid = std::abs(p->pdg_id());
575 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
576 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
577 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
578 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
579 return false;
580 }
581
583
584 template <class T> T findMother(T thePart) {
585 auto partOriVert = thePart->production_vertex();
586 if (!partOriVert) return nullptr;
587
588 long partPDG = thePart->pdg_id();
589 long MotherPDG(0);
590
591 auto MothOriVert = partOriVert;
592 MothOriVert = nullptr;
593 T theMoth(nullptr);
594
595 size_t itr = 0;
596 do {
597 if (itr != 0) partOriVert = MothOriVert;
598 for ( const auto& p : partOriVert->particles_in() ) {
599 theMoth = p;
600 if (!theMoth) continue;
601 MotherPDG = theMoth->pdg_id();
602 MothOriVert = theMoth->production_vertex();
603 if (MotherPDG == partPDG) break;
604 }
605 itr++;
606 if (itr > 100) {
607 break;
608 }
609 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
610 MothOriVert != partOriVert);
611 return theMoth;
612 }
613
615
616 template <class C, class T> T findMatching(C TruthContainer, T p) {
617 T ptrPart = nullptr;
618 if (!p) return ptrPart;
619 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
620 for (T truthParticle : *TruthContainer) {
621 if (HepMC::is_sim_descendant(p,truthParticle)) {
622 ptrPart = truthParticle;
623 break;
624 }
625 }
626 }
627 else {
628 for (T truthParticle : TruthContainer) {
629 if (HepMC::is_sim_descendant(p,truthParticle)) {
630 ptrPart = truthParticle;
631 break;
632 }
633 }
634 }
635 return ptrPart;
636 }
638
639 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
640 auto prodVtx = thePart->production_vertex();
641 if (!prodVtx) return;
642 for (const auto& theMother: prodVtx->particles_in()) {
643 if (!theMother) continue;
644 allancestors.insert(theMother);
645 findParticleAncestors(theMother, allancestors);
646 }
647 }
648
650
651 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
652 auto endVtx = thePart->end_vertex();
653 if (!endVtx) return;
654 for (const auto& theDaughter: endVtx->particles_out()) {
655 if (!theDaughter) continue;
656 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
657 allstabledescendants.insert(theDaughter);
658 }
659 findParticleStableDescendants(theDaughter, allstabledescendants);
660 }
661 }
662
666
667 template <class T> bool isHardScatteringVertex(T pVert) {
668 if (pVert == nullptr) return false;
669 T pV = pVert;
670 int numOfPartIn(0);
671 int pdg(0);
672
673 do {
674 pVert = pV;
675 auto incoming = pVert->particles_in();
676 numOfPartIn = incoming.size();
677 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
678 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
679
680 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
681
682 if (numOfPartIn == 2) {
683 auto incoming = pVert->particles_in();
684 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
685 }
686 return false;
687}
688
692
693 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
694 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
695 auto vtx = p->production_vertex();
696 if (!vtx) return false;
697 bool fromHad = false;
698 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
763#include "AtlasHepMC/GenEvent.h"
764inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
765inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
766
767#endif
768}
769#endif

◆ isSleptonLH() [3/3]

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

Definition at line 495 of file HepMCHelpers.h.

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

◆ isSleptonRH() [1/3]

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

Definition at line 504 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 for ( const auto& p : partOriVert->particles_in() ) {
604 theMoth = p;
605 if (!theMoth) continue;
606 MotherPDG = theMoth->pdg_id();
607 MothOriVert = theMoth->production_vertex();
608 if (MotherPDG == partPDG) break;
609 }
610 itr++;
611 if (itr > 100) {
612 break;
613 }
614 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
615 MothOriVert != partOriVert);
616 return theMoth;
617 }
618
620
621 template <class C, class T> T findMatching(C TruthContainer, T p) {
622 T ptrPart = nullptr;
623 if (!p) return ptrPart;
624 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
625 for (T truthParticle : *TruthContainer) {
626 if (HepMC::is_sim_descendant(p,truthParticle)) {
627 ptrPart = truthParticle;
628 break;
629 }
630 }
631 }
632 else {
633 for (T truthParticle : TruthContainer) {
634 if (HepMC::is_sim_descendant(p,truthParticle)) {
635 ptrPart = truthParticle;
636 break;
637 }
638 }
639 }
640 return ptrPart;
641 }
643
644 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
645 auto prodVtx = thePart->production_vertex();
646 if (!prodVtx) return;
647 for (const auto& theMother: prodVtx->particles_in()) {
648 if (!theMother) continue;
649 allancestors.insert(theMother);
650 findParticleAncestors(theMother, allancestors);
651 }
652 }
653
655
656 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
657 auto endVtx = thePart->end_vertex();
658 if (!endVtx) return;
659 for (const auto& theDaughter: endVtx->particles_out()) {
660 if (!theDaughter) continue;
661 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
662 allstabledescendants.insert(theDaughter);
663 }
664 findParticleStableDescendants(theDaughter, allstabledescendants);
665 }
666 }
667
671
672 template <class T> bool isHardScatteringVertex(T pVert) {
673 if (pVert == nullptr) return false;
674 T pV = pVert;
675 int numOfPartIn(0);
676 int pdg(0);
677
678 do {
679 pVert = pV;
680 auto incoming = pVert->particles_in();
681 numOfPartIn = incoming.size();
682 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
683 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
684
685 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
686
687 if (numOfPartIn == 2) {
688 auto incoming = pVert->particles_in();
689 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
690 }
691 return false;
692}
693
697
698 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
699 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
700 auto vtx = p->production_vertex();
701 if (!vtx) return false;
702 bool fromHad = false;
703 for ( const auto& parent : vtx->particles_in() ) {
704 if (!parent) continue;
705 // should this really go into parton-level territory?
706 // probably depends where BSM particles are being decayed
707 fromBSM |= isBSM(parent);
708 if (!isPhysical(parent)) return false;
709 fromTau |= isTau(parent);
710 if (isHadron(parent)&&!isBeam(parent)) {
711 if (!hadron) hadron = parent; // assumes linear hadron parentage
712 return true;
713 }
714 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
715 }
716 return fromHad;
717 }
718
721
722 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
723 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
724 decltype(thePart->end_vertex()) pVert(nullptr);
725 if (EndVert != nullptr) {
726 do {
727 bool samePart = false;
728 pVert = nullptr;
729 auto outgoing = EndVert->particles_out();
730 auto incoming = EndVert->particles_in();
731 for (const auto& itrDaug: outgoing) {
732 if (!itrDaug) continue;
733 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
734 // brem on generator level for tau
735 (outgoing.size() == 1 && incoming.size() == 1 &&
737 itrDaug->pdg_id() == thePart->pdg_id()) {
738 samePart = true;
739 pVert = itrDaug->end_vertex();
740 }
741 }
742 if (samePart) EndVert = pVert;
743 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
744 }
745 return EndVert;
746 }
747
749
750 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
751 if (!theVert) return {};
752 decltype(theVert->particles_out()) finalStatePart;
753 auto outgoing = theVert->particles_out();
754 for (const auto& thePart: outgoing) {
755 if (!thePart) continue;
756 finalStatePart.push_back(thePart);
757 if (isStable(thePart)) continue;
758 V pVert = findSimulatedEndVertex(thePart);
759 if (pVert == theVert) break; // to prevent Sherpa loop
760 if (pVert != nullptr) {
761 auto vecPart = findFinalStateParticles<V>(pVert);
762 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
763 }
764 }
765 return finalStatePart;
766 }
767#if !defined(XAOD_ANALYSIS)
768#include "AtlasHepMC/GenEvent.h"
769inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
770inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
771
772#endif
773}
774#endif

◆ isSleptonRH() [2/3]

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

Definition at line 507 of file HepMCHelpers.h.

526{
527 namespace Pythia8
528 {
530 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
531
532 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
533
534 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
535 }
536
537#include "AtlasPID.h"
538
540 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
541
543 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
544
546 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
547
549 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
550
552 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
553
555 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
556
558 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
559
561 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
562
564 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
565
567 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
568
572 template <class T> inline bool isStableOrSimDecayed(const T& p) {
573 const auto vertex = p->end_vertex();
574 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
575 }
576
578 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
579
581 template <class T> inline bool isSpecialNonInteracting(const T& p) {
582 const int apid = std::abs(p->pdg_id());
583 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
584 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
585 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
586 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
587 return false;
588 }
589
591
592 template <class T> T findMother(T thePart) {
593 auto partOriVert = thePart->production_vertex();
594 if (!partOriVert) return nullptr;
595
596 long partPDG = thePart->pdg_id();
597 long MotherPDG(0);
598
599 auto MothOriVert = partOriVert;
600 MothOriVert = nullptr;
601 T theMoth(nullptr);
602
603 size_t itr = 0;
604 do {
605 if (itr != 0) partOriVert = MothOriVert;
606 for ( const auto& p : partOriVert->particles_in() ) {
607 theMoth = p;
608 if (!theMoth) continue;
609 MotherPDG = theMoth->pdg_id();
610 MothOriVert = theMoth->production_vertex();
611 if (MotherPDG == partPDG) break;
612 }
613 itr++;
614 if (itr > 100) {
615 break;
616 }
617 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
618 MothOriVert != partOriVert);
619 return theMoth;
620 }
621
623
624 template <class C, class T> T findMatching(C TruthContainer, T p) {
625 T ptrPart = nullptr;
626 if (!p) return ptrPart;
627 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
628 for (T truthParticle : *TruthContainer) {
629 if (HepMC::is_sim_descendant(p,truthParticle)) {
630 ptrPart = truthParticle;
631 break;
632 }
633 }
634 }
635 else {
636 for (T truthParticle : TruthContainer) {
637 if (HepMC::is_sim_descendant(p,truthParticle)) {
638 ptrPart = truthParticle;
639 break;
640 }
641 }
642 }
643 return ptrPart;
644 }
646
647 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
648 auto prodVtx = thePart->production_vertex();
649 if (!prodVtx) return;
650 for (const auto& theMother: prodVtx->particles_in()) {
651 if (!theMother) continue;
652 allancestors.insert(theMother);
653 findParticleAncestors(theMother, allancestors);
654 }
655 }
656
658
659 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
660 auto endVtx = thePart->end_vertex();
661 if (!endVtx) return;
662 for (const auto& theDaughter: endVtx->particles_out()) {
663 if (!theDaughter) continue;
664 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
665 allstabledescendants.insert(theDaughter);
666 }
667 findParticleStableDescendants(theDaughter, allstabledescendants);
668 }
669 }
670
674
675 template <class T> bool isHardScatteringVertex(T pVert) {
676 if (pVert == nullptr) return false;
677 T pV = pVert;
678 int numOfPartIn(0);
679 int pdg(0);
680
681 do {
682 pVert = pV;
683 auto incoming = pVert->particles_in();
684 numOfPartIn = incoming.size();
685 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
686 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
687
688 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
689
690 if (numOfPartIn == 2) {
691 auto incoming = pVert->particles_in();
692 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
693 }
694 return false;
695}
696
700
701 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
702 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
703 auto vtx = p->production_vertex();
704 if (!vtx) return false;
705 bool fromHad = false;
706 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
771#include "AtlasHepMC/GenEvent.h"
772inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
773inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
774
775#endif
776}
777#endif

◆ isSleptonRH() [3/3]

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

Definition at line 503 of file HepMCHelpers.h.

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

◆ isSMLepton() [1/3]

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

Definition at line 203 of file HepMCHelpers.h.

◆ isSMLepton() [2/3]

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

Definition at line 202 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 201 of file HepMCHelpers.h.

◆ isSMNeutrino() [1/2]

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

Definition at line 223 of file HepMCHelpers.h.

223{

◆ isSMNeutrino() [2/2]

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

Definition at line 222 of file HepMCHelpers.h.

222{

◆ isSMQuark() [1/3]

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

Definition at line 181 of file HepMCHelpers.h.

◆ isSMQuark() [2/3]

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

Definition at line 180 of file HepMCHelpers.h.

180: nullptr;

◆ isSMQuark() [3/3]

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

Definition at line 179 of file HepMCHelpers.h.

179: 0;

◆ isSpecialNonInteracting()

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

Identify a special non-interacting particles.

Definition at line 75 of file HepMCHelpers.h.

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

◆ isSquark() [1/3]

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

Definition at line 466 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 for ( const auto& p : partOriVert->particles_in() ) {
566 theMoth = p;
567 if (!theMoth) continue;
568 MotherPDG = theMoth->pdg_id();
569 MothOriVert = theMoth->production_vertex();
570 if (MotherPDG == partPDG) break;
571 }
572 itr++;
573 if (itr > 100) {
574 break;
575 }
576 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
577 MothOriVert != partOriVert);
578 return theMoth;
579 }
580
582
583 template <class C, class T> T findMatching(C TruthContainer, T p) {
584 T ptrPart = nullptr;
585 if (!p) return ptrPart;
586 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
587 for (T truthParticle : *TruthContainer) {
588 if (HepMC::is_sim_descendant(p,truthParticle)) {
589 ptrPart = truthParticle;
590 break;
591 }
592 }
593 }
594 else {
595 for (T truthParticle : TruthContainer) {
596 if (HepMC::is_sim_descendant(p,truthParticle)) {
597 ptrPart = truthParticle;
598 break;
599 }
600 }
601 }
602 return ptrPart;
603 }
605
606 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
607 auto prodVtx = thePart->production_vertex();
608 if (!prodVtx) return;
609 for (const auto& theMother: prodVtx->particles_in()) {
610 if (!theMother) continue;
611 allancestors.insert(theMother);
612 findParticleAncestors(theMother, allancestors);
613 }
614 }
615
617
618 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
619 auto endVtx = thePart->end_vertex();
620 if (!endVtx) return;
621 for (const auto& theDaughter: endVtx->particles_out()) {
622 if (!theDaughter) continue;
623 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
624 allstabledescendants.insert(theDaughter);
625 }
626 findParticleStableDescendants(theDaughter, allstabledescendants);
627 }
628 }
629
633
634 template <class T> bool isHardScatteringVertex(T pVert) {
635 if (pVert == nullptr) return false;
636 T pV = pVert;
637 int numOfPartIn(0);
638 int pdg(0);
639
640 do {
641 pVert = pV;
642 auto incoming = pVert->particles_in();
643 numOfPartIn = incoming.size();
644 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
645 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
646
647 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
648
649 if (numOfPartIn == 2) {
650 auto incoming = pVert->particles_in();
651 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
652 }
653 return false;
654}
655
659
660 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
661 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
662 auto vtx = p->production_vertex();
663 if (!vtx) return false;
664 bool fromHad = false;
665 for ( const auto& parent : vtx->particles_in() ) {
666 if (!parent) continue;
667 // should this really go into parton-level territory?
668 // probably depends where BSM particles are being decayed
669 fromBSM |= isBSM(parent);
670 if (!isPhysical(parent)) return false;
671 fromTau |= isTau(parent);
672 if (isHadron(parent)&&!isBeam(parent)) {
673 if (!hadron) hadron = parent; // assumes linear hadron parentage
674 return true;
675 }
676 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
677 }
678 return fromHad;
679 }
680
683
684 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
685 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
686 decltype(thePart->end_vertex()) pVert(nullptr);
687 if (EndVert != nullptr) {
688 do {
689 bool samePart = false;
690 pVert = nullptr;
691 auto outgoing = EndVert->particles_out();
692 auto incoming = EndVert->particles_in();
693 for (const auto& itrDaug: outgoing) {
694 if (!itrDaug) continue;
695 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
696 // brem on generator level for tau
697 (outgoing.size() == 1 && incoming.size() == 1 &&
699 itrDaug->pdg_id() == thePart->pdg_id()) {
700 samePart = true;
701 pVert = itrDaug->end_vertex();
702 }
703 }
704 if (samePart) EndVert = pVert;
705 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
706 }
707 return EndVert;
708 }
709
711
712 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
713 if (!theVert) return {};
714 decltype(theVert->particles_out()) finalStatePart;
715 auto outgoing = theVert->particles_out();
716 for (const auto& thePart: outgoing) {
717 if (!thePart) continue;
718 finalStatePart.push_back(thePart);
719 if (isStable(thePart)) continue;
720 V pVert = findSimulatedEndVertex(thePart);
721 if (pVert == theVert) break; // to prevent Sherpa loop
722 if (pVert != nullptr) {
723 auto vecPart = findFinalStateParticles<V>(pVert);
724 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
725 }
726 }
727 return finalStatePart;
728 }
729#if !defined(XAOD_ANALYSIS)
730#include "AtlasHepMC/GenEvent.h"
731inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
732inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
733
734#endif
735}
736#endif

◆ isSquark() [2/3]

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

Definition at line 469 of file HepMCHelpers.h.

488{
489 namespace Pythia8
490 {
492 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
493
494 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
495
496 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
497 }
498
499#include "AtlasPID.h"
500
502 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
503
505 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
506
508 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
509
511 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
512
514 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
515
517 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
518
520 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
521
523 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
524
526 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
527
529 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
530
534 template <class T> inline bool isStableOrSimDecayed(const T& p) {
535 const auto vertex = p->end_vertex();
536 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
537 }
538
540 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
541
543 template <class T> inline bool isSpecialNonInteracting(const T& p) {
544 const int apid = std::abs(p->pdg_id());
545 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
546 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
547 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
548 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
549 return false;
550 }
551
553
554 template <class T> T findMother(T thePart) {
555 auto partOriVert = thePart->production_vertex();
556 if (!partOriVert) return nullptr;
557
558 long partPDG = thePart->pdg_id();
559 long MotherPDG(0);
560
561 auto MothOriVert = partOriVert;
562 MothOriVert = nullptr;
563 T theMoth(nullptr);
564
565 size_t itr = 0;
566 do {
567 if (itr != 0) partOriVert = MothOriVert;
568 for ( const auto& p : partOriVert->particles_in() ) {
569 theMoth = p;
570 if (!theMoth) continue;
571 MotherPDG = theMoth->pdg_id();
572 MothOriVert = theMoth->production_vertex();
573 if (MotherPDG == partPDG) break;
574 }
575 itr++;
576 if (itr > 100) {
577 break;
578 }
579 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
580 MothOriVert != partOriVert);
581 return theMoth;
582 }
583
585
586 template <class C, class T> T findMatching(C TruthContainer, T p) {
587 T ptrPart = nullptr;
588 if (!p) return ptrPart;
589 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
590 for (T truthParticle : *TruthContainer) {
591 if (HepMC::is_sim_descendant(p,truthParticle)) {
592 ptrPart = truthParticle;
593 break;
594 }
595 }
596 }
597 else {
598 for (T truthParticle : TruthContainer) {
599 if (HepMC::is_sim_descendant(p,truthParticle)) {
600 ptrPart = truthParticle;
601 break;
602 }
603 }
604 }
605 return ptrPart;
606 }
608
609 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
610 auto prodVtx = thePart->production_vertex();
611 if (!prodVtx) return;
612 for (const auto& theMother: prodVtx->particles_in()) {
613 if (!theMother) continue;
614 allancestors.insert(theMother);
615 findParticleAncestors(theMother, allancestors);
616 }
617 }
618
620
621 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
622 auto endVtx = thePart->end_vertex();
623 if (!endVtx) return;
624 for (const auto& theDaughter: endVtx->particles_out()) {
625 if (!theDaughter) continue;
626 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
627 allstabledescendants.insert(theDaughter);
628 }
629 findParticleStableDescendants(theDaughter, allstabledescendants);
630 }
631 }
632
636
637 template <class T> bool isHardScatteringVertex(T pVert) {
638 if (pVert == nullptr) return false;
639 T pV = pVert;
640 int numOfPartIn(0);
641 int pdg(0);
642
643 do {
644 pVert = pV;
645 auto incoming = pVert->particles_in();
646 numOfPartIn = incoming.size();
647 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
648 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
649
650 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
651
652 if (numOfPartIn == 2) {
653 auto incoming = pVert->particles_in();
654 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
655 }
656 return false;
657}
658
662
663 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
664 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
665 auto vtx = p->production_vertex();
666 if (!vtx) return false;
667 bool fromHad = false;
668 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
733#include "AtlasHepMC/GenEvent.h"
734inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
735inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
736
737#endif
738}
739#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 465 of file HepMCHelpers.h.

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

◆ isSquarkLH() [1/3]

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

Definition at line 474 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 for ( const auto& p : partOriVert->particles_in() ) {
574 theMoth = p;
575 if (!theMoth) continue;
576 MotherPDG = theMoth->pdg_id();
577 MothOriVert = theMoth->production_vertex();
578 if (MotherPDG == partPDG) break;
579 }
580 itr++;
581 if (itr > 100) {
582 break;
583 }
584 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
585 MothOriVert != partOriVert);
586 return theMoth;
587 }
588
590
591 template <class C, class T> T findMatching(C TruthContainer, T p) {
592 T ptrPart = nullptr;
593 if (!p) return ptrPart;
594 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
595 for (T truthParticle : *TruthContainer) {
596 if (HepMC::is_sim_descendant(p,truthParticle)) {
597 ptrPart = truthParticle;
598 break;
599 }
600 }
601 }
602 else {
603 for (T truthParticle : TruthContainer) {
604 if (HepMC::is_sim_descendant(p,truthParticle)) {
605 ptrPart = truthParticle;
606 break;
607 }
608 }
609 }
610 return ptrPart;
611 }
613
614 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
615 auto prodVtx = thePart->production_vertex();
616 if (!prodVtx) return;
617 for (const auto& theMother: prodVtx->particles_in()) {
618 if (!theMother) continue;
619 allancestors.insert(theMother);
620 findParticleAncestors(theMother, allancestors);
621 }
622 }
623
625
626 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
627 auto endVtx = thePart->end_vertex();
628 if (!endVtx) return;
629 for (const auto& theDaughter: endVtx->particles_out()) {
630 if (!theDaughter) continue;
631 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
632 allstabledescendants.insert(theDaughter);
633 }
634 findParticleStableDescendants(theDaughter, allstabledescendants);
635 }
636 }
637
641
642 template <class T> bool isHardScatteringVertex(T pVert) {
643 if (pVert == nullptr) return false;
644 T pV = pVert;
645 int numOfPartIn(0);
646 int pdg(0);
647
648 do {
649 pVert = pV;
650 auto incoming = pVert->particles_in();
651 numOfPartIn = incoming.size();
652 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
653 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
654
655 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
656
657 if (numOfPartIn == 2) {
658 auto incoming = pVert->particles_in();
659 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
660 }
661 return false;
662}
663
667
668 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
669 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
670 auto vtx = p->production_vertex();
671 if (!vtx) return false;
672 bool fromHad = false;
673 for ( const auto& parent : vtx->particles_in() ) {
674 if (!parent) continue;
675 // should this really go into parton-level territory?
676 // probably depends where BSM particles are being decayed
677 fromBSM |= isBSM(parent);
678 if (!isPhysical(parent)) return false;
679 fromTau |= isTau(parent);
680 if (isHadron(parent)&&!isBeam(parent)) {
681 if (!hadron) hadron = parent; // assumes linear hadron parentage
682 return true;
683 }
684 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
685 }
686 return fromHad;
687 }
688
691
692 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
693 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
694 decltype(thePart->end_vertex()) pVert(nullptr);
695 if (EndVert != nullptr) {
696 do {
697 bool samePart = false;
698 pVert = nullptr;
699 auto outgoing = EndVert->particles_out();
700 auto incoming = EndVert->particles_in();
701 for (const auto& itrDaug: outgoing) {
702 if (!itrDaug) continue;
703 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
704 // brem on generator level for tau
705 (outgoing.size() == 1 && incoming.size() == 1 &&
707 itrDaug->pdg_id() == thePart->pdg_id()) {
708 samePart = true;
709 pVert = itrDaug->end_vertex();
710 }
711 }
712 if (samePart) EndVert = pVert;
713 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
714 }
715 return EndVert;
716 }
717
719
720 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
721 if (!theVert) return {};
722 decltype(theVert->particles_out()) finalStatePart;
723 auto outgoing = theVert->particles_out();
724 for (const auto& thePart: outgoing) {
725 if (!thePart) continue;
726 finalStatePart.push_back(thePart);
727 if (isStable(thePart)) continue;
728 V pVert = findSimulatedEndVertex(thePart);
729 if (pVert == theVert) break; // to prevent Sherpa loop
730 if (pVert != nullptr) {
731 auto vecPart = findFinalStateParticles<V>(pVert);
732 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
733 }
734 }
735 return finalStatePart;
736 }
737#if !defined(XAOD_ANALYSIS)
738#include "AtlasHepMC/GenEvent.h"
739inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
740inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
741
742#endif
743}
744#endif

◆ isSquarkLH() [2/3]

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

Definition at line 477 of file HepMCHelpers.h.

496{
497 namespace Pythia8
498 {
500 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
501
502 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
503
504 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
505 }
506
507#include "AtlasPID.h"
508
510 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
511
513 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
514
516 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
517
519 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
520
522 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
523
525 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
526
528 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
529
531 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
532
534 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
535
537 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
538
542 template <class T> inline bool isStableOrSimDecayed(const T& p) {
543 const auto vertex = p->end_vertex();
544 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
545 }
546
548 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
549
551 template <class T> inline bool isSpecialNonInteracting(const T& p) {
552 const int apid = std::abs(p->pdg_id());
553 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
554 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
555 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
556 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
557 return false;
558 }
559
561
562 template <class T> T findMother(T thePart) {
563 auto partOriVert = thePart->production_vertex();
564 if (!partOriVert) return nullptr;
565
566 long partPDG = thePart->pdg_id();
567 long MotherPDG(0);
568
569 auto MothOriVert = partOriVert;
570 MothOriVert = nullptr;
571 T theMoth(nullptr);
572
573 size_t itr = 0;
574 do {
575 if (itr != 0) partOriVert = MothOriVert;
576 for ( const auto& p : partOriVert->particles_in() ) {
577 theMoth = p;
578 if (!theMoth) continue;
579 MotherPDG = theMoth->pdg_id();
580 MothOriVert = theMoth->production_vertex();
581 if (MotherPDG == partPDG) break;
582 }
583 itr++;
584 if (itr > 100) {
585 break;
586 }
587 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
588 MothOriVert != partOriVert);
589 return theMoth;
590 }
591
593
594 template <class C, class T> T findMatching(C TruthContainer, T p) {
595 T ptrPart = nullptr;
596 if (!p) return ptrPart;
597 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
598 for (T truthParticle : *TruthContainer) {
599 if (HepMC::is_sim_descendant(p,truthParticle)) {
600 ptrPart = truthParticle;
601 break;
602 }
603 }
604 }
605 else {
606 for (T truthParticle : TruthContainer) {
607 if (HepMC::is_sim_descendant(p,truthParticle)) {
608 ptrPart = truthParticle;
609 break;
610 }
611 }
612 }
613 return ptrPart;
614 }
616
617 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
618 auto prodVtx = thePart->production_vertex();
619 if (!prodVtx) return;
620 for (const auto& theMother: prodVtx->particles_in()) {
621 if (!theMother) continue;
622 allancestors.insert(theMother);
623 findParticleAncestors(theMother, allancestors);
624 }
625 }
626
628
629 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
630 auto endVtx = thePart->end_vertex();
631 if (!endVtx) return;
632 for (const auto& theDaughter: endVtx->particles_out()) {
633 if (!theDaughter) continue;
634 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
635 allstabledescendants.insert(theDaughter);
636 }
637 findParticleStableDescendants(theDaughter, allstabledescendants);
638 }
639 }
640
644
645 template <class T> bool isHardScatteringVertex(T pVert) {
646 if (pVert == nullptr) return false;
647 T pV = pVert;
648 int numOfPartIn(0);
649 int pdg(0);
650
651 do {
652 pVert = pV;
653 auto incoming = pVert->particles_in();
654 numOfPartIn = incoming.size();
655 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
656 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
657
658 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
659
660 if (numOfPartIn == 2) {
661 auto incoming = pVert->particles_in();
662 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
663 }
664 return false;
665}
666
670
671 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
672 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
673 auto vtx = p->production_vertex();
674 if (!vtx) return false;
675 bool fromHad = false;
676 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
741#include "AtlasHepMC/GenEvent.h"
742inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
743inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
744
745#endif
746}
747#endif

◆ isSquarkLH() [3/3]

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

Definition at line 473 of file HepMCHelpers.h.

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

◆ isSquarkRH() [1/3]

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

Definition at line 482 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 for ( const auto& p : partOriVert->particles_in() ) {
582 theMoth = p;
583 if (!theMoth) continue;
584 MotherPDG = theMoth->pdg_id();
585 MothOriVert = theMoth->production_vertex();
586 if (MotherPDG == partPDG) break;
587 }
588 itr++;
589 if (itr > 100) {
590 break;
591 }
592 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
593 MothOriVert != partOriVert);
594 return theMoth;
595 }
596
598
599 template <class C, class T> T findMatching(C TruthContainer, T p) {
600 T ptrPart = nullptr;
601 if (!p) return ptrPart;
602 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
603 for (T truthParticle : *TruthContainer) {
604 if (HepMC::is_sim_descendant(p,truthParticle)) {
605 ptrPart = truthParticle;
606 break;
607 }
608 }
609 }
610 else {
611 for (T truthParticle : TruthContainer) {
612 if (HepMC::is_sim_descendant(p,truthParticle)) {
613 ptrPart = truthParticle;
614 break;
615 }
616 }
617 }
618 return ptrPart;
619 }
621
622 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
623 auto prodVtx = thePart->production_vertex();
624 if (!prodVtx) return;
625 for (const auto& theMother: prodVtx->particles_in()) {
626 if (!theMother) continue;
627 allancestors.insert(theMother);
628 findParticleAncestors(theMother, allancestors);
629 }
630 }
631
633
634 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
635 auto endVtx = thePart->end_vertex();
636 if (!endVtx) return;
637 for (const auto& theDaughter: endVtx->particles_out()) {
638 if (!theDaughter) continue;
639 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
640 allstabledescendants.insert(theDaughter);
641 }
642 findParticleStableDescendants(theDaughter, allstabledescendants);
643 }
644 }
645
649
650 template <class T> bool isHardScatteringVertex(T pVert) {
651 if (pVert == nullptr) return false;
652 T pV = pVert;
653 int numOfPartIn(0);
654 int pdg(0);
655
656 do {
657 pVert = pV;
658 auto incoming = pVert->particles_in();
659 numOfPartIn = incoming.size();
660 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
661 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
662
663 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
664
665 if (numOfPartIn == 2) {
666 auto incoming = pVert->particles_in();
667 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
668 }
669 return false;
670}
671
675
676 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
677 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
678 auto vtx = p->production_vertex();
679 if (!vtx) return false;
680 bool fromHad = false;
681 for ( const auto& parent : vtx->particles_in() ) {
682 if (!parent) continue;
683 // should this really go into parton-level territory?
684 // probably depends where BSM particles are being decayed
685 fromBSM |= isBSM(parent);
686 if (!isPhysical(parent)) return false;
687 fromTau |= isTau(parent);
688 if (isHadron(parent)&&!isBeam(parent)) {
689 if (!hadron) hadron = parent; // assumes linear hadron parentage
690 return true;
691 }
692 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
693 }
694 return fromHad;
695 }
696
699
700 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
701 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
702 decltype(thePart->end_vertex()) pVert(nullptr);
703 if (EndVert != nullptr) {
704 do {
705 bool samePart = false;
706 pVert = nullptr;
707 auto outgoing = EndVert->particles_out();
708 auto incoming = EndVert->particles_in();
709 for (const auto& itrDaug: outgoing) {
710 if (!itrDaug) continue;
711 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
712 // brem on generator level for tau
713 (outgoing.size() == 1 && incoming.size() == 1 &&
715 itrDaug->pdg_id() == thePart->pdg_id()) {
716 samePart = true;
717 pVert = itrDaug->end_vertex();
718 }
719 }
720 if (samePart) EndVert = pVert;
721 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
722 }
723 return EndVert;
724 }
725
727
728 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
729 if (!theVert) return {};
730 decltype(theVert->particles_out()) finalStatePart;
731 auto outgoing = theVert->particles_out();
732 for (const auto& thePart: outgoing) {
733 if (!thePart) continue;
734 finalStatePart.push_back(thePart);
735 if (isStable(thePart)) continue;
736 V pVert = findSimulatedEndVertex(thePart);
737 if (pVert == theVert) break; // to prevent Sherpa loop
738 if (pVert != nullptr) {
739 auto vecPart = findFinalStateParticles<V>(pVert);
740 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
741 }
742 }
743 return finalStatePart;
744 }
745#if !defined(XAOD_ANALYSIS)
746#include "AtlasHepMC/GenEvent.h"
747inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
748inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
749
750#endif
751}
752#endif

◆ isSquarkRH() [2/3]

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

Definition at line 485 of file HepMCHelpers.h.

504{
505 namespace Pythia8
506 {
508 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
509
510 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
511
512 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
513 }
514
515#include "AtlasPID.h"
516
518 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
519
521 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
522
524 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
525
527 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
528
530 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
531
533 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
534
536 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
537
539 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
540
542 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
543
545 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
546
550 template <class T> inline bool isStableOrSimDecayed(const T& p) {
551 const auto vertex = p->end_vertex();
552 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
553 }
554
556 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
557
559 template <class T> inline bool isSpecialNonInteracting(const T& p) {
560 const int apid = std::abs(p->pdg_id());
561 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
562 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
563 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
564 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
565 return false;
566 }
567
569
570 template <class T> T findMother(T thePart) {
571 auto partOriVert = thePart->production_vertex();
572 if (!partOriVert) return nullptr;
573
574 long partPDG = thePart->pdg_id();
575 long MotherPDG(0);
576
577 auto MothOriVert = partOriVert;
578 MothOriVert = nullptr;
579 T theMoth(nullptr);
580
581 size_t itr = 0;
582 do {
583 if (itr != 0) partOriVert = MothOriVert;
584 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
749#include "AtlasHepMC/GenEvent.h"
750inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
751inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
752
753#endif
754}
755#endif

◆ isSquarkRH() [3/3]

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

Definition at line 481 of file HepMCHelpers.h.

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

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

◆ isStrange() [1/2]

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

Definition at line 184 of file HepMCHelpers.h.

184{

◆ isStrange() [2/2]

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

Definition at line 183 of file HepMCHelpers.h.

◆ isStrangeBaryon()

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

Definition at line 940 of file HepMCHelpers.h.

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

◆ isStrangeHadron()

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

Definition at line 917 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 for ( const auto& p : partOriVert->particles_in() ) {
1017 theMoth = p;
1018 if (!theMoth) continue;
1019 MotherPDG = theMoth->pdg_id();
1020 MothOriVert = theMoth->production_vertex();
1021 if (MotherPDG == partPDG) break;
1022 }
1023 itr++;
1024 if (itr > 100) {
1025 break;
1026 }
1027 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1028 MothOriVert != partOriVert);
1029 return theMoth;
1030 }
1031
1033
1034 template <class C, class T> T findMatching(C TruthContainer, T p) {
1035 T ptrPart = nullptr;
1036 if (!p) return ptrPart;
1037 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1038 for (T truthParticle : *TruthContainer) {
1039 if (HepMC::is_sim_descendant(p,truthParticle)) {
1040 ptrPart = truthParticle;
1041 break;
1042 }
1043 }
1044 }
1045 else {
1046 for (T truthParticle : TruthContainer) {
1047 if (HepMC::is_sim_descendant(p,truthParticle)) {
1048 ptrPart = truthParticle;
1049 break;
1050 }
1051 }
1052 }
1053 return ptrPart;
1054 }
1056
1057 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1058 auto prodVtx = thePart->production_vertex();
1059 if (!prodVtx) return;
1060 for (const auto& theMother: prodVtx->particles_in()) {
1061 if (!theMother) continue;
1062 allancestors.insert(theMother);
1063 findParticleAncestors(theMother, allancestors);
1064 }
1065 }
1066
1068
1069 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1070 auto endVtx = thePart->end_vertex();
1071 if (!endVtx) return;
1072 for (const auto& theDaughter: endVtx->particles_out()) {
1073 if (!theDaughter) continue;
1074 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1075 allstabledescendants.insert(theDaughter);
1076 }
1077 findParticleStableDescendants(theDaughter, allstabledescendants);
1078 }
1079 }
1080
1084
1085 template <class T> bool isHardScatteringVertex(T pVert) {
1086 if (pVert == nullptr) return false;
1087 T pV = pVert;
1088 int numOfPartIn(0);
1089 int pdg(0);
1090
1091 do {
1092 pVert = pV;
1093 auto incoming = pVert->particles_in();
1094 numOfPartIn = incoming.size();
1095 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1096 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1097
1098 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1099
1100 if (numOfPartIn == 2) {
1101 auto incoming = pVert->particles_in();
1102 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1103 }
1104 return false;
1105}
1106
1110
1111 template <class T, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1181#include "AtlasHepMC/GenEvent.h"
1182inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1183inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1184
1185#endif
1186}
1187#endif

◆ isStrangeMeson()

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

Definition at line 924 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 for ( const auto& p : partOriVert->particles_in() ) {
1024 theMoth = p;
1025 if (!theMoth) continue;
1026 MotherPDG = theMoth->pdg_id();
1027 MothOriVert = theMoth->production_vertex();
1028 if (MotherPDG == partPDG) break;
1029 }
1030 itr++;
1031 if (itr > 100) {
1032 break;
1033 }
1034 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1035 MothOriVert != partOriVert);
1036 return theMoth;
1037 }
1038
1040
1041 template <class C, class T> T findMatching(C TruthContainer, T p) {
1042 T ptrPart = nullptr;
1043 if (!p) return ptrPart;
1044 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1045 for (T truthParticle : *TruthContainer) {
1046 if (HepMC::is_sim_descendant(p,truthParticle)) {
1047 ptrPart = truthParticle;
1048 break;
1049 }
1050 }
1051 }
1052 else {
1053 for (T truthParticle : TruthContainer) {
1054 if (HepMC::is_sim_descendant(p,truthParticle)) {
1055 ptrPart = truthParticle;
1056 break;
1057 }
1058 }
1059 }
1060 return ptrPart;
1061 }
1063
1064 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1065 auto prodVtx = thePart->production_vertex();
1066 if (!prodVtx) return;
1067 for (const auto& theMother: prodVtx->particles_in()) {
1068 if (!theMother) continue;
1069 allancestors.insert(theMother);
1070 findParticleAncestors(theMother, allancestors);
1071 }
1072 }
1073
1075
1076 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1077 auto endVtx = thePart->end_vertex();
1078 if (!endVtx) return;
1079 for (const auto& theDaughter: endVtx->particles_out()) {
1080 if (!theDaughter) continue;
1081 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1082 allstabledescendants.insert(theDaughter);
1083 }
1084 findParticleStableDescendants(theDaughter, allstabledescendants);
1085 }
1086 }
1087
1091
1092 template <class T> bool isHardScatteringVertex(T pVert) {
1093 if (pVert == nullptr) return false;
1094 T pV = pVert;
1095 int numOfPartIn(0);
1096 int pdg(0);
1097
1098 do {
1099 pVert = pV;
1100 auto incoming = pVert->particles_in();
1101 numOfPartIn = incoming.size();
1102 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1103 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1104
1105 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1106
1107 if (numOfPartIn == 2) {
1108 auto incoming = pVert->particles_in();
1109 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1110 }
1111 return false;
1112}
1113
1117
1118 template <class T, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1188#include "AtlasHepMC/GenEvent.h"
1189inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1190inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1191
1192#endif
1193}
1194#endif

◆ isStrongInteracting() [1/2]

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

Definition at line 1190 of file HepMCHelpers.h.

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

◆ isStrongInteracting() [2/2]

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

Definition at line 1189 of file HepMCHelpers.h.

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

◆ isSuperpartner() [1/3]

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

Definition at line 520 of file HepMCHelpers.h.

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

◆ isSuperpartner() [2/3]

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

Definition at line 523 of file HepMCHelpers.h.

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

◆ isSuperpartner() [3/3]

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

Definition at line 519 of file HepMCHelpers.h.

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

◆ isSUSY() [1/3]

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

Definition at line 631 of file HepMCHelpers.h.

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

◆ isSUSY() [2/3]

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

Definition at line 632 of file HepMCHelpers.h.

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

◆ isSUSY() [3/3]

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

Definition at line 630 of file HepMCHelpers.h.

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

◆ isTau() [1/2]

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

Definition at line 216 of file HepMCHelpers.h.

◆ isTau() [2/2]

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

Definition at line 215 of file HepMCHelpers.h.

◆ isTechnicolor() [1/3]

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

Definition at line 533 of file HepMCHelpers.h.

552{
553 namespace Pythia8
554 {
556 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
557
558 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
559
560 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
561 }
562
563#include "AtlasPID.h"
564
566 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
567
569 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
570
572 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
573
575 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
576
578 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
579
581 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
582
584 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
585
587 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
588
590 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
591
593 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
594
598 template <class T> inline bool isStableOrSimDecayed(const T& p) {
599 const auto vertex = p->end_vertex();
600 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
601 }
602
604 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
605
607 template <class T> inline bool isSpecialNonInteracting(const T& p) {
608 const int apid = std::abs(p->pdg_id());
609 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
610 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
611 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
612 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
613 return false;
614 }
615
617
618 template <class T> T findMother(T thePart) {
619 auto partOriVert = thePart->production_vertex();
620 if (!partOriVert) return nullptr;
621
622 long partPDG = thePart->pdg_id();
623 long MotherPDG(0);
624
625 auto MothOriVert = partOriVert;
626 MothOriVert = nullptr;
627 T theMoth(nullptr);
628
629 size_t itr = 0;
630 do {
631 if (itr != 0) partOriVert = MothOriVert;
632 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
733 if (!parent) continue;
734 // should this really go into parton-level territory?
735 // probably depends where BSM particles are being decayed
736 fromBSM |= isBSM(parent);
737 if (!isPhysical(parent)) return false;
738 fromTau |= isTau(parent);
739 if (isHadron(parent)&&!isBeam(parent)) {
740 if (!hadron) hadron = parent; // assumes linear hadron parentage
741 return true;
742 }
743 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
744 }
745 return fromHad;
746 }
747
750
751 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
752 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
753 decltype(thePart->end_vertex()) pVert(nullptr);
754 if (EndVert != nullptr) {
755 do {
756 bool samePart = false;
757 pVert = nullptr;
758 auto outgoing = EndVert->particles_out();
759 auto incoming = EndVert->particles_in();
760 for (const auto& itrDaug: outgoing) {
761 if (!itrDaug) continue;
762 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
763 // brem on generator level for tau
764 (outgoing.size() == 1 && incoming.size() == 1 &&
766 itrDaug->pdg_id() == thePart->pdg_id()) {
767 samePart = true;
768 pVert = itrDaug->end_vertex();
769 }
770 }
771 if (samePart) EndVert = pVert;
772 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
773 }
774 return EndVert;
775 }
776
778
779 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
780 if (!theVert) return {};
781 decltype(theVert->particles_out()) finalStatePart;
782 auto outgoing = theVert->particles_out();
783 for (const auto& thePart: outgoing) {
784 if (!thePart) continue;
785 finalStatePart.push_back(thePart);
786 if (isStable(thePart)) continue;
787 V pVert = findSimulatedEndVertex(thePart);
788 if (pVert == theVert) break; // to prevent Sherpa loop
789 if (pVert != nullptr) {
790 auto vecPart = findFinalStateParticles<V>(pVert);
791 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
792 }
793 }
794 return finalStatePart;
795 }
796#if !defined(XAOD_ANALYSIS)
797#include "AtlasHepMC/GenEvent.h"
798inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
799inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
800
801#endif
802}
803#endif

◆ isTechnicolor() [2/3]

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

Definition at line 539 of file HepMCHelpers.h.

558{
559 namespace Pythia8
560 {
562 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
563
564 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
565
566 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
567 }
568
569#include "AtlasPID.h"
570
572 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
573
575 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
576
578 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
579
581 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
582
584 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
585
587 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
588
590 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
591
593 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
594
596 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
597
599 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
600
604 template <class T> inline bool isStableOrSimDecayed(const T& p) {
605 const auto vertex = p->end_vertex();
606 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
607 }
608
610 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
611
613 template <class T> inline bool isSpecialNonInteracting(const T& p) {
614 const int apid = std::abs(p->pdg_id());
615 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
616 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
617 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
618 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
619 return false;
620 }
621
623
624 template <class T> T findMother(T thePart) {
625 auto partOriVert = thePart->production_vertex();
626 if (!partOriVert) return nullptr;
627
628 long partPDG = thePart->pdg_id();
629 long MotherPDG(0);
630
631 auto MothOriVert = partOriVert;
632 MothOriVert = nullptr;
633 T theMoth(nullptr);
634
635 size_t itr = 0;
636 do {
637 if (itr != 0) partOriVert = MothOriVert;
638 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
739 if (!parent) continue;
740 // should this really go into parton-level territory?
741 // probably depends where BSM particles are being decayed
742 fromBSM |= isBSM(parent);
743 if (!isPhysical(parent)) return false;
744 fromTau |= isTau(parent);
745 if (isHadron(parent)&&!isBeam(parent)) {
746 if (!hadron) hadron = parent; // assumes linear hadron parentage
747 return true;
748 }
749 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
750 }
751 return fromHad;
752 }
753
756
757 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
758 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
759 decltype(thePart->end_vertex()) pVert(nullptr);
760 if (EndVert != nullptr) {
761 do {
762 bool samePart = false;
763 pVert = nullptr;
764 auto outgoing = EndVert->particles_out();
765 auto incoming = EndVert->particles_in();
766 for (const auto& itrDaug: outgoing) {
767 if (!itrDaug) continue;
768 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
769 // brem on generator level for tau
770 (outgoing.size() == 1 && incoming.size() == 1 &&
772 itrDaug->pdg_id() == thePart->pdg_id()) {
773 samePart = true;
774 pVert = itrDaug->end_vertex();
775 }
776 }
777 if (samePart) EndVert = pVert;
778 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
779 }
780 return EndVert;
781 }
782
784
785 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
786 if (!theVert) return {};
787 decltype(theVert->particles_out()) finalStatePart;
788 auto outgoing = theVert->particles_out();
789 for (const auto& thePart: outgoing) {
790 if (!thePart) continue;
791 finalStatePart.push_back(thePart);
792 if (isStable(thePart)) continue;
793 V pVert = findSimulatedEndVertex(thePart);
794 if (pVert == theVert) break; // to prevent Sherpa loop
795 if (pVert != nullptr) {
796 auto vecPart = findFinalStateParticles<V>(pVert);
797 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
798 }
799 }
800 return finalStatePart;
801 }
802#if !defined(XAOD_ANALYSIS)
803#include "AtlasHepMC/GenEvent.h"
804inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
805inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
806
807#endif
808}
809#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 531 of file HepMCHelpers.h.

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

◆ isTetraquark() [1/3]

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

Definition at line 333 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 for ( const auto& p : partOriVert->particles_in() ) {
433 theMoth = p;
434 if (!theMoth) continue;
435 MotherPDG = theMoth->pdg_id();
436 MothOriVert = theMoth->production_vertex();
437 if (MotherPDG == partPDG) break;
438 }
439 itr++;
440 if (itr > 100) {
441 break;
442 }
443 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
444 MothOriVert != partOriVert);
445 return theMoth;
446 }
447
449
450 template <class C, class T> T findMatching(C TruthContainer, T p) {
451 T ptrPart = nullptr;
452 if (!p) return ptrPart;
453 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
454 for (T truthParticle : *TruthContainer) {
455 if (HepMC::is_sim_descendant(p,truthParticle)) {
456 ptrPart = truthParticle;
457 break;
458 }
459 }
460 }
461 else {
462 for (T truthParticle : TruthContainer) {
463 if (HepMC::is_sim_descendant(p,truthParticle)) {
464 ptrPart = truthParticle;
465 break;
466 }
467 }
468 }
469 return ptrPart;
470 }
472
473 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
474 auto prodVtx = thePart->production_vertex();
475 if (!prodVtx) return;
476 for (const auto& theMother: prodVtx->particles_in()) {
477 if (!theMother) continue;
478 allancestors.insert(theMother);
479 findParticleAncestors(theMother, allancestors);
480 }
481 }
482
484
485 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
486 auto endVtx = thePart->end_vertex();
487 if (!endVtx) return;
488 for (const auto& theDaughter: endVtx->particles_out()) {
489 if (!theDaughter) continue;
490 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
491 allstabledescendants.insert(theDaughter);
492 }
493 findParticleStableDescendants(theDaughter, allstabledescendants);
494 }
495 }
496
500
501 template <class T> bool isHardScatteringVertex(T pVert) {
502 if (pVert == nullptr) return false;
503 T pV = pVert;
504 int numOfPartIn(0);
505 int pdg(0);
506
507 do {
508 pVert = pV;
509 auto incoming = pVert->particles_in();
510 numOfPartIn = incoming.size();
511 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
512 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
513
514 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
515
516 if (numOfPartIn == 2) {
517 auto incoming = pVert->particles_in();
518 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
519 }
520 return false;
521}
522
526
527 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
528 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
529 auto vtx = p->production_vertex();
530 if (!vtx) return false;
531 bool fromHad = false;
532 for ( const auto& parent : vtx->particles_in() ) {
533 if (!parent) continue;
534 // should this really go into parton-level territory?
535 // probably depends where BSM particles are being decayed
536 fromBSM |= isBSM(parent);
537 if (!isPhysical(parent)) return false;
538 fromTau |= isTau(parent);
539 if (isHadron(parent)&&!isBeam(parent)) {
540 if (!hadron) hadron = parent; // assumes linear hadron parentage
541 return true;
542 }
543 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
544 }
545 return fromHad;
546 }
547
550
551 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
552 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
553 decltype(thePart->end_vertex()) pVert(nullptr);
554 if (EndVert != nullptr) {
555 do {
556 bool samePart = false;
557 pVert = nullptr;
558 auto outgoing = EndVert->particles_out();
559 auto incoming = EndVert->particles_in();
560 for (const auto& itrDaug: outgoing) {
561 if (!itrDaug) continue;
562 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
563 // brem on generator level for tau
564 (outgoing.size() == 1 && incoming.size() == 1 &&
566 itrDaug->pdg_id() == thePart->pdg_id()) {
567 samePart = true;
568 pVert = itrDaug->end_vertex();
569 }
570 }
571 if (samePart) EndVert = pVert;
572 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
573 }
574 return EndVert;
575 }
576
578
579 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
580 if (!theVert) return {};
581 decltype(theVert->particles_out()) finalStatePart;
582 auto outgoing = theVert->particles_out();
583 for (const auto& thePart: outgoing) {
584 if (!thePart) continue;
585 finalStatePart.push_back(thePart);
586 if (isStable(thePart)) continue;
587 V pVert = findSimulatedEndVertex(thePart);
588 if (pVert == theVert) break; // to prevent Sherpa loop
589 if (pVert != nullptr) {
590 auto vecPart = findFinalStateParticles<V>(pVert);
591 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
592 }
593 }
594 return finalStatePart;
595 }
596#if !defined(XAOD_ANALYSIS)
597#include "AtlasHepMC/GenEvent.h"
598inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
599inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
600
601#endif
602}
603#endif

◆ isTetraquark() [2/3]

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

Definition at line 340 of file HepMCHelpers.h.

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

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

◆ isTop() [1/2]

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

Definition at line 193 of file HepMCHelpers.h.

◆ isTop() [2/2]

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

Definition at line 192 of file HepMCHelpers.h.

◆ isTopBaryon()

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

Definition at line 943 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
1143 if (!parent) continue;
1144 // should this really go into parton-level territory?
1145 // probably depends where BSM particles are being decayed
1146 fromBSM |= isBSM(parent);
1147 if (!isPhysical(parent)) return false;
1148 fromTau |= isTau(parent);
1149 if (isHadron(parent)&&!isBeam(parent)) {
1150 if (!hadron) hadron = parent; // assumes linear hadron parentage
1151 return true;
1152 }
1153 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1154 }
1155 return fromHad;
1156 }
1157
1160
1161 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1162 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1163 decltype(thePart->end_vertex()) pVert(nullptr);
1164 if (EndVert != nullptr) {
1165 do {
1166 bool samePart = false;
1167 pVert = nullptr;
1168 auto outgoing = EndVert->particles_out();
1169 auto incoming = EndVert->particles_in();
1170 for (const auto& itrDaug: outgoing) {
1171 if (!itrDaug) continue;
1172 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1173 // brem on generator level for tau
1174 (outgoing.size() == 1 && incoming.size() == 1 &&
1176 itrDaug->pdg_id() == thePart->pdg_id()) {
1177 samePart = true;
1178 pVert = itrDaug->end_vertex();
1179 }
1180 }
1181 if (samePart) EndVert = pVert;
1182 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1183 }
1184 return EndVert;
1185 }
1186
1188
1189 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1190 if (!theVert) return {};
1191 decltype(theVert->particles_out()) finalStatePart;
1192 auto outgoing = theVert->particles_out();
1193 for (const auto& thePart: outgoing) {
1194 if (!thePart) continue;
1195 finalStatePart.push_back(thePart);
1196 if (isStable(thePart)) continue;
1197 V pVert = findSimulatedEndVertex(thePart);
1198 if (pVert == theVert) break; // to prevent Sherpa loop
1199 if (pVert != nullptr) {
1200 auto vecPart = findFinalStateParticles<V>(pVert);
1201 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1202 }
1203 }
1204 return finalStatePart;
1205 }
1206#if !defined(XAOD_ANALYSIS)
1207#include "AtlasHepMC/GenEvent.h"
1208inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1209inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1210
1211#endif
1212}
1213#endif

◆ isTopHadron()

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

Definition at line 920 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1184#include "AtlasHepMC/GenEvent.h"
1185inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1186inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1187
1188#endif
1189}
1190#endif

◆ isTopMeson()

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

Definition at line 927 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
1127 if (!parent) continue;
1128 // should this really go into parton-level territory?
1129 // probably depends where BSM particles are being decayed
1130 fromBSM |= isBSM(parent);
1131 if (!isPhysical(parent)) return false;
1132 fromTau |= isTau(parent);
1133 if (isHadron(parent)&&!isBeam(parent)) {
1134 if (!hadron) hadron = parent; // assumes linear hadron parentage
1135 return true;
1136 }
1137 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1138 }
1139 return fromHad;
1140 }
1141
1144
1145 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1146 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1147 decltype(thePart->end_vertex()) pVert(nullptr);
1148 if (EndVert != nullptr) {
1149 do {
1150 bool samePart = false;
1151 pVert = nullptr;
1152 auto outgoing = EndVert->particles_out();
1153 auto incoming = EndVert->particles_in();
1154 for (const auto& itrDaug: outgoing) {
1155 if (!itrDaug) continue;
1156 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1157 // brem on generator level for tau
1158 (outgoing.size() == 1 && incoming.size() == 1 &&
1160 itrDaug->pdg_id() == thePart->pdg_id()) {
1161 samePart = true;
1162 pVert = itrDaug->end_vertex();
1163 }
1164 }
1165 if (samePart) EndVert = pVert;
1166 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1167 }
1168 return EndVert;
1169 }
1170
1172
1173 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1174 if (!theVert) return {};
1175 decltype(theVert->particles_out()) finalStatePart;
1176 auto outgoing = theVert->particles_out();
1177 for (const auto& thePart: outgoing) {
1178 if (!thePart) continue;
1179 finalStatePart.push_back(thePart);
1180 if (isStable(thePart)) continue;
1181 V pVert = findSimulatedEndVertex(thePart);
1182 if (pVert == theVert) break; // to prevent Sherpa loop
1183 if (pVert != nullptr) {
1184 auto vecPart = findFinalStateParticles<V>(pVert);
1185 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1186 }
1187 }
1188 return finalStatePart;
1189 }
1190#if !defined(XAOD_ANALYSIS)
1191#include "AtlasHepMC/GenEvent.h"
1192inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1193inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1194
1195#endif
1196}
1197#endif

◆ isTrajectory() [1/2]

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

Definition at line 367 of file HepMCHelpers.h.

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

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

◆ isTransportable() [1/3]

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

Definition at line 881 of file HepMCHelpers.h.

900{
901 namespace Pythia8
902 {
904 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
905
906 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
907
908 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
909 }
910
911#include "AtlasPID.h"
912
914 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
915
917 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
918
920 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
921
923 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
924
926 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
927
929 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
930
932 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
933
935 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
936
938 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
939
941 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
942
946 template <class T> inline bool isStableOrSimDecayed(const T& p) {
947 const auto vertex = p->end_vertex();
948 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
949 }
950
952 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
953
955 template <class T> inline bool isSpecialNonInteracting(const T& p) {
956 const int apid = std::abs(p->pdg_id());
957 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
958 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
959 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
960 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
961 return false;
962 }
963
965
966 template <class T> T findMother(T thePart) {
967 auto partOriVert = thePart->production_vertex();
968 if (!partOriVert) return nullptr;
969
970 long partPDG = thePart->pdg_id();
971 long MotherPDG(0);
972
973 auto MothOriVert = partOriVert;
974 MothOriVert = nullptr;
975 T theMoth(nullptr);
976
977 size_t itr = 0;
978 do {
979 if (itr != 0) partOriVert = MothOriVert;
980 for ( const auto& p : partOriVert->particles_in() ) {
981 theMoth = p;
982 if (!theMoth) continue;
983 MotherPDG = theMoth->pdg_id();
984 MothOriVert = theMoth->production_vertex();
985 if (MotherPDG == partPDG) break;
986 }
987 itr++;
988 if (itr > 100) {
989 break;
990 }
991 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
992 MothOriVert != partOriVert);
993 return theMoth;
994 }
995
997
998 template <class C, class T> T findMatching(C TruthContainer, T p) {
999 T ptrPart = nullptr;
1000 if (!p) return ptrPart;
1001 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1002 for (T truthParticle : *TruthContainer) {
1003 if (HepMC::is_sim_descendant(p,truthParticle)) {
1004 ptrPart = truthParticle;
1005 break;
1006 }
1007 }
1008 }
1009 else {
1010 for (T truthParticle : TruthContainer) {
1011 if (HepMC::is_sim_descendant(p,truthParticle)) {
1012 ptrPart = truthParticle;
1013 break;
1014 }
1015 }
1016 }
1017 return ptrPart;
1018 }
1020
1021 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1022 auto prodVtx = thePart->production_vertex();
1023 if (!prodVtx) return;
1024 for (const auto& theMother: prodVtx->particles_in()) {
1025 if (!theMother) continue;
1026 allancestors.insert(theMother);
1027 findParticleAncestors(theMother, allancestors);
1028 }
1029 }
1030
1032
1033 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1034 auto endVtx = thePart->end_vertex();
1035 if (!endVtx) return;
1036 for (const auto& theDaughter: endVtx->particles_out()) {
1037 if (!theDaughter) continue;
1038 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1039 allstabledescendants.insert(theDaughter);
1040 }
1041 findParticleStableDescendants(theDaughter, allstabledescendants);
1042 }
1043 }
1044
1048
1049 template <class T> bool isHardScatteringVertex(T pVert) {
1050 if (pVert == nullptr) return false;
1051 T pV = pVert;
1052 int numOfPartIn(0);
1053 int pdg(0);
1054
1055 do {
1056 pVert = pV;
1057 auto incoming = pVert->particles_in();
1058 numOfPartIn = incoming.size();
1059 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1060 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1061
1062 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1063
1064 if (numOfPartIn == 2) {
1065 auto incoming = pVert->particles_in();
1066 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1067 }
1068 return false;
1069}
1070
1074
1075 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1076 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1077 auto vtx = p->production_vertex();
1078 if (!vtx) return false;
1079 bool fromHad = false;
1080 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1145#include "AtlasHepMC/GenEvent.h"
1146inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1147inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1148
1149#endif
1150}
1151#endif

◆ isTransportable() [2/3]

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

Definition at line 882 of file HepMCHelpers.h.

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

◆ isTransportable() [3/3]

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

Definition at line 880 of file HepMCHelpers.h.

899{
900 namespace Pythia8
901 {
903 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
904
905 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
906
907 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
908 }
909
910#include "AtlasPID.h"
911
913 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
914
916 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
917
919 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
920
922 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
923
925 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
926
928 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
929
931 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
932
934 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
935
937 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
938
940 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
941
945 template <class T> inline bool isStableOrSimDecayed(const T& p) {
946 const auto vertex = p->end_vertex();
947 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
948 }
949
951 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
952
954 template <class T> inline bool isSpecialNonInteracting(const T& p) {
955 const int apid = std::abs(p->pdg_id());
956 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
957 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
958 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
959 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
960 return false;
961 }
962
964
965 template <class T> T findMother(T thePart) {
966 auto partOriVert = thePart->production_vertex();
967 if (!partOriVert) return nullptr;
968
969 long partPDG = thePart->pdg_id();
970 long MotherPDG(0);
971
972 auto MothOriVert = partOriVert;
973 MothOriVert = nullptr;
974 T theMoth(nullptr);
975
976 size_t itr = 0;
977 do {
978 if (itr != 0) partOriVert = MothOriVert;
979 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1144#include "AtlasHepMC/GenEvent.h"
1145inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1146inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1147
1148#endif
1149}
1150#endif

◆ isValid() [1/3]

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

Definition at line 886 of file HepMCHelpers.h.

905{
906 namespace Pythia8
907 {
909 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
910
911 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
912
913 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
914 }
915
916#include "AtlasPID.h"
917
919 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
920
922 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
923
925 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
926
928 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
929
931 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
932
934 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
935
937 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
938
940 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
941
943 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
944
946 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
947
951 template <class T> inline bool isStableOrSimDecayed(const T& p) {
952 const auto vertex = p->end_vertex();
953 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
954 }
955
957 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
958
960 template <class T> inline bool isSpecialNonInteracting(const T& p) {
961 const int apid = std::abs(p->pdg_id());
962 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
963 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
964 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
965 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
966 return false;
967 }
968
970
971 template <class T> T findMother(T thePart) {
972 auto partOriVert = thePart->production_vertex();
973 if (!partOriVert) return nullptr;
974
975 long partPDG = thePart->pdg_id();
976 long MotherPDG(0);
977
978 auto MothOriVert = partOriVert;
979 MothOriVert = nullptr;
980 T theMoth(nullptr);
981
982 size_t itr = 0;
983 do {
984 if (itr != 0) partOriVert = MothOriVert;
985 for ( const auto& p : partOriVert->particles_in() ) {
986 theMoth = p;
987 if (!theMoth) continue;
988 MotherPDG = theMoth->pdg_id();
989 MothOriVert = theMoth->production_vertex();
990 if (MotherPDG == partPDG) break;
991 }
992 itr++;
993 if (itr > 100) {
994 break;
995 }
996 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
997 MothOriVert != partOriVert);
998 return theMoth;
999 }
1000
1002
1003 template <class C, class T> T findMatching(C TruthContainer, T p) {
1004 T ptrPart = nullptr;
1005 if (!p) return ptrPart;
1006 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1007 for (T truthParticle : *TruthContainer) {
1008 if (HepMC::is_sim_descendant(p,truthParticle)) {
1009 ptrPart = truthParticle;
1010 break;
1011 }
1012 }
1013 }
1014 else {
1015 for (T truthParticle : TruthContainer) {
1016 if (HepMC::is_sim_descendant(p,truthParticle)) {
1017 ptrPart = truthParticle;
1018 break;
1019 }
1020 }
1021 }
1022 return ptrPart;
1023 }
1025
1026 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1027 auto prodVtx = thePart->production_vertex();
1028 if (!prodVtx) return;
1029 for (const auto& theMother: prodVtx->particles_in()) {
1030 if (!theMother) continue;
1031 allancestors.insert(theMother);
1032 findParticleAncestors(theMother, allancestors);
1033 }
1034 }
1035
1037
1038 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1039 auto endVtx = thePart->end_vertex();
1040 if (!endVtx) return;
1041 for (const auto& theDaughter: endVtx->particles_out()) {
1042 if (!theDaughter) continue;
1043 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1044 allstabledescendants.insert(theDaughter);
1045 }
1046 findParticleStableDescendants(theDaughter, allstabledescendants);
1047 }
1048 }
1049
1053
1054 template <class T> bool isHardScatteringVertex(T pVert) {
1055 if (pVert == nullptr) return false;
1056 T pV = pVert;
1057 int numOfPartIn(0);
1058 int pdg(0);
1059
1060 do {
1061 pVert = pV;
1062 auto incoming = pVert->particles_in();
1063 numOfPartIn = incoming.size();
1064 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1065 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1066
1067 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1068
1069 if (numOfPartIn == 2) {
1070 auto incoming = pVert->particles_in();
1071 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1072 }
1073 return false;
1074}
1075
1079
1080 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1081 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1082 auto vtx = p->production_vertex();
1083 if (!vtx) return false;
1084 bool fromHad = false;
1085 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1150#include "AtlasHepMC/GenEvent.h"
1151inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1152inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1153
1154#endif
1155}
1156#endif

◆ isValid() [2/3]

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

Definition at line 891 of file HepMCHelpers.h.

910{
911 namespace Pythia8
912 {
914 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
915
916 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
917
918 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
919 }
920
921#include "AtlasPID.h"
922
924 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
925
927 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
928
930 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
931
933 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
934
936 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
937
939 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
940
942 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
943
945 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
946
948 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
949
951 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
952
956 template <class T> inline bool isStableOrSimDecayed(const T& p) {
957 const auto vertex = p->end_vertex();
958 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
959 }
960
962 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
963
965 template <class T> inline bool isSpecialNonInteracting(const T& p) {
966 const int apid = std::abs(p->pdg_id());
967 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
968 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
969 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
970 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
971 return false;
972 }
973
975
976 template <class T> T findMother(T thePart) {
977 auto partOriVert = thePart->production_vertex();
978 if (!partOriVert) return nullptr;
979
980 long partPDG = thePart->pdg_id();
981 long MotherPDG(0);
982
983 auto MothOriVert = partOriVert;
984 MothOriVert = nullptr;
985 T theMoth(nullptr);
986
987 size_t itr = 0;
988 do {
989 if (itr != 0) partOriVert = MothOriVert;
990 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1155#include "AtlasHepMC/GenEvent.h"
1156inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1157inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1158
1159#endif
1160}
1161#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 885 of file HepMCHelpers.h.

904{
905 namespace Pythia8
906 {
908 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
909
910 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
911
912 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
913 }
914
915#include "AtlasPID.h"
916
918 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
919
921 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
922
924 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
925
927 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
928
930 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
931
933 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
934
936 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
937
939 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
940
942 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
943
945 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
946
950 template <class T> inline bool isStableOrSimDecayed(const T& p) {
951 const auto vertex = p->end_vertex();
952 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
953 }
954
956 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
957
959 template <class T> inline bool isSpecialNonInteracting(const T& p) {
960 const int apid = std::abs(p->pdg_id());
961 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
962 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
963 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
964 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
965 return false;
966 }
967
969
970 template <class T> T findMother(T thePart) {
971 auto partOriVert = thePart->production_vertex();
972 if (!partOriVert) return nullptr;
973
974 long partPDG = thePart->pdg_id();
975 long MotherPDG(0);
976
977 auto MothOriVert = partOriVert;
978 MothOriVert = nullptr;
979 T theMoth(nullptr);
980
981 size_t itr = 0;
982 do {
983 if (itr != 0) partOriVert = MothOriVert;
984 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
1085 if (!parent) continue;
1086 // should this really go into parton-level territory?
1087 // probably depends where BSM particles are being decayed
1088 fromBSM |= isBSM(parent);
1089 if (!isPhysical(parent)) return false;
1090 fromTau |= isTau(parent);
1091 if (isHadron(parent)&&!isBeam(parent)) {
1092 if (!hadron) hadron = parent; // assumes linear hadron parentage
1093 return true;
1094 }
1095 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1096 }
1097 return fromHad;
1098 }
1099
1102
1103 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1104 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1105 decltype(thePart->end_vertex()) pVert(nullptr);
1106 if (EndVert != nullptr) {
1107 do {
1108 bool samePart = false;
1109 pVert = nullptr;
1110 auto outgoing = EndVert->particles_out();
1111 auto incoming = EndVert->particles_in();
1112 for (const auto& itrDaug: outgoing) {
1113 if (!itrDaug) continue;
1114 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1115 // brem on generator level for tau
1116 (outgoing.size() == 1 && incoming.size() == 1 &&
1118 itrDaug->pdg_id() == thePart->pdg_id()) {
1119 samePart = true;
1120 pVert = itrDaug->end_vertex();
1121 }
1122 }
1123 if (samePart) EndVert = pVert;
1124 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1125 }
1126 return EndVert;
1127 }
1128
1130
1131 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1132 if (!theVert) return {};
1133 decltype(theVert->particles_out()) finalStatePart;
1134 auto outgoing = theVert->particles_out();
1135 for (const auto& thePart: outgoing) {
1136 if (!thePart) continue;
1137 finalStatePart.push_back(thePart);
1138 if (isStable(thePart)) continue;
1139 V pVert = findSimulatedEndVertex(thePart);
1140 if (pVert == theVert) break; // to prevent Sherpa loop
1141 if (pVert != nullptr) {
1142 auto vecPart = findFinalStateParticles<V>(pVert);
1143 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1144 }
1145 }
1146 return finalStatePart;
1147 }
1148#if !defined(XAOD_ANALYSIS)
1149#include "AtlasHepMC/GenEvent.h"
1150inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1151inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1152
1153#endif
1154}
1155#endif

◆ isW() [1/2]

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

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

◆ isW() [2/2]

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

Definition at line 389 of file HepMCHelpers.h.

408{
409 namespace Pythia8
410 {
412 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
413
414 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
415
416 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
417 }
418
419#include "AtlasPID.h"
420
422 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
423
425 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
426
428 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
429
431 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
432
434 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
435
437 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
438
440 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
441
443 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
444
446 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
447
449 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
450
454 template <class T> inline bool isStableOrSimDecayed(const T& p) {
455 const auto vertex = p->end_vertex();
456 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
457 }
458
460 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
461
463 template <class T> inline bool isSpecialNonInteracting(const T& p) {
464 const int apid = std::abs(p->pdg_id());
465 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
466 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
467 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
468 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
469 return false;
470 }
471
473
474 template <class T> T findMother(T thePart) {
475 auto partOriVert = thePart->production_vertex();
476 if (!partOriVert) return nullptr;
477
478 long partPDG = thePart->pdg_id();
479 long MotherPDG(0);
480
481 auto MothOriVert = partOriVert;
482 MothOriVert = nullptr;
483 T theMoth(nullptr);
484
485 size_t itr = 0;
486 do {
487 if (itr != 0) partOriVert = MothOriVert;
488 for ( const auto& p : partOriVert->particles_in() ) {
489 theMoth = p;
490 if (!theMoth) continue;
491 MotherPDG = theMoth->pdg_id();
492 MothOriVert = theMoth->production_vertex();
493 if (MotherPDG == partPDG) break;
494 }
495 itr++;
496 if (itr > 100) {
497 break;
498 }
499 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
500 MothOriVert != partOriVert);
501 return theMoth;
502 }
503
505
506 template <class C, class T> T findMatching(C TruthContainer, T p) {
507 T ptrPart = nullptr;
508 if (!p) return ptrPart;
509 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
510 for (T truthParticle : *TruthContainer) {
511 if (HepMC::is_sim_descendant(p,truthParticle)) {
512 ptrPart = truthParticle;
513 break;
514 }
515 }
516 }
517 else {
518 for (T truthParticle : TruthContainer) {
519 if (HepMC::is_sim_descendant(p,truthParticle)) {
520 ptrPart = truthParticle;
521 break;
522 }
523 }
524 }
525 return ptrPart;
526 }
528
529 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
530 auto prodVtx = thePart->production_vertex();
531 if (!prodVtx) return;
532 for (const auto& theMother: prodVtx->particles_in()) {
533 if (!theMother) continue;
534 allancestors.insert(theMother);
535 findParticleAncestors(theMother, allancestors);
536 }
537 }
538
540
541 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
542 auto endVtx = thePart->end_vertex();
543 if (!endVtx) return;
544 for (const auto& theDaughter: endVtx->particles_out()) {
545 if (!theDaughter) continue;
546 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
547 allstabledescendants.insert(theDaughter);
548 }
549 findParticleStableDescendants(theDaughter, allstabledescendants);
550 }
551 }
552
556
557 template <class T> bool isHardScatteringVertex(T pVert) {
558 if (pVert == nullptr) return false;
559 T pV = pVert;
560 int numOfPartIn(0);
561 int pdg(0);
562
563 do {
564 pVert = pV;
565 auto incoming = pVert->particles_in();
566 numOfPartIn = incoming.size();
567 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
568 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
569
570 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
571
572 if (numOfPartIn == 2) {
573 auto incoming = pVert->particles_in();
574 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
575 }
576 return false;
577}
578
582
583 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
584 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
585 auto vtx = p->production_vertex();
586 if (!vtx) return false;
587 bool fromHad = false;
588 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
653#include "AtlasHepMC/GenEvent.h"
654inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
655inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
656
657#endif
658}
659#endif

◆ isWeaklyDecayingBHadron() [1/3]

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

Definition at line 975 of file HepMCHelpers.h.

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

◆ isWeaklyDecayingBHadron() [2/3]

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

Definition at line 950 of file HepMCHelpers.h.

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

◆ isWeaklyDecayingBHadron() [3/3]

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

Definition at line 949 of file HepMCHelpers.h.

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

◆ isWeaklyDecayingCHadron() [1/3]

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

Definition at line 999 of file HepMCHelpers.h.

1018{
1019 namespace Pythia8
1020 {
1022 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1023
1024 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1025
1026 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1027 }
1028
1029#include "AtlasPID.h"
1030
1032 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1033
1035 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1036
1038 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1039
1041 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1042
1044 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1045
1047 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1048
1050 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1051
1053 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1054
1056 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1057
1059 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1060
1064 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1065 const auto vertex = p->end_vertex();
1066 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1067 }
1068
1070 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1071
1073 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1074 const int apid = std::abs(p->pdg_id());
1075 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1076 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1077 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1078 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1079 return false;
1080 }
1081
1083
1084 template <class T> T findMother(T thePart) {
1085 auto partOriVert = thePart->production_vertex();
1086 if (!partOriVert) return nullptr;
1087
1088 long partPDG = thePart->pdg_id();
1089 long MotherPDG(0);
1090
1091 auto MothOriVert = partOriVert;
1092 MothOriVert = nullptr;
1093 T theMoth(nullptr);
1094
1095 size_t itr = 0;
1096 do {
1097 if (itr != 0) partOriVert = MothOriVert;
1098 for ( const auto& p : partOriVert->particles_in() ) {
1099 theMoth = p;
1100 if (!theMoth) continue;
1101 MotherPDG = theMoth->pdg_id();
1102 MothOriVert = theMoth->production_vertex();
1103 if (MotherPDG == partPDG) break;
1104 }
1105 itr++;
1106 if (itr > 100) {
1107 break;
1108 }
1109 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1110 MothOriVert != partOriVert);
1111 return theMoth;
1112 }
1113
1115
1116 template <class C, class T> T findMatching(C TruthContainer, T p) {
1117 T ptrPart = nullptr;
1118 if (!p) return ptrPart;
1119 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1120 for (T truthParticle : *TruthContainer) {
1121 if (HepMC::is_sim_descendant(p,truthParticle)) {
1122 ptrPart = truthParticle;
1123 break;
1124 }
1125 }
1126 }
1127 else {
1128 for (T truthParticle : TruthContainer) {
1129 if (HepMC::is_sim_descendant(p,truthParticle)) {
1130 ptrPart = truthParticle;
1131 break;
1132 }
1133 }
1134 }
1135 return ptrPart;
1136 }
1138
1139 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1140 auto prodVtx = thePart->production_vertex();
1141 if (!prodVtx) return;
1142 for (const auto& theMother: prodVtx->particles_in()) {
1143 if (!theMother) continue;
1144 allancestors.insert(theMother);
1145 findParticleAncestors(theMother, allancestors);
1146 }
1147 }
1148
1150
1151 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1152 auto endVtx = thePart->end_vertex();
1153 if (!endVtx) return;
1154 for (const auto& theDaughter: endVtx->particles_out()) {
1155 if (!theDaughter) continue;
1156 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1157 allstabledescendants.insert(theDaughter);
1158 }
1159 findParticleStableDescendants(theDaughter, allstabledescendants);
1160 }
1161 }
1162
1166
1167 template <class T> bool isHardScatteringVertex(T pVert) {
1168 if (pVert == nullptr) return false;
1169 T pV = pVert;
1170 int numOfPartIn(0);
1171 int pdg(0);
1172
1173 do {
1174 pVert = pV;
1175 auto incoming = pVert->particles_in();
1176 numOfPartIn = incoming.size();
1177 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1178 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1179
1180 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1181
1182 if (numOfPartIn == 2) {
1183 auto incoming = pVert->particles_in();
1184 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1185 }
1186 return false;
1187}
1188
1192
1193 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1194 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1195 auto vtx = p->production_vertex();
1196 if (!vtx) return false;
1197 bool fromHad = false;
1198 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1263#include "AtlasHepMC/GenEvent.h"
1264inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1265inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1266
1267#endif
1268}
1269#endif

◆ isWeaklyDecayingCHadron() [2/3]

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

Definition at line 985 of file HepMCHelpers.h.

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

◆ isWeaklyDecayingCHadron() [3/3]

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

Definition at line 984 of file HepMCHelpers.h.

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

◆ isZ() [1/2]

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

Definition at line 387 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
587 if (!parent) continue;
588 // should this really go into parton-level territory?
589 // probably depends where BSM particles are being decayed
590 fromBSM |= isBSM(parent);
591 if (!isPhysical(parent)) return false;
592 fromTau |= isTau(parent);
593 if (isHadron(parent)&&!isBeam(parent)) {
594 if (!hadron) hadron = parent; // assumes linear hadron parentage
595 return true;
596 }
597 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
598 }
599 return fromHad;
600 }
601
604
605 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
606 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
607 decltype(thePart->end_vertex()) pVert(nullptr);
608 if (EndVert != nullptr) {
609 do {
610 bool samePart = false;
611 pVert = nullptr;
612 auto outgoing = EndVert->particles_out();
613 auto incoming = EndVert->particles_in();
614 for (const auto& itrDaug: outgoing) {
615 if (!itrDaug) continue;
616 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
617 // brem on generator level for tau
618 (outgoing.size() == 1 && incoming.size() == 1 &&
620 itrDaug->pdg_id() == thePart->pdg_id()) {
621 samePart = true;
622 pVert = itrDaug->end_vertex();
623 }
624 }
625 if (samePart) EndVert = pVert;
626 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
627 }
628 return EndVert;
629 }
630
632
633 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
634 if (!theVert) return {};
635 decltype(theVert->particles_out()) finalStatePart;
636 auto outgoing = theVert->particles_out();
637 for (const auto& thePart: outgoing) {
638 if (!thePart) continue;
639 finalStatePart.push_back(thePart);
640 if (isStable(thePart)) continue;
641 V pVert = findSimulatedEndVertex(thePart);
642 if (pVert == theVert) break; // to prevent Sherpa loop
643 if (pVert != nullptr) {
644 auto vecPart = findFinalStateParticles<V>(pVert);
645 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
646 }
647 }
648 return finalStatePart;
649 }
650#if !defined(XAOD_ANALYSIS)
651#include "AtlasHepMC/GenEvent.h"
652inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
653inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
654
655#endif
656}
657#endif

◆ isZ() [2/2]

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

Definition at line 386 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 for ( const auto& p : partOriVert->particles_in() ) {
486 theMoth = p;
487 if (!theMoth) continue;
488 MotherPDG = theMoth->pdg_id();
489 MothOriVert = theMoth->production_vertex();
490 if (MotherPDG == partPDG) break;
491 }
492 itr++;
493 if (itr > 100) {
494 break;
495 }
496 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
497 MothOriVert != partOriVert);
498 return theMoth;
499 }
500
502
503 template <class C, class T> T findMatching(C TruthContainer, T p) {
504 T ptrPart = nullptr;
505 if (!p) return ptrPart;
506 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
507 for (T truthParticle : *TruthContainer) {
508 if (HepMC::is_sim_descendant(p,truthParticle)) {
509 ptrPart = truthParticle;
510 break;
511 }
512 }
513 }
514 else {
515 for (T truthParticle : TruthContainer) {
516 if (HepMC::is_sim_descendant(p,truthParticle)) {
517 ptrPart = truthParticle;
518 break;
519 }
520 }
521 }
522 return ptrPart;
523 }
525
526 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
527 auto prodVtx = thePart->production_vertex();
528 if (!prodVtx) return;
529 for (const auto& theMother: prodVtx->particles_in()) {
530 if (!theMother) continue;
531 allancestors.insert(theMother);
532 findParticleAncestors(theMother, allancestors);
533 }
534 }
535
537
538 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
539 auto endVtx = thePart->end_vertex();
540 if (!endVtx) return;
541 for (const auto& theDaughter: endVtx->particles_out()) {
542 if (!theDaughter) continue;
543 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
544 allstabledescendants.insert(theDaughter);
545 }
546 findParticleStableDescendants(theDaughter, allstabledescendants);
547 }
548 }
549
553
554 template <class T> bool isHardScatteringVertex(T pVert) {
555 if (pVert == nullptr) return false;
556 T pV = pVert;
557 int numOfPartIn(0);
558 int pdg(0);
559
560 do {
561 pVert = pV;
562 auto incoming = pVert->particles_in();
563 numOfPartIn = incoming.size();
564 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
565 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
566
567 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
568
569 if (numOfPartIn == 2) {
570 auto incoming = pVert->particles_in();
571 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
572 }
573 return false;
574}
575
579
580 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
581 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
582 auto vtx = p->production_vertex();
583 if (!vtx) return false;
584 bool fromHad = false;
585 for ( const auto& parent : vtx->particles_in() ) {
586 if (!parent) continue;
587 // should this really go into parton-level territory?
588 // probably depends where BSM particles are being decayed
589 fromBSM |= isBSM(parent);
590 if (!isPhysical(parent)) return false;
591 fromTau |= isTau(parent);
592 if (isHadron(parent)&&!isBeam(parent)) {
593 if (!hadron) hadron = parent; // assumes linear hadron parentage
594 return true;
595 }
596 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
597 }
598 return fromHad;
599 }
600
603
604 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
605 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
606 decltype(thePart->end_vertex()) pVert(nullptr);
607 if (EndVert != nullptr) {
608 do {
609 bool samePart = false;
610 pVert = nullptr;
611 auto outgoing = EndVert->particles_out();
612 auto incoming = EndVert->particles_in();
613 for (const auto& itrDaug: outgoing) {
614 if (!itrDaug) continue;
615 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
616 // brem on generator level for tau
617 (outgoing.size() == 1 && incoming.size() == 1 &&
619 itrDaug->pdg_id() == thePart->pdg_id()) {
620 samePart = true;
621 pVert = itrDaug->end_vertex();
622 }
623 }
624 if (samePart) EndVert = pVert;
625 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
626 }
627 return EndVert;
628 }
629
631
632 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
633 if (!theVert) return {};
634 decltype(theVert->particles_out()) finalStatePart;
635 auto outgoing = theVert->particles_out();
636 for (const auto& thePart: outgoing) {
637 if (!thePart) continue;
638 finalStatePart.push_back(thePart);
639 if (isStable(thePart)) continue;
640 V pVert = findSimulatedEndVertex(thePart);
641 if (pVert == theVert) break; // to prevent Sherpa loop
642 if (pVert != nullptr) {
643 auto vecPart = findFinalStateParticles<V>(pVert);
644 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
645 }
646 }
647 return finalStatePart;
648 }
649#if !defined(XAOD_ANALYSIS)
650#include "AtlasHepMC/GenEvent.h"
651inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
652inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
653
654#endif
655}
656#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 72 of file HepMCHelpers.h.

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

◆ leadingQuark() [1/3]

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

Definition at line 897 of file HepMCHelpers.h.

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

◆ leadingQuark() [2/3]

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

Definition at line 913 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 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1177#include "AtlasHepMC/GenEvent.h"
1178inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1179inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1180
1181#endif
1182}
1183#endif

◆ leadingQuark() [3/3]

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

Definition at line 896 of file HepMCHelpers.h.

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

◆ MeVToGeV()

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

Definition at line 267 of file HepMCHelpers.h.

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

◆ numberOfLambdas() [1/3]

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

Definition at line 832 of file HepMCHelpers.h.

851{
852 namespace Pythia8
853 {
855 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
856
857 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
858
859 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
860 }
861
862#include "AtlasPID.h"
863
865 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
866
868 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
869
871 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
872
874 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
875
877 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
878
880 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
881
883 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
884
886 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
887
889 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
890
892 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
893
897 template <class T> inline bool isStableOrSimDecayed(const T& p) {
898 const auto vertex = p->end_vertex();
899 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
900 }
901
903 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
904
906 template <class T> inline bool isSpecialNonInteracting(const T& p) {
907 const int apid = std::abs(p->pdg_id());
908 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
909 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
910 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
911 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
912 return false;
913 }
914
916
917 template <class T> T findMother(T thePart) {
918 auto partOriVert = thePart->production_vertex();
919 if (!partOriVert) return nullptr;
920
921 long partPDG = thePart->pdg_id();
922 long MotherPDG(0);
923
924 auto MothOriVert = partOriVert;
925 MothOriVert = nullptr;
926 T theMoth(nullptr);
927
928 size_t itr = 0;
929 do {
930 if (itr != 0) partOriVert = MothOriVert;
931 for ( const auto& p : partOriVert->particles_in() ) {
932 theMoth = p;
933 if (!theMoth) continue;
934 MotherPDG = theMoth->pdg_id();
935 MothOriVert = theMoth->production_vertex();
936 if (MotherPDG == partPDG) break;
937 }
938 itr++;
939 if (itr > 100) {
940 break;
941 }
942 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
943 MothOriVert != partOriVert);
944 return theMoth;
945 }
946
948
949 template <class C, class T> T findMatching(C TruthContainer, T p) {
950 T ptrPart = nullptr;
951 if (!p) return ptrPart;
952 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
953 for (T truthParticle : *TruthContainer) {
954 if (HepMC::is_sim_descendant(p,truthParticle)) {
955 ptrPart = truthParticle;
956 break;
957 }
958 }
959 }
960 else {
961 for (T truthParticle : TruthContainer) {
962 if (HepMC::is_sim_descendant(p,truthParticle)) {
963 ptrPart = truthParticle;
964 break;
965 }
966 }
967 }
968 return ptrPart;
969 }
971
972 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
973 auto prodVtx = thePart->production_vertex();
974 if (!prodVtx) return;
975 for (const auto& theMother: prodVtx->particles_in()) {
976 if (!theMother) continue;
977 allancestors.insert(theMother);
978 findParticleAncestors(theMother, allancestors);
979 }
980 }
981
983
984 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
985 auto endVtx = thePart->end_vertex();
986 if (!endVtx) return;
987 for (const auto& theDaughter: endVtx->particles_out()) {
988 if (!theDaughter) continue;
989 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
990 allstabledescendants.insert(theDaughter);
991 }
992 findParticleStableDescendants(theDaughter, allstabledescendants);
993 }
994 }
995
999
1000 template <class T> bool isHardScatteringVertex(T pVert) {
1001 if (pVert == nullptr) return false;
1002 T pV = pVert;
1003 int numOfPartIn(0);
1004 int pdg(0);
1005
1006 do {
1007 pVert = pV;
1008 auto incoming = pVert->particles_in();
1009 numOfPartIn = incoming.size();
1010 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1011 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1012
1013 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1014
1015 if (numOfPartIn == 2) {
1016 auto incoming = pVert->particles_in();
1017 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1018 }
1019 return false;
1020}
1021
1025
1026 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1027 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1028 auto vtx = p->production_vertex();
1029 if (!vtx) return false;
1030 bool fromHad = false;
1031 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1096#include "AtlasHepMC/GenEvent.h"
1097inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1098inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1099
1100#endif
1101}
1102#endif

◆ numberOfLambdas() [2/3]

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

Definition at line 837 of file HepMCHelpers.h.

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

◆ numberOfLambdas() [3/3]

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

Definition at line 831 of file HepMCHelpers.h.

850{
851 namespace Pythia8
852 {
854 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
855
856 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
857
858 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
859 }
860
861#include "AtlasPID.h"
862
864 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
865
867 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
868
870 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
871
873 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
874
876 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
877
879 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
880
882 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
883
885 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
886
888 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
889
891 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
892
896 template <class T> inline bool isStableOrSimDecayed(const T& p) {
897 const auto vertex = p->end_vertex();
898 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
899 }
900
902 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
903
905 template <class T> inline bool isSpecialNonInteracting(const T& p) {
906 const int apid = std::abs(p->pdg_id());
907 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
908 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
909 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
910 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
911 return false;
912 }
913
915
916 template <class T> T findMother(T thePart) {
917 auto partOriVert = thePart->production_vertex();
918 if (!partOriVert) return nullptr;
919
920 long partPDG = thePart->pdg_id();
921 long MotherPDG(0);
922
923 auto MothOriVert = partOriVert;
924 MothOriVert = nullptr;
925 T theMoth(nullptr);
926
927 size_t itr = 0;
928 do {
929 if (itr != 0) partOriVert = MothOriVert;
930 for ( const auto& p : partOriVert->particles_in() ) {
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 (const 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 (const 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, class U> bool isFromHadron(T p, U 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 for ( const auto& parent : vtx->particles_in() ) {
1031 if (!parent) continue;
1032 // should this really go into parton-level territory?
1033 // probably depends where BSM particles are being decayed
1034 fromBSM |= isBSM(parent);
1035 if (!isPhysical(parent)) return false;
1036 fromTau |= isTau(parent);
1037 if (isHadron(parent)&&!isBeam(parent)) {
1038 if (!hadron) hadron = parent; // assumes linear hadron parentage
1039 return true;
1040 }
1041 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1042 }
1043 return fromHad;
1044 }
1045
1048
1049 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1050 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1051 decltype(thePart->end_vertex()) pVert(nullptr);
1052 if (EndVert != nullptr) {
1053 do {
1054 bool samePart = false;
1055 pVert = nullptr;
1056 auto outgoing = EndVert->particles_out();
1057 auto incoming = EndVert->particles_in();
1058 for (const auto& itrDaug: outgoing) {
1059 if (!itrDaug) continue;
1060 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1061 // brem on generator level for tau
1062 (outgoing.size() == 1 && incoming.size() == 1 &&
1064 itrDaug->pdg_id() == thePart->pdg_id()) {
1065 samePart = true;
1066 pVert = itrDaug->end_vertex();
1067 }
1068 }
1069 if (samePart) EndVert = pVert;
1070 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1071 }
1072 return EndVert;
1073 }
1074
1076
1077 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1078 if (!theVert) return {};
1079 decltype(theVert->particles_out()) finalStatePart;
1080 auto outgoing = theVert->particles_out();
1081 for (const auto& thePart: outgoing) {
1082 if (!thePart) continue;
1083 finalStatePart.push_back(thePart);
1084 if (isStable(thePart)) continue;
1085 V pVert = findSimulatedEndVertex(thePart);
1086 if (pVert == theVert) break; // to prevent Sherpa loop
1087 if (pVert != nullptr) {
1088 auto vecPart = findFinalStateParticles<V>(pVert);
1089 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1090 }
1091 }
1092 return finalStatePart;
1093 }
1094#if !defined(XAOD_ANALYSIS)
1095#include "AtlasHepMC/GenEvent.h"
1096inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1097inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1098
1099#endif
1100}
1101#endif

◆ numberOfProtons() [1/3]

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

Definition at line 841 of file HepMCHelpers.h.

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

◆ numberOfProtons() [2/3]

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

Definition at line 849 of file HepMCHelpers.h.

868{
869 namespace Pythia8
870 {
872 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
873
874 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
875
876 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
877 }
878
879#include "AtlasPID.h"
880
882 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
883
885 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
886
888 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
889
891 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
892
894 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
895
897 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
898
900 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
901
903 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
904
906 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
907
909 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
910
914 template <class T> inline bool isStableOrSimDecayed(const T& p) {
915 const auto vertex = p->end_vertex();
916 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
917 }
918
920 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
921
923 template <class T> inline bool isSpecialNonInteracting(const T& p) {
924 const int apid = std::abs(p->pdg_id());
925 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
926 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
927 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
928 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
929 return false;
930 }
931
933
934 template <class T> T findMother(T thePart) {
935 auto partOriVert = thePart->production_vertex();
936 if (!partOriVert) return nullptr;
937
938 long partPDG = thePart->pdg_id();
939 long MotherPDG(0);
940
941 auto MothOriVert = partOriVert;
942 MothOriVert = nullptr;
943 T theMoth(nullptr);
944
945 size_t itr = 0;
946 do {
947 if (itr != 0) partOriVert = MothOriVert;
948 for ( const auto& p : partOriVert->particles_in() ) {
949 theMoth = p;
950 if (!theMoth) continue;
951 MotherPDG = theMoth->pdg_id();
952 MothOriVert = theMoth->production_vertex();
953 if (MotherPDG == partPDG) break;
954 }
955 itr++;
956 if (itr > 100) {
957 break;
958 }
959 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
960 MothOriVert != partOriVert);
961 return theMoth;
962 }
963
965
966 template <class C, class T> T findMatching(C TruthContainer, T p) {
967 T ptrPart = nullptr;
968 if (!p) return ptrPart;
969 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
970 for (T truthParticle : *TruthContainer) {
971 if (HepMC::is_sim_descendant(p,truthParticle)) {
972 ptrPart = truthParticle;
973 break;
974 }
975 }
976 }
977 else {
978 for (T truthParticle : TruthContainer) {
979 if (HepMC::is_sim_descendant(p,truthParticle)) {
980 ptrPart = truthParticle;
981 break;
982 }
983 }
984 }
985 return ptrPart;
986 }
988
989 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
990 auto prodVtx = thePart->production_vertex();
991 if (!prodVtx) return;
992 for (const auto& theMother: prodVtx->particles_in()) {
993 if (!theMother) continue;
994 allancestors.insert(theMother);
995 findParticleAncestors(theMother, allancestors);
996 }
997 }
998
1000
1001 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1002 auto endVtx = thePart->end_vertex();
1003 if (!endVtx) return;
1004 for (const auto& theDaughter: endVtx->particles_out()) {
1005 if (!theDaughter) continue;
1006 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1007 allstabledescendants.insert(theDaughter);
1008 }
1009 findParticleStableDescendants(theDaughter, allstabledescendants);
1010 }
1011 }
1012
1016
1017 template <class T> bool isHardScatteringVertex(T pVert) {
1018 if (pVert == nullptr) return false;
1019 T pV = pVert;
1020 int numOfPartIn(0);
1021 int pdg(0);
1022
1023 do {
1024 pVert = pV;
1025 auto incoming = pVert->particles_in();
1026 numOfPartIn = incoming.size();
1027 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1028 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1029
1030 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1031
1032 if (numOfPartIn == 2) {
1033 auto incoming = pVert->particles_in();
1034 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1035 }
1036 return false;
1037}
1038
1042
1043 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1044 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1045 auto vtx = p->production_vertex();
1046 if (!vtx) return false;
1047 bool fromHad = false;
1048 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1113#include "AtlasHepMC/GenEvent.h"
1114inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1115inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1116
1117#endif
1118}
1119#endif

◆ numberOfProtons() [3/3]

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

Definition at line 840 of file HepMCHelpers.h.

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

◆ spin() [1/3]

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

Definition at line 1159 of file HepMCHelpers.h.

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

◆ spin() [2/3]

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

Definition at line 1160 of file HepMCHelpers.h.

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

◆ spin() [3/3]

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

Definition at line 1158 of file HepMCHelpers.h.

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

◆ spin2() [1/3]

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

Definition at line 1119 of file HepMCHelpers.h.

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

◆ spin2() [2/3]

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

Definition at line 1156 of file HepMCHelpers.h.

1175{
1176 namespace Pythia8
1177 {
1179 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1180
1181 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1182
1183 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1184 }
1185
1186#include "AtlasPID.h"
1187
1189 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1190
1192 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1193
1195 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1196
1198 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1199
1201 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1202
1204 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1205
1207 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1208
1210 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1211
1213 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1214
1216 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1217
1221 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1222 const auto vertex = p->end_vertex();
1223 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1224 }
1225
1227 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1228
1230 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1231 const int apid = std::abs(p->pdg_id());
1232 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1233 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1234 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1235 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1236 return false;
1237 }
1238
1240
1241 template <class T> T findMother(T thePart) {
1242 auto partOriVert = thePart->production_vertex();
1243 if (!partOriVert) return nullptr;
1244
1245 long partPDG = thePart->pdg_id();
1246 long MotherPDG(0);
1247
1248 auto MothOriVert = partOriVert;
1249 MothOriVert = nullptr;
1250 T theMoth(nullptr);
1251
1252 size_t itr = 0;
1253 do {
1254 if (itr != 0) partOriVert = MothOriVert;
1255 for ( const auto& p : partOriVert->particles_in() ) {
1256 theMoth = p;
1257 if (!theMoth) continue;
1258 MotherPDG = theMoth->pdg_id();
1259 MothOriVert = theMoth->production_vertex();
1260 if (MotherPDG == partPDG) break;
1261 }
1262 itr++;
1263 if (itr > 100) {
1264 break;
1265 }
1266 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1267 MothOriVert != partOriVert);
1268 return theMoth;
1269 }
1270
1272
1273 template <class C, class T> T findMatching(C TruthContainer, T p) {
1274 T ptrPart = nullptr;
1275 if (!p) return ptrPart;
1276 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1277 for (T truthParticle : *TruthContainer) {
1278 if (HepMC::is_sim_descendant(p,truthParticle)) {
1279 ptrPart = truthParticle;
1280 break;
1281 }
1282 }
1283 }
1284 else {
1285 for (T truthParticle : TruthContainer) {
1286 if (HepMC::is_sim_descendant(p,truthParticle)) {
1287 ptrPart = truthParticle;
1288 break;
1289 }
1290 }
1291 }
1292 return ptrPart;
1293 }
1295
1296 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1297 auto prodVtx = thePart->production_vertex();
1298 if (!prodVtx) return;
1299 for (const auto& theMother: prodVtx->particles_in()) {
1300 if (!theMother) continue;
1301 allancestors.insert(theMother);
1302 findParticleAncestors(theMother, allancestors);
1303 }
1304 }
1305
1307
1308 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1309 auto endVtx = thePart->end_vertex();
1310 if (!endVtx) return;
1311 for (const auto& theDaughter: endVtx->particles_out()) {
1312 if (!theDaughter) continue;
1313 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1314 allstabledescendants.insert(theDaughter);
1315 }
1316 findParticleStableDescendants(theDaughter, allstabledescendants);
1317 }
1318 }
1319
1323
1324 template <class T> bool isHardScatteringVertex(T pVert) {
1325 if (pVert == nullptr) return false;
1326 T pV = pVert;
1327 int numOfPartIn(0);
1328 int pdg(0);
1329
1330 do {
1331 pVert = pV;
1332 auto incoming = pVert->particles_in();
1333 numOfPartIn = incoming.size();
1334 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1335 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1336
1337 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1338
1339 if (numOfPartIn == 2) {
1340 auto incoming = pVert->particles_in();
1341 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1342 }
1343 return false;
1344}
1345
1349
1350 template <class T, class U> bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1351 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1352 auto vtx = p->production_vertex();
1353 if (!vtx) return false;
1354 bool fromHad = false;
1355 for ( const auto& parent : vtx->particles_in() ) {
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#if !defined(XAOD_ANALYSIS)
1420#include "AtlasHepMC/GenEvent.h"
1421inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1422inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1423
1424#endif
1425}
1426#endif

◆ spin2() [3/3]

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

Definition at line 1118 of file HepMCHelpers.h.

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

◆ strangeness() [1/3]

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

Definition at line 794 of file HepMCHelpers.h.

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

◆ strangeness() [2/3]

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

Definition at line 828 of file HepMCHelpers.h.

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

◆ strangeness() [3/3]

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

Definition at line 793 of file HepMCHelpers.h.

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

◆ threeCharge()

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

Definition at line 1010 of file HepMCHelpers.h.

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

Variable Documentation

◆ ARGON

const int MC::ARGON = 1000180400
static

Definition at line 146 of file HepMCHelpers.h.

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

◆ BORON

const int MC::BORON = 1000050110
static

Definition at line 150 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.

◆ CALCIUM

const int MC::CALCIUM = 1000200400
static

Definition at line 145 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.

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

◆ 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 166 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 165 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 151 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.

◆ INDIUM

const int MC::INDIUM = 1000491150
static

Definition at line 143 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 791 of file HepMCHelpers.h.

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

◆ KRYPTON

const int MC::KRYPTON = 1000360840
static

Definition at line 144 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.

◆ MAGNESIUM

const int MC::MAGNESIUM = 1000120240
static

Definition at line 147 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 148 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 157 of file HepMCHelpers.h.

◆ OXYGEN

const int MC::OXYGEN = 1000080160
static

Definition at line 149 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 156 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 158 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.

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

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