MC_TTBAR.cc
Go to the documentation of this file.
00001 #include "Rivet/Analysis.hh" 00002 #include "Rivet/Projections/FinalState.hh" 00003 #include "Rivet/Projections/VetoedFinalState.hh" 00004 #include "Rivet/Projections/ChargedLeptons.hh" 00005 #include "Rivet/Projections/MissingMomentum.hh" 00006 #include "Rivet/Projections/FastJets.hh" 00007 #include "Rivet/AnalysisLoader.hh" 00008 00009 namespace Rivet { 00010 00011 00012 class MC_TTBAR : public Analysis { 00013 public: 00014 00015 /// Minimal constructor 00016 MC_TTBAR() : Analysis("MC_TTBAR") 00017 { 00018 } 00019 00020 00021 /// @name Analysis methods 00022 //@{ 00023 00024 /// Set up projections and book histograms 00025 void init() { 00026 00027 // A FinalState is used to select particles within |eta| < 4.2 and with pT 00028 // > 30 GeV, out of which the ChargedLeptons projection picks only the 00029 // electrons and muons, to be accessed later as "LFS". 00030 ChargedLeptons lfs(FinalState(-4.2, 4.2, 30*GeV)); 00031 addProjection(lfs, "LFS"); 00032 // A second FinalState is used to select all particles in |eta| < 4.2, 00033 // with no pT cut. This is used to construct jets and measure missing 00034 // transverse energy. 00035 VetoedFinalState fs(FinalState(-4.2, 4.2, 0*GeV)); 00036 fs.addVetoOnThisFinalState(lfs); 00037 addProjection(FastJets(fs, FastJets::ANTIKT, 0.6), "Jets"); 00038 addProjection(MissingMomentum(fs), "MissingET"); 00039 00040 // Booking of histograms 00041 _h_njets = bookHisto1D("jet_mult", 11, -0.5, 10.5); 00042 // 00043 _h_jet_1_pT = bookHisto1D("jet_1_pT", logspace(50, 20.0, 500.0)); 00044 _h_jet_2_pT = bookHisto1D("jet_2_pT", logspace(50, 20.0, 400.0)); 00045 _h_jet_3_pT = bookHisto1D("jet_3_pT", logspace(50, 20.0, 300.0)); 00046 _h_jet_4_pT = bookHisto1D("jet_4_pT", logspace(50, 20.0, 200.0)); 00047 _h_jet_HT = bookHisto1D("jet_HT", logspace(50, 100.0, 2000.0)); 00048 // 00049 _h_bjet_1_pT = bookHisto1D("jetb_1_pT", logspace(50, 20.0, 400.0)); 00050 _h_bjet_2_pT = bookHisto1D("jetb_2_pT", logspace(50, 20.0, 300.0)); 00051 // 00052 _h_ljet_1_pT = bookHisto1D("jetl_1_pT", logspace(50, 20.0, 400.0)); 00053 _h_ljet_2_pT = bookHisto1D("jetl_2_pT", logspace(50, 20.0, 300.0)); 00054 // 00055 _h_W_mass = bookHisto1D("W_mass", 75, 30, 180); 00056 _h_t_mass = bookHisto1D("t_mass", 150, 130, 430); 00057 _h_t_mass_W_cut = bookHisto1D("t_mass_W_cut", 150, 130, 430); 00058 // 00059 _h_jetb_1_jetb_2_dR = bookHisto1D("jetb_1_jetb_2_dR", 20, 0.0, 7.0); 00060 _h_jetb_1_jetb_2_deta = bookHisto1D("jetb_1_jetb_2_deta", 20, 0.0, 7.0); 00061 _h_jetb_1_jetb_2_dphi = bookHisto1D("jetb_1_jetb_2_dphi", 20, 0.0, M_PI); 00062 _h_jetb_1_jetl_1_dR = bookHisto1D("jetb_1_jetl_1_dR", 20, 0.0, 7.0); 00063 _h_jetb_1_jetl_1_deta = bookHisto1D("jetb_1_jetl_1_deta", 20, 0.0, 7.0); 00064 _h_jetb_1_jetl_1_dphi = bookHisto1D("jetb_1_jetl_1_dphi", 20, 0.0, M_PI); 00065 _h_jetl_1_jetl_2_dR = bookHisto1D("jetl_1_jetl_2_dR", 20, 0.0, 7.0); 00066 _h_jetl_1_jetl_2_deta = bookHisto1D("jetl_1_jetl_2_deta", 20, 0.0, 7.0); 00067 _h_jetl_1_jetl_2_dphi = bookHisto1D("jetl_1_jetl_2_dphi", 20, 0.0, M_PI); 00068 _h_jetb_1_W_dR = bookHisto1D("jetb_1_W_dR", 20, 0.0, 7.0); 00069 _h_jetb_1_W_deta = bookHisto1D("jetb_1_W_deta", 20, 0.0, 7.0); 00070 _h_jetb_1_W_dphi = bookHisto1D("jetb_1_W_dphi", 20, 0.0, M_PI); 00071 _h_jetb_1_l_dR = bookHisto1D("jetb_1_l_dR", 20, 0.0, 7.0); 00072 _h_jetb_1_l_deta = bookHisto1D("jetb_1_l_deta", 20, 0.0, 7.0); 00073 _h_jetb_1_l_dphi = bookHisto1D("jetb_1_l_dphi", 20, 0.0, M_PI); 00074 _h_jetb_1_l_mass = bookHisto1D("jetb_1_l_mass", 40, 0.0, 500.0); 00075 } 00076 00077 00078 void analyze(const Event& event) { 00079 const double weight = event.weight(); 00080 00081 // Use the "LFS" projection to require at least one hard charged 00082 // lepton. This is an experimental signature for the leptonically decaying 00083 // W. This helps to reduce pure QCD backgrounds. 00084 const ChargedLeptons& lfs = applyProjection<ChargedLeptons>(event, "LFS"); 00085 MSG_DEBUG("Charged lepton multiplicity = " << lfs.chargedLeptons().size()); 00086 foreach (const Particle& lepton, lfs.chargedLeptons()) { 00087 MSG_DEBUG("Lepton pT = " << lepton.pT()); 00088 } 00089 if (lfs.chargedLeptons().empty()) { 00090 MSG_DEBUG("Event failed lepton multiplicity cut"); 00091 vetoEvent; 00092 } 00093 00094 // Use a missing ET cut to bias toward events with a hard neutrino from 00095 // the leptonically decaying W. This helps to reduce pure QCD backgrounds. 00096 const MissingMomentum& met = applyProjection<MissingMomentum>(event, "MissingET"); 00097 MSG_DEBUG("Vector ET = " << met.vectorEt().mod() << " GeV"); 00098 if (met.vectorEt().mod() < 30*GeV) { 00099 MSG_DEBUG("Event failed missing ET cut"); 00100 vetoEvent; 00101 } 00102 00103 // Use the "Jets" projection to check that there are at least 4 jets of 00104 // any pT. Getting the jets sorted by pT ensures that the first jet is the 00105 // hardest, and so on. We apply no pT cut here only because we want to 00106 // plot all jet pTs to help optimise our jet pT cut. 00107 const FastJets& jetpro = applyProjection<FastJets>(event, "Jets"); 00108 const Jets alljets = jetpro.jetsByPt(); 00109 if (alljets.size() < 4) { 00110 MSG_DEBUG("Event failed jet multiplicity cut"); 00111 vetoEvent; 00112 } 00113 00114 // Update passed-cuts counter and fill all-jets histograms 00115 _h_jet_1_pT->fill(alljets[0].pT()/GeV, weight); 00116 _h_jet_2_pT->fill(alljets[1].pT()/GeV, weight); 00117 _h_jet_3_pT->fill(alljets[2].pT()/GeV, weight); 00118 _h_jet_4_pT->fill(alljets[3].pT()/GeV, weight); 00119 00120 // Insist that the hardest 4 jets pass pT hardness cuts. If we don't find 00121 // at least 4 such jets, we abandon this event. 00122 const Jets jets = jetpro.jetsByPt(30*GeV); 00123 _h_njets->fill(jets.size(), weight); 00124 double ht = 0.0; 00125 foreach (const Jet& j, jets) { ht += j.pT(); } 00126 _h_jet_HT->fill(ht/GeV, weight); 00127 if (jets.size() < 4 || 00128 jets[0].pT() < 60*GeV || 00129 jets[1].pT() < 50*GeV || 00130 jets[3].pT() < 30*GeV) { 00131 MSG_DEBUG("Event failed jet cuts"); 00132 vetoEvent; 00133 } 00134 00135 // Sort the jets into b-jets and light jets. We expect one hard b-jet from 00136 // each top decay, so our 4 hardest jets should include two b-jets. The 00137 // Jet::containsBottom() method is equivalent to perfect experimental 00138 // b-tagging, in a generator-independent way. 00139 Jets bjets, ljets; 00140 foreach (const Jet& jet, jets) { 00141 // // Don't count jets that overlap with the hard leptons 00142 bool isolated = true; 00143 foreach (const Particle& lepton, lfs.chargedLeptons()) { 00144 if (deltaR(jet.momentum(), lepton.momentum()) < 0.3) { 00145 isolated = false; 00146 break; 00147 } 00148 } 00149 if (!isolated) { 00150 MSG_DEBUG("Jet failed lepton isolation cut"); 00151 break; 00152 } 00153 if (jet.containsBottom()) { 00154 bjets.push_back(jet); 00155 } else { 00156 ljets.push_back(jet); 00157 } 00158 } 00159 MSG_DEBUG("Number of b-jets = " << bjets.size()); 00160 MSG_DEBUG("Number of l-jets = " << ljets.size()); 00161 if (bjets.size() != 2) { 00162 MSG_DEBUG("Event failed post-lepton-isolation b-tagging cut"); 00163 vetoEvent; 00164 } 00165 if (ljets.size() < 2) { 00166 MSG_DEBUG("Event failed since not enough light jets remaining after lepton-isolation"); 00167 vetoEvent; 00168 } 00169 00170 // Plot the pTs of the identified jets. 00171 _h_bjet_1_pT->fill(bjets[0].pT(), weight); 00172 _h_bjet_2_pT->fill(bjets[1].pT(), weight); 00173 _h_ljet_1_pT->fill(ljets[0].pT(), weight); 00174 _h_ljet_2_pT->fill(ljets[1].pT(), weight); 00175 00176 // Construct the hadronically decaying W momentum 4-vector from pairs of 00177 // non-b-tagged jets. The pair which best matches the W mass is used. We start 00178 // with an always terrible 4-vector estimate which should always be "beaten" by 00179 // a real jet pair. 00180 FourMomentum W(10*sqrtS(), 0, 0, 0); 00181 for (size_t i = 0; i < ljets.size()-1; ++i) { 00182 for (size_t j = i + 1; j < ljets.size(); ++j) { 00183 const FourMomentum Wcand = ljets[i].momentum() + ljets[j].momentum(); 00184 MSG_TRACE(i << "," << j << ": candidate W mass = " << Wcand.mass()/GeV 00185 << " GeV, vs. incumbent candidate with " << W.mass()/GeV << " GeV"); 00186 if (fabs(Wcand.mass() - 80.4*GeV) < fabs(W.mass() - 80.4*GeV)) { 00187 W = Wcand; 00188 } 00189 } 00190 } 00191 MSG_DEBUG("Candidate W mass = " << W.mass() << " GeV"); 00192 00193 // There are two b-jets with which this can be combined to make the 00194 // hadronically decaying top, one of which is correct and the other is 00195 // not... but we have no way to identify which is which, so we construct 00196 // both possible top momenta and fill the histograms with both. 00197 const FourMomentum t1 = W + bjets[0].momentum(); 00198 const FourMomentum t2 = W + bjets[1].momentum(); 00199 _h_W_mass->fill(W.mass(), weight); 00200 _h_t_mass->fill(t1.mass(), weight); 00201 _h_t_mass->fill(t2.mass(), weight); 00202 00203 // Placing a cut on the well-known W mass helps to reduce backgrounds 00204 if (inRange(W.mass()/GeV, 75.0, 85.0)) { 00205 MSG_DEBUG("W found with mass " << W.mass()/GeV << " GeV"); 00206 _h_t_mass_W_cut->fill(t1.mass(), weight); 00207 _h_t_mass_W_cut->fill(t2.mass(), weight); 00208 00209 _h_jetb_1_jetb_2_dR->fill(deltaR(bjets[0].momentum(), bjets[1].momentum()),weight); 00210 _h_jetb_1_jetb_2_deta->fill(fabs(bjets[0].eta()-bjets[1].eta()),weight); 00211 _h_jetb_1_jetb_2_dphi->fill(deltaPhi(bjets[0].momentum(),bjets[1].momentum()),weight); 00212 00213 _h_jetb_1_jetl_1_dR->fill(deltaR(bjets[0].momentum(), ljets[0].momentum()),weight); 00214 _h_jetb_1_jetl_1_deta->fill(fabs(bjets[0].eta()-ljets[0].eta()),weight); 00215 _h_jetb_1_jetl_1_dphi->fill(deltaPhi(bjets[0].momentum(),ljets[0].momentum()),weight); 00216 00217 _h_jetl_1_jetl_2_dR->fill(deltaR(ljets[0].momentum(), ljets[1].momentum()),weight); 00218 _h_jetl_1_jetl_2_deta->fill(fabs(ljets[0].eta()-ljets[1].eta()),weight); 00219 _h_jetl_1_jetl_2_dphi->fill(deltaPhi(ljets[0].momentum(),ljets[1].momentum()),weight); 00220 00221 _h_jetb_1_W_dR->fill(deltaR(bjets[0].momentum(), W),weight); 00222 _h_jetb_1_W_deta->fill(fabs(bjets[0].eta()-W.eta()),weight); 00223 _h_jetb_1_W_dphi->fill(deltaPhi(bjets[0].momentum(),W),weight); 00224 00225 FourMomentum l=lfs.chargedLeptons()[0].momentum(); 00226 _h_jetb_1_l_dR->fill(deltaR(bjets[0].momentum(), l),weight); 00227 _h_jetb_1_l_deta->fill(fabs(bjets[0].eta()-l.eta()),weight); 00228 _h_jetb_1_l_dphi->fill(deltaPhi(bjets[0].momentum(),l),weight); 00229 _h_jetb_1_l_mass->fill(FourMomentum(bjets[0].momentum()+l).mass(), weight); 00230 } 00231 00232 } 00233 00234 00235 void finalize() { 00236 normalize(_h_njets); 00237 normalize(_h_jet_1_pT); 00238 normalize(_h_jet_2_pT); 00239 normalize(_h_jet_3_pT); 00240 normalize(_h_jet_4_pT); 00241 normalize(_h_jet_HT); 00242 normalize(_h_bjet_1_pT); 00243 normalize(_h_bjet_2_pT); 00244 normalize(_h_ljet_1_pT); 00245 normalize(_h_ljet_2_pT); 00246 normalize(_h_W_mass); 00247 normalize(_h_t_mass); 00248 normalize(_h_t_mass_W_cut); 00249 normalize(_h_jetb_1_jetb_2_dR); 00250 normalize(_h_jetb_1_jetb_2_deta); 00251 normalize(_h_jetb_1_jetb_2_dphi); 00252 normalize(_h_jetb_1_jetl_1_dR); 00253 normalize(_h_jetb_1_jetl_1_deta); 00254 normalize(_h_jetb_1_jetl_1_dphi); 00255 normalize(_h_jetl_1_jetl_2_dR); 00256 normalize(_h_jetl_1_jetl_2_deta); 00257 normalize(_h_jetl_1_jetl_2_dphi); 00258 normalize(_h_jetb_1_W_dR); 00259 normalize(_h_jetb_1_W_deta); 00260 normalize(_h_jetb_1_W_dphi); 00261 normalize(_h_jetb_1_l_dR); 00262 normalize(_h_jetb_1_l_deta); 00263 normalize(_h_jetb_1_l_dphi); 00264 normalize(_h_jetb_1_l_mass); 00265 } 00266 00267 //@} 00268 00269 00270 private: 00271 00272 // @name Histogram data members 00273 //@{ 00274 00275 Histo1DPtr _h_njets; 00276 Histo1DPtr _h_jet_1_pT, _h_jet_2_pT, _h_jet_3_pT, _h_jet_4_pT; 00277 Histo1DPtr _h_jet_HT; 00278 Histo1DPtr _h_bjet_1_pT, _h_bjet_2_pT; 00279 Histo1DPtr _h_ljet_1_pT, _h_ljet_2_pT; 00280 Histo1DPtr _h_W_mass; 00281 Histo1DPtr _h_t_mass, _h_t_mass_W_cut; 00282 Histo1DPtr _h_jetb_1_jetb_2_dR, _h_jetb_1_jetb_2_deta, _h_jetb_1_jetb_2_dphi; 00283 Histo1DPtr _h_jetb_1_jetl_1_dR, _h_jetb_1_jetl_1_deta, _h_jetb_1_jetl_1_dphi; 00284 Histo1DPtr _h_jetl_1_jetl_2_dR, _h_jetl_1_jetl_2_deta, _h_jetl_1_jetl_2_dphi; 00285 Histo1DPtr _h_jetb_1_W_dR, _h_jetb_1_W_deta, _h_jetb_1_W_dphi; 00286 Histo1DPtr _h_jetb_1_l_dR, _h_jetb_1_l_deta, _h_jetb_1_l_dphi,_h_jetb_1_l_mass; 00287 00288 00289 //@} 00290 00291 }; 00292 00293 00294 00295 // The hook for the plugin system 00296 DECLARE_RIVET_PLUGIN(MC_TTBAR); 00297 00298 } Generated on Fri Oct 25 2013 12:41:46 for The Rivet MC analysis system by ![]() |