rivet is hosted by Hepforge, IPPP Durham
ATLAS_2012_I1199269.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analysis.hh"
00003 #include "Rivet/Projections/IdentifiedFinalState.hh"
00004 #include "Rivet/Projections/FastJets.hh"
00005 /// @todo These should be unnecessary from 2.2.0 onward when Rivet::Jet is rewritten
00006 #include "fastjet/internal/base.hh"
00007 #include "fastjet/JetDefinition.hh"
00008 #include "fastjet/AreaDefinition.hh"
00009 #include "fastjet/ClusterSequence.hh"
00010 #include "fastjet/ClusterSequenceArea.hh"
00011 #include "fastjet/PseudoJet.hh"
00012 
00013 namespace Rivet {
00014 
00015 
00016   /// @brief Measurement of isolated diphoton + X differential cross-sections
00017   ///
00018   /// Inclusive isolated gamma gamma cross-sections, differential in M(gg), pT(gg),
00019   /// dphi(gg), cos(theta*)_CS
00020   ///
00021   /// @author Giovanni Marchiori
00022   ///
00023   class ATLAS_2012_I1199269 : public Analysis {
00024   public:
00025 
00026     /// Constructor
00027     ATLAS_2012_I1199269()
00028       : Analysis("ATLAS_2012_I1199269")
00029     {
00030       _eta_bins_areaoffset += 0.0, 1.5, 3.0;
00031     }
00032 
00033 
00034     /// Book histograms and initialise projections before the run
00035     void init() {
00036 
00037       FinalState fs;
00038       addProjection(fs, "FS");
00039 
00040       /// @todo Clean-up when jets are better
00041       FastJets fj(fs, FastJets::KT, 0.5);
00042       _area_def = new fastjet::AreaDefinition(fastjet::VoronoiAreaSpec());
00043       fj.useJetArea(_area_def);
00044       addProjection(fj, "KtJetsD05");
00045 
00046       IdentifiedFinalState photonfs(Cuts::abseta < 2.37 && Cuts::pT > 22*GeV);
00047       photonfs.acceptId(PID::PHOTON);
00048       addProjection(photonfs, "Photon");
00049 
00050       _h_M            = bookHisto1D(1, 1, 1);
00051       _h_pT           = bookHisto1D(2, 1, 1);
00052       _h_dPhi         = bookHisto1D(3, 1, 1);
00053       _h_cosThetaStar = bookHisto1D(4, 1, 1);
00054     }
00055 
00056 
00057     // int getBinIndex(double x, const vector<double>& binedges) const {
00058     //   /// @todo Add linear and log bin guessing, use binary split if sufficiently large, etc.
00059     //   for (size_t i = 0; i < _binedges.size()-1; ++i)
00060     //     if (inRange(x, binedges[i], binedges[i+1])) return (int) i;
00061     //   return -1;
00062     // }
00063 
00064 
00065     /// Perform the per-event analysis
00066     void analyze(const Event& event) {
00067       const double weight = event.weight();
00068 
00069       /// Require at least 2 photons in final state
00070       const Particles photons = applyProjection<IdentifiedFinalState>(event, "Photon").particlesByPt();
00071       if (photons.size() < 2) vetoEvent;
00072 
00073       /// Compute the median energy density
00074       _ptDensity.clear();
00075       _sigma.clear();
00076       _Njets.clear();
00077       /// @todo Nicer way to do this... in C++11?
00078       vector<vector<double> > ptDensities;
00079       vector<double> emptyVec;
00080       ptDensities.assign(_eta_bins_areaoffset.size()-1, emptyVec);
00081 
00082       // Get jets, and corresponding jet areas
00083       const fastjet::ClusterSequenceArea* clust_seq_area = applyProjection<FastJets>(event, "KtJetsD05").clusterSeqArea();
00084       foreach (const fastjet::PseudoJet& jet, applyProjection<FastJets>(event, "KtJetsD05").pseudoJets(0.0*GeV)) {
00085         const double aeta = fabs(jet.eta());
00086         const double pt = jet.perp();
00087         const double area = clust_seq_area->area(jet);
00088         if (area < 1e-3) continue;
00089         const int ieta = binIndex(aeta, _eta_bins_areaoffset);
00090         if (ieta != -1) ptDensities[ieta].push_back(pt/area);
00091       }
00092 
00093       // Compute median jet properties over the jets in the event
00094       for (size_t b = 0; b < _eta_bins_areaoffset.size()-1; ++b) {
00095         double median = 0.0;
00096         double sigma = 0.0;
00097         int Njets = 0;
00098         if (ptDensities[b].size() > 0) {
00099           std::sort(ptDensities[b].begin(), ptDensities[b].end());
00100           int nDens = ptDensities[b].size();
00101           median = (nDens % 2 == 0) ? (ptDensities[b][nDens/2]+ptDensities[b][(nDens-2)/2])/2 : ptDensities[b][(nDens-1)/2];
00102           sigma = ptDensities[b][(int)(.15865*nDens)];
00103           Njets = nDens;
00104         }
00105         _ptDensity.push_back(median);
00106         _sigma.push_back(sigma);
00107         _Njets.push_back(Njets);
00108       }
00109 
00110 
00111       // Loop over photons and fill vector of isolated ones
00112       Particles isolated_photons;
00113       foreach (const Particle& photon, photons) {
00114         /// Remove photons in ECAL crack region
00115         if (inRange(photon.abseta(), 1.37, 1.52)) continue;
00116         const double eta_P = photon.eta();
00117         const double phi_P = photon.phi();
00118 
00119         // Compute isolation via particles within an R=0.4 cone of the photon
00120         Particles fs = applyProjection<FinalState>(event, "FS").particles();
00121         FourMomentum mom_in_EtCone;
00122         foreach (const Particle& p, fs) {
00123           // Reject if not in cone
00124           if (deltaR(photon.momentum(), p.momentum()) > 0.4) continue;
00125           // Reject if in the 5x7 cell central core
00126           if (fabs(eta_P - p.eta()) < 0.025 * 5 * 0.5 &&
00127               fabs(phi_P - p.phi()) < PI/128. * 7 * 0.5) continue;
00128           // Sum momentum
00129           mom_in_EtCone += p.momentum();
00130         }
00131         // Now figure out the correction (area*density)
00132         const double EtCone_area = PI*sqr(0.4) - (7*.025)*(5*PI/128.); // cone area - central core rectangle
00133         const double correction = _ptDensity[binIndex(fabs(eta_P), _eta_bins_areaoffset)] * EtCone_area;
00134 
00135         // Discard the photon if there is more than 4 GeV of cone activity
00136         // NOTE: Shouldn't need to subtract photon itself (it's in the central core)
00137         // NOTE: using expected cut at hadron/particle level, not at reco level
00138         if (mom_in_EtCone.Et() - correction > 4*GeV) continue;
00139         // Add isolated photon to list
00140         isolated_photons.push_back(photon);
00141       }
00142 
00143       // Require at least two isolated photons and select leading pT pair
00144       if (isolated_photons.size() < 2) vetoEvent;
00145       sortByPt(isolated_photons);
00146       FourMomentum y1 = isolated_photons[0].momentum();
00147       FourMomentum y2 = isolated_photons[1].momentum();
00148 
00149       // Leading photon should have pT > 25 GeV
00150       if (y1.pT() < 25*GeV) vetoEvent;
00151 
00152       // Require the two photons to be separated by dR > 0.4
00153       if (deltaR(y1, y2) < 0.4) vetoEvent;
00154 
00155       FourMomentum yy = y1 + y2;
00156       const double Myy = yy.mass();
00157       _h_M->fill(Myy/GeV, weight);
00158       const double pTyy = yy.pT();
00159       _h_pT->fill(pTyy/GeV, weight);
00160       const double dPhiyy = mapAngle0ToPi(y1.phi() - y2.phi());
00161       _h_dPhi->fill(dPhiyy, weight);
00162       const double costhetayy = 2 * y1.pT() * y2.pT() * sinh(y1.eta() - y2.eta()) / Myy / add_quad(Myy, pTyy);
00163       _h_cosThetaStar->fill(costhetayy, weight);
00164     }
00165 
00166 
00167     /// Normalise histograms etc., after the run
00168     void finalize() {
00169       scale(_h_M, crossSection()/sumOfWeights());
00170       scale(_h_pT, crossSection()/sumOfWeights());
00171       scale(_h_dPhi, crossSection()/sumOfWeights());
00172       scale(_h_cosThetaStar, crossSection()/sumOfWeights());
00173     }
00174 
00175 
00176   private:
00177 
00178     Histo1DPtr _h_M, _h_pT, _h_dPhi, _h_cosThetaStar;
00179 
00180     fastjet::AreaDefinition* _area_def;
00181 
00182     vector<double> _eta_bins;
00183     vector<double> _eta_bins_areaoffset;
00184 
00185     vector<double> _ptDensity;
00186     vector<double> _sigma;
00187     vector<double> _Njets;
00188   };
00189 
00190 
00191   DECLARE_RIVET_PLUGIN(ATLAS_2012_I1199269);
00192 
00193 }