File indexing completed on 2026-09-15 09:23:21
0001
0002 #ifndef RIVET_SmearedParticles_HH
0003 #define RIVET_SmearedParticles_HH
0004
0005 #include "Rivet/Particle.hh"
0006 #include "Rivet/Projection.hh"
0007 #include "Rivet/Projections/ParticleFinder.hh"
0008 #include "Rivet/Tools/SmearingFunctions.hh"
0009
0010 namespace Rivet {
0011
0012
0013
0014 class SmearedParticles : public ParticleFinder {
0015 public:
0016
0017
0018
0019
0020
0021 template<typename... Args,
0022 typename = std::enable_if_t< allArgumentsOf<ParticleEffSmearFn, Args...>::value >>
0023 SmearedParticles(const ParticleFinder& pf, Args&& ... effSmearFns)
0024 : SmearedParticles(pf, Cuts::open(), std::forward<Args>(effSmearFns) ...)
0025 { }
0026
0027
0028
0029
0030
0031
0032 template<typename... Args,
0033 typename = std::enable_if_t< allArgumentsOf<ParticleEffSmearFn, Args...>::value >>
0034 SmearedParticles(const ParticleFinder& pf, const Cut& c, Args&& ... effSmearFns)
0035 : ParticleFinder(c), _detFns({ParticleEffSmearFn(std::forward<Args>(effSmearFns))...})
0036 {
0037 setName("SmearedParticles");
0038 declare(pf, "TruthParticles");
0039 _noSmear = getEnvParam<bool>("RIVET_DISABLE_SMEARING", false);
0040 }
0041
0042
0043
0044 RIVET_DEFAULT_PROJ_CLONE(SmearedParticles);
0045
0046
0047
0048
0049 using Projection::operator =;
0050
0051
0052
0053
0054
0055
0056 CmpState compare(const Projection& p) const {
0057 const SmearedParticles& other = dynamic_cast<const SmearedParticles&>(p);
0058
0059
0060 const CmpState teq = mkPCmp(other, "TruthParticles");
0061 if (teq != CmpState::EQ) return teq;
0062
0063
0064 if (_cuts != other._cuts) return CmpState::NEQ;
0065
0066
0067 if (!_noSmear) {
0068 const CmpState nfeq = cmp(_detFns.size(), other._detFns.size());
0069 MSG_TRACE("Numbers of detector functions = " << _detFns.size() << " VS " << other._detFns.size());
0070 if (nfeq != CmpState::EQ) return nfeq;
0071 for (size_t i = 0; i < _detFns.size(); ++i) {
0072 const CmpState feq = _detFns[i].cmp(other._detFns[i]);
0073 if (feq != CmpState::EQ) return feq;
0074 }
0075 }
0076
0077
0078 MSG_DEBUG("Equivalent detected! " << p.name() << ", " << this->name());
0079 return CmpState::EQ;
0080 }
0081
0082
0083
0084 void project(const Event& e) {
0085 const Particles& truthparticles = apply<ParticleFinder>(e, "TruthParticles").particlesByPt();
0086
0087
0088 if (_noSmear) {
0089 _theParticles = select(truthparticles, _cuts);
0090 return;
0091 }
0092
0093
0094 _theParticles.clear(); _theParticles.reserve(truthparticles.size());
0095 for (const Particle& p : truthparticles) {
0096 Particle pdet = p;
0097 double peff = -1;
0098 bool keep = true;
0099 MSG_TRACE("Number of detector functions = " << _detFns.size());
0100 for (const ParticleEffSmearFn& fn : _detFns) {
0101 std::tie(pdet, peff) = fn(pdet);
0102
0103 if (peff <= 0 || rand01() > peff) keep = false;
0104 MSG_DEBUG("New det particle: pid=" << pdet.pid()
0105 << ", mom=" << pdet.mom()/GeV << " GeV, "
0106 << "pT=" << pdet.pT()/GeV << ", eta=" << pdet.eta()
0107 << " : eff=" << 100*peff << "%, discarded=" << std::boolalpha << !keep);
0108 if (!keep) break;
0109 }
0110
0111 if (!keep) continue;
0112
0113 if (!_cuts->accept(pdet)) continue;
0114
0115
0116 pdet.addConstituent(p);
0117 _theParticles.push_back(pdet);
0118 }
0119 }
0120
0121
0122 const Particles truthParticles() const {
0123 return getProjection<ParticleFinder>("TruthParticles").particlesByPt();
0124 }
0125
0126
0127 void reset() { _theParticles.clear(); }
0128
0129
0130 protected:
0131
0132
0133 vector<ParticleEffSmearFn> _detFns;
0134
0135
0136
0137
0138 bool _noSmear{false};
0139
0140 };
0141
0142
0143 }
0144
0145 #endif