Rivet analyses referenceATLAS_2016_I1492320WWW production at 8 TeVExperiment: ATLAS (LHC) Inspire ID: 1492320 Status: VALIDATED Authors:
Beam energies: (4000.0, 4000.0) GeV Run details:
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}
|