Rivet analyses


title: ALICE_2015_I1395253

Pseudorapidity and transverse-momentum distributions of charged particles in pp collisions at $\sqrt{s} = 13$ TeV

Experiment: ALICE (LHC)

Inspire ID: 1395253

Status: VALIDATED

Authors: - Awais Ahmed

References: - Phys.Lett.B753(2016)319-329 - DOI:10.1016/j.physletb.2015.12.030 - arXiv: 1509.08734

Beams: p+ p+

Beam energies: (6500.0, 6500.0)GeV

Run details: - Measurement of $\mathrm{d}N_{\mathrm{ch}}/\mathrm{d}\eta$ ($|\eta| < 1.8$) and invariant $p_{\mathrm{T}}$ spectra ($|\eta| < 0.8$, $0.15 < p_{\mathrm{T}} < 20$ GeV/$c$) in INEL and INEL${>}0$ pp collisions at $\sqrt{s} = 13$ TeV.

The pseudorapidity ($\eta$) and transverse-momentum ($p_\text{T}$) distributions of charged particles produced in proton-proton collisions are measured at the centre-of-mass energy $\sqrt{S} = 13$ TeV. The pseudorapidity distribution in $|\eta|< 1.8$ is reported for inelastic events and for events with at least one charged particle in $|\eta|< 1$. The pseudorapidity density of charged particles produced in the pseudorapidity region $|\eta|< 0.5$ is $5.31 \pm 0.18$ and $6.46 \pm 0.19$ for the two event classes, respectively. The transverse-momentum distribution of charged particles is measured in the range $0.15 < $p_\mathrm{T}$ < 20$ GeV and $|\eta|< 0.8$ for events with at least one charged particle in $|\eta|< 1$. The correlation between transverse momentum and particle multiplicity is also investigated by studying the evolution of the spectra with event multiplicity. The results are compared with calculations from PYTHIA and EPOS Monte Carlo generators. WARNING: It is unclear whether ALICE applied a 1/pT reweighting per-particle at fill-time, or scaled bin contents post-hoc using a representative bin pT value (bin midpoint), when constructing the invariant pT spectrum (d02/pT_INEL0 and multiplicity-class spectra). Both options are implemented via the PTMODE analysis option (default: XMID). If an ALICE analyser can confirm the correct procedure, we will update this analysis accordingly. For the implementation of PTMODE=PTWEIGHT use rivet -a ALICE_2015_I1395253:PTMODE=PTWEIGHT file.hepmc

Source code:ALICE_2015_I1395253.cc

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

include "Rivet/Analysis.hh"

include "Rivet/Projections/ChargedFinalState.hh"

