WFinder.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Projections/WFinder.hh"
00003 #include "Rivet/Projections/InvMassFinalState.hh"
00004 #include "Rivet/Projections/MissingMomentum.hh"
00005 #include "Rivet/Projections/MergedFinalState.hh"
00006 #include "Rivet/Projections/ClusteredPhotons.hh"
00007 #include "Rivet/Projections/VetoedFinalState.hh"
00008 #include "Rivet/Tools/ParticleIdUtils.hh"
00009 #include "Rivet/Tools/Logging.hh"
00010 #include "Rivet/Cmp.hh"
00011 
00012 namespace Rivet {
00013 
00014 
00015   WFinder::WFinder(const ChargedFinalState& fs_l,
00016                    PdgId pid,
00017                    double m2_min, double m2_max,
00018                    double missingET,
00019                    double dRmax) {
00020     _init(fs_l, pid, m2_min, m2_max, missingET, dRmax);
00021   }
00022 
00023 
00024   WFinder::WFinder(double etaMin, double etaMax,
00025                    double pTmin,
00026                    PdgId pid,
00027                    double m2_min, double m2_max,
00028                    double missingET,
00029                    double dRmax) {
00030     vector<pair<double, double> > etaRanges;
00031     etaRanges += std::make_pair(etaMin, etaMax);
00032     _init(etaRanges, pTmin, pid, m2_min, m2_max, missingET, dRmax);
00033   }
00034 
00035 
00036   WFinder::WFinder(const std::vector<std::pair<double, double> >& etaRanges,
00037                    double pTmin,
00038                    PdgId pid,
00039                    double m2_min, double m2_max,
00040                    double missingET,
00041                    double dRmax) {
00042     _init(etaRanges, pTmin, pid, m2_min, m2_max, missingET, dRmax);
00043   }
00044 
00045 
00046   void WFinder::_init(const std::vector<std::pair<double, double> >& etaRanges,
00047                       double pTmin,
00048                       PdgId pid,
00049                       double m2_min, double m2_max,
00050                       double missingET,
00051                       double dRmax) {
00052     ChargedFinalState fs_l(etaRanges, pTmin);
00053     _init(fs_l, pid, m2_min, m2_max, missingET, dRmax);
00054   }
00055 
00056 
00057   void WFinder::_init(const ChargedFinalState& fs_l,
00058                       PdgId pid,
00059                       double m2_min, double m2_max,
00060                       double missingET,
00061                       double dRmax)
00062   {
00063     setName("WFinder");
00064 
00065     // Check that the arguments are legal
00066     assert(abs(pid) == ELECTRON || abs(pid) == MUON);
00067     PdgId nu_pid = abs(pid) + 1;
00068     assert(abs(nu_pid) == NU_E || abs(nu_pid) == NU_MU);
00069 
00070     // Don't make pT or eta cuts on the neutrino
00071     IdentifiedFinalState fs_nu;
00072     fs_nu.acceptNeutrinos();
00073 
00074     // Make a merged final state projection for charged and neutral leptons
00075     MergedFinalState mergedFS(fs_l, fs_nu);
00076 
00077     // Mass range
00078     _m2_min = m2_min;
00079     _m2_max = m2_max;
00080 
00081     // Set ETmiss
00082     _etMiss = missingET;
00083 
00084     // Make and register an invariant mass final state for the W decay leptons
00085     vector<pair<PdgId, PdgId> > l_nu_ids;
00086     l_nu_ids += make_pair(abs(pid), -abs(nu_pid));
00087     l_nu_ids += make_pair(-abs(pid), abs(nu_pid));
00088     InvMassFinalState imfs(mergedFS, l_nu_ids, m2_min, m2_max);
00089     addProjection(imfs, "IMFS");
00090 
00091     // A projection for clustering photons on to the charged lepton
00092     ClusteredPhotons cphotons(FinalState(), imfs, dRmax);
00093     addProjection(cphotons, "CPhotons");
00094 
00095     // Projection for all signal constituents
00096     MergedFinalState signalFS(imfs, cphotons);
00097     addProjection(signalFS, "SignalParticles");
00098 
00099     // Add MissingMomentum proj to calc MET
00100     MissingMomentum vismom(signalFS);
00101     addProjection(vismom, "MissingET");
00102 
00103     // FS for non-signal bits of the event
00104     VetoedFinalState remainingFS;
00105     remainingFS.addVetoOnThisFinalState(signalFS);
00106     addProjection(remainingFS, "RFS");
00107   }
00108 
00109 
00110   /////////////////////////////////////////////////////
00111 
00112 
00113   const FinalState& WFinder::remainingFinalState() const {
00114     return getProjection<FinalState>("RFS");
00115   }
00116 
00117 
00118   const FinalState& WFinder::constituentsFinalState() const {
00119     return getProjection<FinalState>("SignalParticles");
00120   }
00121 
00122 
00123   const FinalState& WFinder::constituentLeptonsFinalState() const {
00124     return getProjection<FinalState>("IMFS");
00125   }
00126 
00127 
00128   const FinalState& WFinder::clusteredPhotonsFinalState() const
00129   {
00130     return getProjection<FinalState>("CPhotons");
00131   }
00132 
00133 
00134   int WFinder::compare(const Projection& p) const {
00135     PCmp cmp = mkNamedPCmp(p, "IMFS");
00136     if (cmp != EQUIVALENT) return cmp;
00137 
00138     cmp = mkNamedPCmp(p, "CPhotons");
00139     if (cmp != EQUIVALENT) return cmp;
00140 
00141     return EQUIVALENT;
00142   }
00143 
00144 
00145   void WFinder::clear() {
00146     _theParticles.clear();
00147   }
00148 
00149 
00150   void WFinder::project(const Event& e) {
00151     clear();
00152     const InvMassFinalState& imfs = applyProjection<InvMassFinalState>(e, "IMFS");
00153 
00154     Particle p1,p2;
00155     if(imfs.particles().size() == 2) {
00156       p1 = imfs.particles()[0];
00157       p2 = imfs.particles()[1];
00158     }
00159     else {
00160       // no candiate, return
00161       if(imfs.particles().empty()) {
00162     getLog() << Log::DEBUG << "No W+- candidates found" << " "
00163          << imfs.particles().size() << " " << endl;
00164     return;
00165       }
00166       // more than one, pick the one nearer the W mass
00167       double deltaM = 1e30;
00168       for(unsigned int ix=0;ix<imfs.particlePairs().size();++ix) {
00169     FourMomentum pW = imfs.particlePairs()[ix].first .momentum()+
00170       imfs.particlePairs()[ix].second.momentum();
00171     double mW = pW.mass();
00172     if(abs(mW-80.403)<deltaM) {
00173       deltaM = abs(mW-80.4);
00174       p1 = imfs.particlePairs()[ix].first ;
00175       p2 = imfs.particlePairs()[ix].second;
00176     }
00177       }
00178     }
00179 
00180     FourMomentum pW = p1.momentum() + p2.momentum();
00181     const int w3charge = PID::threeCharge(p1) + PID::threeCharge(p2);
00182     assert(abs(w3charge) == 3);
00183     const int wcharge = w3charge/3;
00184 
00185     stringstream msg;
00186     string wsign = (wcharge == 1) ? "+" : "-";
00187     string wstr = "W" + wsign;
00188     msg << wstr << " reconstructed from: " << endl
00189         << "   " << p1.momentum() << " " << p1.pdgId() << endl
00190         << " + " << p2.momentum() << " " << p2.pdgId() << endl;
00191 
00192     // Add in clustered photons
00193     const FinalState& photons = applyProjection<FinalState>(e, "CPhotons");
00194     foreach (const Particle& photon, photons.particles()) {
00195       msg << " + " << photon.momentum() << " " << photon.pdgId() << endl;
00196       pW += photon.momentum();
00197     }
00198     msg << " = " << pW;
00199 
00200     // Check missing ET
00201     const MissingMomentum& vismom = applyProjection<MissingMomentum>(e, "MissingET");
00202     /// @todo Restrict missing momentum eta range? Use vectorET()?
00203     if (vismom.scalarET() < _etMiss) {
00204       getLog() << Log::DEBUG << "Not enough missing ET: " << vismom.scalarET()/GeV
00205                << " GeV vs. " << _etMiss/GeV << " GeV" << endl;
00206       return;
00207     }
00208 
00209     // Check mass range again
00210     if (!inRange(pW.mass()/GeV, _m2_min, _m2_max)) return;
00211     getLog() << Log::DEBUG << msg.str() << endl;
00212 
00213     // Make W Particle and insert into particles list
00214     const PdgId wpid = (wcharge == 1) ? WPLUSBOSON : WMINUSBOSON;
00215     _theParticles.push_back(Particle(wpid, pW));
00216   }
00217 
00218 
00219 }