rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

CMS_2012_I1298807

Inclusive ZZ production cross section and constraints on anomalous triple gauge couplings at 8 TeV
Experiment: CMS (LHC)
Inspire ID: 1298807
Status: VALIDATED
Authors:
  • Alexander Savin
  • Ian Ross
References: Beams: p+ p+
Beam energies: (4000.0, 4000.0) GeV
Run details:
  • ZZ production, leptonic Z decays

A measurement of the inclusive $ZZ$ production cross section and constraints on anomalous triple gauge couplings in proton-proton collisions at $\sqrt{s} = 8 TeV$ are presented. The analysis is based on a data sample, corresponding to an integrated luminosity of 19.6/fb, collected with the CMS experiment at the LHC. The measurements are performed in the leptonic decay modes $ZZ \to lll^\prime l^\prime$, where $l = e,\mu$ and $l^\prime = e, \mu, \tau$. The measured total cross section $ \sigma (pp \to ZZ) = 7.7 \pm 0.5 (\mathrm{stat}) + 0.5 -0.4 (\mathrm{syst}) \pm 0.4 (\mathrm{theo}) \pm 0.2 (\mathrm{lumi}) pb$, for both $Z$ bosons produced in the mass range $60 < m_Z < 120 \text{GeV}$, is consistent with standard model predictions. Differential cross sections, in phase space $p_T(\mu) > 5 \text{GeV}$, $p_T(e) > 7 \text{GeV}$, $|\eta(\mu)|<2.4$ , $|\eta(e)|<2.5$ and the 60--120 \text{GeV} mass requirement, are measured and well described by the theoretical predictions. The invariant mass distribution of the four-lepton system is used to set limits on anomalous $ZZZ$ and $ZZ\gamma$ couplings at the 95\% confidence level, $-0.004 < f4Z < 0.004$, $-0.004 < f5Z < 0.004$, $-0.005 < f4\gamma < 0.005$, and $-0.005 < f5\gamma < 0.005.$

