rivet is hosted by Hepforge, IPPP Durham
MC_JetAnalysis.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #include "Rivet/Analyses/MC_JetAnalysis.hh"
00003 #include "Rivet/Projections/FastJets.hh"
00004 
00005 namespace Rivet {
00006 
00007 
00008   MC_JetAnalysis::MC_JetAnalysis(const string& name,
00009                                  size_t njet,
00010                                  const string& jetpro_name,
00011                                  double jetptcut)
00012     : Analysis(name), m_njet(njet), m_jetpro_name(jetpro_name), m_jetptcut(jetptcut),
00013       _h_pT_jet(njet),
00014       _h_eta_jet(njet), _h_eta_jet_plus(njet), _h_eta_jet_minus(njet),
00015       _h_rap_jet(njet), _h_rap_jet_plus(njet), _h_rap_jet_minus(njet),
00016       _h_mass_jet(njet)
00017   {
00018     setNeedsCrossSection(true); // legitimate use, since a base class has no .info file!
00019   }
00020 
00021 
00022 
00023   // Book histograms
00024   void MC_JetAnalysis::init() {
00025 
00026     for (size_t i = 0; i < m_njet; ++i) {
00027       string pTname = "jet_pT_" + to_str(i+1);
00028       double pTmax = 1.0/(double(i)+2.0) * sqrtS()/GeV/2.0;
00029       int nbins_pT = 100/(i+1);
00030       _h_pT_jet[i] = bookHisto1D(pTname, logspace(nbins_pT, 10.0, pTmax));
00031 
00032       string massname = "jet_mass_" + to_str(i+1);
00033       double mmax = 100.0;
00034       int nbins_m = 100/(i+1);
00035       _h_mass_jet[i] = bookHisto1D(massname, logspace(nbins_m, 1.0, mmax));
00036 
00037       string etaname = "jet_eta_" + to_str(i+1);
00038       _h_eta_jet[i] = bookHisto1D(etaname, i > 1 ? 25 : 50, -5.0, 5.0);
00039       _h_eta_jet_plus[i].reset(new Histo1D(i > 1 ? 15 : 25, 0, 5));
00040       _h_eta_jet_minus[i].reset(new Histo1D(i > 1 ? 15 : 25, 0, 5));
00041 
00042       string rapname = "jet_y_" + to_str(i+1);
00043       _h_rap_jet[i] = bookHisto1D(rapname, i>1 ? 25 : 50, -5.0, 5.0);
00044       _h_rap_jet_plus[i].reset(new Histo1D(i > 1 ? 15 : 25, 0, 5));
00045       _h_rap_jet_minus[i].reset(new Histo1D(i > 1 ? 15 : 25, 0, 5));
00046 
00047       for (size_t j = i+1; j < min(size_t(3), m_njet); ++j) {
00048         std::pair<size_t, size_t> ij = std::make_pair(i, j);
00049 
00050         string detaname = "jets_deta_" + to_str(i+1) + to_str(j+1);
00051         _h_deta_jets.insert(make_pair(ij, bookHisto1D(detaname, 25, -5.0, 5.0)));
00052 
00053         string dphiname = "jets_dphi_" + to_str(i+1) + to_str(j+1);
00054         _h_dphi_jets.insert(make_pair(ij, bookHisto1D(dphiname, 25, 0.0, M_PI)));
00055 
00056         string dRname = "jets_dR_" + to_str(i+1) + to_str(j+1);
00057         _h_dR_jets.insert(make_pair(ij, bookHisto1D(dRname, 25, 0.0, 5.0)));
00058       }
00059     }
00060 
00061     _h_jet_multi_exclusive = bookHisto1D("jet_multi_exclusive", m_njet+3, -0.5, m_njet+3-0.5);
00062     _h_jet_multi_inclusive = bookHisto1D("jet_multi_inclusive", m_njet+3, -0.5, m_njet+3-0.5);
00063     _h_jet_multi_ratio = bookScatter2D("jet_multi_ratio");
00064     _h_jet_HT = bookHisto1D("jet_HT", logspace(50, m_jetptcut, sqrtS()/GeV/2.0));
00065   }
00066 
00067 
00068   // Do the analysis
00069   void MC_JetAnalysis::analyze(const Event & e) {
00070     const double weight = e.weight();
00071 
00072     const Jets& jets = applyProjection<FastJets>(e, m_jetpro_name).jetsByPt(m_jetptcut);
00073 
00074     for (size_t i = 0; i < m_njet; ++i) {
00075       if (jets.size() < i+1) continue;
00076       _h_pT_jet[i]->fill(jets[i].pT()/GeV, weight);
00077       // Check for numerical precision issues with jet masses
00078       double m2_i = jets[i].momentum().mass2();
00079       if (m2_i < 0) {
00080         if (m2_i < -1e-4) {
00081           MSG_WARNING("Jet mass2 is negative: " << m2_i << " GeV^2. "
00082                       << "Truncating to 0.0, assuming numerical precision is to blame.");
00083         }
00084         m2_i = 0.0;
00085       }
00086 
00087       // Jet mass
00088       _h_mass_jet[i]->fill(sqrt(m2_i)/GeV, weight);
00089 
00090       // Jet eta
00091       const double eta_i = jets[i].eta();
00092       _h_eta_jet[i]->fill(eta_i, weight);
00093       if (eta_i > 0.0) {
00094         _h_eta_jet_plus[i]->fill(eta_i, weight);
00095       } else {
00096         _h_eta_jet_minus[i]->fill(fabs(eta_i), weight);
00097       }
00098 
00099       // Jet rapidity
00100       const double rap_i = jets[i].rapidity();
00101       _h_rap_jet[i]->fill(rap_i, weight);
00102       if (rap_i > 0.0) {
00103         _h_rap_jet_plus[i]->fill(rap_i, weight);
00104       } else {
00105         _h_rap_jet_minus[i]->fill(fabs(rap_i), weight);
00106       }
00107 
00108       // Inter-jet properties
00109       for (size_t j = i+1; j < min(size_t(3),m_njet); ++j) {
00110         if (jets.size() < j+1) continue;
00111         std::pair<size_t, size_t> ij = std::make_pair(i, j);
00112         double deta = jets[i].eta()-jets[j].eta();
00113         double dphi = deltaPhi(jets[i].momentum(),jets[j].momentum());
00114         double dR = deltaR(jets[i].momentum(), jets[j].momentum());
00115         _h_deta_jets[ij]->fill(deta, weight);
00116         _h_dphi_jets[ij]->fill(dphi, weight);
00117         _h_dR_jets[ij]->fill(dR, weight);
00118       }
00119     }
00120     _h_jet_multi_exclusive->fill(jets.size(), weight);
00121 
00122     for (size_t i = 0; i < m_njet+2; ++i) {
00123       if (jets.size() >= i) {
00124         _h_jet_multi_inclusive->fill(i, weight);
00125       }
00126     }
00127 
00128     double HT=0.0;
00129     foreach (const Jet& jet, jets) {
00130       HT += jet.pT();
00131     }
00132     _h_jet_HT->fill(HT, weight);
00133   }
00134 
00135 
00136   // Finalize
00137   void MC_JetAnalysis::finalize() {
00138     for (size_t i = 0; i < m_njet; ++i) {
00139       scale(_h_pT_jet[i], crossSection()/sumOfWeights());
00140       scale(_h_mass_jet[i], crossSection()/sumOfWeights());
00141       scale(_h_eta_jet[i], crossSection()/sumOfWeights());
00142       scale(_h_rap_jet[i], crossSection()/sumOfWeights());
00143 
00144       // Create eta/rapidity ratio plots
00145       // @todo seems to crash when the divided histo happens to be unfilled
00146       //divide(*_h_eta_jet_plus[i], *_h_eta_jet_minus[i], bookScatter2D("jet_eta_pmratio_" + to_str(i+1)));
00147       //divide(*_h_rap_jet_plus[i], *_h_rap_jet_minus[i], bookScatter2D("jet_y_pmratio_" + to_str(i+1)));
00148     }
00149 
00150     // Scale the d{eta,phi,R} histograms
00151     typedef map<pair<size_t, size_t>, Histo1DPtr> HistMap;
00152     foreach (HistMap::value_type& it, _h_deta_jets) scale(it.second, crossSection()/sumOfWeights());
00153     foreach (HistMap::value_type& it, _h_dphi_jets) scale(it.second, crossSection()/sumOfWeights());
00154     foreach (HistMap::value_type& it, _h_dR_jets) scale(it.second, crossSection()/sumOfWeights());
00155 
00156     // Fill inclusive jet multi ratio
00157     int Nbins = _h_jet_multi_inclusive->numBins();
00158     for (int i = 0; i < Nbins-1; ++i) {
00159       _h_jet_multi_ratio->addPoint(i+1, 0, 0, 0);
00160       if (_h_jet_multi_inclusive->bin(i).sumW() > 0.0) {
00161         const double ratio = _h_jet_multi_inclusive->bin(i+1).sumW()/_h_jet_multi_inclusive->bin(i).sumW();
00162         const double relerr_i = _h_jet_multi_inclusive->bin(i).relErr();
00163         const double relerr_j = _h_jet_multi_inclusive->bin(i+1).relErr();
00164         const double err = ratio * (relerr_i + relerr_j);
00165         _h_jet_multi_ratio->point(i).setY(ratio, err);
00166       }
00167     }
00168 
00169     scale(_h_jet_multi_exclusive, crossSection()/sumOfWeights());
00170     scale(_h_jet_multi_inclusive, crossSection()/sumOfWeights());
00171     scale(_h_jet_HT, crossSection()/sumOfWeights());
00172   }
00173 
00174 
00175 }