00001
00002 #include "FastSimulation/Calorimetry/interface/HCALResponse.h"
00003 #include "FastSimulation/Utilities/interface/RandomEngine.h"
00004
00005
00006 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00008
00009 #include <iostream>
00010 #include <vector>
00011 #include <math.h>
00012
00013 using namespace edm;
00014
00015 HCALResponse::HCALResponse(const edm::ParameterSet& pset,
00016 const RandomEngine* engine) :
00017 random(engine)
00018 {
00019
00020 debug = pset.getParameter<bool>("debug");
00021 usemip = pset.getParameter<bool>("usemip");
00022
00023
00024
00025 RespPar[HCAL][0][0] = pset.getParameter<double>("HadronBarrelResolution_Stochastic");
00026 RespPar[HCAL][0][1] = pset.getParameter<double>("HadronBarrelResolution_Constant");
00027 RespPar[HCAL][0][2] = pset.getParameter<double>("HadronBarrelResolution_Noise");
00028
00029 RespPar[HCAL][1][0] = pset.getParameter<double>("HadronEndcapResolution_Stochastic");
00030 RespPar[HCAL][1][1] = pset.getParameter<double>("HadronEndcapResolution_Constant");
00031 RespPar[HCAL][1][2] = pset.getParameter<double>("HadronEndcapResolution_Noise");
00032
00033 RespPar[VFCAL][0][0] = pset.getParameter<double>("HadronForwardResolution_Stochastic");
00034 RespPar[VFCAL][0][1] = pset.getParameter<double>("HadronForwardResolution_Constant");
00035 RespPar[VFCAL][0][2] = pset.getParameter<double>("HadronForwardResolution_Noise");
00036
00037 RespPar[VFCAL][1][0] = pset.getParameter<double>("ElectronForwardResolution_Stochastic");
00038 RespPar[VFCAL][1][1] = pset.getParameter<double>("ElectronForwardResolution_Constant");
00039 RespPar[VFCAL][1][2] = pset.getParameter<double>("ElectronForwardResolution_Noise");
00040
00041 eResponseScale[0] = pset.getParameter<double>("eResponseScaleHB");
00042 eResponseScale[1] = pset.getParameter<double>("eResponseScaleHE");
00043 eResponseScale[2] = pset.getParameter<double>("eResponseScaleHF");
00044
00045 eResponsePlateau[0] = pset.getParameter<double>("eResponsePlateauHB");
00046 eResponsePlateau[1] = pset.getParameter<double>("eResponsePlateauHE");
00047 eResponsePlateau[2] = pset.getParameter<double>("eResponsePlateauHF");
00048
00049 eResponseExponent = pset.getParameter<double>("eResponseExponent");
00050 eResponseCoefficient = pset.getParameter<double>("eResponseCoefficient");
00051 eResponseCorrection = pset.getParameter<double>("eResponseCorrection");
00052
00053
00054 eBias = pset.getParameter<double>("energyBias");
00055
00056
00057
00058 etaStep = pset.getParameter<double>("etaStep");
00059 maxHDe = pset.getParameter<int>("maxHDe");
00060 eGridHD = pset.getParameter<std::vector<double> >("eGridHD");
00061
00062
00063 maxHDeta = abs((int)(pset.getParameter<double>("maxHDeta") / etaStep)) + 1;
00064 barrelHDeta = abs((int)(pset.getParameter<double>("barrelHDeta") / etaStep));
00065 endcapHDeta = abs((int)(pset.getParameter<double>("endcapHDeta") / etaStep));
00066 forwardHDeta = abs((int)(pset.getParameter<double>("forwardHDeta") / etaStep));
00067 int maxHDetas[] = {endcapHDeta - barrelHDeta, forwardHDeta - endcapHDeta, maxHDeta - forwardHDeta};
00068
00069
00070 useAdHocCorrections_ = pset.getParameter<bool>("useAdHocCorrections");
00071 barrelCorrection = pset.getParameter<std::vector<double> >("barrelCorrection");
00072 endcapCorrection = pset.getParameter<std::vector<double> >("endcapCorrection");
00073 forwardCorrectionEnergyDependent = pset.getParameter<std::vector<double> >("forwardCorrectionEnergyDependent");
00074 forwardCorrectionEtaDependent = pset.getParameter<std::vector<double> >("forwardCorrectionEtaDependent");
00075
00076
00077 std::vector<double> _meanHD[3] = {pset.getParameter<std::vector<double> >("meanHDBarrel"),pset.getParameter<std::vector<double> >("meanHDEndcap"),pset.getParameter<std::vector<double> >("meanHDForward")};
00078 std::vector<double> _meanHD_mip[3] = {pset.getParameter<std::vector<double> >("meanHDBarrel_mip"),pset.getParameter<std::vector<double> >("meanHDEndcap_mip"),pset.getParameter<std::vector<double> >("meanHDForward_mip")};
00079 std::vector<double> _meanHD_nomip[3] = {pset.getParameter<std::vector<double> >("meanHDBarrel_nomip"),pset.getParameter<std::vector<double> >("meanHDEndcap_nomip"),pset.getParameter<std::vector<double> >("meanHDForward_nomip")};
00080
00081
00082 std::vector<double> _sigmaHD[3] = {pset.getParameter<std::vector<double> >("sigmaHDBarrel"),pset.getParameter<std::vector<double> >("sigmaHDEndcap"),pset.getParameter<std::vector<double> >("sigmaHDForward")};
00083 std::vector<double> _sigmaHD_mip[3] = {pset.getParameter<std::vector<double> >("sigmaHDBarrel_mip"),pset.getParameter<std::vector<double> >("sigmaHDEndcap_mip"),pset.getParameter<std::vector<double> >("sigmaHDForward_mip")};
00084 std::vector<double> _sigmaHD_nomip[3] = {pset.getParameter<std::vector<double> >("sigmaHDBarrel_nomip"),pset.getParameter<std::vector<double> >("sigmaHDEndcap_nomip"),pset.getParameter<std::vector<double> >("sigmaHDForward_nomip")};
00085
00086
00087 meanHD = std::vector<std::vector<double> >(maxHDe,std::vector<double>(maxHDeta,0));
00088 meanHD_mip = std::vector<std::vector<double> >(maxHDe,std::vector<double>(maxHDeta,0));
00089 meanHD_nomip = std::vector<std::vector<double> >(maxHDe,std::vector<double>(maxHDeta,0));
00090 sigmaHD = std::vector<std::vector<double> >(maxHDe,std::vector<double>(maxHDeta,0));
00091 sigmaHD_mip = std::vector<std::vector<double> >(maxHDe,std::vector<double>(maxHDeta,0));
00092 sigmaHD_nomip = std::vector<std::vector<double> >(maxHDe,std::vector<double>(maxHDeta,0));
00093
00094
00095 int loc, eta_loc;
00096 loc = eta_loc = -1;
00097 for(int i = 0; i < maxHDe; i++){
00098 for(int j = 0; j < maxHDeta; j++){
00099
00100 if(j==barrelHDeta) {loc = 0; eta_loc = barrelHDeta;}
00101 else if(j==endcapHDeta) {loc = 1; eta_loc = endcapHDeta;}
00102 else if(j==forwardHDeta) {loc = 2; eta_loc = forwardHDeta;}
00103
00104 meanHD[i][j] = _meanHD[loc][i*maxHDetas[loc] + j - eta_loc];
00105 meanHD_mip[i][j] = _meanHD_mip[loc][i*maxHDetas[loc] + j - eta_loc];
00106 meanHD_nomip[i][j] = _meanHD_nomip[loc][i*maxHDetas[loc] + j - eta_loc];
00107 sigmaHD[i][j] = _sigmaHD[loc][i*maxHDetas[loc] + j - eta_loc];
00108 sigmaHD_mip[i][j] = _sigmaHD_mip[loc][i*maxHDetas[loc] + j - eta_loc];
00109 sigmaHD_nomip[i][j] = _sigmaHD_nomip[loc][i*maxHDetas[loc] + j - eta_loc];
00110 }
00111 }
00112
00113
00114
00115 muStep = pset.getParameter<double>("muStep");
00116 maxMUe = pset.getParameter<int>("maxMUe");
00117 maxMUeta = pset.getParameter<int>("maxMUeta");
00118 maxMUbin = pset.getParameter<int>("maxMUbin");
00119 eGridMU = pset.getParameter<std::vector<double> >("eGridMU");
00120 etaGridMU = pset.getParameter<std::vector<double> >("etaGridMU");
00121 std::vector<double> _responseMU[2] = {pset.getParameter<std::vector<double> >("responseMUBarrel"),pset.getParameter<std::vector<double> >("responseMUEndcap")};
00122
00123
00124 double _barrelMUeta = pset.getParameter<double>("barrelMUeta");
00125 double _endcapMUeta = pset.getParameter<double>("endcapMUeta");
00126 barrelMUeta = endcapMUeta = maxMUeta;
00127 for(int i = 0; i < maxMUeta; i++) {
00128 if(fabs(_barrelMUeta) <= etaGridMU[i]) { barrelMUeta = i; break; }
00129 }
00130 for(int i = 0; i < maxMUeta; i++) {
00131 if(fabs(_endcapMUeta) <= etaGridMU[i]) { endcapMUeta = i; break; }
00132 }
00133 int maxMUetas[] = {endcapMUeta - barrelMUeta, maxMUeta - endcapMUeta};
00134
00135
00136 responseMU = std::vector<std::vector<std::vector<double> > >(maxMUe,std::vector<std::vector<double> >(maxMUeta,std::vector<double>(maxMUbin,0)));
00137
00138
00139
00140 loc = eta_loc = -1;
00141 for(int i = 0; i < maxMUe; i++){
00142 for(int j = 0; j < maxMUeta; j++){
00143
00144 if(j==barrelMUeta) {loc = 0; eta_loc = barrelMUeta;}
00145 else if(j==endcapMUeta) {loc = 1; eta_loc = endcapMUeta;}
00146
00147 for(int k = 0; k < maxMUbin; k++){
00148 responseMU[i][j][k] = _responseMU[loc][i*maxMUetas[loc]*maxMUbin + (j-eta_loc)*maxMUbin + k];
00149
00150 if(debug) {
00151
00152 LogInfo("FastCalorimetry") << " responseMU " << i << " " << j << " " << k << " = "
00153 << responseMU[i][j][k] << std::endl;
00154 }
00155 }
00156 }
00157 }
00158
00159
00160
00161 maxEMe = pset.getParameter<int>("maxEMe");
00162 maxEMeta = maxHDetas[2];
00163 respFactorEM = pset.getParameter<double>("respFactorEM");
00164 eGridEM = pset.getParameter<std::vector<double> >("eGridEM");
00165
00166
00167 std::vector<double> _meanEM = pset.getParameter<std::vector<double> >("meanEM");
00168 std::vector<double> _sigmaEM = pset.getParameter<std::vector<double> >("sigmaEM");
00169
00170
00171 for(int i = 0; i < maxEMe; i++){
00172 std::vector<double> m_tmp;
00173 std::vector<double> s_tmp;
00174 for(int j = 0; j < maxEMeta; j++){
00175 m_tmp.push_back(_meanEM[i*maxEMeta + j]);
00176 s_tmp.push_back(_sigmaEM[i*maxEMeta + j]);
00177 }
00178 meanEM.push_back(m_tmp);
00179 sigmaEM.push_back(s_tmp);
00180 }
00181
00182
00183
00184 for(int i = 0; i<maxHDe; i++) {
00185 for(int j = 0; j<maxHDeta; j++) {
00186 double factor = 1.0;
00187 double factor_s = 1.0;
00188
00189 if (useAdHocCorrections_) {
00190 if( j < endcapHDeta) factor = barrelCorrection[i];
00191 else if( j < forwardHDeta) factor = endcapCorrection[i];
00192 else factor = forwardCorrectionEnergyDependent[i]*forwardCorrectionEtaDependent[j-forwardHDeta];
00193 } else factor = 1.;
00194
00195 meanHD[i][j] = factor * meanHD[i][j] / eGridHD[i];
00196 sigmaHD[i][j] = factor_s * sigmaHD[i][j] / eGridHD[i];
00197
00198 meanHD_mip[i][j] = factor * meanHD_mip[i][j] / eGridHD[i];
00199 sigmaHD_mip[i][j] = factor_s * sigmaHD_mip[i][j] / eGridHD[i];
00200
00201 meanHD_nomip[i][j] = factor * meanHD_nomip[i][j] / eGridHD[i];
00202 sigmaHD_nomip[i][j] = factor_s * sigmaHD_nomip[i][j] / eGridHD[i];
00203
00204 }
00205 }
00206
00207 for(int i = 0; i<maxEMe; i++) {
00208 for(int j = 0; j<maxEMeta; j++) {
00209 meanEM[i][j] = respFactorEM * meanEM[i][j] / eGridEM[i];
00210 sigmaEM[i][j] = respFactorEM * sigmaEM[i][j] / eGridEM[i];
00211 }
00212 }
00213
00214
00215 }
00216
00217
00218 std::pair<double,double>
00219 HCALResponse::responseHCAL(int _mip, double energy, double eta, int partype){
00220 int ieta = abs((int)(eta / etaStep)) ;
00221 int ie = -1;
00222
00223 int mip;
00224 if(usemip) mip = _mip;
00225 else mip = 2;
00226
00227 mean = 0.;
00228 sigma = 0.;
00229
00230
00231 if(partype == 0) {
00232 ieta -= forwardHDeta;
00233
00234 if(ieta >= maxEMeta ) ieta = maxEMeta-1;
00235 else if(ieta < 0) ieta = 0;
00236
00237 for (int i = 0; i < maxEMe; i++) {
00238 if(energy < eGridEM[i]) {
00239 if(i == 0) ie = 0;
00240 else ie = i-1;
00241 break;
00242 }
00243 }
00244 if(ie == -1) ie = maxEMe - 2;
00245 interEM(energy, ie, ieta);
00246 }
00247
00248
00249 else if(partype == 1) {
00250 if(ieta >= maxHDeta) ieta = maxHDeta-1;
00251
00252 if(ieta < 0 ) ieta = 0;
00253 for (int i = 0; i < maxHDe; i++) {
00254 if(energy < eGridHD[i]) {
00255 if(i == 0) ie = 0;
00256 else ie = i-1;
00257 break;
00258 }
00259 }
00260 if(ie == -1) ie = maxHDe - 2;
00261
00262 interHD(mip, energy, ie, ieta);
00263
00264
00265 mean *= eResponseCorrection;
00266 mean += eBias;
00267 sigma *= eResponseCorrection;
00268 }
00269
00270
00271
00272 else if(partype == 2) {
00273
00274 ieta = maxMUeta;
00275 for(int i = 0; i < maxMUeta; i++) {
00276 if(fabs(eta) < etaGridMU[i]) {
00277 ieta = i;
00278 break;
00279 }
00280 }
00281 if(ieta < 0) ieta = 0;
00282
00283 if(ieta < maxMUeta) {
00284
00285 for (int i = 0; i < maxMUe; i++) {
00286 if(energy < eGridMU[i]) {
00287 if(i == 0) ie = 0;
00288 else ie = i-1;
00289 break;
00290 }
00291 }
00292 if(ie == -1) ie = maxMUe - 2;
00293
00294 interMU(energy, ie, ieta);
00295
00296 if(mean > energy) mean = energy;
00297 }
00298 }
00299
00300
00301 if(debug) {
00302
00303 LogInfo("FastCalorimetry") << std::endl
00304 << " HCALResponse::responseHCAL, partype = " << partype
00305 << " E, eta = " << energy << " " << eta
00306 << " mean & sigma = " << mean << " " << sigma << std::endl;
00307 }
00308
00309 return std::pair<double,double>(mean,sigma);
00310 }
00311
00312 void HCALResponse::interMU(double e, int ie, int ieta)
00313 {
00314
00315 double x = random->flatShoot();
00316
00317 int bin1 = maxMUbin;
00318 for(int i = 0; i < maxMUbin; i++) {
00319 if(x > responseMU[ie][ieta][i]) {
00320 bin1 = i-1;
00321 break;
00322 }
00323 }
00324 int bin2 = maxMUbin;
00325 for(int i = 0; i < maxMUbin; i++) {
00326 if(x > responseMU[ie+1][ieta][i]) {
00327 bin2 = i-1;
00328 break;
00329 }
00330 }
00331
00332 double x1 = eGridMU[ie];
00333 double x2 = eGridMU[ie+1];
00334 double y1 = (bin1 + random->flatShoot()) * muStep;
00335 double y2 = (bin2 + random->flatShoot()) * muStep;
00336
00337 if(debug) {
00338
00339 LogInfo("FastCalorimetry") << std::endl
00340 << " HCALResponse::interMU " << std::endl
00341 << " x, x1-x2, y1-y2 = "
00342 << e << ", " << x1 <<"-" << x2 << " " << y1 <<"-" << y2 << std::endl;
00343
00344 }
00345
00346
00347 mean = y1 + (y2-y1) * (e - x1)/(x2 - x1);
00348 sigma = 0.;
00349
00350 if(debug) {
00351
00352 LogInfo("FastCalorimetry") << std::endl
00353 << " HCALResponse::interMU " << std::endl
00354 << " e, ie, ieta = " << e << " " << ie << " " << ieta << std::endl
00355 << " response = " << mean << std::endl;
00356 }
00357
00358 }
00359
00360 void HCALResponse::interHD(int mip, double e, int ie, int ieta)
00361 {
00362
00363 double y1, y2;
00364
00365 double x1 = eGridHD[ie];
00366 double x2 = eGridHD[ie+1];
00367
00368 if(mip == 2) {
00369 y1 = meanHD[ie][ieta];
00370 y2 = meanHD[ie+1][ieta];
00371 }
00372 else {
00373 if(mip == 0) {
00374 y1 = meanHD_nomip[ie][ieta];
00375 y2 = meanHD_nomip[ie+1][ieta];
00376 }
00377 else {
00378 y1 = meanHD_mip[ie][ieta];
00379 y2 = meanHD_mip[ie+1][ieta];
00380 }
00381 }
00382
00383 if(debug) {
00384
00385 LogInfo("FastCalorimetry") << std::endl
00386 << " HCALResponse::interHD mean " << std::endl
00387 << " x, x1-x2, y1-y2 = "
00388 << e << ", " << x1 <<"-" << x2 << " "
00389 << y1 <<"-" << y2 << std::endl;
00390 }
00391
00392 mean = e * (y1 + (y2 - y1) * (e - x1)/(x2 - x1));
00393
00394
00395 if(mip == 2) {
00396 y1 = sigmaHD[ie][ieta];
00397 y2 = sigmaHD[ie+1][ieta];
00398 }
00399 else {
00400 if(mip == 0) {
00401 y1 = sigmaHD_nomip[ie][ieta];
00402 y2 = sigmaHD_nomip[ie+1][ieta];
00403 }
00404 else {
00405 y1 = sigmaHD_mip[ie][ieta];
00406 y2 = sigmaHD_mip[ie+1][ieta];
00407 }
00408 }
00409
00410 if(debug) {
00411
00412 LogInfo("FastCalorimetry") << std::endl
00413 << " HCALResponse::interHD sigma" << std::endl
00414 << " x, x1-x2, y1-y2 = "
00415 << e << ", " << x1 <<"-" << x2 << " " << y1 <<"-" << y2 << std::endl;
00416
00417 }
00418
00419 sigma = e * (y1 + (y2 - y1) * (e - x1)/(x2 - x1));
00420
00421
00422 if(debug) {
00423
00424 LogInfo("FastCalorimetry") << std::endl
00425 << " HCALResponse::interHD " << std::endl
00426 << " e, ie, ieta = " << e << " " << ie << " " << ieta << std::endl
00427 << " mean, sigma = " << mean << " " << sigma << std::endl ;
00428 }
00429
00430 }
00431
00432
00433 void HCALResponse::interEM(double e, int ie, int ieta)
00434 {
00435 double y1 = meanEM[ie][ieta];
00436 double y2 = meanEM[ie+1][ieta];
00437 double x1 = eGridEM[ie];
00438 double x2 = eGridEM[ie+1];
00439
00440 if(debug) {
00441
00442 LogInfo("FastCalorimetry") << std::endl
00443 << " HCALResponse::interEM mean " << std::endl
00444 << " x, x1-x2, y1-y2 = "
00445 << e << ", " << x1 <<"-" << x2 << " " << y1 <<"-" << y2 << std::endl;
00446
00447 }
00448
00449 mean = e * (y1 + (y2 - y1) * (e - x1)/(x2 - x1));
00450
00451 y1 = sigmaEM[ie][ieta];
00452 y2 = sigmaEM[ie+1][ieta];
00453
00454 if(debug) {
00455
00456 LogInfo("FastCalorimetry") << std::endl
00457 << " HCALResponse::interEM sigma" << std::endl
00458 << " x, x1-x2, y1-y2 = "
00459 << e << ", " << x1 <<"-" << x2 << " " << y1 <<"-" << y2 << std::endl;
00460
00461 }
00462
00463 sigma = e * (y1 + (y2 - y1) * (e - x1)/(x2 - x1));
00464 }
00465
00466
00467 double HCALResponse::getHCALEnergyResolution(double e, int hit){
00468
00469 if(hit==hcforward)
00470 return e *sqrt( RespPar[VFCAL][1][0]*RespPar[VFCAL][1][0] / e +
00471 RespPar[VFCAL][1][1]*RespPar[VFCAL][1][1] );
00472 else
00473 return e * sqrt( RespPar[HCAL][hit][0]*RespPar[HCAL][hit][0]/(e)
00474 + RespPar[HCAL][hit][1]*RespPar[HCAL][hit][1]);
00475
00476 }
00477
00478
00479 double HCALResponse::getHCALEnergyResponse(double e, int hit){
00480
00481 double s = eResponseScale[hit];
00482 double n = eResponseExponent;
00483 double p = eResponsePlateau[hit];
00484 double c = eResponseCoefficient;
00485
00486 double response = e * p / (1+c*exp(n * log(s/e)));
00487
00488 if(response<0.) response = 0.;
00489
00490 return response;
00491 }
00492
00493
00494 double HCALResponse::getHFEnergyResolution(double EGen)
00495 {
00496 return EGen *sqrt( RespPar[VFCAL][0][0]*RespPar[VFCAL][0][0] / EGen +
00497 RespPar[VFCAL][0][1]*RespPar[VFCAL][0][1] );
00498 }