rivet is hosted by Hepforge, IPPP Durham
H1_1994_S2919893.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/Math/Constants.hh"
00004 #include "Rivet/Projections/FinalState.hh"
00005 #include "Rivet/Projections/DISKinematics.hh"
00006 
00007 namespace Rivet {
00008 
00009   
00010 
00011 
00012   /// @brief H1 energy flow and charged particle spectra
00013   /// @author Peter Richardson
00014   /// Based on the equivalent HZTool analysis
00015   class H1_1994_S2919893 : public Analysis {
00016   public:
00017 
00018     /// Constructor
00019     H1_1994_S2919893()
00020       : Analysis("H1_1994_S2919893")
00021     {
00022 
00023       // Initialise member variables
00024       _w77  = make_pair(0.0, 0.0);
00025       _w122 = make_pair(0.0, 0.0);
00026       _w169 = make_pair(0.0, 0.0);
00027       _w117 = make_pair(0.0, 0.0);
00028       _wEnergy = make_pair(0.0, 0.0);
00029     }
00030 
00031 
00032 
00033     /// @name Analysis methods
00034     //@{
00035 
00036     void analyze(const Event& event) {
00037       const FinalState& fs = applyProjection<FinalState>(event, "FS");
00038       const DISKinematics& dk = applyProjection<DISKinematics>(event, "Kinematics");
00039       const DISLepton& dl = applyProjection<DISLepton>(event,"Lepton");
00040 
00041       // Get the DIS kinematics
00042       double x  = dk.x();
00043       double w2 = dk.W2();
00044       double w = sqrt(w2);
00045 
00046       // Momentum of the scattered lepton
00047       FourMomentum leptonMom = dl.out().momentum();
00048       double ptel = leptonMom.pT();
00049       double enel = leptonMom.E();
00050       double thel = leptonMom.angle(dk.beamHadron().momentum())/degree;
00051 
00052       // Extract the particles other than the lepton
00053       Particles particles;
00054       particles.reserve(fs.particles().size());
00055       const GenParticle* dislepGP = dl.out().genParticle();
00056       foreach (const Particle& p, fs.particles()) {
00057         const GenParticle* loopGP = p.genParticle();
00058         if (loopGP == dislepGP) continue;
00059         particles.push_back(p);
00060       }
00061 
00062       // Cut on the forward energy
00063       double efwd = 0.0;
00064       foreach (const Particle& p, particles) {
00065         double th = p.angle(dk.beamHadron().momentum())/degree;
00066         if (th > 4.4 && th < 15.) {
00067           efwd += p.E();
00068         }
00069       }
00070 
00071       // Apply the cuts
00072       // Lepton energy and angle, w2 and forward energy
00073       MSG_DEBUG("enel/GeV = " << enel/GeV << ", thel = " << thel
00074                 << ", w2 = " << w2 << ", efwd/GeV = " << efwd/GeV);
00075       bool cut = enel/GeV > 14. && thel > 157. && thel < 172.5 && w2 >= 3000. && efwd/GeV > 0.5;
00076       if (!cut) vetoEvent;
00077 
00078       // Weight of the event
00079       const double weight = event.weight();
00080       // weights for x<1e-3 and x>1e-3
00081       if (x < 1e-3) {
00082         _wEnergy.first  += weight;
00083       } else {
00084         _wEnergy.second += weight;
00085       }
00086 
00087       // Boost to hadronic CM
00088       const LorentzTransform hcmboost = dk.boostHCM();
00089       // Loop over the particles
00090       long ncharged(0);
00091       for (size_t ip1 = 0; ip1 < particles.size(); ++ip1) {
00092         const Particle& p = particles[ip1];
00093 
00094         double th = p.angle(dk.beamHadron().momentum()) / degree;
00095         // Boost momentum to lab
00096         const FourMomentum hcmMom = hcmboost.transform(p.momentum());
00097         // Angular cut
00098         if (th <= 4.4) continue;
00099 
00100         // Energy flow histogram
00101         double et = fabs(hcmMom.Et());
00102         double eta = hcmMom.eta();
00103         if (x < 1e-3) {
00104           _histEnergyFlowLowX ->fill(eta, et*weight);
00105         } else {
00106           _histEnergyFlowHighX->fill(eta, et*weight);
00107         }
00108         if (PID::threeCharge(p.pid()) != 0) {
00109           /// @todo Use units in w comparisons... what are the units?
00110           if (w > 50. && w <= 200.) {
00111             double xf= 2 * hcmMom.z() / w;
00112             double pt2 = hcmMom.pT2();
00113             if (w > 50. && w <= 100.) {
00114               _histSpectraW77 ->fill(xf, weight);
00115             } else if (w > 100. && w <= 150.) {
00116               _histSpectraW122->fill(xf, weight);
00117             } else if (w > 150. && w <= 200.) {
00118               _histSpectraW169->fill(xf, weight);
00119             }
00120             _histSpectraW117->fill(xf, weight);
00121             /// @todo Is this profile meant to be filled with 2 weight factors?
00122             _histPT2->fill(xf, pt2*weight/GeV2, weight);
00123             ++ncharged;
00124           }
00125         }
00126 
00127 
00128         // Energy-energy correlation
00129         if (th <= 8.) continue;
00130         double phi1 = p.phi(ZERO_2PI);
00131         double eta1 = p.eta();
00132         double et1 = fabs(p.momentum().Et());
00133         for (size_t ip2 = ip1+1; ip2 < particles.size(); ++ip2) {
00134           const Particle& p2 = particles[ip2];
00135 
00136           //double th2 = beamAngle(p2.momentum(), order);
00137           double th2 = p2.angle(dk.beamHadron().momentum()) / degree;
00138           if (th2 <= 8.) continue;
00139           double phi2 = p2.phi(ZERO_2PI);
00140 
00141           /// @todo Use angle function
00142           double deltaphi = phi1 - phi2;
00143           if (fabs(deltaphi) > PI)
00144             deltaphi = fabs(fabs(deltaphi) - TWOPI);
00145           double eta2 = p2.eta();
00146           double omega = sqrt(sqr(eta1-eta2) + sqr(deltaphi));
00147           double et2 = fabs(p2.momentum().Et());
00148           double wt = et1*et2 / sqr(ptel) * weight;
00149           if(x < 1e-3) {
00150             _histEECLowX ->fill(omega, wt);
00151           } else {
00152             _histEECHighX->fill(omega,wt);
00153           }
00154         }
00155       }
00156 
00157       // Factors for normalization
00158       if (w > 50. && w <= 200.) {
00159         if (w <= 100.) {
00160           _w77.first  += ncharged*weight;
00161           _w77.second += weight;
00162         } else if (w <= 150.) {
00163           _w122.first  += ncharged*weight;
00164           _w122.second += weight;
00165         } else {
00166           _w169.first  += ncharged*weight;
00167           _w169.second += weight;
00168         }
00169         _w117.first  += ncharged*weight;
00170         _w117.second += weight;
00171       }
00172     }
00173 
00174 
00175 
00176     void init() {
00177       // Projections
00178       addProjection(DISLepton(), "Lepton");
00179       addProjection(DISKinematics(), "Kinematics");
00180       addProjection(FinalState(), "FS");
00181 
00182       // Histos
00183       _histEnergyFlowLowX =  bookHisto1D(1, 1, 1);
00184       _histEnergyFlowHighX = bookHisto1D(1, 1, 2);
00185 
00186       _histEECLowX = bookHisto1D(2, 1, 1);
00187       _histEECHighX = bookHisto1D(2, 1, 2);
00188 
00189       _histSpectraW77 = bookHisto1D(3, 1, 1);
00190       _histSpectraW122 = bookHisto1D(3, 1, 2);
00191       _histSpectraW169 = bookHisto1D(3, 1, 3);
00192       _histSpectraW117 = bookHisto1D(3, 1, 4);
00193 
00194       _histPT2 = bookProfile1D(4, 1, 1);
00195     }
00196 
00197 
00198     /// Finalize
00199     void finalize() {
00200       // Normalize inclusive single particle distributions to the average number
00201       // of charged particles per event.
00202       double avgNumParts = _w77.first/_w77.second;
00203       normalize(_histSpectraW77, avgNumParts);
00204 
00205       avgNumParts = _w122.first/_w122.second;
00206       normalize(_histSpectraW122, avgNumParts);
00207 
00208       avgNumParts = _w169.first/_w169.second;
00209       normalize(_histSpectraW169, avgNumParts);
00210 
00211       avgNumParts = _w117.first/_w117.second;
00212       normalize(_histSpectraW117, avgNumParts);
00213 
00214       scale(_histEnergyFlowLowX , 1./_wEnergy.first );
00215       scale(_histEnergyFlowHighX, 1./_wEnergy.second);
00216 
00217       scale(_histEECLowX , 1./_wEnergy.first );
00218       scale(_histEECHighX, 1./_wEnergy.second);
00219     }
00220 
00221 
00222     //@}
00223 
00224 
00225   private:
00226 
00227     /**
00228      *  Polar angle with right direction of the beam
00229      */
00230     inline double beamAngle(const FourVector& v, const bool & order) {
00231       double thel = v.polarAngle()/degree;
00232       if(thel<0.) thel+=180.;
00233       if(!order) thel = 180.-thel;
00234       return thel;
00235     }
00236 
00237     /// @name Histograms
00238     //@{
00239     Histo1DPtr _histEnergyFlowLowX;
00240     Histo1DPtr _histEnergyFlowHighX;
00241     Histo1DPtr _histEECLowX;
00242     Histo1DPtr _histEECHighX;
00243     Histo1DPtr _histSpectraW77;
00244     Histo1DPtr _histSpectraW122;
00245     Histo1DPtr _histSpectraW169;
00246     Histo1DPtr _histSpectraW117;
00247     Profile1DPtr _histPT2;
00248     //@}
00249 
00250     /// @name storage of weight to calculate averages for normalisation
00251     //@{
00252     pair<double,double> _w77,_w122,_w169,_w117,_wEnergy;
00253     //@}
00254   };
00255 
00256 
00257 
00258   // The hook for the plugin system
00259   DECLARE_RIVET_PLUGIN(H1_1994_S2919893);
00260 
00261 }