Rivet analyses


title: ATLAS_2019_I1759875

dileptonic ttbar at 13 TeV

Experiment: ATLAS (LHC)

Inspire ID: 1759875

Status: VALIDATED

Authors: - Richard Hawkings

References: - Expt page: ATLAS-TOPQ-2018-17 - 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

```c++

include "Rivet/Analysis.hh"

include "Rivet/Projections/IdentifiedFinalState.hh"

include "Rivet/Projections/LeptonFinder.hh"

include "Rivet/Projections/PromptFinalState.hh"

include "Rivet/Projections/VetoedFinalState.hh"

namespace Rivet {

/// @brief Lepton differential ttbar analysis at 13 TeV class ATLAS_2019_I1759875 : public Analysis { public:

RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2019_I1759875);

void init() {

  Cut eta_full = Cuts::abseta < 5.0 && Cuts::pT > 1.0 * MeV;

  // Get photons to dress leptons
  PromptFinalState photons(Cuts::pid == PID::PHOTON);

  // Projection to find the electrons
  PromptFinalState prompt_el(Cuts::abspid == PID::ELECTRON, TauDecaysAs::PROMPT);
  LeptonFinder elecs(prompt_el, photons, 0.1, Cuts::abseta < 2.5 && Cuts::pT > 20 * GeV);
  LeptonFinder veto_elecs(prompt_el, photons, 0.1, eta_full);
  declare(elecs, "elecs");

  // Projection to find the muons
  PromptFinalState prompt_mu(Cuts::abspid == PID::MUON, TauDecaysAs::PROMPT);
  LeptonFinder muons(prompt_mu, photons, 0.1, Cuts::abseta < 2.5 && Cuts::pT > 20 * GeV);
  LeptonFinder veto_muons(prompt_mu, photons, 0.1, eta_full);
  declare(muons, "muons");

  VetoedFinalState vfs;
  vfs.addVetoOnThisFinalState(veto_elecs);
  vfs.addVetoOnThisFinalState(veto_muons);

  // Book histograms
  bookHistos("lep_pt", 1);
  bookHistos("lep_eta", 3);
  bookHistos("dilep_pt", 5);
  bookHistos("dilep_mass", 7);
  bookHistos("dilep_rap", 9);
  bookHistos("dilep_dphi", 11);
  bookHistos("dilep_sumpt", 13);
  bookHistos("dilep_sumE", 15);

  // unrolled 2D distributions - 2nd-dim bin edges must be specified
  std::vector<double> massbins = {0., 80., 120., 200., 500.};

  bookHisto2D("lep_eta_mass", 17, massbins);
  bookHisto2D("dilep_rap_mass", 19, massbins);
  bookHisto2D("dilep_dphi_mass", 21, massbins);
}

void analyze(const Event& event) {
  DressedLeptons elecs = apply<LeptonFinder>(event, "elecs").dressedLeptons();
  DressedLeptons muons = apply<LeptonFinder>(event, "muons").dressedLeptons();

  if (elecs.empty() || muons.empty()) vetoEvent;
  if (elecs[0].charge() == muons[0].charge()) vetoEvent;

  FourMomentum el = elecs[0].momentum();
  FourMomentum mu = muons[0].momentum();
  FourMomentum ll = elecs[0].momentum() + muons[0].momentum();

  // Fill histograms
  // include explicit overflow protection as last bins are inclusive
  fillHistos("lep_pt", min(el.pT() / GeV, 299.));
  fillHistos("lep_pt", min(mu.pT() / GeV, 299.));
  fillHistos("lep_eta", el.abseta());
  fillHistos("lep_eta", mu.abseta());
  fillHistos("dilep_pt", min(ll.pT() / GeV, 299.));
  fillHistos("dilep_mass", min(ll.mass() / GeV, 499.));
  fillHistos("dilep_rap", ll.absrap());
  fillHistos("dilep_dphi", deltaPhi(el, mu));
  fillHistos("dilep_sumpt", min((el.pT() + mu.pT()) / GeV, 399.));
  fillHistos("dilep_sumE", min((el.E() + mu.E()) / GeV, 699.));

  // find mass bin variable, with overflow protection
  float massv = ll.mass() / GeV;
  if (massv > 499.) massv = 499.;
  // Fill unrolled 2D histograms vs mass
  fillHisto2D("lep_eta_mass", el.abseta(), massv);
  fillHisto2D("lep_eta_mass", mu.abseta(), massv);
  fillHisto2D("dilep_rap_mass", ll.absrap(), massv);
  fillHisto2D("dilep_dphi_mass", deltaPhi(el, mu), massv);
}

void finalize() {
  // Normalize to cross-section
  const double sf = crossSection() / femtobarn / sumOfWeights();

  // finalisation of 1D histograms
  for (auto& hist : _h) {
    const double norm = 1.0 / hist.second->integral();
    // histogram normalisation
    if (hist.first.find("norm") != string::npos)
      scale(hist.second, norm);
    else
      scale(hist.second, sf);
  }

  // finalisation of 2D histograms
  for (auto& hist : _h_multi) {
    if (hist.first.find("_norm") != std::string::npos) {
      // scaling for normalised distribution according integral of whole set
      hist.second->normalizeGroup(1.0, false);
    }
    else {
      // scaling for non-normalised distribution
      scale(hist.second, sf);
    }
  }
  divByGroupWidth(_h_multi);
}

private:

/// @name Histogram helper functions
/// @{
void bookHistos(const std::string name, unsigned int index) {
  book(_h[name], index, 1, 1);
  book(_h["norm_" + name], index + 1, 1, 1);
}

void fillHistos(const std::string name, double value) {
  _h[name]->fill(value);
  _h["norm_" + name]->fill(value);
}

void bookHisto2D(const std::string& name, unsigned int index, const std::vector<double>& massbins) {
  book(_h_multi[name], massbins);
  book(_h_multi[name + "_norm"], massbins);
  for (size_t i = 1; i < _h_multi[name]->numBins() + 1; ++i) {
    book(_h_multi[name]->bin(i), index, 1, i);
    book(_h_multi[name + "_norm"]->bin(i), index + 1, 1, i);
  }
}


void fillHisto2D(const std::string& name, double val, double massval) {
  _h_multi[name]->fill(massval, val);
  _h_multi[name + "_norm"]->fill(massval, val);
}


// pointers to 1D and 2D histograms
map<string, Histo1DPtr> _h;
map<string, Histo1DGroupPtr> _h_multi;
/// @}
// acceptance counter

};

RIVET_DECLARE_PLUGIN(ATLAS_2019_I1759875); } ```