00001
00002
00003
00005
00006 #include "SimG4CMS/Calo/interface/HcalQie.h"
00007
00008 #include "FWCore/ServiceRegistry/interface/Service.h"
00009 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00010 #include "CLHEP/Random/RandGaussQ.h"
00011 #include "CLHEP/Random/RandPoissonQ.h"
00012 #include "FWCore/Utilities/interface/Exception.h"
00013 #include "CLHEP/Units/GlobalPhysicalConstants.h"
00014
00015 #include <iostream>
00016 #include <iomanip>
00017 #include <cmath>
00018
00019
00020
00021 HcalQie::HcalQie(edm::ParameterSet const & p) {
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 edm::ParameterSet m_HQ = p.getParameter<edm::ParameterSet>("HcalQie");
00033 qToPE = m_HQ.getParameter<double>("qToPE");
00034 binOfMax = m_HQ.getParameter<int>("BinOfMax");
00035 signalBuckets = m_HQ.getParameter<int>("SignalBuckets");
00036 preSamples = m_HQ.getParameter<int>("PreSamples");
00037 numOfBuckets = m_HQ.getParameter<int>("NumOfBuckets");
00038 sigma = m_HQ.getParameter<double>("SigmaNoise");
00039 eDepPerPE = m_HQ.getParameter<double>("EDepPerPE");
00040 int bl = m_HQ.getParameter<int>("BaseLine");
00041
00042 shape_ = shape();
00043 code_ = code();
00044 charge_ = charge();
00045 if (signalBuckets == 1) {
00046 phase_ = -3; rescale_ = 1.46;
00047 } else if (signalBuckets == 3) {
00048 phase_ = -1; rescale_ = 1.06;
00049 } else if (signalBuckets == 4) {
00050 phase_ = 0; rescale_ = 1.03;
00051 } else {
00052 phase_ = -2; rescale_ = 1.14; signalBuckets = 2;
00053 }
00054 weight_ = weight(binOfMax, signalBuckets, preSamples, numOfBuckets);
00055 baseline= codeToQ(bl);
00056 bmin_ = binOfMax-3;
00057 if (bmin_<0) bmin_ = 0;
00058 if (binOfMax>numOfBuckets)
00059 bmax_ = numOfBuckets+5;
00060 else
00061 bmax_ = binOfMax+5;
00062
00063 edm::LogInfo("HcalSim") << "HcalQie: initialized with binOfMax " << binOfMax
00064 << " sample from " << bmin_ << " to " << bmax_
00065 << "; signalBuckets " << signalBuckets
00066 << " Baseline/Phase/Scale " << baseline << "/"
00067 << phase_ << "/" << rescale_ << "\n"
00068 <<" Noise " << sigma
00069 << "fC fCToPE " << qToPE << " EDepPerPE "
00070 << eDepPerPE;
00071 }
00072
00073 HcalQie::~HcalQie() {
00074 edm::LogInfo("HcalSim") << "HcalQie:: Deleting Qie";
00075 }
00076
00077 std::vector<double> HcalQie::shape() {
00078
00079
00080 const float ts1 = 8.;
00081 const float ts2 = 10.;
00082 const float ts3 = 29.3;
00083 const float thpd = 4.;
00084 const float tpre = 5.;
00085
00086 const float wd1 = 2.;
00087 const float wd2 = 0.7;
00088 const float wd3 = 1.;
00089
00090
00091 double norm=0.0;
00092 int j, hpd_siz = (int)(thpd);
00093 std::vector<double> hpd_drift(hpd_siz);
00094 for (j=0; j<hpd_siz; j++) {
00095 double tmp = (double)j + 0.5;
00096 hpd_drift[j] = 1.0 + tmp/thpd;
00097 norm += hpd_drift[j];
00098 }
00099
00100 for (j=0; j<hpd_siz; j++) {
00101 hpd_drift[j] /= norm;
00102 }
00103
00104
00105 int preamp_siz=(int)(6*tpre);
00106 std::vector<double> preamp(preamp_siz);
00107 norm = 0;
00108 for (j=0; j<preamp_siz; j++) {
00109 double tmp = (double)j + 0.5;
00110 preamp[j] = tmp*exp(-(tmp*tmp)/(tpre*tpre));
00111 norm += preamp[j];
00112 }
00113
00114 for (j=0; j<preamp_siz; j++) {
00115 preamp[j] /= norm;
00116 }
00117
00118
00119
00120
00121
00122 int tmax = 6 * (int)ts3;
00123 std::vector<double> scnt_decay(tmax);
00124 norm = 0;
00125 for (j=0; j<tmax; j++) {
00126 double tmp = (double)j + 0.5;
00127 scnt_decay[j] = wd1*exp(-tmp/ts1) + wd2*exp(-tmp/ts2) + wd3*exp(-tmp/ts3);
00128 norm += scnt_decay[j];
00129 }
00130
00131 for (j=0; j<tmax; j++) {
00132 scnt_decay[j] /= norm;
00133 }
00134
00135 int nsiz = tmax + hpd_siz + preamp_siz + 1;
00136 std::vector<double> pulse(nsiz,0.0);
00137 norm = 0;
00138 int i, k;
00139 for (i=0; i<tmax; i++) {
00140 int t1 = i;
00141 for (j=0; j<hpd_siz; j++) {
00142 int t2 = t1 + j;
00143 for (k=0; k<preamp_siz; k++) {
00144 int t3 = t2 + k;
00145 float tmp = scnt_decay[i]*hpd_drift[j]*preamp[k];
00146 pulse[t3]+= tmp;
00147 norm += tmp;
00148 }
00149 }
00150 }
00151
00152
00153 edm::LogInfo("HcalSim") << "HcalQie: Convoluted Shape ============== "
00154 << "Normalisation " << norm;
00155 for (i=0; i<nsiz; i++) {
00156 pulse[i] /= norm;
00157 #ifdef DebugLog
00158 LogDebug("HcalSim") << "HcalQie: Pulse[" << std::setw(3) << i << "] "
00159 << std::setw(8) << pulse[i];
00160 #endif
00161 }
00162
00163 return pulse;
00164 }
00165
00166 std::vector<int> HcalQie::code() {
00167
00168 unsigned int CodeFADCdata[122] = {
00169 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
00170 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
00171 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
00172 30, 31, 34, 35, 36, 37, 38, 39,
00173 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
00174 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
00175 60, 61, 62, 63, 66, 67, 68, 69,
00176 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
00177 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
00178 90, 91, 92, 93, 94, 95, 98, 99,
00179 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
00180 110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
00181 120, 121, 122, 123, 124, 125, 126, 127 };
00182
00183 std::vector<int> temp(122);
00184 int i;
00185 for (i = 0; i < 122; i++)
00186 temp[i] = (int)CodeFADCdata[i];
00187
00188 #ifdef DebugLog
00189 int siz = temp.size();
00190 LogDebug("HcalSim") << "HcalQie: Codes in array of size " << siz;
00191 for (i=0; i<siz; i++)
00192 LogDebug("HcalSim") << "HcalQie: Code[" << std::setw(3) << i << "] "
00193 << std::setw(6) << temp[i];
00194 #endif
00195 return temp;
00196 }
00197
00198 std::vector<double> HcalQie::charge() {
00199
00200 double ChargeFADCdata[122] = {
00201 -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5,
00202 8.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5, 16.5, 18.5, 20.5,
00203 22.5, 24.5, 26.5, 28.5, 31.5, 34.5, 37.5, 40.5, 44.5, 48.5,
00204 52.5, 57.5, 62.5, 67.5, 72.5, 77.5, 82.5, 87.5,
00205 92.5, 97.5, 102.5, 107.5, 112.5, 117.5, 122.5, 127.5, 132.5, 142.5,
00206 152.5, 162.5, 172.5, 182.5, 192.5, 202.5, 217.5, 232.5, 247.5, 262.5,
00207 282.5, 302.5, 322.5, 347.5, 372.5, 397.5, 422.5, 447.5,
00208 472.5, 497.5, 522.5, 547.5, 572.5, 597.5, 622.5, 647.5, 672.5, 697.5,
00209 722.5, 772.5, 822.5, 872.5, 922.5, 972.5, 1022.5, 1072.5, 1147.5, 1222.5,
00210 1297.5,1372.5, 1472.5, 1572.5, 1672.5, 1797.5, 1922.5, 2047.5,
00211 2172.5,2297.5, 2422.5, 2547.5, 2672.5, 2797.5, 2922.5, 3047.5, 3172.5, 3397.5,
00212 3422.5,3547.5, 3672.5, 3922.5, 4172.5, 4422.5, 4672.5, 4922.5, 5172.5, 5422.5,
00213 5797.5,6172.5, 6547.5, 6922.5, 7422.5, 7922.5, 8422.5, 9047.5 };
00214
00215 std::vector<double> temp(122);
00216 int i;
00217 for (i = 0; i < 122; i++)
00218 temp[i] = (double)(ChargeFADCdata[i]);
00219
00220 #ifdef DebugLog
00221 int siz = temp.size();
00222 LogDebug("HcalSim") << "HcalQie: Charges in array of size " << siz;
00223 for (i=0; i<siz; i++)
00224 LogDebug("HcalSim") << "HcalQie: Charge[" << std::setw(3) << i << "] "
00225 << std::setw(8) << temp[i];
00226 #endif
00227 return temp;
00228 }
00229
00230 std::vector<double> HcalQie::weight(int binOfMax, int mode, int npre,
00231 int bucket) {
00232
00233 std::vector<double> temp(bucket,0);
00234 int i;
00235 for (i=binOfMax-1; i<binOfMax+mode-1; i++)
00236 temp[i] = 1.;
00237 if (npre>0) {
00238 for (i=0; i<npre; i++) {
00239 int j = binOfMax-2-i;
00240 temp[j] =-(double)mode/(double)npre;
00241 }
00242 }
00243
00244 #ifdef DebugLog
00245 int siz = temp.size();
00246 LogDebug("HcalSim") << "HcalQie: Weights in array of size " << siz
00247 << " and Npre " << npre;
00248 for (i=0; i<siz; i++)
00249 LogDebug("HcalSim") << "HcalQie: [Weight[" << i << "] = " << temp[i];
00250 #endif
00251 return temp;
00252 }
00253
00254
00255 double HcalQie::codeToQ(int ic) {
00256
00257 double tmp=0;
00258 for (unsigned int i=0; i<code_.size(); i++) {
00259 if (ic == code_[i]) {
00260 double delta;
00261 if (i == code_.size()-1)
00262 delta = charge_[i] - charge_[i-1];
00263 else
00264 delta = charge_[i+1] - charge_[i];
00265 tmp = charge_[i] + 0.5*delta;
00266 break;
00267 }
00268 }
00269
00270 return tmp;
00271 }
00272
00273
00274 int HcalQie::getCode(double charge) {
00275
00276 int tmp=0;
00277 for (unsigned int i=0; i<charge_.size(); i++) {
00278 if (charge < charge_[i]) {
00279 if (i>0) tmp = code_[i-1];
00280 break;
00281 }
00282 }
00283
00284 return tmp;
00285 }
00286
00287
00288 double HcalQie::getShape(double time) {
00289
00290 double tmp = 0;
00291 int k = (int) (time + 0.5);
00292 if (k>=0 && k<((int)(shape_.size())-1))
00293 tmp = 0.5*(shape_[k]+shape_[k+1]);
00294
00295 return tmp;
00296 }
00297
00298
00299 std::vector<int> HcalQie::getCode(int nht, std::vector<CaloHit> hitbuf) {
00300
00301 const double bunchSpace=25.;
00302 int nmax = (bmax_ > numOfBuckets ? bmax_ : numOfBuckets);
00303 std::vector<double> work(nmax);
00304
00305 edm::Service<edm::RandomNumberGenerator> rng;
00306 if ( ! rng.isAvailable()) {
00307 throw cms::Exception("Configuration")
00308 << "HcalQIE requires the RandomNumberGeneratorService\n"
00309 << "which is not present in the configuration file. "
00310 << "You must add the service\n in the configuration file or "
00311 << "remove the modules that require it.";
00312 }
00313 CLHEP::RandGaussQ randGauss(rng->getEngine(), baseline,sigma);
00314 CLHEP::RandPoissonQ randPoisson(rng->getEngine());
00315
00316
00317
00318 for (int i=0; i<numOfBuckets; i++)
00319 work[i] = randGauss.fire();
00320
00321 #ifdef DebugLog
00322 LogDebug("HcalSim") << "HcalQie::getCode: Noise with baseline " << baseline
00323 << " width " << sigma << " and " << nht << " hits";
00324 for (int i=0; i<numOfBuckets; i++)
00325 LogDebug("HcalSim") << "HcalQie: Code[" << i << "] = " << work[i];
00326 #endif
00327 double etot=0, esum=0, photons=0;
00328 if (nht>0) {
00329
00330
00331 std::vector<CaloHit*> hits(nht);
00332 std::vector<CaloHit*>::iterator k1, k2;
00333 int kk;
00334 for (kk = 0; kk < nht; kk++) {
00335 hits[kk] = &hitbuf[kk];
00336 }
00337 sort(hits.begin(),hits.end(),CaloHitMore());
00338
00339
00340 for (kk = 0, k1 = hits.begin(); k1 != hits.end(); kk++, k1++) {
00341 double ehit = (**k1).e();
00342 double jitter= (**k1).t();
00343 int jump = 0;
00344 for (k2 = k1+1; k2 != hits.end() && (jitter-(**k2).t())<1. &&
00345 (jitter-(**k2).t())>-1.; k2++) {
00346 ehit += (**k2).e();
00347 jump++;
00348 }
00349
00350 double avpe = ehit/eDepPerPE;
00351 double photo = randPoisson.fire(avpe);
00352 etot += ehit;
00353 photons+= photo;
00354 #ifdef DebugLog
00355 LogDebug("HcalSim") << "HcalQie::getCode: Hit " << kk << ":" << kk+jump
00356 << " Energy deposit " << ehit << " Time " << jitter
00357 << " Average and true no of PE " << avpe << " "
00358 << photo;
00359 #endif
00360 double bintime = jitter - phase_ - bunchSpace*(binOfMax-bmin_);
00361 #ifdef DebugLog
00362 LogDebug("HcalSim") << "HcalQie::getCode: phase " << phase_
00363 << " binTime " << bintime;
00364 #endif
00365 std::vector<double> binsum(nmax,0);
00366 double norm=0, sum=0.;
00367 for (int i=bmin_; i<bmax_; i++) {
00368 bintime += bunchSpace;
00369 for (int j=0; j<(int)(bunchSpace); j++) {
00370 double tim = bintime + j;
00371 double tmp = getShape(tim);
00372 binsum[i] += tmp;
00373 }
00374 sum += binsum[i];
00375 }
00376
00377 if (sum>0) norm = (photo/(sum*qToPE));
00378 #ifdef DebugLog
00379 LogDebug("HcalSim") << "HcalQie::getCode: PE " << photo << " Sum " << sum
00380 << " Norm. " << norm;
00381 #endif
00382 for (int i=bmin_; i<bmax_; i++)
00383 work[i] += binsum[i]*norm;
00384
00385 kk += jump;
00386 k1 += jump;
00387 }
00388 }
00389
00390 std::vector<int> temp(numOfBuckets,0);
00391 for (int i=0; i<numOfBuckets; i++) {
00392 temp[i] = getCode(work[i]);
00393 esum += work[i];
00394 }
00395 #ifdef DebugLog
00396 LogDebug("HcalSim") << "HcalQie::getCode: Input " << etot << " GeV; Photons "
00397 << photons << "; Output " << esum << " fc";
00398 #endif
00399 return temp;
00400 }
00401
00402
00403 double HcalQie::getEnergy(std::vector<int> code) {
00404
00405 std::vector<double> work(numOfBuckets);
00406 double sum=0;
00407 for (int i=0; i<numOfBuckets; i++) {
00408 work[i] = codeToQ (code[i]);
00409 sum += work[i]*weight_[i];
00410 #ifdef DebugLog
00411 LogDebug("HcalSim") << "HcalQie::getEnergy: " << i << " code " << code[i]
00412 << " PE " << work[i];
00413 #endif
00414 }
00415
00416 double tmp;
00417 if (preSamples == 0) {
00418 tmp = (sum - signalBuckets*baseline) * rescale_ * qToPE * eDepPerPE;
00419 } else {
00420 tmp = sum * rescale_ * qToPE;
00421 }
00422 #ifdef DebugLog
00423 LogDebug("HcalSim") << "HcalQie::getEnergy: PE " << sum*qToPE << " Energy "
00424 << tmp << " GeV";
00425 #endif
00426 return tmp;
00427 }