rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

ATLAS_2015_I1351916

$Z$ forward-backward asymmetry
Experiment: ATLAS (LHC)
Inspire ID: 1351916
Status: VALIDATED
Authors:
  • Christian Gutschow
References: Beams: p+ p+
Beam energies: (3500.0, 3500.0) GeV
Run details:
  • Inclusive $Z$ in the electron channel

Measurements from the ATLAS experiment of the forward-backward asymmetry in the reaction $pp \rightarrow Z / \gamma^\ast \rightarrow \ell^+\ell^-$, with $\ell$ being electrons or muons. The results are based on the full set of data collected in 2011 in $pp$ collisions at the LHC at $\sqrt{s} = 7$ TeV, corresponding to an integrated luminosity of 4.8 $\text{fb}^{-1}$. The measured asymmetry values are found to be in agreement with the corresponding Standard Model predictions. The default routine will pick up the electron decay channel of the $Z$ boson. Individual channels can be specified directly with the plugins ATLAS_2014_I1312627_EL and ATLAS_2014_I1312627_MU, respectively. N.B. When running on multiple files, the asymmetry might have to be reconstructed in a post-processing step. To that end, the necessary Histo1D objects are written out as well. The asymmetry is a Scatter2D objects ending in y01 and is constructed from the Histo1D objects (ending in y02 and y03) in the following way: y01 = (y02 - y03) / (y02 + y03)

Source code: ATLAS_2015_I1351916.cc
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// -*- C++ -*-
#include "Rivet/Analysis.hh"
#include "Rivet/Projections/FinalState.hh"
#include "Rivet/Projections/IdentifiedFinalState.hh"
#include "Rivet/Projections/DressedLeptons.hh"

namespace Rivet {


  class ATLAS_2015_I1351916 : public Analysis {
  public:

    /// @name Constructors etc.
    //@{

    /// Constructors
    ATLAS_2015_I1351916(string name="ATLAS_2015_I1351916", size_t mode=0)
      : Analysis(name), _mode(mode) // pick electron channel by default
    { }

    //@}


    /// @name Analysis methods
    //@{

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

      const FinalState fs;

      IdentifiedFinalState bareleptons(fs);
      bareleptons.acceptIdPair(_mode? PID::MUON : PID::ELECTRON);

      const Cut cuts = (_mode == 0) ? (Cuts::pT > 25*GeV && Cuts::abseta < 4.9) : (Cuts::pT > 20*GeV && Cuts::abseta < 2.47);
      DressedLeptons leptons(fs, bareleptons, 0.1, cuts, true);
      declare(leptons, "leptons");


      // Book dummy histograms for heterogeneous merging
      /// @todo AB: Don't we have a nicer way to book dummy/tmp histos from ref?
      string label = "NCC";
      string hname = "d01-x01-y01";
      const Scatter2D& ref = refData(hname);
      hname = "d01-x01-y02";
      _h[label + "_pos"] = bookHisto1D(hname, ref);
      hname = "d01-x01-y03";
      _h[label + "_neg"] = bookHisto1D(hname, ref);
      if (_mode == 0) {
        label = "NCF";
        hname = "d01-x02-y01";
        const Scatter2D& ref_cf = refData(hname);
        hname = "d01-x02-y02";
        _h[label + "_pos"] = bookHisto1D(hname, ref_cf);
        hname = "d01-x02-y03";
        _h[label + "_neg"] = bookHisto1D(hname, ref_cf);
      }

      // Book asymmetry scatter plots
      _s["CC"] = bookScatter2D(1, 1, 1, true);
      if (_mode == 0) _s["CF"] = bookScatter2D(1, 2, 1, true);
    }


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

      // Get and cut on dressed leptons
      const vector<DressedLepton>& leptons = apply<DressedLeptons>(e, "leptons").dressedLeptons();
      if (leptons.size() != 2) vetoEvent; // require exactly two leptons
      if (leptons[0].threeCharge() * leptons[1].threeCharge() > 0) vetoEvent; // require opposite charge

      // Identify lepton vs antilepton
      const Particle& lpos = leptons[(leptons[0].threeCharge() > 0) ? 0 : 1];
      const Particle& lneg = leptons[(leptons[0].threeCharge() < 0) ? 0 : 1];

      string label = "N";
      if (_mode == 1) {// electron channel
        label += "CC"; // only central-central for muons
      } else { // electron channel
        const double eta1 = lpos.abseta();
        const double eta2 = lneg.abseta();
        if ( (eta1 < 2.47 && inRange(eta2, 2.5, 4.9)) || (eta2 < 2.47 && inRange(eta1, 2.5, 4.9)) )
          label += "CF"; // central-forward
        else if (eta1 < 2.47 && eta2 < 2.47)
          label += "CC"; // central-central
        else vetoEvent; // ain't no forward-forward
      }

      const double cosThetaStar = cosCollinsSoper(lneg, lpos);
      const double mll = (lpos.mom() + lneg.mom()).mass();
      label += cosThetaStar < 0.0?  "_neg" : "_pos";
      _h[label]->fill(mll/GeV, e.weight());
    }


    /// Normalise histograms etc., after the run
    void finalize() {
      const double sf = crossSectionPerEvent() / picobarn;
      for (const auto& key_hist : _h) scale(key_hist.second, sf);
      divide(*_h["NCC_pos"] - *_h["NCC_neg"], *_h["NCC_pos"] + *_h["NCC_neg"], _s["CC"]);
      if (!_mode)  divide(*_h["NCF_pos"] - *_h["NCF_neg"], *_h["NCF_pos"] + *_h["NCF_neg"], _s["CF"]);
    }


    // Cosine of the decay angle in the Collins-Soper frame
    double cosCollinsSoper(const FourMomentum& l1, const FourMomentum& l2) {
      const FourMomentum ll = l1 + l2;
      const double nom  = (l1.E() + l1.pz()) * (l2.E() - l2.pz()) - (l1.E() - l1.pz()) * (l2.E() + l2.pz());
      const double denom = ll.mass() * sqrt( sqr(ll.mass()) + sqr(ll.pt()) );
      return sign(ll.pz()) * safediv(nom, denom); // protect against division by zero, you never know...
    }

    //@}


  protected:

    /// Electron or muon mode = 0 or 1, for use by derived _EL, _MU analysis classes
    size_t _mode;


  private:

    /// Histograms
    map<string, Histo1DPtr> _h;
    /// Asymmetries
    map<string, Scatter2DPtr> _s;

  };



  class ATLAS_2015_I1351916_EL : public ATLAS_2015_I1351916 {
  public:
    ATLAS_2015_I1351916_EL() : ATLAS_2015_I1351916("ATLAS_2015_I1351916_EL", 0) { }
  };


  class ATLAS_2015_I1351916_MU : public ATLAS_2015_I1351916 {
  public:
    ATLAS_2015_I1351916_MU() : ATLAS_2015_I1351916("ATLAS_2015_I1351916_MU", 1) { }
  };


  DECLARE_RIVET_PLUGIN(ATLAS_2015_I1351916);
  DECLARE_RIVET_PLUGIN(ATLAS_2015_I1351916_EL);
  DECLARE_RIVET_PLUGIN(ATLAS_2015_I1351916_MU);

}