rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

ATLAS_2019_I1720438

Measurement of the $WZ$ production cross section at 13 TeV
Experiment: ATLAS (LHC)
Inspire ID: 1720438
Status: UNVALIDATED
Authors:
  • Eirini Kasimi
  • Emmanuel Sauvan
References: Beams: p+ p+
Beam energies: (6500.0, 6500.0) GeV
Run details:
  • pp -> WZ + X, diboson decays to electrons or muons, data only for single channel

The production of $W^\pm Z$ events in proton--proton collisions at a centre-of-mass energy of 13 TeV is measured with the ATLAS detector at the LHC. The collected data correspond to an integrated luminosity of 36.1 fb${}^{-1}$ . The $W^\pm Z$ candidates are reconstructed using leptonic decays of the gauge bosons into electrons or muons. The measured inclusive cross section in the detector fiducial region for leptonic decay modes is $\sigma(W^\pm Z\to\ell^\prime\nu\ell\ell \text{fid.}) = 63.7\pm 3.2$(stat.)$\pm 1.0$(sys.)$\pm 1.4$(lumi.) fb. In comparison, the next-to-leading-order Standard Model prediction is 61.5-1.3+1.4 fb. Cross sections for $W^+Z$ and $W^-Z$ production and their ratio are presented as well as differentialcross sections for several kinematic observable. Users should note that explicit matching of lepton flavour between individual SM neutrinos and charged leptons is used in this analysis routine, to match the MC-based correction to the fiducial region applied in the paper. The data are therefore only valid under the assumption of the Standard Model and cannot be used for BSM reinterpretation. Uses SM neutrino-lepton flavour matching and a resonant shape algorithm assuming the Standard Model, to match the MC-based correction to the fiducial region applied in the paper. This routine is therefore only valid under the assumption of the Standard Model and cannot be used for BSM reinterpretation

