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

Namespaces

namespace  Pythia8
namespace  HepMCStr
namespace  HepMC
namespace  HepMC3

Classes

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

Functions

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

Variables

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

Function Documentation

◆ baryonNumber() [1/3]

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

Definition at line 775 of file HepMCHelpers.h.

◆ baryonNumber() [2/3]

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

Definition at line 776 of file HepMCHelpers.h.

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

◆ baryonNumber() [3/3]

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

Definition at line 774 of file HepMCHelpers.h.

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

◆ baryonNumber3() [1/3]

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

Definition at line 750 of file HepMCHelpers.h.

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

◆ baryonNumber3() [2/3]

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

Definition at line 772 of file HepMCHelpers.h.

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

◆ baryonNumber3() [3/3]

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

Definition at line 749 of file HepMCHelpers.h.

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

◆ charge()

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

Definition at line 998 of file HepMCHelpers.h.

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

◆ charge3() [1/3]

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

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

Definition at line 1008 of file HepMCHelpers.h.

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

◆ charge3() [2/3]

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

Definition at line 1083 of file HepMCHelpers.h.

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

◆ charge3() [3/3]

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

Definition at line 996 of file HepMCHelpers.h.

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

◆ containedQuarks() [1/3]

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

Definition at line 1182 of file HepMCHelpers.h.

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

◆ containedQuarks() [2/3]

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

Definition at line 1160 of file HepMCHelpers.h.

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

◆ containedQuarks() [3/3]

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

Definition at line 1159 of file HepMCHelpers.h.

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

◆ findFinalStateParticles()

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

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

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

Definition at line 253 of file HepMCHelpers.h.

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

◆ findMatching()

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

Function to find a particle in container.

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

Definition at line 123 of file HepMCHelpers.h.

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

◆ findMother()

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

Function to get a mother of particle. MCTruthClassifier legacy.

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

Definition at line 91 of file HepMCHelpers.h.

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

◆ findParticleAncestors()

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

Function to find all ancestors of the particle.

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

Definition at line 146 of file HepMCHelpers.h.

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

◆ findParticleStableDescendants()

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

Function to get the particle stable MC daughters.

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

Definition at line 158 of file HepMCHelpers.h.

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

◆ findSimulatedEndVertex()

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

Function to find the end vertex of a particle.

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

Definition at line 225 of file HepMCHelpers.h.

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

◆ fractionalCharge() [1/3]

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

Definition at line 1096 of file HepMCHelpers.h.

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

◆ fractionalCharge() [2/3]

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

Definition at line 1103 of file HepMCHelpers.h.

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

◆ fractionalCharge() [3/3]

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

Definition at line 997 of file HepMCHelpers.h.

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

◆ GeVToMeV()

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

Definition at line 272 of file HepMCHelpers.h.

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

◆ hasBottom()

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

Definition at line 739 of file HepMCHelpers.h.

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

◆ hasCharm()

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

Definition at line 738 of file HepMCHelpers.h.

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

◆ hasQuark() [1/3]

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

Definition at line 717 of file HepMCHelpers.h.

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

◆ hasQuark() [2/3]

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

Definition at line 735 of file HepMCHelpers.h.

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

◆ hasQuark() [3/3]

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

◆ hasSquark() [1/3]

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

Definition at line 612 of file HepMCHelpers.h.

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

◆ hasSquark() [2/3]

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

Definition at line 619 of file HepMCHelpers.h.

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

◆ hasSquark() [3/3]

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

Definition at line 611 of file HepMCHelpers.h.

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

◆ hasStrange()

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

Definition at line 737 of file HepMCHelpers.h.

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

◆ hasTop()

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

Definition at line 740 of file HepMCHelpers.h.

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

◆ isBaryon() [1/3]

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

Definition at line 284 of file HepMCHelpers.h.

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

◆ isBaryon() [2/3]

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

Definition at line 317 of file HepMCHelpers.h.

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

◆ isBaryon() [3/3]

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

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

Definition at line 283 of file HepMCHelpers.h.

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

◆ isBBbarMeson() [1/3]

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

Definition at line 928 of file HepMCHelpers.h.

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

◆ isBBbarMeson() [2/3]

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

Definition at line 929 of file HepMCHelpers.h.

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

◆ isBBbarMeson() [3/3]

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

Definition at line 927 of file HepMCHelpers.h.

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

◆ isBeam()

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

Identify if the particle is beam particle.

Definition at line 45 of file HepMCHelpers.h.

◆ isBoson() [1/3]

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

Definition at line 372 of file HepMCHelpers.h.

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

◆ isBoson() [2/3]

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

Definition at line 371 of file HepMCHelpers.h.

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

◆ isBoson() [3/3]

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

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

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

Definition at line 370 of file HepMCHelpers.h.

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

◆ isBottom() [1/2]

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

Definition at line 184 of file HepMCHelpers.h.

184: 0;

◆ isBottom() [2/2]

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

Definition at line 183 of file HepMCHelpers.h.

◆ isBottomBaryon()

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

Definition at line 936 of file HepMCHelpers.h.

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

◆ isBottomHadron()

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

Definition at line 913 of file HepMCHelpers.h.

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

◆ isBottomMeson()

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

Definition at line 920 of file HepMCHelpers.h.

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

◆ isBSM() [1/3]

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

Definition at line 848 of file HepMCHelpers.h.

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

◆ isBSM() [2/3]

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

Definition at line 865 of file HepMCHelpers.h.

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

◆ isBSM() [3/3]

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

APID: graviton and all Higgs extensions are BSM.

Definition at line 847 of file HepMCHelpers.h.

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

◆ isCCbarMeson() [1/3]

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

Definition at line 924 of file HepMCHelpers.h.

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

◆ isCCbarMeson() [2/3]

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

Definition at line 925 of file HepMCHelpers.h.

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

◆ isCCbarMeson() [3/3]

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

Definition at line 923 of file HepMCHelpers.h.

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

◆ isCharged()

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

Definition at line 1005 of file HepMCHelpers.h.

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

◆ isChargedNonShowering()

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

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

Definition at line 42 of file HepMCHelpers.h.

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

◆ isCharm() [1/2]

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

Definition at line 181 of file HepMCHelpers.h.

◆ isCharm() [2/2]

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

Definition at line 180 of file HepMCHelpers.h.

