CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
HcalSiPM.cc
Go to the documentation of this file.
4 
5 #include <cmath>
6 
7 using std::vector;
8 //345678911234567892123456789312345678941234567895123456789612345678971234567898
9 HcalSiPM::HcalSiPM(int nCells, double tau) :
10  theCellCount(nCells), theSiPM(nCells,1.), theTauInv(1.0/tau),
11  theCrossTalk(0.), theTempDep(0.), theLastHitTime(-1.),
12  theRndGauss(0), theRndPoisson(0), theRndFlat(0) {
13 
14  assert(theCellCount>0);
15  resetSiPM();
16 }
17 
19  delete theRndGauss;
20  delete theRndPoisson;
21  delete theRndFlat;
22 }
23 
24 int HcalSiPM::hitCells(unsigned int photons, unsigned int integral) const {
25  //don't need to do zero or negative photons.
26  if (photons < 1) return 0;
27  if (integral >= theCellCount) return 0;
28 
29  if (theRndGauss == 0) {
30  //random number generator setup
32  if ( ! rng.isAvailable()) {
33  throw cms::Exception("Configuration")
34  << "HcalSiPM requires the RandomNumberGeneratorService\n"
35  "which is not present in the configuration file. "
36  "You must add the service\n"
37  "in the configuration file or remove the modules that require it.";
38  }
39 
40  CLHEP::HepRandomEngine& engine = rng->getEngine();
41  theRndGauss = new CLHEP::RandGaussQ(engine);
42  theRndPoisson = new CLHEP::RandPoissonQ(engine);
43  theRndFlat = new CLHEP::RandFlat(engine);
44  }
45 
46  //normalize by theCellCount to remove dependency on SiPM size and pixel density.
47  if ((theCrossTalk > 0.) && (theCrossTalk < 1.))
48  photons += theRndPoisson->fire(photons/(1.-theCrossTalk)-photons);
49  double x(photons/double(theCellCount));
50  double prehit(integral/double(theCellCount));
51 
52  //calculate the width and mean of the distribution for a given x
53  double mean(1. - std::exp(-x));
54  double width2(std::exp(-x)*(1-(1+x)*std::exp(-x)));
55 
56  //you can't hit more than everything.
57  if (mean > 1.) mean = 1.;
58 
59  //convert back to absolute pixels
60  mean *= (1-prehit)*theCellCount;
61  width2 *= (1-prehit)*theCellCount;
62 
63  double npe;
64  while (true) {
65  npe = theRndGauss->fire(mean, std::sqrt(width2 + (mean*prehit)));
66  if ((npe > -0.5) && (npe <= theCellCount-integral))
67  return int(npe + 0.5);
68  }
69 }
70 
71 double HcalSiPM::hitCells(unsigned int pes, double tempDiff,
72  double photonTime) {
73  // response to light impulse with pes input photons. The return is the number
74  // of micro-pixels hit. If a fraction other than 0. is supplied then the
75  // micro-pixel doesn't fully discharge. The tempDiff is the temperature
76  // difference from nominal and is used to modify the relative strength of a
77  // hit pixel. Pixels which are fractionally charged return a fractional
78  // number of hit pixels.
79 
80  if (theRndGauss == 0) {
81  //random number generator setup
83  if ( ! rng.isAvailable()) {
84  throw cms::Exception("Configuration")
85  << "HcalSiPM requires the RandomNumberGeneratorService\n"
86  "which is not present in the configuration file. "
87  "You must add the service\n"
88  "in the configuration file or remove the modules that require it.";
89  }
90 
91  CLHEP::HepRandomEngine& engine = rng->getEngine();
92  theRndGauss = new CLHEP::RandGaussQ(engine);
93  theRndPoisson = new CLHEP::RandPoissonQ(engine);
94  theRndFlat = new CLHEP::RandFlat(engine);
95  }
96 
97  if ((theCrossTalk > 0.) && (theCrossTalk < 1.))
98  pes += theRndPoisson->fire(pes/(1. - theCrossTalk) - pes);
99 
100  unsigned int pixel;
101  double sum(0.), hit(0.);
102  for (unsigned int pe(0); pe < pes; ++pe) {
103  pixel = theRndFlat->fireInt(theCellCount);
104  hit = (theSiPM[pixel] < 0.) ? 1.0 :
105  (cellCharge(photonTime - theSiPM[pixel]));
106  sum += hit*(1 + (tempDiff*theTempDep));
107  theSiPM[pixel] = photonTime;
108  }
109 
110  theLastHitTime = photonTime;
111 
112  return sum;
113 }
114 
115 double HcalSiPM::totalCharge(double time) const {
116  // sum of the micro-pixels. NP is a fully charged device.
117  // 0 is a fullly depleted device.
118  double tot(0.), hit(0.);
119  for(unsigned int i=0; i<theCellCount; ++i) {
120  hit = (theSiPM[i] < 0.) ? 1. : cellCharge(time - theSiPM[i]);
121  tot += hit;
122  }
123  return tot;
124 }
125 
126 // void HcalSiPM::recoverForTime(double time, double dt) {
127 // // apply the RC recover model to the pixels for time. If dt is not
128 // // positive then tau/5 will be used for dt.
129 // if (dt <= 0.)
130 // dt = 1.0/(theTauInv*5.);
131 // for (double t = 0; t < time; t += dt) {
132 // expRecover(dt);
133 // }
134 // }
135 
136 void HcalSiPM::setNCells(int nCells) {
137  assert(nCells>0);
138  theCellCount = nCells;
139  theSiPM.resize(nCells);
140  resetSiPM();
141 }
142 
143 void HcalSiPM::setCrossTalk(double xTalk) {
144  // set the cross-talk probability
145 
146  if((xTalk < 0) || (xTalk >= 1)) {
147  theCrossTalk = 0.;
148  } else {
149  theCrossTalk = xTalk;
150  }
151 
152 }
153 
155  // set the temperature dependence
156  theTempDep = dTemp;
157 }
158 
159 void HcalSiPM::initRandomEngine(CLHEP::HepRandomEngine& engine) {
160  if(theRndGauss) delete theRndGauss;
161  theRndGauss = new CLHEP::RandGaussQ(engine);
162  if(theRndPoisson) delete theRndPoisson;
163  theRndPoisson = new CLHEP::RandPoissonQ(engine);
164  if(theRndFlat) delete theRndFlat;
165  theRndFlat = new CLHEP::RandFlat(engine);
166 }
167 
168 // void HcalSiPM::expRecover(double dt) {
169 // // recover each micro-pixel using the RC model. For this to work well.
170 // // dt << tau (typically dt = 0.2*tau or less)
171 // double newval;
172 
173 // for (unsigned int i=0; i<theCellCount; ++i) {
174 // if (theSiPM[i] < 0.999) {
175 // newval = theSiPM[i] + (1 - theSiPM[i])*dt*theTauInv;
176 // theSiPM[i] = (newval > 0.99) ? 1.0 : newval;
177 // }
178 // }
179 
180 double HcalSiPM::cellCharge(double deltaTime) const {
181  if (deltaTime <= 0.) return 0.;
182  if (deltaTime > 10./theTauInv) return 1.;
183  double result(1. - std::exp(-deltaTime*theTauInv));
184  return (result > 0.99) ? 1.0 : result;
185 }
int i
Definition: DBlmapReader.cc:9
double theTempDep
Definition: HcalSiPM.h:59
virtual ~HcalSiPM()
Definition: HcalSiPM.cc:18
double cellCharge(double deltaTime) const
Definition: HcalSiPM.cc:180
virtual double totalCharge() const
Definition: HcalSiPM.h:32
double theTauInv
Definition: HcalSiPM.h:57
void resetSiPM()
Definition: HcalSiPM.h:26
CLHEP::RandGaussQ * theRndGauss
Definition: HcalSiPM.h:62
double theCrossTalk
Definition: HcalSiPM.h:58
std::vector< double > theSiPM
Definition: HcalSiPM.h:56
T sqrt(T t)
Definition: SSEVec.h:48
void setNCells(int nCells)
Definition: HcalSiPM.cc:136
tuple result
Definition: query.py:137
bool isAvailable() const
Definition: Service.h:46
double theLastHitTime
Definition: HcalSiPM.h:60
void setCrossTalk(double xtalk)
Definition: HcalSiPM.cc:143
void initRandomEngine(CLHEP::HepRandomEngine &engine)
Definition: HcalSiPM.cc:159
virtual CLHEP::HepRandomEngine & getEngine() const =0
Use this to get the random number engine, this is the only function most users should call...
Integral< F, X >::type integral(const F &f)
Definition: Integral.h:69
CLHEP::RandFlat * theRndFlat
Definition: HcalSiPM.h:64
CLHEP::RandPoissonQ * theRndPoisson
Definition: HcalSiPM.h:63
virtual int hitCells(unsigned int photons, unsigned int integral=0) const
Definition: HcalSiPM.cc:24
unsigned int theCellCount
Definition: HcalSiPM.h:55
Definition: DDAxes.h:10
HcalSiPM(int nCells=1, double tau=15.)
Definition: HcalSiPM.cc:9
void setTemperatureDependence(double tempDep)
Definition: HcalSiPM.cc:154