D0_2001_S4674421.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/RivetAIDA.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() : Analysis("D0_2001_S4674421") {
00022       setBeams(PROTON, ANTIPROTON);
00023       setNeedsCrossSection(true);
00024     }
00025  
00026  
00027     /// @name Analysis methods
00028     //@{
00029  
00030     void init() {
00031       // Final state projection
00032       FinalState fs(-5.0, 5.0); // corrected for detector acceptance
00033       addProjection(fs, "FS");
00034 
00035       // Z -> e- e+
00036       LeadingParticlesFinalState eeFS(FinalState(-2.5, 2.5, 0.)); //20.);
00037       eeFS.addParticleIdPair(ELECTRON);
00038       addProjection(eeFS, "eeFS");
00039    
00040       // W- -> e- nu_e~
00041       LeadingParticlesFinalState enuFS(FinalState(-2.5, 2.5, 0.)); //25.);
00042       enuFS.addParticleId(ELECTRON).addParticleId(NU_EBAR);
00043       addProjection(enuFS, "enuFS");
00044    
00045       // W+ -> e+ nu_e
00046       LeadingParticlesFinalState enubFS(FinalState(-2.5, 2.5, 0.)); //25.);
00047       enubFS.addParticleId(POSITRON).addParticleId(NU_E);
00048       addProjection(enubFS, "enubFS");
00049 
00050       // Remove neutrinos for isolation of final state particles
00051       VetoedFinalState vfs(fs);
00052       vfs.vetoNeutrinos();
00053       addProjection(vfs, "VFS");
00054 
00055       // Counters
00056       _eventsFilledW = 0.0;
00057       _eventsFilledZ = 0.0;
00058 
00059       // Histograms
00060       _h_dsigdpt_w = bookHistogram1D(1, 1, 1);
00061       _h_dsigdpt_z = bookHistogram1D(1, 1, 2);
00062       /// @todo Can't take this from ref data? 
00063       vector<double> bins(23);
00064       bins += 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 25, 30, 35, 40, 50, 60, 70, 80, 100, 120, 160, 200;
00065       _h_dsigdpt_scaled_z = bookHistogram1D("d01-x01-y03", bins);
00066     }
00067 
00068 
00069 
00070     void analyze(const Event& event) {
00071       const double weight = event.weight();
00072 
00073       const LeadingParticlesFinalState& eeFS = applyProjection<LeadingParticlesFinalState>(event, "eeFS");
00074       if (eeFS.particles().size() == 2) {
00075         // If there is a Z candidate:
00076         static size_t Zcount = 0;
00077         // Fill Z pT distributions
00078         const ParticleVector& Zdaughters = eeFS.particles();
00079         const FourMomentum pmom = Zdaughters[0].momentum() + Zdaughters[1].momentum();
00080         double mass = sqrt(pmom.invariant());
00081         if (inRange(mass/GeV, 75.0, 105.0)) {
00082           ++Zcount;
00083           _eventsFilledZ += weight;
00084           getLog() << Log::DEBUG << "Z #" << Zcount << " pmom.pT() = " << pmom.pT()/GeV << " GeV" << endl;
00085           const double MW_MZ = 0.8820; // Ratio M_W/M_Z
00086           _h_dsigdpt_z->fill(pmom.pT()/GeV, weight);
00087           _h_dsigdpt_scaled_z->fill(pmom.pT()/GeV * MW_MZ, weight);
00088         }
00089       } else {
00090         // There is no Z -> ee candidate... so this must be a W event, right?
00091         const LeadingParticlesFinalState& enuFS = applyProjection<LeadingParticlesFinalState>(event, "enuFS");
00092         const LeadingParticlesFinalState& enubFS = applyProjection<LeadingParticlesFinalState>(event, "enubFS");
00093         static size_t Wcount = 0;
00094 
00095         // Fill W pT distributions
00096         ParticleVector Wdaughters;
00097         if (enuFS.particles().size() == 2 && enubFS.empty()) {
00098           Wdaughters = enuFS.particles();
00099         } else if (enuFS.empty() && enubFS.particles().size() == 2) {
00100           Wdaughters = enubFS.particles();
00101         }
00102         if (! Wdaughters.empty()) {
00103           assert(Wdaughters.size() == 2);
00104           const FourMomentum pmom = Wdaughters[0].momentum() + Wdaughters[1].momentum();
00105           ++Wcount;
00106           _eventsFilledW += weight;
00107           _h_dsigdpt_w->fill(pmom.pT()/GeV, weight);
00108         }
00109       }
00110     }
00111 
00112 
00113 
00114     void finalize() {
00115       // Get cross-section per event (i.e. per unit weight) from generator
00116       const double xSecPerEvent = crossSectionPerEvent()/picobarn;
00117 
00118       // Correct W pT distribution to W cross-section
00119       const double xSecW = xSecPerEvent * _eventsFilledW;
00120 
00121       // Correct Z pT distribution to Z cross-section
00122       const double xSecZ = xSecPerEvent * _eventsFilledZ;
00123 
00124       // Get W and Z pT integrals
00125       const double wpt_integral = integral(_h_dsigdpt_w);
00126       const double zpt_scaled_integral = integral(_h_dsigdpt_scaled_z);
00127 
00128       // Divide and scale ratio histos
00129       AIDA::IDataPointSet* div = histogramFactory().divide(histoDir() + "/d02-x01-y01", *_h_dsigdpt_w, *_h_dsigdpt_scaled_z);
00130       div->setTitle("$[\\mathrm{d}\\sigma/\\mathrm{d}p_\\perp(W)] / [\\mathrm{d}\\sigma/\\mathrm{d}(p_\\perp(Z) \\cdot M_W/M_Z)]$");
00131       if (xSecW == 0 || wpt_integral == 0 || xSecZ == 0 || zpt_scaled_integral == 0) {
00132         getLog() << Log::WARN << "Not filling ratio plot because input histos are empty" << endl;
00133       } else {
00134         // Scale factor converts event counts to cross-sections, and inverts the
00135         // branching ratios since only one decay channel has been analysed for each boson.
00136         const double BRZEE_BRWENU = 0.033632 / 0.1073;
00137         const double scalefactor = (xSecW / wpt_integral) / (xSecZ / zpt_scaled_integral) * BRZEE_BRWENU;
00138         for (int pt = 0; pt < div->size(); ++pt) {
00139           assert(div->point(pt)->dimension() == 2);
00140           AIDA::IMeasurement* m = div->point(pt)->coordinate(1);
00141           m->setValue(m->value() * scalefactor);
00142           m->setErrorPlus(m->errorPlus() * scalefactor);
00143           m->setErrorMinus(m->errorPlus() * scalefactor);
00144         }
00145       }
00146 
00147       // Normalize non-ratio histos
00148       normalize(_h_dsigdpt_w, xSecW);
00149       normalize(_h_dsigdpt_z, xSecZ);
00150       normalize(_h_dsigdpt_scaled_z, xSecZ);
00151 
00152     }
00153 
00154 
00155     //@}
00156  
00157   private:
00158 
00159     /// @name Event counters for cross section normalizations
00160     //@{
00161     double _eventsFilledW;
00162     double _eventsFilledZ;
00163     //@}
00164 
00165     //@{
00166     /// Histograms
00167     AIDA::IHistogram1D* _h_dsigdpt_w;
00168     AIDA::IHistogram1D* _h_dsigdpt_z;
00169     AIDA::IHistogram1D* _h_dsigdpt_scaled_z;
00170     //@}
00171 
00172   };
00173 
00174 
00175 
00176   // This global object acts as a hook for the plugin system
00177   AnalysisBuilder<D0_2001_S4674421> plugin_D0_2001_S4674421;
00178 
00179 }