Source code: CMS_2012_I1298807.cc
  1// -*- C++ -*-
  2#include "Rivet/Analysis.hh"
  3#include "Rivet/Projections/FinalState.hh"
  4#include "Rivet/Projections/IdentifiedFinalState.hh"
  5#include "Rivet/Projections/DileptonFinder.hh"
  6#include "Rivet/Projections/VetoedFinalState.hh"
  7#include "Rivet/Projections/MergedFinalState.hh"
  8
  9namespace Rivet {
 10
 11
 12  /// Inclusive ZZ production cross section and constraints on anomalous triple gauge couplings
 13  class CMS_2012_I1298807 : public Analysis {
 14  public:
 15
 16    // Constructor
 17    RIVET_DEFAULT_ANALYSIS_CTOR(CMS_2012_I1298807);
 18
 19
 20    /// Initialise projections and histograms
 21    void init() {
 22
 23      FinalState leptons((Cuts::abspid == PID::ELECTRON && Cuts::abseta < 2.5) ||
 24                         (Cuts::abspid == PID::MUON && Cuts::abseta < 2.4));
 25      declare(leptons, "Leptons");
 26
 27      Cut cut_el = Cuts::abseta < 2.5 && Cuts::pT > 7.0*GeV;
 28      DileptonFinder zeefinder(91.2*GeV, 0.1, cut_el && Cuts::abspid == PID::ELECTRON,
 29                               Cuts::massIn(60*GeV, 120*GeV));
 30      declare(zeefinder, "ZeeFinder");
 31
 32      Cut cut_mu = Cuts::abseta < 2.4 && Cuts::pT > 5.0*GeV;
 33      DileptonFinder zmmfinder(91.2*GeV, 0.1, cut_mu && Cuts::abspid == PID::MUON,
 34                               Cuts::massIn(60*GeV, 120*GeV));
 35      declare(zmmfinder, "ZmmFinder");
 36
 37      VetoedFinalState fs_woZmm;
 38      fs_woZmm.addVetoOnThisFinalState(zmmfinder);
 39      VetoedFinalState fs_woZee;
 40      fs_woZee.addVetoOnThisFinalState(zeefinder);
 41
 42      DileptonFinder zeefinder_woZee(fs_woZee, 91.2*GeV, 0.1,
 43                                     cut_el && Cuts::abspid == PID::ELECTRON, Cuts::massIn(60*GeV, 120*GeV));
 44      declare(zeefinder_woZee, "Zeefinder_WoZee");
 45      DileptonFinder zmmfinder_woZmm(fs_woZmm, 91.2*GeV, 0.1,
 46                                     cut_mu && Cuts::abspid == PID::MUON, Cuts::massIn(60*GeV, 120*GeV));
 47      declare(zmmfinder_woZmm, "Zmmfinder_WoZmm");
 48
 49      // Book histograms
 50      book(_h["pt_l1"],   1, 1, 1);
 51      book(_h["pt_z1"],   1, 1, 2);
 52      book(_h["pt_zz"],   1, 1, 3);
 53      book(_h["m_zz"],    1, 1, 4);
 54      book(_h["dphi_zz"], 1, 1, 5);
 55      book(_h["dR_zz"],   1, 1, 6);
 56
 57    }
 58
 59
 60    // Perform the per-event analysis
 61    void analyze(const Event& evt) {
 62
 63      // Find leading leptons and apply cuts
 64      const Particles& leptons = apply<FinalState>(evt, "Leptons").particlesByPt();
 65      if (leptons.size() < 2) vetoEvent;
 66      const double leading_l_pt = leptons[0].pT();
 67      const double second_l_pt = leptons[1].pT();
 68      if (leading_l_pt < 20*GeV || second_l_pt < 10*GeV) vetoEvent;
 69
 70      // Find acceptable ZZ combinations and build four-momenta, otherwise veto
 71      const DileptonFinder& zeefinder = apply<DileptonFinder>(evt, "ZeeFinder");
 72      const DileptonFinder& zeefinder_woZee = apply<DileptonFinder>(evt, "Zeefinder_WoZee");
 73      const DileptonFinder& zmmfinder = apply<DileptonFinder>(evt, "ZmmFinder");
 74      const DileptonFinder& zmmfinder_woZmm = apply<DileptonFinder>(evt, "Zmmfinder_WoZmm");
 75
 76      FourMomentum pZ_a, pZ_b, pZ_1, pZ_2;
 77      FourMomentum pZZ, Z_a_l1, Z_a_l2, Z_b_l1, Z_b_l2;
 78      if (zeefinder.bosons().size() > 0 && zmmfinder.bosons().size() > 0) {
 79        pZ_a = zeefinder.boson();
 80        pZ_b = zmmfinder.boson();
 81        pZZ = pZ_a + pZ_b;
 82        pZ_1 = pZ_a;
 83        pZ_2 = pZ_b;
 84        Z_a_l1 = zeefinder.constituents()[0];
 85        Z_a_l2 = zeefinder.constituents()[1];
 86        Z_b_l1 = zmmfinder.constituents()[0];
 87        Z_b_l2 = zmmfinder.constituents()[1];
 88      } else if (zeefinder.bosons().size() > 0 && zeefinder_woZee.bosons().size() > 0) {
 89        pZ_a = zeefinder.boson();
 90        pZ_b = zeefinder_woZee.boson();
 91        pZZ = pZ_a + pZ_b;
 92        pZ_1 = pZ_a;
 93        pZ_2 = pZ_b;
 94        Z_a_l1 = zeefinder.constituents()[0];
 95        Z_a_l2 = zeefinder.constituents()[1];
 96        Z_b_l1 = zeefinder_woZee.constituents()[0];
 97        Z_b_l2 = zeefinder_woZee.constituents()[1];
 98      } else if (zmmfinder.bosons().size() > 0 && zmmfinder_woZmm.bosons().size() > 0) {
 99        pZ_a = zmmfinder.boson();
100        pZ_b = zmmfinder_woZmm.boson();
101        pZZ = pZ_a + pZ_b;
102        pZ_1 = pZ_a;
103        pZ_2 = pZ_b;
104        Z_a_l1 = zmmfinder.constituents()[0];
105        Z_a_l2 = zmmfinder.constituents()[1];
106        Z_b_l1 = zmmfinder_woZmm.constituents()[0];
107        Z_b_l2 = zmmfinder_woZmm.constituents()[1];
108      } else {
109        vetoEvent;
110      }
111
112      // Set ordered pT variables
113      /// @todo Looks like there should be a nicer way than this
114      double pt_l1 = Z_a_l1.pT();
115      if (Z_a_l2.pT() > pt_l1) pt_l1 = Z_a_l2.pT();
116      if (Z_b_l1.pT() > pt_l1) pt_l1 = Z_b_l1.pT();
117      if (Z_b_l2.pT() > pt_l1) pt_l1 = Z_b_l2.pT();
118
119      // Leading Z pT
120      double pt_z1 = pZ_a.pT();
121      if (pZ_b.pT() > pZ_a.pT()) {
122        pt_z1 = pZ_b.pT();
123        pZ_1 = pZ_b;
124        pZ_2 = pZ_a;
125      }
126
127      // Fill histograms
128      _h["pt_zz"]->fill(pZZ.pT()/GeV);
129      _h["m_zz"]->fill(pZZ.mass()/GeV);
130      _h["dphi_zz"]->fill(deltaPhi(pZ_a, pZ_b));
131      _h["dR_zz"]->fill(deltaR(pZ_a, pZ_b, PSEUDORAPIDITY));
132      _h["pt_z1"]->fill(pt_z1/GeV);
133      _h["pt_l1"]->fill(pt_l1/GeV);
134
135    }
136
137
138    /// Scale histograms
139    /// @todo Why is it scaling by bin width twice??
140    void finalize() {
141
142      for (auto& item : _h) {
143        double area = 0.;
144        for (auto& b : item.second->bins()) {
145          b.scaleW(1.0/b.xWidth());
146          area += b.sumW() / b.dVol();
147        }
148        if (area)  scale(item.second, 1.0 / area);
149      }
150    }
151
152
153    /// Histograms
154    map<string, Histo1DPtr> _h;
155
156  };
157
158
159  RIVET_DECLARE_PLUGIN(CMS_2012_I1298807);
160
161}