1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
| // -*- C++ -*-
#include "Rivet/Analysis.hh"
#include "Rivet/Projections/FinalState.hh"
#include "Rivet/Projections/IdentifiedFinalState.hh"
#include "Rivet/Projections/ZFinder.hh"
#include "Rivet/Projections/VetoedFinalState.hh"
#include "Rivet/Projections/MergedFinalState.hh"
namespace Rivet {
/// Inclusive ZZ production cross section and constraints on anomalous triple gauge couplings
class CMS_2012_I1298807 : public Analysis {
public:
// Constructor
RIVET_DEFAULT_ANALYSIS_CTOR(CMS_2012_I1298807);
/// Initialise projections and histograms
void init() {
// FinalState electrons(Cuts::abseta < 2.5 && Cuts::abspid == PID::ELECTRON);
// FinalState muons(Cuts::abseta < 2.4 && Cuts::abspid == PID::MUON);
// MergedFinalState leptons(electrons, muons);
FinalState leptons((Cuts::abspid == PID::ELECTRON && Cuts::abseta < 2.5) ||
(Cuts::abspid == PID::MUON && Cuts::abseta < 2.4));
declare(leptons, "Leptons");
Cut cut_el = Cuts::abseta < 2.5 && Cuts::pT > 7.0*GeV;
Cut cut_mu = Cuts::abseta < 2.4 && Cuts::pT > 5.0*GeV;
ZFinder zeefinder(FinalState(), cut_el, PID::ELECTRON, 60*GeV, 120*GeV, 0.1, ZFinder::ClusterPhotons::NODECAY, ZFinder::AddPhotons::YES);
declare(zeefinder, "ZeeFinder");
ZFinder zmmfinder(FinalState(), cut_mu, PID::MUON, 60*GeV, 120*GeV, 0.1, ZFinder::ClusterPhotons::NODECAY, ZFinder::AddPhotons::YES);
declare(zmmfinder, "ZmmFinder");
VetoedFinalState fs_woZmm;
fs_woZmm.addVetoOnThisFinalState(zmmfinder);
VetoedFinalState fs_woZee;
fs_woZee.addVetoOnThisFinalState(zeefinder);
ZFinder zeefinder_woZee(fs_woZee, cut_el, PID::ELECTRON, 60*GeV, 120*GeV, 0.1, ZFinder::ClusterPhotons::NODECAY);
declare(zeefinder_woZee, "Zeefinder_WoZee");
ZFinder zmmfinder_woZmm(fs_woZmm, cut_mu, PID::MUON, 60*GeV, 120*GeV, 0.1, ZFinder::ClusterPhotons::NODECAY);
declare(zmmfinder_woZmm, "Zmmfinder_WoZmm");
// Book histograms
book(_hist_pt_l1 , 1, 1, 1);
book(_hist_pt_z1 , 1, 1, 2);
book(_hist_pt_zz , 1, 1, 3);
book(_hist_m_zz , 1, 1, 4);
book(_hist_dphi_zz, 1, 1, 5);
book(_hist_dR_zz , 1, 1, 6);
}
// Perform the per-event analysis
void analyze(const Event& evt) {
// Find leading leptons and apply cuts
const Particles& leptons = apply<FinalState>(evt, "Leptons").particlesByPt();
if (leptons.size() < 2) vetoEvent;
const double leading_l_pt = leptons[0].pT();
const double second_l_pt = leptons[1].pT();
if (leading_l_pt < 20*GeV || second_l_pt < 10*GeV) vetoEvent;
// Find acceptable ZZ combinations and build four-momenta, otherwise veto
const ZFinder& zeefinder = applyProjection<ZFinder>(evt, "ZeeFinder");
const ZFinder& zeefinder_woZee = applyProjection<ZFinder>(evt, "Zeefinder_WoZee");
const ZFinder& zmmfinder = applyProjection<ZFinder>(evt, "ZmmFinder");
const ZFinder& zmmfinder_woZmm = applyProjection<ZFinder>(evt, "Zmmfinder_WoZmm");
FourMomentum pZ_a, pZ_b, pZ_1, pZ_2;
FourMomentum pZZ, Z_a_l1, Z_a_l2, Z_b_l1, Z_b_l2;
if (zeefinder.bosons().size() > 0 && zmmfinder.bosons().size() > 0) {
pZ_a = zeefinder.bosons()[0];
pZ_b = zmmfinder.bosons()[0];
pZZ = pZ_a + pZ_b;
pZ_1 = pZ_a;
pZ_2 = pZ_b;
Z_a_l1 = zeefinder.constituents()[0];
Z_a_l2 = zeefinder.constituents()[1];
Z_b_l1 = zmmfinder.constituents()[0];
Z_b_l2 = zmmfinder.constituents()[1];
} else if (zeefinder.bosons().size() > 0 && zeefinder_woZee.bosons().size() > 0) {
pZ_a = zeefinder.bosons()[0];
pZ_b = zeefinder_woZee.bosons()[0];
pZZ = pZ_a + pZ_b;
pZ_1 = pZ_a;
pZ_2 = pZ_b;
Z_a_l1 = zeefinder.constituents()[0];
Z_a_l2 = zeefinder.constituents()[1];
Z_b_l1 = zeefinder_woZee.constituents()[0];
Z_b_l2 = zeefinder_woZee.constituents()[1];
} else if (zmmfinder.bosons().size() > 0 && zmmfinder_woZmm.bosons().size() > 0) {
pZ_a = zmmfinder.bosons()[0];
pZ_b = zmmfinder_woZmm.bosons()[0];
pZZ = pZ_a + pZ_b;
pZ_1 = pZ_a;
pZ_2 = pZ_b;
Z_a_l1 = zmmfinder.constituents()[0];
Z_a_l2 = zmmfinder.constituents()[1];
Z_b_l1 = zmmfinder_woZmm.constituents()[0];
Z_b_l2 = zmmfinder_woZmm.constituents()[1];
} else {
vetoEvent;
}
// Set ordered pT variables
/// @todo Looks like there should be a nicer way than this
double pt_l1 = Z_a_l1.pT();
if (Z_a_l2.pT() > pt_l1) pt_l1 = Z_a_l2.pT();
if (Z_b_l1.pT() > pt_l1) pt_l1 = Z_b_l1.pT();
if (Z_b_l2.pT() > pt_l1) pt_l1 = Z_b_l2.pT();
// Leading Z pT
double pt_z1 = pZ_a.pT();
if (pZ_b.pT() > pZ_a.pT()) {
pt_z1 = pZ_b.pT();
pZ_1 = pZ_b;
pZ_2 = pZ_a;
}
// Fill histograms
const double weight = 1.0;
_hist_pt_zz->fill(pZZ.pT()/GeV, weight);
_hist_m_zz->fill(pZZ.mass()/GeV, weight);
_hist_dphi_zz->fill(deltaPhi(pZ_a, pZ_b), weight);
_hist_dR_zz->fill(deltaR(pZ_a, pZ_b, PSEUDORAPIDITY), weight);
_hist_pt_z1->fill(pt_z1/GeV, weight);
_hist_pt_l1->fill(pt_l1/GeV, weight);
}
/// Scale histograms
/// @note This is all needed to undo bin width factor -- WHY DO PEOPLE USE UNPHYSICAL HISTOGRAMS?!?
/// @todo If we introduce a "bar plot" or similar, it'd work better here
void finalize() {
double sum_height_pt_zz = 0;
for (size_t i = 0; i < _hist_pt_zz->numBins(); i++) {
_hist_pt_zz->bin(i).scaleW(1. / _hist_pt_zz->bin(i).width());
sum_height_pt_zz += _hist_pt_zz->bin(i).height();
}
scale(_hist_pt_zz, 1. / sum_height_pt_zz);
double sum_height_m_zz = 0;
for (size_t i = 0; i < _hist_m_zz->numBins(); i++) {
_hist_m_zz->bin(i).scaleW(1. / _hist_m_zz->bin(i).width());
sum_height_m_zz += _hist_m_zz->bin(i).height();
}
scale(_hist_m_zz, 1. / sum_height_m_zz);
double sum_height_dphi_zz = 0;
for (size_t i = 0; i < _hist_dphi_zz->numBins(); i++) {
_hist_dphi_zz->bin(i).scaleW(1. / _hist_dphi_zz->bin(i).width());
sum_height_dphi_zz += _hist_dphi_zz->bin(i).height();
}
scale(_hist_dphi_zz, 1. / sum_height_dphi_zz);
double sum_height_dR_zz = 0;
for (size_t i = 0; i < _hist_dR_zz->numBins(); i++) {
_hist_dR_zz->bin(i).scaleW(1. / _hist_dR_zz->bin(i).width());
sum_height_dR_zz += _hist_dR_zz->bin(i).height();
}
scale(_hist_dR_zz, 1. / sum_height_dR_zz);
double sum_height_pt_z1 = 0;
for (size_t i = 0; i < _hist_pt_z1->numBins(); i++) {
_hist_pt_z1->bin(i).scaleW(1. / _hist_pt_z1->bin(i).width());
sum_height_pt_z1 += _hist_pt_z1->bin(i).height();
}
scale(_hist_pt_z1, 1. / sum_height_pt_z1);
double sum_height_pt_l1 = 0;
for (size_t i = 0; i < _hist_pt_l1->numBins(); i++) {
_hist_pt_l1->bin(i).scaleW(1. / _hist_pt_l1->bin(i).width());
sum_height_pt_l1 += _hist_pt_l1->bin(i).height();
}
scale(_hist_pt_l1, 1. / sum_height_pt_l1);
}
/// Histograms
Histo1DPtr _hist_pt_zz, _hist_m_zz, _hist_dphi_zz, _hist_dR_zz, _hist_pt_z1, _hist_pt_l1;
};
// The hook for the plugin system
RIVET_DECLARE_PLUGIN(CMS_2012_I1298807);
}
|