namespace Rivet {

/// @brief Pseudorapidity and transverse-momentum distributions of charged particles in pp collisions at 13 TeV class ALICE_2015_I1395253 : public Analysis { public:

/// Constructor
RIVET_DEFAULT_ANALYSIS_CTOR(ALICE_2015_I1395253);


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

/// Book histograms and initialise projections before the run
void init() {
  // pT reweighting mode: XMID (default, divide bin content by bin
  // midpoint pT post-hoc) or PTWEIGHT (weight each particle fill by 1/pT at fill-time).
  _ptMode = (getOption("PTMODE") == "PTWEIGHT") ? PTWEIGHT : XMID;

  // INEL trigger: OR of V0A, V0C, ADA, ADC acceptances.
  declare(ChargedFinalState(Cuts::etaIn(2.8, 5.1) || Cuts::etaIn(-3.7, -1.7) || Cuts::etaIn(4.8, 6.3)
                            || Cuts::etaIn(-7.0, -4.9)),
          "TrigCFS");

  // Final states for kinematic cuts
  declare(ChargedFinalState(Cuts::abseta < 1.0), "INEL0CFS");
  declare(ChargedFinalState(Cuts::abseta < 1.8), "EtaCFS");
  declare(ChargedFinalState(Cuts::abseta < 0.8 && Cuts::pT > 0.15 * GeV && Cuts::pT < 20 * GeV), "PtCFS");

  // Book dN/deta and INEL0 pT histograms
  book(_h["dNch_deta_INEL"], 1, 1, 1);
  book(_h["dNch_deta_INEL0"], 1, 1, 2);
  book(_h["pT_INEL0"], 2, 1, 1);

  // Book multiplicity class histograms and ratios dynamically
  book(_h["pT_incl"], "TMP/pT_incl", refData(4, 1, 1));
  for (size_t i = 1; i <= 3; ++i) {
    const string mode = to_string(i);
    book(_h["pT_c" + mode], "TMP/pT_c" + mode, refData(4, 1, i));
    book(_e["ratio_c" + mode], 4, 1, i);
  }

  // Book event counters
  book(_c["INEL"], "TMP/c_INEL");
  book(_c["INEL0"], "TMP/c_INEL0");
}


/// Perform the per-event analysis
void analyze(const Event& event) {
  const ChargedFinalState& trigCFS = apply<ChargedFinalState>(event, "TrigCFS");
  const ChargedFinalState& inel0CFS = apply<ChargedFinalState>(event, "INEL0CFS");
  const ChargedFinalState& etaCFS = apply<ChargedFinalState>(event, "EtaCFS");
  const ChargedFinalState& ptCFS = apply<ChargedFinalState>(event, "PtCFS");
  // INEL Trigger requirement
  if (!trigCFS.particles().empty()) {
    _c["INEL"]->fill();
    for (const Particle& p : etaCFS.particles()) {
      _h["dNch_deta_INEL"]->fill(p.eta());
    }
  }

  // INEL > 0 Trigger requirement
  if (inel0CFS.particles().empty()) return;

  _c["INEL0"]->fill();

  // Inclusive distributions
  for (const Particle& p : etaCFS.particles()) {
    _h["dNch_deta_INEL0"]->fill(p.eta());
  }

  for (const Particle& p : ptCFS.particles()) {
    const double pT = p.pT() / GeV;
    const double w = (_ptMode == PTWEIGHT) ? 1.0 / pT : 1.0;
    _h["pT_INEL0"]->fill(pT, w);
    _h["pT_incl"]->fill(pT, w);
  }

  // Multiplicity class evaluation is deferred to finalize(), since the
  // classification thresholds depend on the sample's own <Nch>
  const size_t nch = ptCFS.size();
  if (nch >= 1) {
    vector<double> pts;
    pts.reserve(nch);
    for (const Particle& p : ptCFS.particles()) pts.push_back(p.pT() / GeV);
    _nchBuffer.push_back(nch);
    _ptBuffer.push_back(pts);
    _sumNch += nch;
  }
}

/// Normalise histograms etc., after the run
void finalize() {
  // Classify buffered events by multiplicity, using this sample's own
  // <Nch> over INEL>0 events (paper Sec. 5), then fill the per-class pT histograms accordingly.
  if (!_nchBuffer.empty()) {
    const double meanNch = _sumNch / double(_nchBuffer.size());
    for (size_t iEv = 0; iEv < _nchBuffer.size(); ++iEv) {
      const size_t nch = _nchBuffer[iEv];
      size_t idx;
      if (nch < meanNch)
        idx = 1;
      else if (nch < 2.0 * meanNch)
        idx = 2;
      else
        idx = 3;
      const string mode = to_string(idx);
      for (const double pT : _ptBuffer[iEv]) {
        const double w = (_ptMode == PTWEIGHT) ? 1.0 / pT : 1.0;
        _h["pT_c" + mode]->fill(pT, w);
      }
    }
  }

  // Normalise dN/deta by number of events
  if (_c["INEL"]->val() > 0) scale(_h["dNch_deta_INEL"], 1.0 / _c["INEL"]->val());
  if (_c["INEL0"]->val() > 0) scale(_h["dNch_deta_INEL0"], 1.0 / _c["INEL0"]->val());

  // Normalise inclusive pT by 1/(Nev * 2pi * pT * deta).
  // In PTWEIGHT mode the 1/pT factor was already applied per-particle
  // at fill-time, so it must not be divided out again here.
  if (_c["INEL0"]->val() > 0) {
    const double deta = 2.0 * 0.8;
    for (auto& b : _h["pT_INEL0"]->bins()) {
      const double norm = (_ptMode == PTWEIGHT)
          ? 1.0 / (_c["INEL0"]->val() * 2.0 * M_PI * deta)
          : 1.0 / (_c["INEL0"]->val() * 2.0 * M_PI * b.xMid() * deta);
      b.scaleW(norm);
    }
  }

  // Multiplicity ratios: normalise each spectrum to unit area
  normalize(_h["pT_incl"]);
  for (size_t i = 1; i <= 3; ++i) {
    const string mode = to_string(i);
    normalize(_h["pT_c" + mode]);
    divide(_h["pT_c" + mode], _h["pT_incl"], _e["ratio_c" + mode]);
  }
}

/// @}

private:

// Buffers for deferred multiplicity classification (see finalize()):
// each INEL>0 event's Nacc_ch and per-particle pT list are stored here,
// then classified in finalize() once this sample's own <Nch> is known.
vector<size_t> _nchBuffer;
vector<vector<double>> _ptBuffer;
double _sumNch = 0.0;

// pT reweighting mode (see PTMODE option in init())
enum PtRewMode { XMID, PTWEIGHT };
PtRewMode _ptMode;

/// @name Histograms and Counters
/// @{
map<string, Histo1DPtr> _h;
map<string, Estimate1DPtr> _e;
map<string, CounterPtr> _c;
/// @}

};

RIVET_DECLARE_PLUGIN(ALICE_2015_I1395253);

} ```