Rivet analyses


title: ATLAS_2012_I1091481

Azimuthal ordering of charged hadrons

Experiment: ATLAS (LHC)

Inspire ID: 1091481

Status: VALIDATED

Authors: - Sharka Todorova - Holger Schulz - Christian Guetschow

References: - Expt page: ATLAS-STDM-2011-20 - CERN-PH-EP-2011-197 - arXiv: 1203.0419

Beams: p+ p+

Beam energies: (450.0, 450.0); (3500.0, 3500.0)GeV

Run details: - QCD events with diffractives switched on.

Measurement of the ordering of charged hadrons in the azimuthal angle relative to the beam axis at the Large Hadron Collider (LHC). A spectral analysis of correlations between longitudinal and transverse components of the momentum of the charged hadrons is performed. Data were recorded with the ATLAS detector at centre-of-mass energies of $\sqrt{s} = 900~\GeV$ and $\sqrt{s} = 7~\TeV$. The correlations measured in a phase space region dominated by low-$\pT$ particles are not well described by conventional models of hadron production. The measured spectra show features consistent with the fragmentation of a QCD string represented by a helix-like ordered gluon chain.

Source code:ATLAS_2012_I1091481.cc

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

include "Rivet/Analysis.hh"

include "Rivet/Projections/ChargedFinalState.hh"

namespace Rivet {

/// @brief Azimuthal ordering of charged hadrons class ATLAS_2012_I1091481 : public Analysis { public:

/// Constructor
RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2012_I1091481);

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

  ChargedFinalState cfs100(Cuts::abseta < 2.5 && Cuts::pT > 0.1 * GeV);
  declare(cfs100, "CFS100");
  ChargedFinalState cfs500(Cuts::abseta < 2.5 && Cuts::pT > 0.5 * GeV);
  declare(cfs500, "CFS500");

  for (double eVal : allowedEnergies()) {
    const string en = toString(round(eVal));
    if (isCompatibleWithSqrtS(eVal)) _sqs = en;
    size_t ih = bool(en == "900") + 1;

    book(_h[en + "E_10_100"], ih, 1, 1);
    book(_h[en + "E_1_100"], ih, 1, 2);
    book(_h[en + "E_10_500"], ih, 1, 3);

    book(_h[en + "eta_10_100"], ih, 2, 1);
    book(_h[en + "eta_1_100"], ih, 2, 2);
    book(_h[en + "eta_10_500"], ih, 2, 3);

    book(_c[en + "inclusive"], "_norm_inclusive_" + en);
    book(_c[en + "lowPt"], "_norm_lowPt_" + en);
    book(_c[en + "pt500"], "_norm_pt500_" + en);
  }
  raiseBeamErrorIf(_sqs.empty());
}


// Recalculate particle energy assuming pion mass
double getPionEnergy(const Particle& p) {
  double m_pi = 0.1396 * GeV;
  double p2 = p.p3().mod2() / (GeV * GeV);
  return sqrt(sqr(m_pi) + p2);
}


// S_eta core for one event
//
//  -1 + 1/Nch * |sum_j^Nch exp[i*(xi eta_j - Phi_j)]|^2
//
double getSeta(const Particles& part, double xi) {
  std::complex<double> c_eta(0.0, 0.0);
  for (const Particle& p : part) {
    double eta = p.eta();
    double phi = p.phi();
    double arg = xi * eta - phi;
    std::complex<double> temp(cos(arg), sin(arg));
    c_eta += temp;
  }
  return std::norm(c_eta) / part.size() - 1.0;
}


// S_E core for one event
//
//  -1 + 1/Nch * |sum_j^Nch exp[i*(omega X_j - Phi_j)]|^2
//
double getSE(const Particles& part, double omega) {
  double Xj = 0.0;
  std::complex<double> c_E(0.0, 0.0);
  for (unsigned int i = 0; i < part.size(); ++i) {
    Xj += 0.5 * getPionEnergy(part[i]);
    double phi = part[i].phi();
    double arg = omega * Xj - phi;
    std::complex<double> temp(cos(arg), sin(arg));
    c_E += temp;
    Xj += 0.5 * getPionEnergy(part[i]);
  }
  return std::norm(c_E) / part.size() - 1.0;
}


// Convenient fill function
void fillS(Histo1DPtr h, const Particles& part, bool SE = true) {
  // Loop over bins, take bin centers as parameter values
  // @todo use barchart()
  for (auto& b : h->bins()) {
    double x = b.xMid();
    double width = b.xWidth();
    double y;
    if (SE)
      y = getSE(part, x);
    else
      y = getSeta(part, x);
    h->fill(x, y * width);
  }
}


/// Perform the per-event analysis
void analyze(const Event& event) {
  // Charged fs
  const ChargedFinalState& cfs100 = apply<ChargedFinalState>(event, "CFS100");
  const Particles part100 = cfs100.particles(cmpMomByEta);
  const ChargedFinalState& cfs500 = apply<ChargedFinalState>(event, "CFS500");
  const Particles& part500 = cfs500.particles(cmpMomByEta);

  // Veto event if the most inclusive phase space has less than 10 particles and the max pT is > 10 GeV
  if (part100.size() < 11) vetoEvent;
  double ptmax = cfs100.particlesByPt()[0].pT() / GeV;
  if (ptmax > 10.0) vetoEvent;

  // Fill the pt>100, pTmax<10 GeV histos
  fillS(_h[_sqs + "E_10_100"], part100, true);
  fillS(_h[_sqs + "eta_10_100"], part100, false);
  _c[_sqs + "inclusive"]->fill();

  // Fill the pt>100, pTmax<1 GeV histos
  if (ptmax < 1.0) {
    fillS(_h[_sqs + "E_1_100"], part100, true);
    fillS(_h[_sqs + "eta_1_100"], part100, false);
    _c[_sqs + "lowPt"]->fill();
  }

  // Fill the pt>500, pTmax<10 GeV histos
  if (part500.size() > 10) {
    fillS(_h[_sqs + "E_10_500"], part500, true);
    fillS(_h[_sqs + "eta_10_500"], part500, false);
    _c[_sqs + "pt500"]->fill();
  }
}

/// Normalise histograms etc., after the run
void finalize() {
  // The scaling takes the multiple fills per event into account
  for (double eVal : allowedEnergies()) {
    const string en = toString(round(eVal));

    scale(_h[en + "E_10_100"], 1.0 / *_c[en + "inclusive"]);
    scale(_h[en + "E_1_100"], 1.0 / *_c[en + "lowPt"]);
    scale(_h[en + "E_10_500"], 1.0 / *_c[en + "pt500"]);

    scale(_h[en + "eta_10_100"], 1.0 / *_c[en + "inclusive"]);
    scale(_h[en + "eta_1_100"], 1.0 / *_c[en + "lowPt"]);
    scale(_h[en + "eta_10_500"], 1.0 / *_c[en + "pt500"]);
  }
}

private:

map<string, Histo1DPtr> _h;
map<string, CounterPtr> _c;

string _sqs = "";

};

RIVET_DECLARE_PLUGIN(ATLAS_2012_I1091481);

} ```