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.
2 
3 #include "CLHEP/Random/RandGaussQ.h"
4 #include "CLHEP/Random/RandPoissonQ.h"
5 #include "CLHEP/Random/RandFlat.h"
6 
7 #include <cmath>
8 
9 using std::vector;
10 //345678911234567892123456789312345678941234567895123456789612345678971234567898
11 HcalSiPM::HcalSiPM(int nCells, double tau) :
12  theCellCount(nCells), theSiPM(nCells,1.), theTauInv(1.0/tau),
13  theCrossTalk(0.), theTempDep(0.), theLastHitTime(-1.) {
14 
15  assert(theCellCount>0);
16  resetSiPM();
17 }
18 
20 }
21 
22 int HcalSiPM::hitCells(CLHEP::HepRandomEngine* engine, unsigned int photons, unsigned int integral) const {
23  //don't need to do zero or negative photons.
24  if (photons < 1) return 0;
25  if (integral >= theCellCount) return 0;
26 
27  //normalize by theCellCount to remove dependency on SiPM size and pixel density.
28  if ((theCrossTalk > 0.) && (theCrossTalk < 1.)) {
29  CLHEP::RandPoissonQ randPoissonQ(*engine, photons/(1.-theCrossTalk)-photons);
30  photons += randPoissonQ.fire();
31  }
32  double x(photons/double(theCellCount));
33  double prehit(integral/double(theCellCount));
34 
35  //calculate the width and mean of the distribution for a given x
36  double mean(1. - std::exp(-x));
37  double width2(std::exp(-x)*(1-(1+x)*std::exp(-x)));
38 
39  //you can't hit more than everything.
40  if (mean > 1.) mean = 1.;
41 
42  //convert back to absolute pixels
43  mean *= (1-prehit)*theCellCount;
44  width2 *= (1-prehit)*theCellCount;
45 
46  double npe;
47  while (true) {
48  npe = CLHEP::RandGaussQ::shoot(engine, mean, std::sqrt(width2 + (mean*prehit)));
49  if ((npe > -0.5) && (npe <= theCellCount-integral))
50  return int(npe + 0.5);
51  }
52 }
53 
54 double HcalSiPM::hitCells(CLHEP::HepRandomEngine* engine, unsigned int pes, double tempDiff,
55  double photonTime) {
56  // response to light impulse with pes input photons. The return is the number
57  // of micro-pixels hit. If a fraction other than 0. is supplied then the
58  // micro-pixel doesn't fully discharge. The tempDiff is the temperature
59  // difference from nominal and is used to modify the relative strength of a
60  // hit pixel. Pixels which are fractionally charged return a fractional
61  // number of hit pixels.
62 
63  if ((theCrossTalk > 0.) && (theCrossTalk < 1.)) {
64  CLHEP::RandPoissonQ randPoissonQ(*engine, pes/(1. - theCrossTalk) - pes);
65  pes += randPoissonQ.fire();
66  }
67 
68  unsigned int pixel;
69  double sum(0.), hit(0.);
70  for (unsigned int pe(0); pe < pes; ++pe) {
71  pixel = CLHEP::RandFlat::shootInt(engine, theCellCount);
72  hit = (theSiPM[pixel] < 0.) ? 1.0 :
73  (cellCharge(photonTime - theSiPM[pixel]));
74  sum += hit*(1 + (tempDiff*theTempDep));
75  theSiPM[pixel] = photonTime;
76  }
77 
78  theLastHitTime = photonTime;
79 
80  return sum;
81 }
82 
83 double HcalSiPM::totalCharge(double time) const {
84  // sum of the micro-pixels. NP is a fully charged device.
85  // 0 is a fullly depleted device.
86  double tot(0.), hit(0.);
87  for(unsigned int i=0; i<theCellCount; ++i) {
88  hit = (theSiPM[i] < 0.) ? 1. : cellCharge(time - theSiPM[i]);
89  tot += hit;
90  }
91  return tot;
92 }
93 
94 // void HcalSiPM::recoverForTime(double time, double dt) {
95 // // apply the RC recover model to the pixels for time. If dt is not
96 // // positive then tau/5 will be used for dt.
97 // if (dt <= 0.)
98 // dt = 1.0/(theTauInv*5.);
99 // for (double t = 0; t < time; t += dt) {
100 // expRecover(dt);
101 // }
102 // }
103 
104 void HcalSiPM::setNCells(int nCells) {
105  assert(nCells>0);
106  theCellCount = nCells;
107  theSiPM.resize(nCells);
108  resetSiPM();
109 }
110 
111 void HcalSiPM::setCrossTalk(double xTalk) {
112  // set the cross-talk probability
113 
114  if((xTalk < 0) || (xTalk >= 1)) {
115  theCrossTalk = 0.;
116  } else {
117  theCrossTalk = xTalk;
118  }
119 
120 }
121 
123  // set the temperature dependence
124  theTempDep = dTemp;
125 }
126 
127 // void HcalSiPM::expRecover(double dt) {
128 // // recover each micro-pixel using the RC model. For this to work well.
129 // // dt << tau (typically dt = 0.2*tau or less)
130 // double newval;
131 
132 // for (unsigned int i=0; i<theCellCount; ++i) {
133 // if (theSiPM[i] < 0.999) {
134 // newval = theSiPM[i] + (1 - theSiPM[i])*dt*theTauInv;
135 // theSiPM[i] = (newval > 0.99) ? 1.0 : newval;
136 // }
137 // }
138 
139 double HcalSiPM::cellCharge(double deltaTime) const {
140  if (deltaTime <= 0.) return 0.;
141  if (deltaTime > 10./theTauInv) return 1.;
142  double result(1. - std::exp(-deltaTime*theTauInv));
143  return (result > 0.99) ? 1.0 : result;
144 }
int i
Definition: DBlmapReader.cc:9
double theTempDep
Definition: HcalSiPM.h:56
virtual ~HcalSiPM()
Definition: HcalSiPM.cc:19
double cellCharge(double deltaTime) const
Definition: HcalSiPM.cc:139
virtual double totalCharge() const
Definition: HcalSiPM.h:32
double theTauInv
Definition: HcalSiPM.h:54
void resetSiPM()
Definition: HcalSiPM.h:26
double theCrossTalk
Definition: HcalSiPM.h:55
std::vector< double > theSiPM
Definition: HcalSiPM.h:53
T sqrt(T t)
Definition: SSEVec.h:48
void setNCells(int nCells)
Definition: HcalSiPM.cc:104
tuple result
Definition: query.py:137
double theLastHitTime
Definition: HcalSiPM.h:57
void setCrossTalk(double xtalk)
Definition: HcalSiPM.cc:111
Integral< F, X >::type integral(const F &f)
Definition: Integral.h:69
virtual int hitCells(CLHEP::HepRandomEngine *, unsigned int photons, unsigned int integral=0) const
Definition: HcalSiPM.cc:22
unsigned int theCellCount
Definition: HcalSiPM.h:52
Definition: DDAxes.h:10
HcalSiPM(int nCells=1, double tau=15.)
Definition: HcalSiPM.cc:11
void setTemperatureDependence(double tempDep)
Definition: HcalSiPM.cc:122