rivet is hosted by Hepforge, IPPP Durham
SmearedParticles.hh
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #ifndef RIVET_SmearedParticles_HH
00003 #define RIVET_SmearedParticles_HH
00004 
00005 #include "Rivet/Particle.hh"
00006 #include "Rivet/Projection.hh"
00007 #include "Rivet/Projections/ParticleFinder.hh"
00008 #include "Rivet/Tools/SmearingFunctions.hh"
00009 #include <functional>
00010 
00011 namespace Rivet {
00012 
00013 
00014   /// Wrapper projection for smearing {@link Jet}s with detector resolutions and efficiencies
00015   class SmearedParticles : public ParticleFinder {
00016   public:
00017 
00018     /// @name Constructors etc.
00019     //@{
00020 
00021     /// @brief Constructor with efficiency and smearing function args
00022     template <typename P2DFN>
00023     SmearedParticles(const ParticleFinder& pf,
00024                      const P2DFN& effFn,
00025                      const Cut& c=Cuts::open())
00026       : SmearedParticles(pf, effFn, PARTICLE_SMEAR_IDENTITY, c)
00027     {    }
00028 
00029 
00030     /// @brief Constructor with efficiency and smearing function args
00031     template <typename P2DFN, typename P2PFN>
00032     SmearedParticles(const ParticleFinder& pf,
00033                      const P2DFN& effFn, const P2PFN& smearFn,
00034                      const Cut& c=Cuts::open())
00035       : ParticleFinder(c),
00036         _effFn(effFn), _smearFn(smearFn)
00037     {
00038       setName("SmearedParticles");
00039       addProjection(pf, "TruthParticles");
00040     }
00041 
00042 
00043     /// Clone on the heap.
00044     DEFAULT_RIVET_PROJ_CLONE(SmearedParticles);
00045 
00046     //@}
00047 
00048 
00049     /// Compare to another SmearedParticles
00050     int compare(const Projection& p) const {
00051       const SmearedParticles& other = dynamic_cast<const SmearedParticles&>(p);
00052       if (get_address(_effFn) == 0) return UNDEFINED;
00053       if (get_address(_smearFn) == 0) return UNDEFINED;
00054       MSG_TRACE("Eff hashes = " << get_address(_effFn) << "," << get_address(other._effFn) << "; " <<
00055                 "smear hashes = " << get_address(_smearFn) << "," << get_address(other._smearFn));
00056       return mkPCmp(other, "TruthParticles") ||
00057         cmp(get_address(_effFn), get_address(other._effFn)) ||
00058         cmp(get_address(_smearFn), get_address(other._smearFn));
00059     }
00060 
00061 
00062     /// Perform the particle finding & smearing calculation
00063     void project(const Event& e) {
00064       // Copying and filtering
00065       const Particles& truthparticles = apply<ParticleFinder>(e, "TruthParticles").particlesByPt();
00066       _theParticles.clear(); _theParticles.reserve(truthparticles.size());
00067       for (const Particle& p : truthparticles) {
00068         const double peff = _effFn ? _effFn(p) : 1;
00069         MSG_DEBUG("Efficiency of particle with pid=" << p.pid()
00070                   << ", mom=" << p.mom()/GeV << " GeV, "
00071                   << "pT=" << p.pT()/GeV << ", eta=" << p.eta()
00072                   << " : " << 100*peff << "%");
00073         if (peff <= 0) continue; //< no need to roll expensive dice (and we deal with -ve probabilities, just in case)
00074         if (peff < 1 && rand01() > peff) continue; //< roll dice (and deal with >1 probabilities, just in case)
00075         _theParticles.push_back(_smearFn ? _smearFn(p) : p); //< smearing
00076       }
00077     }
00078 
00079 
00080     /// Reset the projection. Smearing functions will be unchanged.
00081     void reset() { _theParticles.clear(); }
00082 
00083 
00084   private:
00085 
00086     /// Stored efficiency function
00087     std::function<double(const Particle&)> _effFn;
00088 
00089     /// Stored smearing function
00090     std::function<Particle(const Particle&)> _smearFn;
00091 
00092   };
00093 
00094 
00095 }
00096 
00097 #endif