180{

◆ isCharmBaryon()

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

Definition at line 935 of file HepMCHelpers.h.

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

◆ isCharmHadron()

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

Definition at line 912 of file HepMCHelpers.h.

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

◆ isCharmMeson()

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

Definition at line 919 of file HepMCHelpers.h.

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

◆ isChLepton() [1/2]

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

Definition at line 201 of file HepMCHelpers.h.

201{

◆ isChLepton() [2/2]

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

APID: the fourth generation leptons are leptons.

Definition at line 200 of file HepMCHelpers.h.

◆ isDecayed()

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

Identify if the particle decayed.

Definition at line 48 of file HepMCHelpers.h.

◆ isDiquark() [1/3]

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

Definition at line 229 of file HepMCHelpers.h.

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

◆ isDiquark() [2/3]

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

Definition at line 235 of file HepMCHelpers.h.

◆ isDiquark() [3/3]

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

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

Definition at line 228 of file HepMCHelpers.h.

228{

◆ isDM() [1/2]

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

Definition at line 660 of file HepMCHelpers.h.

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

◆ isDM() [2/2]

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

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

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

Definition at line 659 of file HepMCHelpers.h.

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

◆ isElectron() [1/2]

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

Definition at line 204 of file HepMCHelpers.h.

◆ isElectron() [2/2]

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

Definition at line 203 of file HepMCHelpers.h.

◆ isEMInteracting() [1/2]

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

Definition at line 1107 of file HepMCHelpers.h.

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

◆ isEMInteracting() [2/2]

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

Definition at line 1106 of file HepMCHelpers.h.

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

◆ isExcited() [1/3]

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

Definition at line 539 of file HepMCHelpers.h.

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

◆ isExcited() [2/3]

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

Definition at line 544 of file HepMCHelpers.h.

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

◆ isExcited() [3/3]

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

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

Definition at line 537 of file HepMCHelpers.h.

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

◆ isFinalState()

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

Identify if the particle is final state particle.

Definition at line 54 of file HepMCHelpers.h.

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

◆ isFourthGeneration() [1/2]

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

Definition at line 222 of file HepMCHelpers.h.

◆ isFourthGeneration() [2/2]

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

Is this a 4th generation fermion?

APID: 4th generation fermions are not standard model particles

Definition at line 221 of file HepMCHelpers.h.

◆ isFromHadron()

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

Function to classify the particle.

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

Definition at line 201 of file HepMCHelpers.h.

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

◆ isGaugino() [1/3]

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

Definition at line 506 of file HepMCHelpers.h.

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

◆ isGaugino() [2/3]

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

Definition at line 509 of file HepMCHelpers.h.

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

◆ isGaugino() [3/3]

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

Definition at line 505 of file HepMCHelpers.h.

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

◆ isGeantino() [1/2]

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

Definition at line 439 of file HepMCHelpers.h.

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

◆ isGeantino() [2/2]

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

Definition at line 438 of file HepMCHelpers.h.

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

◆ isGenericMultichargedParticle() [1/3]

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

Definition at line 686 of file HepMCHelpers.h.

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

◆ isGenericMultichargedParticle() [2/3]

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

Definition at line 687 of file HepMCHelpers.h.

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

◆ isGenericMultichargedParticle() [3/3]

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

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

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

Definition at line 685 of file HepMCHelpers.h.

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

◆ isGenSpecific() [1/2]

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

Definition at line 427 of file HepMCHelpers.h.

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

◆ isGenSpecific() [2/2]

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

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

Definition at line 426 of file HepMCHelpers.h.

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

◆ isGenStable()

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

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

Definition at line 60 of file HepMCHelpers.h.

◆ isGlueball() [1/3]

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

Definition at line 443 of file HepMCHelpers.h.

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

◆ isGlueball() [2/3]

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

Definition at line 449 of file HepMCHelpers.h.

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

◆ isGlueball() [3/3]

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

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

Definition at line 442 of file HepMCHelpers.h.

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

◆ isGluon() [1/2]

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

Definition at line 375 of file HepMCHelpers.h.

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

◆ isGluon() [2/2]

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

Definition at line 374 of file HepMCHelpers.h.

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

◆ isGraviton() [1/2]

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

Definition at line 399 of file HepMCHelpers.h.

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

◆ isGraviton() [2/2]

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

Definition at line 398 of file HepMCHelpers.h.

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

◆ isHadron() [1/3]

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

Definition at line 353 of file HepMCHelpers.h.

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

◆ isHadron() [2/3]

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

Definition at line 354 of file HepMCHelpers.h.

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

◆ isHadron() [3/3]

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

Definition at line 352 of file HepMCHelpers.h.

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

◆ isHardScatteringVertex()

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

Function to classify the vertex as hard scattering vertex.

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

Definition at line 174 of file HepMCHelpers.h.

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

◆ isHeavyBaryon()

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

Definition at line 933 of file HepMCHelpers.h.

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

◆ isHeavyBoson() [1/2]

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

Definition at line 388 of file HepMCHelpers.h.

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

◆ isHeavyBoson() [2/2]

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

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

Definition at line 387 of file HepMCHelpers.h.

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

◆ isHeavyHadron()

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

Definition at line 910 of file HepMCHelpers.h.

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

◆ isHeavyMeson()

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

Definition at line 917 of file HepMCHelpers.h.

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

◆ isHiddenValley() [1/3]

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

Definition at line 671 of file HepMCHelpers.h.

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

◆ isHiddenValley() [2/3]

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

Definition at line 677 of file HepMCHelpers.h.

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

◆ isHiddenValley() [3/3]

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

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

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

Definition at line 669 of file HepMCHelpers.h.

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

◆ isHiggs() [1/2]

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

Definition at line 392 of file HepMCHelpers.h.

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

◆ isHiggs() [2/2]

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

APID: HIGGS boson is only one particle.

Definition at line 391 of file HepMCHelpers.h.

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

◆ isInteracting()

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

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

Definition at line 39 of file HepMCHelpers.h.

◆ isKK() [1/3]

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

Definition at line 637 of file HepMCHelpers.h.

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

◆ isKK() [2/3]

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

Definition at line 638 of file HepMCHelpers.h.

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

◆ isKK() [3/3]

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

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

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

Definition at line 636 of file HepMCHelpers.h.

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

◆ isLepton() [1/3]

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

Definition at line 192 of file HepMCHelpers.h.

◆ isLepton() [2/3]

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

Definition at line 191 of file HepMCHelpers.h.

◆ isLepton() [3/3]

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

APID: the fourth generation leptons are leptons.

Definition at line 190 of file HepMCHelpers.h.

◆ isLeptoQuark() [1/2]

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

Definition at line 410 of file HepMCHelpers.h.

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

◆ isLeptoQuark() [2/2]

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

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

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

Definition at line 409 of file HepMCHelpers.h.

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

◆ isLightBaryon()

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

Definition at line 932 of file HepMCHelpers.h.

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

◆ isLightHadron()

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

Definition at line 909 of file HepMCHelpers.h.

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

◆ isLightMeson()

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

Definition at line 916 of file HepMCHelpers.h.

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

◆ isMeson() [1/3]

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

Definition at line 246 of file HepMCHelpers.h.

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

◆ isMeson() [2/3]

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

Definition at line 267 of file HepMCHelpers.h.

◆ isMeson() [3/3]

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

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

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

Definition at line 245 of file HepMCHelpers.h.

◆ isMonopole() [1/3]

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

Definition at line 647 of file HepMCHelpers.h.

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

◆ isMonopole() [2/3]

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

Definition at line 648 of file HepMCHelpers.h.

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

◆ isMonopole() [3/3]

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

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

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

Definition at line 646 of file HepMCHelpers.h.

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

◆ isMSSMHiggs() [1/2]

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

Definition at line 396 of file HepMCHelpers.h.

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

◆ isMSSMHiggs() [2/2]

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

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

Definition at line 395 of file HepMCHelpers.h.

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

◆ isMuon() [1/2]

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

Definition at line 207 of file HepMCHelpers.h.

◆ isMuon() [2/2]

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

Definition at line 206 of file HepMCHelpers.h.

206: particles_in(vtx) ) {

◆ isNeutral() [1/3]

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

Definition at line 1092 of file HepMCHelpers.h.

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

◆ isNeutral() [2/3]

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

Definition at line 1093 of file HepMCHelpers.h.

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

◆ isNeutral() [3/3]

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

Definition at line 1091 of file HepMCHelpers.h.

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

◆ isNeutrino() [1/2]

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

Definition at line 214 of file HepMCHelpers.h.

◆ isNeutrino() [2/2]

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

APID: the fourth generation neutrinos are neutrinos.

Definition at line 213 of file HepMCHelpers.h.

213{

◆ isNeutrinoRH() [1/2]

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

Definition at line 422 of file HepMCHelpers.h.

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

◆ isNeutrinoRH() [2/2]

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

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

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

Definition at line 421 of file HepMCHelpers.h.

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

◆ isNucleus() [1/3]

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

Definition at line 704 of file HepMCHelpers.h.

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

◆ isNucleus() [2/3]

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

Definition at line 713 of file HepMCHelpers.h.

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

◆ isNucleus() [3/3]

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

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

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

Definition at line 703 of file HepMCHelpers.h.

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

◆ isParton()

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

Definition at line 1109 of file HepMCHelpers.h.

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

◆ isPentaquark() [1/3]

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

Definition at line 344 of file HepMCHelpers.h.

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

◆ isPentaquark() [2/3]

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

Definition at line 349 of file HepMCHelpers.h.

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

◆ isPentaquark() [3/3]

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

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

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

Definition at line 343 of file HepMCHelpers.h.

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

◆ isPhoton() [1/2]

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

Definition at line 378 of file HepMCHelpers.h.

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

◆ isPhoton() [2/2]

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

Definition at line 377 of file HepMCHelpers.h.

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

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

◆ isPythia8Specific() [1/3]

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

Definition at line 413 of file HepMCHelpers.h.

432{
433 template <class VTX>
434 auto particles_in (const VTX* p) { return p->particles_in(); }
435 template <class VTX>
436 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
613 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 : particles_in(vtx) ) {
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 414 of file HepMCHelpers.h.

433{
434 template <class VTX>
435 auto particles_in (const VTX* p) { return p->particles_in(); }
436 template <class VTX>
437 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
614 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 : particles_in(vtx) ) {
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 412 of file HepMCHelpers.h.

431{
432 template <class VTX>
433 auto particles_in (const VTX* p) { return p->particles_in(); }
434 template <class VTX>
435 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
436
437 namespace Pythia8
438 {
440 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
441
442 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
443
444 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
445 }
446
447#include "AtlasPID.h"
448
450 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
451
453 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
454
456 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
457
459 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
460
462 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
463
465 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
466
468 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
469
471 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
472
474 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
475
477 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
478
482 template <class T> inline bool isStableOrSimDecayed(const T& p) {
483 const auto vertex = p->end_vertex();
484 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
485 }
486
488 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
489
491 template <class T> inline bool isSpecialNonInteracting(const T& p) {
492 const int apid = std::abs(p->pdg_id());
493 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
494 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
495 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
496 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
497 return false;
498 }
499
501
502 template <class T> T findMother(T thePart) {
503 auto partOriVert = thePart->production_vertex();
504 if (!partOriVert) return nullptr;
505
506 long partPDG = thePart->pdg_id();
507 long MotherPDG(0);
508
509 auto MothOriVert = partOriVert;
510 MothOriVert = nullptr;
511 T theMoth(nullptr);
512
513 size_t itr = 0;
514 do {
515 if (itr != 0) partOriVert = MothOriVert;
516 for ( const auto& p : particles_in(partOriVert) ) {
517 theMoth = p;
518 if (!theMoth) continue;
519 MotherPDG = theMoth->pdg_id();
520 MothOriVert = theMoth->production_vertex();
521 if (MotherPDG == partPDG) break;
522 }
523 itr++;
524 if (itr > 100) {
525 break;
526 }
527 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
528 MothOriVert != partOriVert);
529 return theMoth;
530 }
531
533
534 template <class C, class T> T findMatching(C TruthContainer, T p) {
535 T ptrPart = nullptr;
536 if (!p) return ptrPart;
537 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
538 for (T truthParticle : *TruthContainer) {
539 if (HepMC::is_sim_descendant(p,truthParticle)) {
540 ptrPart = truthParticle;
541 break;
542 }
543 }
544 }
545 else {
546 for (T truthParticle : TruthContainer) {
547 if (HepMC::is_sim_descendant(p,truthParticle)) {
548 ptrPart = truthParticle;
549 break;
550 }
551 }
552 }
553 return ptrPart;
554 }
556
557 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
558 auto prodVtx = thePart->production_vertex();
559 if (!prodVtx) return;
560 for (const auto& theMother: prodVtx->particles_in()) {
561 if (!theMother) continue;
562 allancestors.insert(theMother);
563 findParticleAncestors(theMother, allancestors);
564 }
565 }
566
568
569 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
570 auto endVtx = thePart->end_vertex();
571 if (!endVtx) return;
572 for (const auto& theDaughter: endVtx->particles_out()) {
573 if (!theDaughter) continue;
574 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
575 allstabledescendants.insert(theDaughter);
576 }
577 findParticleStableDescendants(theDaughter, allstabledescendants);
578 }
579 }
580
584
585 template <class T> bool isHardScatteringVertex(T pVert) {
586 if (pVert == nullptr) return false;
587 T pV = pVert;
588 int numOfPartIn(0);
589 int pdg(0);
590
591 do {
592 pVert = pV;
593 auto incoming = pVert->particles_in();
594 numOfPartIn = incoming.size();
595 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
596 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
597
598 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
599
600 if (numOfPartIn == 2) {
601 auto incoming = pVert->particles_in();
602 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
603 }
604 return false;
605}
606
610
611 template <class T, class U>
612 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 : particles_in(vtx) ) {
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 170 of file HepMCHelpers.h.

◆ isQuark() [2/3]

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

Definition at line 169 of file HepMCHelpers.h.

◆ isQuark() [3/3]

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

PDG rule 2: Quarks and leptons are numbered consecutively starting from 1 and 11 respectively; to do this they are first ordered by family and within families by weak isospin.

APID: the fourth generation quarks are quarks.

Definition at line 168 of file HepMCHelpers.h.

◆ isQuarkonium() [1/3]

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

Definition at line 275 of file HepMCHelpers.h.

◆ isQuarkonium() [2/3]

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

Definition at line 279 of file HepMCHelpers.h.

298{
299 template <class VTX>
300 auto particles_in (const VTX* p) { return p->particles_in(); }
301 template <class VTX>
302 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
303
304 namespace Pythia8
305 {
307 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
308
309 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
310
311 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
312 }
313
314#include "AtlasPID.h"
315
317 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
318
320 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
321
323 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
324
326 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
327
329 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
330
332 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
333
335 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
336
338 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
339
341 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
342
344 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
345
349 template <class T> inline bool isStableOrSimDecayed(const T& p) {
350 const auto vertex = p->end_vertex();
351 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
352 }
353
355 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
356
358 template <class T> inline bool isSpecialNonInteracting(const T& p) {
359 const int apid = std::abs(p->pdg_id());
360 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
361 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
362 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
363 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
364 return false;
365 }
366
368
369 template <class T> T findMother(T thePart) {
370 auto partOriVert = thePart->production_vertex();
371 if (!partOriVert) return nullptr;
372
373 long partPDG = thePart->pdg_id();
374 long MotherPDG(0);
375
376 auto MothOriVert = partOriVert;
377 MothOriVert = nullptr;
378 T theMoth(nullptr);
379
380 size_t itr = 0;
381 do {
382 if (itr != 0) partOriVert = MothOriVert;
383 for ( const auto& p : particles_in(partOriVert) ) {
384 theMoth = p;
385 if (!theMoth) continue;
386 MotherPDG = theMoth->pdg_id();
387 MothOriVert = theMoth->production_vertex();
388 if (MotherPDG == partPDG) break;
389 }
390 itr++;
391 if (itr > 100) {
392 break;
393 }
394 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
395 MothOriVert != partOriVert);
396 return theMoth;
397 }
398
400
401 template <class C, class T> T findMatching(C TruthContainer, T p) {
402 T ptrPart = nullptr;
403 if (!p) return ptrPart;
404 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
405 for (T truthParticle : *TruthContainer) {
406 if (HepMC::is_sim_descendant(p,truthParticle)) {
407 ptrPart = truthParticle;
408 break;
409 }
410 }
411 }
412 else {
413 for (T truthParticle : TruthContainer) {
414 if (HepMC::is_sim_descendant(p,truthParticle)) {
415 ptrPart = truthParticle;
416 break;
417 }
418 }
419 }
420 return ptrPart;
421 }
423
424 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
425 auto prodVtx = thePart->production_vertex();
426 if (!prodVtx) return;
427 for (const auto& theMother: prodVtx->particles_in()) {
428 if (!theMother) continue;
429 allancestors.insert(theMother);
430 findParticleAncestors(theMother, allancestors);
431 }
432 }
433
435
436 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
437 auto endVtx = thePart->end_vertex();
438 if (!endVtx) return;
439 for (const auto& theDaughter: endVtx->particles_out()) {
440 if (!theDaughter) continue;
441 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
442 allstabledescendants.insert(theDaughter);
443 }
444 findParticleStableDescendants(theDaughter, allstabledescendants);
445 }
446 }
447
451
452 template <class T> bool isHardScatteringVertex(T pVert) {
453 if (pVert == nullptr) return false;
454 T pV = pVert;
455 int numOfPartIn(0);
456 int pdg(0);
457
458 do {
459 pVert = pV;
460 auto incoming = pVert->particles_in();
461 numOfPartIn = incoming.size();
462 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
463 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
464
465 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
466
467 if (numOfPartIn == 2) {
468 auto incoming = pVert->particles_in();
469 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
470 }
471 return false;
472}
473
477
478 template <class T, class U>
479 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 : particles_in(vtx) ) {
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 274 of file HepMCHelpers.h.

◆ isRBaryon() [1/3]

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

Definition at line 591 of file HepMCHelpers.h.

610{
611 template <class VTX>
612 auto particles_in (const VTX* p) { return p->particles_in(); }
613 template <class VTX>
614 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
791 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 : particles_in(vtx) ) {
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 601 of file HepMCHelpers.h.

620{
621 template <class VTX>
622 auto particles_in (const VTX* p) { return p->particles_in(); }
623 template <class VTX>
624 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
625
626 namespace Pythia8
627 {
629 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
630
631 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
632
633 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
634 }
635
636#include "AtlasPID.h"
637
639 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
640
642 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
643
645 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
646
648 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
649
651 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
652
654 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
655
657 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
658
660 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
661
663 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
664
666 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
667
671 template <class T> inline bool isStableOrSimDecayed(const T& p) {
672 const auto vertex = p->end_vertex();
673 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
674 }
675
677 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
678
680 template <class T> inline bool isSpecialNonInteracting(const T& p) {
681 const int apid = std::abs(p->pdg_id());
682 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
683 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
684 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
685 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
686 return false;
687 }
688
690
691 template <class T> T findMother(T thePart) {
692 auto partOriVert = thePart->production_vertex();
693 if (!partOriVert) return nullptr;
694
695 long partPDG = thePart->pdg_id();
696 long MotherPDG(0);
697
698 auto MothOriVert = partOriVert;
699 MothOriVert = nullptr;
700 T theMoth(nullptr);
701
702 size_t itr = 0;
703 do {
704 if (itr != 0) partOriVert = MothOriVert;
705 for ( const auto& p : particles_in(partOriVert) ) {
706 theMoth = p;
707 if (!theMoth) continue;
708 MotherPDG = theMoth->pdg_id();
709 MothOriVert = theMoth->production_vertex();
710 if (MotherPDG == partPDG) break;
711 }
712 itr++;
713 if (itr > 100) {
714 break;
715 }
716 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
717 MothOriVert != partOriVert);
718 return theMoth;
719 }
720
722
723 template <class C, class T> T findMatching(C TruthContainer, T p) {
724 T ptrPart = nullptr;
725 if (!p) return ptrPart;
726 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
727 for (T truthParticle : *TruthContainer) {
728 if (HepMC::is_sim_descendant(p,truthParticle)) {
729 ptrPart = truthParticle;
730 break;
731 }
732 }
733 }
734 else {
735 for (T truthParticle : TruthContainer) {
736 if (HepMC::is_sim_descendant(p,truthParticle)) {
737 ptrPart = truthParticle;
738 break;
739 }
740 }
741 }
742 return ptrPart;
743 }
745
746 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
747 auto prodVtx = thePart->production_vertex();
748 if (!prodVtx) return;
749 for (const auto& theMother: prodVtx->particles_in()) {
750 if (!theMother) continue;
751 allancestors.insert(theMother);
752 findParticleAncestors(theMother, allancestors);
753 }
754 }
755
757
758 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
759 auto endVtx = thePart->end_vertex();
760 if (!endVtx) return;
761 for (const auto& theDaughter: endVtx->particles_out()) {
762 if (!theDaughter) continue;
763 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
764 allstabledescendants.insert(theDaughter);
765 }
766 findParticleStableDescendants(theDaughter, allstabledescendants);
767 }
768 }
769
773
774 template <class T> bool isHardScatteringVertex(T pVert) {
775 if (pVert == nullptr) return false;
776 T pV = pVert;
777 int numOfPartIn(0);
778 int pdg(0);
779
780 do {
781 pVert = pV;
782 auto incoming = pVert->particles_in();
783 numOfPartIn = incoming.size();
784 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
785 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
786
787 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
788
789 if (numOfPartIn == 2) {
790 auto incoming = pVert->particles_in();
791 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
792 }
793 return false;
794}
795
799
800 template <class T, class U>
801 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 : particles_in(vtx) ) {
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 590 of file HepMCHelpers.h.

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

420{
421 template <class VTX>
422 auto particles_in (const VTX* p) { return p->particles_in(); }
423 template <class VTX>
424 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
425
426 namespace Pythia8
427 {
429 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
430
431 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
432
433 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
434 }
435
436#include "AtlasPID.h"
437
439 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
440
442 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
443
445 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
446
448 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
449
451 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
452
454 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
455
457 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
458
460 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
461
463 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
464
466 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
467
471 template <class T> inline bool isStableOrSimDecayed(const T& p) {
472 const auto vertex = p->end_vertex();
473 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
474 }
475
477 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
478
480 template <class T> inline bool isSpecialNonInteracting(const T& p) {
481 const int apid = std::abs(p->pdg_id());
482 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
483 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
484 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
485 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
486 return false;
487 }
488
490
491 template <class T> T findMother(T thePart) {
492 auto partOriVert = thePart->production_vertex();
493 if (!partOriVert) return nullptr;
494
495 long partPDG = thePart->pdg_id();
496 long MotherPDG(0);
497
498 auto MothOriVert = partOriVert;
499 MothOriVert = nullptr;
500 T theMoth(nullptr);
501
502 size_t itr = 0;
503 do {
504 if (itr != 0) partOriVert = MothOriVert;
505 for ( const auto& p : particles_in(partOriVert) ) {
506 theMoth = p;
507 if (!theMoth) continue;
508 MotherPDG = theMoth->pdg_id();
509 MothOriVert = theMoth->production_vertex();
510 if (MotherPDG == partPDG) break;
511 }
512 itr++;
513 if (itr > 100) {
514 break;
515 }
516 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
517 MothOriVert != partOriVert);
518 return theMoth;
519 }
520
522
523 template <class C, class T> T findMatching(C TruthContainer, T p) {
524 T ptrPart = nullptr;
525 if (!p) return ptrPart;
526 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
527 for (T truthParticle : *TruthContainer) {
528 if (HepMC::is_sim_descendant(p,truthParticle)) {
529 ptrPart = truthParticle;
530 break;
531 }
532 }
533 }
534 else {
535 for (T truthParticle : TruthContainer) {
536 if (HepMC::is_sim_descendant(p,truthParticle)) {
537 ptrPart = truthParticle;
538 break;
539 }
540 }
541 }
542 return ptrPart;
543 }
545
546 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
547 auto prodVtx = thePart->production_vertex();
548 if (!prodVtx) return;
549 for (const auto& theMother: prodVtx->particles_in()) {
550 if (!theMother) continue;
551 allancestors.insert(theMother);
552 findParticleAncestors(theMother, allancestors);
553 }
554 }
555
557
558 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
559 auto endVtx = thePart->end_vertex();
560 if (!endVtx) return;
561 for (const auto& theDaughter: endVtx->particles_out()) {
562 if (!theDaughter) continue;
563 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
564 allstabledescendants.insert(theDaughter);
565 }
566 findParticleStableDescendants(theDaughter, allstabledescendants);
567 }
568 }
569
573
574 template <class T> bool isHardScatteringVertex(T pVert) {
575 if (pVert == nullptr) return false;
576 T pV = pVert;
577 int numOfPartIn(0);
578 int pdg(0);
579
580 do {
581 pVert = pV;
582 auto incoming = pVert->particles_in();
583 numOfPartIn = incoming.size();
584 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
585 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
586
587 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
588
589 if (numOfPartIn == 2) {
590 auto incoming = pVert->particles_in();
591 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
592 }
593 return false;
594}
595
599
600 template <class T, class U>
601 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 : particles_in(vtx) ) {
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 564 of file HepMCHelpers.h.

583{
584 template <class VTX>
585 auto particles_in (const VTX* p) { return p->particles_in(); }
586 template <class VTX>
587 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
764 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 : particles_in(vtx) ) {
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 571 of file HepMCHelpers.h.

590{
591 template <class VTX>
592 auto particles_in (const VTX* p) { return p->particles_in(); }
593 template <class VTX>
594 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
595
596 namespace Pythia8
597 {
599 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
600
601 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
602
603 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
604 }
605
606#include "AtlasPID.h"
607
609 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
610
612 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
613
615 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
616
618 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
619
621 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
622
624 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
625
627 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
628
630 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
631
633 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
634
636 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
637
641 template <class T> inline bool isStableOrSimDecayed(const T& p) {
642 const auto vertex = p->end_vertex();
643 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
644 }
645
647 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
648
650 template <class T> inline bool isSpecialNonInteracting(const T& p) {
651 const int apid = std::abs(p->pdg_id());
652 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
653 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
654 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
655 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
656 return false;
657 }
658
660
661 template <class T> T findMother(T thePart) {
662 auto partOriVert = thePart->production_vertex();
663 if (!partOriVert) return nullptr;
664
665 long partPDG = thePart->pdg_id();
666 long MotherPDG(0);
667
668 auto MothOriVert = partOriVert;
669 MothOriVert = nullptr;
670 T theMoth(nullptr);
671
672 size_t itr = 0;
673 do {
674 if (itr != 0) partOriVert = MothOriVert;
675 for ( const auto& p : particles_in(partOriVert) ) {
676 theMoth = p;
677 if (!theMoth) continue;
678 MotherPDG = theMoth->pdg_id();
679 MothOriVert = theMoth->production_vertex();
680 if (MotherPDG == partPDG) break;
681 }
682 itr++;
683 if (itr > 100) {
684 break;
685 }
686 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
687 MothOriVert != partOriVert);
688 return theMoth;
689 }
690
692
693 template <class C, class T> T findMatching(C TruthContainer, T p) {
694 T ptrPart = nullptr;
695 if (!p) return ptrPart;
696 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
697 for (T truthParticle : *TruthContainer) {
698 if (HepMC::is_sim_descendant(p,truthParticle)) {
699 ptrPart = truthParticle;
700 break;
701 }
702 }
703 }
704 else {
705 for (T truthParticle : TruthContainer) {
706 if (HepMC::is_sim_descendant(p,truthParticle)) {
707 ptrPart = truthParticle;
708 break;
709 }
710 }
711 }
712 return ptrPart;
713 }
715
716 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
717 auto prodVtx = thePart->production_vertex();
718 if (!prodVtx) return;
719 for (const auto& theMother: prodVtx->particles_in()) {
720 if (!theMother) continue;
721 allancestors.insert(theMother);
722 findParticleAncestors(theMother, allancestors);
723 }
724 }
725
727
728 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
729 auto endVtx = thePart->end_vertex();
730 if (!endVtx) return;
731 for (const auto& theDaughter: endVtx->particles_out()) {
732 if (!theDaughter) continue;
733 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
734 allstabledescendants.insert(theDaughter);
735 }
736 findParticleStableDescendants(theDaughter, allstabledescendants);
737 }
738 }
739
743
744 template <class T> bool isHardScatteringVertex(T pVert) {
745 if (pVert == nullptr) return false;
746 T pV = pVert;
747 int numOfPartIn(0);
748 int pdg(0);
749
750 do {
751 pVert = pV;
752 auto incoming = pVert->particles_in();
753 numOfPartIn = incoming.size();
754 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
755 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
756
757 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
758
759 if (numOfPartIn == 2) {
760 auto incoming = pVert->particles_in();
761 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
762 }
763 return false;
764}
765
769
770 template <class T, class U>
771 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 : particles_in(vtx) ) {
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 563 of file HepMCHelpers.h.

582{
583 template <class VTX>
584 auto particles_in (const VTX* p) { return p->particles_in(); }
585 template <class VTX>
586 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
587
588 namespace Pythia8
589 {
591 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
592
593 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
594
595 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
596 }
597
598#include "AtlasPID.h"
599
601 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
602
604 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
605
607 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
608
610 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
611
613 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
614
616 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
617
619 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
620
622 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
623
625 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
626
628 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
629
633 template <class T> inline bool isStableOrSimDecayed(const T& p) {
634 const auto vertex = p->end_vertex();
635 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
636 }
637
639 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
640
642 template <class T> inline bool isSpecialNonInteracting(const T& p) {
643 const int apid = std::abs(p->pdg_id());
644 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
645 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
646 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
647 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
648 return false;
649 }
650
652
653 template <class T> T findMother(T thePart) {
654 auto partOriVert = thePart->production_vertex();
655 if (!partOriVert) return nullptr;
656
657 long partPDG = thePart->pdg_id();
658 long MotherPDG(0);
659
660 auto MothOriVert = partOriVert;
661 MothOriVert = nullptr;
662 T theMoth(nullptr);
663
664 size_t itr = 0;
665 do {
666 if (itr != 0) partOriVert = MothOriVert;
667 for ( const auto& p : particles_in(partOriVert) ) {
668 theMoth = p;
669 if (!theMoth) continue;
670 MotherPDG = theMoth->pdg_id();
671 MothOriVert = theMoth->production_vertex();
672 if (MotherPDG == partPDG) break;
673 }
674 itr++;
675 if (itr > 100) {
676 break;
677 }
678 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
679 MothOriVert != partOriVert);
680 return theMoth;
681 }
682
684
685 template <class C, class T> T findMatching(C TruthContainer, T p) {
686 T ptrPart = nullptr;
687 if (!p) return ptrPart;
688 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
689 for (T truthParticle : *TruthContainer) {
690 if (HepMC::is_sim_descendant(p,truthParticle)) {
691 ptrPart = truthParticle;
692 break;
693 }
694 }
695 }
696 else {
697 for (T truthParticle : TruthContainer) {
698 if (HepMC::is_sim_descendant(p,truthParticle)) {
699 ptrPart = truthParticle;
700 break;
701 }
702 }
703 }
704 return ptrPart;
705 }
707
708 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
709 auto prodVtx = thePart->production_vertex();
710 if (!prodVtx) return;
711 for (const auto& theMother: prodVtx->particles_in()) {
712 if (!theMother) continue;
713 allancestors.insert(theMother);
714 findParticleAncestors(theMother, allancestors);
715 }
716 }
717
719
720 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
721 auto endVtx = thePart->end_vertex();
722 if (!endVtx) return;
723 for (const auto& theDaughter: endVtx->particles_out()) {
724 if (!theDaughter) continue;
725 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
726 allstabledescendants.insert(theDaughter);
727 }
728 findParticleStableDescendants(theDaughter, allstabledescendants);
729 }
730 }
731
735
736 template <class T> bool isHardScatteringVertex(T pVert) {
737 if (pVert == nullptr) return false;
738 T pV = pVert;
739 int numOfPartIn(0);
740 int pdg(0);
741
742 do {
743 pVert = pV;
744 auto incoming = pVert->particles_in();
745 numOfPartIn = incoming.size();
746 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
747 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
748
749 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
750
751 if (numOfPartIn == 2) {
752 auto incoming = pVert->particles_in();
753 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
754 }
755 return false;
756}
757
761
762 template <class T, class U>
763 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 : particles_in(vtx) ) {
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 605 of file HepMCHelpers.h.

624{
625 template <class VTX>
626 auto particles_in (const VTX* p) { return p->particles_in(); }
627 template <class VTX>
628 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
805 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 : particles_in(vtx) ) {
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 608 of file HepMCHelpers.h.

627{
628 template <class VTX>
629 auto particles_in (const VTX* p) { return p->particles_in(); }
630 template <class VTX>
631 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
632
633 namespace Pythia8
634 {
636 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
637
638 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
639
640 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
641 }
642
643#include "AtlasPID.h"
644
646 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
647
649 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
650
652 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
653
655 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
656
658 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
659
661 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
662
664 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
665
667 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
668
670 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
671
673 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
674
678 template <class T> inline bool isStableOrSimDecayed(const T& p) {
679 const auto vertex = p->end_vertex();
680 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
681 }
682
684 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
685
687 template <class T> inline bool isSpecialNonInteracting(const T& p) {
688 const int apid = std::abs(p->pdg_id());
689 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
690 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
691 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
692 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
693 return false;
694 }
695
697
698 template <class T> T findMother(T thePart) {
699 auto partOriVert = thePart->production_vertex();
700 if (!partOriVert) return nullptr;
701
702 long partPDG = thePart->pdg_id();
703 long MotherPDG(0);
704
705 auto MothOriVert = partOriVert;
706 MothOriVert = nullptr;
707 T theMoth(nullptr);
708
709 size_t itr = 0;
710 do {
711 if (itr != 0) partOriVert = MothOriVert;
712 for ( const auto& p : particles_in(partOriVert) ) {
713 theMoth = p;
714 if (!theMoth) continue;
715 MotherPDG = theMoth->pdg_id();
716 MothOriVert = theMoth->production_vertex();
717 if (MotherPDG == partPDG) break;
718 }
719 itr++;
720 if (itr > 100) {
721 break;
722 }
723 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
724 MothOriVert != partOriVert);
725 return theMoth;
726 }
727
729
730 template <class C, class T> T findMatching(C TruthContainer, T p) {
731 T ptrPart = nullptr;
732 if (!p) return ptrPart;
733 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
734 for (T truthParticle : *TruthContainer) {
735 if (HepMC::is_sim_descendant(p,truthParticle)) {
736 ptrPart = truthParticle;
737 break;
738 }
739 }
740 }
741 else {
742 for (T truthParticle : TruthContainer) {
743 if (HepMC::is_sim_descendant(p,truthParticle)) {
744 ptrPart = truthParticle;
745 break;
746 }
747 }
748 }
749 return ptrPart;
750 }
752
753 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
754 auto prodVtx = thePart->production_vertex();
755 if (!prodVtx) return;
756 for (const auto& theMother: prodVtx->particles_in()) {
757 if (!theMother) continue;
758 allancestors.insert(theMother);
759 findParticleAncestors(theMother, allancestors);
760 }
761 }
762
764
765 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
766 auto endVtx = thePart->end_vertex();
767 if (!endVtx) return;
768 for (const auto& theDaughter: endVtx->particles_out()) {
769 if (!theDaughter) continue;
770 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
771 allstabledescendants.insert(theDaughter);
772 }
773 findParticleStableDescendants(theDaughter, allstabledescendants);
774 }
775 }
776
780
781 template <class T> bool isHardScatteringVertex(T pVert) {
782 if (pVert == nullptr) return false;
783 T pV = pVert;
784 int numOfPartIn(0);
785 int pdg(0);
786
787 do {
788 pVert = pV;
789 auto incoming = pVert->particles_in();
790 numOfPartIn = incoming.size();
791 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
792 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
793
794 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
795
796 if (numOfPartIn == 2) {
797 auto incoming = pVert->particles_in();
798 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
799 }
800 return false;
801}
802
806
807 template <class T, class U>
808 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 : particles_in(vtx) ) {
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 604 of file HepMCHelpers.h.

623{
624 template <class VTX>
625 auto particles_in (const VTX* p) { return p->particles_in(); }
626 template <class VTX>
627 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
628
629 namespace Pythia8
630 {
632 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
633
634 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
635
636 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
637 }
638
639#include "AtlasPID.h"
640
642 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
643
645 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
646
648 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
649
651 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
652
654 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
655
657 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
658
660 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
661
663 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
664
666 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
667
669 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
670
674 template <class T> inline bool isStableOrSimDecayed(const T& p) {
675 const auto vertex = p->end_vertex();
676 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
677 }
678
680 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
681
683 template <class T> inline bool isSpecialNonInteracting(const T& p) {
684 const int apid = std::abs(p->pdg_id());
685 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
686 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
687 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
688 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
689 return false;
690 }
691
693
694 template <class T> T findMother(T thePart) {
695 auto partOriVert = thePart->production_vertex();
696 if (!partOriVert) return nullptr;
697
698 long partPDG = thePart->pdg_id();
699 long MotherPDG(0);
700
701 auto MothOriVert = partOriVert;
702 MothOriVert = nullptr;
703 T theMoth(nullptr);
704
705 size_t itr = 0;
706 do {
707 if (itr != 0) partOriVert = MothOriVert;
708 for ( const auto& p : particles_in(partOriVert) ) {
709 theMoth = p;
710 if (!theMoth) continue;
711 MotherPDG = theMoth->pdg_id();
712 MothOriVert = theMoth->production_vertex();
713 if (MotherPDG == partPDG) break;
714 }
715 itr++;
716 if (itr > 100) {
717 break;
718 }
719 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
720 MothOriVert != partOriVert);
721 return theMoth;
722 }
723
725
726 template <class C, class T> T findMatching(C TruthContainer, T p) {
727 T ptrPart = nullptr;
728 if (!p) return ptrPart;
729 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
730 for (T truthParticle : *TruthContainer) {
731 if (HepMC::is_sim_descendant(p,truthParticle)) {
732 ptrPart = truthParticle;
733 break;
734 }
735 }
736 }
737 else {
738 for (T truthParticle : TruthContainer) {
739 if (HepMC::is_sim_descendant(p,truthParticle)) {
740 ptrPart = truthParticle;
741 break;
742 }
743 }
744 }
745 return ptrPart;
746 }
748
749 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
750 auto prodVtx = thePart->production_vertex();
751 if (!prodVtx) return;
752 for (const auto& theMother: prodVtx->particles_in()) {
753 if (!theMother) continue;
754 allancestors.insert(theMother);
755 findParticleAncestors(theMother, allancestors);
756 }
757 }
758
760
761 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
762 auto endVtx = thePart->end_vertex();
763 if (!endVtx) return;
764 for (const auto& theDaughter: endVtx->particles_out()) {
765 if (!theDaughter) continue;
766 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
767 allstabledescendants.insert(theDaughter);
768 }
769 findParticleStableDescendants(theDaughter, allstabledescendants);
770 }
771 }
772
776
777 template <class T> bool isHardScatteringVertex(T pVert) {
778 if (pVert == nullptr) return false;
779 T pV = pVert;
780 int numOfPartIn(0);
781 int pdg(0);
782
783 do {
784 pVert = pV;
785 auto incoming = pVert->particles_in();
786 numOfPartIn = incoming.size();
787 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
788 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
789
790 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
791
792 if (numOfPartIn == 2) {
793 auto incoming = pVert->particles_in();
794 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
795 }
796 return false;
797}
798
802
803 template <class T, class U>
804 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 : particles_in(vtx) ) {
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 576 of file HepMCHelpers.h.

595{
596 template <class VTX>
597 auto particles_in (const VTX* p) { return p->particles_in(); }
598 template <class VTX>
599 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
776 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 : particles_in(vtx) ) {
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 586 of file HepMCHelpers.h.

605{
606 template <class VTX>
607 auto particles_in (const VTX* p) { return p->particles_in(); }
608 template <class VTX>
609 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
610
611 namespace Pythia8
612 {
614 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
615
616 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
617
618 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
619 }
620
621#include "AtlasPID.h"
622
624 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
625
627 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
628
630 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
631
633 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
634
636 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
637
639 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
640
642 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
643
645 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
646
648 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
649
651 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
652
656 template <class T> inline bool isStableOrSimDecayed(const T& p) {
657 const auto vertex = p->end_vertex();
658 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
659 }
660
662 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
663
665 template <class T> inline bool isSpecialNonInteracting(const T& p) {
666 const int apid = std::abs(p->pdg_id());
667 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
668 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
669 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
670 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
671 return false;
672 }
673
675
676 template <class T> T findMother(T thePart) {
677 auto partOriVert = thePart->production_vertex();
678 if (!partOriVert) return nullptr;
679
680 long partPDG = thePart->pdg_id();
681 long MotherPDG(0);
682
683 auto MothOriVert = partOriVert;
684 MothOriVert = nullptr;
685 T theMoth(nullptr);
686
687 size_t itr = 0;
688 do {
689 if (itr != 0) partOriVert = MothOriVert;
690 for ( const auto& p : particles_in(partOriVert) ) {
691 theMoth = p;
692 if (!theMoth) continue;
693 MotherPDG = theMoth->pdg_id();
694 MothOriVert = theMoth->production_vertex();
695 if (MotherPDG == partPDG) break;
696 }
697 itr++;
698 if (itr > 100) {
699 break;
700 }
701 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
702 MothOriVert != partOriVert);
703 return theMoth;
704 }
705
707
708 template <class C, class T> T findMatching(C TruthContainer, T p) {
709 T ptrPart = nullptr;
710 if (!p) return ptrPart;
711 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
712 for (T truthParticle : *TruthContainer) {
713 if (HepMC::is_sim_descendant(p,truthParticle)) {
714 ptrPart = truthParticle;
715 break;
716 }
717 }
718 }
719 else {
720 for (T truthParticle : TruthContainer) {
721 if (HepMC::is_sim_descendant(p,truthParticle)) {
722 ptrPart = truthParticle;
723 break;
724 }
725 }
726 }
727 return ptrPart;
728 }
730
731 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
732 auto prodVtx = thePart->production_vertex();
733 if (!prodVtx) return;
734 for (const auto& theMother: prodVtx->particles_in()) {
735 if (!theMother) continue;
736 allancestors.insert(theMother);
737 findParticleAncestors(theMother, allancestors);
738 }
739 }
740
742
743 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
744 auto endVtx = thePart->end_vertex();
745 if (!endVtx) return;
746 for (const auto& theDaughter: endVtx->particles_out()) {
747 if (!theDaughter) continue;
748 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
749 allstabledescendants.insert(theDaughter);
750 }
751 findParticleStableDescendants(theDaughter, allstabledescendants);
752 }
753 }
754
758
759 template <class T> bool isHardScatteringVertex(T pVert) {
760 if (pVert == nullptr) return false;
761 T pV = pVert;
762 int numOfPartIn(0);
763 int pdg(0);
764
765 do {
766 pVert = pV;
767 auto incoming = pVert->particles_in();
768 numOfPartIn = incoming.size();
769 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
770 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
771
772 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
773
774 if (numOfPartIn == 2) {
775 auto incoming = pVert->particles_in();
776 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
777 }
778 return false;
779}
780
784
785 template <class T, class U>
786 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 : particles_in(vtx) ) {
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 575 of file HepMCHelpers.h.

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

66{ 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 63 of file HepMCHelpers.h.

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

◆ isSlepton() [1/3]

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

Definition at line 484 of file HepMCHelpers.h.

503{
504 template <class VTX>
505 auto particles_in (const VTX* p) { return p->particles_in(); }
506 template <class VTX>
507 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
684 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 : particles_in(vtx) ) {
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 485 of file HepMCHelpers.h.

504{
505 template <class VTX>
506 auto particles_in (const VTX* p) { return p->particles_in(); }
507 template <class VTX>
508 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
685 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 : particles_in(vtx) ) {
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 483 of file HepMCHelpers.h.

502{
503 template <class VTX>
504 auto particles_in (const VTX* p) { return p->particles_in(); }
505 template <class VTX>
506 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
507
508 namespace Pythia8
509 {
511 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
512
513 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
514
515 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
516 }
517
518#include "AtlasPID.h"
519
521 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
522
524 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
525
527 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
528
530 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
531
533 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
534
536 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
537
539 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
540
542 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
543
545 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
546
548 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
549
553 template <class T> inline bool isStableOrSimDecayed(const T& p) {
554 const auto vertex = p->end_vertex();
555 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
556 }
557
559 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
560
562 template <class T> inline bool isSpecialNonInteracting(const T& p) {
563 const int apid = std::abs(p->pdg_id());
564 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
565 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
566 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
567 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
568 return false;
569 }
570
572
573 template <class T> T findMother(T thePart) {
574 auto partOriVert = thePart->production_vertex();
575 if (!partOriVert) return nullptr;
576
577 long partPDG = thePart->pdg_id();
578 long MotherPDG(0);
579
580 auto MothOriVert = partOriVert;
581 MothOriVert = nullptr;
582 T theMoth(nullptr);
583
584 size_t itr = 0;
585 do {
586 if (itr != 0) partOriVert = MothOriVert;
587 for ( const auto& p : particles_in(partOriVert) ) {
588 theMoth = p;
589 if (!theMoth) continue;
590 MotherPDG = theMoth->pdg_id();
591 MothOriVert = theMoth->production_vertex();
592 if (MotherPDG == partPDG) break;
593 }
594 itr++;
595 if (itr > 100) {
596 break;
597 }
598 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
599 MothOriVert != partOriVert);
600 return theMoth;
601 }
602
604
605 template <class C, class T> T findMatching(C TruthContainer, T p) {
606 T ptrPart = nullptr;
607 if (!p) return ptrPart;
608 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
609 for (T truthParticle : *TruthContainer) {
610 if (HepMC::is_sim_descendant(p,truthParticle)) {
611 ptrPart = truthParticle;
612 break;
613 }
614 }
615 }
616 else {
617 for (T truthParticle : TruthContainer) {
618 if (HepMC::is_sim_descendant(p,truthParticle)) {
619 ptrPart = truthParticle;
620 break;
621 }
622 }
623 }
624 return ptrPart;
625 }
627
628 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
629 auto prodVtx = thePart->production_vertex();
630 if (!prodVtx) return;
631 for (const auto& theMother: prodVtx->particles_in()) {
632 if (!theMother) continue;
633 allancestors.insert(theMother);
634 findParticleAncestors(theMother, allancestors);
635 }
636 }
637
639
640 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
641 auto endVtx = thePart->end_vertex();
642 if (!endVtx) return;
643 for (const auto& theDaughter: endVtx->particles_out()) {
644 if (!theDaughter) continue;
645 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
646 allstabledescendants.insert(theDaughter);
647 }
648 findParticleStableDescendants(theDaughter, allstabledescendants);
649 }
650 }
651
655
656 template <class T> bool isHardScatteringVertex(T pVert) {
657 if (pVert == nullptr) return false;
658 T pV = pVert;
659 int numOfPartIn(0);
660 int pdg(0);
661
662 do {
663 pVert = pV;
664 auto incoming = pVert->particles_in();
665 numOfPartIn = incoming.size();
666 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
667 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
668
669 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
670
671 if (numOfPartIn == 2) {
672 auto incoming = pVert->particles_in();
673 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
674 }
675 return false;
676}
677
681
682 template <class T, class U>
683 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 : particles_in(vtx) ) {
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 490 of file HepMCHelpers.h.

509{
510 template <class VTX>
511 auto particles_in (const VTX* p) { return p->particles_in(); }
512 template <class VTX>
513 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
690 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 : particles_in(vtx) ) {
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 493 of file HepMCHelpers.h.

512{
513 template <class VTX>
514 auto particles_in (const VTX* p) { return p->particles_in(); }
515 template <class VTX>
516 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
517
518 namespace Pythia8
519 {
521 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
522
523 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
524
525 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
526 }
527
528#include "AtlasPID.h"
529
531 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
532
534 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
535
537 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
538
540 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
541
543 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
544
546 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
547
549 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
550
552 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
553
555 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
556
558 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
559
563 template <class T> inline bool isStableOrSimDecayed(const T& p) {
564 const auto vertex = p->end_vertex();
565 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
566 }
567
569 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
570
572 template <class T> inline bool isSpecialNonInteracting(const T& p) {
573 const int apid = std::abs(p->pdg_id());
574 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
575 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
576 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
577 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
578 return false;
579 }
580
582
583 template <class T> T findMother(T thePart) {
584 auto partOriVert = thePart->production_vertex();
585 if (!partOriVert) return nullptr;
586
587 long partPDG = thePart->pdg_id();
588 long MotherPDG(0);
589
590 auto MothOriVert = partOriVert;
591 MothOriVert = nullptr;
592 T theMoth(nullptr);
593
594 size_t itr = 0;
595 do {
596 if (itr != 0) partOriVert = MothOriVert;
597 for ( const auto& p : particles_in(partOriVert) ) {
598 theMoth = p;
599 if (!theMoth) continue;
600 MotherPDG = theMoth->pdg_id();
601 MothOriVert = theMoth->production_vertex();
602 if (MotherPDG == partPDG) break;
603 }
604 itr++;
605 if (itr > 100) {
606 break;
607 }
608 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
609 MothOriVert != partOriVert);
610 return theMoth;
611 }
612
614
615 template <class C, class T> T findMatching(C TruthContainer, T p) {
616 T ptrPart = nullptr;
617 if (!p) return ptrPart;
618 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
619 for (T truthParticle : *TruthContainer) {
620 if (HepMC::is_sim_descendant(p,truthParticle)) {
621 ptrPart = truthParticle;
622 break;
623 }
624 }
625 }
626 else {
627 for (T truthParticle : TruthContainer) {
628 if (HepMC::is_sim_descendant(p,truthParticle)) {
629 ptrPart = truthParticle;
630 break;
631 }
632 }
633 }
634 return ptrPart;
635 }
637
638 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
639 auto prodVtx = thePart->production_vertex();
640 if (!prodVtx) return;
641 for (const auto& theMother: prodVtx->particles_in()) {
642 if (!theMother) continue;
643 allancestors.insert(theMother);
644 findParticleAncestors(theMother, allancestors);
645 }
646 }
647
649
650 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
651 auto endVtx = thePart->end_vertex();
652 if (!endVtx) return;
653 for (const auto& theDaughter: endVtx->particles_out()) {
654 if (!theDaughter) continue;
655 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
656 allstabledescendants.insert(theDaughter);
657 }
658 findParticleStableDescendants(theDaughter, allstabledescendants);
659 }
660 }
661
665
666 template <class T> bool isHardScatteringVertex(T pVert) {
667 if (pVert == nullptr) return false;
668 T pV = pVert;
669 int numOfPartIn(0);
670 int pdg(0);
671
672 do {
673 pVert = pV;
674 auto incoming = pVert->particles_in();
675 numOfPartIn = incoming.size();
676 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
677 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
678
679 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
680
681 if (numOfPartIn == 2) {
682 auto incoming = pVert->particles_in();
683 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
684 }
685 return false;
686}
687
691
692 template <class T, class U>
693 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 : particles_in(vtx) ) {
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 489 of file HepMCHelpers.h.

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

517{
518 template <class VTX>
519 auto particles_in (const VTX* p) { return p->particles_in(); }
520 template <class VTX>
521 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
698 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 : particles_in(vtx) ) {
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 501 of file HepMCHelpers.h.

520{
521 template <class VTX>
522 auto particles_in (const VTX* p) { return p->particles_in(); }
523 template <class VTX>
524 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
525
526 namespace Pythia8
527 {
529 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
530
531 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
532
533 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
534 }
535
536#include "AtlasPID.h"
537
539 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
540
542 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
543
545 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
546
548 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
549
551 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
552
554 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
555
557 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
558
560 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
561
563 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
564
566 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
567
571 template <class T> inline bool isStableOrSimDecayed(const T& p) {
572 const auto vertex = p->end_vertex();
573 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
574 }
575
577 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
578
580 template <class T> inline bool isSpecialNonInteracting(const T& p) {
581 const int apid = std::abs(p->pdg_id());
582 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
583 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
584 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
585 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
586 return false;
587 }
588
590
591 template <class T> T findMother(T thePart) {
592 auto partOriVert = thePart->production_vertex();
593 if (!partOriVert) return nullptr;
594
595 long partPDG = thePart->pdg_id();
596 long MotherPDG(0);
597
598 auto MothOriVert = partOriVert;
599 MothOriVert = nullptr;
600 T theMoth(nullptr);
601
602 size_t itr = 0;
603 do {
604 if (itr != 0) partOriVert = MothOriVert;
605 for ( const auto& p : particles_in(partOriVert) ) {
606 theMoth = p;
607 if (!theMoth) continue;
608 MotherPDG = theMoth->pdg_id();
609 MothOriVert = theMoth->production_vertex();
610 if (MotherPDG == partPDG) break;
611 }
612 itr++;
613 if (itr > 100) {
614 break;
615 }
616 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
617 MothOriVert != partOriVert);
618 return theMoth;
619 }
620
622
623 template <class C, class T> T findMatching(C TruthContainer, T p) {
624 T ptrPart = nullptr;
625 if (!p) return ptrPart;
626 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
627 for (T truthParticle : *TruthContainer) {
628 if (HepMC::is_sim_descendant(p,truthParticle)) {
629 ptrPart = truthParticle;
630 break;
631 }
632 }
633 }
634 else {
635 for (T truthParticle : TruthContainer) {
636 if (HepMC::is_sim_descendant(p,truthParticle)) {
637 ptrPart = truthParticle;
638 break;
639 }
640 }
641 }
642 return ptrPart;
643 }
645
646 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
647 auto prodVtx = thePart->production_vertex();
648 if (!prodVtx) return;
649 for (const auto& theMother: prodVtx->particles_in()) {
650 if (!theMother) continue;
651 allancestors.insert(theMother);
652 findParticleAncestors(theMother, allancestors);
653 }
654 }
655
657
658 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
659 auto endVtx = thePart->end_vertex();
660 if (!endVtx) return;
661 for (const auto& theDaughter: endVtx->particles_out()) {
662 if (!theDaughter) continue;
663 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
664 allstabledescendants.insert(theDaughter);
665 }
666 findParticleStableDescendants(theDaughter, allstabledescendants);
667 }
668 }
669
673
674 template <class T> bool isHardScatteringVertex(T pVert) {
675 if (pVert == nullptr) return false;
676 T pV = pVert;
677 int numOfPartIn(0);
678 int pdg(0);
679
680 do {
681 pVert = pV;
682 auto incoming = pVert->particles_in();
683 numOfPartIn = incoming.size();
684 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
685 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
686
687 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
688
689 if (numOfPartIn == 2) {
690 auto incoming = pVert->particles_in();
691 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
692 }
693 return false;
694}
695
699
700 template <class T, class U>
701 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 : particles_in(vtx) ) {
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 497 of file HepMCHelpers.h.

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

◆ isSMLepton() [2/3]

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

Definition at line 196 of file HepMCHelpers.h.

◆ isSMLepton() [3/3]

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

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

Definition at line 195 of file HepMCHelpers.h.

◆ isSMNeutrino() [1/2]

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

Definition at line 217 of file HepMCHelpers.h.

◆ isSMNeutrino() [2/2]

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

Definition at line 216 of file HepMCHelpers.h.

◆ isSMQuark() [1/3]

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

Definition at line 175 of file HepMCHelpers.h.

◆ isSMQuark() [2/3]

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

Definition at line 174 of file HepMCHelpers.h.

174{

◆ isSMQuark() [3/3]

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

Definition at line 173 of file HepMCHelpers.h.

◆ isSpecialNonInteracting()

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

Identify a special non-interacting particles.

Definition at line 80 of file HepMCHelpers.h.

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

◆ isSquark() [1/3]

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

Definition at line 460 of file HepMCHelpers.h.

479{
480 template <class VTX>
481 auto particles_in (const VTX* p) { return p->particles_in(); }
482 template <class VTX>
483 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
660 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 : particles_in(vtx) ) {
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 463 of file HepMCHelpers.h.

482{
483 template <class VTX>
484 auto particles_in (const VTX* p) { return p->particles_in(); }
485 template <class VTX>
486 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
487
488 namespace Pythia8
489 {
491 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
492
493 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
494
495 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
496 }
497
498#include "AtlasPID.h"
499
501 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
502
504 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
505
507 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
508
510 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
511
513 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
514
516 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
517
519 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
520
522 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
523
525 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
526
528 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
529
533 template <class T> inline bool isStableOrSimDecayed(const T& p) {
534 const auto vertex = p->end_vertex();
535 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
536 }
537
539 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
540
542 template <class T> inline bool isSpecialNonInteracting(const T& p) {
543 const int apid = std::abs(p->pdg_id());
544 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
545 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
546 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
547 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
548 return false;
549 }
550
552
553 template <class T> T findMother(T thePart) {
554 auto partOriVert = thePart->production_vertex();
555 if (!partOriVert) return nullptr;
556
557 long partPDG = thePart->pdg_id();
558 long MotherPDG(0);
559
560 auto MothOriVert = partOriVert;
561 MothOriVert = nullptr;
562 T theMoth(nullptr);
563
564 size_t itr = 0;
565 do {
566 if (itr != 0) partOriVert = MothOriVert;
567 for ( const auto& p : particles_in(partOriVert) ) {
568 theMoth = p;
569 if (!theMoth) continue;
570 MotherPDG = theMoth->pdg_id();
571 MothOriVert = theMoth->production_vertex();
572 if (MotherPDG == partPDG) break;
573 }
574 itr++;
575 if (itr > 100) {
576 break;
577 }
578 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
579 MothOriVert != partOriVert);
580 return theMoth;
581 }
582
584
585 template <class C, class T> T findMatching(C TruthContainer, T p) {
586 T ptrPart = nullptr;
587 if (!p) return ptrPart;
588 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
589 for (T truthParticle : *TruthContainer) {
590 if (HepMC::is_sim_descendant(p,truthParticle)) {
591 ptrPart = truthParticle;
592 break;
593 }
594 }
595 }
596 else {
597 for (T truthParticle : TruthContainer) {
598 if (HepMC::is_sim_descendant(p,truthParticle)) {
599 ptrPart = truthParticle;
600 break;
601 }
602 }
603 }
604 return ptrPart;
605 }
607
608 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
609 auto prodVtx = thePart->production_vertex();
610 if (!prodVtx) return;
611 for (const auto& theMother: prodVtx->particles_in()) {
612 if (!theMother) continue;
613 allancestors.insert(theMother);
614 findParticleAncestors(theMother, allancestors);
615 }
616 }
617
619
620 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
621 auto endVtx = thePart->end_vertex();
622 if (!endVtx) return;
623 for (const auto& theDaughter: endVtx->particles_out()) {
624 if (!theDaughter) continue;
625 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
626 allstabledescendants.insert(theDaughter);
627 }
628 findParticleStableDescendants(theDaughter, allstabledescendants);
629 }
630 }
631
635
636 template <class T> bool isHardScatteringVertex(T pVert) {
637 if (pVert == nullptr) return false;
638 T pV = pVert;
639 int numOfPartIn(0);
640 int pdg(0);
641
642 do {
643 pVert = pV;
644 auto incoming = pVert->particles_in();
645 numOfPartIn = incoming.size();
646 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
647 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
648
649 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
650
651 if (numOfPartIn == 2) {
652 auto incoming = pVert->particles_in();
653 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
654 }
655 return false;
656}
657
661
662 template <class T, class U>
663 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 : particles_in(vtx) ) {
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 459 of file HepMCHelpers.h.

478{
479 template <class VTX>
480 auto particles_in (const VTX* p) { return p->particles_in(); }
481 template <class VTX>
482 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
483
484 namespace Pythia8
485 {
487 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
488
489 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
490
491 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
492 }
493
494#include "AtlasPID.h"
495
497 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
498
500 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
501
503 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
504
506 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
507
509 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
510
512 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
513
515 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
516
518 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
519
521 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
522
524 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
525
529 template <class T> inline bool isStableOrSimDecayed(const T& p) {
530 const auto vertex = p->end_vertex();
531 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
532 }
533
535 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
536
538 template <class T> inline bool isSpecialNonInteracting(const T& p) {
539 const int apid = std::abs(p->pdg_id());
540 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
541 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
542 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
543 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
544 return false;
545 }
546
548
549 template <class T> T findMother(T thePart) {
550 auto partOriVert = thePart->production_vertex();
551 if (!partOriVert) return nullptr;
552
553 long partPDG = thePart->pdg_id();
554 long MotherPDG(0);
555
556 auto MothOriVert = partOriVert;
557 MothOriVert = nullptr;
558 T theMoth(nullptr);
559
560 size_t itr = 0;
561 do {
562 if (itr != 0) partOriVert = MothOriVert;
563 for ( const auto& p : particles_in(partOriVert) ) {
564 theMoth = p;
565 if (!theMoth) continue;
566 MotherPDG = theMoth->pdg_id();
567 MothOriVert = theMoth->production_vertex();
568 if (MotherPDG == partPDG) break;
569 }
570 itr++;
571 if (itr > 100) {
572 break;
573 }
574 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
575 MothOriVert != partOriVert);
576 return theMoth;
577 }
578
580
581 template <class C, class T> T findMatching(C TruthContainer, T p) {
582 T ptrPart = nullptr;
583 if (!p) return ptrPart;
584 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
585 for (T truthParticle : *TruthContainer) {
586 if (HepMC::is_sim_descendant(p,truthParticle)) {
587 ptrPart = truthParticle;
588 break;
589 }
590 }
591 }
592 else {
593 for (T truthParticle : TruthContainer) {
594 if (HepMC::is_sim_descendant(p,truthParticle)) {
595 ptrPart = truthParticle;
596 break;
597 }
598 }
599 }
600 return ptrPart;
601 }
603
604 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
605 auto prodVtx = thePart->production_vertex();
606 if (!prodVtx) return;
607 for (const auto& theMother: prodVtx->particles_in()) {
608 if (!theMother) continue;
609 allancestors.insert(theMother);
610 findParticleAncestors(theMother, allancestors);
611 }
612 }
613
615
616 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
617 auto endVtx = thePart->end_vertex();
618 if (!endVtx) return;
619 for (const auto& theDaughter: endVtx->particles_out()) {
620 if (!theDaughter) continue;
621 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
622 allstabledescendants.insert(theDaughter);
623 }
624 findParticleStableDescendants(theDaughter, allstabledescendants);
625 }
626 }
627
631
632 template <class T> bool isHardScatteringVertex(T pVert) {
633 if (pVert == nullptr) return false;
634 T pV = pVert;
635 int numOfPartIn(0);
636 int pdg(0);
637
638 do {
639 pVert = pV;
640 auto incoming = pVert->particles_in();
641 numOfPartIn = incoming.size();
642 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
643 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
644
645 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
646
647 if (numOfPartIn == 2) {
648 auto incoming = pVert->particles_in();
649 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
650 }
651 return false;
652}
653
657
658 template <class T, class U>
659 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 : particles_in(vtx) ) {
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 468 of file HepMCHelpers.h.

487{
488 template <class VTX>
489 auto particles_in (const VTX* p) { return p->particles_in(); }
490 template <class VTX>
491 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
668 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 : particles_in(vtx) ) {
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 471 of file HepMCHelpers.h.

490{
491 template <class VTX>
492 auto particles_in (const VTX* p) { return p->particles_in(); }
493 template <class VTX>
494 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
495
496 namespace Pythia8
497 {
499 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
500
501 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
502
503 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
504 }
505
506#include "AtlasPID.h"
507
509 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
510
512 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
513
515 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
516
518 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
519
521 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
522
524 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
525
527 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
528
530 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
531
533 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
534
536 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
537
541 template <class T> inline bool isStableOrSimDecayed(const T& p) {
542 const auto vertex = p->end_vertex();
543 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
544 }
545
547 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
548
550 template <class T> inline bool isSpecialNonInteracting(const T& p) {
551 const int apid = std::abs(p->pdg_id());
552 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
553 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
554 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
555 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
556 return false;
557 }
558
560
561 template <class T> T findMother(T thePart) {
562 auto partOriVert = thePart->production_vertex();
563 if (!partOriVert) return nullptr;
564
565 long partPDG = thePart->pdg_id();
566 long MotherPDG(0);
567
568 auto MothOriVert = partOriVert;
569 MothOriVert = nullptr;
570 T theMoth(nullptr);
571
572 size_t itr = 0;
573 do {
574 if (itr != 0) partOriVert = MothOriVert;
575 for ( const auto& p : particles_in(partOriVert) ) {
576 theMoth = p;
577 if (!theMoth) continue;
578 MotherPDG = theMoth->pdg_id();
579 MothOriVert = theMoth->production_vertex();
580 if (MotherPDG == partPDG) break;
581 }
582 itr++;
583 if (itr > 100) {
584 break;
585 }
586 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
587 MothOriVert != partOriVert);
588 return theMoth;
589 }
590
592
593 template <class C, class T> T findMatching(C TruthContainer, T p) {
594 T ptrPart = nullptr;
595 if (!p) return ptrPart;
596 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
597 for (T truthParticle : *TruthContainer) {
598 if (HepMC::is_sim_descendant(p,truthParticle)) {
599 ptrPart = truthParticle;
600 break;
601 }
602 }
603 }
604 else {
605 for (T truthParticle : TruthContainer) {
606 if (HepMC::is_sim_descendant(p,truthParticle)) {
607 ptrPart = truthParticle;
608 break;
609 }
610 }
611 }
612 return ptrPart;
613 }
615
616 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
617 auto prodVtx = thePart->production_vertex();
618 if (!prodVtx) return;
619 for (const auto& theMother: prodVtx->particles_in()) {
620 if (!theMother) continue;
621 allancestors.insert(theMother);
622 findParticleAncestors(theMother, allancestors);
623 }
624 }
625
627
628 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
629 auto endVtx = thePart->end_vertex();
630 if (!endVtx) return;
631 for (const auto& theDaughter: endVtx->particles_out()) {
632 if (!theDaughter) continue;
633 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
634 allstabledescendants.insert(theDaughter);
635 }
636 findParticleStableDescendants(theDaughter, allstabledescendants);
637 }
638 }
639
643
644 template <class T> bool isHardScatteringVertex(T pVert) {
645 if (pVert == nullptr) return false;
646 T pV = pVert;
647 int numOfPartIn(0);
648 int pdg(0);
649
650 do {
651 pVert = pV;
652 auto incoming = pVert->particles_in();
653 numOfPartIn = incoming.size();
654 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
655 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
656
657 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
658
659 if (numOfPartIn == 2) {
660 auto incoming = pVert->particles_in();
661 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
662 }
663 return false;
664}
665
669
670 template <class T, class U>
671 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 : particles_in(vtx) ) {
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 467 of file HepMCHelpers.h.

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

495{
496 template <class VTX>
497 auto particles_in (const VTX* p) { return p->particles_in(); }
498 template <class VTX>
499 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
676 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 : particles_in(vtx) ) {
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 479 of file HepMCHelpers.h.

498{
499 template <class VTX>
500 auto particles_in (const VTX* p) { return p->particles_in(); }
501 template <class VTX>
502 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
503
504 namespace Pythia8
505 {
507 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
508
509 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
510
511 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
512 }
513
514#include "AtlasPID.h"
515
517 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
518
520 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
521
523 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
524
526 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
527
529 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
530
532 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
533
535 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
536
538 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
539
541 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
542
544 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
545
549 template <class T> inline bool isStableOrSimDecayed(const T& p) {
550 const auto vertex = p->end_vertex();
551 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
552 }
553
555 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
556
558 template <class T> inline bool isSpecialNonInteracting(const T& p) {
559 const int apid = std::abs(p->pdg_id());
560 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
561 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
562 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
563 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
564 return false;
565 }
566
568
569 template <class T> T findMother(T thePart) {
570 auto partOriVert = thePart->production_vertex();
571 if (!partOriVert) return nullptr;
572
573 long partPDG = thePart->pdg_id();
574 long MotherPDG(0);
575
576 auto MothOriVert = partOriVert;
577 MothOriVert = nullptr;
578 T theMoth(nullptr);
579
580 size_t itr = 0;
581 do {
582 if (itr != 0) partOriVert = MothOriVert;
583 for ( const auto& p : particles_in(partOriVert) ) {
584 theMoth = p;
585 if (!theMoth) continue;
586 MotherPDG = theMoth->pdg_id();
587 MothOriVert = theMoth->production_vertex();
588 if (MotherPDG == partPDG) break;
589 }
590 itr++;
591 if (itr > 100) {
592 break;
593 }
594 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
595 MothOriVert != partOriVert);
596 return theMoth;
597 }
598
600
601 template <class C, class T> T findMatching(C TruthContainer, T p) {
602 T ptrPart = nullptr;
603 if (!p) return ptrPart;
604 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
605 for (T truthParticle : *TruthContainer) {
606 if (HepMC::is_sim_descendant(p,truthParticle)) {
607 ptrPart = truthParticle;
608 break;
609 }
610 }
611 }
612 else {
613 for (T truthParticle : TruthContainer) {
614 if (HepMC::is_sim_descendant(p,truthParticle)) {
615 ptrPart = truthParticle;
616 break;
617 }
618 }
619 }
620 return ptrPart;
621 }
623
624 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
625 auto prodVtx = thePart->production_vertex();
626 if (!prodVtx) return;
627 for (const auto& theMother: prodVtx->particles_in()) {
628 if (!theMother) continue;
629 allancestors.insert(theMother);
630 findParticleAncestors(theMother, allancestors);
631 }
632 }
633
635
636 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
637 auto endVtx = thePart->end_vertex();
638 if (!endVtx) return;
639 for (const auto& theDaughter: endVtx->particles_out()) {
640 if (!theDaughter) continue;
641 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
642 allstabledescendants.insert(theDaughter);
643 }
644 findParticleStableDescendants(theDaughter, allstabledescendants);
645 }
646 }
647
651
652 template <class T> bool isHardScatteringVertex(T pVert) {
653 if (pVert == nullptr) return false;
654 T pV = pVert;
655 int numOfPartIn(0);
656 int pdg(0);
657
658 do {
659 pVert = pV;
660 auto incoming = pVert->particles_in();
661 numOfPartIn = incoming.size();
662 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
663 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
664
665 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
666
667 if (numOfPartIn == 2) {
668 auto incoming = pVert->particles_in();
669 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
670 }
671 return false;
672}
673
677
678 template <class T, class U>
679 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 : particles_in(vtx) ) {
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 475 of file HepMCHelpers.h.

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

71 {
72 const auto vertex = p->end_vertex();
73 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
74 }

◆ isStrange() [1/2]

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

Definition at line 178 of file HepMCHelpers.h.

◆ isStrange() [2/2]

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

Definition at line 177 of file HepMCHelpers.h.

◆ isStrangeBaryon()

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

Definition at line 934 of file HepMCHelpers.h.

953{
954 template <class VTX>
955 auto particles_in (const VTX* p) { return p->particles_in(); }
956 template <class VTX>
957 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1134 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 : particles_in(vtx) ) {
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 911 of file HepMCHelpers.h.

930{
931 template <class VTX>
932 auto particles_in (const VTX* p) { return p->particles_in(); }
933 template <class VTX>
934 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1111 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 : particles_in(vtx) ) {
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 918 of file HepMCHelpers.h.

937{
938 template <class VTX>
939 auto particles_in (const VTX* p) { return p->particles_in(); }
940 template <class VTX>
941 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1118 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 : particles_in(vtx) ) {
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 1185 of file HepMCHelpers.h.

1204{
1205 template <class VTX>
1206 auto particles_in (const VTX* p) { return p->particles_in(); }
1207 template <class VTX>
1208 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1385 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1386 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1387 auto vtx = p->production_vertex();
1388 if (!vtx) return false;
1389 bool fromHad = false;
1390 for ( const auto& parent : particles_in(vtx) ) {
1391 if (!parent) continue;
1392 // should this really go into parton-level territory?
1393 // probably depends where BSM particles are being decayed
1394 fromBSM |= isBSM(parent);
1395 if (!isPhysical(parent)) return false;
1396 fromTau |= isTau(parent);
1397 if (isHadron(parent)&&!isBeam(parent)) {
1398 if (!hadron) hadron = parent; // assumes linear hadron parentage
1399 return true;
1400 }
1401 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1402 }
1403 return fromHad;
1404 }
1405
1408
1409 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1410 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1411 decltype(thePart->end_vertex()) pVert(nullptr);
1412 if (EndVert != nullptr) {
1413 do {
1414 bool samePart = false;
1415 pVert = nullptr;
1416 auto outgoing = EndVert->particles_out();
1417 auto incoming = EndVert->particles_in();
1418 for (const auto& itrDaug: outgoing) {
1419 if (!itrDaug) continue;
1420 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1421 // brem on generator level for tau
1422 (outgoing.size() == 1 && incoming.size() == 1 &&
1424 itrDaug->pdg_id() == thePart->pdg_id()) {
1425 samePart = true;
1426 pVert = itrDaug->end_vertex();
1427 }
1428 }
1429 if (samePart) EndVert = pVert;
1430 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1431 }
1432 return EndVert;
1433 }
1434
1436
1437 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1438 if (!theVert) return {};
1439 decltype(theVert->particles_out()) finalStatePart;
1440 auto outgoing = theVert->particles_out();
1441 for (const auto& thePart: outgoing) {
1442 if (!thePart) continue;
1443 finalStatePart.push_back(thePart);
1444 if (isStable(thePart)) continue;
1445 V pVert = findSimulatedEndVertex(thePart);
1446 if (pVert == theVert) break; // to prevent Sherpa loop
1447 if (pVert != nullptr) {
1448 auto vecPart = findFinalStateParticles<V>(pVert);
1449 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1450 }
1451 }
1452 return finalStatePart;
1453 }
1454#if !defined(XAOD_ANALYSIS)
1455#include "AtlasHepMC/GenEvent.h"
1456inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1457inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1458
1459#endif
1460}
1461#endif

◆ isStrongInteracting() [2/2]

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

Definition at line 1184 of file HepMCHelpers.h.

1203{
1204 template <class VTX>
1205 auto particles_in (const VTX* p) { return p->particles_in(); }
1206 template <class VTX>
1207 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1384 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 : particles_in(vtx) ) {
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

◆ isSuperpartner() [1/3]

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

Definition at line 514 of file HepMCHelpers.h.

533{
534 template <class VTX>
535 auto particles_in (const VTX* p) { return p->particles_in(); }
536 template <class VTX>
537 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
714 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 : particles_in(vtx) ) {
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 517 of file HepMCHelpers.h.

536{
537 template <class VTX>
538 auto particles_in (const VTX* p) { return p->particles_in(); }
539 template <class VTX>
540 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
541
542 namespace Pythia8
543 {
545 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
546
547 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
548
549 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
550 }
551
552#include "AtlasPID.h"
553
555 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
556
558 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
559
561 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
562
564 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
565
567 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
568
570 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
571
573 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
574
576 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
577
579 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
580
582 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
583
587 template <class T> inline bool isStableOrSimDecayed(const T& p) {
588 const auto vertex = p->end_vertex();
589 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
590 }
591
593 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
594
596 template <class T> inline bool isSpecialNonInteracting(const T& p) {
597 const int apid = std::abs(p->pdg_id());
598 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
599 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
600 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
601 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
602 return false;
603 }
604
606
607 template <class T> T findMother(T thePart) {
608 auto partOriVert = thePart->production_vertex();
609 if (!partOriVert) return nullptr;
610
611 long partPDG = thePart->pdg_id();
612 long MotherPDG(0);
613
614 auto MothOriVert = partOriVert;
615 MothOriVert = nullptr;
616 T theMoth(nullptr);
617
618 size_t itr = 0;
619 do {
620 if (itr != 0) partOriVert = MothOriVert;
621 for ( const auto& p : particles_in(partOriVert) ) {
622 theMoth = p;
623 if (!theMoth) continue;
624 MotherPDG = theMoth->pdg_id();
625 MothOriVert = theMoth->production_vertex();
626 if (MotherPDG == partPDG) break;
627 }
628 itr++;
629 if (itr > 100) {
630 break;
631 }
632 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
633 MothOriVert != partOriVert);
634 return theMoth;
635 }
636
638
639 template <class C, class T> T findMatching(C TruthContainer, T p) {
640 T ptrPart = nullptr;
641 if (!p) return ptrPart;
642 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
643 for (T truthParticle : *TruthContainer) {
644 if (HepMC::is_sim_descendant(p,truthParticle)) {
645 ptrPart = truthParticle;
646 break;
647 }
648 }
649 }
650 else {
651 for (T truthParticle : TruthContainer) {
652 if (HepMC::is_sim_descendant(p,truthParticle)) {
653 ptrPart = truthParticle;
654 break;
655 }
656 }
657 }
658 return ptrPart;
659 }
661
662 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
663 auto prodVtx = thePart->production_vertex();
664 if (!prodVtx) return;
665 for (const auto& theMother: prodVtx->particles_in()) {
666 if (!theMother) continue;
667 allancestors.insert(theMother);
668 findParticleAncestors(theMother, allancestors);
669 }
670 }
671
673
674 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
675 auto endVtx = thePart->end_vertex();
676 if (!endVtx) return;
677 for (const auto& theDaughter: endVtx->particles_out()) {
678 if (!theDaughter) continue;
679 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
680 allstabledescendants.insert(theDaughter);
681 }
682 findParticleStableDescendants(theDaughter, allstabledescendants);
683 }
684 }
685
689
690 template <class T> bool isHardScatteringVertex(T pVert) {
691 if (pVert == nullptr) return false;
692 T pV = pVert;
693 int numOfPartIn(0);
694 int pdg(0);
695
696 do {
697 pVert = pV;
698 auto incoming = pVert->particles_in();
699 numOfPartIn = incoming.size();
700 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
701 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
702
703 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
704
705 if (numOfPartIn == 2) {
706 auto incoming = pVert->particles_in();
707 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
708 }
709 return false;
710}
711
715
716 template <class T, class U>
717 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 : particles_in(vtx) ) {
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 513 of file HepMCHelpers.h.

532{
533 template <class VTX>
534 auto particles_in (const VTX* p) { return p->particles_in(); }
535 template <class VTX>
536 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
537
538 namespace Pythia8
539 {
541 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
542
543 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
544
545 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
546 }
547
548#include "AtlasPID.h"
549
551 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
552
554 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
555
557 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
558
560 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
561
563 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
564
566 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
567
569 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
570
572 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
573
575 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
576
578 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
579
583 template <class T> inline bool isStableOrSimDecayed(const T& p) {
584 const auto vertex = p->end_vertex();
585 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
586 }
587
589 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
590
592 template <class T> inline bool isSpecialNonInteracting(const T& p) {
593 const int apid = std::abs(p->pdg_id());
594 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
595 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
596 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
597 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
598 return false;
599 }
600
602
603 template <class T> T findMother(T thePart) {
604 auto partOriVert = thePart->production_vertex();
605 if (!partOriVert) return nullptr;
606
607 long partPDG = thePart->pdg_id();
608 long MotherPDG(0);
609
610 auto MothOriVert = partOriVert;
611 MothOriVert = nullptr;
612 T theMoth(nullptr);
613
614 size_t itr = 0;
615 do {
616 if (itr != 0) partOriVert = MothOriVert;
617 for ( const auto& p : particles_in(partOriVert) ) {
618 theMoth = p;
619 if (!theMoth) continue;
620 MotherPDG = theMoth->pdg_id();
621 MothOriVert = theMoth->production_vertex();
622 if (MotherPDG == partPDG) break;
623 }
624 itr++;
625 if (itr > 100) {
626 break;
627 }
628 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
629 MothOriVert != partOriVert);
630 return theMoth;
631 }
632
634
635 template <class C, class T> T findMatching(C TruthContainer, T p) {
636 T ptrPart = nullptr;
637 if (!p) return ptrPart;
638 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
639 for (T truthParticle : *TruthContainer) {
640 if (HepMC::is_sim_descendant(p,truthParticle)) {
641 ptrPart = truthParticle;
642 break;
643 }
644 }
645 }
646 else {
647 for (T truthParticle : TruthContainer) {
648 if (HepMC::is_sim_descendant(p,truthParticle)) {
649 ptrPart = truthParticle;
650 break;
651 }
652 }
653 }
654 return ptrPart;
655 }
657
658 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
659 auto prodVtx = thePart->production_vertex();
660 if (!prodVtx) return;
661 for (const auto& theMother: prodVtx->particles_in()) {
662 if (!theMother) continue;
663 allancestors.insert(theMother);
664 findParticleAncestors(theMother, allancestors);
665 }
666 }
667
669
670 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
671 auto endVtx = thePart->end_vertex();
672 if (!endVtx) return;
673 for (const auto& theDaughter: endVtx->particles_out()) {
674 if (!theDaughter) continue;
675 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
676 allstabledescendants.insert(theDaughter);
677 }
678 findParticleStableDescendants(theDaughter, allstabledescendants);
679 }
680 }
681
685
686 template <class T> bool isHardScatteringVertex(T pVert) {
687 if (pVert == nullptr) return false;
688 T pV = pVert;
689 int numOfPartIn(0);
690 int pdg(0);
691
692 do {
693 pVert = pV;
694 auto incoming = pVert->particles_in();
695 numOfPartIn = incoming.size();
696 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
697 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
698
699 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
700
701 if (numOfPartIn == 2) {
702 auto incoming = pVert->particles_in();
703 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
704 }
705 return false;
706}
707
711
712 template <class T, class U>
713 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 : particles_in(vtx) ) {
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 625 of file HepMCHelpers.h.

644{
645 template <class VTX>
646 auto particles_in (const VTX* p) { return p->particles_in(); }
647 template <class VTX>
648 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
825 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 : particles_in(vtx) ) {
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 626 of file HepMCHelpers.h.

645{
646 template <class VTX>
647 auto particles_in (const VTX* p) { return p->particles_in(); }
648 template <class VTX>
649 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
826 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 : particles_in(vtx) ) {
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 624 of file HepMCHelpers.h.

643{
644 template <class VTX>
645 auto particles_in (const VTX* p) { return p->particles_in(); }
646 template <class VTX>
647 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
648
649 namespace Pythia8
650 {
652 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
653
654 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
655
656 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
657 }
658
659#include "AtlasPID.h"
660
662 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
663
665 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
666
668 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
669
671 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
672
674 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
675
677 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
678
680 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
681
683 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
684
686 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
687
689 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
690
694 template <class T> inline bool isStableOrSimDecayed(const T& p) {
695 const auto vertex = p->end_vertex();
696 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
697 }
698
700 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
701
703 template <class T> inline bool isSpecialNonInteracting(const T& p) {
704 const int apid = std::abs(p->pdg_id());
705 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
706 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
707 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
708 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
709 return false;
710 }
711
713
714 template <class T> T findMother(T thePart) {
715 auto partOriVert = thePart->production_vertex();
716 if (!partOriVert) return nullptr;
717
718 long partPDG = thePart->pdg_id();
719 long MotherPDG(0);
720
721 auto MothOriVert = partOriVert;
722 MothOriVert = nullptr;
723 T theMoth(nullptr);
724
725 size_t itr = 0;
726 do {
727 if (itr != 0) partOriVert = MothOriVert;
728 for ( const auto& p : particles_in(partOriVert) ) {
729 theMoth = p;
730 if (!theMoth) continue;
731 MotherPDG = theMoth->pdg_id();
732 MothOriVert = theMoth->production_vertex();
733 if (MotherPDG == partPDG) break;
734 }
735 itr++;
736 if (itr > 100) {
737 break;
738 }
739 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
740 MothOriVert != partOriVert);
741 return theMoth;
742 }
743
745
746 template <class C, class T> T findMatching(C TruthContainer, T p) {
747 T ptrPart = nullptr;
748 if (!p) return ptrPart;
749 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
750 for (T truthParticle : *TruthContainer) {
751 if (HepMC::is_sim_descendant(p,truthParticle)) {
752 ptrPart = truthParticle;
753 break;
754 }
755 }
756 }
757 else {
758 for (T truthParticle : TruthContainer) {
759 if (HepMC::is_sim_descendant(p,truthParticle)) {
760 ptrPart = truthParticle;
761 break;
762 }
763 }
764 }
765 return ptrPart;
766 }
768
769 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
770 auto prodVtx = thePart->production_vertex();
771 if (!prodVtx) return;
772 for (const auto& theMother: prodVtx->particles_in()) {
773 if (!theMother) continue;
774 allancestors.insert(theMother);
775 findParticleAncestors(theMother, allancestors);
776 }
777 }
778
780
781 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
782 auto endVtx = thePart->end_vertex();
783 if (!endVtx) return;
784 for (const auto& theDaughter: endVtx->particles_out()) {
785 if (!theDaughter) continue;
786 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
787 allstabledescendants.insert(theDaughter);
788 }
789 findParticleStableDescendants(theDaughter, allstabledescendants);
790 }
791 }
792
796
797 template <class T> bool isHardScatteringVertex(T pVert) {
798 if (pVert == nullptr) return false;
799 T pV = pVert;
800 int numOfPartIn(0);
801 int pdg(0);
802
803 do {
804 pVert = pV;
805 auto incoming = pVert->particles_in();
806 numOfPartIn = incoming.size();
807 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
808 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
809
810 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
811
812 if (numOfPartIn == 2) {
813 auto incoming = pVert->particles_in();
814 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
815 }
816 return false;
817}
818
822
823 template <class T, class U>
824 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 : particles_in(vtx) ) {
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 210 of file HepMCHelpers.h.

◆ isTau() [2/2]

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

Definition at line 209 of file HepMCHelpers.h.

◆ isTechnicolor() [1/3]

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

Definition at line 527 of file HepMCHelpers.h.

546{
547 template <class VTX>
548 auto particles_in (const VTX* p) { return p->particles_in(); }
549 template <class VTX>
550 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
551
552 namespace Pythia8
553 {
555 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
556
557 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
558
559 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
560 }
561
562#include "AtlasPID.h"
563
565 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
566
568 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
569
571 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
572
574 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
575
577 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
578
580 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
581
583 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
584
586 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
587
589 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
590
592 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
593
597 template <class T> inline bool isStableOrSimDecayed(const T& p) {
598 const auto vertex = p->end_vertex();
599 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
600 }
601
603 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
604
606 template <class T> inline bool isSpecialNonInteracting(const T& p) {
607 const int apid = std::abs(p->pdg_id());
608 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
609 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
610 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
611 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
612 return false;
613 }
614
616
617 template <class T> T findMother(T thePart) {
618 auto partOriVert = thePart->production_vertex();
619 if (!partOriVert) return nullptr;
620
621 long partPDG = thePart->pdg_id();
622 long MotherPDG(0);
623
624 auto MothOriVert = partOriVert;
625 MothOriVert = nullptr;
626 T theMoth(nullptr);
627
628 size_t itr = 0;
629 do {
630 if (itr != 0) partOriVert = MothOriVert;
631 for ( const auto& p : particles_in(partOriVert) ) {
632 theMoth = p;
633 if (!theMoth) continue;
634 MotherPDG = theMoth->pdg_id();
635 MothOriVert = theMoth->production_vertex();
636 if (MotherPDG == partPDG) break;
637 }
638 itr++;
639 if (itr > 100) {
640 break;
641 }
642 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
643 MothOriVert != partOriVert);
644 return theMoth;
645 }
646
648
649 template <class C, class T> T findMatching(C TruthContainer, T p) {
650 T ptrPart = nullptr;
651 if (!p) return ptrPart;
652 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
653 for (T truthParticle : *TruthContainer) {
654 if (HepMC::is_sim_descendant(p,truthParticle)) {
655 ptrPart = truthParticle;
656 break;
657 }
658 }
659 }
660 else {
661 for (T truthParticle : TruthContainer) {
662 if (HepMC::is_sim_descendant(p,truthParticle)) {
663 ptrPart = truthParticle;
664 break;
665 }
666 }
667 }
668 return ptrPart;
669 }
671
672 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
673 auto prodVtx = thePart->production_vertex();
674 if (!prodVtx) return;
675 for (const auto& theMother: prodVtx->particles_in()) {
676 if (!theMother) continue;
677 allancestors.insert(theMother);
678 findParticleAncestors(theMother, allancestors);
679 }
680 }
681
683
684 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
685 auto endVtx = thePart->end_vertex();
686 if (!endVtx) return;
687 for (const auto& theDaughter: endVtx->particles_out()) {
688 if (!theDaughter) continue;
689 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
690 allstabledescendants.insert(theDaughter);
691 }
692 findParticleStableDescendants(theDaughter, allstabledescendants);
693 }
694 }
695
699
700 template <class T> bool isHardScatteringVertex(T pVert) {
701 if (pVert == nullptr) return false;
702 T pV = pVert;
703 int numOfPartIn(0);
704 int pdg(0);
705
706 do {
707 pVert = pV;
708 auto incoming = pVert->particles_in();
709 numOfPartIn = incoming.size();
710 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
711 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
712
713 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
714
715 if (numOfPartIn == 2) {
716 auto incoming = pVert->particles_in();
717 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
718 }
719 return false;
720}
721
725
726 template <class T, class U>
727 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 : particles_in(vtx) ) {
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 533 of file HepMCHelpers.h.

552{
553 template <class VTX>
554 auto particles_in (const VTX* p) { return p->particles_in(); }
555 template <class VTX>
556 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
557
558 namespace Pythia8
559 {
561 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
562
563 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
564
565 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
566 }
567
568#include "AtlasPID.h"
569
571 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
572
574 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
575
577 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
578
580 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
581
583 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
584
586 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
587
589 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
590
592 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
593
595 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
596
598 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
599
603 template <class T> inline bool isStableOrSimDecayed(const T& p) {
604 const auto vertex = p->end_vertex();
605 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
606 }
607
609 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
610
612 template <class T> inline bool isSpecialNonInteracting(const T& p) {
613 const int apid = std::abs(p->pdg_id());
614 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
615 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
616 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
617 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
618 return false;
619 }
620
622
623 template <class T> T findMother(T thePart) {
624 auto partOriVert = thePart->production_vertex();
625 if (!partOriVert) return nullptr;
626
627 long partPDG = thePart->pdg_id();
628 long MotherPDG(0);
629
630 auto MothOriVert = partOriVert;
631 MothOriVert = nullptr;
632 T theMoth(nullptr);
633
634 size_t itr = 0;
635 do {
636 if (itr != 0) partOriVert = MothOriVert;
637 for ( const auto& p : particles_in(partOriVert) ) {
638 theMoth = p;
639 if (!theMoth) continue;
640 MotherPDG = theMoth->pdg_id();
641 MothOriVert = theMoth->production_vertex();
642 if (MotherPDG == partPDG) break;
643 }
644 itr++;
645 if (itr > 100) {
646 break;
647 }
648 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
649 MothOriVert != partOriVert);
650 return theMoth;
651 }
652
654
655 template <class C, class T> T findMatching(C TruthContainer, T p) {
656 T ptrPart = nullptr;
657 if (!p) return ptrPart;
658 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
659 for (T truthParticle : *TruthContainer) {
660 if (HepMC::is_sim_descendant(p,truthParticle)) {
661 ptrPart = truthParticle;
662 break;
663 }
664 }
665 }
666 else {
667 for (T truthParticle : TruthContainer) {
668 if (HepMC::is_sim_descendant(p,truthParticle)) {
669 ptrPart = truthParticle;
670 break;
671 }
672 }
673 }
674 return ptrPart;
675 }
677
678 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
679 auto prodVtx = thePart->production_vertex();
680 if (!prodVtx) return;
681 for (const auto& theMother: prodVtx->particles_in()) {
682 if (!theMother) continue;
683 allancestors.insert(theMother);
684 findParticleAncestors(theMother, allancestors);
685 }
686 }
687
689
690 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
691 auto endVtx = thePart->end_vertex();
692 if (!endVtx) return;
693 for (const auto& theDaughter: endVtx->particles_out()) {
694 if (!theDaughter) continue;
695 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
696 allstabledescendants.insert(theDaughter);
697 }
698 findParticleStableDescendants(theDaughter, allstabledescendants);
699 }
700 }
701
705
706 template <class T> bool isHardScatteringVertex(T pVert) {
707 if (pVert == nullptr) return false;
708 T pV = pVert;
709 int numOfPartIn(0);
710 int pdg(0);
711
712 do {
713 pVert = pV;
714 auto incoming = pVert->particles_in();
715 numOfPartIn = incoming.size();
716 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
717 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
718
719 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
720
721 if (numOfPartIn == 2) {
722 auto incoming = pVert->particles_in();
723 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
724 }
725 return false;
726}
727
731
732 template <class T, class U>
733 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 : particles_in(vtx) ) {
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 525 of file HepMCHelpers.h.

544{
545 template <class VTX>
546 auto particles_in (const VTX* p) { return p->particles_in(); }
547 template <class VTX>
548 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
549
550 namespace Pythia8
551 {
553 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
554
555 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
556
557 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
558 }
559
560#include "AtlasPID.h"
561
563 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
564
566 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
567
569 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
570
572 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
573
575 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
576
578 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
579
581 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
582
584 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
585
587 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
588
590 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
591
595 template <class T> inline bool isStableOrSimDecayed(const T& p) {
596 const auto vertex = p->end_vertex();
597 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
598 }
599
601 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
602
604 template <class T> inline bool isSpecialNonInteracting(const T& p) {
605 const int apid = std::abs(p->pdg_id());
606 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
607 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
608 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
609 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
610 return false;
611 }
612
614
615 template <class T> T findMother(T thePart) {
616 auto partOriVert = thePart->production_vertex();
617 if (!partOriVert) return nullptr;
618
619 long partPDG = thePart->pdg_id();
620 long MotherPDG(0);
621
622 auto MothOriVert = partOriVert;
623 MothOriVert = nullptr;
624 T theMoth(nullptr);
625
626 size_t itr = 0;
627 do {
628 if (itr != 0) partOriVert = MothOriVert;
629 for ( const auto& p : particles_in(partOriVert) ) {
630 theMoth = p;
631 if (!theMoth) continue;
632 MotherPDG = theMoth->pdg_id();
633 MothOriVert = theMoth->production_vertex();
634 if (MotherPDG == partPDG) break;
635 }
636 itr++;
637 if (itr > 100) {
638 break;
639 }
640 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
641 MothOriVert != partOriVert);
642 return theMoth;
643 }
644
646
647 template <class C, class T> T findMatching(C TruthContainer, T p) {
648 T ptrPart = nullptr;
649 if (!p) return ptrPart;
650 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
651 for (T truthParticle : *TruthContainer) {
652 if (HepMC::is_sim_descendant(p,truthParticle)) {
653 ptrPart = truthParticle;
654 break;
655 }
656 }
657 }
658 else {
659 for (T truthParticle : TruthContainer) {
660 if (HepMC::is_sim_descendant(p,truthParticle)) {
661 ptrPart = truthParticle;
662 break;
663 }
664 }
665 }
666 return ptrPart;
667 }
669
670 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
671 auto prodVtx = thePart->production_vertex();
672 if (!prodVtx) return;
673 for (const auto& theMother: prodVtx->particles_in()) {
674 if (!theMother) continue;
675 allancestors.insert(theMother);
676 findParticleAncestors(theMother, allancestors);
677 }
678 }
679
681
682 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
683 auto endVtx = thePart->end_vertex();
684 if (!endVtx) return;
685 for (const auto& theDaughter: endVtx->particles_out()) {
686 if (!theDaughter) continue;
687 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
688 allstabledescendants.insert(theDaughter);
689 }
690 findParticleStableDescendants(theDaughter, allstabledescendants);
691 }
692 }
693
697
698 template <class T> bool isHardScatteringVertex(T pVert) {
699 if (pVert == nullptr) return false;
700 T pV = pVert;
701 int numOfPartIn(0);
702 int pdg(0);
703
704 do {
705 pVert = pV;
706 auto incoming = pVert->particles_in();
707 numOfPartIn = incoming.size();
708 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
709 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
710
711 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
712
713 if (numOfPartIn == 2) {
714 auto incoming = pVert->particles_in();
715 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
716 }
717 return false;
718}
719
723
724 template <class T, class U>
725 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 : particles_in(vtx) ) {
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 327 of file HepMCHelpers.h.

346{
347 template <class VTX>
348 auto particles_in (const VTX* p) { return p->particles_in(); }
349 template <class VTX>
350 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
527 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 : particles_in(vtx) ) {
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 334 of file HepMCHelpers.h.

353{
354 template <class VTX>
355 auto particles_in (const VTX* p) { return p->particles_in(); }
356 template <class VTX>
357 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
358
359 namespace Pythia8
360 {
362 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
363
364 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
365
366 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
367 }
368
369#include "AtlasPID.h"
370
372 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
373
375 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
376
378 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
379
381 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
382
384 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
385
387 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
388
390 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
391
393 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
394
396 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
397
399 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
400
404 template <class T> inline bool isStableOrSimDecayed(const T& p) {
405 const auto vertex = p->end_vertex();
406 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
407 }
408
410 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
411
413 template <class T> inline bool isSpecialNonInteracting(const T& p) {
414 const int apid = std::abs(p->pdg_id());
415 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
416 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
417 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
418 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
419 return false;
420 }
421
423
424 template <class T> T findMother(T thePart) {
425 auto partOriVert = thePart->production_vertex();
426 if (!partOriVert) return nullptr;
427
428 long partPDG = thePart->pdg_id();
429 long MotherPDG(0);
430
431 auto MothOriVert = partOriVert;
432 MothOriVert = nullptr;
433 T theMoth(nullptr);
434
435 size_t itr = 0;
436 do {
437 if (itr != 0) partOriVert = MothOriVert;
438 for ( const auto& p : particles_in(partOriVert) ) {
439 theMoth = p;
440 if (!theMoth) continue;
441 MotherPDG = theMoth->pdg_id();
442 MothOriVert = theMoth->production_vertex();
443 if (MotherPDG == partPDG) break;
444 }
445 itr++;
446 if (itr > 100) {
447 break;
448 }
449 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
450 MothOriVert != partOriVert);
451 return theMoth;
452 }
453
455
456 template <class C, class T> T findMatching(C TruthContainer, T p) {
457 T ptrPart = nullptr;
458 if (!p) return ptrPart;
459 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
460 for (T truthParticle : *TruthContainer) {
461 if (HepMC::is_sim_descendant(p,truthParticle)) {
462 ptrPart = truthParticle;
463 break;
464 }
465 }
466 }
467 else {
468 for (T truthParticle : TruthContainer) {
469 if (HepMC::is_sim_descendant(p,truthParticle)) {
470 ptrPart = truthParticle;
471 break;
472 }
473 }
474 }
475 return ptrPart;
476 }
478
479 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
480 auto prodVtx = thePart->production_vertex();
481 if (!prodVtx) return;
482 for (const auto& theMother: prodVtx->particles_in()) {
483 if (!theMother) continue;
484 allancestors.insert(theMother);
485 findParticleAncestors(theMother, allancestors);
486 }
487 }
488
490
491 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
492 auto endVtx = thePart->end_vertex();
493 if (!endVtx) return;
494 for (const auto& theDaughter: endVtx->particles_out()) {
495 if (!theDaughter) continue;
496 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
497 allstabledescendants.insert(theDaughter);
498 }
499 findParticleStableDescendants(theDaughter, allstabledescendants);
500 }
501 }
502
506
507 template <class T> bool isHardScatteringVertex(T pVert) {
508 if (pVert == nullptr) return false;
509 T pV = pVert;
510 int numOfPartIn(0);
511 int pdg(0);
512
513 do {
514 pVert = pV;
515 auto incoming = pVert->particles_in();
516 numOfPartIn = incoming.size();
517 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
518 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
519
520 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
521
522 if (numOfPartIn == 2) {
523 auto incoming = pVert->particles_in();
524 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
525 }
526 return false;
527}
528
532
533 template <class T, class U>
534 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 : particles_in(vtx) ) {
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 326 of file HepMCHelpers.h.

345{
346 template <class VTX>
347 auto particles_in (const VTX* p) { return p->particles_in(); }
348 template <class VTX>
349 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
350
351 namespace Pythia8
352 {
354 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
355
356 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
357
358 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
359 }
360
361#include "AtlasPID.h"
362
364 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
365
367 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
368
370 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
371
373 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
374
376 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
377
379 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
380
382 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
383
385 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
386
388 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
389
391 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
392
396 template <class T> inline bool isStableOrSimDecayed(const T& p) {
397 const auto vertex = p->end_vertex();
398 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
399 }
400
402 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
403
405 template <class T> inline bool isSpecialNonInteracting(const T& p) {
406 const int apid = std::abs(p->pdg_id());
407 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
408 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
409 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
410 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
411 return false;
412 }
413
415
416 template <class T> T findMother(T thePart) {
417 auto partOriVert = thePart->production_vertex();
418 if (!partOriVert) return nullptr;
419
420 long partPDG = thePart->pdg_id();
421 long MotherPDG(0);
422
423 auto MothOriVert = partOriVert;
424 MothOriVert = nullptr;
425 T theMoth(nullptr);
426
427 size_t itr = 0;
428 do {
429 if (itr != 0) partOriVert = MothOriVert;
430 for ( const auto& p : particles_in(partOriVert) ) {
431 theMoth = p;
432 if (!theMoth) continue;
433 MotherPDG = theMoth->pdg_id();
434 MothOriVert = theMoth->production_vertex();
435 if (MotherPDG == partPDG) break;
436 }
437 itr++;
438 if (itr > 100) {
439 break;
440 }
441 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
442 MothOriVert != partOriVert);
443 return theMoth;
444 }
445
447
448 template <class C, class T> T findMatching(C TruthContainer, T p) {
449 T ptrPart = nullptr;
450 if (!p) return ptrPart;
451 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
452 for (T truthParticle : *TruthContainer) {
453 if (HepMC::is_sim_descendant(p,truthParticle)) {
454 ptrPart = truthParticle;
455 break;
456 }
457 }
458 }
459 else {
460 for (T truthParticle : TruthContainer) {
461 if (HepMC::is_sim_descendant(p,truthParticle)) {
462 ptrPart = truthParticle;
463 break;
464 }
465 }
466 }
467 return ptrPart;
468 }
470
471 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
472 auto prodVtx = thePart->production_vertex();
473 if (!prodVtx) return;
474 for (const auto& theMother: prodVtx->particles_in()) {
475 if (!theMother) continue;
476 allancestors.insert(theMother);
477 findParticleAncestors(theMother, allancestors);
478 }
479 }
480
482
483 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
484 auto endVtx = thePart->end_vertex();
485 if (!endVtx) return;
486 for (const auto& theDaughter: endVtx->particles_out()) {
487 if (!theDaughter) continue;
488 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
489 allstabledescendants.insert(theDaughter);
490 }
491 findParticleStableDescendants(theDaughter, allstabledescendants);
492 }
493 }
494
498
499 template <class T> bool isHardScatteringVertex(T pVert) {
500 if (pVert == nullptr) return false;
501 T pV = pVert;
502 int numOfPartIn(0);
503 int pdg(0);
504
505 do {
506 pVert = pV;
507 auto incoming = pVert->particles_in();
508 numOfPartIn = incoming.size();
509 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
510 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
511
512 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
513
514 if (numOfPartIn == 2) {
515 auto incoming = pVert->particles_in();
516 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
517 }
518 return false;
519}
520
524
525 template <class T, class U>
526 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 : particles_in(vtx) ) {
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 187 of file HepMCHelpers.h.

◆ isTop() [2/2]

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

Definition at line 186 of file HepMCHelpers.h.

◆ isTopBaryon()

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

Definition at line 937 of file HepMCHelpers.h.

956{
957 template <class VTX>
958 auto particles_in (const VTX* p) { return p->particles_in(); }
959 template <class VTX>
960 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1137 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 : particles_in(vtx) ) {
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 914 of file HepMCHelpers.h.

933{
934 template <class VTX>
935 auto particles_in (const VTX* p) { return p->particles_in(); }
936 template <class VTX>
937 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1114 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 : particles_in(vtx) ) {
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 921 of file HepMCHelpers.h.

940{
941 template <class VTX>
942 auto particles_in (const VTX* p) { return p->particles_in(); }
943 template <class VTX>
944 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1121 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 : particles_in(vtx) ) {
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 361 of file HepMCHelpers.h.

380{
381 template <class VTX>
382 auto particles_in (const VTX* p) { return p->particles_in(); }
383 template <class VTX>
384 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
561 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 : particles_in(vtx) ) {
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 360 of file HepMCHelpers.h.

379{
380 template <class VTX>
381 auto particles_in (const VTX* p) { return p->particles_in(); }
382 template <class VTX>
383 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
384
385 namespace Pythia8
386 {
388 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
389
390 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
391
392 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
393 }
394
395#include "AtlasPID.h"
396
398 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
399
401 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
402
404 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
405
407 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
408
410 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
411
413 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
414
416 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
417
419 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
420
422 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
423
425 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
426
430 template <class T> inline bool isStableOrSimDecayed(const T& p) {
431 const auto vertex = p->end_vertex();
432 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
433 }
434
436 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
437
439 template <class T> inline bool isSpecialNonInteracting(const T& p) {
440 const int apid = std::abs(p->pdg_id());
441 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
442 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
443 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
444 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
445 return false;
446 }
447
449
450 template <class T> T findMother(T thePart) {
451 auto partOriVert = thePart->production_vertex();
452 if (!partOriVert) return nullptr;
453
454 long partPDG = thePart->pdg_id();
455 long MotherPDG(0);
456
457 auto MothOriVert = partOriVert;
458 MothOriVert = nullptr;
459 T theMoth(nullptr);
460
461 size_t itr = 0;
462 do {
463 if (itr != 0) partOriVert = MothOriVert;
464 for ( const auto& p : particles_in(partOriVert) ) {
465 theMoth = p;
466 if (!theMoth) continue;
467 MotherPDG = theMoth->pdg_id();
468 MothOriVert = theMoth->production_vertex();
469 if (MotherPDG == partPDG) break;
470 }
471 itr++;
472 if (itr > 100) {
473 break;
474 }
475 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
476 MothOriVert != partOriVert);
477 return theMoth;
478 }
479
481
482 template <class C, class T> T findMatching(C TruthContainer, T p) {
483 T ptrPart = nullptr;
484 if (!p) return ptrPart;
485 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
486 for (T truthParticle : *TruthContainer) {
487 if (HepMC::is_sim_descendant(p,truthParticle)) {
488 ptrPart = truthParticle;
489 break;
490 }
491 }
492 }
493 else {
494 for (T truthParticle : TruthContainer) {
495 if (HepMC::is_sim_descendant(p,truthParticle)) {
496 ptrPart = truthParticle;
497 break;
498 }
499 }
500 }
501 return ptrPart;
502 }
504
505 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
506 auto prodVtx = thePart->production_vertex();
507 if (!prodVtx) return;
508 for (const auto& theMother: prodVtx->particles_in()) {
509 if (!theMother) continue;
510 allancestors.insert(theMother);
511 findParticleAncestors(theMother, allancestors);
512 }
513 }
514
516
517 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
518 auto endVtx = thePart->end_vertex();
519 if (!endVtx) return;
520 for (const auto& theDaughter: endVtx->particles_out()) {
521 if (!theDaughter) continue;
522 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
523 allstabledescendants.insert(theDaughter);
524 }
525 findParticleStableDescendants(theDaughter, allstabledescendants);
526 }
527 }
528
532
533 template <class T> bool isHardScatteringVertex(T pVert) {
534 if (pVert == nullptr) return false;
535 T pV = pVert;
536 int numOfPartIn(0);
537 int pdg(0);
538
539 do {
540 pVert = pV;
541 auto incoming = pVert->particles_in();
542 numOfPartIn = incoming.size();
543 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
544 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
545
546 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
547
548 if (numOfPartIn == 2) {
549 auto incoming = pVert->particles_in();
550 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
551 }
552 return false;
553}
554
558
559 template <class T, class U>
560 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 : particles_in(vtx) ) {
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 875 of file HepMCHelpers.h.

894{
895 template <class VTX>
896 auto particles_in (const VTX* p) { return p->particles_in(); }
897 template <class VTX>
898 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1075 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 : particles_in(vtx) ) {
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 876 of file HepMCHelpers.h.

895{
896 template <class VTX>
897 auto particles_in (const VTX* p) { return p->particles_in(); }
898 template <class VTX>
899 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1076 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 : particles_in(vtx) ) {
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 874 of file HepMCHelpers.h.

893{
894 template <class VTX>
895 auto particles_in (const VTX* p) { return p->particles_in(); }
896 template <class VTX>
897 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
898
899 namespace Pythia8
900 {
902 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
903
904 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
905
906 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
907 }
908
909#include "AtlasPID.h"
910
912 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
913
915 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
916
918 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
919
921 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
922
924 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
925
927 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
928
930 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
931
933 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
934
936 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
937
939 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
940
944 template <class T> inline bool isStableOrSimDecayed(const T& p) {
945 const auto vertex = p->end_vertex();
946 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
947 }
948
950 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
951
953 template <class T> inline bool isSpecialNonInteracting(const T& p) {
954 const int apid = std::abs(p->pdg_id());
955 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
956 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
957 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
958 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
959 return false;
960 }
961
963
964 template <class T> T findMother(T thePart) {
965 auto partOriVert = thePart->production_vertex();
966 if (!partOriVert) return nullptr;
967
968 long partPDG = thePart->pdg_id();
969 long MotherPDG(0);
970
971 auto MothOriVert = partOriVert;
972 MothOriVert = nullptr;
973 T theMoth(nullptr);
974
975 size_t itr = 0;
976 do {
977 if (itr != 0) partOriVert = MothOriVert;
978 for ( const auto& p : particles_in(partOriVert) ) {
979 theMoth = p;
980 if (!theMoth) continue;
981 MotherPDG = theMoth->pdg_id();
982 MothOriVert = theMoth->production_vertex();
983 if (MotherPDG == partPDG) break;
984 }
985 itr++;
986 if (itr > 100) {
987 break;
988 }
989 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
990 MothOriVert != partOriVert);
991 return theMoth;
992 }
993
995
996 template <class C, class T> T findMatching(C TruthContainer, T p) {
997 T ptrPart = nullptr;
998 if (!p) return ptrPart;
999 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1000 for (T truthParticle : *TruthContainer) {
1001 if (HepMC::is_sim_descendant(p,truthParticle)) {
1002 ptrPart = truthParticle;
1003 break;
1004 }
1005 }
1006 }
1007 else {
1008 for (T truthParticle : TruthContainer) {
1009 if (HepMC::is_sim_descendant(p,truthParticle)) {
1010 ptrPart = truthParticle;
1011 break;
1012 }
1013 }
1014 }
1015 return ptrPart;
1016 }
1018
1019 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1020 auto prodVtx = thePart->production_vertex();
1021 if (!prodVtx) return;
1022 for (const auto& theMother: prodVtx->particles_in()) {
1023 if (!theMother) continue;
1024 allancestors.insert(theMother);
1025 findParticleAncestors(theMother, allancestors);
1026 }
1027 }
1028
1030
1031 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1032 auto endVtx = thePart->end_vertex();
1033 if (!endVtx) return;
1034 for (const auto& theDaughter: endVtx->particles_out()) {
1035 if (!theDaughter) continue;
1036 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1037 allstabledescendants.insert(theDaughter);
1038 }
1039 findParticleStableDescendants(theDaughter, allstabledescendants);
1040 }
1041 }
1042
1046
1047 template <class T> bool isHardScatteringVertex(T pVert) {
1048 if (pVert == nullptr) return false;
1049 T pV = pVert;
1050 int numOfPartIn(0);
1051 int pdg(0);
1052
1053 do {
1054 pVert = pV;
1055 auto incoming = pVert->particles_in();
1056 numOfPartIn = incoming.size();
1057 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1058 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1059
1060 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1061
1062 if (numOfPartIn == 2) {
1063 auto incoming = pVert->particles_in();
1064 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1065 }
1066 return false;
1067}
1068
1072
1073 template <class T, class U>
1074 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 : particles_in(vtx) ) {
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 880 of file HepMCHelpers.h.

899{
900 template <class VTX>
901 auto particles_in (const VTX* p) { return p->particles_in(); }
902 template <class VTX>
903 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1080 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 : particles_in(vtx) ) {
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 885 of file HepMCHelpers.h.

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

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

403{
404 template <class VTX>
405 auto particles_in (const VTX* p) { return p->particles_in(); }
406 template <class VTX>
407 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
584 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 : particles_in(vtx) ) {
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 383 of file HepMCHelpers.h.

402{
403 template <class VTX>
404 auto particles_in (const VTX* p) { return p->particles_in(); }
405 template <class VTX>
406 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
407
408 namespace Pythia8
409 {
411 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
412
413 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
414
415 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
416 }
417
418#include "AtlasPID.h"
419
421 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
422
424 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
425
427 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
428
430 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
431
433 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
434
436 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
437
439 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
440
442 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
443
445 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
446
448 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
449
453 template <class T> inline bool isStableOrSimDecayed(const T& p) {
454 const auto vertex = p->end_vertex();
455 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
456 }
457
459 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
460
462 template <class T> inline bool isSpecialNonInteracting(const T& p) {
463 const int apid = std::abs(p->pdg_id());
464 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
465 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
466 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
467 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
468 return false;
469 }
470
472
473 template <class T> T findMother(T thePart) {
474 auto partOriVert = thePart->production_vertex();
475 if (!partOriVert) return nullptr;
476
477 long partPDG = thePart->pdg_id();
478 long MotherPDG(0);
479
480 auto MothOriVert = partOriVert;
481 MothOriVert = nullptr;
482 T theMoth(nullptr);
483
484 size_t itr = 0;
485 do {
486 if (itr != 0) partOriVert = MothOriVert;
487 for ( const auto& p : particles_in(partOriVert) ) {
488 theMoth = p;
489 if (!theMoth) continue;
490 MotherPDG = theMoth->pdg_id();
491 MothOriVert = theMoth->production_vertex();
492 if (MotherPDG == partPDG) break;
493 }
494 itr++;
495 if (itr > 100) {
496 break;
497 }
498 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
499 MothOriVert != partOriVert);
500 return theMoth;
501 }
502
504
505 template <class C, class T> T findMatching(C TruthContainer, T p) {
506 T ptrPart = nullptr;
507 if (!p) return ptrPart;
508 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
509 for (T truthParticle : *TruthContainer) {
510 if (HepMC::is_sim_descendant(p,truthParticle)) {
511 ptrPart = truthParticle;
512 break;
513 }
514 }
515 }
516 else {
517 for (T truthParticle : TruthContainer) {
518 if (HepMC::is_sim_descendant(p,truthParticle)) {
519 ptrPart = truthParticle;
520 break;
521 }
522 }
523 }
524 return ptrPart;
525 }
527
528 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
529 auto prodVtx = thePart->production_vertex();
530 if (!prodVtx) return;
531 for (const auto& theMother: prodVtx->particles_in()) {
532 if (!theMother) continue;
533 allancestors.insert(theMother);
534 findParticleAncestors(theMother, allancestors);
535 }
536 }
537
539
540 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
541 auto endVtx = thePart->end_vertex();
542 if (!endVtx) return;
543 for (const auto& theDaughter: endVtx->particles_out()) {
544 if (!theDaughter) continue;
545 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
546 allstabledescendants.insert(theDaughter);
547 }
548 findParticleStableDescendants(theDaughter, allstabledescendants);
549 }
550 }
551
555
556 template <class T> bool isHardScatteringVertex(T pVert) {
557 if (pVert == nullptr) return false;
558 T pV = pVert;
559 int numOfPartIn(0);
560 int pdg(0);
561
562 do {
563 pVert = pV;
564 auto incoming = pVert->particles_in();
565 numOfPartIn = incoming.size();
566 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
567 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
568
569 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
570
571 if (numOfPartIn == 2) {
572 auto incoming = pVert->particles_in();
573 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
574 }
575 return false;
576}
577
581
582 template <class T, class U>
583 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 : particles_in(vtx) ) {
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 969 of file HepMCHelpers.h.

988{
989 template <class VTX>
990 auto particles_in (const VTX* p) { return p->particles_in(); }
991 template <class VTX>
992 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
993
994 namespace Pythia8
995 {
997 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
998
999 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1000
1001 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1002 }
1003
1004#include "AtlasPID.h"
1005
1007 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1008
1010 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1011
1013 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1014
1016 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1017
1019 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1020
1022 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1023
1025 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1026
1028 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1029
1031 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1032
1034 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1035
1039 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1040 const auto vertex = p->end_vertex();
1041 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1042 }
1043
1045 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1046
1048 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1049 const int apid = std::abs(p->pdg_id());
1050 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1051 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1052 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1053 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1054 return false;
1055 }
1056
1058
1059 template <class T> T findMother(T thePart) {
1060 auto partOriVert = thePart->production_vertex();
1061 if (!partOriVert) return nullptr;
1062
1063 long partPDG = thePart->pdg_id();
1064 long MotherPDG(0);
1065
1066 auto MothOriVert = partOriVert;
1067 MothOriVert = nullptr;
1068 T theMoth(nullptr);
1069
1070 size_t itr = 0;
1071 do {
1072 if (itr != 0) partOriVert = MothOriVert;
1073 for ( const auto& p : particles_in(partOriVert) ) {
1074 theMoth = p;
1075 if (!theMoth) continue;
1076 MotherPDG = theMoth->pdg_id();
1077 MothOriVert = theMoth->production_vertex();
1078 if (MotherPDG == partPDG) break;
1079 }
1080 itr++;
1081 if (itr > 100) {
1082 break;
1083 }
1084 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1085 MothOriVert != partOriVert);
1086 return theMoth;
1087 }
1088
1090
1091 template <class C, class T> T findMatching(C TruthContainer, T p) {
1092 T ptrPart = nullptr;
1093 if (!p) return ptrPart;
1094 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1095 for (T truthParticle : *TruthContainer) {
1096 if (HepMC::is_sim_descendant(p,truthParticle)) {
1097 ptrPart = truthParticle;
1098 break;
1099 }
1100 }
1101 }
1102 else {
1103 for (T truthParticle : TruthContainer) {
1104 if (HepMC::is_sim_descendant(p,truthParticle)) {
1105 ptrPart = truthParticle;
1106 break;
1107 }
1108 }
1109 }
1110 return ptrPart;
1111 }
1113
1114 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1115 auto prodVtx = thePart->production_vertex();
1116 if (!prodVtx) return;
1117 for (const auto& theMother: prodVtx->particles_in()) {
1118 if (!theMother) continue;
1119 allancestors.insert(theMother);
1120 findParticleAncestors(theMother, allancestors);
1121 }
1122 }
1123
1125
1126 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1127 auto endVtx = thePart->end_vertex();
1128 if (!endVtx) return;
1129 for (const auto& theDaughter: endVtx->particles_out()) {
1130 if (!theDaughter) continue;
1131 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1132 allstabledescendants.insert(theDaughter);
1133 }
1134 findParticleStableDescendants(theDaughter, allstabledescendants);
1135 }
1136 }
1137
1141
1142 template <class T> bool isHardScatteringVertex(T pVert) {
1143 if (pVert == nullptr) return false;
1144 T pV = pVert;
1145 int numOfPartIn(0);
1146 int pdg(0);
1147
1148 do {
1149 pVert = pV;
1150 auto incoming = pVert->particles_in();
1151 numOfPartIn = incoming.size();
1152 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1153 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1154
1155 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1156
1157 if (numOfPartIn == 2) {
1158 auto incoming = pVert->particles_in();
1159 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1160 }
1161 return false;
1162}
1163
1167
1168 template <class T, class U>
1169 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 : particles_in(vtx) ) {
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 944 of file HepMCHelpers.h.

963{
964 template <class VTX>
965 auto particles_in (const VTX* p) { return p->particles_in(); }
966 template <class VTX>
967 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1144 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 : particles_in(vtx) ) {
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 943 of file HepMCHelpers.h.

962{
963 template <class VTX>
964 auto particles_in (const VTX* p) { return p->particles_in(); }
965 template <class VTX>
966 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
967
968 namespace Pythia8
969 {
971 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
972
973 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
974
975 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
976 }
977
978#include "AtlasPID.h"
979
981 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
982
984 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
985
987 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
988
990 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
991
993 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
994
996 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
997
999 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1000
1002 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1003
1005 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1006
1008 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1009
1013 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1014 const auto vertex = p->end_vertex();
1015 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1016 }
1017
1019 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1020
1022 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1023 const int apid = std::abs(p->pdg_id());
1024 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1025 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1026 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1027 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1028 return false;
1029 }
1030
1032
1033 template <class T> T findMother(T thePart) {
1034 auto partOriVert = thePart->production_vertex();
1035 if (!partOriVert) return nullptr;
1036
1037 long partPDG = thePart->pdg_id();
1038 long MotherPDG(0);
1039
1040 auto MothOriVert = partOriVert;
1041 MothOriVert = nullptr;
1042 T theMoth(nullptr);
1043
1044 size_t itr = 0;
1045 do {
1046 if (itr != 0) partOriVert = MothOriVert;
1047 for ( const auto& p : particles_in(partOriVert) ) {
1048 theMoth = p;
1049 if (!theMoth) continue;
1050 MotherPDG = theMoth->pdg_id();
1051 MothOriVert = theMoth->production_vertex();
1052 if (MotherPDG == partPDG) break;
1053 }
1054 itr++;
1055 if (itr > 100) {
1056 break;
1057 }
1058 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1059 MothOriVert != partOriVert);
1060 return theMoth;
1061 }
1062
1064
1065 template <class C, class T> T findMatching(C TruthContainer, T p) {
1066 T ptrPart = nullptr;
1067 if (!p) return ptrPart;
1068 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1069 for (T truthParticle : *TruthContainer) {
1070 if (HepMC::is_sim_descendant(p,truthParticle)) {
1071 ptrPart = truthParticle;
1072 break;
1073 }
1074 }
1075 }
1076 else {
1077 for (T truthParticle : TruthContainer) {
1078 if (HepMC::is_sim_descendant(p,truthParticle)) {
1079 ptrPart = truthParticle;
1080 break;
1081 }
1082 }
1083 }
1084 return ptrPart;
1085 }
1087
1088 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1089 auto prodVtx = thePart->production_vertex();
1090 if (!prodVtx) return;
1091 for (const auto& theMother: prodVtx->particles_in()) {
1092 if (!theMother) continue;
1093 allancestors.insert(theMother);
1094 findParticleAncestors(theMother, allancestors);
1095 }
1096 }
1097
1099
1100 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1101 auto endVtx = thePart->end_vertex();
1102 if (!endVtx) return;
1103 for (const auto& theDaughter: endVtx->particles_out()) {
1104 if (!theDaughter) continue;
1105 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1106 allstabledescendants.insert(theDaughter);
1107 }
1108 findParticleStableDescendants(theDaughter, allstabledescendants);
1109 }
1110 }
1111
1115
1116 template <class T> bool isHardScatteringVertex(T pVert) {
1117 if (pVert == nullptr) return false;
1118 T pV = pVert;
1119 int numOfPartIn(0);
1120 int pdg(0);
1121
1122 do {
1123 pVert = pV;
1124 auto incoming = pVert->particles_in();
1125 numOfPartIn = incoming.size();
1126 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1127 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1128
1129 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1130
1131 if (numOfPartIn == 2) {
1132 auto incoming = pVert->particles_in();
1133 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1134 }
1135 return false;
1136}
1137
1141
1142 template <class T, class U>
1143 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 : particles_in(vtx) ) {
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 993 of file HepMCHelpers.h.

1012{
1013 template <class VTX>
1014 auto particles_in (const VTX* p) { return p->particles_in(); }
1015 template <class VTX>
1016 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1017
1018 namespace Pythia8
1019 {
1021 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1022
1023 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1024
1025 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1026 }
1027
1028#include "AtlasPID.h"
1029
1031 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1032
1034 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1035
1037 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1038
1040 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1041
1043 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1044
1046 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1047
1049 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1050
1052 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1053
1055 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1056
1058 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1059
1063 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1064 const auto vertex = p->end_vertex();
1065 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1066 }
1067
1069 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1070
1072 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1073 const int apid = std::abs(p->pdg_id());
1074 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1075 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1076 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1077 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1078 return false;
1079 }
1080
1082
1083 template <class T> T findMother(T thePart) {
1084 auto partOriVert = thePart->production_vertex();
1085 if (!partOriVert) return nullptr;
1086
1087 long partPDG = thePart->pdg_id();
1088 long MotherPDG(0);
1089
1090 auto MothOriVert = partOriVert;
1091 MothOriVert = nullptr;
1092 T theMoth(nullptr);
1093
1094 size_t itr = 0;
1095 do {
1096 if (itr != 0) partOriVert = MothOriVert;
1097 for ( const auto& p : particles_in(partOriVert) ) {
1098 theMoth = p;
1099 if (!theMoth) continue;
1100 MotherPDG = theMoth->pdg_id();
1101 MothOriVert = theMoth->production_vertex();
1102 if (MotherPDG == partPDG) break;
1103 }
1104 itr++;
1105 if (itr > 100) {
1106 break;
1107 }
1108 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1109 MothOriVert != partOriVert);
1110 return theMoth;
1111 }
1112
1114
1115 template <class C, class T> T findMatching(C TruthContainer, T p) {
1116 T ptrPart = nullptr;
1117 if (!p) return ptrPart;
1118 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1119 for (T truthParticle : *TruthContainer) {
1120 if (HepMC::is_sim_descendant(p,truthParticle)) {
1121 ptrPart = truthParticle;
1122 break;
1123 }
1124 }
1125 }
1126 else {
1127 for (T truthParticle : TruthContainer) {
1128 if (HepMC::is_sim_descendant(p,truthParticle)) {
1129 ptrPart = truthParticle;
1130 break;
1131 }
1132 }
1133 }
1134 return ptrPart;
1135 }
1137
1138 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1139 auto prodVtx = thePart->production_vertex();
1140 if (!prodVtx) return;
1141 for (const auto& theMother: prodVtx->particles_in()) {
1142 if (!theMother) continue;
1143 allancestors.insert(theMother);
1144 findParticleAncestors(theMother, allancestors);
1145 }
1146 }
1147
1149
1150 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1151 auto endVtx = thePart->end_vertex();
1152 if (!endVtx) return;
1153 for (const auto& theDaughter: endVtx->particles_out()) {
1154 if (!theDaughter) continue;
1155 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1156 allstabledescendants.insert(theDaughter);
1157 }
1158 findParticleStableDescendants(theDaughter, allstabledescendants);
1159 }
1160 }
1161
1165
1166 template <class T> bool isHardScatteringVertex(T pVert) {
1167 if (pVert == nullptr) return false;
1168 T pV = pVert;
1169 int numOfPartIn(0);
1170 int pdg(0);
1171
1172 do {
1173 pVert = pV;
1174 auto incoming = pVert->particles_in();
1175 numOfPartIn = incoming.size();
1176 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1177 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1178
1179 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1180
1181 if (numOfPartIn == 2) {
1182 auto incoming = pVert->particles_in();
1183 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1184 }
1185 return false;
1186}
1187
1191
1192 template <class T, class U>
1193 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 : particles_in(vtx) ) {
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 979 of file HepMCHelpers.h.

998{
999 template <class VTX>
1000 auto particles_in (const VTX* p) { return p->particles_in(); }
1001 template <class VTX>
1002 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1179 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 : particles_in(vtx) ) {
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 978 of file HepMCHelpers.h.

997{
998 template <class VTX>
999 auto particles_in (const VTX* p) { return p->particles_in(); }
1000 template <class VTX>
1001 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1002
1003 namespace Pythia8
1004 {
1006 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1007
1008 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1009
1010 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1011 }
1012
1013#include "AtlasPID.h"
1014
1016 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1017
1019 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1020
1022 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1023
1025 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1026
1028 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1029
1031 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1032
1034 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1035
1037 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1038
1040 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1041
1043 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1044
1048 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1049 const auto vertex = p->end_vertex();
1050 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1051 }
1052
1054 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1055
1057 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1058 const int apid = std::abs(p->pdg_id());
1059 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1060 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1061 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1062 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1063 return false;
1064 }
1065
1067
1068 template <class T> T findMother(T thePart) {
1069 auto partOriVert = thePart->production_vertex();
1070 if (!partOriVert) return nullptr;
1071
1072 long partPDG = thePart->pdg_id();
1073 long MotherPDG(0);
1074
1075 auto MothOriVert = partOriVert;
1076 MothOriVert = nullptr;
1077 T theMoth(nullptr);
1078
1079 size_t itr = 0;
1080 do {
1081 if (itr != 0) partOriVert = MothOriVert;
1082 for ( const auto& p : particles_in(partOriVert) ) {
1083 theMoth = p;
1084 if (!theMoth) continue;
1085 MotherPDG = theMoth->pdg_id();
1086 MothOriVert = theMoth->production_vertex();
1087 if (MotherPDG == partPDG) break;
1088 }
1089 itr++;
1090 if (itr > 100) {
1091 break;
1092 }
1093 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1094 MothOriVert != partOriVert);
1095 return theMoth;
1096 }
1097
1099
1100 template <class C, class T> T findMatching(C TruthContainer, T p) {
1101 T ptrPart = nullptr;
1102 if (!p) return ptrPart;
1103 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1104 for (T truthParticle : *TruthContainer) {
1105 if (HepMC::is_sim_descendant(p,truthParticle)) {
1106 ptrPart = truthParticle;
1107 break;
1108 }
1109 }
1110 }
1111 else {
1112 for (T truthParticle : TruthContainer) {
1113 if (HepMC::is_sim_descendant(p,truthParticle)) {
1114 ptrPart = truthParticle;
1115 break;
1116 }
1117 }
1118 }
1119 return ptrPart;
1120 }
1122
1123 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1124 auto prodVtx = thePart->production_vertex();
1125 if (!prodVtx) return;
1126 for (const auto& theMother: prodVtx->particles_in()) {
1127 if (!theMother) continue;
1128 allancestors.insert(theMother);
1129 findParticleAncestors(theMother, allancestors);
1130 }
1131 }
1132
1134
1135 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1136 auto endVtx = thePart->end_vertex();
1137 if (!endVtx) return;
1138 for (const auto& theDaughter: endVtx->particles_out()) {
1139 if (!theDaughter) continue;
1140 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1141 allstabledescendants.insert(theDaughter);
1142 }
1143 findParticleStableDescendants(theDaughter, allstabledescendants);
1144 }
1145 }
1146
1150
1151 template <class T> bool isHardScatteringVertex(T pVert) {
1152 if (pVert == nullptr) return false;
1153 T pV = pVert;
1154 int numOfPartIn(0);
1155 int pdg(0);
1156
1157 do {
1158 pVert = pV;
1159 auto incoming = pVert->particles_in();
1160 numOfPartIn = incoming.size();
1161 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1162 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1163
1164 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1165
1166 if (numOfPartIn == 2) {
1167 auto incoming = pVert->particles_in();
1168 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1169 }
1170 return false;
1171}
1172
1176
1177 template <class T, class U>
1178 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 : particles_in(vtx) ) {
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 381 of file HepMCHelpers.h.

400{
401 template <class VTX>
402 auto particles_in (const VTX* p) { return p->particles_in(); }
403 template <class VTX>
404 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
581 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 : particles_in(vtx) ) {
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 380 of file HepMCHelpers.h.

399{
400 template <class VTX>
401 auto particles_in (const VTX* p) { return p->particles_in(); }
402 template <class VTX>
403 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
404
405 namespace Pythia8
406 {
408 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
409
410 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
411
412 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
413 }
414
415#include "AtlasPID.h"
416
418 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
419
421 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
422
424 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
425
427 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
428
430 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
431
433 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
434
436 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
437
439 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
440
442 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
443
445 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
446
450 template <class T> inline bool isStableOrSimDecayed(const T& p) {
451 const auto vertex = p->end_vertex();
452 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
453 }
454
456 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
457
459 template <class T> inline bool isSpecialNonInteracting(const T& p) {
460 const int apid = std::abs(p->pdg_id());
461 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
462 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
463 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
464 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
465 return false;
466 }
467
469
470 template <class T> T findMother(T thePart) {
471 auto partOriVert = thePart->production_vertex();
472 if (!partOriVert) return nullptr;
473
474 long partPDG = thePart->pdg_id();
475 long MotherPDG(0);
476
477 auto MothOriVert = partOriVert;
478 MothOriVert = nullptr;
479 T theMoth(nullptr);
480
481 size_t itr = 0;
482 do {
483 if (itr != 0) partOriVert = MothOriVert;
484 for ( const auto& p : particles_in(partOriVert) ) {
485 theMoth = p;
486 if (!theMoth) continue;
487 MotherPDG = theMoth->pdg_id();
488 MothOriVert = theMoth->production_vertex();
489 if (MotherPDG == partPDG) break;
490 }
491 itr++;
492 if (itr > 100) {
493 break;
494 }
495 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
496 MothOriVert != partOriVert);
497 return theMoth;
498 }
499
501
502 template <class C, class T> T findMatching(C TruthContainer, T p) {
503 T ptrPart = nullptr;
504 if (!p) return ptrPart;
505 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
506 for (T truthParticle : *TruthContainer) {
507 if (HepMC::is_sim_descendant(p,truthParticle)) {
508 ptrPart = truthParticle;
509 break;
510 }
511 }
512 }
513 else {
514 for (T truthParticle : TruthContainer) {
515 if (HepMC::is_sim_descendant(p,truthParticle)) {
516 ptrPart = truthParticle;
517 break;
518 }
519 }
520 }
521 return ptrPart;
522 }
524
525 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
526 auto prodVtx = thePart->production_vertex();
527 if (!prodVtx) return;
528 for (const auto& theMother: prodVtx->particles_in()) {
529 if (!theMother) continue;
530 allancestors.insert(theMother);
531 findParticleAncestors(theMother, allancestors);
532 }
533 }
534
536
537 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
538 auto endVtx = thePart->end_vertex();
539 if (!endVtx) return;
540 for (const auto& theDaughter: endVtx->particles_out()) {
541 if (!theDaughter) continue;
542 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
543 allstabledescendants.insert(theDaughter);
544 }
545 findParticleStableDescendants(theDaughter, allstabledescendants);
546 }
547 }
548
552
553 template <class T> bool isHardScatteringVertex(T pVert) {
554 if (pVert == nullptr) return false;
555 T pV = pVert;
556 int numOfPartIn(0);
557 int pdg(0);
558
559 do {
560 pVert = pV;
561 auto incoming = pVert->particles_in();
562 numOfPartIn = incoming.size();
563 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
564 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
565
566 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
567
568 if (numOfPartIn == 2) {
569 auto incoming = pVert->particles_in();
570 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
571 }
572 return false;
573}
574
578
579 template <class T, class U>
580 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 : particles_in(vtx) ) {
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 77 of file HepMCHelpers.h.

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

◆ leadingQuark() [1/3]

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

Definition at line 891 of file HepMCHelpers.h.

910{
911 template <class VTX>
912 auto particles_in (const VTX* p) { return p->particles_in(); }
913 template <class VTX>
914 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1091 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 : particles_in(vtx) ) {
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 907 of file HepMCHelpers.h.

926{
927 template <class VTX>
928 auto particles_in (const VTX* p) { return p->particles_in(); }
929 template <class VTX>
930 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
931
932 namespace Pythia8
933 {
935 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
936
937 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
938
939 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
940 }
941
942#include "AtlasPID.h"
943
945 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
946
948 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
949
951 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
952
954 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
955
957 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
958
960 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
961
963 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
964
966 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
967
969 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
970
972 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
973
977 template <class T> inline bool isStableOrSimDecayed(const T& p) {
978 const auto vertex = p->end_vertex();
979 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
980 }
981
983 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
984
986 template <class T> inline bool isSpecialNonInteracting(const T& p) {
987 const int apid = std::abs(p->pdg_id());
988 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
989 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
990 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
991 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
992 return false;
993 }
994
996
997 template <class T> T findMother(T thePart) {
998 auto partOriVert = thePart->production_vertex();
999 if (!partOriVert) return nullptr;
1000
1001 long partPDG = thePart->pdg_id();
1002 long MotherPDG(0);
1003
1004 auto MothOriVert = partOriVert;
1005 MothOriVert = nullptr;
1006 T theMoth(nullptr);
1007
1008 size_t itr = 0;
1009 do {
1010 if (itr != 0) partOriVert = MothOriVert;
1011 for ( const auto& p : particles_in(partOriVert) ) {
1012 theMoth = p;
1013 if (!theMoth) continue;
1014 MotherPDG = theMoth->pdg_id();
1015 MothOriVert = theMoth->production_vertex();
1016 if (MotherPDG == partPDG) break;
1017 }
1018 itr++;
1019 if (itr > 100) {
1020 break;
1021 }
1022 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1023 MothOriVert != partOriVert);
1024 return theMoth;
1025 }
1026
1028
1029 template <class C, class T> T findMatching(C TruthContainer, T p) {
1030 T ptrPart = nullptr;
1031 if (!p) return ptrPart;
1032 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1033 for (T truthParticle : *TruthContainer) {
1034 if (HepMC::is_sim_descendant(p,truthParticle)) {
1035 ptrPart = truthParticle;
1036 break;
1037 }
1038 }
1039 }
1040 else {
1041 for (T truthParticle : TruthContainer) {
1042 if (HepMC::is_sim_descendant(p,truthParticle)) {
1043 ptrPart = truthParticle;
1044 break;
1045 }
1046 }
1047 }
1048 return ptrPart;
1049 }
1051
1052 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1053 auto prodVtx = thePart->production_vertex();
1054 if (!prodVtx) return;
1055 for (const auto& theMother: prodVtx->particles_in()) {
1056 if (!theMother) continue;
1057 allancestors.insert(theMother);
1058 findParticleAncestors(theMother, allancestors);
1059 }
1060 }
1061
1063
1064 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1065 auto endVtx = thePart->end_vertex();
1066 if (!endVtx) return;
1067 for (const auto& theDaughter: endVtx->particles_out()) {
1068 if (!theDaughter) continue;
1069 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1070 allstabledescendants.insert(theDaughter);
1071 }
1072 findParticleStableDescendants(theDaughter, allstabledescendants);
1073 }
1074 }
1075
1079
1080 template <class T> bool isHardScatteringVertex(T pVert) {
1081 if (pVert == nullptr) return false;
1082 T pV = pVert;
1083 int numOfPartIn(0);
1084 int pdg(0);
1085
1086 do {
1087 pVert = pV;
1088 auto incoming = pVert->particles_in();
1089 numOfPartIn = incoming.size();
1090 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1091 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1092
1093 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1094
1095 if (numOfPartIn == 2) {
1096 auto incoming = pVert->particles_in();
1097 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1098 }
1099 return false;
1100}
1101
1105
1106 template <class T, class U>
1107 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 : particles_in(vtx) ) {
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 890 of file HepMCHelpers.h.

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

273{ 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 826 of file HepMCHelpers.h.

845{
846 template <class VTX>
847 auto particles_in (const VTX* p) { return p->particles_in(); }
848 template <class VTX>
849 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1026 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 : particles_in(vtx) ) {
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 831 of file HepMCHelpers.h.

850{
851 template <class VTX>
852 auto particles_in (const VTX* p) { return p->particles_in(); }
853 template <class VTX>
854 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
855
856 namespace Pythia8
857 {
859 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
860
861 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
862
863 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
864 }
865
866#include "AtlasPID.h"
867
869 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
870
872 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
873
875 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
876
878 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
879
881 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
882
884 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
885
887 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
888
890 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
891
893 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
894
896 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
897
901 template <class T> inline bool isStableOrSimDecayed(const T& p) {
902 const auto vertex = p->end_vertex();
903 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
904 }
905
907 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
908
910 template <class T> inline bool isSpecialNonInteracting(const T& p) {
911 const int apid = std::abs(p->pdg_id());
912 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
913 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
914 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
915 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
916 return false;
917 }
918
920
921 template <class T> T findMother(T thePart) {
922 auto partOriVert = thePart->production_vertex();
923 if (!partOriVert) return nullptr;
924
925 long partPDG = thePart->pdg_id();
926 long MotherPDG(0);
927
928 auto MothOriVert = partOriVert;
929 MothOriVert = nullptr;
930 T theMoth(nullptr);
931
932 size_t itr = 0;
933 do {
934 if (itr != 0) partOriVert = MothOriVert;
935 for ( const auto& p : particles_in(partOriVert) ) {
936 theMoth = p;
937 if (!theMoth) continue;
938 MotherPDG = theMoth->pdg_id();
939 MothOriVert = theMoth->production_vertex();
940 if (MotherPDG == partPDG) break;
941 }
942 itr++;
943 if (itr > 100) {
944 break;
945 }
946 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
947 MothOriVert != partOriVert);
948 return theMoth;
949 }
950
952
953 template <class C, class T> T findMatching(C TruthContainer, T p) {
954 T ptrPart = nullptr;
955 if (!p) return ptrPart;
956 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
957 for (T truthParticle : *TruthContainer) {
958 if (HepMC::is_sim_descendant(p,truthParticle)) {
959 ptrPart = truthParticle;
960 break;
961 }
962 }
963 }
964 else {
965 for (T truthParticle : TruthContainer) {
966 if (HepMC::is_sim_descendant(p,truthParticle)) {
967 ptrPart = truthParticle;
968 break;
969 }
970 }
971 }
972 return ptrPart;
973 }
975
976 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
977 auto prodVtx = thePart->production_vertex();
978 if (!prodVtx) return;
979 for (const auto& theMother: prodVtx->particles_in()) {
980 if (!theMother) continue;
981 allancestors.insert(theMother);
982 findParticleAncestors(theMother, allancestors);
983 }
984 }
985
987
988 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
989 auto endVtx = thePart->end_vertex();
990 if (!endVtx) return;
991 for (const auto& theDaughter: endVtx->particles_out()) {
992 if (!theDaughter) continue;
993 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
994 allstabledescendants.insert(theDaughter);
995 }
996 findParticleStableDescendants(theDaughter, allstabledescendants);
997 }
998 }
999
1003
1004 template <class T> bool isHardScatteringVertex(T pVert) {
1005 if (pVert == nullptr) return false;
1006 T pV = pVert;
1007 int numOfPartIn(0);
1008 int pdg(0);
1009
1010 do {
1011 pVert = pV;
1012 auto incoming = pVert->particles_in();
1013 numOfPartIn = incoming.size();
1014 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1015 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1016
1017 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1018
1019 if (numOfPartIn == 2) {
1020 auto incoming = pVert->particles_in();
1021 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1022 }
1023 return false;
1024}
1025
1029
1030 template <class T, class U>
1031 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 : particles_in(vtx) ) {
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 825 of file HepMCHelpers.h.

844{
845 template <class VTX>
846 auto particles_in (const VTX* p) { return p->particles_in(); }
847 template <class VTX>
848 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
849
850 namespace Pythia8
851 {
853 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
854
855 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
856
857 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
858 }
859
860#include "AtlasPID.h"
861
863 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
864
866 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
867
869 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
870
872 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
873
875 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
876
878 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
879
881 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
882
884 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
885
887 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
888
890 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
891
895 template <class T> inline bool isStableOrSimDecayed(const T& p) {
896 const auto vertex = p->end_vertex();
897 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
898 }
899
901 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
902
904 template <class T> inline bool isSpecialNonInteracting(const T& p) {
905 const int apid = std::abs(p->pdg_id());
906 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
907 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
908 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
909 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
910 return false;
911 }
912
914
915 template <class T> T findMother(T thePart) {
916 auto partOriVert = thePart->production_vertex();
917 if (!partOriVert) return nullptr;
918
919 long partPDG = thePart->pdg_id();
920 long MotherPDG(0);
921
922 auto MothOriVert = partOriVert;
923 MothOriVert = nullptr;
924 T theMoth(nullptr);
925
926 size_t itr = 0;
927 do {
928 if (itr != 0) partOriVert = MothOriVert;
929 for ( const auto& p : particles_in(partOriVert) ) {
930 theMoth = p;
931 if (!theMoth) continue;
932 MotherPDG = theMoth->pdg_id();
933 MothOriVert = theMoth->production_vertex();
934 if (MotherPDG == partPDG) break;
935 }
936 itr++;
937 if (itr > 100) {
938 break;
939 }
940 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
941 MothOriVert != partOriVert);
942 return theMoth;
943 }
944
946
947 template <class C, class T> T findMatching(C TruthContainer, T p) {
948 T ptrPart = nullptr;
949 if (!p) return ptrPart;
950 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
951 for (T truthParticle : *TruthContainer) {
952 if (HepMC::is_sim_descendant(p,truthParticle)) {
953 ptrPart = truthParticle;
954 break;
955 }
956 }
957 }
958 else {
959 for (T truthParticle : TruthContainer) {
960 if (HepMC::is_sim_descendant(p,truthParticle)) {
961 ptrPart = truthParticle;
962 break;
963 }
964 }
965 }
966 return ptrPart;
967 }
969
970 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
971 auto prodVtx = thePart->production_vertex();
972 if (!prodVtx) return;
973 for (const auto& theMother: prodVtx->particles_in()) {
974 if (!theMother) continue;
975 allancestors.insert(theMother);
976 findParticleAncestors(theMother, allancestors);
977 }
978 }
979
981
982 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
983 auto endVtx = thePart->end_vertex();
984 if (!endVtx) return;
985 for (const auto& theDaughter: endVtx->particles_out()) {
986 if (!theDaughter) continue;
987 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
988 allstabledescendants.insert(theDaughter);
989 }
990 findParticleStableDescendants(theDaughter, allstabledescendants);
991 }
992 }
993
997
998 template <class T> bool isHardScatteringVertex(T pVert) {
999 if (pVert == nullptr) return false;
1000 T pV = pVert;
1001 int numOfPartIn(0);
1002 int pdg(0);
1003
1004 do {
1005 pVert = pV;
1006 auto incoming = pVert->particles_in();
1007 numOfPartIn = incoming.size();
1008 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1009 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1010
1011 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1012
1013 if (numOfPartIn == 2) {
1014 auto incoming = pVert->particles_in();
1015 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1016 }
1017 return false;
1018}
1019
1023
1024 template <class T, class U>
1025 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 : particles_in(vtx) ) {
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 835 of file HepMCHelpers.h.

854{
855 template <class VTX>
856 auto particles_in (const VTX* p) { return p->particles_in(); }
857 template <class VTX>
858 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1035 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 : particles_in(vtx) ) {
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 843 of file HepMCHelpers.h.

862{
863 template <class VTX>
864 auto particles_in (const VTX* p) { return p->particles_in(); }
865 template <class VTX>
866 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
867
868 namespace Pythia8
869 {
871 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
872
873 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
874
875 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
876 }
877
878#include "AtlasPID.h"
879
881 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
882
884 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
885
887 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
888
890 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
891
893 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
894
896 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
897
899 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
900
902 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
903
905 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
906
908 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
909
913 template <class T> inline bool isStableOrSimDecayed(const T& p) {
914 const auto vertex = p->end_vertex();
915 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
916 }
917
919 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
920
922 template <class T> inline bool isSpecialNonInteracting(const T& p) {
923 const int apid = std::abs(p->pdg_id());
924 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
925 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
926 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
927 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
928 return false;
929 }
930
932
933 template <class T> T findMother(T thePart) {
934 auto partOriVert = thePart->production_vertex();
935 if (!partOriVert) return nullptr;
936
937 long partPDG = thePart->pdg_id();
938 long MotherPDG(0);
939
940 auto MothOriVert = partOriVert;
941 MothOriVert = nullptr;
942 T theMoth(nullptr);
943
944 size_t itr = 0;
945 do {
946 if (itr != 0) partOriVert = MothOriVert;
947 for ( const auto& p : particles_in(partOriVert) ) {
948 theMoth = p;
949 if (!theMoth) continue;
950 MotherPDG = theMoth->pdg_id();
951 MothOriVert = theMoth->production_vertex();
952 if (MotherPDG == partPDG) break;
953 }
954 itr++;
955 if (itr > 100) {
956 break;
957 }
958 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
959 MothOriVert != partOriVert);
960 return theMoth;
961 }
962
964
965 template <class C, class T> T findMatching(C TruthContainer, T p) {
966 T ptrPart = nullptr;
967 if (!p) return ptrPart;
968 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
969 for (T truthParticle : *TruthContainer) {
970 if (HepMC::is_sim_descendant(p,truthParticle)) {
971 ptrPart = truthParticle;
972 break;
973 }
974 }
975 }
976 else {
977 for (T truthParticle : TruthContainer) {
978 if (HepMC::is_sim_descendant(p,truthParticle)) {
979 ptrPart = truthParticle;
980 break;
981 }
982 }
983 }
984 return ptrPart;
985 }
987
988 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
989 auto prodVtx = thePart->production_vertex();
990 if (!prodVtx) return;
991 for (const auto& theMother: prodVtx->particles_in()) {
992 if (!theMother) continue;
993 allancestors.insert(theMother);
994 findParticleAncestors(theMother, allancestors);
995 }
996 }
997
999
1000 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1001 auto endVtx = thePart->end_vertex();
1002 if (!endVtx) return;
1003 for (const auto& theDaughter: endVtx->particles_out()) {
1004 if (!theDaughter) continue;
1005 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1006 allstabledescendants.insert(theDaughter);
1007 }
1008 findParticleStableDescendants(theDaughter, allstabledescendants);
1009 }
1010 }
1011
1015
1016 template <class T> bool isHardScatteringVertex(T pVert) {
1017 if (pVert == nullptr) return false;
1018 T pV = pVert;
1019 int numOfPartIn(0);
1020 int pdg(0);
1021
1022 do {
1023 pVert = pV;
1024 auto incoming = pVert->particles_in();
1025 numOfPartIn = incoming.size();
1026 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1027 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1028
1029 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1030
1031 if (numOfPartIn == 2) {
1032 auto incoming = pVert->particles_in();
1033 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1034 }
1035 return false;
1036}
1037
1041
1042 template <class T, class U>
1043 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 : particles_in(vtx) ) {
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 834 of file HepMCHelpers.h.

853{
854 template <class VTX>
855 auto particles_in (const VTX* p) { return p->particles_in(); }
856 template <class VTX>
857 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
858
859 namespace Pythia8
860 {
862 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
863
864 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
865
866 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
867 }
868
869#include "AtlasPID.h"
870
872 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
873
875 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
876
878 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
879
881 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
882
884 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
885
887 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
888
890 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
891
893 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
894
896 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
897
899 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
900
904 template <class T> inline bool isStableOrSimDecayed(const T& p) {
905 const auto vertex = p->end_vertex();
906 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
907 }
908
910 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
911
913 template <class T> inline bool isSpecialNonInteracting(const T& p) {
914 const int apid = std::abs(p->pdg_id());
915 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
916 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
917 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
918 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
919 return false;
920 }
921
923
924 template <class T> T findMother(T thePart) {
925 auto partOriVert = thePart->production_vertex();
926 if (!partOriVert) return nullptr;
927
928 long partPDG = thePart->pdg_id();
929 long MotherPDG(0);
930
931 auto MothOriVert = partOriVert;
932 MothOriVert = nullptr;
933 T theMoth(nullptr);
934
935 size_t itr = 0;
936 do {
937 if (itr != 0) partOriVert = MothOriVert;
938 for ( const auto& p : particles_in(partOriVert) ) {
939 theMoth = p;
940 if (!theMoth) continue;
941 MotherPDG = theMoth->pdg_id();
942 MothOriVert = theMoth->production_vertex();
943 if (MotherPDG == partPDG) break;
944 }
945 itr++;
946 if (itr > 100) {
947 break;
948 }
949 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
950 MothOriVert != partOriVert);
951 return theMoth;
952 }
953
955
956 template <class C, class T> T findMatching(C TruthContainer, T p) {
957 T ptrPart = nullptr;
958 if (!p) return ptrPart;
959 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
960 for (T truthParticle : *TruthContainer) {
961 if (HepMC::is_sim_descendant(p,truthParticle)) {
962 ptrPart = truthParticle;
963 break;
964 }
965 }
966 }
967 else {
968 for (T truthParticle : TruthContainer) {
969 if (HepMC::is_sim_descendant(p,truthParticle)) {
970 ptrPart = truthParticle;
971 break;
972 }
973 }
974 }
975 return ptrPart;
976 }
978
979 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
980 auto prodVtx = thePart->production_vertex();
981 if (!prodVtx) return;
982 for (const auto& theMother: prodVtx->particles_in()) {
983 if (!theMother) continue;
984 allancestors.insert(theMother);
985 findParticleAncestors(theMother, allancestors);
986 }
987 }
988
990
991 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
992 auto endVtx = thePart->end_vertex();
993 if (!endVtx) return;
994 for (const auto& theDaughter: endVtx->particles_out()) {
995 if (!theDaughter) continue;
996 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
997 allstabledescendants.insert(theDaughter);
998 }
999 findParticleStableDescendants(theDaughter, allstabledescendants);
1000 }
1001 }
1002
1006
1007 template <class T> bool isHardScatteringVertex(T pVert) {
1008 if (pVert == nullptr) return false;
1009 T pV = pVert;
1010 int numOfPartIn(0);
1011 int pdg(0);
1012
1013 do {
1014 pVert = pV;
1015 auto incoming = pVert->particles_in();
1016 numOfPartIn = incoming.size();
1017 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1018 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1019
1020 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1021
1022 if (numOfPartIn == 2) {
1023 auto incoming = pVert->particles_in();
1024 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1025 }
1026 return false;
1027}
1028
1032
1033 template <class T, class U>
1034 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 : particles_in(vtx) ) {
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

◆ particles_in() [1/2]

template<class VTX>
auto MC::particles_in ( const std::shared_ptr< VTX > & p)

Definition at line 24 of file HepMCHelpers.h.

24{ return p->particles_in(); }

◆ particles_in() [2/2]

template<class VTX>
auto MC::particles_in ( const VTX * p)

Definition at line 22 of file HepMCHelpers.h.

22{ return p->particles_in(); }

◆ spin() [1/3]

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

Definition at line 1154 of file HepMCHelpers.h.

1173{
1174 template <class VTX>
1175 auto particles_in (const VTX* p) { return p->particles_in(); }
1176 template <class VTX>
1177 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1354 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 : particles_in(vtx) ) {
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() [2/3]

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

Definition at line 1155 of file HepMCHelpers.h.

1174{
1175 template <class VTX>
1176 auto particles_in (const VTX* p) { return p->particles_in(); }
1177 template <class VTX>
1178 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1355 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1356 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1357 auto vtx = p->production_vertex();
1358 if (!vtx) return false;
1359 bool fromHad = false;
1360 for ( const auto& parent : particles_in(vtx) ) {
1361 if (!parent) continue;
1362 // should this really go into parton-level territory?
1363 // probably depends where BSM particles are being decayed
1364 fromBSM |= isBSM(parent);
1365 if (!isPhysical(parent)) return false;
1366 fromTau |= isTau(parent);
1367 if (isHadron(parent)&&!isBeam(parent)) {
1368 if (!hadron) hadron = parent; // assumes linear hadron parentage
1369 return true;
1370 }
1371 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1372 }
1373 return fromHad;
1374 }
1375
1378
1379 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1380 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1381 decltype(thePart->end_vertex()) pVert(nullptr);
1382 if (EndVert != nullptr) {
1383 do {
1384 bool samePart = false;
1385 pVert = nullptr;
1386 auto outgoing = EndVert->particles_out();
1387 auto incoming = EndVert->particles_in();
1388 for (const auto& itrDaug: outgoing) {
1389 if (!itrDaug) continue;
1390 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1391 // brem on generator level for tau
1392 (outgoing.size() == 1 && incoming.size() == 1 &&
1394 itrDaug->pdg_id() == thePart->pdg_id()) {
1395 samePart = true;
1396 pVert = itrDaug->end_vertex();
1397 }
1398 }
1399 if (samePart) EndVert = pVert;
1400 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1401 }
1402 return EndVert;
1403 }
1404
1406
1407 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1408 if (!theVert) return {};
1409 decltype(theVert->particles_out()) finalStatePart;
1410 auto outgoing = theVert->particles_out();
1411 for (const auto& thePart: outgoing) {
1412 if (!thePart) continue;
1413 finalStatePart.push_back(thePart);
1414 if (isStable(thePart)) continue;
1415 V pVert = findSimulatedEndVertex(thePart);
1416 if (pVert == theVert) break; // to prevent Sherpa loop
1417 if (pVert != nullptr) {
1418 auto vecPart = findFinalStateParticles<V>(pVert);
1419 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1420 }
1421 }
1422 return finalStatePart;
1423 }
1424#if !defined(XAOD_ANALYSIS)
1425#include "AtlasHepMC/GenEvent.h"
1426inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1427inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1428
1429#endif
1430}
1431#endif

