CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
HcalQie.cc
Go to the documentation of this file.
1 // File: HcalQie.cc
3 // Description: Simulation of QIE readout for HCal
5 
7 
10 #include "CLHEP/Random/RandGaussQ.h"
11 #include "CLHEP/Random/RandPoissonQ.h"
13 #include "CLHEP/Units/GlobalPhysicalConstants.h"
14 
15 #include <iostream>
16 #include <iomanip>
17 #include <cmath>
18 
19 //#define DebugLog
20 
22 
23  //static SimpleConfigurable<double> p1(4.0, "HcalQie:qToPE");
24  //static SimpleConfigurable<int> p2(6, "HcalQie:BinOfMax");
25  //static SimpleConfigurable<int> p3(2, "HcalQie:SignalBuckets");
26  //static SimpleConfigurable<int> p4(0, "HcalQie:PreSamples");
27  //static SimpleConfigurable<int> p5(10, "HcalQie:NumOfBuckets");
28  //static SimpleConfigurable<double> p6(0.5, "HcalQie:SigmaNoise");
29  //static SimpleConfigurable<double> p7(0.0005,"HcalQie:EDepPerPE");
30  //static SimpleConfigurable<int> p8(4, "HcalQie:BaseLine");
31 
33  qToPE = m_HQ.getParameter<double>("qToPE");
34  binOfMax = m_HQ.getParameter<int>("BinOfMax");
35  signalBuckets = m_HQ.getParameter<int>("SignalBuckets");
36  preSamples = m_HQ.getParameter<int>("PreSamples");
37  numOfBuckets = m_HQ.getParameter<int>("NumOfBuckets");
38  sigma = m_HQ.getParameter<double>("SigmaNoise");
39  eDepPerPE = m_HQ.getParameter<double>("EDepPerPE");
40  int bl = m_HQ.getParameter<int>("BaseLine");
41 
42  shape_ = shape();
43  code_ = code();
44  charge_ = charge();
45  if (signalBuckets == 1) {
46  phase_ = -3; rescale_ = 1.46;
47  } else if (signalBuckets == 3) {
48  phase_ = -1; rescale_ = 1.06;
49  } else if (signalBuckets == 4) {
50  phase_ = 0; rescale_ = 1.03;
51  } else {
52  phase_ = -2; rescale_ = 1.14; signalBuckets = 2;
53  }
54  weight_ = weight(binOfMax, signalBuckets, preSamples, numOfBuckets);
55  baseline= codeToQ(bl);
56  bmin_ = binOfMax-3;
57  if (bmin_<0) bmin_ = 0;
58  if (binOfMax>numOfBuckets)
59  bmax_ = numOfBuckets+5;
60  else
61  bmax_ = binOfMax+5;
62 
63  edm::LogInfo("HcalSim") << "HcalQie: initialized with binOfMax " << binOfMax
64  << " sample from " << bmin_ << " to " << bmax_
65  << "; signalBuckets " << signalBuckets
66  << " Baseline/Phase/Scale " << baseline << "/"
67  << phase_ << "/" << rescale_ << "\n"
68  <<" Noise " << sigma
69  << "fC fCToPE " << qToPE << " EDepPerPE "
70  << eDepPerPE;
71 }
72 
74  edm::LogInfo("HcalSim") << "HcalQie:: Deleting Qie";
75 }
76 
77 std::vector<double> HcalQie::shape() {
78 
79  // pulse shape time constants in ns
80  const float ts1 = 8.; // scintillation time constants : 1,2,3
81  const float ts2 = 10.;
82  const float ts3 = 29.3;
83  const float thpd = 4.; // HPD current collection drift time
84  const float tpre = 5.; // preamp time constant
85 
86  const float wd1 = 2.; // relative weights of decay exponents
87  const float wd2 = 0.7;
88  const float wd3 = 1.;
89 
90  // HPD starts at I and rises to 2I in thpd of time
91  double norm=0.0;
92  int j, hpd_siz = (int)(thpd);
93  std::vector<double> hpd_drift(hpd_siz);
94  for (j=0; j<hpd_siz; j++) {
95  double tmp = (double)j + 0.5;
96  hpd_drift[j] = 1.0 + tmp/thpd;
97  norm += hpd_drift[j];
98  }
99  // normalize integrated current to 1.0
100  for (j=0; j<hpd_siz; j++) {
101  hpd_drift[j] /= norm;
102  }
103 
104  // Binkley shape over 6 time constants
105  int preamp_siz=(int)(6*tpre);
106  std::vector<double> preamp(preamp_siz);
107  norm = 0;
108  for (j=0; j<preamp_siz; j++) {
109  double tmp = (double)j + 0.5;
110  preamp[j] = tmp*exp(-(tmp*tmp)/(tpre*tpre));
111  norm += preamp[j];
112  }
113  // normalize pulse area to 1.0
114  for (j=0; j<preamp_siz; j++) {
115  preamp[j] /= norm;
116  }
117 
118  // ignore stochastic variation of photoelectron emission
119  // <...>
120  // effective tile plus wave-length shifter decay time over 4 time constants
121 
122  int tmax = 6 * (int)ts3;
123  std::vector<double> scnt_decay(tmax);
124  norm = 0;
125  for (j=0; j<tmax; j++) {
126  double tmp = (double)j + 0.5;
127  scnt_decay[j] = wd1*exp(-tmp/ts1) + wd2*exp(-tmp/ts2) + wd3*exp(-tmp/ts3);
128  norm += scnt_decay[j];
129  }
130  // normalize pulse area to 1.0
131  for (j=0; j<tmax; j++) {
132  scnt_decay[j] /= norm;
133  }
134 
135  int nsiz = tmax + hpd_siz + preamp_siz + 1;
136  std::vector<double> pulse(nsiz,0.0); // zeroing output pulse shape
137  norm = 0;
138  int i, k;
139  for (i=0; i<tmax; i++) {
140  int t1 = i; // and ignore jitter from optical path length
141  for (j=0; j<hpd_siz; j++) {
142  int t2 = t1 + j;
143  for (k=0; k<preamp_siz; k++) {
144  int t3 = t2 + k;
145  float tmp = scnt_decay[i]*hpd_drift[j]*preamp[k];
146  pulse[t3]+= tmp;
147  norm += tmp;
148  }
149  }
150  }
151 
152  // normalize for 1 GeV pulse height
153  edm::LogInfo("HcalSim") << "HcalQie: Convoluted Shape ============== "
154  << "Normalisation " << norm;
155  for (i=0; i<nsiz; i++) {
156  pulse[i] /= norm;
157 #ifdef DebugLog
158  LogDebug("HcalSim") << "HcalQie: Pulse[" << std::setw(3) << i << "] "
159  << std::setw(8) << pulse[i];
160 #endif
161  }
162 
163  return pulse;
164 }
165 
166 std::vector<int> HcalQie::code() {
167 
168  unsigned int CodeFADCdata[122] = {
169  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
170  10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
171  20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
172  30, 31, 34, 35, 36, 37, 38, 39,
173  40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
174  50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
175  60, 61, 62, 63, 66, 67, 68, 69,
176  70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
177  80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
178  90, 91, 92, 93, 94, 95, 98, 99,
179  100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
180  110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
181  120, 121, 122, 123, 124, 125, 126, 127 };
182 
183  std::vector<int> temp(122);
184  int i;
185  for (i = 0; i < 122; i++)
186  temp[i] = (int)CodeFADCdata[i];
187 
188 #ifdef DebugLog
189  int siz = temp.size();
190  LogDebug("HcalSim") << "HcalQie: Codes in array of size " << siz;
191  for (i=0; i<siz; i++)
192  LogDebug("HcalSim") << "HcalQie: Code[" << std::setw(3) << i << "] "
193  << std::setw(6) << temp[i];
194 #endif
195  return temp;
196 }
197 
198 std::vector<double> HcalQie::charge() {
199 
200  double ChargeFADCdata[122] = {
201  -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5,
202  8.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5, 16.5, 18.5, 20.5,
203  22.5, 24.5, 26.5, 28.5, 31.5, 34.5, 37.5, 40.5, 44.5, 48.5,
204  52.5, 57.5, 62.5, 67.5, 72.5, 77.5, 82.5, 87.5,
205  92.5, 97.5, 102.5, 107.5, 112.5, 117.5, 122.5, 127.5, 132.5, 142.5,
206  152.5, 162.5, 172.5, 182.5, 192.5, 202.5, 217.5, 232.5, 247.5, 262.5,
207  282.5, 302.5, 322.5, 347.5, 372.5, 397.5, 422.5, 447.5,
208  472.5, 497.5, 522.5, 547.5, 572.5, 597.5, 622.5, 647.5, 672.5, 697.5,
209  722.5, 772.5, 822.5, 872.5, 922.5, 972.5, 1022.5, 1072.5, 1147.5, 1222.5,
210  1297.5,1372.5, 1472.5, 1572.5, 1672.5, 1797.5, 1922.5, 2047.5,
211  2172.5,2297.5, 2422.5, 2547.5, 2672.5, 2797.5, 2922.5, 3047.5, 3172.5, 3397.5,
212  3422.5,3547.5, 3672.5, 3922.5, 4172.5, 4422.5, 4672.5, 4922.5, 5172.5, 5422.5,
213  5797.5,6172.5, 6547.5, 6922.5, 7422.5, 7922.5, 8422.5, 9047.5 };
214 
215  std::vector<double> temp(122);
216  int i;
217  for (i = 0; i < 122; i++)
218  temp[i] = (double)(ChargeFADCdata[i]);
219 
220 #ifdef DebugLog
221  int siz = temp.size();
222  LogDebug("HcalSim") << "HcalQie: Charges in array of size " << siz;
223  for (i=0; i<siz; i++)
224  LogDebug("HcalSim") << "HcalQie: Charge[" << std::setw(3) << i << "] "
225  << std::setw(8) << temp[i];
226 #endif
227  return temp;
228 }
229 
230 std::vector<double> HcalQie::weight(int binOfMax, int mode, int npre,
231  int bucket) {
232 
233  std::vector<double> temp(bucket,0);
234  int i;
235  for (i=binOfMax-1; i<binOfMax+mode-1; i++)
236  temp[i] = 1.;
237  if (npre>0) {
238  for (i=0; i<npre; i++) {
239  int j = binOfMax-2-i;
240  temp[j] =-(double)mode/(double)npre;
241  }
242  }
243 
244 #ifdef DebugLog
245  int siz = temp.size();
246  LogDebug("HcalSim") << "HcalQie: Weights in array of size " << siz
247  << " and Npre " << npre;
248  for (i=0; i<siz; i++)
249  LogDebug("HcalSim") << "HcalQie: [Weight[" << i << "] = " << temp[i];
250 #endif
251  return temp;
252 }
253 
254 
255 double HcalQie::codeToQ(int ic) {
256 
257  double tmp=0;
258  for (unsigned int i=0; i<code_.size(); i++) {
259  if (ic == code_[i]) {
260  double delta;
261  if (i == code_.size()-1)
262  delta = charge_[i] - charge_[i-1];
263  else
264  delta = charge_[i+1] - charge_[i];
265  tmp = charge_[i] + 0.5*delta;
266  break;
267  }
268  }
269 
270  return tmp;
271 }
272 
273 
275 
276  int tmp=0;
277  for (unsigned int i=0; i<charge_.size(); i++) {
278  if (charge < charge_[i]) {
279  if (i>0) tmp = code_[i-1];
280  break;
281  }
282  }
283 
284  return tmp;
285 }
286 
287 
288 double HcalQie::getShape(double time) {
289 
290  double tmp = 0;
291  int k = (int) (time + 0.5);
292  if (k>=0 && k<((int)(shape_.size())-1))
293  tmp = 0.5*(shape_[k]+shape_[k+1]);
294 
295  return tmp;
296 }
297 
298 
299 std::vector<int> HcalQie::getCode(int nht, std::vector<CaloHit> hitbuf) {
300 
301  const double bunchSpace=25.;
302  int nmax = (bmax_ > numOfBuckets ? bmax_ : numOfBuckets);
303  std::vector<double> work(nmax);
304 
306  if ( ! rng.isAvailable()) {
307  throw cms::Exception("Configuration")
308  << "HcalQIE requires the RandomNumberGeneratorService\n"
309  << "which is not present in the configuration file. "
310  << "You must add the service\n in the configuration file or "
311  << "remove the modules that require it.";
312  }
313  CLHEP::RandGaussQ randGauss(rng->getEngine(), baseline,sigma);
314  CLHEP::RandPoissonQ randPoisson(rng->getEngine());
315 
316 
317  // Noise in the channel
318  for (int i=0; i<numOfBuckets; i++)
319  work[i] = randGauss.fire();
320 
321 #ifdef DebugLog
322  LogDebug("HcalSim") << "HcalQie::getCode: Noise with baseline " << baseline
323  << " width " << sigma << " and " << nht << " hits";
324  for (int i=0; i<numOfBuckets; i++)
325  LogDebug("HcalSim") << "HcalQie: Code[" << i << "] = " << work[i];
326 #endif
327  double etot=0, esum=0, photons=0;
328  if (nht>0) {
329 
330  // Sort the hits
331  std::vector<CaloHit*> hits(nht);
332  std::vector<CaloHit*>::iterator k1, k2;
333  int kk;
334  for (kk = 0; kk < nht; kk++) {
335  hits[kk] = &hitbuf[kk];
336  }
337  sort(hits.begin(),hits.end(),CaloHitMore());
338 
339  // Energy deposits
340  for (kk = 0, k1 = hits.begin(); k1 != hits.end(); kk++, k1++) {
341  double ehit = (**k1).e();
342  double jitter= (**k1).t();
343  int jump = 0;
344  for (k2 = k1+1; k2 != hits.end() && (jitter-(**k2).t())<1. &&
345  (jitter-(**k2).t())>-1.; k2++) {
346  ehit += (**k2).e();
347  jump++;
348  }
349 
350  double avpe = ehit/eDepPerPE;
351  double photo = randPoisson.fire(avpe);
352  etot += ehit;
353  photons+= photo;
354 #ifdef DebugLog
355  LogDebug("HcalSim") << "HcalQie::getCode: Hit " << kk << ":" << kk+jump
356  << " Energy deposit " << ehit << " Time " << jitter
357  << " Average and true no of PE " << avpe << " "
358  << photo;
359 #endif
360  double bintime = jitter - phase_ - bunchSpace*(binOfMax-bmin_);
361 #ifdef DebugLog
362  LogDebug("HcalSim") << "HcalQie::getCode: phase " << phase_
363  << " binTime " << bintime;
364 #endif
365  std::vector<double> binsum(nmax,0);
366  double norm=0, sum=0.;
367  for (int i=bmin_; i<bmax_; i++) {
368  bintime += bunchSpace;
369  for (int j=0; j<(int)(bunchSpace); j++) {
370  double tim = bintime + j;
371  double tmp = getShape(tim);
372  binsum[i] += tmp;
373  }
374  sum += binsum[i];
375  }
376 
377  if (sum>0) norm = (photo/(sum*qToPE));
378 #ifdef DebugLog
379  LogDebug("HcalSim") << "HcalQie::getCode: PE " << photo << " Sum " << sum
380  << " Norm. " << norm;
381 #endif
382  for (int i=bmin_; i<bmax_; i++)
383  work[i] += binsum[i]*norm;
384 
385  kk += jump;
386  k1 += jump;
387  }
388  }
389 
390  std::vector<int> temp(numOfBuckets,0);
391  for (int i=0; i<numOfBuckets; i++) {
392  temp[i] = getCode(work[i]);
393  esum += work[i];
394  }
395 #ifdef DebugLog
396  LogDebug("HcalSim") << "HcalQie::getCode: Input " << etot << " GeV; Photons "
397  << photons << "; Output " << esum << " fc";
398 #endif
399  return temp;
400 }
401 
402 
403 double HcalQie::getEnergy(std::vector<int> code) {
404 
405  std::vector<double> work(numOfBuckets);
406  double sum=0;
407  for (int i=0; i<numOfBuckets; i++) {
408  work[i] = codeToQ (code[i]);
409  sum += work[i]*weight_[i];
410 #ifdef DebugLog
411  LogDebug("HcalSim") << "HcalQie::getEnergy: " << i << " code " << code[i]
412  << " PE " << work[i];
413 #endif
414  }
415 
416  double tmp;
417  if (preSamples == 0) {
418  tmp = (sum - signalBuckets*baseline) * rescale_ * qToPE * eDepPerPE;
419  } else {
420  tmp = sum * rescale_ * qToPE;
421  }
422 #ifdef DebugLog
423  LogDebug("HcalSim") << "HcalQie::getEnergy: PE " << sum*qToPE << " Energy "
424  << tmp << " GeV";
425 #endif
426  return tmp;
427 }
#define LogDebug(id)
dbl * delta
Definition: mlp_gen.cc:36
T getParameter(std::string const &) const
double getEnergy(std::vector< int >)
Definition: HcalQie.cc:403
int i
Definition: DBlmapReader.cc:9
std::vector< double > shape()
Definition: HcalQie.cc:77
int preSamples
Definition: HcalQie.h:39
virtual ~HcalQie()
Definition: HcalQie.cc:73
double eDepPerPE
Definition: HcalQie.h:41
double codeToQ(int ic)
Definition: HcalQie.cc:255
int bmax_
Definition: HcalQie.h:42
double baseline
Definition: HcalQie.h:41
HcalQie(edm::ParameterSet const &p)
Definition: HcalQie.cc:21
double charge(const std::vector< uint8_t > &Ampls)
int signalBuckets
Definition: HcalQie.h:39
double getShape(double time)
Definition: HcalQie.cc:288
std::vector< double > weight_
Definition: HcalQie.h:40
std::vector< double > charge()
Definition: HcalQie.cc:198
bool isAvailable() const
Definition: Service.h:47
int j
Definition: DBlmapReader.cc:9
double qToPE
Definition: HcalQie.h:41
virtual CLHEP::HepRandomEngine & getEngine() const =0
Use this to get the random number engine, this is the only function most users should call...
int bmin_
Definition: HcalQie.h:42
double rescale_
Definition: HcalQie.h:43
std::vector< double > charge_
Definition: HcalQie.h:38
std::vector< int > getCode(int, std::vector< CaloHit >)
Definition: HcalQie.cc:299
int k[5][pyjets_maxn]
static const double tmax[3]
std::vector< int > code_
Definition: HcalQie.h:37
double phase_
Definition: HcalQie.h:43
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
int binOfMax
Definition: HcalQie.h:39
std::vector< double > shape_
Definition: HcalQie.h:36
double sigma
Definition: HcalQie.h:41
std::vector< double > weight(int binofmax, int mode, int npre, int numbucket)
Definition: HcalQie.cc:230
std::vector< int > code()
Definition: HcalQie.cc:166
int numOfBuckets
Definition: HcalQie.h:39