H1_1994_S2919893.cc

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