◆ spin() [3/3]

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

Definition at line 1153 of file HepMCHelpers.h.

1172{
1173 template <class VTX>
1174 auto particles_in (const VTX* p) { return p->particles_in(); }
1175 template <class VTX>
1176 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1353 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 : particles_in(vtx) ) {
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

◆ spin2() [1/3]

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

Definition at line 1114 of file HepMCHelpers.h.

1133{
1134 template <class VTX>
1135 auto particles_in (const VTX* p) { return p->particles_in(); }
1136 template <class VTX>
1137 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1314 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1315 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1316 auto vtx = p->production_vertex();
1317 if (!vtx) return false;
1318 bool fromHad = false;
1319 for ( const auto& parent : particles_in(vtx) ) {
1320 if (!parent) continue;
1321 // should this really go into parton-level territory?
1322 // probably depends where BSM particles are being decayed
1323 fromBSM |= isBSM(parent);
1324 if (!isPhysical(parent)) return false;
1325 fromTau |= isTau(parent);
1326 if (isHadron(parent)&&!isBeam(parent)) {
1327 if (!hadron) hadron = parent; // assumes linear hadron parentage
1328 return true;
1329 }
1330 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1331 }
1332 return fromHad;
1333 }
1334
1337
1338 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1339 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1340 decltype(thePart->end_vertex()) pVert(nullptr);
1341 if (EndVert != nullptr) {
1342 do {
1343 bool samePart = false;
1344 pVert = nullptr;
1345 auto outgoing = EndVert->particles_out();
1346 auto incoming = EndVert->particles_in();
1347 for (const auto& itrDaug: outgoing) {
1348 if (!itrDaug) continue;
1349 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1350 // brem on generator level for tau
1351 (outgoing.size() == 1 && incoming.size() == 1 &&
1353 itrDaug->pdg_id() == thePart->pdg_id()) {
1354 samePart = true;
1355 pVert = itrDaug->end_vertex();
1356 }
1357 }
1358 if (samePart) EndVert = pVert;
1359 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1360 }
1361 return EndVert;
1362 }
1363
1365
1366 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1367 if (!theVert) return {};
1368 decltype(theVert->particles_out()) finalStatePart;
1369 auto outgoing = theVert->particles_out();
1370 for (const auto& thePart: outgoing) {
1371 if (!thePart) continue;
1372 finalStatePart.push_back(thePart);
1373 if (isStable(thePart)) continue;
1374 V pVert = findSimulatedEndVertex(thePart);
1375 if (pVert == theVert) break; // to prevent Sherpa loop
1376 if (pVert != nullptr) {
1377 auto vecPart = findFinalStateParticles<V>(pVert);
1378 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1379 }
1380 }
1381 return finalStatePart;
1382 }
1383#if !defined(XAOD_ANALYSIS)
1384#include "AtlasHepMC/GenEvent.h"
1385inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1386inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1387
1388#endif
1389}
1390#endif

