rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

ATLAS_2018_I1705857

ttbb at 13 TeV
Experiment: ATLAS (LHC)
Inspire ID: 1705857
Status: VALIDATED
Authors:
  • Stewart Swift
  • Tom Neep
  • Christian Gutschow
References: Beams: p+ p+
Beam energies: (6500.0, 6500.0) GeV
Run details:
  • ttbb production at 13 TeV in dilepton and lepton+jets channel

This paper presents measurements of $t\bar{t}$ production in association with additional $b$-jets in $pp$ collisions at the LHC at a centre-of-mass energy of 13 TeV. The data were recorded with the ATLAS detector and correspond to an integrated luminosity of 36.1 fb$^{-1}$. Fiducial cross-section measurements are performed in the dilepton and lepton-plus-jets $t\bar{t}$ decay channels. Results are presented at particle level in the form of inclusive cross-sections of $t\bar{t}$ final states with three and four $b$-jets as well as differential cross-sections as a function of global event properties and properties of $b$-jet pairs. The measured inclusive fiducial cross-sections generally exceed the $t\bar{t}b\bar{b}$ predictions from various next-to-leading-order matrix element calculations matched to a parton shower but are compatible within the total uncertainties. The experimental uncertainties are smaller than the uncertainties in the predictions. Comparisons of state-of-the-art theoretical predictions with the differential measurements are shown and good agreement with data is found for most of them.

