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