◆ spin2() [2/3]

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

Definition at line 1151 of file HepMCHelpers.h.

1170{
1171 template <class VTX>
1172 auto particles_in (const VTX* p) { return p->particles_in(); }
1173 template <class VTX>
1174 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1351 bool isFromHadron(T p, U hadron, bool &fromTau, bool &fromBSM) {
1352 if (isHadron(p)&&!isBeam(p)) return true; // trivial case
1353 auto vtx = p->production_vertex();
1354 if (!vtx) return false;
1355 bool fromHad = false;
1356 for ( const auto& parent : particles_in(vtx) ) {
1357 if (!parent) continue;
1358 // should this really go into parton-level territory?
1359 // probably depends where BSM particles are being decayed
1360 fromBSM |= isBSM(parent);
1361 if (!isPhysical(parent)) return false;
1362 fromTau |= isTau(parent);
1363 if (isHadron(parent)&&!isBeam(parent)) {
1364 if (!hadron) hadron = parent; // assumes linear hadron parentage
1365 return true;
1366 }
1367 fromHad |= isFromHadron(parent, hadron, fromTau, fromBSM);
1368 }
1369 return fromHad;
1370 }
1371
1374
1375 template <class T> auto findSimulatedEndVertex(T thePart) -> decltype(thePart->end_vertex()) {
1376 decltype(thePart->end_vertex()) EndVert = thePart->end_vertex();
1377 decltype(thePart->end_vertex()) pVert(nullptr);
1378 if (EndVert != nullptr) {
1379 do {
1380 bool samePart = false;
1381 pVert = nullptr;
1382 auto outgoing = EndVert->particles_out();
1383 auto incoming = EndVert->particles_in();
1384 for (const auto& itrDaug: outgoing) {
1385 if (!itrDaug) continue;
1386 if ((( HepMC::is_same_generator_particle(itrDaug,thePart)) ||
1387 // brem on generator level for tau
1388 (outgoing.size() == 1 && incoming.size() == 1 &&
1390 itrDaug->pdg_id() == thePart->pdg_id()) {
1391 samePart = true;
1392 pVert = itrDaug->end_vertex();
1393 }
1394 }
1395 if (samePart) EndVert = pVert;
1396 } while (pVert != nullptr && pVert != EndVert); // pVert!=EndVert to prevent Sherpa loop
1397 }
1398 return EndVert;
1399 }
1400
1402
1403 template <class V> auto findFinalStateParticles(V theVert) -> decltype(theVert->particles_out()) {
1404 if (!theVert) return {};
1405 decltype(theVert->particles_out()) finalStatePart;
1406 auto outgoing = theVert->particles_out();
1407 for (const auto& thePart: outgoing) {
1408 if (!thePart) continue;
1409 finalStatePart.push_back(thePart);
1410 if (isStable(thePart)) continue;
1411 V pVert = findSimulatedEndVertex(thePart);
1412 if (pVert == theVert) break; // to prevent Sherpa loop
1413 if (pVert != nullptr) {
1414 auto vecPart = findFinalStateParticles<V>(pVert);
1415 finalStatePart.insert(finalStatePart.end(),vecPart.begin(),vecPart.end());
1416 }
1417 }
1418 return finalStatePart;
1419 }
1420#if !defined(XAOD_ANALYSIS)
1421#include "AtlasHepMC/GenEvent.h"
1422inline void GeVToMeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1000); p->set_generated_mass(1000* p->generated_mass());}}
1423inline void MeVToGeV(HepMC::GenEvent* evt) { for (auto& p: evt->particles()) { p->set_momentum(p->momentum()*1.0/1000); p->set_generated_mass(1.0/1000* p->generated_mass());} }
1424
1425#endif
1426}
1427#endif

