rivet is hosted by Hepforge, IPPP Durham
CDF_2010_S8591881_DY.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/RivetYODA.hh"
00004 #include "Rivet/Tools/ParticleIdUtils.hh"
00005 #include "Rivet/Tools/Logging.hh"
00006 #include "Rivet/Projections/ChargedFinalState.hh"
00007 #include "Rivet/Projections/ChargedLeptons.hh"
00008 
00009 namespace Rivet {
00010 
00011 
00012   /// @brief CDF Run II underlying event in Drell-Yan
00013   /// @author Hendrik Hoeth
00014   ///
00015   /// Measurement of the underlying event in Drell-Yan
00016   /// \f$ Z/\gamma^* \to e^+ e^- \f$ and
00017   /// \f$ Z/\gamma^* \to \mu^+ \mu^- \f$ events. The reconstructed
00018   /// Z defines the \f$ \phi \f$ orientation. A Z mass window cut is applied.
00019   ///
00020   /// @par Run conditions
00021   ///
00022   /// @arg \f$ \sqrt{s} = \f$ 1960 GeV
00023   /// @arg produce Drell-Yan events
00024   /// @arg Set particles with c*tau > 10 mm stable
00025   /// @arg Z decay mode: Z -> e+e- and Z -> mu+mu-
00026   /// @arg gamma decay mode: gamma -> e+e- and gamma -> mu+mu-
00027   /// @arg minimum invariant mass of the fermion pair coming from the Z/gamma: 70 GeV
00028   class CDF_2010_S8591881_DY : public Analysis {
00029   public:
00030 
00031     /// Constructor
00032     CDF_2010_S8591881_DY() : Analysis("CDF_2010_S8591881_DY")
00033     {
00034     }
00035 
00036 
00037     /// @name Analysis methods
00038     //@{
00039 
00040     void init() {
00041       // Set up projections
00042       const ChargedFinalState cfs(-1.0, 1.0, 0.5*GeV);
00043       const ChargedFinalState clfs(-1.0, 1.0, 20*GeV);
00044       addProjection(cfs, "FS");
00045       addProjection(ChargedLeptons(clfs), "CL");
00046 
00047       // Book histograms
00048       _hist_tnchg      = bookProfile1D( 1, 1, 1);
00049       _hist_pnchg      = bookProfile1D( 1, 1, 2);
00050       _hist_anchg      = bookProfile1D( 1, 1, 3);
00051       _hist_pmaxnchg   = bookProfile1D( 2, 1, 1);
00052       _hist_pminnchg   = bookProfile1D( 2, 1, 2);
00053       _hist_pdifnchg   = bookProfile1D( 2, 1, 3);
00054       _hist_tcptsum    = bookProfile1D( 3, 1, 1);
00055       _hist_pcptsum    = bookProfile1D( 3, 1, 2);
00056       _hist_acptsum    = bookProfile1D( 3, 1, 3);
00057       _hist_pmaxcptsum = bookProfile1D( 4, 1, 1);
00058       _hist_pmincptsum = bookProfile1D( 4, 1, 2);
00059       _hist_pdifcptsum = bookProfile1D( 4, 1, 3);
00060       _hist_tcptave    = bookProfile1D( 5, 1, 1);
00061       _hist_pcptave    = bookProfile1D( 5, 1, 2);
00062       _hist_tcptmax    = bookProfile1D( 6, 1, 1);
00063       _hist_pcptmax    = bookProfile1D( 6, 1, 2);
00064       _hist_zptvsnchg  = bookProfile1D( 7, 1, 1);
00065       _hist_cptavevsnchg = bookProfile1D( 8, 1, 1);
00066       _hist_cptavevsnchgsmallzpt = bookProfile1D( 9, 1, 1);
00067     }
00068 
00069 
00070     /// Do the analysis
00071     void analyze(const Event& e) {
00072 
00073       const FinalState& fs = applyProjection<FinalState>(e, "FS");
00074       const size_t numParticles = fs.particles().size();
00075 
00076       // Even if we only generate hadronic events, we still need a cut on numCharged >= 2.
00077       if (numParticles < 1) {
00078         MSG_DEBUG("Failed multiplicity cut");
00079         vetoEvent;
00080       }
00081 
00082       // Get the event weight
00083       const double weight = e.weight();
00084 
00085       // Get the leptons
00086       const ParticleVector& leptons = applyProjection<ChargedLeptons>(e, "CL").chargedLeptons();
00087 
00088       // We want exactly two leptons of the same flavour.
00089       MSG_DEBUG("lepton multiplicity = " << leptons.size());
00090       if (leptons.size() != 2 || leptons[0].pdgId() != -leptons[1].pdgId() ) vetoEvent;
00091 
00092       // Lepton pT > 20 GeV
00093       if (leptons[0].momentum().pT()/GeV <= 20 || leptons[1].momentum().pT()/GeV <= 20) vetoEvent;
00094 
00095       // Lepton pair should have an invariant mass between 70 and 110 and |eta| < 6
00096       const FourMomentum dilepton = leptons[0].momentum() + leptons[1].momentum();
00097       if (!inRange(dilepton.mass()/GeV, 70., 110.) || fabs(dilepton.eta()) >= 6) vetoEvent;
00098       MSG_DEBUG("Dilepton mass = " << mass(dilepton)/GeV << " GeV");
00099       MSG_DEBUG("Dilepton pT   = " << pT(dilepton)/GeV << " GeV");
00100 
00101       // Calculate the observables
00102       size_t   numToward(0),     numAway(0);
00103       long int numTrans1(0),     numTrans2(0);
00104       double ptSumToward(0.0), ptSumTrans1(0.0), ptSumTrans2(0.0), ptSumAway(0.0);
00105       double ptMaxToward(0.0), ptMaxTrans1(0.0), ptMaxTrans2(0.0), ptMaxAway(0.0);
00106       const double phiZ = azimuthalAngle(dilepton);
00107       const double pTZ  = pT(dilepton);
00108       /// @todo Replace with foreach
00109       for (ParticleVector::const_iterator p = fs.particles().begin(); p != fs.particles().end(); ++p) {
00110         // Don't use the leptons
00111         /// @todo Replace with PID::isLepton
00112         if (abs(p->pdgId()) < 20) continue;
00113 
00114         const double dPhi = deltaPhi(p->momentum().phi(), phiZ);
00115         const double pT = p->momentum().pT();
00116         double rotatedphi = p->momentum().phi() - phiZ;
00117         while (rotatedphi < 0) rotatedphi += 2*PI;
00118 
00119         if (dPhi < PI/3.0) {
00120           ptSumToward += pT;
00121           ++numToward;
00122           if (pT > ptMaxToward)
00123             ptMaxToward = pT;
00124         } else if (dPhi < 2*PI/3.0) {
00125           if (rotatedphi <= PI) {
00126             ptSumTrans1 += pT;
00127             ++numTrans1;
00128             if (pT > ptMaxTrans1)
00129               ptMaxTrans1 = pT;
00130           }
00131           else {
00132             ptSumTrans2 += pT;
00133             ++numTrans2;
00134             if (pT > ptMaxTrans2)
00135               ptMaxTrans2 = pT;
00136           }
00137         } else {
00138           ptSumAway += pT;
00139           ++numAway;
00140           if (pT > ptMaxAway)
00141             ptMaxAway = pT;
00142         }
00143         // We need to subtract the two leptons from the number of particles to get the correct multiplicity
00144         _hist_cptavevsnchg->fill(numParticles-2, pT, weight);
00145         if (pTZ < 10)
00146           _hist_cptavevsnchgsmallzpt->fill(numParticles-2, pT, weight);
00147       }
00148 
00149       // Fill the histograms
00150       _hist_tnchg->fill(pTZ, numToward/(4*PI/3), weight);
00151       _hist_pnchg->fill(pTZ, (numTrans1+numTrans2)/(4*PI/3), weight);
00152       _hist_pmaxnchg->fill(pTZ, (numTrans1>numTrans2 ? numTrans1 : numTrans2)/(2*PI/3), weight);
00153       _hist_pminnchg->fill(pTZ, (numTrans1<numTrans2 ? numTrans1 : numTrans2)/(2*PI/3), weight);
00154       _hist_pdifnchg->fill(pTZ, abs(numTrans1-numTrans2)/(2*PI/3), weight);
00155       _hist_anchg->fill(pTZ, numAway/(4*PI/3), weight);
00156 
00157       _hist_tcptsum->fill(pTZ, ptSumToward/(4*PI/3), weight);
00158       _hist_pcptsum->fill(pTZ, (ptSumTrans1+ptSumTrans2)/(4*PI/3), weight);
00159       _hist_pmaxcptsum->fill(pTZ, (ptSumTrans1>ptSumTrans2 ? ptSumTrans1 : ptSumTrans2)/(2*PI/3), weight);
00160       _hist_pmincptsum->fill(pTZ, (ptSumTrans1<ptSumTrans2 ? ptSumTrans1 : ptSumTrans2)/(2*PI/3), weight);
00161       _hist_pdifcptsum->fill(pTZ, fabs(ptSumTrans1-ptSumTrans2)/(2*PI/3), weight);
00162       _hist_acptsum->fill(pTZ, ptSumAway/(4*PI/3), weight);
00163 
00164       if (numToward > 0) {
00165         _hist_tcptave->fill(pTZ, ptSumToward/numToward, weight);
00166         _hist_tcptmax->fill(pTZ, ptMaxToward, weight);
00167       }
00168       if ((numTrans1+numTrans2) > 0) {
00169         _hist_pcptave->fill(pTZ, (ptSumTrans1+ptSumTrans2)/(numTrans1+numTrans2), weight);
00170         _hist_pcptmax->fill(pTZ, (ptMaxTrans1 > ptMaxTrans2 ? ptMaxTrans1 : ptMaxTrans2), weight);
00171       }
00172 
00173       // We need to subtract the two leptons from the number of particles to get the correct multiplicity
00174       _hist_zptvsnchg->fill(numParticles-2, pTZ, weight);
00175     }
00176 
00177 
00178     void finalize() {
00179     }
00180 
00181     //@}
00182 
00183 
00184   private:
00185 
00186     Profile1DPtr _hist_tnchg;
00187     Profile1DPtr _hist_pnchg;
00188     Profile1DPtr _hist_pmaxnchg;
00189     Profile1DPtr _hist_pminnchg;
00190     Profile1DPtr _hist_pdifnchg;
00191     Profile1DPtr _hist_anchg;
00192     Profile1DPtr _hist_tcptsum;
00193     Profile1DPtr _hist_pcptsum;
00194     Profile1DPtr _hist_pmaxcptsum;
00195     Profile1DPtr _hist_pmincptsum;
00196     Profile1DPtr _hist_pdifcptsum;
00197     Profile1DPtr _hist_acptsum;
00198     Profile1DPtr _hist_tcptave;
00199     Profile1DPtr _hist_pcptave;
00200     Profile1DPtr _hist_tcptmax;
00201     Profile1DPtr _hist_pcptmax;
00202     Profile1DPtr _hist_zptvsnchg;
00203     Profile1DPtr _hist_cptavevsnchg;
00204     Profile1DPtr _hist_cptavevsnchgsmallzpt;
00205 
00206   };
00207 
00208 
00209 
00210   // The hook for the plugin system
00211   DECLARE_RIVET_PLUGIN(CDF_2010_S8591881_DY);
00212 
00213 }