Rivet analyses

W and Z inclusive cross sections at 7 TeV

Experiment: ATLAS (LHC)

Inspire ID: 1502620

Status: VALIDATED

Authors: - Jan Kretzschmar - Christian Gutschow

References: - Expt page: ATLAS-STDM-2012-20 - Eur. Phys. J. C77 (2017) no.6, 367 - DOI: 10.1140/epjc/s10052-017-4911-9 - arXiv: 1612.03016

Beams: p+ p+

Beam energies: (3500.0, 3500.0)GeV

Run details: - p + p -> Z + X ( Z -> e e )

High-precision measurements by the ATLAS Collaboration are presented of inclusive W+ → +, W → , Z/γ* →  ( = e, μ) Drell-Yan production cross sections at the LHC. The data were collected in proton-proton collisions at $\sqrt{s}=7$ TeV with an integrated luminosity of 4.6 fb−1. Differential W+ and W cross sections are measured in a lepton pseudorapidity range |η| < 2.5. Differential Z/γ* cross sections are measured as a function of the absolute dilepton rapidity, for |y| < 3.6, for three intervals of dilepton mass, m, extending from 46 to 150 GeV. The integrated and differential electron- and muon-channel cross sections are combined and compared to theoretical predictions using recent sets of parton distribution functions. The data, together with the final inclusive e±p scattering cross-section data from H1 and ZEUS, are interpreted in a next-to-next-to-leading-order QCD analysis, and a new set of parton distribution functions, ATLAS-epWZ16, is obtained. The ratio of strange-to-light sea-quark densities in the proton is determined more accurately than in previous determinations based on collider data only, and is established to be close to unity in the sensitivity range of the data. A new measurement of the CKM matrix element |Vcs| is also provided. N.B.: Use :LMODE to choose specify the signature decay channel directly. Default, run everything, assuming all decay modes are generated Contains Z (W): fill only Z (W) signature histograms Contains EL (MU): assume only electron (muon) decay modes are being generated.

Source code:ATLAS_2016_I1502620.cc


#include "Rivet/Analysis.hh"
#include "Rivet/Projections/FinalState.hh"
#include "Rivet/Projections/MissingMomentum.hh"
#include "Rivet/Projections/LeptonFinder.hh"
#include "Rivet/Projections/DileptonFinder.hh"

namespace Rivet {


  /// @brief inclusive W/Z cross sections at 7 TeV
  class ATLAS_2016_I1502620 : public Analysis {
  public:

    /// Constructor
    RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2016_I1502620);


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

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

      // Get options from the option system
      _mode = 0;
      _runZ = true;
      _runW = true;
      if ( getOption("LMODE") == "EL" ||
           getOption("LMODE") == "ZEL" ||
           getOption("LMODE") == "WEL" )
        _mode = 1;
      if ( getOption("LMODE") == "MU" ||
           getOption("LMODE") == "ZMU" ||
           getOption("LMODE") == "WMU" )
        _mode = 2;
      if ( getOption("LMODE") == "Z" ||
           getOption("LMODE") == "ZEL" ||
           getOption("LMODE") == "ZMU" )
        _runW = false;
      if ( getOption("LMODE") == "W" ||
           getOption("LMODE") == "WEL" ||
           getOption("LMODE") == "WMU" )
        _runZ = false;


      // Initialise and register projections
      declare("MET", MissingMomentum());
      LeptonFinder ef(0.1, Cuts::pT > 25*GeV && Cuts::abspid == PID::ELECTRON);
      declare(ef, "Elecs");
      LeptonFinder mf(0.1, Cuts::pT > 25*GeV && Cuts::abspid == PID::MUON);
      declare(mf, "Muons");

      DileptonFinder zfe(91.2*GeV, 0.1, Cuts::pT > 20*GeV && Cuts::abspid == PID::ELECTRON, Cuts::massIn(46.0*GeV, 150*GeV));
      declare(zfe, "Zee");
      DileptonFinder zfm(91.2*GeV, 0.1, Cuts::pT > 20*GeV && Cuts::abspid == PID::MUON, Cuts::massIn(46.0*GeV, 150*GeV));
      declare(zfm, "Zmm");


