rivet is hosted by Hepforge, IPPP Durham
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/DressedLeptons.hh"
00007 #include "Rivet/Projections/VetoedFinalState.hh"
00008 
00009 namespace Rivet {
00010 
00011 
00012   /// @todo Not necessary in C++11, where constructors can be chained
00013   void WFinder::_init(const FinalState& inputfs,
00014                       const vector<pair<double, double> >& etaRanges,
00015                       double pTmin,
00016                       PdgId pid,
00017                       double minmass, double maxmass,
00018                       double missingET,
00019                       double dRmax,
00020                       ClusterPhotons clusterPhotons,
00021                       PhotonTracking trackPhotons,
00022                       MassWindow masstype,
00023                       double masstarget) {
00024     setName("WFinder");
00025 
00026     _minmass = minmass;
00027     _maxmass = maxmass;
00028     _masstarget = masstarget;
00029     _pid = pid;
00030     _trackPhotons = trackPhotons;
00031     _useTransverseMass = (masstype == MASS);
00032 
00033     // Check that the arguments are legal
00034     assert(abs(_pid) == PID::ELECTRON || abs(_pid) == PID::MUON);
00035     _nu_pid = abs(_pid) + 1;
00036     assert(abs(_nu_pid) == PID::NU_E || abs(_nu_pid) == PID::NU_MU);
00037 
00038     // Don't make pT or eta cuts on the neutrino
00039     IdentifiedFinalState neutrinos(inputfs);
00040     neutrinos.acceptNeutrinos();
00041     addProjection(neutrinos, "Neutrinos");
00042 
00043     // Lepton clusters
00044     IdentifiedFinalState bareleptons(inputfs);
00045     bareleptons.acceptIdPair(pid);
00046     const bool doClustering = (clusterPhotons != NOCLUSTER);
00047     const bool useDecayPhotons = (clusterPhotons == CLUSTERALL);
00048     DressedLeptons leptons(inputfs, bareleptons, dRmax, doClustering, etaRanges, pTmin, useDecayPhotons);
00049     addProjection(leptons, "DressedLeptons");
00050 
00051     // Add MissingMomentum proj to calc MET
00052     MissingMomentum vismom(inputfs);
00053     addProjection(vismom, "MissingET");
00054     // Set ETmiss
00055     _etMiss = missingET;
00056 
00057     VetoedFinalState remainingFS;
00058     remainingFS.addVetoOnThisFinalState(*this);
00059     addProjection(remainingFS, "RFS");
00060   }
00061 
00062 
00063   /////////////////////////////////////////////////////
00064 
00065 
00066   const FinalState& WFinder::remainingFinalState() const {
00067     return getProjection<FinalState>("RFS");
00068   }
00069 
00070 
00071   int WFinder::compare(const Projection& p) const {
00072     PCmp LCcmp = mkNamedPCmp(p, "DressedLeptons");
00073     if (LCcmp != EQUIVALENT) return LCcmp;
00074 
00075     const WFinder& other = dynamic_cast<const WFinder&>(p);
00076     return (cmp(_minmass, other._minmass) || cmp(_maxmass, other._maxmass) ||
00077             cmp(_useTransverseMass, other._useTransverseMass) ||
00078             cmp(_etMiss, other._etMiss) ||
00079             cmp(_pid, other._pid) || cmp(_trackPhotons, other._trackPhotons));
00080   }
00081 
00082 
00083   void WFinder::project(const Event& e) {
00084     clear();
00085 
00086     const DressedLeptons& leptons = applyProjection<DressedLeptons>(e, "DressedLeptons");
00087     const FinalState& neutrinos = applyProjection<FinalState>(e, "Neutrinos");
00088 
00089     // Make and register an invariant mass final state for the W decay leptons
00090     vector<pair<PdgId, PdgId> > l_nu_ids;
00091     l_nu_ids += make_pair(abs(_pid), -abs(_nu_pid));
00092     l_nu_ids += make_pair(-abs(_pid), abs(_nu_pid));
00093     InvMassFinalState imfs(l_nu_ids, _minmass, _maxmass, _masstarget);
00094     imfs.useTransverseMass(_useTransverseMass);
00095     Particles tmp;
00096     tmp.insert(tmp.end(), leptons.clusteredLeptons().begin(), leptons.clusteredLeptons().end());
00097     tmp.insert(tmp.end(), neutrinos.particles().begin(), neutrinos.particles().end());
00098     imfs.calc(tmp);
00099 
00100     if (imfs.particlePairs().size() < 1) return;
00101 
00102     ParticlePair Wconstituents(imfs.particlePairs()[0]);
00103     Particle p1(Wconstituents.first), p2(Wconstituents.second);
00104 
00105     if (PID::threeCharge(p1) == 0) {
00106       _constituentLeptons += p2;
00107       _constituentNeutrinos += p1;
00108     } else {
00109       _constituentLeptons += p1;
00110       _constituentNeutrinos += p2;
00111     }
00112 
00113     FourMomentum pW = p1.momentum() + p2.momentum();
00114     const int w3charge = PID::threeCharge(p1) + PID::threeCharge(p2);
00115     assert(abs(w3charge) == 3);
00116     const int wcharge = w3charge/3;
00117 
00118     stringstream msg;
00119     string wsign = (wcharge == 1) ? "+" : "-";
00120     string wstr = "W" + wsign;
00121     msg << wstr << " reconstructed from: " << "\n"
00122         << "   " << p1.momentum() << " " << p1.pdgId() << "\n"
00123         << " + " << p2.momentum() << " " << p2.pdgId();
00124     MSG_DEBUG(msg.str());
00125 
00126     // Check missing ET
00127     const MissingMomentum& vismom = applyProjection<MissingMomentum>(e, "MissingET");
00128     /// @todo Restrict missing momentum eta range? Use vectorET()?
00129     if (vismom.scalarEt() < _etMiss) {
00130       MSG_DEBUG("Not enough missing ET: " << vismom.scalarEt()/GeV
00131                 << " GeV vs. " << _etMiss/GeV << " GeV");
00132       return;
00133     }
00134 
00135     // Make W Particle and insert into particles list
00136     const PdgId wpid = (wcharge == 1) ? PID::WPLUSBOSON : PID::WMINUSBOSON;
00137     _bosons.push_back(Particle(wpid, pW));
00138 
00139     // Find the DressedLeptons and neutrinos which survived the IMFS cut such that we can
00140     // extract their original particles
00141     foreach (const Particle& p, _constituentNeutrinos) {
00142       _theParticles.push_back(p);
00143     }
00144     foreach (const Particle& p, _constituentLeptons) {
00145       foreach (const ClusteredLepton& l, leptons.clusteredLeptons()) {
00146         if (p.pdgId() == l.pdgId() && p.momentum() == l.momentum()) {
00147           _theParticles.push_back(l.constituentLepton());
00148           if (_trackPhotons) {
00149             _theParticles.insert(_theParticles.end(), l.constituentPhotons().begin(), l.constituentPhotons().end());
00150           }
00151         }
00152       }
00153     }
00154   }
00155 
00156 
00157 }