rivet is hosted by Hepforge, IPPP Durham

Rivet analyses reference

ATLAS_2016_I1492320

WWW production at 8 TeV
Experiment: ATLAS (LHC)
Inspire ID: 1492320
Status: VALIDATED
Authors:
  • Alex Long
  • Ismet Siral
  • Louis Helary
  • Christian Gutschow
References: Beams: p+ p+
Beam energies: (4000.0, 4000.0) GeV
Run details:
  • pp -> WWW production at 8 TeV

This paper reports a search for triboson $W^\pm W^\pm W^\mp$ production in two decay channels ($W^\pm W^\pm W^\mp \to \ell^\pm\nu \ell^\pm\nu \ell^\mp\nu$) and ($W^\pm W^\pm W^\mp \to \ell^\pm\nu \ell^\pm\nu jj$ with $\ell = e,\mu$) in proton-proton collision data corresponding to an integrated luminosity of 20.3 fb${}^{-1}$ at a centre-of-mass energy of 8 TeV with the ATLAS detector at the Large Hadron Collider. Events with exactly three charged leptons, or two leptons with the same electric charge in association with two jets, are selected. The total number of events observed in data is consistent with the Standard Model (SM) predictions. The observed 95 % confidence level upper limit on the SM $W^\pm W^\pm W^\mp$ production cross section is found to be 730 fb with an expected limit of 560 fb in the absence of SM $W^\pm W^\pm W^\mp$ production. Limits are also set on $WWWW$ anomalous quartic gauge couplings. Default will make both plots. Use options 2L2J or 3J to make just one.

