Rivet analyses referenceATLAS_2015_I1394865Inclusive 4-lepton lineshapeExperiment: ATLAS (LHC) Inspire ID: 1394865 Status: TRUE Authors:
Beam energies: (4000.0, 4000.0) GeV Run details:
The four-lepton (4$\ell$, $\ell = e,\mu$) production cross section is measured in the mass range from 80 to 1000 GeV using 20.3 fb$^{-1}$ of data in $pp$ collisions at $\sqrt{s}=8$ TeV collected with the ATLAS detector at the LHC. The $4\ell$ events are produced in the decays of resonant $Z$ and Higgs bosons and the non-resonant $ZZ$ continuum originating from $q\bar{q}$, $gg$, $qg$ initial states. A total of 476 signal candidate events are observed with a background expectation of 26.2$\pm$3.6 events, enabling the measurement of the integrated cross section and the differential cross section as a function of the invariant mass and transverse momentum of the four-lepton system. Source code: ATLAS_2015_I1394865.cc 1// -*- C++ -*-
2#include "Rivet/Analysis.hh"
3#include "Rivet/Projections/FinalState.hh"
4#include "Rivet/Projections/IdentifiedFinalState.hh"
5#include "Rivet/Projections/PromptFinalState.hh"
6#include "Rivet/Projections/LeptonFinder.hh"
7
8namespace Rivet {
9
10
11 /// Inclusive 4-lepton lineshape
12 class ATLAS_2015_I1394865 : public Analysis {
13 public:
14
15 /// Default constructor
16 RIVET_DEFAULT_ANALYSIS_CTOR(ATLAS_2015_I1394865);
17
18
19 void init() {
20 FinalState fs(Cuts::abseta < 5.0);
21 PromptFinalState pfs(Cuts::abseta < 5.0);
22
23 IdentifiedFinalState photon(fs, PID::PHOTON);
24 IdentifiedFinalState bare_EL(pfs, {PID::ELECTRON, -PID::ELECTRON});
25 IdentifiedFinalState bare_MU(pfs, {PID::MUON, -PID::MUON});
26
27 // Selection 1: ZZ-> llll selection
28 Cut etaranges_el = Cuts::abseta < 2.5 && Cuts::pT > 7*GeV;
29 Cut etaranges_mu = Cuts::abseta < 2.7 && Cuts::pT > 6*GeV;
30
31 LeptonFinder electron_sel4l(bare_EL, photon, 0.1, etaranges_el);
32 declare(electron_sel4l, "ELECTRON_sel4l");
33 LeptonFinder muon_sel4l(bare_MU, photon, 0.1, etaranges_mu);
34 declare(muon_sel4l, "MUON_sel4l");
35
36
37 // Both ZZ on-shell histos
38 book(_h_ZZ_mZZ , 1, 1, 1);
39 book(_h_ZZ_pTZZ, 2, 1, 1);
40 }
41
42
43 /// Do the analysis
44 void analyze(const Event& e) {
45 ////////////////////////////////////////////////////////////////////
46 // Preselection of leptons for ZZ-> llll final state
47 ////////////////////////////////////////////////////////////////////
48
49 Particles leptons_sel4l;
50 const DressedLeptons& mu_sel4l = apply<LeptonFinder>(e, "MUON_sel4l").dressedLeptons();
51 const DressedLeptons& el_sel4l = apply<LeptonFinder>(e, "ELECTRON_sel4l").dressedLeptons();
52 const DressedLeptons leptonsFS_sel4l = mu_sel4l + el_sel4l;
53 // leptonsFS_sel4l.insert( leptonsFS_sel4l.end(), mu_sel4l.begin(), mu_sel4l.end() );
54 // leptonsFS_sel4l.insert( leptonsFS_sel4l.end(), el_sel4l.begin(), el_sel4l.end() );
55
56 // mu: pT > 6 GeV, eta < 2.7; ele: pT > 7 GeV, eta < 2.5
57 for (const DressedLepton& l : leptonsFS_sel4l) {
58 if (l.abspid() == PID::ELECTRON) leptons_sel4l.push_back(l); // REDUNDANT: if (l.pT() > 7*GeV && l.abseta() < 2.5)
59 else if (l.abspid() == PID::MUON) leptons_sel4l.push_back(l); // REDUNDANT: if (l.pT() > 6*GeV && l.abseta() < 2.7)
60 }
61
62 //////////////////////////////////////////////////////////////////
63 // Exactly two opposite charged leptons
64 //////////////////////////////////////////////////////////////////
65
66 // Calculate total 'flavour' charge
67 double totalcharge = 0;
68 for (const Particle& l : leptons_sel4l) totalcharge += l.pid();
69
70 // Analyze 4 lepton events
71 if (leptons_sel4l.size() != 4 || totalcharge != 0) vetoEvent;
72
73 // Identify Z states from 4 lepton pairs
74 Zstate Z1, Z2, Z1_alt, Z2_alt;
75 if ( !identifyZstates(Z1, Z2, Z1_alt, Z2_alt, leptons_sel4l) ) vetoEvent;
76
77 const double mZ1 = Z1.mom().mass();
78 const double mZ2 = Z2.mom().mass();
79 const double mZ1_alt = Z1_alt.mom().mass();
80 const double mZ2_alt = Z2_alt.mom().mass();
81 const double pTZ1 = Z1.mom().pT();
82 const double pTZ2 = Z2.mom().pT();
83 const double mZZ = (Z1.mom() + Z2.mom()).mass();
84 const double pTZZ = (Z1.mom() + Z2.mom()).pT();
85
86 // Event selections
87 // pT(Z) > 2 GeV
88 bool pass = pTZ1 > 2*GeV && pTZ2 > 2*GeV;
89 if (!pass) vetoEvent;
90
91 // Lepton kinematics: pT > 20, 15, 10 (8 if muon) GeV
92 int n1 = 0, n2 = 0, n3 = 0;
93 for (Particle& l : leptons_sel4l) {
94 if (l.pT() > 20*GeV) ++n1;
95 if (l.pT() > 15*GeV) ++n2;
96 if (l.pT() > 10*GeV && l.abspid() == PID::ELECTRON) ++n3;
97 if (l.pT() > 8*GeV && l.abspid() == PID::MUON) ++n3;
98 }
99 pass = pass && n1>=1 && n2>=2 && n3>=3;
100 if (!pass) vetoEvent;
101
102 // Dilepton mass: 50 < mZ1 < 120 GeV, 12 < mZ2 < 120 GeV
103 pass = pass && mZ1 > 50*GeV && mZ1 < 120*GeV;
104 pass = pass && mZ2 > 12*GeV && mZ2 < 120*GeV;
105 if (!pass) vetoEvent;
106
107 // Lepton separation: deltaR(l, l') > 0.1 (0.2) for same- (different-) flavor leptons
108 for (size_t i = 0; i < leptons_sel4l.size(); ++i) {
109 for (size_t j = i + 1; j < leptons_sel4l.size(); ++j) {
110 const Particle& l1 = leptons_sel4l[i];
111 const Particle& l2 = leptons_sel4l[j];
112 pass = pass && deltaR(l1, l2) > (l1.abspid() == l2.abspid() ? 0.1 : 0.2);
113 if (!pass) vetoEvent;
114 }
115 }
116
117 // J/Psi veto: m(l+l-) > 5 GeV
118 pass = pass && mZ1 > 5*GeV && mZ2 > 5*GeV && mZ1_alt > 5*GeV && mZ2_alt > 5*GeV;
119 if (!pass) vetoEvent;
120
121 // 80 < m4l < 1000 GeV
122 pass = pass && mZZ > 80*GeV && mZZ < 1000*GeV;
123 if (!pass) vetoEvent;
124
125 // Fill histograms
126 _h_ZZ_mZZ->fill(mZZ);
127 _h_ZZ_pTZZ->fill(pTZZ);
128 }
129
130
131 /// Finalize
132 void finalize() {
133 const double norm = crossSection()/sumOfWeights()/femtobarn*TeV;
134 scale(_h_ZZ_mZZ, norm);
135 scale(_h_ZZ_pTZZ, norm);
136 }
137
138
139 /// Generic Z candidate
140 struct Zstate : public ParticlePair {
141 Zstate() { }
142 Zstate(ParticlePair _particlepair) : ParticlePair(_particlepair) { }
143 FourMomentum mom() const { return first.momentum() + second.momentum(); }
144 operator FourMomentum() const { return mom(); }
145 static bool cmppT(const Zstate& lx, const Zstate& rx) { return lx.mom().pT() < rx.mom().pT(); }
146 };
147
148
149 /// @brief 4l to ZZ assignment algorithm
150 ///
151 /// ZZ->4l pairing
152 /// - At least two same flavour opposite sign (SFOS) lepton pairs
153 /// - Ambiguities in pairing are resolved following the procedure
154 /// 1. the leading Z (Z1) is choosen as the SFOS with dilepton mass closet to Z mass
155 /// 2. the subleading Z (Z2) is choosen as the remaining SFOS dilepton pair
156 ///
157 /// Z1, Z2: the selected pairing
158 /// Z1_alt, Z2_alt: the alternative pairing (the same as Z1, Z2 in 2e2m case)
159 bool identifyZstates(Zstate& Z1, Zstate& Z2, Zstate& Z1_alt, Zstate& Z2_alt, const Particles& leptons_sel4l) {
160 const double ZMASS = 91.1876*GeV;
161 bool findZZ = false;
162
163 Particles part_pos_el, part_neg_el, part_pos_mu, part_neg_mu;
164 for (const Particle& l : leptons_sel4l) {
165 if (l.abspid() == PID::ELECTRON) {
166 if (l.pid() < 0) part_neg_el.push_back(l);
167 if (l.pid() > 0) part_pos_el.push_back(l);
168 }
169 else if (l.abspid() == PID::MUON) {
170 if (l.pid() < 0) part_neg_mu.push_back(l);
171 if (l.pid() > 0) part_pos_mu.push_back(l);
172 }
173 }
174
175 // eeee/mmmm channel
176 if ((part_neg_el.size() == 2 && part_pos_el.size() == 2) || (part_neg_mu.size() == 2 && part_pos_mu.size() == 2)) {
177 findZZ = true;
178
179 Zstate Zcand_1, Zcand_2, Zcand_3, Zcand_4;
180 Zstate Zcand_1_tmp, Zcand_2_tmp, Zcand_3_tmp, Zcand_4_tmp;
181 if (part_neg_el.size() == 2) { // eeee
182 Zcand_1_tmp = Zstate( ParticlePair( part_neg_el[0], part_pos_el[0] ) );
183 Zcand_2_tmp = Zstate( ParticlePair( part_neg_el[0], part_pos_el[1] ) );
184 Zcand_3_tmp = Zstate( ParticlePair( part_neg_el[1], part_pos_el[0] ) );
185 Zcand_4_tmp = Zstate( ParticlePair( part_neg_el[1], part_pos_el[1] ) );
186 }
187 else { // mmmm
188 Zcand_1_tmp = Zstate( ParticlePair( part_neg_mu[0], part_pos_mu[0] ) );
189 Zcand_2_tmp = Zstate( ParticlePair( part_neg_mu[0], part_pos_mu[1] ) );
190 Zcand_3_tmp = Zstate( ParticlePair( part_neg_mu[1], part_pos_mu[0] ) );
191 Zcand_4_tmp = Zstate( ParticlePair( part_neg_mu[1], part_pos_mu[1] ) );
192 }
193
194 // We can have the following pairs: (Z1 + Z4) || (Z2 + Z3)
195 // Firstly, reorder withing each quadruplet to have
196 // - fabs(mZ1 - ZMASS) < fabs(mZ4 - ZMASS)
197 // - fabs(mZ2 - ZMASS) < fabs(mZ3 - ZMASS)
198 if (fabs(Zcand_1_tmp.mom().mass() - ZMASS) < fabs(Zcand_4_tmp.mom().mass() - ZMASS)) {
199 Zcand_1 = Zcand_1_tmp;
200 Zcand_4 = Zcand_4_tmp;
201 } else {
202 Zcand_1 = Zcand_4_tmp;
203 Zcand_4 = Zcand_1_tmp;
204 }
205 if (fabs(Zcand_2_tmp.mom().mass() - ZMASS) < fabs(Zcand_3_tmp.mom().mass() - ZMASS)) {
206 Zcand_2 = Zcand_2_tmp;
207 Zcand_3 = Zcand_3_tmp;
208 } else {
209 Zcand_2 = Zcand_3_tmp;
210 Zcand_3 = Zcand_2_tmp;
211 }
212
213 // We can have the following pairs: (Z1 + Z4) || (Z2 + Z3)
214 // Secondly, select the leading and subleading Z following
215 // 1. the leading Z (Z1) is choosen as the SFOS with dilepton mass closet to Z mass
216 // 2. the subleading Z (Z2) is choosen as the remaining SFOS dilepton pair
217 if (fabs(Zcand_1.mom().mass() - ZMASS) < fabs(Zcand_2.mom().mass() - ZMASS)) {
218 Z1 = Zcand_1;
219 Z2 = Zcand_4;
220 Z1_alt = Zcand_2;
221 Z2_alt = Zcand_3;
222 } else {
223 Z1 = Zcand_2;
224 Z2 = Zcand_3;
225 Z1_alt = Zcand_1;
226 Z2_alt = Zcand_4;
227 }
228 } // end of eeee/mmmm channel
229 else if (part_neg_el.size() == 1 && part_pos_el.size() == 1 && part_neg_mu.size() == 1 && part_pos_mu.size() == 1) { // 2e2m channel
230 findZZ = true;
231
232 Zstate Zcand_1, Zcand_2;
233
234 Zcand_1 = Zstate( ParticlePair( part_neg_mu[0], part_pos_mu[0] ) );
235 Zcand_2 = Zstate( ParticlePair( part_neg_el[0], part_pos_el[0] ) );
236
237 if (fabs(Zcand_1.mom().mass() - ZMASS) < fabs(Zcand_2.mom().mass() - ZMASS)) {
238 Z1 = Zcand_1;
239 Z2 = Zcand_2;
240 } else {
241 Z1 = Zcand_2;
242 Z2 = Zcand_1;
243 }
244 Z1_alt = Z1;
245 Z2_alt = Z2;
246 }
247
248 return findZZ;
249 }
250
251
252 private:
253
254 Histo1DPtr _h_ZZ_pTZZ, _h_ZZ_mZZ;
255
256 };
257
258
259 RIVET_DECLARE_PLUGIN(ATLAS_2015_I1394865);
260
261}
|