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