Source code: ATLAS_2016_I1492320.cc
  1// -*- C++ -*
  2#include "Rivet/Analysis.hh"
  3#include "Rivet/Projections/FinalState.hh"
  4#include "Rivet/Projections/FastJets.hh"
  5#include "Rivet/Projections/VetoedFinalState.hh"
  6#include "Rivet/Projections/MissingMomentum.hh"
  7#include "Rivet/Projections/LeptonFinder.hh"
  8#include "Rivet/Projections/PromptFinalState.hh"
  9#include "Rivet/Projections/HeavyHadrons.hh"
 10
 11namespace Rivet {
 12
 13
 14  /// @brief WWW cross-section at 8 TeV, 3L mode
 15  class ATLAS_2016_I1492320 : public Analysis {
 16  public:
 17
 18    // Default constructor
 19    RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2016_I1492320);
 20
 21    /// @name Analysis methods
 22    /// @{
 23
 24    /// Book histograms and initialise projections before the run
 25    void init() {
 26
 27      // Get options from the new option system
 28      _mode = 0;
 29      if ( getOption("LMODE") == "3L" ) _mode = 1;
 30      if ( getOption("LMODE") == "2L2J" ) _mode = 2;
 31
 32
 33      // Charged leptons within acceptance
 34      const PromptFinalState chLep_fid = PromptFinalState(Cuts::abspid == PID::ELECTRON || Cuts::abspid == PID::MUON);
 35      const PromptFinalState photon_fs = PromptFinalState(Cuts::abspid == PID::PHOTON);
 36      const LeptonFinder dressed_leps(chLep_fid, photon_fs, 0.1, Cuts::pT > 20*GeV && Cuts::abseta < 2.5);
 37      declare(dressed_leps, "LeptonFinder");
 38
 39      const LeptonFinder dressed_leps2(chLep_fid, photon_fs, 0.1, Cuts::pT > 10*GeV);
 40      declare(dressed_leps2, "LeptonFinder2");
 41
 42
 43      // Jets, anti-kt 0.4
 44      VetoedFinalState fsJets(FinalState(Cuts::abseta < 7.0)); //final state for jet finding: veto leptons and neutrinos
 45      fsJets.vetoNeutrinos();
 46      fsJets.addVetoOnThisFinalState(photon_fs);
 47      fsJets.addVetoOnThisFinalState(chLep_fid);
 48      declare(FastJets(fsJets, JetAlg::ANTIKT, 0.4), "Jets");
 49
 50      // b hadrons for b-tagging
 51      declare(HeavyHadrons(Cuts::abseta < 2.5 && Cuts::pT > 5*GeV), "Bhadrons");
 52
 53      // Missing momentum
 54      declare(MissingMomentum(), "MET");
 55
 56      // Histograms
 57      if (_mode != 2){
 58	book(_h_fiducial_3l, "d01-x01-y01");
 59      }
 60      if (_mode != 1){
 61	book(_h_2l2j, "d01-x01-y02");
 62      }
 63    }
 64
 65
 66    /// Perform the per-event analysis
 67    void analyze(const Event& event) {
 68
 69      // Get the dressed leptons, sorted by pT of their constituent bare lepton (!!)
 70      DressedLeptons _vbs_lep = apply<LeptonFinder>(event, "LeptonFinder").dressedLeptons();
 71      if (_vbs_lep.size() == 3 && _mode != 2) {
 72	std::sort(_vbs_lep.begin(), _vbs_lep.end(), [](const DressedLepton& l1, const DressedLepton& l2) {
 73	    return (l1.bareLepton().pT() > l2.bareLepton().pT());
 74	  });
 75
 76	// Get the jets
 77	const Jets& _vbs_jets = apply<FastJets>(event, "Jets").jetsByPt(Cuts::pT > 25*GeV && Cuts::abseta < 4.5);
 78	if (_vbs_jets.size() <= 1) {
 79
 80	  // Determine nsfos pairs for channel classification
 81	  int nSFOS = 0;
 82	  for (size_t i = 0; i < _vbs_lep.size(); ++i) {
 83	    const double ch_l0 = _vbs_lep[i].charge();
 84	    for (size_t j = i + 1; j < _vbs_lep.size(); ++j) {
 85	      const double ch_l1 = _vbs_lep[j].charge();
 86	      if (_vbs_lep[i].abspid() == _vbs_lep[j].abspid() && ch_l0*ch_l1 < 0) ++nSFOS;
 87	    }
 88	  }
 89
 90	  double minDRll = DBL_MAX, mSFOS_MinDiff = DBL_MAX, meeSS_MinDiff = DBL_MAX, mSF_min = DBL_MAX;
 91	  for (size_t i = 0; i < _vbs_lep.size(); ++i) {
 92	    const double ch_l0 = _vbs_lep[i].charge();
 93	    for (size_t j = i + 1; j < _vbs_lep.size(); ++j) {
 94	      const double ch_l1 = _vbs_lep[j].charge();
 95	      const bool samesign = ch_l0*ch_l1 > 0;
 96
 97	      // Update min dR between leptons
 98	      minDRll = min(minDRll, deltaR(_vbs_lep[i], _vbs_lep[j]));
 99
100	      // Require same flavour
101	      if (_vbs_lep[i].abspid() != _vbs_lep[j].abspid()) continue;
102
103	      // SF dilepton mass (used several times)
104	      const double mSF = (_vbs_lep[i].momentum() + _vbs_lep[j].momentum()).mass();
105
106	      // Determine min for all same-flavor pairs
107	      mSF_min = min(mSF, mSF_min);
108
109	      // Determine min for all m_ee same-sign pairs
110	      if (_vbs_lep[i].abspid() == PID::ELECTRON && samesign) {
111		if (fabs(mSF-ZMASS) < fabs(meeSS_MinDiff-ZMASS)) meeSS_MinDiff = mSF;
112	      }
113
114	      // Determine min for all mSFOS pairs
115	      if (!samesign && fabs(mSF-ZMASS) < abs(mSFOS_MinDiff-ZMASS)) mSFOS_MinDiff = mSF;
116	    }
117	  }
118
119	  bool setVeto = false;
120	  if (minDRll < 0.1) setVeto = true;
121	  if (nSFOS == 0 && mSF_min < 20*GeV) setVeto = true;
122	  if (nSFOS == 0 && fabs(meeSS_MinDiff - ZMASS) < 15*GeV) setVeto = true;
123	  if (nSFOS == 1 && ((ZMASS - mSFOS_MinDiff) < 35*GeV && (mSFOS_MinDiff - ZMASS) < 20*GeV)) setVeto = true;
124	  if (nSFOS == 2 && fabs(mSFOS_MinDiff - ZMASS) < 20*GeV) setVeto = true;
125
126	  if (!setVeto) {
127	    const Vector3& met = -1.0 * apply<MissingMomentum>(event, "MET").vectorEt();
128	    if (nSFOS == 1 && met.mod() < 45*GeV) setVeto = true;
129	    if (nSFOS == 2 && met.mod() < 55*GeV) setVeto = true;
130
131	    if (!setVeto) {
132	      const double dPhi = deltaPhi((_vbs_lep[0].momentum() + _vbs_lep[1].momentum() + _vbs_lep[2].momentum()), met);
133	      if (dPhi < 2.5) setVeto = true;
134	    }
135	    // Fill histo
136	    if (!setVeto) {
137	      _h_fiducial_3l->fill();
138	    }
139	  }
140	}
141      }
142
143      if (_mode != 1){
144	// Get leptons
145	DressedLeptons leps = apply<LeptonFinder>(event, "LeptonFinder").dressedLeptons();
146	if (leps.size() >= 2) {
147	  // Sort the dressed leptons by pt of their constituent lepton (bare lepton pt)
148	  std::sort(leps.begin(), leps.end() ,
149		    [](const DressedLepton& l1, const DressedLepton& l2) {
150		      return (l1.bareLepton().pT() > l2.bareLepton().pT()); });
151	  if (leps[0].pT() < 30*GeV || leps[0].abseta() > 2.5)  vetoEvent;
152	  if (leps[1].pT() < 30*GeV || leps[1].abseta() > 2.5)  vetoEvent;
153
154	  // Get jets
155	  const Jets& jets = apply<FastJets>(event, "Jets").jetsByPt(Cuts::pT > 15*GeV);
156
157	  // Find min dilepton DR and mass
158	  double minDRll = DBL_MAX, mll = DBL_MAX;
159	  for (size_t i = 0; i < leps.size(); ++i) {
160	    for (size_t j = i + 1; j < leps.size(); ++j) {
161	      minDRll = min(minDRll, deltaR(leps[i], leps[j]));
162	      mll = min(mll, (leps[i].momentum() + leps[j].momentum()).mass());
163	    }
164	  }
165	  if (minDRll < 0.1) vetoEvent;
166	  if (mll < 40*GeV) vetoEvent;
167
168	  // Require same-sign leading leptons
169	  if (leps[0].charge()*leps[1].charge() < 0) vetoEvent;
170
171	  // Veto di-electron combinations within 10 GeV of the Z mass
172	  if (fabs(mll - 91.188*GeV) < 10*GeV && leps[0].abspid() == PID::ELECTRON && leps[1].abspid() == PID::ELECTRON) vetoEvent;
173
174	  // Now jet cuts
175	  if (jets.size() < 2) vetoEvent;
176	  if (jets[0].pT() < 30*GeV || jets[0].abseta() > 2.5) vetoEvent;
177	  if (jets[1].pT() < 20*GeV || jets[1].abseta() > 2.5) vetoEvent;
178
179	  // Find closest jet/lepton pair and veto if too close in phi or too far in eta
180	  double minDRLepJets = DBL_MAX;
181	  for (const Jet& jet : jets) {
182	    for (const Particle& lep : leps) minDRLepJets = min(minDRLepJets, deltaR(lep, jet));
183	  }
184	  if (minDRLepJets < 0.3) vetoEvent;
185	  if (fabs(deltaEta(jets[0], jets[1])) > 1.5) vetoEvent;
186
187	  // Dijet mass requirement
188	  double mjj = (jets[0].momentum() + jets[1].momentum()).mass();
189	  if (mjj < 65 || mjj > 105)  vetoEvent;
190	  if (!inRange(mjj, 65*GeV, 105*GeV)) vetoEvent;
191
192	  // Veto if any good jets are b-jets
193	  const Particles& bhadrons = apply<HeavyHadrons>(event, "Bhadrons").bHadrons();
194	  for (const Jet& j : jets) {
195	    if (j.abseta() > 2.5) continue; // outside acceptance of b-tagging
196	    const bool isbJet = any(bhadrons, deltaRLess(j, 0.3));
197	    if (isbJet) vetoEvent;
198	  }
199
200	  // MET vetoing for non-muon events
201	  const MissingMomentum& met = apply<MissingMomentum>(event, "MET");
202	  if (met.vectorEt().mod() < 55*GeV && (leps[0].abspid() != PID::MUON || leps[1].abspid() != PID::MUON)) vetoEvent;
203
204	  // Fill counter
205	  _h_2l2j->fill();
206	}
207      }
208    }
209
210
211
212    /// Normalise histograms etc., after the run
213    void finalize() {
214      if (_mode != 2){
215        scale(_h_fiducial_3l, crossSection()/sumOfWeights()/femtobarn);
216      }
217      if (_mode != 1){
218        scale(_h_2l2j, crossSection()/sumOfWeights()/femtobarn);
219      }
220    }
221
222    /// @}
223
224  protected:
225
226    size_t _mode;
227
228
229  private:
230
231    /// @name Histograms
232    /// @{
233    const double ZMASS = 91.1876*GeV;
234    CounterPtr _h_fiducial_3l;
235    CounterPtr _h_2l2j;
236    /// @}
237
238  };
239
240
241  RIVET_DECLARE_PLUGIN(ATLAS_2016_I1492320);
242
243}