rivet is hosted by Hepforge, IPPP Durham
D0_2001_S4674421.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/Projections/LeadingParticlesFinalState.hh"
00004 #include "Rivet/Projections/VetoedFinalState.hh"
00005 
00006 namespace Rivet {
00007 
00008 
00009   /// @brief D0 Run I differential W/Z boson cross-section analysis
00010   /// @author Lars Sonnenschein
00011   /// @author Andy Buckley
00012   class D0_2001_S4674421 : public Analysis {
00013   public:
00014 
00015     /// @name Constructors etc.
00016     //@{
00017 
00018     /// Constructor.
00019     D0_2001_S4674421()
00020       : Analysis("D0_2001_S4674421")
00021     {    }
00022 
00023 
00024     /// @name Analysis methods
00025     //@{
00026 
00027     void init() {
00028       // Final state projection
00029       FinalState fs(-5.0, 5.0); // corrected for detector acceptance
00030       addProjection(fs, "FS");
00031 
00032       // Z -> e- e+
00033       LeadingParticlesFinalState eeFS(FinalState(-5.0, 5.0, 0.)); //20.);
00034       eeFS.addParticleIdPair(PID::ELECTRON);
00035       addProjection(eeFS, "eeFS");
00036 
00037       // W- -> e- nu_e~
00038       LeadingParticlesFinalState enuFS(FinalState(-5.0, 5.0, 0.)); //25.);
00039       enuFS.addParticleId(PID::ELECTRON).addParticleId(PID::NU_EBAR);
00040       addProjection(enuFS, "enuFS");
00041 
00042       // W+ -> e+ nu_e
00043       LeadingParticlesFinalState enubFS(FinalState(-5.0, 5.0, 0.)); //25.);
00044       enubFS.addParticleId(PID::POSITRON).addParticleId(PID::NU_E);
00045       addProjection(enubFS, "enubFS");
00046 
00047       // Remove neutrinos for isolation of final state particles
00048       VetoedFinalState vfs(fs);
00049       vfs.vetoNeutrinos();
00050       addProjection(vfs, "VFS");
00051 
00052       // Counters
00053       _eventsFilledW = 0.0;
00054       _eventsFilledZ = 0.0;
00055 
00056       // Histograms
00057       _h_dsigdpt_w = bookHisto1D(1, 1, 1);
00058       _h_dsigdpt_z = bookHisto1D(1, 1, 2);
00059       _h_dsigdpt_scaled_z = bookScatter2D(2, 1, 1);
00060     }
00061 
00062 
00063 
00064     void analyze(const Event& event) {
00065       const double weight = event.weight();
00066 
00067       const LeadingParticlesFinalState& eeFS = applyProjection<LeadingParticlesFinalState>(event, "eeFS");
00068       // Z boson analysis
00069       if (eeFS.particles().size() >= 2) {
00070         // If there is a Z candidate:
00071         // Fill Z pT distributions
00072         double deltaM2=1e30,mass2(0.);
00073         double pT=-1.;
00074         const Particles& Zdaughters = eeFS.particles();
00075         for (size_t ix = 0; ix < Zdaughters.size(); ++ix) {
00076           for (size_t iy = ix+1; iy < Zdaughters.size(); ++iy) {
00077             if (Zdaughters[ix].pid()!=-Zdaughters[iy].pid()) continue;
00078             const FourMomentum pmom = Zdaughters[ix].momentum() + Zdaughters[iy].momentum();
00079             double mz2 = pmom.mass2();
00080             double dm2 = fabs(mz2 - sqr(91.118*GeV));
00081             if (dm2 < deltaM2) {
00082               pT = pmom.pT();
00083               deltaM2 = dm2;
00084               mass2 = mz2;
00085             }
00086           }
00087         }
00088         if (pT > 0. && mass2 > 0. && inRange(sqrt(mass2)/GeV, 75.0, 105.0)) {
00089           _eventsFilledZ += weight;
00090           MSG_DEBUG("Z pmom.pT() = " << pT/GeV << " GeV");
00091           _h_dsigdpt_z->fill(pT/GeV, weight);
00092           // return if found a Z
00093           return;
00094         }
00095       }
00096       // There is no Z -> ee candidate... so this might be a W event
00097       const LeadingParticlesFinalState& enuFS = applyProjection<LeadingParticlesFinalState>(event, "enuFS");
00098       const LeadingParticlesFinalState& enubFS = applyProjection<LeadingParticlesFinalState>(event, "enubFS");
00099 
00100       double deltaM2=1e30;
00101       double pT=-1.;
00102       for (size_t iw = 0; iw < 2; ++iw) {
00103         Particles Wdaughters;
00104         Wdaughters = (iw == 0) ? enuFS.particles() : enubFS.particles();
00105         for (size_t ix = 0; ix < Wdaughters.size(); ++ix) {
00106           for (size_t iy = ix+1; iy < Wdaughters.size(); ++iy) {
00107             if (Wdaughters[ix].pid() == Wdaughters[iy].pid())  continue;
00108             const FourMomentum pmom = Wdaughters[0].momentum() + Wdaughters[1].momentum();
00109             double dm2 = abs(pmom.mass2() - sqr(80.4*GeV));
00110             if (dm2 < deltaM2) {
00111               pT = pmom.pT();
00112               deltaM2 = dm2;
00113             }
00114           }
00115         }
00116       }
00117       if (pT > 0.) {
00118         _eventsFilledW += weight;
00119         _h_dsigdpt_w->fill(pT/GeV, weight);
00120       }
00121     }
00122 
00123 
00124 
00125     void finalize() {
00126       // Get cross-section per event (i.e. per unit weight) from generator
00127       const double xSecPerEvent = crossSectionPerEvent()/picobarn;
00128 
00129       // Correct W pT distribution to W cross-section
00130       const double xSecW = xSecPerEvent * _eventsFilledW;
00131 
00132       // Correct Z pT distribution to Z cross-section
00133       const double xSecZ = xSecPerEvent * _eventsFilledZ;
00134 
00135       // Get W and Z pT integrals
00136       const double wpt_integral = _h_dsigdpt_w->integral();
00137       const double zpt_integral = _h_dsigdpt_z->integral();
00138 
00139       // Divide and scale ratio histos
00140       if (xSecW == 0 || wpt_integral == 0 || xSecZ == 0 || zpt_integral == 0) {
00141         MSG_WARNING("Not filling ratio plot because input histos are empty");
00142       } else {
00143         // Scale factor converts event counts to cross-sections, and inverts the
00144         // branching ratios since only one decay channel has been analysed for each boson.
00145         // Oh, and we put MW/MZ in, like they do in the paper.
00146         const double MW_MZ = 0.8820; // Ratio M_W/M_Z
00147         const double BRZEE_BRWENU = 0.033632 / 0.1073; // Ratio of branching fractions
00148         const double scalefactor = (xSecW / wpt_integral) / (xSecZ / zpt_integral) * MW_MZ * BRZEE_BRWENU;
00149         for (size_t ibin = 0; ibin < _h_dsigdpt_w->numBins(); ibin++) {
00150           const double xval = _h_dsigdpt_w->bin(ibin).xMid();
00151           const double xerr = _h_dsigdpt_w->bin(ibin).xWidth() / 2.;
00152           double yval(0), yerr(0);
00153           if (_h_dsigdpt_w->bin(ibin).sumW() != 0 && _h_dsigdpt_z->bin(ibin).sumW() != 0) {
00154             yval = scalefactor * _h_dsigdpt_w->bin(ibin).sumW() / _h_dsigdpt_z->bin(ibin).sumW();
00155             yerr = yval * sqrt( sqr(_h_dsigdpt_w->bin(ibin).relErr()) + sqr(_h_dsigdpt_z->bin(ibin).areaErr()) );
00156           }
00157           _h_dsigdpt_scaled_z->addPoint(xval, yval, xerr, yerr);
00158         }
00159       }
00160 
00161       // Normalize non-ratio histos
00162       normalize(_h_dsigdpt_w, xSecW);
00163       normalize(_h_dsigdpt_z, xSecZ);
00164     }
00165 
00166 
00167     //@}
00168 
00169   private:
00170 
00171     /// @name Event counters for cross section normalizations
00172     //@{
00173     double _eventsFilledW;
00174     double _eventsFilledZ;
00175     //@}
00176 
00177     //@{
00178     /// Histograms
00179     Histo1DPtr  _h_dsigdpt_w;
00180     Histo1DPtr  _h_dsigdpt_z;
00181     Scatter2DPtr _h_dsigdpt_scaled_z;
00182     //@}
00183 
00184   };
00185 
00186 
00187 
00188   // The hook for the plugin system
00189   DECLARE_RIVET_PLUGIN(D0_2001_S4674421);
00190 
00191 }