Rivet analyses


title: DELPHI_2003_I620250

Measurements of event shapes by DELPHI, above and below $m_Z$

Experiment: DELPHI (LEP)

Inspire ID: 620250

Status: VALIDATED

Authors: - Peter Richardson

References: - Eur.Phys.J. C29 (2003) 285-312

Beams: e+ e-

Beam energies: (22.5, 22.5); (33.0, 33.0); (38.0, 38.0); (91.5, 91.5); (94.5, 94.5); (96.0, 96.0); (98.0, 98.0); (100.0, 100.0); (101.0, 101.0); (102.5, 102.5); (103.5, 103.5)GeV

Run details: - Hadronic Z decay events generated below the Z pole.

Measurement of a wide range of event shapes by DELPHI at energies below the Z pole using radiative events and above $m_Z$ from LEP2. This analyses allows the energy dependence of simulations to be studied. Only the distributions and not the means are implemented.

Source code:DELPHI_2003_I620250.cc

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

include "Rivet/Analysis.hh"

include "Rivet/Projections/Beam.hh"

include "Rivet/Projections/FinalState.hh"

include "Rivet/Projections/Hemispheres.hh"

include "Rivet/Projections/ParisiTensor.hh"

include "Rivet/Projections/Sphericity.hh"

include "Rivet/Projections/Thrust.hh"

namespace Rivet {

/// @brief DELPHI event shapes below the Z pole class DELPHI_2003_I620250 : public Analysis { public:

/// Constructor
RIVET_DEFAULT_ANALYSIS_CTOR(DELPHI_2003_I620250);


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

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

  // Initialise and register projections.
  declare(Beam(), "Beams");
  const FinalState fs;
  declare(fs, "FS");
  const Thrust thrust(fs);
  declare(thrust, "Thrust");
  declare(Sphericity(fs), "Sphericity");
  declare(ParisiTensor(fs), "Parisi");
  declare(Hemispheres(thrust), "Hemispheres");

  // Histogram booking offset numbers.
  size_t ih = 0, iy = 1;
  for (double eVal : allowedEnergies()) {

    const string en = toString(round(eVal));
    if (isCompatibleWithSqrtS(eVal)) {
      _sqs = en;
      skipBin = eVal < 200.;
      isDisc = eVal >= 100.;
    }

    book(_c[en], "_sumW_" + en);
    if (eVal < 100.) {
      book(_h[en + "thrust"], 1, 1, iy);
      book(_h[en + "major"], 2, 1, iy);
      book(_h[en + "minor"], 3, 1, iy);
      book(_h[en + "sphericity"], 4, 1, iy);
      book(_h[en + "planarity"], 5, 1, iy);
      book(_h[en + "oblateness"], 6, 1, iy);
      book(_h[en + "heavy_jet_mass"], 7, 1, iy);
      book(_h[en + "light_jet_mass"], 9, 1, iy);
      book(_h[en + "diff_jet_mass"], 10, 1, iy);
      book(_h[en + "total_jet_mass"], 11, 1, iy);
      book(_h[en + "heavy_jet_mass_E"], 8, 1, iy);
      book(_h[en + "total_jet_mass_E"], 12, 1, iy);
      book(_h[en + "wide_broading"], 13, 1, iy);
      book(_h[en + "narrow_broading"], 14, 1, iy);
      book(_h[en + "total_broading"], 15, 1, iy);
      book(_h[en + "diff_broading"], 16, 1, iy);
      book(_h[en + "CParam"], 17, 1, iy);
      if (iy == 3) iy = 0;
    }
    else {
      book(_d[en]["rap"], 30 + ih, 1, iy);
      book(_d[en]["xi"], 32 + ih, 1, iy);
      book(_d[en]["pTIn"], 34 + ih, 1, iy);
      book(_d[en]["pTOut"], 36 + ih, 1, iy);
      book(_d[en]["thrust"], 38 + ih, 1, iy);
      book(_d[en]["major"], 40 + ih, 1, iy);
      book(_d[en]["minor"], 42 + ih, 1, iy);
      book(_d[en]["oblateness"], 44 + ih, 1, iy);
      book(_d[en]["wide_broading"], 46 + ih, 1, iy);
      book(_d[en]["total_broading"], 48 + ih, 1, iy);
      book(_d[en]["diff_broading"], 50 + ih, 1, iy);
      book(_d[en]["CParam"], 52 + ih, 1, iy);
      book(_d[en]["DParam"], 54 + ih, 1, iy);
      book(_d[en]["heavy_jet_mass"], 56 + ih, 1, iy);
      book(_d[en]["heavy_jet_mass_P"], 58 + ih, 1, iy);
      book(_d[en]["heavy_jet_mass_E"], 60 + ih, 1, iy);
      book(_d[en]["light_jet_mass"], 62 + ih, 1, iy);
      book(_d[en]["diff_jet_mass"], 64 + ih, 1, iy);
      book(_d[en]["sphericity"], 66 + ih, 1, iy);
      book(_d[en]["planarity"], 68 + ih, 1, iy);
      book(_d[en]["aplanarity"], 70 + ih, 1, iy);
    }

    if (iy == 4) {
      ++ih;
      iy = 0;
    }
    ++iy;
  }
  raiseBeamErrorIf(_sqs.empty());

