-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathJetMETUncertainty.cc
454 lines (387 loc) · 13.9 KB
/
JetMETUncertainty.cc
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
#include "JetMETUncertainty.h"
#include "jetcorr/JetCorrectionUncertainty.h"
#include "jetSmearingTools.h"
#include <math.h>
using namespace std;
//
// default constructor
//
JetMETUncertainty::JetMETUncertainty ()
: ele_unc_b_(0.006), ele_unc_e_(0.015), mu_unc_(0.01), uncl_unc_(0.1), have_jetcorr_unc_(false), have_jetsmear_(false)
{
jetCorrectionUncertainty_ = 0;
jetSmearer_ = 0;
}
//
// constructor taking jet parameter file names
//
JetMETUncertainty::JetMETUncertainty(string jetcorr_unc_file_name,
vector<string> &jetsmear_file_names)
: ele_unc_b_(0.006), ele_unc_e_(0.015), mu_unc_(0.01), uncl_unc_(0.1)
{
have_jetcorr_unc_ = false;
jetcorr_unc_file_name_ = jetcorr_unc_file_name;
if (!jetcorr_unc_file_name.empty()) {
jetCorrectionUncertainty_ = new JetCorrectionUncertainty(jetcorr_unc_file_name_);
if (jetCorrectionUncertainty_ != 0)
have_jetcorr_unc_ = true;
else
cout << "Trouble getting jet correction uncertainty service." << endl;
}
have_jetsmear_ = false;
jetsmear_file_names_ = vector<string>(jetsmear_file_names);
if (jetsmear_file_names_.size() == 3) {
jetSmearer_ = makeJetSmearer(jetsmear_file_names_);
if (jetSmearer_ != 0)
have_jetsmear_ = true;
else
cout << "Trouble getting jet resolution smearing service." << endl;
}
}
//
// return total met uncertainty
// return a pair<double, double>
// first entry is the uncertainty on the UP scaling
// second entry is the uncertainty on the DOWN scaling
//
dpair JetMETUncertainty::GetTotalUncertainty(dpair good_met)
{
good_met_ = dpair(good_met);
double base_met = good_met_.first;
vector<dpair> vmet_up;
vector<dpair> vmet_down;
SmearMETForElectronUncertainty ();
vmet_up.push_back(met_ele_up_);
vmet_down.push_back(met_ele_down_);
SmearMETForMuonUncertainty ();
vmet_up.push_back(met_mu_up_);
vmet_down.push_back(met_mu_down_);
SmearMETForUnclusteredEnergyUncertainty ();
vmet_up.push_back(met_uncl_up_);
vmet_down.push_back(met_uncl_down_);
if (have_jetcorr_unc_) {
SmearMETForJESUncertainty ();
vmet_up.push_back(met_jes_up_);
vmet_down.push_back(met_jes_down_);
}
if (have_jetsmear_) {
SmearMETForJERUncertainty ();
vmet_up.push_back(met_jer_up_);
vmet_down.push_back(met_jer_down_);
}
assert(vmet_up.size() == vmet_down.size());
double unc_up = 0.;
double unc_down = 0.;
for (unsigned int idx = 0; idx < vmet_up.size(); idx++) {
double tmp_up = (vmet_up.at(idx).first - base_met) / base_met;
unc_up += pow(tmp_up, 2);
double tmp_down = (vmet_down.at(idx).first - base_met) / base_met;
unc_down += pow(tmp_down, 2);
}
return make_pair(sqrt(unc_up), sqrt(unc_down));
}
//
// get scaled MET
// component is after scaling either electrons (ELE), muons (MU), unclustered energy (UNCL)
// jet energy scale (JES), or jet energy resolution (JER)
// scale_type is either UP or DOWN
// returns a pair<double, double>
// first entry is the MET
// second entry is the MET phi
//
dpair JetMETUncertainty::GetScaledMET (dpair good_met, Component component, ScaleType scale_type)
{
good_met_ = dpair(good_met);
if (component == ELE) {
SmearMETForElectronUncertainty ();
return (scale_type == DOWN) ? met_ele_down_ : met_ele_up_;
}
else if (component == MU) {
SmearMETForMuonUncertainty ();
return (scale_type == DOWN) ? met_mu_down_ : met_mu_up_;
}
else if (component == UNCL) {
SmearMETForUnclusteredEnergyUncertainty ();
return (scale_type == DOWN) ? met_uncl_down_ : met_uncl_up_;
}
else if (component == JES) {
SmearMETForJESUncertainty ();
return (scale_type == DOWN) ? met_jes_down_ : met_jes_up_;
}
else if (component == JER) {
SmearMETForJERUncertainty ();
return (scale_type == DOWN) ? met_jer_down_ : met_jer_up_;
}
else {
cout << "Do not recognize the component you asked for." << endl;
return make_pair(-1., 0.);
}
}
//
// smear met for electron energy scale uncertainty
// default uncertainty is 0.6% in barrel
// and 1.5% in endcap
//
void JetMETUncertainty::SmearMETForElectronUncertainty ()
{
double dmet_x = good_met_.first * cos(good_met_.second);
double dmet_y = good_met_.first * sin(good_met_.second);
double umet_x = good_met_.first * cos(good_met_.second);
double umet_y = good_met_.first * sin(good_met_.second);
for (unsigned int idx = 0; idx < good_els_.size(); idx++) {
double eta = fabs(good_els_.at(idx).eta());
double px = good_els_.at(idx).px();
double py = good_els_.at(idx).py();
double scale = (eta < 1.479) ? ele_unc_b_ : ele_unc_e_;
dmet_x -= DOWN * scale * px;
dmet_y -= DOWN * scale * py;
umet_x -= UP * scale * px;
umet_y -= UP * scale * py;
}
met_ele_up_ = make_pair(sqrt( pow(umet_x, 2) + pow(umet_y, 2)), atan2(umet_y, umet_x));
met_ele_down_ = make_pair(sqrt( pow(dmet_x, 2) + pow(dmet_y, 2)), atan2(dmet_y, dmet_x));
}
//
// smear met for muon momentum scale uncertainty
// default uncertainty is 1.0%
//
void JetMETUncertainty::SmearMETForMuonUncertainty ()
{
double dmet_x = good_met_.first * cos(good_met_.second);
double dmet_y = good_met_.first * sin(good_met_.second);
double umet_x = good_met_.first * cos(good_met_.second);
double umet_y = good_met_.first * sin(good_met_.second);
for (unsigned int idx = 0; idx < good_mus_.size(); idx++) {
double px = good_mus_.at(idx).px();
double py = good_mus_.at(idx).py();
dmet_x -= DOWN * mu_unc_ * px;
dmet_y -= DOWN * mu_unc_ * py;
umet_x -= UP * mu_unc_ * px;
umet_y -= UP * mu_unc_ * py;
}
met_mu_up_ = make_pair(sqrt( pow(umet_x, 2) + pow(umet_y, 2)), atan2(umet_y, umet_x));
met_mu_down_ = make_pair(sqrt( pow(dmet_x, 2) + pow(dmet_y, 2)), atan2(dmet_y, dmet_x));
}
//
// smear met for unclustered energy scale uncertainty
// default uncertainty is 10%
//
void JetMETUncertainty::SmearMETForUnclusteredEnergyUncertainty ()
{
dpair tmp_met = GetUnclusteredMET ();
double dmet_x = good_met_.first * cos(good_met_.second);
double dmet_y = good_met_.first * sin(good_met_.second);
dmet_x -= DOWN * uncl_unc_ * tmp_met.first;
dmet_y -= DOWN * uncl_unc_ * tmp_met.second;
double umet_x = good_met_.first * cos(good_met_.second);
double umet_y = good_met_.first * sin(good_met_.second);
umet_x -= DOWN * uncl_unc_ * tmp_met.first;
umet_y -= DOWN * uncl_unc_ * tmp_met.second;
met_uncl_up_ = make_pair(sqrt( pow(umet_x, 2) + pow(umet_y, 2)), atan2(umet_y, umet_x));
met_uncl_down_ = make_pair(sqrt( pow(dmet_x, 2) + pow(dmet_y, 2)), atan2(dmet_y, dmet_x));
}
//
// calculate component of MET from unclustered energy
// start with input MET and remove the following
// 1) good electrons
// 2) good muons
// 3) good jets
//
dpair JetMETUncertainty::GetUnclusteredMET ()
{
double met_x = good_met_.first * cos(good_met_.second);
double met_y = good_met_.first * sin(good_met_.second);
for (unsigned int idx = 0; idx < good_els_.size(); idx++) {
met_x += good_els_.at(idx).px();
met_y += good_els_.at(idx).py();
}
for (unsigned int idx = 0; idx < good_mus_.size(); idx++) {
met_x += good_mus_.at(idx).px();
met_y += good_mus_.at(idx).py();
}
for (unsigned int idx = 0; idx < good_jets_.size(); idx++) {
met_x += good_jets_.at(idx).px();
met_y += good_jets_.at(idx).py();
}
return make_pair(met_x, met_y);
}
//
// smear met for JES uncertainty
// uncertainty determined on jet-by-jet basis
// using text file from jetcorr/data
// the good_jets input to this method are the final corrected jets used by the analysis
// after all selections on the jets
// the default selections should be
// |eta| < 4.7 and corrected pt > 10 GeV
//
void JetMETUncertainty::SmearMETForJESUncertainty ()
{
if (!have_jetcorr_unc_) {
cout << "Attempting to smear MET for JES but do not have a valid jet correction uncertainty service." << endl;
met_jes_up_ = make_pair(-1., 0.);
met_jes_down_ = make_pair(-1., 0.);
return;
}
double dmet_x = good_met_.first * cos(good_met_.second);
double dmet_y = good_met_.first * sin(good_met_.second);
double umet_x = good_met_.first * cos(good_met_.second);
double umet_y = good_met_.first * sin(good_met_.second);
jetcorr_uncertainties_.clear();
for (unsigned int idx = 0; idx < good_jets_.size(); idx++) {
double px = good_jets_.at(idx).px();
double py = good_jets_.at(idx).py();
jetCorrectionUncertainty_->setJetEta(good_jets_.at(idx).eta());
jetCorrectionUncertainty_->setJetPt(good_jets_.at(idx).pt());
double scale = jetCorrectionUncertainty_->getUncertainty(true);
jetcorr_uncertainties_.push_back(scale);
dmet_x -= DOWN * scale * px;
dmet_y -= DOWN * scale * py;
umet_x -= UP * scale * px;
umet_y -= UP * scale * py;
}
met_jes_up_ = make_pair(sqrt( pow(umet_x, 2) + pow(umet_y, 2)), atan2(umet_y, umet_x));
met_jes_down_ = make_pair(sqrt( pow(dmet_x, 2) + pow(dmet_y, 2)), atan2(dmet_y, dmet_x));
}
//
// smear met for JER uncertainty
// uncertainty determined on jet-by-jet basis
// using text files jetsmear/data
// the good_jets input to this method are the final corrected jets used by the analysis
// after all selections on the jets
// the default selections should be
// |eta| < 4.7 and corrected pt > 10 GeV
//
void JetMETUncertainty::SmearMETForJERUncertainty ()
{
if (!have_jetsmear_) {
cout << "Attempting to smear MET for JER but do not have valid jet smearing service." << endl;
met_jer_up_ = make_pair(-1., 0.);
met_jer_down_ = make_pair(-1., 0.);
return;
}
smeared_jets_ = smearJets(good_jets_, jetSmearer_);
//
// this is all just to make the up/down variation easier to deal with
//
smeared_jet_sf_.clear();
smeared_jet_sf_.reserve(smeared_jets_.size());
for (unsigned int idx = 0; idx < smeared_jets_.size(); idx++) {
double diff = (smeared_jets_.at(idx).pt() - good_jets_.at(idx).pt()) / good_jets_.at(idx).pt();
smeared_jet_sf_.push_back(diff - 1.);
}
assert(smeared_jet_sf_.size() == good_jets_.size());
double dmet_x = good_met_.first * cos(good_met_.second);
double dmet_y = good_met_.first * sin(good_met_.second);
double umet_x = good_met_.first * cos(good_met_.second);
double umet_y = good_met_.first * sin(good_met_.second);
for (unsigned int idx = 0; idx < good_jets_.size(); idx++) {
double px = good_jets_.at(idx).px();
double py = good_jets_.at(idx).py();
double scale = smeared_jet_sf_.at(idx);
dmet_x -= DOWN * scale * px;
dmet_y -= DOWN * scale * py;
umet_x -= UP * scale * px;
umet_y -= UP * scale * py;
}
met_jer_up_ = make_pair(sqrt( pow(umet_x, 2) + pow(umet_y, 2) ), atan2(umet_y, umet_x));
met_jer_down_ = make_pair(sqrt( pow(dmet_x, 2) + pow(dmet_y, 2) ), atan2(dmet_y, dmet_x));
}
//
// set input parameters
// 1) vector of good electrons as defined by analysis selections
// 2) vector of good muons as defined by analysis selections
// 3) vector of good jets - default should be |eta| < 4.7 and corrected pt > 10 GeV, but it can be defined by the user
//
void JetMETUncertainty::SetInputParameters (VofP4s &good_els, VofP4s &good_mus, VofP4s &good_jets)
{
good_els_ = VofP4s(good_els);
good_mus_ = VofP4s(good_mus);
good_jets_ = VofP4s(good_jets);
}
//
// set jet correction uncertainty pararmeter file name
//
void JetMETUncertainty::SetJetCorrUncFileName(string jetcorr_unc_file_name)
{
have_jetcorr_unc_ = false;
jetcorr_unc_file_name_ = std::string(jetcorr_unc_file_name);
if (!jetcorr_unc_file_name.empty()) {
jetCorrectionUncertainty_ = new JetCorrectionUncertainty(jetcorr_unc_file_name_);
if (jetCorrectionUncertainty_ != 0)
have_jetcorr_unc_ = true;
}
}
//
// set jet smearing parameter file names
//
void JetMETUncertainty::SetJetSmearFileNames(vector<string> &jetsmear_file_names)
{
have_jetsmear_ = false;
jetsmear_file_names_ = std::vector<std::string>(jetsmear_file_names);
if (jetsmear_file_names_.size() == 3) {
jetSmearer_ = makeJetSmearer(jetsmear_file_names_);
if (jetSmearer_ != 0)
have_jetsmear_ = true;
}
}
//
// set electron energy scale uncertainty
// first argument is the barrel uncertainty
// second argument is the endcap uncertainty
//
void JetMETUncertainty::SetElectronUncertainty(double barrel_uncertainty, double endcap_uncertainty)
{
ele_unc_b_ = barrel_uncertainty;
ele_unc_e_ = endcap_uncertainty;
}
//
// set muon momentum scale uncertainty
//
void JetMETUncertainty::SetMuonUncertainty(double muon_uncertainty)
{
mu_unc_ = muon_uncertainty;
}
//
// set unclustered energy scale uncertainty
//
void JetMETUncertainty::SetUnclusteredEnergyUncertainty(double unclustered_uncertainty)
{
uncl_unc_ = unclustered_uncertainty;
}
//
// get electron energy scale uncertainties
// first entry is the barrel uncertainty
// second entry is the endcap uncertainty
//
dpair JetMETUncertainty::GetElectronUncertainty()
{
return make_pair(ele_unc_b_, ele_unc_e_);
}
//
// get muon momentum scale uncertaintya
//
double JetMETUncertainty::GetMuonUncertainty()
{
return mu_unc_;
}
//
// get unclustered energy scale uncertainty
//
double JetMETUncertainty::GetUnclusteredEnergyUncertainty()
{
return uncl_unc_;
}
//
// get SF used to smear jets for JER uncertainty
//
vector<double> JetMETUncertainty::GetSmearedJetScaleFactors ()
{
return smeared_jet_sf_;
}
//
// get JES uncertainty for jets
//
vector<double> JetMETUncertainty::GetJESUncertainties ()
{
return jetcorr_uncertainties_;
}