Rivet analyses


title: ATLAS_2023_I2648096

dileptonic ttbar at 13 TeV

Experiment: ATLAS (LHC)

Inspire ID: 2648096

Status: VALIDATED

Authors: - Christian Gutschow

References: - Expt page: ATLAS-TOPQ-2018-26 - JHEP 07 (2023) 141 - arXiv: 2303.15340

Beams: p+ p+

Beam energies: (6500.0, 6500.0)GeV

Run details: - dileptonic top-quark pair production

Differential and double-differential distributions of kinematic variables of leptons from decays of top-quark pairs ($t\bar{t}$) are measured using the full LHC Run 2 data sample collected with the ATLAS detector. The data were collected at a pp collision energy of $\sqrt{s}=13$ TeV and correspond to an integrated luminosity of 140 fb$^{-1}$. The measurements use events containing an oppositely charged $e\mu$ pair and $b$-tagged jets. The results are compared with predictions from several Monte Carlo generators. While no prediction is found to be consistent with all distributions, a better agreement with measurements of the lepton $p_\text{T}$ distributions is obtained by reweighting the $t\bar{t}$ sample so as to reproduce the top-quark $p_\text{T}$ distribution from an NNLO calculation. The inclusive top-quark pair production cross-section is measured as well, both in a fiducial region and in the full phase-space. The total inclusive cross-section is found to be $\sigma_{t\bar{t}$ = 829\pm 1\text{(stat)}\pm 13\text{(syst)}\pm 8\text{(lumi)}\pm 2\text{(beam)}$ pb, where the uncertainties are due to statistics, systematic effects, the integrated luminosity and the beam energy. This is in excellent agreement with the theoretical expectation.

Source code:ATLAS_2023_I2648096.cc

```c++

include "Rivet/Analysis.hh"

include "Rivet/Projections/FastJets.hh"

include "Rivet/Projections/InvisibleFinalState.hh"

include "Rivet/Projections/LeptonFinder.hh"

include "Rivet/Projections/PromptFinalState.hh"

include "Rivet/Projections/VetoedFinalState.hh"

include "Rivet/Tools/HistoGroup.hh"

namespace Rivet {

/// @brief lepton differential ttbar analysis at 13 TeV class ATLAS_2023_I2648096 : public Analysis { public:

RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2023_I2648096);

void init() {

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

  // Get photons to dress leptons
  FinalState photons(Cuts::abspid == 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 > 25 * 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 > 25 * GeV));
  LeptonFinder veto_muons(prompt_mu, photons, 0.1, eta_full);
  declare(muons, "muons");

  const InvisibleFinalState invis(OnlyPrompt::YES, TauDecaysAs::PROMPT);
  VetoedFinalState vfs;
  vfs.addVetoOnThisFinalState(veto_elecs);
  vfs.addVetoOnThisFinalState(veto_muons);
  vfs.addVetoOnThisFinalState(invis);
  FastJets jets(vfs, JetAlg::ANTIKT, 0.4, JetMuons::ALL, JetInvisibles::ALL);
  declare(jets, "jets");

  // Book histograms
  bookHistos("lep_pt", 6);
  bookHistos("lep_eta", 9);
  bookHistos("dilep_sumE", 12);
  bookHistos("dilep_mass", 15);
  bookHistos("dilep_sumpt", 18);
  bookHistos("dilep_pt", 21);
  bookHistos("dilep_dphi", 24);
  bookHistos("dilep_rap", 27);

  // unrolled 2D distributions - 2nd-dim bin edges must be specified
  const vector<double> b_mass_2D = {0., 70., 100., 130., 200., 800.};
  const vector<double> b_pt_2D = {0., 40., 65., 100.};
  const vector<double> b_sumE_2D = {0., 110., 140., 200., 250., 900.};

  bookHisto2D("dilep_rap_mass", 78, b_mass_2D);
  bookHisto2D("dilep_dphi_mass", 79, b_mass_2D);
  bookHisto2D("dilep_dphi_pt", 80, b_pt_2D);
  bookHisto2D("dilep_dphi_sumE", 81, b_sumE_2D);
}

void analyze(const Event& event) {
  DressedLeptons elecs = apply<LeptonFinder>(event, "elecs").dressedLeptons();
  DressedLeptons muons = apply<LeptonFinder>(event, "muons").dressedLeptons();
  Jets jets = apply<FastJets>(event, "jets").jetsByPt(Cuts::pT > 25 * GeV && Cuts::abseta < 2.5);

  // Check overlap of jets/leptons.
  for (const Jet& jet : jets) {
    idiscard(elecs, deltaRLess(jet, 0.4));
    idiscard(muons, deltaRLess(jet, 0.4));
  }
  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();

  if (max(el.pT(), mu.pT()) < 27 * GeV) vetoEvent;

  const double dphi = deltaPhi(el, mu);
  const double drap = ll.absrap();
  const double pt = ll.pT() / GeV;
  const double sumE = min((el.E() + mu.E()) / GeV, 899);
  const double mass = min(ll.mass() / GeV, 799.);

  // Fill histograms
  // include explicit overflow protection as last bins are inclusive
  fillHistos("lep_pt", min(el.pT() / GeV, 349.));
  fillHistos("lep_pt", min(mu.pT() / GeV, 349.));
  fillHistos("lep_eta", el.abseta());
  fillHistos("lep_eta", mu.abseta());
  fillHistos("dilep_pt", min(pt, 299.));
  fillHistos("dilep_mass", mass);
  fillHistos("dilep_rap", drap);
  fillHistos("dilep_dphi", dphi);
  fillHistos("dilep_sumpt", min((el.pT() + mu.pT()) / GeV, 599));
  fillHistos("dilep_sumE", sumE);

  // Fill unrolled 2D histograms vs mass
  fillHisto2D("dilep_rap_mass", mass, drap);
  fillHisto2D("dilep_dphi_mass", mass, dphi);
  fillHisto2D("dilep_dphi_pt", min(pt, 99.), dphi);
  fillHisto2D("dilep_dphi_sumE", sumE, dphi);
}

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) {
      const double sf = safediv(1.0, hist.second->integral(false));
      scale(hist.second, sf);
    }
    else {
      scale(hist.second, sf);
    }
    divByGroupWidth(hist.second);
  }
}

private:

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

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

void bookHisto2D(const string& name, const unsigned int id, const vector<double>& axis1) {
  book(_h_multi[name], axis1);
  book(_h_multi[name + "_norm"], axis1);
  for (size_t i = 1; i < axis1.size(); ++i) {
    book(_h_multi[name]->bin(i), id, 1, i);
    book(_h_multi[name + "_norm"]->bin(i), id + 4, 1, i);
  }
}


void fillHisto2D(const string& name, const double val1, const double val2) {
  _h_multi[name]->fill(val1, val2);
  _h_multi[name + "_norm"]->fill(val1, val2);
}


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

};

// Declare the class as a hook for the plugin system RIVET_DECLARE_PLUGIN(ATLAS_2023_I2648096); } ```