  _axis["rap"] = YODA::Axis<double>({0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.5});
  _axis["xi"] = YODA::Axis<double>(
      {0.0, 0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 2.8, 3.2, 3.6, 4.0, 4.4, 4.8, 5.2, 5.6, 6.0, 6.4});
  _axis["pTIn"] = YODA::Axis<double>({0.0, 0.1, 0.4, 0.65, 0.9, 1.1, 1.4, 2.0, 3.0, 4.0, 6.0, 8.0, 12.0});
  _axis["pTOut"] = YODA::Axis<double>({0.0, 0.2, 0.4, 0.6, 0.85, 1.2, 1.6, 2.0, 3.0});
  _axis["thrust"] = YODA::Axis<double>({0.0,  0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09,
                                        0.10, 0.12, 0.14, 0.16, 0.18, 0.20, 0.24, 0.28, 0.32, 0.36});
  _axis["major"] = YODA::Axis<double>({0.0, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1,  0.12, 0.14, 0.16,
                                       0.2, 0.24, 0.28, 0.32, 0.36, 0.4,  0.44, 0.48, 0.52, 0.56, 0.6});
  _axis["minor"] = YODA::Axis<double>(
      {0.0, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.12, 0.14, 0.16, 0.2, 0.24, 0.28, 0.32});
  _axis["oblateness"] = YODA::Axis<double>({0.0, 0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18,
                                            0.20, 0.24, 0.28, 0.32, 0.36, 0.4, 0.44});
  _axis["wide_broading"] = YODA::Axis<double>(
      {0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.12, 0.14, 0.17, 0.20, 0.24, 0.28});
  _axis["total_broading"] = YODA::Axis<double>({0.0,  0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07,
                                                0.08, 0.09, 0.1,  0.11, 0.13, 0.15, 0.17, 0.19,
                                                0.21, 0.24, 0.27, 0.3,  0.33, 0.36});
  _axis["diff_broading"] = YODA::Axis<double>({0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09,
                                               0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.24, 0.28});
  _axis["CParam"] = YODA::Axis<double>({0.0,  0.04, 0.08, 0.12, 0.16, 0.2,  0.24, 0.28,
                                        0.32, 0.36, 0.4,  0.44, 0.48, 0.52, 0.56, 0.6,
                                        0.64, 0.68, 0.72, 0.76, 0.8,  0.84, 0.88});
  _axis["DParam"] = YODA::Axis<double>({0.00, 0.02, 0.04, 0.06, 0.08, 0.10, 0.12, 0.14, 0.16, 0.20, 0.24,
                                        0.28, 0.32, 0.36, 0.40, 0.44, 0.48, 0.54});
  _axis["heavy_jet_mass"] = YODA::Axis<double>(
      {0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.08, 0.10, 0.12, 0.14, 0.16, 0.20, 0.24, 0.28, 0.32});
  _axis["heavy_jet_mass_P"] = YODA::Axis<double>(
      {0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.2, 0.24, 0.28, 0.32});
  _axis["heavy_jet_mass_E"] = YODA::Axis<double>(
      {0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.08, 0.10, 0.12, 0.14, 0.16, 0.20, 0.24, 0.28, 0.32});
  _axis["light_jet_mass"] = YODA::Axis<double>({0.0, 0.01, 0.02, 0.03, 0.04, 0.05});
  _axis["diff_jet_mass"] = YODA::Axis<double>(
      {0.0, 0.01, 0.02, 0.03, 0.04, 0.06, 0.08, 0.12, 0.16, 0.2, 0.25, 0.3});
  _axis["sphericity"] = YODA::Axis<double>({0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.08, 0.1, 0.12,
                                            0.16, 0.2, 0.25, 0.3, 0.35, 0.4, 0.5, 0.6});
  _axis["planarity"] = YODA::Axis<double>(
      {0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.08, 0.1, 0.12, 0.16, 0.2, 0.25, 0.3, 0.35, 0.4});
  _axis["aplanarity"] = YODA::Axis<double>(
      {0.0, 0.004, 0.01, 0.016, 0.02, 0.03, 0.04, 0.06, 0.08, 0.1, 0.12, 0.16});
}


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

  if (isDisc && _edges.empty()) {
    for (const auto& item : _axis) {
      _edges[item.first] = _d[_sqs][item.first]->xEdges();
    }
  }

  _c[_sqs]->fill();

  // Get beams and average beam momentum
  const ParticlePair& beams = apply<Beam>(event, "Beams").beams();
  const double meanBeamMom = (beams.first.p3().mod() + beams.second.p3().mod()) / 2.0;
  MSG_DEBUG("Avg beam momentum = " << meanBeamMom);

  const Thrust& thrust = apply<Thrust>(event, "Thrust");
  // sphericity related
  const Sphericity& sphericity = apply<Sphericity>(event, "Sphericity");
  // hemisphere related
  const Hemispheres& hemi = apply<Hemispheres>(event, "Hemispheres");
  smartfill("thrust", 1. - thrust.thrust());
  smartfill("major", thrust.thrustMajor());
  smartfill("minor", thrust.thrustMinor());
  smartfill("oblateness", thrust.oblateness());
  smartfill("sphericity", sphericity.sphericity());
  smartfill("planarity", sphericity.planarity());
  if (isDisc) smartfill("aplanarity", sphericity.aplanarity());
  smartfill("heavy_jet_mass", hemi.scaledM2high());
  smartfill("light_jet_mass", hemi.scaledM2low());
  smartfill("diff_jet_mass", hemi.scaledM2diff());
  smartfill("wide_broading", hemi.Bmax());
  if (!isDisc) smartfill("narrow_broading", hemi.Bmin());
  smartfill("total_broading", hemi.Bsum());
  smartfill("diff_broading", hemi.Bdiff());
  if (!isDisc) smartfill("total_jet_mass", hemi.scaledM2low() + hemi.scaledM2high());
  // E and p scheme jet masses
  Vector3 axis = thrust.thrustAxis();
  FourMomentum p4WithE, p4AgainstE;
  FourMomentum p4WithP, p4AgainstP;
  double Evis(0);
  for (const Particle& p : apply<FinalState>(event, "FS").particles()) {
    Vector3 p3 = p.momentum().vector3().unitVec();
    const double E = p.momentum().E();
    Evis += E;
    p3 = E * p3;
    const double p3Para = dot(p3, axis);
    FourMomentum p4E(E, p3.x(), p3.y(), p3.z());
    FourMomentum p4P(p.p3().mod(), p.p3().x(), p.p3().y(), p.p3().z());
    if (p3Para > 0) {
      p4WithE += p4E;
      p4WithP += p4P;
    }
    else if (p3Para < 0) {
      p4AgainstE += p4E;
      p4AgainstP += p4P;
    }
    else {
      MSG_WARNING("Particle split between hemispheres");
      p4WithE += 0.5 * p4E;
      p4AgainstE += 0.5 * p4E;
      p4WithP += 0.5 * p4P;
      p4AgainstP += 0.5 * p4P;
    }
  }
  // E scheme
  const double mass2With_E = p4WithE.mass2() / sqr(Evis);
  const double mass2Against_E = p4AgainstE.mass2() / sqr(Evis);
  // fill the histograms
  smartfill("heavy_jet_mass_E", max(mass2With_E, mass2Against_E));
  if (!isDisc) smartfill("total_jet_mass_E", mass2With_E + mass2Against_E);
  // pscheme
  const double mass2With_P = p4WithP.mass2() / sqr(Evis);
  const double mass2Against_P = p4AgainstP.mass2() / sqr(Evis);
  // fill the histograms
  if (isDisc) smartfill("heavy_jet_mass_P", max(mass2With_P, mass2Against_P));

  MSG_DEBUG("Calculating Parisi params");
  const ParisiTensor& parisi = apply<ParisiTensor>(event, "Parisi");
  smartfill("CParam", parisi.C());
  if (isDisc) smartfill("DParam", parisi.D());

  // single particle distributions
  const FinalState& fs = apply<FinalState>(event, "FS");
  if (isDisc) {
    for (const Particle& p : fs.particles()) {
      if (!PID::isCharged(p.pid())) continue;
      // Get momentum and energy of each particle.
      const Vector3 mom3 = p.p3();
      const double energy = p.E();

      // Scaled momenta.
      const double mom = mom3.mod();
      const double scaledMom = mom / meanBeamMom;
      const double logInvScaledMom = -std::log(scaledMom);
      smartfill("xi", logInvScaledMom);

      // Get momenta components w.r.t. thrust and sphericity.
      const double momT = dot(thrust.thrustAxis(), mom3);
      const double pTinT = dot(mom3, thrust.thrustMajorAxis());
      const double pToutT = dot(mom3, thrust.thrustMinorAxis());
      smartfill("pTIn", fabs(pTinT / GeV));
      smartfill("pTOut", fabs(pToutT / GeV));

      // Calculate rapidities w.r.t. thrust and sphericity.
      const double rapidityT = 0.5 * std::log((energy + momT) / (energy - momT));
      smartfill("rap", fabs(rapidityT));
      MSG_TRACE(fabs(rapidityT) << " " << scaledMom / GeV);
    }
  }
}

