File indexing completed on 2025-05-12 09:05:03
0001
0002 #ifndef RIVET_PartonicTops_HH
0003 #define RIVET_PartonicTops_HH
0004
0005 #include "Rivet/Projections/ParticleFinder.hh"
0006
0007 namespace Rivet {
0008
0009
0010
0011
0012
0013 enum class TopDecay {
0014 ANY=0, ALL=0,
0015 ELECTRON,
0016 MUON,
0017 TAU,
0018 E_MU,
0019 E_MU_TAU,
0020 HADRONIC
0021 };
0022
0023
0024 enum class WhichTop { FIRST, LAST };
0025
0026 enum class PromptEMuFromTau { YES, NO };
0027
0028 enum class InclHadronicTau { YES, NO };
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 class PartonicTops : public ParticleFinder {
0040 public:
0041
0042
0043
0044
0045
0046 PartonicTops(TopDecay decaymode,
0047 PromptEMuFromTau emu_from_prompt_tau=PromptEMuFromTau::YES,
0048 InclHadronicTau include_hadronic_taus=InclHadronicTau::NO,
0049 const Cut& c=Cuts::OPEN, WhichTop whichtop=WhichTop::LAST)
0050 : ParticleFinder(c), _topmode(whichtop), _decaymode(decaymode),
0051 _emu_from_prompt_tau(emu_from_prompt_tau == PromptEMuFromTau::YES),
0052 _include_hadronic_taus(include_hadronic_taus == InclHadronicTau::YES)
0053 { }
0054
0055
0056 PartonicTops(TopDecay decaymode, const Cut& c,
0057 PromptEMuFromTau emu_from_prompt_tau=PromptEMuFromTau::YES,
0058 InclHadronicTau include_hadronic_taus=InclHadronicTau::NO,
0059 WhichTop whichtop=WhichTop::LAST)
0060 : PartonicTops(decaymode, emu_from_prompt_tau, include_hadronic_taus, c, whichtop)
0061 { }
0062
0063
0064 PartonicTops(const Cut& c=Cuts::OPEN, WhichTop whichtop=WhichTop::LAST)
0065 : PartonicTops(TopDecay::ALL, PromptEMuFromTau::YES, InclHadronicTau::NO, c, whichtop)
0066 { }
0067
0068
0069
0070 RIVET_DEFAULT_PROJ_CLONE(PartonicTops);
0071
0072
0073
0074
0075
0076 using Projection::operator =;
0077
0078
0079
0080 const Particles& tops() const { return _theParticles; }
0081
0082
0083
0084 void clear() {
0085 _theParticles.clear();
0086 }
0087
0088
0089 protected:
0090
0091
0092 void project(const Event& event) {
0093
0094
0095 static bool donerubric = false;
0096 if (!donerubric) {
0097 MSG_WARNING("PartonicTops is not recommended: MC generators do not guarantee physical properties for, or even the existence of, partonic event-record entries. Caveat emptor!");
0098 donerubric = true;
0099 }
0100
0101
0102 _theParticles = select(event.allParticles(_cuts), (_topmode == WhichTop::LAST ? lastParticleWith(isTop) : firstParticleWith(isTop)));
0103
0104
0105 if (_decaymode != TopDecay::ALL) {
0106 const auto decaycheck = [&](const Particle& t) {
0107 const Particles descendants = t.allDescendants();
0108 const bool prompt_e = any(descendants, [&](const Particle& p){ return p.abspid() == PID::ELECTRON && p.isPrompt(_emu_from_prompt_tau) && !p.hasAncestorWith(Cuts::pid == PID::PHOTON, false); });
0109 const bool prompt_mu = any(descendants, [&](const Particle& p){ return p.abspid() == PID::MUON && p.isPrompt(_emu_from_prompt_tau) && !p.hasAncestorWith(Cuts::pid == PID::PHOTON, false); });
0110 if (prompt_e && (_decaymode == TopDecay::ELECTRON || _decaymode == TopDecay::E_MU || _decaymode == TopDecay::E_MU_TAU)) return true;
0111 if (prompt_mu && (_decaymode == TopDecay::MUON || _decaymode == TopDecay::E_MU || _decaymode == TopDecay::E_MU_TAU)) return true;
0112 const bool prompt_tau = any(descendants, [&](const Particle& p){ return p.abspid() == PID::TAU && p.isPrompt() && !p.hasAncestorWith(Cuts::pid == PID::PHOTON, false); });
0113 const bool prompt_hadronic_tau = any(descendants, [&](const Particle& p){ return p.abspid() == PID::TAU && p.isPrompt() && !p.hasAncestorWith(Cuts::pid == PID::PHOTON, false) && none(p.children(), isChargedLepton); });
0114 if (prompt_tau && (_decaymode == TopDecay::TAU || _decaymode == TopDecay::E_MU_TAU)) return (_include_hadronic_taus || !prompt_hadronic_tau);
0115 if (_decaymode == TopDecay::HADRONIC && (!prompt_e && !prompt_mu && (!prompt_tau || (_include_hadronic_taus && prompt_hadronic_tau)))) return true;
0116 return false;
0117 };
0118 iselect(_theParticles, decaycheck);
0119 }
0120
0121
0122 const auto physcheck = [&](const Particle& t) {
0123 if (t.E() < 0 || t.mass() < 0) {
0124 MSG_WARNING("Unphysical partonic top with negative E or m found: " << t.mom());
0125 return false;
0126 }
0127 return true;
0128 };
0129 iselect(_theParticles, physcheck);
0130 }
0131
0132
0133
0134 CmpState compare(const Projection& p) const {
0135 const PartonicTops& other = dynamic_cast<const PartonicTops&>(p);
0136 return cmp(_cuts, other._cuts) ||
0137 cmp(_topmode, other._topmode) ||
0138 cmp(_decaymode, other._decaymode) ||
0139 cmp(_emu_from_prompt_tau, other._emu_from_prompt_tau) ||
0140 cmp(_include_hadronic_taus, other._include_hadronic_taus);
0141 }
0142
0143
0144 protected:
0145
0146 WhichTop _topmode;
0147
0148 TopDecay _decaymode;
0149
0150 bool _emu_from_prompt_tau, _include_hadronic_taus;
0151
0152 };
0153
0154
0155 }
0156
0157 #endif