File indexing completed on 2025-11-04 10:25:53
0001 
0002 #ifndef RIVET_SmearedJets_HH
0003 #define RIVET_SmearedJets_HH
0004 
0005 #include "Rivet/Jet.hh"
0006 #include "Rivet/Particle.hh"
0007 #include "Rivet/Projection.hh"
0008 #include "Rivet/Projections/JetFinder.hh"
0009 #include "Rivet/Tools/SmearingFunctions.hh"
0010 #include <functional>
0011 
0012 namespace Rivet {
0013 
0014 
0015   
0016 
0017 
0018   
0019   class SmearedJets : public JetFinder {
0020   public:
0021 
0022     
0023     
0024 
0025     
0026     
0027     
0028     SmearedJets(const JetFinder& ja,
0029                 const JetSmearFn& smearFn,
0030                 const JetEffFn& bTagEffFn=JET_BTAG_PERFECT,
0031                 const JetEffFn& cTagEffFn=JET_CTAG_PERFECT)
0032       : SmearedJets(ja, bTagEffFn, cTagEffFn, smearFn)
0033     {    }
0034 
0035 
0036     
0037     
0038     
0039     
0040     template <typename... Args,
0041               typename = std::enable_if_t< allArgumentsOf<JetEffSmearFn, Args...>::value >>
0042     SmearedJets(const JetFinder& ja, const JetEffFn& bTagEffFn, const JetEffFn& cTagEffFn, Args&& ... effSmearFns)
0043       : _detFns({JetEffSmearFn(std::forward<Args>(effSmearFns))...}), _bTagEffFn(bTagEffFn), _cTagEffFn(cTagEffFn)
0044     {
0045       setName("SmearedJets");
0046       declare(ja, "TruthJets");
0047     }
0048 
0049     
0050     
0051     
0052 
0053 
0054     
0055     RIVET_DEFAULT_PROJ_CLONE(SmearedJets);
0056 
0057     
0058 
0059     
0060     using Projection::operator =;
0061 
0062 
0063     
0064     CmpState compare(const Projection& p) const {
0065       
0066       const CmpState teq = mkPCmp(p, "TruthJets");
0067       if (teq != CmpState::EQ) return teq;
0068 
0069       
0070       const SmearedJets& other = dynamic_cast<const SmearedJets&>(p);
0071       const CmpState nfeq = cmp(_detFns.size(), other._detFns.size());
0072       if (nfeq != CmpState::EQ) return nfeq;
0073       for (size_t i = 0; i < _detFns.size(); ++i) {
0074         const CmpState feq = _detFns[i].cmp(other._detFns[i]);
0075         if (feq != CmpState::EQ) return feq;
0076       }
0077       return Rivet::cmp(get_address(_bTagEffFn), get_address(other._bTagEffFn)) ||
0078              Rivet::cmp(get_address(_cTagEffFn), get_address(other._cTagEffFn));
0079     }
0080 
0081 
0082     
0083     void project(const Event& e) {
0084       
0085       const Jets& truthjets = apply<JetFinder>(e, "TruthJets").jetsByPt(); 
0086       _recojets.clear(); _recojets.reserve(truthjets.size());
0087       
0088       for (const Jet& j : truthjets) {
0089         Jet jdet = j;
0090         bool keep = true;
0091         MSG_DEBUG("Truth jet: " << "mom=" << jdet.mom()/GeV << " GeV, pT=" << jdet.pT()/GeV << ", eta=" << jdet.eta());
0092         for (const JetEffSmearFn& fn : _detFns) {
0093           double jeff = -1;
0094           std::tie(jdet, jeff) = fn(jdet); 
0095           
0096           if (jdet.particles().empty() && !j.particles().empty()) jdet.particles() = j.particles();
0097           if (jdet.tags().empty() && !j.tags().empty()) jdet.tags() = j.tags();
0098           MSG_DEBUG("         ->" << "mom=" << jdet.mom()/GeV << " GeV, pT=" << jdet.pT()/GeV << ", eta=" << jdet.eta());
0099           
0100           
0101           
0102           
0103           
0104           if (jeff <= 0) { keep = false; break; } 
0105           if (jeff < 1 && rand01() > jeff)  { keep = false; break; } 
0106         }
0107         if (keep) _recojets.push_back(jdet);
0108       }
0109       
0110       for (Jet& j : _recojets) {
0111         
0112         const double beff = _bTagEffFn ? _bTagEffFn(j) : j.bTagged();
0113         const bool btag = beff == 1 || (beff != 0 && rand01() < beff);
0114         
0115         if (!btag && j.bTagged()) j.tags().erase(std::remove_if(j.tags().begin(), j.tags().end(), hasBottom), j.tags().end());
0116         if (btag && !j.bTagged()) j.tags().push_back(Particle(PID::BQUARK, j.mom())); 
0117         
0118         const double ceff = _cTagEffFn ? _cTagEffFn(j) : j.cTagged();
0119         const bool ctag = ceff == 1 || (ceff != 0 && rand01() < beff);
0120         
0121         if (!ctag && j.cTagged()) j.tags().erase(std::remove_if(j.tags().begin(), j.tags().end(), hasCharm), j.tags().end());
0122         if (ctag && !j.cTagged()) j.tags().push_back(Particle(PID::CQUARK, j.mom())); 
0123       }
0124     }
0125 
0126 
0127     
0128     Jets _jets() const { return _recojets; }
0129 
0130     
0131     const Jets truthJets() const {
0132       return getProjection<JetFinder>("TruthJets").jetsByPt();
0133     }
0134 
0135     
0136     void reset() { _recojets.clear(); }
0137 
0138 
0139   protected:
0140 
0141     
0142     Jets _recojets;
0143 
0144     
0145     vector<JetEffSmearFn> _detFns;
0146 
0147     
0148     JetEffFn _bTagEffFn, _cTagEffFn;
0149 
0150   };
0151 
0152 
0153 }
0154 
0155 #endif