Go to the documentation of this file.00001 #include "SimCalorimetry/HcalSimAlgos/interface/HcalSiPM.h"
00002 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00003 #include "FWCore/ServiceRegistry/interface/Service.h"
00004
00005 #include <cmath>
00006
00007 using std::vector;
00008
00009 HcalSiPM::HcalSiPM(int nCells, double tau) :
00010 theCellCount(nCells), theSiPM(nCells,1.), theTauInv(1.0/tau),
00011 theCrossTalk(0.), theTempDep(0.), theLastHitTime(-1.),
00012 theRndGauss(0), theRndPoisson(0), theRndFlat(0) {
00013
00014 assert(theCellCount>0);
00015 resetSiPM();
00016 }
00017
00018 HcalSiPM::~HcalSiPM() {
00019 delete theRndGauss;
00020 delete theRndPoisson;
00021 delete theRndFlat;
00022 }
00023
00024 int HcalSiPM::hitCells(unsigned int photons, unsigned int integral) const {
00025
00026 if (photons < 1) return 0;
00027 if (integral >= theCellCount) return 0;
00028
00029 if (theRndGauss == 0) {
00030
00031 edm::Service<edm::RandomNumberGenerator> rng;
00032 if ( ! rng.isAvailable()) {
00033 throw cms::Exception("Configuration")
00034 << "HcalSiPM requires the RandomNumberGeneratorService\n"
00035 "which is not present in the configuration file. "
00036 "You must add the service\n"
00037 "in the configuration file or remove the modules that require it.";
00038 }
00039
00040 CLHEP::HepRandomEngine& engine = rng->getEngine();
00041 theRndGauss = new CLHEP::RandGaussQ(engine);
00042 theRndPoisson = new CLHEP::RandPoissonQ(engine);
00043 theRndFlat = new CLHEP::RandFlat(engine);
00044 }
00045
00046
00047 if ((theCrossTalk > 0.) && (theCrossTalk < 1.))
00048 photons += theRndPoisson->fire(photons/(1.-theCrossTalk)-photons);
00049 double x(photons/double(theCellCount));
00050 double prehit(integral/double(theCellCount));
00051
00052
00053 double mean(1. - std::exp(-x));
00054 double width2(std::exp(-x)*(1-(1+x)*std::exp(-x)));
00055
00056
00057 if (mean > 1.) mean = 1.;
00058
00059
00060 mean *= (1-prehit)*theCellCount;
00061 width2 *= (1-prehit)*theCellCount;
00062
00063 double npe;
00064 while (true) {
00065 npe = theRndGauss->fire(mean, std::sqrt(width2 + (mean*prehit)));
00066 if ((npe > -0.5) && (npe <= theCellCount-integral))
00067 return int(npe + 0.5);
00068 }
00069 }
00070
00071 double HcalSiPM::hitCells(unsigned int pes, double tempDiff,
00072 double photonTime) {
00073
00074
00075
00076
00077
00078
00079
00080 if (theRndGauss == 0) {
00081
00082 edm::Service<edm::RandomNumberGenerator> rng;
00083 if ( ! rng.isAvailable()) {
00084 throw cms::Exception("Configuration")
00085 << "HcalSiPM requires the RandomNumberGeneratorService\n"
00086 "which is not present in the configuration file. "
00087 "You must add the service\n"
00088 "in the configuration file or remove the modules that require it.";
00089 }
00090
00091 CLHEP::HepRandomEngine& engine = rng->getEngine();
00092 theRndGauss = new CLHEP::RandGaussQ(engine);
00093 theRndPoisson = new CLHEP::RandPoissonQ(engine);
00094 theRndFlat = new CLHEP::RandFlat(engine);
00095 }
00096
00097 if ((theCrossTalk > 0.) && (theCrossTalk < 1.))
00098 pes += theRndPoisson->fire(pes/(1. - theCrossTalk) - pes);
00099
00100 unsigned int pixel;
00101 double sum(0.), hit(0.);
00102 for (unsigned int pe(0); pe < pes; ++pe) {
00103 pixel = theRndFlat->fireInt(theCellCount);
00104 hit = (theSiPM[pixel] < 0.) ? 1.0 :
00105 (cellCharge(photonTime - theSiPM[pixel]));
00106 sum += hit*(1 + (tempDiff*theTempDep));
00107 theSiPM[pixel] = photonTime;
00108 }
00109
00110 theLastHitTime = photonTime;
00111
00112 return sum;
00113 }
00114
00115 double HcalSiPM::totalCharge(double time) const {
00116
00117
00118 double tot(0.), hit(0.);
00119 for(unsigned int i=0; i<theCellCount; ++i) {
00120 hit = (theSiPM[i] < 0.) ? 1. : cellCharge(time - theSiPM[i]);
00121 tot += hit;
00122 }
00123 return tot;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 void HcalSiPM::setNCells(int nCells) {
00137 assert(nCells>0);
00138 theCellCount = nCells;
00139 theSiPM.resize(nCells);
00140 resetSiPM();
00141 }
00142
00143 void HcalSiPM::setCrossTalk(double xTalk) {
00144
00145
00146 if((xTalk < 0) || (xTalk >= 1)) {
00147 theCrossTalk = 0.;
00148 } else {
00149 theCrossTalk = xTalk;
00150 }
00151
00152 }
00153
00154 void HcalSiPM::setTemperatureDependence(double dTemp) {
00155
00156 theTempDep = dTemp;
00157 }
00158
00159 void HcalSiPM::initRandomEngine(CLHEP::HepRandomEngine& engine) {
00160 if(theRndGauss) delete theRndGauss;
00161 theRndGauss = new CLHEP::RandGaussQ(engine);
00162 if(theRndPoisson) delete theRndPoisson;
00163 theRndPoisson = new CLHEP::RandPoissonQ(engine);
00164 if(theRndFlat) delete theRndFlat;
00165 theRndFlat = new CLHEP::RandFlat(engine);
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 double HcalSiPM::cellCharge(double deltaTime) const {
00181 if (deltaTime <= 0.) return 0.;
00182 if (deltaTime > 10./theTauInv) return 1.;
00183 double result(1. - std::exp(-deltaTime*theTauInv));
00184 return (result > 0.99) ? 1.0 : result;
00185 }