Source code: ATLAS_2018_I1705857.cc
  1#include "Rivet/Analysis.hh"
  2#include "Rivet/Projections/FastJets.hh"
  3#include "Rivet/Projections/FinalState.hh"
  4#include "Rivet/Projections/LeptonFinder.hh"
  5#include "Rivet/Projections/PromptFinalState.hh"
  6#include "Rivet/Projections/VetoedFinalState.hh"
  7
  8namespace Rivet {
  9
 10
 11  /// ttbb at 13 TeV
 12  class ATLAS_2018_I1705857 : public Analysis {
 13  public:
 14
 15    /// Constructor
 16    RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2018_I1705857);
 17
 18
 19    void init() {
 20      // Eta ranges
 21      Cut eta_full = (Cuts::abseta < 5.0);
 22      // Lepton cuts
 23      Cut lep_cuts25 = (Cuts::abseta < 2.5) && (Cuts::pT >= 25*GeV);
 24      // All final state particles
 25      FinalState fs(eta_full);
 26
 27      // Get photons to dress leptons
 28      PromptFinalState photons(eta_full && Cuts::abspid == PID::PHOTON, TauDecaysAs::PROMPT);
 29
 30      // Projection to find the electrons
 31      PromptFinalState electrons(eta_full && Cuts::abspid == PID::ELECTRON, TauDecaysAs::PROMPT);
 32
 33      // Projection to find the muons
 34      PromptFinalState muons(eta_full && Cuts::abspid == PID::MUON, TauDecaysAs::PROMPT);
 35
 36      LeptonFinder dressedelectrons25(electrons, photons, 0.1, lep_cuts25);
 37      LeptonFinder dressedmuons25(muons, photons, 0.1, lep_cuts25);
 38
 39      declare(dressedelectrons25, "elecs");
 40      declare(dressedmuons25, "muons");
 41
 42      // From here on we are just setting up the jet clustering
 43      IdentifiedFinalState nu_id;
 44      nu_id.acceptNeutrinos();
 45      PromptFinalState neutrinos(nu_id);
 46      neutrinos.acceptTauDecays(true);
 47
 48      PromptFinalState jet_photons(eta_full && Cuts::abspid == PID::PHOTON, TauDecaysAs::NONPROMPT);
 49      LeptonFinder all_dressed_electrons(electrons, jet_photons, 0.1, eta_full);
 50      LeptonFinder all_dressed_muons(muons, jet_photons, 0.1, eta_full);
 51
 52      VetoedFinalState vfs(fs);
 53      vfs.addVetoOnThisFinalState(all_dressed_electrons);
 54      vfs.addVetoOnThisFinalState(all_dressed_muons);
 55      vfs.addVetoOnThisFinalState(neutrinos);
 56
 57      FastJets jets(vfs, JetAlg::ANTIKT, 0.4, JetMuons::DECAY, JetInvisibles::DECAY);
 58      declare(jets, "jets");
 59
 60      // fiducial cross-section histogram
 61      book(_histograms["fid_xsec"], 1, 1, 1);
 62      book(_histograms["fid_xsec_no_ttX"], 2, 1, 1);
 63
 64      book(_d["nbjets_emu"], 3, 1, 1);
 65      book(_d["nbjets_emu_no_ttX"], 4, 1, 1);
 66
 67      // HT
 68      book_hist("ht_emu", 3);
 69      book_hist("ht_had_emu", 4);
 70
 71      book_hist("ht_ljets", 5);
 72      book_hist("ht_had_ljets", 6);
 73
 74      // b-jet pTs
 75      book_hist("lead_bjet_pt_emu",    7);
 76      book_hist("sublead_bjet_pt_emu", 8);
 77      book_hist("third_bjet_pt_emu",   9);
 78
 79      book_hist("lead_bjet_pt_ljets",    10);
 80      book_hist("sublead_bjet_pt_ljets", 11);
 81      book_hist("third_bjet_pt_ljets",   12);
 82      book_hist("fourth_bjet_pt_ljets",  13);
 83
 84      // leading bb pair
 85      book_hist("m_bb_leading_emu",  14);
 86      book_hist("pt_bb_leading_emu", 15);
 87      book_hist("dR_bb_leading_emu", 16);
 88
 89      book_hist("m_bb_leading_ljets",  17);
 90      book_hist("pt_bb_leading_ljets", 18);
 91      book_hist("dR_bb_leading_ljets", 19);
 92
 93      // closest bb pair
 94      book_hist("m_bb_closest_emu",  20);
 95      book_hist("pt_bb_closest_emu", 21);
 96      book_hist("dR_bb_closest_emu", 22);
 97
 98      book_hist("m_bb_closest_ljets",  23);
 99      book_hist("pt_bb_closest_ljets", 24);
100      book_hist("dR_bb_closest_ljets", 25);
101    }
102
103
104    void analyze(const Event& event) {
105      DressedLeptons leptons;
106      for (auto &lep : apply<LeptonFinder>(event, "muons").dressedLeptons()) { leptons.push_back(lep); }
107      for (auto &lep : apply<LeptonFinder>(event, "elecs").dressedLeptons()) { leptons.push_back(lep); }
108
109      const Jets jets = apply<FastJets>(event, "jets").jetsByPt(Cuts::pT > 25*GeV && Cuts::abseta < 2.5);
110      for (const auto& jet : jets) {
111        idiscard(leptons, [&](const DressedLepton& lep) { return deltaR(jet, lep) < 0.4; });
112      }
113
114      Jets bjets;
115      for (const Jet& jet : jets) {
116        if (jet.bTagged(Cuts::pT >= 5*GeV))  bjets += jet;
117      }
118
119      size_t njets = jets.size();
120      size_t nbjets = bjets.size();
121
122      // Evaluate basic event selection
123      bool pass_ljets = (leptons.size() == 1 && leptons[0].pT() > 27*GeV);
124
125      bool pass_emu =
126        // 2 leptons > 27 GeV
127        (leptons.size() == 2) &&
128        (leptons[0].pT() > 27*GeV && leptons[1].pT() > 27*GeV) &&
129        // emu events
130        ((leptons[0].abspid() == 11 && leptons[1].abspid() == 13) ||
131         (leptons[0].abspid() == 13 && leptons[1].abspid() == 11)) &&
132        // opposite charge
133        (leptons[0].charge() != leptons[1].charge());
134
135      // If we don't have exactly 1 or 2 leptons then veto the event
136      if (!pass_emu && !pass_ljets)  vetoEvent;
137
138      if (pass_emu) {
139        if (nbjets >= 2)  dfill("nbjets_emu", nbjets);
140        if (nbjets >= 3)  fill("fid_xsec", 1);
141        if (nbjets >= 4)  fill("fid_xsec", 2);
142      }
143
144      if (pass_ljets) {
145        if (nbjets >= 3 && njets >= 5)  fill("fid_xsec", 3);
146        if (nbjets >= 4 && njets >= 6)  fill("fid_xsec", 4);
147      }
148
149      if (pass_emu && (nbjets < 3 || njets < 3))    vetoEvent;
150      if (pass_ljets && (nbjets < 4 || njets < 6))  vetoEvent;
151
152      double hthad = sum(jets, Kin::pT, 0.0);
153      double ht = sum(leptons, Kin::pT, hthad);
154
155      FourMomentum jsum = bjets[0].momentum() + bjets[1].momentum();
156      double dr_leading = deltaR(bjets[0], bjets[1]);
157
158      size_t ind1 = 0, ind2 = 0; double mindr = 999.;
159      for (size_t i = 0; i < bjets.size(); ++i) {
160        for (size_t j = 0; j < bjets.size(); ++j) {
161          if (i == j)  continue;
162          double dr = deltaR(bjets[i], bjets[j]);
163          if (dr < mindr) {
164            ind1 = i;
165            ind2 = j;
166            mindr = dr;
167          }
168        }
169      }
170
171      FourMomentum bb_closest = bjets[ind1].momentum() + bjets[ind2].momentum();
172      double dr_closest = deltaR(bjets[ind1], bjets[ind2]);
173
174      if (pass_ljets) {
175        // b-jet pTs
176        fill("lead_bjet_pt_ljets", bjets[0].pT()/GeV);
177        fill("sublead_bjet_pt_ljets", bjets[1].pT()/GeV);
178        fill("third_bjet_pt_ljets", bjets[2].pT()/GeV);
179
180        if (nbjets >= 4)  fill("fourth_bjet_pt_ljets", bjets[3].pT()/GeV);
181
182        // HT
183        fill("ht_ljets", ht/GeV);
184        fill("ht_had_ljets", hthad/GeV);
185
186        // leading bb pair
187        fill("m_bb_leading_ljets", jsum.mass()/GeV);
188        fill("pt_bb_leading_ljets", jsum.pT()/GeV);
189        fill("dR_bb_leading_ljets", dr_leading);
190
191        // closest bb pair
192        fill("m_bb_closest_ljets", bb_closest.mass()/GeV);
193        fill("pt_bb_closest_ljets", bb_closest.pT()/GeV);
194        fill("dR_bb_closest_ljets", dr_closest);
195      }
196      if (pass_emu) {
197        // b-jet pTs
198        fill("lead_bjet_pt_emu", bjets[0].pT()/GeV);
199        fill("sublead_bjet_pt_emu", bjets[1].pT()/GeV);
200        fill("third_bjet_pt_emu", bjets[2].pT()/GeV);
201
202        // HT
203        fill("ht_emu", ht/GeV);
204        fill("ht_had_emu", hthad/GeV);
205
206        // leading bb pair
207        fill("m_bb_leading_emu", jsum.mass()/GeV);
208        fill("pt_bb_leading_emu", jsum.pT()/GeV);
209        fill("dR_bb_leading_emu", dr_leading);
210
211        // closest bb pair
212        fill("m_bb_closest_emu", bb_closest.mass()/GeV);
213        fill("pt_bb_closest_emu", bb_closest.pT()/GeV);
214        fill("dR_bb_closest_emu", dr_closest);
215      }
216    }
217
218    void finalize() {
219      // Normalise all histograms
220      const double sf = crossSection() / femtobarn / sumOfWeights();
221      for (auto& h : _histograms) {
222        scale(h.second, sf);
223        if (h.first.find("fid_xsec") != string::npos)  continue;
224        normalize(h.second, 1.0);
225      }
226      scale(_d, sf);
227      normalize(_d["nbjets_emu"]);
228      normalize(_d["nbjets_emu_no_ttX"]);
229    }
230
231    void fill(const string& name, const double value) {
232      _histograms[name]->fill(value);
233      _histograms[name + "_no_ttX"]->fill(value);
234    }
235
236    void dfill(const string& name, const size_t value) {
237      string edge("OTHER");
238      if (value == 2)  edge = "2";
239      else if (value == 3)  edge = "3";
240      else if (value >= 4)  edge = ">= 4";
241      _d[name]->fill(edge);
242      _d[name + "_no_ttX"]->fill(edge);
243    }
244
245    void book_hist(const std::string& name, unsigned int d) {
246      // ttX substracted histograms are even numbers
247      book(_histograms[name], (d * 2) - 1, 1, 1);
248      book(_histograms[name + "_no_ttX"], d * 2, 1, 1);
249    }
250
251    private:
252      map<std::string, Histo1DPtr> _histograms;
253      map<std::string, BinnedHistoPtr<string>> _d;
254
255  };
256
257  RIVET_DECLARE_PLUGIN(ATLAS_2018_I1705857);
258}