CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
HCALResponse.cc
Go to the documentation of this file.
1 //FastSimulation headers
5 
6 // CMSSW Headers
9 
10 #include <iostream>
11 #include <vector>
12 #include <string>
13 #include <math.h>
14 
15 using namespace edm;
16 
17 HCALResponse::HCALResponse(const edm::ParameterSet& pset, const RandomEngine* engine) : random(engine), cball(random) {
18  //switches
19  debug = pset.getParameter<bool>("debug");
20  usemip = pset.getParameter<bool>("usemip");
21 
22 //values for "old" response parameterizations
23 //--------------------------------------------------------------------
24  RespPar[HCAL][0][0] = pset.getParameter<double>("HadronBarrelResolution_Stochastic");
25  RespPar[HCAL][0][1] = pset.getParameter<double>("HadronBarrelResolution_Constant");
26  RespPar[HCAL][0][2] = pset.getParameter<double>("HadronBarrelResolution_Noise");
27 
28  RespPar[HCAL][1][0] = pset.getParameter<double>("HadronEndcapResolution_Stochastic");
29  RespPar[HCAL][1][1] = pset.getParameter<double>("HadronEndcapResolution_Constant");
30  RespPar[HCAL][1][2] = pset.getParameter<double>("HadronEndcapResolution_Noise");
31 
32  RespPar[VFCAL][0][0] = pset.getParameter<double>("HadronForwardResolution_Stochastic");
33  RespPar[VFCAL][0][1] = pset.getParameter<double>("HadronForwardResolution_Constant");
34  RespPar[VFCAL][0][2] = pset.getParameter<double>("HadronForwardResolution_Noise");
35 
36  RespPar[VFCAL][1][0] = pset.getParameter<double>("ElectronForwardResolution_Stochastic");
37  RespPar[VFCAL][1][1] = pset.getParameter<double>("ElectronForwardResolution_Constant");
38  RespPar[VFCAL][1][2] = pset.getParameter<double>("ElectronForwardResolution_Noise");
39 
40  eResponseScale[0] = pset.getParameter<double>("eResponseScaleHB");
41  eResponseScale[1] = pset.getParameter<double>("eResponseScaleHE");
42  eResponseScale[2] = pset.getParameter<double>("eResponseScaleHF");
43 
44  eResponsePlateau[0] = pset.getParameter<double>("eResponsePlateauHB");
45  eResponsePlateau[1] = pset.getParameter<double>("eResponsePlateauHE");
46  eResponsePlateau[2] = pset.getParameter<double>("eResponsePlateauHF");
47 
48  eResponseExponent = pset.getParameter<double>("eResponseExponent");
49  eResponseCoefficient = pset.getParameter<double>("eResponseCoefficient");
50 
51 //pion parameters
52 //--------------------------------------------------------------------
53  //energy values
54  maxHDe[0] = pset.getParameter<int>("maxHBe");
55  maxHDe[1] = pset.getParameter<int>("maxHEe");
56  maxHDe[2] = pset.getParameter<int>("maxHFe");
57  eGridHD[0] = pset.getParameter<vec1>("eGridHB");
58  eGridHD[1] = pset.getParameter<vec1>("eGridHE");
59  eGridHD[2] = pset.getParameter<vec1>("eGridHF");
60 
61  //region eta indices calculated from eta values
62  etaStep = pset.getParameter<double>("etaStep");
63  //eta boundaries
64  HDeta[0] = abs((int)(pset.getParameter<double>("HBeta") / etaStep));
65  HDeta[1] = abs((int)(pset.getParameter<double>("HEeta") / etaStep));
66  HDeta[2] = abs((int)(pset.getParameter<double>("HFeta") / etaStep));
67  HDeta[3] = abs((int)(pset.getParameter<double>("maxHDeta") / etaStep)); //add 1 because this is the max index
68  //eta ranges
69  maxHDetas[0] = HDeta[1] - HDeta[0];
70  maxHDetas[1] = HDeta[2] - HDeta[1];
71  maxHDetas[2] = HDeta[3] - HDeta[2];
72 
73  //parameter info
74  nPar = pset.getParameter<int>("nPar");
75  parNames = pset.getParameter<std::vector<std::string> >("parNames");
76  std::string detNames[] = {"_HB","_HE","_HF"};
77  std::string mipNames[] = {"_mip","_nomip",""};
78 
79  //setup parameters (5D vector)
80  parameters = vec5(nPar,vec4(3,vec3(3)));
81  for(int p = 0; p < nPar; p++){ //loop over parameters
82  for(int m = 0; m < 3; m++){ //loop over mip, nomip, total
83  for(int d = 0; d < 3; d++){ //loop over dets: HB, HE, HF
84  //get from python
85  std::string pname = parNames[p] + detNames[d] + mipNames[m];
86  vec1 tmp = pset.getParameter<vec1>(pname);
87 
88  //resize vector for energy range of det d
89  parameters[p][m][d].resize(maxHDe[d]);
90 
91  for(int i = 0; i < maxHDe[d]; i++){ //loop over energy for det d
92  //resize vector for eta range of det d
93  parameters[p][m][d][i].resize(maxHDetas[d]);
94 
95  for(int j = 0; j < maxHDetas[d]; j++){ //loop over eta for det d
96  //fill in parameters vector from python
97  parameters[p][m][d][i][j] = tmp[i*maxHDetas[d] + j];
98  }
99  }
100  }
101  }
102  }
103 
104 // MUON probability histos for bin size = 0.25 GeV (0-10 GeV, 40 bins)
105 //--------------------------------------------------------------------
106  muStep = pset.getParameter<double>("muStep");
107  maxMUe = pset.getParameter<int>("maxMUe");
108  maxMUeta = pset.getParameter<int>("maxMUeta");
109  maxMUbin = pset.getParameter<int>("maxMUbin");
110  eGridMU = pset.getParameter<vec1>("eGridMU");
111  etaGridMU = pset.getParameter<vec1>("etaGridMU");
112  vec1 _responseMU[2] = {pset.getParameter<vec1>("responseMUBarrel"),pset.getParameter<vec1>("responseMUEndcap")};
113 
114  //get muon region eta indices from the eta grid
115  double _barrelMUeta = pset.getParameter<double>("barrelMUeta");
116  double _endcapMUeta = pset.getParameter<double>("endcapMUeta");
118  for(int i = 0; i < maxMUeta; i++) {
119  if(fabs(_barrelMUeta) <= etaGridMU[i]) { barrelMUeta = i; break; }
120  }
121  for(int i = 0; i < maxMUeta; i++) {
122  if(fabs(_endcapMUeta) <= etaGridMU[i]) { endcapMUeta = i; break; }
123  }
124  int maxMUetas[] = {endcapMUeta - barrelMUeta, maxMUeta - endcapMUeta};
125 
126  //initialize 3D vector
127  responseMU = vec3(maxMUe,vec2(maxMUeta,vec1(maxMUbin,0)));
128 
129  //fill in 3D vector
130  //(complementary cumulative distribution functions, from normalized response distributions)
131  int loc, eta_loc;
132  loc = eta_loc = -1;
133  for(int i = 0; i < maxMUe; i++){
134  for(int j = 0; j < maxMUeta; j++){
135  //check location - barrel, endcap, or forward
136  if(j==barrelMUeta) {loc = 0; eta_loc = barrelMUeta;}
137  else if(j==endcapMUeta) {loc = 1; eta_loc = endcapMUeta;}
138 
139  for(int k = 0; k < maxMUbin; k++){
140  responseMU[i][j][k] = _responseMU[loc][i*maxMUetas[loc]*maxMUbin + (j-eta_loc)*maxMUbin + k];
141 
142  if(debug) {
143  //cout.width(6);
144  LogInfo("FastCalorimetry") << " responseMU " << i << " " << j << " " << k << " = "
145  << responseMU[i][j][k] << std::endl;
146  }
147  }
148  }
149  }
150 
151 // values for EM response in HF
152 //--------------------------------------------------------------------
153  maxEMe = pset.getParameter<int>("maxEMe");
154  maxEMeta = maxHDetas[2];
155  respFactorEM = pset.getParameter<double>("respFactorEM");
156  eGridEM = pset.getParameter<vec1>("eGridEM");
157 
158  // e-gamma mean response and sigma in HF
159  vec1 _meanEM = pset.getParameter<vec1>("meanEM");
160  vec1 _sigmaEM = pset.getParameter<vec1>("sigmaEM");
161 
162  //fill in 2D vectors (w/ correction factor applied)
163  meanEM = vec2(maxEMe,vec1(maxEMeta,0));
164  sigmaEM = vec2(maxEMe,vec1(maxEMeta,0));
165  for(int i = 0; i < maxEMe; i++){
166  for(int j = 0; j < maxEMeta; j++){
167  meanEM[i][j] = respFactorEM * _meanEM[i*maxEMeta + j];
168  sigmaEM[i][j] = respFactorEM * _sigmaEM[i*maxEMeta + j];
169  }
170  }
171 
172 }
173 
174 
175 double HCALResponse::responseHCAL(int _mip, double energy, double eta, int partype){
176  int ieta = abs((int)(eta / etaStep)) ;
177  int ie = -1;
178 
179  int mip;
180  if(usemip) mip = _mip;
181  else mip = 2; //ignore mip, use only overall (mip + nomip) parameters
182 
183  double mean = 0;
184 
185  // e/gamma in HF
186  if(partype == 0) {
187  //check eta
188  ieta -= HDeta[2]; // HF starts at ieta=30 till ieta=51
189  // but resp.vector from index=0 through 20
190  if(ieta >= maxEMeta ) ieta = maxEMeta-1;
191  else if(ieta < 0) ieta = 0;
192 
193  //find energy range
194  for (int i = 0; i < maxEMe; i++) {
195  if(energy < eGridEM[i]) {
196  if(i == 0) ie = 0; // less than minimal - back extrapolation with the 1st interval
197  else ie = i-1;
198  break;
199  }
200  }
201  if(ie == -1) ie = maxEMe - 2; // more than maximum - extrapolation with last interval
202 
203  //do smearing
204  mean = interEM(energy, ie, ieta);
205  }
206 
207  // hadrons
208  else if(partype == 1) {
209  //check eta and det
210  int det = getDet(ieta);
211  int deta = ieta - HDeta[det];
212  if(deta >= maxHDetas[det]) deta = maxHDetas[det] - 1;
213  else if(deta < 0 ) deta = 0;
214 
215  //find energy range
216  for (int i = 0; i < maxHDe[det]; i++) {
217  if(energy < eGridHD[det][i]) {
218  if(i == 0) ie = 0; // less than minimal - back extrapolation with the 1st interval
219  else ie = i-1;
220  break;
221  }
222  }
223  if(ie == -1) ie = maxHDe[det] - 2; // more than maximum - extrapolation with last interval
224 
225  //do smearing
226  mean = interHD(mip, energy, ie, deta, det);
227  }
228 
229 
230  // muons
231  else if(partype == 2) {
232  //check eta
233  ieta = maxMUeta;
234  for(int i = 0; i < maxMUeta; i++) {
235  if(fabs(eta) < etaGridMU[i]) {
236  ieta = i;
237  break;
238  }
239  }
240  if(ieta < 0) ieta = 0;
241 
242  if(ieta < maxMUeta) { // HB-HE
243  //find energy range
244  for (int i = 0; i < maxMUe; i++) {
245  if(energy < eGridMU[i]) {
246  if(i == 0) ie = 0; // less than minimal - back extrapolation with the 1st interval
247  else ie = i-1;
248  break;
249  }
250  }
251  if(ie == -1) ie = maxMUe - 2; // more than maximum - extrapolation with last interval
252 
253  //do smearing
254  mean = interMU(energy, ie, ieta);
255  if(mean > energy) mean = energy;
256  }
257  }
258 
259  // debugging
260  if(debug) {
261  // cout.width(6);
262  LogInfo("FastCalorimetry") << std::endl
263  << " HCALResponse::responseHCAL, partype = " << partype
264  << " E, eta = " << energy << " " << eta
265  << " mean = " << mean << std::endl;
266  }
267 
268  return mean;
269 }
270 
271 double HCALResponse::interMU(double e, int ie, int ieta) {
272  double x = random->flatShoot();
273 
274  int bin1 = maxMUbin;
275  for(int i = 0; i < maxMUbin; i++) {
276  if(x > responseMU[ie][ieta][i]) {
277  bin1 = i-1;
278  break;
279  }
280  }
281  int bin2 = maxMUbin;
282  for(int i = 0; i < maxMUbin; i++) {
283  if(x > responseMU[ie+1][ieta][i]) {
284  bin2 = i-1;
285  break;
286  }
287  }
288 
289  double x1 = eGridMU[ie];
290  double x2 = eGridMU[ie+1];
291  double y1 = (bin1 + random->flatShoot()) * muStep;
292  double y2 = (bin2 + random->flatShoot()) * muStep;
293 
294  if(debug) {
295  // cout.width(6);
296  LogInfo("FastCalorimetry") << std::endl
297  << " HCALResponse::interMU " << std::endl
298  << " x, x1-x2, y1-y2 = "
299  << e << ", " << x1 <<"-" << x2 << " " << y1 <<"-" << y2 << std::endl;
300 
301  }
302 
303  //linear interpolation
304  double mean = (y1*(x2-e) + y2*(e-x1))/(x2-x1);
305 
306  if(debug) {
307  //cout.width(6);
308  LogInfo("FastCalorimetry") << std::endl
309  << " HCALResponse::interMU " << std::endl
310  << " e, ie, ieta = " << e << " " << ie << " " << ieta << std::endl
311  << " response = " << mean << std::endl;
312  }
313 
314  return mean;
315 }
316 
317 double HCALResponse::interHD(int mip, double e, int ie, int ieta, int det) {
318  double y1, y2;
319 
320  double x1 = eGridHD[det][ie];
321  double x2 = eGridHD[det][ie+1];
322 
323  vec1 pars(nPar,0);
324 
325  //calculate all parameters
326  for(int p = 0; p < nPar; p++){
327  y1 = parameters[p][mip][det][ie][ieta];
328  y2 = parameters[p][mip][det][ie+1][ieta];
329 
330  //par-specific checks
331  double custom = 0;
332  bool use_custom = false;
333 
334  //do not let mu or sigma get extrapolated below zero for low energies
335  //especially important for HF since extrapolation is used for E < 15 GeV
336  if((p==0 || p==1) && e < x1){
337  double tmp = (y1*x2-y2*x1)/(x2-x1); //extrapolate down to e=0
338  if(tmp<0) { //require mu,sigma > 0 for E > 0
339  custom = y1*e/x1;
340  use_custom = true;
341  }
342  }
343  //tail parameters have lower bounds - never extrapolate down
344  else if((p==2 || p==3 || p==4 || p==5)){
345  if(e < x1 && y1 < y2){
346  custom = y1;
347  use_custom = true;
348  }
349  else if(e > x2 && y2 < y1){
350  custom = y2;
351  use_custom = true;
352  }
353  }
354 
355  //linear interpolation
356  if(use_custom) pars[p] = custom;
357  else pars[p] = (y1*(x2-e) + y2*(e-x1))/(x2-x1);
358  }
359 
360  //random smearing
361  double mean = 0;
362  if(nPar==6) mean = cballShootNoNegative(pars[0],pars[1],pars[2],pars[3],pars[4],pars[5]);
363  else if(nPar==2) mean = gaussShootNoNegative(pars[0],pars[1]); //gaussian fallback
364 
365  return mean;
366 }
367 
368 
369 double HCALResponse::interEM(double e, int ie, int ieta) {
370  double y1 = meanEM[ie][ieta];
371  double y2 = meanEM[ie+1][ieta];
372  double x1 = eGridEM[ie];
373  double x2 = eGridEM[ie+1];
374 
375  if(debug) {
376  // cout.width(6);
377  LogInfo("FastCalorimetry") << std::endl
378  << " HCALResponse::interEM mean " << std::endl
379  << " x, x1-x2, y1-y2 = "
380  << e << ", " << x1 <<"-" << x2 << " " << y1 <<"-" << y2 << std::endl;
381  }
382 
383  //linear interpolation
384  double mean = (y1*(x2-e) + y2*(e-x1))/(x2-x1);
385 
386  y1 = sigmaEM[ie][ieta];
387  y2 = sigmaEM[ie+1][ieta];
388 
389  if(debug) {
390  // cout.width(6);
391  LogInfo("FastCalorimetry") << std::endl
392  << " HCALResponse::interEM sigma" << std::endl
393  << " x, x1-x2, y1-y2 = "
394  << e << ", " << x1 <<"-" << x2 << " " << y1 <<"-" << y2 << std::endl;
395  }
396 
397  //linear interpolation
398  double sigma = (y1*(x2-e) + y2*(e-x1))/(x2-x1);
399 
400  //random smearing
401  double rndm = gaussShootNoNegative(mean,sigma);
402 
403  return rndm;
404 }
405 
406 // Old parameterization of the calo response to hadrons
408  //response
409  double s = eResponseScale[hit];
410  double n = eResponseExponent;
411  double p = eResponsePlateau[hit];
412  double c = eResponseCoefficient;
413 
414  double response = e * p / (1+c*exp(n * log(s/e)));
415 
416  if(response<0.) response = 0.;
417 
418  //resolution
419  double resolution;
420  if(hit==hcforward)
421  resolution = e *sqrt( RespPar[VFCAL][1][0]*RespPar[VFCAL][1][0] / e + RespPar[VFCAL][1][1]*RespPar[VFCAL][1][1] );
422  else
423  resolution = e * sqrt( RespPar[HCAL][hit][0]*RespPar[HCAL][hit][0]/(e) + RespPar[HCAL][hit][1]*RespPar[HCAL][hit][1] );
424 
425  //random smearing
426  double rndm = gaussShootNoNegative(response,resolution);
427 
428  return rndm;
429 }
430 
431 //find subdet and eta offset
432 int HCALResponse::getDet(int ieta){
433  int d;
434  for(d = 0; d < 2; d++){
435  if(ieta < HDeta[d+1]){
436  break;
437  }
438  }
439  return d;
440 }
441 
442 // Remove (most) hits with negative energies
443 double HCALResponse::gaussShootNoNegative(double e, double sigma) {
444  double out = random->gaussShoot(e,sigma);
445  if (e >= 0.) {
446  while (out < 0.) out = random->gaussShoot(e,sigma);
447  }
448  //else give up on re-trying, otherwise too much time can be lost before emeas comes out positive
449 
450  return out;
451 }
452 
453 // Remove (most) hits with negative energies
454 double HCALResponse::cballShootNoNegative(double mu, double sigma, double aL, double nL, double aR, double nR) {
455  double out = cball.shoot(mu,sigma,aL,nL,aR,nR);
456  if (mu >= 0.) {
457  while (out < 0.) out = cball.shoot(mu,sigma,aL,nL,aR,nR);
458  }
459  //else give up on re-trying, otherwise too much time can be lost before emeas comes out positive
460 
461  return out;
462 }
double getHCALEnergyResponse(double e, int hit)
double etaStep
Definition: HCALResponse.h:77
T getParameter(std::string const &) const
double RespPar[3][2][3]
Definition: HCALResponse.h:65
int i
Definition: DBlmapReader.cc:9
int maxHDe[3]
Definition: HCALResponse.h:75
HCALResponse(const edm::ParameterSet &pset, const RandomEngine *engine)
Definition: HCALResponse.cc:17
const RandomEngine * random
Definition: HCALResponse.h:106
double interHD(int mip, double e, int ie, int ieta, int det)
int HDeta[4]
Definition: HCALResponse.h:79
double eResponseCoefficient
Definition: HCALResponse.h:71
int getDet(int ieta)
double eResponseScale[3]
Definition: HCALResponse.h:68
std::vector< std::string > parNames
Definition: HCALResponse.h:94
#define abs(x)
Definition: mlp_lapack.h:159
TRandom random
Definition: MVATrainer.cc:138
double eResponseExponent
Definition: HCALResponse.h:70
T eta() const
double gaussShoot(double mean=0.0, double sigma=1.0) const
Definition: RandomEngine.h:37
double gaussShootNoNegative(double e, double sigma)
double interEM(double e, int ie, int ieta)
std::vector< vec4 > vec5
Definition: HCALResponse.h:19
std::vector< vec2 > vec3
Definition: HCALResponse.h:17
double interMU(double e, int ie, int ieta)
vec1 eGridHD[3]
Definition: HCALResponse.h:86
std::vector< double > vec1
Definition: HCALResponse.h:15
double muStep
Definition: HCALResponse.h:81
T sqrt(T t)
Definition: SSEVec.h:48
int j
Definition: DBlmapReader.cc:9
std::vector< vec3 > vec4
Definition: HCALResponse.h:18
const int mu
Definition: Constants.h:23
int k[5][pyjets_maxn]
tuple out
Definition: dbtoconf.py:99
double respFactorEM
Definition: HCALResponse.h:83
double flatShoot(double xmin=0.0, double xmax=1.0) const
Definition: RandomEngine.h:30
double cballShootNoNegative(double mu, double sigma, double aL, double nL, double aR, double nR)
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
int maxHDetas[3]
Definition: HCALResponse.h:79
double responseHCAL(int _mip, double energy, double eta, int partype)
DoubleCrystalBallGenerator cball
Definition: HCALResponse.h:109
Definition: DDAxes.h:10
std::vector< vec1 > vec2
Definition: HCALResponse.h:16
double shoot(double mu, double sigma, double aL, double nL, double aR, double nR)
double eResponsePlateau[3]
Definition: HCALResponse.h:69