rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

ATLAS_2019_I1759875

dileptonic ttbar at 13 TeV
Experiment: ATLAS (LHC)
Inspire ID: 1759875
Status: VALIDATED
Authors:
  • Richard Hawkings
References:
  • Eur.Phys.J.C 80 (2020) 6, 528
Beams: p+ p+
Beam energies: (6500.0, 6500.0) GeV
Run details:
  • dileptonic top-quark pair production

The inclusive top quark pair ($t\bar{t}$) production cross-section $\sigma_{t\bar{t}}$ has been measured in proton-proton collisions at $\sqrt{s}=13$ TeV, using 36.1 fb$^{-1}$ of data collected in 2015-2016 by the ATLAS experiment at the LHC. Using events with an opposite-charge $e\mu$ pair and $b$-tagged jets, the cross-section is measured to be: $\sigma_{t\bar{t}} = 826.4 \pm 3.6$ (stat) $\pm 11.5$ (syst) $\pm 15.7$ (lumi) $\pm 1.9$ (beam) pb, where the uncertainties reflect the limited size of the data sample, experimental and theoretical systematic effects, the integrated luminosity, and the LHC beam energy, giving a total uncertainty of 2.4%. The result is consistent with theoretical QCD calculations at next-to-next-to-leading order. It is used to determine the top quark pole mass via the dependence of the predicted cross-section on $m_t^{\mathrm{pole}}$, giving $m_t^{\mathrm{pole}}=173.1^{+2.0}_{-2.1}$ GeV. It is also combined with measurements at $\sqrt{s}=7$ TeV and $\sqrt{s}=8$ TeV to derive ratios and double ratios of $t\bar{t}$ and $Z$ cross-sections at different energies. The same event sample is used to measure absolute and normalised differential cross-sections as functions of single-lepton and dilepton kinematic variables, and the results are compared with predictions from various Monte Carlo event generators.

