Rivet analyses


title: ATLAS_2024_I2791854

Jet cross-section ratios at 13 TeV

Experiment: ATLAS (LHC)

Inspire ID: 2791854

Status: VALIDATED

Authors: - Jennifer Roloff

References: - Expt page: ATLAS-STDM-2020-04 - arXiv: 2405.20206

Beams: p+ p+

Beam energies: (6500.0, 6500.0)GeV

Run details: - pp -> jets

Measurements of jet cross-section ratios between inclusive bins of jet multiplicity are performed in 140 fb$^{-1}$ of proton--proton collisions with $\sqrt{s}$=13 TeV center-of-mass energy, recorded with the ATLAS detector at CERN's Large Hadron Collider. Observables that are sensitive the energy-scale and angular distribution of radiation due to the strong interaction in the final state are measured double-differentially, in bins of jet multiplicity, and are unfolded to account for acceptance and detector-related effects. Additionally, the scalar sum of the two leading jets' transverse momenta is measured triple-differentially, in bins of the third jet's transverse momentum as well as bins of jet multiplicity. The measured distributions are used to construct ratios of the inclusive jet-multiplicity bins, which have been shown to be sensitive to the strong coupling $\alpha_\text{s}$ while being less sensitive than other observables to systematic uncertainties and parton distribution functions. The measured distributions are compared with state-of-the-art QCD calculations, including next-to-next-to-leading-order predictions. Studies leading to reduced jet energy scale uncertainties significantly improve the precision of this work, and are documented herein.

Source code:ATLAS_2024_I2791854.cc

