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