ATLAS_2011_S8994773.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/RivetAIDA.hh"
00004 #include "Rivet/Projections/FinalState.hh"
00005 #include "Rivet/Tools/Logging.hh"
00006 #include "LWH/Profile1D.h"
00007 #include "LWH/Histogram1D.h"
00008 
00009 namespace Rivet {
00010 
00011 
00012   /// @author Jinlong Zhang
00013   class ATLAS_2011_S8994773 : public Analysis {
00014   public:
00015 
00016     ATLAS_2011_S8994773()
00017       : Analysis("ATLAS_2011_S8994773") {    }
00018 
00019 
00020     void init() {
00021       const FinalState fs500(-2.5, 2.5, 500*MeV);
00022       addProjection(fs500, "FS500");
00023       const FinalState fslead(-2.5, 2.5, 1.0*GeV);
00024       addProjection(fslead, "FSlead");
00025 
00026       // Get an index for the beam energy
00027       isqrts = -1;
00028       if (fuzzyEquals(sqrtS(), 900*GeV)) isqrts = 0;
00029       else if (fuzzyEquals(sqrtS(), 7*TeV)) isqrts = 1;
00030       assert(isqrts >= 0);
00031 
00032       // N profiles, 500 MeV pT cut
00033       _hist_N_transverse_500 = bookProfile1D(1+isqrts, 1, 1);
00034       // pTsum profiles, 500 MeV pT cut
00035       _hist_ptsum_transverse_500 = bookProfile1D(3+isqrts, 1, 1);
00036       // N vs. Delta(phi) profiles, 500 MeV pT cut
00037       _hist_N_vs_dPhi_1_500 = bookProfile1D(13+isqrts, 1, 1);
00038       _hist_N_vs_dPhi_2_500 = bookProfile1D(13+isqrts, 1, 2);
00039       _hist_N_vs_dPhi_3_500 = bookProfile1D(13+isqrts, 1, 3);
00040     }
00041 
00042 
00043     void analyze(const Event& event) {
00044       const double weight = event.weight();
00045 
00046       // Require at least one cluster in the event with pT >= 1 GeV
00047       const FinalState& fslead = applyProjection<FinalState>(event, "FSlead");
00048       if (fslead.size() < 1) {
00049         vetoEvent;
00050       }
00051 
00052       // These are the particles  with pT > 500 MeV
00053       const FinalState& chargedNeutral500 = applyProjection<FinalState>(event, "FS500");
00054 
00055       // Identify leading object and its phi and pT
00056       ParticleVector particles500 = chargedNeutral500.particlesByPt();
00057       Particle p_lead = particles500[0];
00058       const double philead = p_lead.momentum().phi();
00059       const double etalead = p_lead.momentum().eta();
00060       const double pTlead  = p_lead.momentum().perp();
00061       MSG_DEBUG("Leading oject: pT = " << pTlead << ", eta = " << etalead << ", phi = " << philead);
00062 
00063       // Iterate over all > 500 MeV particles and count particles and scalar pTsum in the three regions
00064       vector<double> num500(3, 0), ptSum500(3, 0.0);
00065       // Temporary histos that bin N in dPhi.
00066       // NB. Only one of each needed since binnings are the same for the energies and pT cuts
00067       LWH::Histogram1D hist_num_dphi_500(binEdges(13+isqrts,1,1));
00068       foreach (const Particle& p, particles500) {
00069         const double pT = p.momentum().pT();
00070         const double dPhi = deltaPhi(philead, p.momentum().phi());
00071         const int ir = region_index(dPhi);
00072         num500[ir] += 1;
00073         ptSum500[ir] += pT;
00074 
00075         // Fill temp histos to bin N in dPhi
00076         if (p.genParticle() != p_lead.genParticle()) { // We don't want to fill all those zeros from the leading track...
00077           hist_num_dphi_500.fill(dPhi, 1);
00078         }
00079       }
00080 
00081 
00082       // Now fill underlying event histograms
00083       // The densities are calculated by dividing the UE properties by dEta*dPhi
00084       // -- each region has a dPhi of 2*PI/3 and dEta is two times 2.5
00085       const double dEtadPhi = (2*2.5 * 2*PI/3.0);
00086       _hist_N_transverse_500->fill(pTlead/GeV,  num500[1]/dEtadPhi, weight);
00087       _hist_ptsum_transverse_500->fill(pTlead/GeV, ptSum500[1]/GeV/dEtadPhi, weight);
00088 
00089       // Update the "proper" dphi profile histograms
00090       // Note that we fill dN/dEtadPhi: dEta = 2*2.5, dPhi = 2*PI/nBins
00091       // The values tabulated in the note are for an (undefined) signed Delta(phi) rather than
00092       // |Delta(phi)| and so differ by a factor of 2: we have to actually norm for angular range = 2pi
00093       const size_t nbins = binEdges(13+isqrts,1,1).size() - 1;
00094       for (size_t i = 0; i < nbins; ++i) {
00095         const double binmean_num = hist_num_dphi_500.binMean(i);
00096         const double binvalue_num = hist_num_dphi_500.binHeight(i)/hist_num_dphi_500.axis().binWidth(i)/10.0;
00097         if (pTlead/GeV >= 1.0) _hist_N_vs_dPhi_1_500->fill(binmean_num, binvalue_num, weight);
00098         if (pTlead/GeV >= 2.0) _hist_N_vs_dPhi_2_500->fill(binmean_num, binvalue_num, weight);
00099         if (pTlead/GeV >= 3.0) _hist_N_vs_dPhi_3_500->fill(binmean_num, binvalue_num, weight);
00100       }
00101 
00102     }
00103 
00104 
00105     void finalize() {
00106       // nothing
00107     }
00108 
00109 
00110   private:
00111 
00112     // Little helper function to identify Delta(phi) regions
00113     inline int region_index(double dphi) {
00114       assert(inRange(dphi, 0.0, PI, CLOSED, CLOSED));
00115       if (dphi < PI/3.0) return 0;
00116       if (dphi < 2*PI/3.0) return 1;
00117       return 2;
00118     }
00119 
00120 
00121   private:
00122     int isqrts;
00123 
00124     AIDA::IProfile1D*  _hist_N_transverse_500;
00125 
00126     AIDA::IProfile1D*  _hist_ptsum_transverse_500;
00127 
00128     AIDA::IProfile1D*  _hist_N_vs_dPhi_1_500;
00129     AIDA::IProfile1D*  _hist_N_vs_dPhi_2_500;
00130     AIDA::IProfile1D*  _hist_N_vs_dPhi_3_500;
00131 
00132   };
00133 
00134 
00135 
00136   // The hook for the plugin system
00137   DECLARE_RIVET_PLUGIN(ATLAS_2011_S8994773);
00138 
00139 }