      // Book histograms
      if (_runW) {
        book(_h_Wp_eta,  9, 1, 1);
        book(_h_Wm_eta, 10, 1, 1);
        book(_h_W_asym, 35, 1, 1);
      }
      if (_runZ) {
        book(_h_Zcenlow_y_dressed,  11, 1, 1);
        book(_h_Zcenpeak_y_dressed, 12, 1, 1);
        book(_h_Zcenhigh_y_dressed, 13, 1, 1);
        book(_h_Zfwdpeak_y_dressed, 14, 1, 1);
        book(_h_Zfwdhigh_y_dressed, 15, 1, 1);
      }
    }


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

      // W reco, starting with MET
      const P4& pmiss = apply<MissingMom>(event, "MET").missingMom();

      // Identify the closest-matching l+MET to m == mW
      const Particles& es = apply<LeptonFinder>(event, "Elecs").particles();
      const Particles es_mtfilt = select(es, [&](const Particle& e){ return mT(e, pmiss) > 40*GeV; });
      const int iefound = closestMatchIndex(es_mtfilt, pmiss, Kin::mass, 80.4*GeV);
      const Particles& mus = apply<LeptonFinder>(event, "Muons").particles();
      const Particles mus_mtfilt = select(mus, [&](const Particle& m){ return mT(m, pmiss) > 40*GeV; });
      const int imfound = closestMatchIndex(mus_mtfilt, pmiss, Kin::mass, 80.4*GeV);

      // Require only one W candidate
      if (pmiss.pT() > 25*GeV && (int(iefound >= 0) + int(imfound >= 0)) == 1 && _runW) {
        Particle lep;
        if (_mode != 2 && iefound >= 0) lep = es_mtfilt[iefound];
        else if (_mode != 1 && imfound >= 0) lep = mus_mtfilt[imfound];

        if (lep.charge3() == 3) _h_Wp_eta->fill(lep.abseta());
        else if (lep.charge3() == -3) _h_Wm_eta->fill(lep.abseta());
      }


      // Now the Z stuff.
      const DileptonFinder& zee = apply<DileptonFinder>(event, "Zee");
      const DileptonFinder& zmm = apply<DileptonFinder>(event, "Zmm");
      if ((zee.bosons().size() + zmm.bosons().size()) == 1 && _runZ) {
        Particle zboson;
        if (_mode != 2 && zee.bosons().size() == 1) zboson = zee.boson();
        else if (_mode !=1 && zmm.bosons().size() == 1 ) zboson = zmm.boson();

        const Particles& leptons = zboson.constituents();
        if (leptons.size() > 1) {
          const double zrap  = zboson.absrap();
          const double zmass = zboson.mass();
          const double eta1 = leptons[0].abseta();
          const double eta2 = leptons[1].abseta();

          // Separation into central/forward and three mass bins
          if (eta1 < 2.5 && eta2 < 2.5) {
            if (zmass < 66.0*GeV)        _h_Zcenlow_y_dressed->fill(zrap);
            else if (zmass < 116.0*GeV)  _h_Zcenpeak_y_dressed->fill(zrap);
            else                         _h_Zcenhigh_y_dressed->fill(zrap);
          }
          else if ((eta1 < 2.5 && 2.5 < eta2 && eta2 < 4.9) || (eta2 < 2.5 && 2.5 < eta1 && eta1 < 4.9)) {
            if (zmass > 66.0*GeV) {
              if (zmass < 116.0*GeV)  _h_Zfwdpeak_y_dressed->fill(zrap);
              else                    _h_Zfwdhigh_y_dressed->fill(zrap);
            }
          }
        }
      }
    }


    /// Normalise histograms etc., after the run
    void finalize() {

      // Construct asymmetry: (dsig+/deta - dsig-/deta) / (dsig+/deta + dsig-/deta)
      if (_runW) asymm(_h_Wp_eta, _h_Wm_eta, _h_W_asym);

      ///  Normalise, scale and otherwise manipulate histograms here
      double lfac = 1.0;
      // If we running on both electrons and muons, divide by two -> xsec for one flavour
      if (_mode == 0) lfac = 0.5;
      const double sf = lfac * 0.5 * crossSection() /picobarn / sumOfWeights(); //< 0.5 accounts for folding +/- rapidity

      if (_runW){
        scale(_h_Wp_eta, sf);
        scale(_h_Wm_eta, sf);
      }

      if (_runZ){
        scale(_h_Zcenlow_y_dressed, sf);
        scale(_h_Zcenpeak_y_dressed, sf);
        scale(_h_Zcenhigh_y_dressed, sf);
        scale(_h_Zfwdpeak_y_dressed, sf);
        scale(_h_Zfwdhigh_y_dressed, sf);
      }
    }

    /// @}


  protected:

    size_t _mode;
    bool _runZ, _runW;


  private:

    /// @name Histograms
    /// @{
    Histo1DPtr _h_Wp_eta, _h_Wm_eta;
    Estimate1DPtr _h_W_asym;

    Histo1DPtr _h_Zcenlow_y_dressed;
    Histo1DPtr _h_Zcenpeak_y_dressed;
    Histo1DPtr _h_Zcenhigh_y_dressed;
    Histo1DPtr _h_Zfwdpeak_y_dressed;
    Histo1DPtr _h_Zfwdhigh_y_dressed;
    /// @}

  };


  RIVET_DECLARE_PLUGIN(ATLAS_2016_I1502620);

}