```c++ // -- C++ --

include "Rivet/Analysis.hh"

include "Rivet/Projections/FastJets.hh"

include "Rivet/Projections/FinalState.hh"

include "Rivet/Tools/HistoGroup.hh"

namespace Rivet {

/// @brief Jet cross-section ratios at 13 TeV class ATLAS_2024_I2791854 : public Analysis { public:

/// Constructor
RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2024_I2791854);


double maxDY(const Jets& jets) const {
  double biggest_y_gap = 0;
  for (size_t iJet = 0; iJet < jets.size(); ++iJet) {
    for (size_t jJet = iJet + 1; jJet < jets.size(); ++jJet) {
      double y_gap = std::abs(jets[iJet].rap() - jets[jJet].rap());
      if (y_gap > biggest_y_gap) {
        biggest_y_gap = y_gap;
      }
    }
  }
  return biggest_y_gap;
}

double maxMjj(const Jets& jets) const {
  double maxMass = 0;
  for (size_t iJet = 0; iJet < jets.size(); ++iJet) {
    for (size_t jJet = iJet + 1; jJet < jets.size(); ++jJet) {
      double mass = (jets[iJet].mom() + jets[jJet].mom()).mass();
      if (mass > maxMass) {
        maxMass = mass;
      }
    }
  }
  return maxMass;
}


/// @name Analysis methods
/// @{

/// Book histograms and initialise projections before the run
void init() {

  // Initialise and register projections
  const FinalState fs(Cuts::abseta < 4.9);

  // The final-state particles declared above are clustered using FastJet with
  // the anti-kT algorithm and a jet-radius parameter 0.4
  // muons and neutrinos are excluded from the clustering
  FastJets jet4(fs, JetAlg::ANTIKT, 0.4, JetMuons::NONE, JetInvisibles::NONE);
  declare(jet4, "Jets");

  // booking pT3-binned HT2 results
  for (size_t pt3bin = 0; pt3bin < _pt3_cuts.size(); ++pt3bin) {
    HistoGroupPtr<int, double> tmp;
    _ht2.emplace_back(book(tmp, {2, 3, 4, 5}));
    for (auto& b : _ht2[pt3bin]->bins()) {
      book(b, 33 + b.index() + 4 * pt3bin, 1, 1);
    }
  }

  // booking all other results
  for (size_t njet = 0; njet < 4; ++njet) {
    Histo1DPtr tmp;
    size_t hid = 54 + njet;

    if (njet < 3) {
      _h_ptjet.emplace_back(book(tmp, hid, 1, 1));
    }

    hid += 3;
    _h_mjjmax.emplace_back(book(tmp, hid, 1, 1));

    hid += 4;
    _h_mjj.emplace_back(book(tmp, hid, 1, 1));

    hid += 4;
    _h_dy.emplace_back(book(tmp, hid, 1, 1));

    hid += 4;
    _h_dymax.emplace_back(book(tmp, hid, 1, 1));
  }
}


/// Perform the per-event analysis
void analyze(const Event& event) {


  // Retrieve clustered jets, sorted by pT, with a minimum pT cut
  const Jets jets = apply<FastJets>(event, "Jets").jetsByPt(Cuts::pT > 60 * GeV && Cuts::abseta < 4.5);

  if (jets.size() < 2) vetoEvent; // Dijet events

  const double mjj = (jets[0].mom() + jets[1].mom()).mass();
  const double mjjmax = maxMjj(jets);
  const double dy = std::abs(jets[0].rap() - jets[1].rap());
  const double dymax = maxDY(jets);
  const double ht2 = jets[0].pt() + jets[1].pt();

  if (ht2 < 250) vetoEvent;

  const double pt3 = jets.size() > 2 ? jets[2].pt() : 0.0;
  for (size_t nj = std::min(5ul, jets.size()); nj >= 2; --nj) {
    for (size_t pt3bin = 0; pt3bin < _pt3_cuts.size(); ++pt3bin) {
      if (nj > 2 && pt3 < _pt3_cuts[pt3bin] * ht2) continue;
      _ht2[pt3bin]->fill(nj, ht2);
    }
    _h_mjj[nj - 2]->fill(mjj / GeV);
    _h_mjjmax[nj - 2]->fill(mjjmax / GeV);
    _h_dy[nj - 2]->fill(dy);
    _h_dymax[nj - 2]->fill(dymax);
  }

  size_t jetSize = jets.size();
  for (size_t j = 0; j < 3; ++j) {
    for (int i = std::min(j + 1, jetSize - 1); i >= 0; --i) {
      _h_ptjet[j]->fill(jets[i].pt() / GeV);
    }
  }
}

/// Normalise histograms etc., after the run
void finalize() {
  const double sf = crossSectionPerEvent();
  scale(_ht2, sf);
  scale(_h_dy, sf);
  scale(_h_dymax, sf);
  scale(_h_mjj, sf);
  scale(_h_mjjmax, sf);
  scale(_h_ptjet, sf);

  Estimate1DPtr ratio;
  for (size_t ir = 0; ir < 4; ++ir) {
    size_t hid = 10 * ir + 6;
    // Temporary hack for missing hepdata
    if (ir == 1) hid = 10 + 4;
    if (ir == 2) hid = 18 + 3;
    if (ir == 3) hid = 25 + 4;

    if (ir < 2) {
      book(ratio, hid, 1, 1);
      divide(_h_ptjet[ir + 1], _h_ptjet[ir], ratio);
    }

    book(ratio, ++hid, 1, 1);
    divide(_h_dy[ir == 3 ? 2 : ir + 1], _h_dy[ir == 3 ? 0 : ir], ratio);

    book(ratio, ++hid, 1, 1);
    divide(_h_dymax[ir == 3 ? 2 : ir + 1], _h_dymax[ir == 3 ? 0 : ir], ratio);

    book(ratio, ++hid, 1, 1);
    divide(_h_mjj[ir == 3 ? 2 : ir + 1], _h_mjj[ir == 3 ? 0 : ir], ratio);

    book(ratio, ++hid, 1, 1);
    divide(_h_mjjmax[ir == 3 ? 2 : ir + 1], _h_mjjmax[ir == 3 ? 0 : ir], ratio);
  }

  for (size_t pt3bin = 0; pt3bin < _pt3_cuts.size(); ++pt3bin) {
    for (size_t ir = 0; ir < 4; ++ir) {
      size_t hid = pt3bin + 10 * ir + 1;
      if (ir == 2) hid = pt3bin + 10 + 8 + 1;
      if (ir == 3) hid = pt3bin + 10 + 8 + 7 + 1;

      if ((pt3bin == 1 || pt3bin == 3) && ir > 0) continue;
      if (ir > 0 && pt3bin == 2) hid -= 1;
      if (ir > 0 && pt3bin == 4) hid -= 2;

      book(ratio, hid, 1, 1);
      MSG_DEBUG("ratio HT2: " << hid << " for pt3bin = " << pt3bin << " and ir = " << ir);
      divide(_ht2[pt3bin]->bin(ir == 3 ? 3 : ir + 2), _ht2[pt3bin]->bin(ir == 3 ? 1 : ir + 1), ratio);
    }
  }
}

/// @name Histograms
/// @{

// for pT-inclusive histograms
vector<HistoGroupPtr<int, double>> _ht2;
vector<Histo1DPtr> _h_dymax, _h_dy, _h_mjjmax, _h_mjj, _h_ptjet;

const vector<double> _pt3_cuts{0.0, 0.05, 0.1, 0.2, 0.3};

/// @}

};

RIVET_DECLARE_PLUGIN(ATLAS_2024_I2791854);

} ```