◆ spin2() [3/3]

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

Definition at line 1113 of file HepMCHelpers.h.

1132{
1133 template <class VTX>
1134 auto particles_in (const VTX* p) { return p->particles_in(); }
1135 template <class VTX>
1136 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
1313 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 : particles_in(vtx) ) {
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

◆ strangeness() [1/3]

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

Definition at line 788 of file HepMCHelpers.h.

807{
808 template <class VTX>
809 auto particles_in (const VTX* p) { return p->particles_in(); }
810 template <class VTX>
811 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
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 : particles_in(partOriVert) ) {
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>
988 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 : particles_in(vtx) ) {
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 822 of file HepMCHelpers.h.

841{
842 template <class VTX>
843 auto particles_in (const VTX* p) { return p->particles_in(); }
844 template <class VTX>
845 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
846
847 namespace Pythia8
848 {
850 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
851
852 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
853
854 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
855 }
856
857#include "AtlasPID.h"
858
860 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
861
863 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
864
866 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
867
869 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
870
872 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
873
875 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
876
878 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
879
881 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
882
884 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
885
887 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
888
892 template <class T> inline bool isStableOrSimDecayed(const T& p) {
893 const auto vertex = p->end_vertex();
894 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
895 }
896
898 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
899
901 template <class T> inline bool isSpecialNonInteracting(const T& p) {
902 const int apid = std::abs(p->pdg_id());
903 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
904 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
905 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
906 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
907 return false;
908 }
909
911
912 template <class T> T findMother(T thePart) {
913 auto partOriVert = thePart->production_vertex();
914 if (!partOriVert) return nullptr;
915
916 long partPDG = thePart->pdg_id();
917 long MotherPDG(0);
918
919 auto MothOriVert = partOriVert;
920 MothOriVert = nullptr;
921 T theMoth(nullptr);
922
923 size_t itr = 0;
924 do {
925 if (itr != 0) partOriVert = MothOriVert;
926 for ( const auto& p : particles_in(partOriVert) ) {
927 theMoth = p;
928 if (!theMoth) continue;
929 MotherPDG = theMoth->pdg_id();
930 MothOriVert = theMoth->production_vertex();
931 if (MotherPDG == partPDG) break;
932 }
933 itr++;
934 if (itr > 100) {
935 break;
936 }
937 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
938 MothOriVert != partOriVert);
939 return theMoth;
940 }
941
943
944 template <class C, class T> T findMatching(C TruthContainer, T p) {
945 T ptrPart = nullptr;
946 if (!p) return ptrPart;
947 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
948 for (T truthParticle : *TruthContainer) {
949 if (HepMC::is_sim_descendant(p,truthParticle)) {
950 ptrPart = truthParticle;
951 break;
952 }
953 }
954 }
955 else {
956 for (T truthParticle : TruthContainer) {
957 if (HepMC::is_sim_descendant(p,truthParticle)) {
958 ptrPart = truthParticle;
959 break;
960 }
961 }
962 }
963 return ptrPart;
964 }
966
967 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
968 auto prodVtx = thePart->production_vertex();
969 if (!prodVtx) return;
970 for (const auto& theMother: prodVtx->particles_in()) {
971 if (!theMother) continue;
972 allancestors.insert(theMother);
973 findParticleAncestors(theMother, allancestors);
974 }
975 }
976
978
979 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
980 auto endVtx = thePart->end_vertex();
981 if (!endVtx) return;
982 for (const auto& theDaughter: endVtx->particles_out()) {
983 if (!theDaughter) continue;
984 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
985 allstabledescendants.insert(theDaughter);
986 }
987 findParticleStableDescendants(theDaughter, allstabledescendants);
988 }
989 }
990
994
995 template <class T> bool isHardScatteringVertex(T pVert) {
996 if (pVert == nullptr) return false;
997 T pV = pVert;
998 int numOfPartIn(0);
999 int pdg(0);
1000
1001 do {
1002 pVert = pV;
1003 auto incoming = pVert->particles_in();
1004 numOfPartIn = incoming.size();
1005 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1006 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1007
1008 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1009
1010 if (numOfPartIn == 2) {
1011 auto incoming = pVert->particles_in();
1012 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1013 }
1014 return false;
1015}
1016
1020
1021 template <class T, class U>
1022 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 : particles_in(vtx) ) {
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 787 of file HepMCHelpers.h.

806{
807 template <class VTX>
808 auto particles_in (const VTX* p) { return p->particles_in(); }
809 template <class VTX>
810 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
811
812 namespace Pythia8
813 {
815 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
816
817 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
818
819 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
820 }
821
822#include "AtlasPID.h"
823
825 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
826
828 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
829
831 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
832
834 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
835
837 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
838
840 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
841
843 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
844
846 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
847
849 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
850
852 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
853
857 template <class T> inline bool isStableOrSimDecayed(const T& p) {
858 const auto vertex = p->end_vertex();
859 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
860 }
861
863 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
864
866 template <class T> inline bool isSpecialNonInteracting(const T& p) {
867 const int apid = std::abs(p->pdg_id());
868 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
869 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
870 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
871 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
872 return false;
873 }
874
876
877 template <class T> T findMother(T thePart) {
878 auto partOriVert = thePart->production_vertex();
879 if (!partOriVert) return nullptr;
880
881 long partPDG = thePart->pdg_id();
882 long MotherPDG(0);
883
884 auto MothOriVert = partOriVert;
885 MothOriVert = nullptr;
886 T theMoth(nullptr);
887
888 size_t itr = 0;
889 do {
890 if (itr != 0) partOriVert = MothOriVert;
891 for ( const auto& p : particles_in(partOriVert) ) {
892 theMoth = p;
893 if (!theMoth) continue;
894 MotherPDG = theMoth->pdg_id();
895 MothOriVert = theMoth->production_vertex();
896 if (MotherPDG == partPDG) break;
897 }
898 itr++;
899 if (itr > 100) {
900 break;
901 }
902 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
903 MothOriVert != partOriVert);
904 return theMoth;
905 }
906
908
909 template <class C, class T> T findMatching(C TruthContainer, T p) {
910 T ptrPart = nullptr;
911 if (!p) return ptrPart;
912 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
913 for (T truthParticle : *TruthContainer) {
914 if (HepMC::is_sim_descendant(p,truthParticle)) {
915 ptrPart = truthParticle;
916 break;
917 }
918 }
919 }
920 else {
921 for (T truthParticle : TruthContainer) {
922 if (HepMC::is_sim_descendant(p,truthParticle)) {
923 ptrPart = truthParticle;
924 break;
925 }
926 }
927 }
928 return ptrPart;
929 }
931
932 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
933 auto prodVtx = thePart->production_vertex();
934 if (!prodVtx) return;
935 for (const auto& theMother: prodVtx->particles_in()) {
936 if (!theMother) continue;
937 allancestors.insert(theMother);
938 findParticleAncestors(theMother, allancestors);
939 }
940 }
941
943
944 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
945 auto endVtx = thePart->end_vertex();
946 if (!endVtx) return;
947 for (const auto& theDaughter: endVtx->particles_out()) {
948 if (!theDaughter) continue;
949 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
950 allstabledescendants.insert(theDaughter);
951 }
952 findParticleStableDescendants(theDaughter, allstabledescendants);
953 }
954 }
955
959
960 template <class T> bool isHardScatteringVertex(T pVert) {
961 if (pVert == nullptr) return false;
962 T pV = pVert;
963 int numOfPartIn(0);
964 int pdg(0);
965
966 do {
967 pVert = pV;
968 auto incoming = pVert->particles_in();
969 numOfPartIn = incoming.size();
970 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
971 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
972
973 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
974
975 if (numOfPartIn == 2) {
976 auto incoming = pVert->particles_in();
977 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
978 }
979 return false;
980}
981
985
986 template <class T, class U>
987 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 : particles_in(vtx) ) {
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 1004 of file HepMCHelpers.h.

1023{
1024 template <class VTX>
1025 auto particles_in (const VTX* p) { return p->particles_in(); }
1026 template <class VTX>
1027 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
1028
1029 namespace Pythia8
1030 {
1032 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
1033
1034 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
1035
1036 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
1037 }
1038
1039#include "AtlasPID.h"
1040
1042 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
1043
1045 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
1046
1048 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
1049
1051 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
1052
1054 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
1055
1057 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
1058
1060 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
1061
1063 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
1064
1066 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
1067
1069 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
1070
1074 template <class T> inline bool isStableOrSimDecayed(const T& p) {
1075 const auto vertex = p->end_vertex();
1076 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
1077 }
1078
1080 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
1081
1083 template <class T> inline bool isSpecialNonInteracting(const T& p) {
1084 const int apid = std::abs(p->pdg_id());
1085 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
1086 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
1087 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
1088 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
1089 return false;
1090 }
1091
1093
1094 template <class T> T findMother(T thePart) {
1095 auto partOriVert = thePart->production_vertex();
1096 if (!partOriVert) return nullptr;
1097
1098 long partPDG = thePart->pdg_id();
1099 long MotherPDG(0);
1100
1101 auto MothOriVert = partOriVert;
1102 MothOriVert = nullptr;
1103 T theMoth(nullptr);
1104
1105 size_t itr = 0;
1106 do {
1107 if (itr != 0) partOriVert = MothOriVert;
1108 for ( const auto& p : particles_in(partOriVert) ) {
1109 theMoth = p;
1110 if (!theMoth) continue;
1111 MotherPDG = theMoth->pdg_id();
1112 MothOriVert = theMoth->production_vertex();
1113 if (MotherPDG == partPDG) break;
1114 }
1115 itr++;
1116 if (itr > 100) {
1117 break;
1118 }
1119 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
1120 MothOriVert != partOriVert);
1121 return theMoth;
1122 }
1123
1125
1126 template <class C, class T> T findMatching(C TruthContainer, T p) {
1127 T ptrPart = nullptr;
1128 if (!p) return ptrPart;
1129 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
1130 for (T truthParticle : *TruthContainer) {
1131 if (HepMC::is_sim_descendant(p,truthParticle)) {
1132 ptrPart = truthParticle;
1133 break;
1134 }
1135 }
1136 }
1137 else {
1138 for (T truthParticle : TruthContainer) {
1139 if (HepMC::is_sim_descendant(p,truthParticle)) {
1140 ptrPart = truthParticle;
1141 break;
1142 }
1143 }
1144 }
1145 return ptrPart;
1146 }
1148
1149 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
1150 auto prodVtx = thePart->production_vertex();
1151 if (!prodVtx) return;
1152 for (const auto& theMother: prodVtx->particles_in()) {
1153 if (!theMother) continue;
1154 allancestors.insert(theMother);
1155 findParticleAncestors(theMother, allancestors);
1156 }
1157 }
1158
1160
1161 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
1162 auto endVtx = thePart->end_vertex();
1163 if (!endVtx) return;
1164 for (const auto& theDaughter: endVtx->particles_out()) {
1165 if (!theDaughter) continue;
1166 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
1167 allstabledescendants.insert(theDaughter);
1168 }
1169 findParticleStableDescendants(theDaughter, allstabledescendants);
1170 }
1171 }
1172
1176
1177 template <class T> bool isHardScatteringVertex(T pVert) {
1178 if (pVert == nullptr) return false;
1179 T pV = pVert;
1180 int numOfPartIn(0);
1181 int pdg(0);
1182
1183 do {
1184 pVert = pV;
1185 auto incoming = pVert->particles_in();
1186 numOfPartIn = incoming.size();
1187 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
1188 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
1189
1190 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
1191
1192 if (numOfPartIn == 2) {
1193 auto incoming = pVert->particles_in();
1194 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
1195 }
1196 return false;
1197}
1198
1202
1203 template <class T, class U>
1204 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 : particles_in(vtx) ) {
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

◆ B0

const int MC::B0 = 511
static

Definition at line 123 of file HepMCHelpers.h.

◆ BCPLUS

const int MC::BCPLUS = 541
static

Definition at line 124 of file HepMCHelpers.h.

◆ BPRIME

const int MC::BPRIME = 7
static

Definition at line 71 of file HepMCHelpers.h.

◆ BQUARK

const int MC::BQUARK = 5
static

Definition at line 69 of file HepMCHelpers.h.

◆ COMPOSITEGLUON

const int MC::COMPOSITEGLUON = 9
static

Definition at line 87 of file HepMCHelpers.h.

◆ CQUARK

const int MC::CQUARK = 4
static

Definition at line 68 of file HepMCHelpers.h.

◆ D0

const int MC::D0 = 421
static

Definition at line 120 of file HepMCHelpers.h.

◆ DARKPHOTON

const int MC::DARKPHOTON = 60000
static

PDG Ids for Mavtop madgraph UFO model found under DarkX.

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

Definition at line 107 of file HepMCHelpers.h.

◆ double_spin

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

Definition at line 51 of file HepMCHelpers.h.

52
54 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
55
57 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
58
60 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
61

◆ DPLUS

const int MC::DPLUS = 411
static

Definition at line 118 of file HepMCHelpers.h.

◆ DQUARK

const int MC::DQUARK = 1
static

Definition at line 65 of file HepMCHelpers.h.

◆ DSPLUS

const int MC::DSPLUS = 431
static

Definition at line 121 of file HepMCHelpers.h.

◆ DSTAR

const int MC::DSTAR = 413
static

Definition at line 119 of file HepMCHelpers.h.

◆ ELECTRON

const int MC::ELECTRON = 11
static

Definition at line 75 of file HepMCHelpers.h.

◆ GEANTINO0

const int MC::GEANTINO0 = 999
static

Definition at line 160 of file HepMCHelpers.h.

◆ GEANTINOPLUS

const int MC::GEANTINOPLUS = 998
static

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

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

Definition at line 159 of file HepMCHelpers.h.

◆ GLUON

const int MC::GLUON = 21
static

Definition at line 85 of file HepMCHelpers.h.

◆ GRAVITON

const int MC::GRAVITON = 39
static

Definition at line 99 of file HepMCHelpers.h.

◆ HELIUM

const int MC::HELIUM = 1000020040
static

Definition at line 145 of file HepMCHelpers.h.

◆ HIGGS2

const int MC::HIGGS2 = 35
static

Definition at line 95 of file HepMCHelpers.h.

◆ HIGGS3

const int MC::HIGGS3 = 36
static

Definition at line 96 of file HepMCHelpers.h.

◆ HIGGS4

const int MC::HIGGS4 = 40
static

Definition at line 100 of file HepMCHelpers.h.

◆ HIGGSBOSON

const int MC::HIGGSBOSON = 25
static

Definition at line 91 of file HepMCHelpers.h.

◆ HIGGSPLUS

const int MC::HIGGSPLUS = 37
static

Definition at line 97 of file HepMCHelpers.h.

◆ HIGGSPLUSPLUS

const int MC::HIGGSPLUSPLUS = 38
static

Definition at line 98 of file HepMCHelpers.h.

◆ is_strange

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

Definition at line 785 of file HepMCHelpers.h.

804{
805 template <class VTX>
806 auto particles_in (const VTX* p) { return p->particles_in(); }
807 template <class VTX>
808 auto particles_in (const std::shared_ptr<VTX>& p) { return p->particles_in(); }
809
810 namespace Pythia8
811 {
813 template <class T> inline bool isConditionA(const T& p) { return p->status() == 62 || p->status() == 52 || p->status() == 21 || p->status() == 22;}
814
815 template <class T> inline bool isConditionB(const T& p) { return p->status() == 23;}
816
817 template <class T> inline bool isConditionC(const T& p) { return p->status() > 30 && p->status() < 40;}
818 }
819
820#include "AtlasPID.h"
821
823 template <class T> inline bool isInteracting(const T& p) { return isStrongInteracting<T>(p) || isEMInteracting<T>(p) || isGeantino<T>(p); }
824
826 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
827
829 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
830
832 template <class T> inline bool isDecayed(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 2;}
833
835 template <class T> inline bool isStable(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1;}
836
838 template <class T> inline bool isFinalState(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 1 && !p->end_vertex();}
839
841 template <class T> inline bool isPhysical(const T& p) { return isStable<T>(p) || isDecayed<T>(p); }
842
844 template <class T> inline bool isGenStable(const T& p) { return isStable<T>(p) && !HepMC::is_simulation_particle<T>(p);}
845
847 template <class T> inline bool isSimStable(const T& p) { return isStable<T>(p) && !p->end_vertex() && HepMC::is_simulation_particle<T>(p);}
848
850 template <class T> inline bool isSimInteracting(const T& p) { return isGenStable<T>(p) && isInteracting<T>(p);}
851
855 template <class T> inline bool isStableOrSimDecayed(const T& p) {
856 const auto vertex = p->end_vertex();
857 return ( isStable<T>(p) || (isDecayed<T>(p) && (!vertex || HepMC::is_simulation_vertex(vertex))));
858 }
859
861 template <class T> inline bool isZeroEnergyPhoton(const T& p) { return isPhoton<T>(p) && p->e() == 0;}
862
864 template <class T> inline bool isSpecialNonInteracting(const T& p) {
865 const int apid = std::abs(p->pdg_id());
866 if (apid == NU_E || apid == NU_MU || apid == NU_TAU) return true; //< neutrinos
867 if (apid == 1000022 || apid == 1000024 || apid == 5100022) return true; // SUSY & KK photon and Z partners
868 if (apid == GRAVITON || apid == 1000039 || apid == 5000039) return true; //< gravitons: standard, SUSY and KK
869 if (apid == 9000001 || apid == 9000002 || apid == 9000003 || apid == 9000004 || apid == 9000005 || apid == 9000006) return true; //< exotic particles from monotop model
870 return false;
871 }
872
874
875 template <class T> T findMother(T thePart) {
876 auto partOriVert = thePart->production_vertex();
877 if (!partOriVert) return nullptr;
878
879 long partPDG = thePart->pdg_id();
880 long MotherPDG(0);
881
882 auto MothOriVert = partOriVert;
883 MothOriVert = nullptr;
884 T theMoth(nullptr);
885
886 size_t itr = 0;
887 do {
888 if (itr != 0) partOriVert = MothOriVert;
889 for ( const auto& p : particles_in(partOriVert) ) {
890 theMoth = p;
891 if (!theMoth) continue;
892 MotherPDG = theMoth->pdg_id();
893 MothOriVert = theMoth->production_vertex();
894 if (MotherPDG == partPDG) break;
895 }
896 itr++;
897 if (itr > 100) {
898 break;
899 }
900 } while (MothOriVert != nullptr && MotherPDG == partPDG && !HepMC::is_simulation_particle(thePart) &&
901 MothOriVert != partOriVert);
902 return theMoth;
903 }
904
906
907 template <class C, class T> T findMatching(C TruthContainer, T p) {
908 T ptrPart = nullptr;
909 if (!p) return ptrPart;
910 if constexpr (std::is_pointer_v<C> || HepMC::is_smart_ptr_v<C>){ //C is ptr
911 for (T truthParticle : *TruthContainer) {
912 if (HepMC::is_sim_descendant(p,truthParticle)) {
913 ptrPart = truthParticle;
914 break;
915 }
916 }
917 }
918 else {
919 for (T truthParticle : TruthContainer) {
920 if (HepMC::is_sim_descendant(p,truthParticle)) {
921 ptrPart = truthParticle;
922 break;
923 }
924 }
925 }
926 return ptrPart;
927 }
929
930 template <class T> void findParticleAncestors(T thePart, std::set<T>& allancestors) {
931 auto prodVtx = thePart->production_vertex();
932 if (!prodVtx) return;
933 for (const auto& theMother: prodVtx->particles_in()) {
934 if (!theMother) continue;
935 allancestors.insert(theMother);
936 findParticleAncestors(theMother, allancestors);
937 }
938 }
939
941
942 template <class T> void findParticleStableDescendants(T thePart, std::set<T>& allstabledescendants) {
943 auto endVtx = thePart->end_vertex();
944 if (!endVtx) return;
945 for (const auto& theDaughter: endVtx->particles_out()) {
946 if (!theDaughter) continue;
947 if (isStable(theDaughter) && !HepMC::is_simulation_particle(theDaughter)) {
948 allstabledescendants.insert(theDaughter);
949 }
950 findParticleStableDescendants(theDaughter, allstabledescendants);
951 }
952 }
953
957
958 template <class T> bool isHardScatteringVertex(T pVert) {
959 if (pVert == nullptr) return false;
960 T pV = pVert;
961 int numOfPartIn(0);
962 int pdg(0);
963
964 do {
965 pVert = pV;
966 auto incoming = pVert->particles_in();
967 numOfPartIn = incoming.size();
968 pdg = numOfPartIn && incoming.front() != nullptr ? incoming.front()->pdg_id() : 0;
969 pV = numOfPartIn && incoming.front() != nullptr ? incoming.front()->production_vertex() : nullptr;
970
971 } while (numOfPartIn == 1 && (std::abs(pdg) < 81 || std::abs(pdg) > 100) && pV != nullptr);
972
973 if (numOfPartIn == 2) {
974 auto incoming = pVert->particles_in();
975 if (incoming.at(0) && incoming.at(1) && (std::abs(incoming.at(0)->pdg_id()) < 7 || incoming.at(0)->pdg_id() == 21) && (std::abs(incoming.at(1)->pdg_id()) < 7 || incoming.at(1)->pdg_id() == 21)) return true;
976 }
977 return false;
978}
979
983
984 template <class T, class U>
985 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 : particles_in(vtx) ) {
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.

◆ LAMBDA0

const int MC::LAMBDA0 = 3122
static

Definition at line 127 of file HepMCHelpers.h.

◆ LAMBDAB0

const int MC::LAMBDAB0 = 5122
static

Definition at line 129 of file HepMCHelpers.h.

◆ LAMBDACPLUS

const int MC::LAMBDACPLUS = 4122
static

Definition at line 128 of file HepMCHelpers.h.

◆ LEAD

const int MC::LEAD = 1000822080
static

Definition at line 142 of file HepMCHelpers.h.

◆ LEPTOQUARK

const int MC::LEPTOQUARK = 42
static

Definition at line 101 of file HepMCHelpers.h.

◆ LPRIME

const int MC::LPRIME = 17
static

Definition at line 82 of file HepMCHelpers.h.

◆ MAVTOP

const int MC::MAVTOP = 60001
static

Definition at line 108 of file HepMCHelpers.h.

◆ MUON

const int MC::MUON = 13
static

Definition at line 78 of file HepMCHelpers.h.

◆ NEON

const int MC::NEON = 1000100200
static

Definition at line 144 of file HepMCHelpers.h.

◆ NEUTRON

const int MC::NEUTRON = 2112
static

Definition at line 126 of file HepMCHelpers.h.

◆ NU_E

const int MC::NU_E = 12
static

Definition at line 77 of file HepMCHelpers.h.

◆ NU_MU

const int MC::NU_MU = 14
static

Definition at line 79 of file HepMCHelpers.h.

◆ NU_TAU

const int MC::NU_TAU = 16
static

Definition at line 81 of file HepMCHelpers.h.

◆ NUPRIME

const int MC::NUPRIME = 18
static

Definition at line 83 of file HepMCHelpers.h.

◆ ODDERON

const int MC::ODDERON = 9990
static

Definition at line 151 of file HepMCHelpers.h.

◆ OXYGEN

const int MC::OXYGEN = 1000080160
static

Definition at line 143 of file HepMCHelpers.h.

◆ PHOTON

const int MC::PHOTON = 22
static

Definition at line 88 of file HepMCHelpers.h.

◆ PI0

const int MC::PI0 = 111
static

Definition at line 112 of file HepMCHelpers.h.

◆ PIMINUS

const int MC::PIMINUS = -PIPLUS
static

Definition at line 111 of file HepMCHelpers.h.

◆ PIPLUS

const int MC::PIPLUS = 211
static

Definition at line 110 of file HepMCHelpers.h.

◆ POMERON

const int MC::POMERON = 990
static

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

Definition at line 150 of file HepMCHelpers.h.

◆ POSITRON

const int MC::POSITRON = -ELECTRON
static

Definition at line 76 of file HepMCHelpers.h.

◆ PROTON

const int MC::PROTON = 2212
static

Definition at line 125 of file HepMCHelpers.h.

◆ PSI2S

const int MC::PSI2S = 20443
static

Definition at line 130 of file HepMCHelpers.h.

◆ QUARK_LIMIT

const int MC::QUARK_LIMIT = BPRIME
static

Definition at line 73 of file HepMCHelpers.h.

◆ REGGEON

const int MC::REGGEON = 110
static

Definition at line 152 of file HepMCHelpers.h.

◆ RH_NU_E

const int MC::RH_NU_E = 9900012
static

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

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

Definition at line 137 of file HepMCHelpers.h.

◆ RH_NU_MU

const int MC::RH_NU_MU = 9900014
static

Definition at line 138 of file HepMCHelpers.h.

◆ RH_NU_TAU

const int MC::RH_NU_TAU = 9900016
static

Definition at line 139 of file HepMCHelpers.h.

◆ SQUARK

const int MC::SQUARK = 3
static

Definition at line 67 of file HepMCHelpers.h.

◆ TABLESIZE

const int MC::TABLESIZE = 100
static

Definition at line 35 of file HepMCHelpers.h.

◆ TAU

const int MC::TAU = 15
static

Definition at line 80 of file HepMCHelpers.h.

◆ TPRIME

const int MC::TPRIME = 8
static

Definition at line 72 of file HepMCHelpers.h.

◆ TQUARK

const int MC::TQUARK = 6
static

Definition at line 70 of file HepMCHelpers.h.

◆ triple_charge

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

Definition at line 36 of file HepMCHelpers.h.

40
42 template <class T> inline bool isChargedNonShowering(const T& p) { return (isMuon<T>(p) || isSUSY<T>(p)); }
43
45 template <class T> inline bool isBeam(const T& p) { return HepMC::status(p)%HepMC::SIM_STATUS_THRESHOLD == 4;}
46
bool isSUSY(const T &p)
Definition AtlasPID.h:623
bool isMuon(const T &p)
Definition AtlasPID.h:205

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