void smartfill(const string& tag, const double value) {
  if (isDisc) {
    size_t idx = _axis[tag].index(value);
    // skip masked bin in wide broadening
    if (tag == "wide_broading" && skipBin) {
      if (idx == 8)
        idx = 0;
      else if (idx > 8)
        --idx;
    }
    if (idx && idx <= _edges[tag].size()) {
      _d[_sqs][tag]->fill(_edges[tag][idx - 1]);
    }
    else {
      _d[_sqs][tag]->fill(string("OTHER"));
    }
  }
  else {
    _h[_sqs + tag]->fill(value);
  }
}

/// Normalise histograms etc., after the run
void finalize() {
  normalize(_h);
  scale(_c, crossSectionPerEvent());
  scale(_d, crossSectionPerEvent());
  for (double eVal : allowedEnergies()) {
    const string en = toString(round(eVal));
    for (auto& item : _d[en]) {
      if (item.first == "rap" || item.first == "xi" || item.first == "pTIn" || item.first == "pTOut") {
        if (!isZero(_c[en]->sumW())) scale(item.second, 1.0 / _c[en]->sumW());
      }
      else
        normalize(item.second);
      for (auto& b : item.second->bins()) {
        size_t idx = b.index();
        // skip masked bin in wide broadening
        if (skipBin && item.first == "wide_broading") {
          if (idx >= 8) ++idx;
        }
        b.scaleW(1. / _axis[item.first].width(idx));
      }
    }
  }
}

/// @}


/// @name Histograms
/// @{
map<string, map<string, BinnedHistoPtr<string>>> _d;
map<string, YODA::Axis<double>> _axis;
map<string, vector<string>> _edges;
map<string, Histo1DPtr> _h;
map<string, CounterPtr> _c;
bool isDisc, skipBin;
string _sqs = "";

/// @}

};

RIVET_DECLARE_PLUGIN(DELPHI_2003_I620250);

} ```