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