Source code: ATLAS_2019_I1720438.cc
  1// -*- C++ -*-
  2#include "Rivet/Analysis.hh"
  3#include "Rivet/Projections/FinalState.hh"
  4#include "Rivet/Projections/FastJets.hh"
  5#include "Rivet/Projections/IdentifiedFinalState.hh"
  6#include "Rivet/Projections/PromptFinalState.hh"
  7#include "Rivet/Projections/LeptonFinder.hh"
  8#include "Rivet/Projections/VetoedFinalState.hh"
  9
 10namespace Rivet {
 11
 12
 13  /// @brief WZ production cross-section at 13 TeV
 14  class ATLAS_2019_I1720438 : public Analysis {
 15  public:
 16
 17    /// Constructor
 18    RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2019_I1720438);
 19
 20    /// @name Analysis methods
 21    /// @{
 22
 23    /// Book histograms and initialise projections before the run
 24    void init() {
 25
 26      PromptFinalState photons(Cuts::abspid == PID::PHOTON);
 27
 28      // Electrons and muons in Fiducial PS
 29      PromptFinalState leptons(Cuts::abspid == PID::ELECTRON || Cuts::abspid == PID::MUON);
 30      leptons.acceptTauDecays(false);
 31      LeptonFinder dressedleptons(leptons, photons, 0.1);
 32      declare(dressedleptons, "LeptonFinder");
 33
 34      // Prompt neutrinos (yikes!)
 35      IdentifiedFinalState nu_id;
 36      nu_id.acceptNeutrinos();
 37      PromptFinalState neutrinos(nu_id);
 38      neutrinos.acceptTauDecays(false);
 39      declare(neutrinos, "Neutrinos");
 40      MSG_WARNING("\033[91;1mLIMITED VALIDITY - check info file for details!\033[m");
 41
 42      // Muons
 43      PromptFinalState bare_mu(Cuts::abspid == PID::MUON, TauDecaysAs::PROMPT);
 44      LeptonFinder all_dressed_mu(bare_mu, photons, 0.1, Cuts::abseta < 2.5);
 45
 46      // Electrons
 47      PromptFinalState bare_el(Cuts::abspid == PID::ELECTRON, TauDecaysAs::PROMPT);
 48      LeptonFinder all_dressed_el(bare_el, photons, 0.1, Cuts::abseta < 2.5);
 49
 50      //Jet forming
 51      VetoedFinalState vfs(FinalState(Cuts::abseta < 5.0));
 52      vfs.addVetoOnThisFinalState(all_dressed_el);
 53      vfs.addVetoOnThisFinalState(all_dressed_mu);
 54
 55      FastJets jets(vfs, JetAlg::ANTIKT, 0.4, JetMuons::ALL, JetInvisibles::DECAY);
 56      declare(jets, "Jets");
 57
 58      // Book auxiliary histograms
 59      book(_h["pTZ"],    "_pTZ",    refData( 8, 1, 1));
 60      book(_h["pTW"],    "_pTW",    refData(10, 1, 1));
 61      book(_h["mTWZ"],   "_mTWZ",   refData(12, 1, 1));
 62      book(_h["dPhiWZ"], "_dPhiWZ", refData(14, 1, 1));
 63      book(_h["pTv"],    "_pTV",    refData(16, 1, 1));
 64      book(_h["dRapWZ"], "_drapWZ", refData(18, 1, 1));
 65      book(_h["Mjj"],    "_mjj",    refData(22, 1, 1));
 66
 67      // Book discrete histogram
 68      book(_d, 20, 1, 1);
 69
 70      // book output bar charts
 71      book(_s["pTZ"],     8, 1, 1);
 72      book(_s["pTW"],    10, 1, 1);
 73      book(_s["mTWZ"],   12, 1, 1);
 74      book(_s["dPhiWZ"], 14, 1, 1);
 75      book(_s["pTv"],    16, 1, 1);
 76      book(_s["dRapWZ"], 18, 1, 1);
 77      book(_s["Mjj"],    22, 1, 1);
 78
 79    }
 80
 81
 82    void analyze(const Event& event) {
 83
 84      if (sedges.empty())  sedges = _d->xEdges();
 85
 86      const Particles& dressedleptons = apply<LeptonFinder>(event, "LeptonFinder").particlesByPt();
 87      const Particles& neutrinos = apply<PromptFinalState>(event, "Neutrinos").particlesByPt();
 88      Jets jets = apply<FastJets>(event, "Jets").jetsByPt(Cuts::pT > 25*GeV && Cuts::abseta < 4.5);
 89      int i, j, k;
 90      double MassZ01 = 0., MassZ02 = 0., MassZ12 = 0.;
 91      double MassW0 = 0., MassW1 = 0., MassW2 = 0.;
 92      double WeightZ1, WeightZ2, WeightZ3;
 93      double WeightW1, WeightW2, WeightW3;
 94      double M1, M2, M3;
 95      double WeightTotal1, WeightTotal2, WeightTotal3;
 96
 97      //---Fiducial PS: assign leptons to W and Z bosons using Resonant shape algorithm
 98       if (dressedleptons.size() < 3 || neutrinos.size() < 1) vetoEvent;
 99
100      int icomb=0;
101      // try Z pair of leptons 01
102      if ( (dressedleptons[0].pid() ==-(dressedleptons[1].pid())) &&
103           (dressedleptons[2].pid()*neutrinos[0].pid()< 0) &&
104           (dressedleptons[2].abspid()==neutrinos[0].abspid()-1)) {
105        MassZ01 = (dressedleptons[0].momentum() + dressedleptons[1].momentum()).mass();
106        MassW2 = (dressedleptons[2].momentum() + neutrinos[0].momentum()).mass();
107        icomb = 1;
108      }
109
110      // try Z pair of leptons 02
111      if ( (dressedleptons[0].pid()==-(dressedleptons[2].pid())) &&
112           (dressedleptons[1].pid()*neutrinos[0].pid()< 0) &&
113           (dressedleptons[1].abspid()==neutrinos[0].abspid()-1)) {
114        MassZ02 = (dressedleptons[0].momentum() + dressedleptons[2].momentum()).mass();
115        MassW1 = (dressedleptons[1].momentum() + neutrinos[0].momentum()).mass();
116        icomb = 2;
117      }
118      // try Z pair of leptons 12
119      if ( (dressedleptons[1].pid()==-(dressedleptons[2].pid())) &&
120           (dressedleptons[0].pid()*neutrinos[0].pid()< 0) &&
121           (dressedleptons[0].abspid()==neutrinos[0].abspid()-1)) {
122        MassZ12 = (dressedleptons[1].momentum() + dressedleptons[2].momentum()).mass();
123        MassW0 = (dressedleptons[0].momentum() + neutrinos[0].momentum()).mass();
124        icomb = 3;
125      }
126
127      if (icomb<=0)  vetoEvent;
128
129
130      WeightZ1 = 1/(pow(MassZ01*MassZ01 - MZ_PDG*MZ_PDG,2) + pow(MZ_PDG*GammaZ_PDG,2));
131      WeightW1 = 1/(pow(MassW2*MassW2 - MW_PDG*MW_PDG,2) + pow(MW_PDG*GammaW_PDG,2));
132      WeightTotal1 = WeightZ1*WeightW1;
133      M1 = -1*WeightTotal1;
134
135      WeightZ2 = 1/(pow(MassZ02*MassZ02- MZ_PDG*MZ_PDG,2) + pow(MZ_PDG*GammaZ_PDG,2));
136      WeightW2 = 1/(pow(MassW1*MassW1- MW_PDG*MW_PDG,2) + pow(MW_PDG*GammaW_PDG,2));
137      WeightTotal2 = WeightZ2*WeightW2;
138      M2 = -1*WeightTotal2;
139
140      WeightZ3 = 1/(pow(MassZ12*MassZ12 - MZ_PDG*MZ_PDG,2) + pow(MZ_PDG*GammaZ_PDG,2));
141      WeightW3 = 1/(pow(MassW0*MassW0 - MW_PDG*MW_PDG,2) + pow(MW_PDG*GammaW_PDG,2));
142      WeightTotal3 = WeightZ3*WeightW3;
143      M3 = -1*WeightTotal3;
144
145      if( (M1 < M2 && M1 < M3) || (MassZ01 != 0 && MassW2 != 0 && MassZ02 == 0 && MassZ12 == 0) ) {
146        i = 0; j = 1; k = 2;
147      }
148      if((M2 < M1 && M2 < M3) || (MassZ02 != 0 && MassW1 != 0 && MassZ01 == 0 && MassZ12 == 0) ) {
149        i = 0; j = 2; k = 1;
150      }
151      if((M3 < M1 && M3 < M2) || (MassZ12 != 0 && MassW0 != 0 && MassZ01 == 0 && MassZ02 == 0) ) {
152        i = 1; j = 2; k = 0;
153      }
154
155      FourMomentum Zlepton1 = dressedleptons[i].mom();
156      FourMomentum Zlepton2 = dressedleptons[j].mom();
157      FourMomentum Wlepton  = dressedleptons[k].mom();
158      FourMomentum Zboson   = dressedleptons[i].mom()+dressedleptons[j].mom();
159      FourMomentum Wboson   = dressedleptons[k].mom()+neutrinos[0].mom();
160
161      double cosLepNeut;
162      double Wboson_mT = 0;
163   	  double norm = Wlepton.pT() * neutrinos[0].pt();
164 	    if (norm != 0) {
165        cosLepNeut = ( Wlepton.px()*neutrinos[0].px() + Wlepton.py()*neutrinos[0].py() )/norm;
166        if ( 1-cosLepNeut >= 0 )  Wboson_mT = sqrt( 2 * Wlepton.pT() * neutrinos[0].pt() * (1-cosLepNeut ) );
167      }
168
169      //---- CUTS (based on Table 1 WZ: 36.1 fb-1)----//
170      if (Wlepton.pT() <= 20*GeV || Zlepton1.pT() <= 15*GeV || Zlepton2.pT() <= 15*GeV)  vetoEvent;
171      if (Wlepton.abseta() >= 2.5 || Zlepton1.abseta() >= 2.5 || Zlepton2.abseta() >= 2.5)  vetoEvent;
172      if (fabs(Zboson.mass()/GeV - MZ_PDG) >= 10.) vetoEvent;
173      if (Wboson_mT <= 30*GeV)                     vetoEvent;
174      if (deltaR(Zlepton1, Zlepton2) <= 0.2)       vetoEvent;
175      if (deltaR(Zlepton1, Wlepton)  <= 0.3)       vetoEvent;
176      if (deltaR(Zlepton2, Wlepton)  <= 0.3)       vetoEvent;
177
178      double pTZ = Zboson.pT()/GeV;
179      double WZ_pt = (Zlepton1.pt() + Zlepton2.pt() + Wlepton.pt() + neutrinos[0].pt())/GeV;
180      double WZ_px = (Zlepton1.px() + Zlepton2.px() + Wlepton.px() + neutrinos[0].px())/GeV;
181      double WZ_py = (Zlepton1.py() + Zlepton2.py() + Wlepton.py() + neutrinos[0].py())/GeV;
182      double mTWZ = sqrt( pow(WZ_pt, 2) - ( pow(WZ_px, 2) + pow(WZ_py,2) ));
183
184      double dPhiWZTruth = acos(cos(Zboson.phi()-Wboson.phi()));
185      double pTW = Wboson.pT()/GeV;
186      double pTv = neutrinos[0].pT()/GeV;
187      double AbsDeltay = fabs(Zboson.rapidity()-Wlepton.rapidity());
188
189      idiscard(jets, [&](const Jet& j) {
190        return deltaR(j, Zlepton1) < 0.3 || deltaR(j, Zlepton2) < 0.3 || deltaR(j, Wlepton) < 0.3;
191      });
192
193      size_t njets = jets.size()>5? 5 : jets.size();
194      _d->fill(sedges[njets]);
195
196      if (njets > 1) {
197        double mjj = (jets[0].mom() + jets[1].mom()).mass()/GeV;
198        if (mjj > 800.)  mjj = 800.;
199        _h["Mjj"]->fill(mjj);
200      }
201
202      if (pTZ > 220.) pTZ = 220.;
203      _h["pTZ"]->fill(pTZ);
204
205      if (pTW > 220.)  pTW = 220.;
206      _h["pTW"]->fill(pTW);
207
208      if (mTWZ > 600.)  mTWZ = 600.;
209      _h["mTWZ"]->fill(mTWZ);
210
211      _h["dPhiWZ"]->fill(dPhiWZTruth);
212
213      if (pTv > 90.)  pTv = 90.;
214      _h["pTv"]->fill(pTv);
215
216      _h["dRapWZ"]->fill(AbsDeltay);
217
218    }
219
220
221    void finalize() {
222
223      scale(_h, 0.25 * crossSectionPerEvent() / femtobarn); // data values are for _single_ lepton channel
224      scale(_d, 0.25 * crossSectionPerEvent() / femtobarn); // data values are for _single_ lepton channel
225      // unfortunately, no differential cross-sections were measured in this analysis
226      for (auto &item : _h)  barchart(item.second, _s[item.first]);
227
228    }
229
230    /// @}
231
232
233  private:
234
235
236    /// @name Histograms
237    /// @{
238    BinnedHistoPtr<string> _d;
239    map<string, Histo1DPtr> _h;
240    map<string, Estimate1DPtr> _s;
241    vector<string> sedges;
242    /// @}
243
244    const double MZ_PDG = 91.1876;
245    const double MW_PDG = 80.385;
246    const double GammaZ_PDG = 2.4952;
247    const double GammaW_PDG = 2.085;
248
249  };
250
251
252  RIVET_DECLARE_PLUGIN(ATLAS_2019_I1720438);
253
254}