File indexing completed on 2024-04-06 12:10:19
0001 #include "EgammaAnalysis/ElectronTools/interface/EnergyScaleCorrection_class.h"
0002 #include "FWCore/ParameterSet/interface/FileInPath.h"
0003 #include <RooDataSet.h>
0004 #include <RooArgSet.h>
0005
0006 #define NGENMAX 10000
0007
0008
0009 #include <cstdlib>
0010 #include <cfloat>
0011
0012 #include <iomanip>
0013
0014 #include <sstream>
0015
0016
0017
0018
0019 EnergyScaleCorrection_class::EnergyScaleCorrection_class(std::string correctionFileName, unsigned int genSeed)
0020 : doScale(false), doSmearings(false), smearingType_(ECALELF) {
0021 if (!correctionFileName.empty()) {
0022 std::string filename = correctionFileName + "_scales.dat";
0023 ReadFromFile(filename);
0024 if (scales.empty()) {
0025 std::cerr << "[ERROR] scale correction map empty" << std::endl;
0026 exit(1);
0027 }
0028 }
0029
0030 if (!correctionFileName.empty()) {
0031 std::string filename = correctionFileName + "_smearings.dat";
0032 ReadSmearingFromFile(filename);
0033 if (smearings.empty()) {
0034 std::cerr << "[ERROR] smearing correction map empty" << std::endl;
0035 exit(1);
0036 }
0037 }
0038
0039 return;
0040 }
0041
0042 EnergyScaleCorrection_class::~EnergyScaleCorrection_class(void) { return; }
0043
0044 float EnergyScaleCorrection_class::ScaleCorrection(
0045 unsigned int runNumber, bool isEBEle, double R9Ele, double etaSCEle, double EtEle) const {
0046 float correction = 1;
0047 if (doScale)
0048 correction *= getScaleOffset(runNumber, isEBEle, R9Ele, etaSCEle, EtEle);
0049
0050 return correction;
0051 }
0052
0053 float EnergyScaleCorrection_class::ScaleCorrectionUncertainty(
0054 unsigned int runNumber, bool isEBEle, double R9Ele, double etaSCEle, double EtEle) const {
0055 float statUncert = getScaleStatUncertainty(runNumber, isEBEle, R9Ele, etaSCEle, EtEle);
0056 float systUncert = getScaleSystUncertainty(runNumber, isEBEle, R9Ele, etaSCEle, EtEle);
0057
0058 return sqrt(statUncert * statUncert + systUncert * systUncert);
0059 }
0060
0061 float EnergyScaleCorrection_class::getScaleStatUncertainty(
0062 unsigned int runNumber, bool isEBEle, double R9Ele, double etaSCEle, double EtEle) const {
0063 return getScaleCorrection(runNumber, isEBEle, R9Ele, etaSCEle, EtEle).scale_err;
0064 }
0065
0066 float EnergyScaleCorrection_class::getScaleSystUncertainty(
0067 unsigned int runNumber, bool isEBEle, double R9Ele, double etaSCEle, double EtEle) const {
0068 return getScaleCorrection(runNumber, isEBEle, R9Ele, etaSCEle, EtEle).scale_err_syst;
0069 }
0070
0071 correctionValue_class EnergyScaleCorrection_class::getScaleCorrection(
0072 unsigned int runNumber, bool isEBEle, double R9Ele, double etaSCEle, double EtEle) const {
0073
0074 correctionCategory_class category(runNumber, etaSCEle, R9Ele, EtEle);
0075 correction_map_t::const_iterator corr_itr =
0076 scales.find(category);
0077
0078 if (corr_itr == scales.end()) {
0079
0080
0081
0082
0083
0084
0085
0086
0087 std::cout << "[ERROR] Scale category not found: " << std::endl;
0088 std::cout << category << std::endl;
0089 std::cout << "Returning uncorrected value." << std::endl;
0090
0091 correctionValue_class nocorr;
0092 std::cout << nocorr << std::endl;
0093 return nocorr;
0094 }
0095
0096 #ifdef DEBUG
0097 std::cout << "[DEBUG] Checking scale correction for category: " << category << std::endl;
0098 std::cout << "[DEBUG] Correction is: " << corr_itr->second << std::endl
0099 << " given for category " << corr_itr->first << std::endl;
0100 ;
0101 #endif
0102 return corr_itr->second;
0103 }
0104
0105 float EnergyScaleCorrection_class::getScaleOffset(
0106 unsigned int runNumber, bool isEBEle, double R9Ele, double etaSCEle, double EtEle) const {
0107
0108 correctionCategory_class category(runNumber, etaSCEle, R9Ele, EtEle);
0109 correction_map_t::const_iterator corr_itr =
0110 scales.find(category);
0111
0112 if (corr_itr == scales.end()) {
0113
0114
0115
0116
0117
0118
0119
0120
0121 std::cout << "[ERROR] Scale offset category not found: " << std::endl;
0122 std::cout << category << std::endl;
0123 std::cout << "Returning uncorrected value." << std::endl;
0124
0125 correctionValue_class nocorr;
0126 return nocorr.scale;
0127 }
0128
0129 #ifdef DEBUG
0130 std::cout << "[DEBUG] Checking scale offset correction for category: " << category << std::endl;
0131 std::cout << "[DEBUG] Correction is: " << corr_itr->second << std::endl
0132 << " given for category " << corr_itr->first << std::endl;
0133 ;
0134 #endif
0135
0136 return corr_itr->second.scale;
0137 }
0138
0139
0140
0141
0142
0143
0144 void EnergyScaleCorrection_class::ReadFromFile(TString filename) {
0145 #ifdef PEDANTIC_OUTPUT
0146 std::cout << "[STATUS] Reading energy scale correction values from file: " << filename << std::endl;
0147 #endif
0148 std::cout << "[STATUS] Reading energy scale correction values from file: " << filename << std::endl;
0149
0150
0151 std::ifstream f_in(edm::FileInPath(filename).fullPath().c_str());
0152
0153 if (!f_in.good()) {
0154 std::cerr << "[ERROR] file " << filename << " not readable" << std::endl;
0155 exit(1);
0156 return;
0157 }
0158
0159 int runMin, runMax;
0160 TString category, region2;
0161 double deltaP, err_deltaP, err_deltaP_stat, err_deltaP_syst;
0162
0163 for (f_in >> category; f_in.good(); f_in >> category) {
0164 f_in >> region2 >> runMin >> runMax >> deltaP >> err_deltaP >> err_deltaP_stat >> err_deltaP_syst;
0165
0166 AddScale(category, runMin, runMax, deltaP, err_deltaP_stat, err_deltaP_syst);
0167 }
0168
0169 f_in.close();
0170
0171 return;
0172 }
0173
0174
0175 void EnergyScaleCorrection_class::AddScale(
0176 TString category_, int runMin_, int runMax_, double deltaP_, double err_deltaP_, double err_syst_deltaP) {
0177 correctionCategory_class cat(category_);
0178 cat.runmin = runMin_;
0179 cat.runmax = runMax_;
0180
0181
0182 if (scales.count(cat) != 0) {
0183 std::cerr << "[ERROR] Category already defined!" << std::endl;
0184 std::cerr << " Adding category: " << cat << std::endl;
0185 std::cerr << " Defined category: " << scales[cat] << std::endl;
0186 exit(1);
0187 }
0188
0189 correctionValue_class corr;
0190 corr.scale = deltaP_;
0191 corr.scale_err = err_deltaP_;
0192 corr.scale_err_syst = err_syst_deltaP;
0193 scales[cat] = corr;
0194
0195 #ifdef PEDANTIC_OUTPUT
0196 std::cout << "[INFO:scale correction] " << cat << corr << std::endl;
0197 #endif
0198 return;
0199 }
0200
0201
0202 void EnergyScaleCorrection_class::AddSmearing(TString category_,
0203 int runMin_,
0204 int runMax_,
0205 double rho,
0206 double err_rho,
0207 double phi,
0208 double err_phi,
0209 double Emean,
0210 double err_Emean) {
0211 correctionCategory_class cat(category_);
0212 cat.runmin = (runMin_ < 0) ? 0 : runMin_;
0213 cat.runmax = runMax_;
0214
0215 if (smearings.count(cat) != 0) {
0216 std::cerr << "[ERROR] Smearing category already defined!" << std::endl;
0217 std::cerr << " Adding category: " << cat << std::endl;
0218 std::cerr << " Defined category: " << smearings[cat] << std::endl;
0219 exit(1);
0220 }
0221
0222 correctionValue_class corr;
0223 corr.rho = rho;
0224 corr.rho_err = err_rho;
0225 corr.phi = phi;
0226 corr.phi_err = err_phi;
0227 corr.Emean = Emean;
0228 corr.Emean_err = err_Emean;
0229 smearings[cat] = corr;
0230
0231 #ifdef PEDANTIC_OUTPUT
0232 #ifndef CMSSW
0233 std::cout << "[INFO:smearings] " << cat << corr << std::endl;
0234 #else
0235 edm::LogInfo("[INFO:smearings] ") << cat << corr;
0236 #endif
0237 #endif
0238
0239 return;
0240 }
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257 void EnergyScaleCorrection_class::ReadSmearingFromFile(TString filename) {
0258 #ifdef PEDANTIC_OUTPUT
0259 std::cout << "[STATUS] Reading smearing values from file: " << filename << std::endl;
0260 #endif
0261
0262 std::ifstream f_in(edm::FileInPath(filename).fullPath().c_str());
0263 if (!f_in.good()) {
0264 std::cerr << "[ERROR] file " << filename << " not readable" << std::endl;
0265 exit(1);
0266 }
0267
0268 int runMin = 0, runMax = 900000;
0269 int unused = 0;
0270 TString category, region2;
0271
0272 double rho, phi, Emean, err_rho, err_phi, err_Emean;
0273 double etaMin, etaMax, r9Min, r9Max;
0274 std::string phi_string, err_phi_string;
0275
0276 while (f_in.peek() != EOF && f_in.good()) {
0277 if (f_in.peek() == 10) {
0278 f_in.get();
0279 continue;
0280 }
0281
0282 if (f_in.peek() == 35) {
0283 f_in.ignore(1000, 10);
0284 continue;
0285 }
0286
0287 if (smearingType_ == UNKNOWN) {
0288 std::cerr << "[ERROR] Not implemented" << std::endl;
0289 assert(false);
0290
0291 } else if (smearingType_ == GLOBE) {
0292 f_in >> category >> unused >> etaMin >> etaMax >> r9Min >> r9Max >> runMin >> runMax >> Emean >> err_Emean >>
0293 rho >> err_rho >> phi >> err_phi;
0294
0295 AddSmearing(category, runMin, runMax, rho, err_rho, phi, err_phi, Emean, err_Emean);
0296
0297 } else if (smearingType_ == ECALELF) {
0298 f_in >> category >> Emean >> err_Emean >> rho >> err_rho >> phi_string >> err_phi_string;
0299 #ifdef DEBUG
0300 std::cout
0301 << category
0302
0303 << "\tEmean=" << Emean << "\t" << rho << "\t" << err_rho << "\tphi_string=" << phi_string
0304 << "#\terr_phi_string=" << err_phi_string << std::endl;
0305 #endif
0306
0307 if (phi_string == "M_PI_2")
0308 phi = M_PI_2;
0309 else
0310 phi = std::stod(phi_string);
0311
0312 if (err_phi_string == "M_PI_2")
0313 err_phi = M_PI_2;
0314 else
0315 err_phi = std::stod(err_phi_string);
0316
0317 AddSmearing(category, runMin, runMax, rho, err_rho, phi, err_phi, Emean, err_Emean);
0318
0319 } else {
0320 f_in >> category >> rho >> phi;
0321 err_rho = err_phi = Emean = err_Emean = 0;
0322 AddSmearing(category, runMin, runMax, rho, err_rho, phi, err_phi, Emean, err_Emean);
0323 }
0324 #ifdef DEBUG
0325 std::cout << category << "\t" << etaMin << "\t" << etaMax << "\t" << r9Min << "\t" << r9Max << "\t" << runMin
0326 << "\t" << runMax << "\tEmean=" << Emean << "\t" << rho << "\t" << phi << std::endl;
0327 #endif
0328 }
0329
0330 f_in.close();
0331
0332
0333 return;
0334 }
0335
0336 float EnergyScaleCorrection_class::getSmearingSigma(
0337 int runNumber, bool isEBEle, float R9Ele, float etaSCEle, float EtEle, paramSmear_t par, float nSigma) const {
0338 if (par == kRho)
0339 return getSmearingSigma(runNumber, isEBEle, R9Ele, etaSCEle, EtEle, nSigma, 0.);
0340 if (par == kPhi)
0341 return getSmearingSigma(runNumber, isEBEle, R9Ele, etaSCEle, EtEle, 0., nSigma);
0342 return getSmearingSigma(runNumber, isEBEle, R9Ele, etaSCEle, EtEle, 0., 0.);
0343 }
0344
0345 float EnergyScaleCorrection_class::getSmearingSigma(
0346 int runNumber, bool isEBEle, float R9Ele, float etaSCEle, float EtEle, float nSigma_rho, float nSigma_phi) const {
0347 correctionCategory_class category(runNumber, etaSCEle, R9Ele, EtEle);
0348 correction_map_t::const_iterator corr_itr = smearings.find(category);
0349 if (corr_itr == smearings.end()) {
0350
0351
0352
0353
0354
0355 corr_itr = smearings_not_defined.find(category);
0356 std::cerr << "[WARNING] Smearing category not found: " << std::endl;
0357 std::cerr << category << std::endl;
0358
0359 }
0360
0361 #ifdef DEBUG
0362 std::cout << "[DEBUG] Checking smearing correction for category: " << category << std::endl;
0363 std::cout << "[DEBUG] Correction is: " << corr_itr->second << std::endl
0364 << " given for category " << corr_itr->first;
0365 #endif
0366
0367 double rho = corr_itr->second.rho + corr_itr->second.rho_err * nSigma_rho;
0368 double phi = corr_itr->second.phi + corr_itr->second.phi_err * nSigma_phi;
0369
0370 double constTerm = rho * sin(phi);
0371 double alpha = rho * corr_itr->second.Emean * cos(phi);
0372
0373 return sqrt(constTerm * constTerm + alpha * alpha / EtEle);
0374 }
0375
0376 float EnergyScaleCorrection_class::getSmearingRho(
0377 int runNumber, bool isEBEle, float R9Ele, float etaSCEle, float EtEle) const {
0378 correctionCategory_class category(runNumber, etaSCEle, R9Ele, EtEle);
0379 correction_map_t::const_iterator corr_itr = smearings.find(category);
0380 if (corr_itr == smearings.end()) {
0381
0382
0383
0384
0385 corr_itr = smearings_not_defined.find(category);
0386 }
0387
0388 return corr_itr->second.rho;
0389 }
0390
0391 bool correctionCategory_class::operator<(const correctionCategory_class& b) const {
0392 if (runmin < b.runmin && runmax < b.runmax)
0393 return true;
0394 if (runmax > b.runmax && runmin > b.runmin)
0395 return false;
0396
0397 if (etamin < b.etamin && etamax < b.etamax)
0398 return true;
0399 if (etamax > b.etamax && etamin > b.etamin)
0400 return false;
0401
0402 if (r9min < b.r9min && r9max < b.r9max)
0403 return true;
0404 if (r9max > b.r9max && r9min > b.r9min)
0405 return false;
0406
0407 if (etmin < b.etmin && etmax < b.etmax)
0408 return true;
0409 if (etmax > b.etmax && etmin > b.etmin)
0410 return false;
0411 return false;
0412 }
0413
0414 correctionCategory_class::correctionCategory_class(TString category_) {
0415 std::string category(category_.Data());
0416 #ifdef DEBUG
0417 std::cout << "[DEBUG] correctionClass defined for category: " << category << std::endl;
0418 #endif
0419
0420 runmin = 0;
0421 runmax = 999999;
0422 etamin = 2;
0423 etamax = 7;
0424 r9min = -1;
0425 r9max = 0.94;
0426 etmin = -1;
0427 etmax = 99999.;
0428
0429 size_t p1, p2;
0430
0431 p1 = category.find("absEta_");
0432 if (category.find("absEta_0_1") != std::string::npos) {
0433 etamin = 0;
0434 etamax = 1;
0435 } else if (category.find("absEta_1_1.4442") != std::string::npos) {
0436 etamin = 1;
0437 etamax = 1.479;
0438 }
0439 else if (category.find("absEta_1.566_2") != std::string::npos) {
0440 etamin = 1.479;
0441 etamax = 2;
0442 }
0443 else if (category.find("absEta_2_2.5") != std::string::npos) {
0444 etamin = 2;
0445 etamax = 3;
0446 } else {
0447 if (p1 != std::string::npos) {
0448 p1 = category.find('_', p1);
0449 p2 = category.find('_', p1 + 1);
0450 etamin = TString(category.substr(p1 + 1, p2 - p1 - 1)).Atof();
0451 p1 = p2;
0452 p2 = category.find('-', p1);
0453 etamax = TString(category.substr(p1 + 1, p2 - p1 - 1)).Atof();
0454 }
0455 }
0456
0457 if (category.find("EBlowEta") != std::string::npos) {
0458 etamin = 0;
0459 etamax = 1;
0460 };
0461 if (category.find("EBhighEta") != std::string::npos) {
0462 etamin = 1;
0463 etamax = 1.479;
0464 };
0465 if (category.find("EElowEta") != std::string::npos) {
0466 etamin = 1.479;
0467 etamax = 2;
0468 };
0469 if (category.find("EEhighEta") != std::string::npos) {
0470 etamin = 2;
0471 etamax = 7;
0472 };
0473
0474
0475 p1 = category.find("-Et_");
0476
0477
0478
0479 if (p1 != std::string::npos) {
0480 p1 = category.find('_', p1);
0481 p2 = category.find('_', p1 + 1);
0482 etmin = TString(category.substr(p1 + 1, p2 - p1 - 1)).Atof();
0483 p1 = p2;
0484 p2 = category.find('-', p1);
0485 etmax = TString(category.substr(p1 + 1, p2 - p1 - 1)).Atof();
0486
0487 }
0488
0489 if (category.find("gold") != std::string::npos || category.find("Gold") != std::string::npos ||
0490 category.find("highR9") != std::string::npos) {
0491 r9min = 0.94;
0492 r9max = FLT_MAX;
0493 } else if (category.find("bad") != std::string::npos || category.find("Bad") != std::string::npos ||
0494 category.find("lowR9") != std::string::npos) {
0495 r9min = -1;
0496 r9max = 0.94;
0497 };
0498 }