Source code: ATLAS_2019_I1759875.cc
  1#include "Rivet/Analysis.hh"
  2#include "Rivet/Projections/VetoedFinalState.hh"
  3#include "Rivet/Projections/IdentifiedFinalState.hh"
  4#include "Rivet/Projections/PromptFinalState.hh"
  5#include "Rivet/Projections/DressedLeptons.hh"
  6#include "Rivet/Tools/BinnedHistogram.hh"
  7
  8namespace Rivet {
  9
 10  /// @brief lepton differential ttbar analysis at 13 TeV
 11  class ATLAS_2019_I1759875 : public Analysis {
 12  public:
 13    
 14    RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2019_I1759875);
 15    
 16    void init() {
 17
 18      Cut eta_full = Cuts::abseta < 5.0 && Cuts::pT > 1.0*MeV;
 19
 20      // All final state particles
 21      const FinalState fs;
 22
 23      // Get photons to dress leptons
 24      IdentifiedFinalState photons(fs);
 25      photons.acceptIdPair(PID::PHOTON);
 26
 27      // Projection to find the electrons
 28      PromptFinalState prompt_el(Cuts::abspid == PID::ELECTRON, true);
 29      DressedLeptons elecs(photons, prompt_el, 0.1, (Cuts::abseta < 2.5) && (Cuts::pT > 20*GeV));
 30      DressedLeptons veto_elecs(photons, prompt_el, 0.1, eta_full, false);
 31      declare(elecs, "elecs");
 32
 33      // Projection to find the muons
 34      PromptFinalState prompt_mu(Cuts::abspid == PID::MUON, true);
 35      DressedLeptons muons(photons, prompt_mu, 0.1, (Cuts::abseta < 2.5) && (Cuts::pT > 20*GeV));
 36      DressedLeptons veto_muons(photons, prompt_mu, 0.1, eta_full, false);
 37      declare(muons, "muons");
 38
 39      VetoedFinalState vfs;
 40      vfs.addVetoOnThisFinalState(veto_elecs);
 41      vfs.addVetoOnThisFinalState(veto_muons);
 42
 43      // Book histograms
 44      bookHistos("lep_pt",       1);
 45      bookHistos("lep_eta",      3);
 46      bookHistos("dilep_pt",     5);
 47      bookHistos("dilep_mass",   7);
 48      bookHistos("dilep_rap",    9);
 49      bookHistos("dilep_dphi",  11);
 50      bookHistos("dilep_sumpt", 13);
 51      bookHistos("dilep_sumE",  15);
 52
 53      // unrolled 2D distributions - 2nd-dim bin edges must be specified
 54      std::vector<double> massbins={0.,80.,120.,200.,500.};
 55      
 56      bookHisto2D("lep_eta_mass",17,massbins);
 57      bookHisto2D("dilep_rap_mass",19,massbins);
 58      bookHisto2D("dilep_dphi_mass",21,massbins);
 59    }
 60
 61    void analyze(const Event& event) {
 62      vector<DressedLepton> elecs = apply<DressedLeptons>(event, "elecs").dressedLeptons();
 63      vector<DressedLepton> muons = apply<DressedLeptons>(event, "muons").dressedLeptons();
 64
 65      if (elecs.empty() || muons.empty())  vetoEvent;
 66      if (elecs[0].charge() == muons[0].charge())  vetoEvent;  
 67 
 68      FourMomentum el = elecs[0].momentum();
 69      FourMomentum mu = muons[0].momentum();
 70      FourMomentum ll = elecs[0].momentum() + muons[0].momentum();
 71                  
 72      // Fill histograms
 73      // include explicit overflow protection as last bins are inclusive
 74      fillHistos("lep_pt",      min(el.pT()/GeV,299.));
 75      fillHistos("lep_pt",      min(mu.pT()/GeV,299.));
 76      fillHistos("lep_eta",     el.abseta());
 77      fillHistos("lep_eta",     mu.abseta());
 78      fillHistos("dilep_pt",    min(ll.pT()/GeV,299.));
 79      fillHistos("dilep_mass",  min(ll.mass()/GeV,499.));
 80      fillHistos("dilep_rap",   ll.absrap());
 81      fillHistos("dilep_dphi",  deltaPhi(el, mu));
 82      fillHistos("dilep_sumpt", min((el.pT()+mu.pT())/GeV,399.));
 83      fillHistos("dilep_sumE",  min((el.E()+mu.E())/GeV,699.));
 84
 85      // find mass bin variable, with overflow protection
 86      float massv=ll.mass()/GeV;
 87      if (massv>499.) massv=499.;
 88      // Fill unrolled 2D histograms vs mass
 89      fillHisto2D("lep_eta_mass",el.abseta(),massv);
 90      fillHisto2D("lep_eta_mass",mu.abseta(),massv);
 91      fillHisto2D("dilep_rap_mass",ll.absrap(),massv);
 92      fillHisto2D("dilep_dphi_mass",deltaPhi(el,mu),massv);
 93    }
 94
 95    void finalize() {
 96      // Normalize to cross-section
 97      const double sf = crossSection()/femtobarn/sumOfWeights();
 98
 99      // finalisation of 1D histograms
100      for (auto& hist : _h) {
101        const double norm = 1.0 / hist.second->integral();
102        // histogram normalisation
103        if (hist.first.find("norm") != string::npos)  scale(hist.second, norm);
104        else  scale(hist.second, sf);
105      }
106
107      // finalisation of 2D histograms
108      for (auto& hist : _h_multi) {
109        if (hist.first.find("_norm") != std::string::npos) {
110          // scaling for normalised distribution according integral of whole set
111          double norm2D = integral2D(hist.second);
112          hist.second.scale(1./norm2D, this);
113        }
114        else {
115          // scaling for non-normalised distribution
116          hist.second.scale(sf, this);
117        }
118      }
119    }
120
121
122  private:
123
124    /// @name Histogram helper functions
125    //@{
126    void bookHistos(const std::string name, unsigned int index) {
127      book(_h[name], index, 1, 1);
128      book(_h["norm_" + name],index + 1, 1, 1);
129    }
130
131    void fillHistos(const std::string name, double value) {
132      _h[name]->fill(value);
133      _h["norm_" + name]->fill(value);
134    }
135
136    void bookHisto2D(const std::string name, unsigned int index, std::vector<double> massbins) {
137      unsigned int nmbins = massbins.size()-1;
138      for (unsigned int i=0; i < nmbins; ++i) {
139	{ Histo1DPtr tmp; _h_multi[name].add(massbins[i], massbins[i+1], book(tmp, index,1,1+i)); }
140	const std::string namen = name+"_norm";
141	{ Histo1DPtr tmp; _h_multi[namen].add(massbins[i], massbins[i+1], book(tmp, index+1,1,1+i)); }
142      }
143    }
144
145
146
147    void fillHisto2D(const std::string name,
148		     double val, double massval) {
149      _h_multi[name].fill(massval, val);
150      _h_multi[name+"_norm"].fill(massval, val);
151    }
152
153
154    double integral2D(BinnedHistogram& h_multi) {
155        double total_integral = 0;
156        for  (Histo1DPtr& h : h_multi.histos()) {
157          total_integral += h->integral(false);
158        }
159        return total_integral;
160      }
161
162
163    // pointers to 1D and 2D histograms
164    map<string, Histo1DPtr> _h;
165    map<string, BinnedHistogram> _h_multi;
166    //@}
167    // acceptance counter
168
169  };
170
171  // Declare the class as a hook for the plugin system
172  RIVET_DECLARE_PLUGIN(ATLAS_2019_I1759875);
173}