CDF_2008_NOTE_9351.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/RivetAIDA.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 Z/gamma->e+e-
00016    * and Z/gamma->mu+mu- events. The reconstructed Z defines the
00017    * phi orientation. A Z mass window cut is applied.
00018    *
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    *
00029    */
00030   class CDF_2008_NOTE_9351 : public Analysis {
00031   public:
00032 
00033     /// Constructor
00034     CDF_2008_NOTE_9351() : Analysis("CDF_2008_NOTE_9351")
00035     {
00036       setBeams(PROTON, ANTIPROTON);
00037     }
00038 
00039 
00040     /// @name Analysis methods
00041     //@{
00042 
00043     void init() {
00044       // Set up projections
00045       const ChargedFinalState cfs(-1.0, 1.0, 0.5*GeV);
00046       const ChargedFinalState clfs(-1.0, 1.0, 20*GeV);
00047       addProjection(cfs, "FS");
00048       addProjection(ChargedLeptons(clfs), "CL");
00049    
00050       // Book histograms
00051       _hist_tnchg      = bookProfile1D( 1, 1, 1);
00052       _hist_pnchg      = bookProfile1D( 2, 1, 1);
00053       _hist_pmaxnchg   = bookProfile1D( 3, 1, 1);
00054       _hist_pminnchg   = bookProfile1D( 4, 1, 1);
00055       _hist_pdifnchg   = bookProfile1D( 5, 1, 1);
00056       _hist_anchg      = bookProfile1D( 6, 1, 1);
00057    
00058       _hist_tcptsum    = bookProfile1D( 7, 1, 1);
00059       _hist_pcptsum    = bookProfile1D( 8, 1, 1);
00060       _hist_pmaxcptsum = bookProfile1D( 9, 1, 1);
00061       _hist_pmincptsum = bookProfile1D(10, 1, 1);
00062       _hist_pdifcptsum = bookProfile1D(11, 1, 1);
00063       _hist_acptsum    = bookProfile1D(12, 1, 1);
00064    
00065       _hist_tcptave    = bookProfile1D(13, 1, 1);
00066       _hist_pcptave    = bookProfile1D(14, 1, 1);
00067       _hist_acptave    = bookProfile1D(15, 1, 1);
00068    
00069       _hist_tcptmax    = bookProfile1D(16, 1, 1);
00070       _hist_pcptmax    = bookProfile1D(17, 1, 1);
00071       _hist_acptmax    = bookProfile1D(18, 1, 1);
00072    
00073       _hist_zptvsnchg  = bookProfile1D(19, 1, 1);
00074       _hist_cptavevsnchg = bookProfile1D(20, 1, 1);
00075       _hist_cptavevsnchgsmallzpt = bookProfile1D(21, 1, 1);
00076     }
00077  
00078  
00079     /// Do the analysis
00080     void analyze(const Event& e) {
00081    
00082       const FinalState& fs = applyProjection<FinalState>(e, "FS");
00083       const size_t numParticles = fs.particles().size();
00084    
00085       // Even if we only generate hadronic events, we still need a cut on numCharged >= 2.
00086       if (numParticles < 1) {
00087         getLog() << Log::DEBUG << "Failed multiplicity cut" << endl;
00088         vetoEvent;
00089       }
00090    
00091       // Get the event weight
00092       const double weight = e.weight();
00093    
00094       // Get the leptons
00095       const ParticleVector& leptons = applyProjection<ChargedLeptons>(e, "CL").chargedLeptons();
00096    
00097       // We want exactly two leptons of the same flavour.
00098       getLog() << Log::DEBUG << "lepton multiplicity = " << leptons.size() << endl;
00099       if (leptons.size() != 2 || leptons[0].pdgId() != -leptons[1].pdgId() ) vetoEvent;
00100    
00101       // Lepton pT > 20 GeV
00102       if (leptons[0].momentum().pT()/GeV <= 20 || leptons[1].momentum().pT()/GeV <= 20) vetoEvent;
00103 
00104       // Lepton pair should have an invariant mass between 70 and 110 and |eta| < 6
00105       const FourMomentum dilepton = leptons[0].momentum() + leptons[1].momentum();
00106       if (!inRange(dilepton.mass()/GeV, 70., 110.) || fabs(dilepton.eta()) >= 6) vetoEvent;
00107       getLog() << Log::DEBUG << "Dilepton mass = " << mass(dilepton)/GeV << " GeV" << endl;
00108       getLog() << Log::DEBUG << "Dilepton pT   = " << pT(dilepton)/GeV << " GeV" << endl;
00109    
00110       // Calculate the observables
00111       size_t   numToward(0),     numTrans1(0),     numTrans2(0),     numAway(0);
00112       double ptSumToward(0.0), ptSumTrans1(0.0), ptSumTrans2(0.0), ptSumAway(0.0);
00113       double ptMaxToward(0.0), ptMaxTrans1(0.0), ptMaxTrans2(0.0), ptMaxAway(0.0);
00114       const double phiZ = azimuthalAngle(dilepton);
00115       const double pTZ  = pT(dilepton);
00116       /// @todo Replace with foreach
00117       for (ParticleVector::const_iterator p = fs.particles().begin(); p != fs.particles().end(); ++p) {
00118         // Don't use the leptons
00119         /// @todo Replace with PID::isLepton
00120         if (abs(p->pdgId()) < 20) continue;
00121      
00122         const double dPhi = deltaPhi(p->momentum().phi(), phiZ);
00123         const double pT = p->momentum().pT();
00124         double rotatedphi = p->momentum().phi() - phiZ;
00125         while (rotatedphi < 0) rotatedphi += 2*PI;
00126      
00127         if (dPhi < PI/3.0) {
00128           ptSumToward += pT;
00129           ++numToward;
00130           if (pT > ptMaxToward)
00131             ptMaxToward = pT;
00132         } else if (dPhi < 2*PI/3.0) {
00133           if (rotatedphi <= PI) {
00134             ptSumTrans1 += pT;
00135             ++numTrans1;
00136             if (pT > ptMaxTrans1)
00137               ptMaxTrans1 = pT;
00138           }
00139           else {
00140             ptSumTrans2 += pT;
00141             ++numTrans2;
00142             if (pT > ptMaxTrans2)
00143               ptMaxTrans2 = pT;
00144           }
00145         } else {
00146           ptSumAway += pT;
00147           ++numAway;
00148           if (pT > ptMaxAway)
00149             ptMaxAway = pT;
00150         }
00151         // We need to subtract the two leptons from the number of particles to get the correct multiplicity
00152         _hist_cptavevsnchg->fill(numParticles-2, pT, weight);
00153         if (pTZ < 10)
00154           _hist_cptavevsnchgsmallzpt->fill(numParticles-2, pT, weight);
00155       }
00156    
00157       // Fill the histograms
00158       _hist_tnchg->fill(pTZ, numToward/(4*PI/3), weight);
00159       _hist_pnchg->fill(pTZ, (numTrans1+numTrans2)/(4*PI/3), weight);
00160       _hist_pmaxnchg->fill(pTZ, (numTrans1>numTrans2 ? numTrans1 : numTrans2)/(2*PI/3), weight);
00161       _hist_pminnchg->fill(pTZ, (numTrans1<numTrans2 ? numTrans1 : numTrans2)/(2*PI/3), weight);
00162       _hist_pdifnchg->fill(pTZ, abs(numTrans1-numTrans2)/(2*PI/3), weight);
00163       _hist_anchg->fill(pTZ, numAway/(4*PI/3), weight);
00164    
00165       _hist_tcptsum->fill(pTZ, ptSumToward/(4*PI/3), weight);
00166       _hist_pcptsum->fill(pTZ, (ptSumTrans1+ptSumTrans2)/(4*PI/3), weight);
00167       _hist_pmaxcptsum->fill(pTZ, (ptSumTrans1>ptSumTrans2 ? ptSumTrans1 : ptSumTrans2)/(2*PI/3), weight);
00168       _hist_pmincptsum->fill(pTZ, (ptSumTrans1<ptSumTrans2 ? ptSumTrans1 : ptSumTrans2)/(2*PI/3), weight);
00169       _hist_pdifcptsum->fill(pTZ, fabs(ptSumTrans1-ptSumTrans2)/(2*PI/3), weight);
00170       _hist_acptsum->fill(pTZ, ptSumAway/(4*PI/3), weight);
00171    
00172       if (numToward > 0) {
00173         _hist_tcptave->fill(pTZ, ptSumToward/numToward, weight);
00174         _hist_tcptmax->fill(pTZ, ptMaxToward, weight);
00175       }
00176       if ((numTrans1+numTrans2) > 0) {
00177         _hist_pcptave->fill(pTZ, (ptSumTrans1+ptSumTrans2)/(numTrans1+numTrans2), weight);
00178         _hist_pcptmax->fill(pTZ, (ptMaxTrans1 > ptMaxTrans2 ? ptMaxTrans1 : ptMaxTrans2), weight);
00179       }
00180       if (numAway > 0) {
00181         _hist_acptave->fill(pTZ, ptSumAway/numAway, weight);
00182         _hist_acptmax->fill(pTZ, ptMaxAway, weight);
00183       }
00184    
00185       // We need to subtract the two leptons from the number of particles to get the correct multiplicity
00186       _hist_zptvsnchg->fill(numParticles-2, pTZ, weight);
00187     }
00188  
00189  
00190     void finalize() {
00191       //
00192     }
00193  
00194     //@}
00195 
00196   private:
00197 
00198     AIDA::IProfile1D *_hist_tnchg;
00199     AIDA::IProfile1D *_hist_pnchg;
00200     AIDA::IProfile1D *_hist_pmaxnchg;
00201     AIDA::IProfile1D *_hist_pminnchg;
00202     AIDA::IProfile1D *_hist_pdifnchg;
00203     AIDA::IProfile1D *_hist_anchg;
00204     AIDA::IProfile1D *_hist_tcptsum;
00205     AIDA::IProfile1D *_hist_pcptsum;
00206     AIDA::IProfile1D *_hist_pmaxcptsum;
00207     AIDA::IProfile1D *_hist_pmincptsum;
00208     AIDA::IProfile1D *_hist_pdifcptsum;
00209     AIDA::IProfile1D *_hist_acptsum;
00210     AIDA::IProfile1D *_hist_tcptave;
00211     AIDA::IProfile1D *_hist_pcptave;
00212     AIDA::IProfile1D *_hist_acptave;
00213     AIDA::IProfile1D *_hist_tcptmax;
00214     AIDA::IProfile1D *_hist_pcptmax;
00215     AIDA::IProfile1D *_hist_acptmax;
00216     AIDA::IProfile1D *_hist_zptvsnchg;
00217     AIDA::IProfile1D *_hist_cptavevsnchg;
00218     AIDA::IProfile1D *_hist_cptavevsnchgsmallzpt;
00219 
00220   };
00221 
00222  
00223   // This global object acts as a hook for the plugin system
00224   AnalysisBuilder<CDF_2008_NOTE_9351> plugin_CDF_2008_NOTE_9351;
00225 
00226 }