CMS 3D CMS Logo

HcalSiPMHitResponse.cc
Go to the documentation of this file.
13 
14 #include "CLHEP/Random/RandPoissonQ.h"
15 
16 #include <math.h>
17 #include <list>
18 
20  const CaloShapes * shapes, bool PreMix1, bool HighFidelity) :
21  CaloHitResponse(parameterMap, shapes), theSiPM(), PreMixDigis(PreMix1), HighFidelityPreMix(HighFidelity),
22  nbins((PreMixDigis and HighFidelityPreMix) ? 1 : BUNCHSPACE*HcalPulseShapes::invDeltaTSiPM_),
23  dt(HcalPulseShapes::deltaTSiPM_), invdt(HcalPulseShapes::invDeltaTSiPM_)
24 {
25  //fill shape map
29 }
30 
32 
34  precisionTimedPhotons.clear();
35 }
36 
39  int readoutFrameSize = parameters.readoutFrameSize();
41  //preserve fidelity of time info
42  readoutFrameSize *= BUNCHSPACE*HcalPulseShapes::invDeltaTSiPM_;
43  }
44  return readoutFrameSize;
45 }
46 
47 void HcalSiPMHitResponse::finalizeHits(CLHEP::HepRandomEngine* engine) {
48  //do not add PE noise for initial premix
49  if(!PreMixDigis) addPEnoise(engine);
50 
51  photonTimeMap::iterator channelPhotons;
52  for (channelPhotons = precisionTimedPhotons.begin();
53  channelPhotons != precisionTimedPhotons.end();
54  ++channelPhotons) {
55  CaloSamples signal(makeSiPMSignal(channelPhotons->first,
56  channelPhotons->second,
57  engine));
58  bool keep( keepBlank() );
59  if (!keep) {
60  const unsigned int size ( signal.size() ) ;
61  if( 0 != size ) {
62  for( unsigned int i ( 0 ) ; i != size ; ++i ) {
63  keep = keep || signal[i] > 1.e-7 ;
64  }
65  }
66  }
67 
68  LogDebug("HcalSiPMHitResponse") << HcalDetId(signal.id()) << ' ' << signal;
69 
70  if (keep) CaloHitResponse::add(signal);
71  }
72 }
73 
74 //used for premixing - premixed CaloSamples have fine time binning
76  if(!HighFidelityPreMix){
77  CaloHitResponse::add(signal);
78  return;
79  }
80  DetId id(signal.id());
81  int photonTimeHistSize = nbins * getReadoutFrameSize(id);
82  assert(photonTimeHistSize == signal.size());
83  if (precisionTimedPhotons.find(id)==precisionTimedPhotons.end()) {
84  precisionTimedPhotons.insert(
85  std::pair<DetId, photonTimeHist >(id, photonTimeHist(photonTimeHistSize, 0)
86  )
87  );
88  }
89  for(int i = 0; i < signal.size(); ++i){
90  unsigned int photons(signal[i] + 0.5);
92  }
93 }
94 
95 void HcalSiPMHitResponse::add(const PCaloHit& hit, CLHEP::HepRandomEngine* engine) {
96  if (!edm::isNotFinite(hit.time()) &&
97  ((theHitFilter == 0) || (theHitFilter->accepts(hit)))) {
98  HcalDetId id(hit.id());
99  const HcalSimParameters& pars = dynamic_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
100  //divide out mean of crosstalk distribution 1/(1-lambda) = multiply by (1-lambda)
101  double signal(analogSignalAmplitude(id, hit.energy(), pars, engine)*(1-pars.sipmCrossTalk(id)));
102  unsigned int photons(signal + 0.5);
103  double tof( timeOfFlight(id) );
104  double time( hit.time() );
105  if(ignoreTime) time = tof;
106 
107  if (photons > 0)
108  if (precisionTimedPhotons.find(id)==precisionTimedPhotons.end()) {
109  precisionTimedPhotons.insert(
110  std::pair<DetId, photonTimeHist >(id,
112  )
113  );
114  }
115 
116  LogDebug("HcalSiPMHitResponse") << id;
117  LogDebug("HcalSiPMHitResponse") << " fCtoGeV: " << pars.fCtoGeV(id)
118  << " samplingFactor: " << pars.samplingFactor(id)
119  << " photoelectronsToAnalog: " << pars.photoelectronsToAnalog(id)
120  << " simHitToPhotoelectrons: " << pars.simHitToPhotoelectrons(id);
121  LogDebug("HcalSiPMHitResponse") << " energy: " << hit.energy()
122  << " photons: " << photons
123  << " time: " << time;
124  LogDebug("HcalSiPMHitResponse") << " timePhase: " << pars.timePhase()
125  << " tof: " << tof
126  << " binOfMaximum: " << pars.binOfMaximum()
127  << " phaseShift: " << thePhaseShift_;
128  double tzero(0.0 + pars.timePhase() -
129  (time - tof) -
130  BUNCHSPACE*( pars.binOfMaximum() - thePhaseShift_));
131  LogDebug("HcalSiPMHitResponse") << " tzero: " << tzero;
132  double tzero_bin(-tzero*invdt);
133  LogDebug("HcalSiPMHitResponse") << " corrected tzero: " << tzero_bin << '\n';
134  double t_pe(0.);
135  int t_bin(0);
136  for (unsigned int pe(0); pe<photons; ++pe) {
138  t_bin = int(t_pe*invdt + tzero_bin + 0.5);
139  LogDebug("HcalSiPMHitResponse") << "t_pe: " << t_pe << " t_pe + tzero: " << (t_pe+tzero_bin*dt)
140  << " t_bin: " << t_bin << '\n';
141  if ((t_bin >= 0) &&
142  (static_cast<unsigned int>(t_bin) < precisionTimedPhotons[id].size()))
143  precisionTimedPhotons[id][t_bin] += 1;
144  }
145  }
146 }
147 
148 void HcalSiPMHitResponse::addPEnoise(CLHEP::HepRandomEngine* engine)
149 {
150  // Add SiPM dark current noise to all cells
151  for(std::vector<DetId>::const_iterator idItr = theDetIds->begin();
152  idItr != theDetIds->end(); ++idItr) {
153  HcalDetId id(*idItr);
154  const HcalSimParameters& pars =
155  static_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
156 
157  // uA * ns / (fC/pe) = pe!
158  double dc_pe_avg =
159  pars.sipmDarkCurrentuA(id) * dt /
160  pars.photoelectronsToAnalog(id);
161 
162  if (dc_pe_avg <= 0.) continue;
163 
164  int nPreciseBins = nbins * getReadoutFrameSize(id);
165 
166  unsigned int sumnoisePE(0);
167  double elapsedTime(0.);
168  for (int tprecise(0); tprecise < nPreciseBins; ++tprecise) {
169  int noisepe = CLHEP::RandPoissonQ::shoot(engine, dc_pe_avg); // add dark current noise
170 
171  if (noisepe > 0) {
172  if (precisionTimedPhotons.find(id)==precisionTimedPhotons.end()) {
173  photonTimeHist photons(nPreciseBins, 0);
174  photons[tprecise] = noisepe;
175  precisionTimedPhotons.insert
176  (std::pair<DetId, photonTimeHist >(id, photons ) );
177  } else {
178  precisionTimedPhotons[id][tprecise] += noisepe;
179  }
180 
181  sumnoisePE += noisepe;
182  }
183  elapsedTime += dt;
184 
185  } // precise time loop
186 
187  LogDebug("HcalSiPMHitResponse") << id;
188  LogDebug("HcalSiPMHitResponse") << " total noise (PEs): " << sumnoisePE;
189 
190  } // detId loop
191 } // HcalSiPMHitResponse::addPEnoise()
192 
196  int preciseSize(readoutFrameSize * nbins);
197  CaloSamples result(detId, readoutFrameSize, preciseSize);
198  result.setPresamples(parameters.binOfMaximum()-1);
199  result.setPrecise(result.presamples() * nbins, dt);
200  return result;
201 }
202 
204  photonTimeHist const& photonTimeBins,
205  CLHEP::HepRandomEngine* engine) {
206  const HcalSimParameters& pars = static_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
207  theSiPM.setNCells(pars.pixels(id));
208  theSiPM.setTau(pars.sipmTau());
211 
212  //use to make signal
213  CaloSamples signal( makeBlankSignal(id) );
214  int sampleBin(0), preciseBin(0);
215  signal.resetPrecise();
216  unsigned int pe(0);
217  double hitPixels(0.), elapsedTime(0.);
218  unsigned int sumPE(0);
219  double sumHits(0.);
220 
221  auto& sipmPulseShape(shapeMap[pars.signalShape(id)]);
222 
223  std::list< std::pair<double, double> > pulses;
224  std::list< std::pair<double, double> >::iterator pulse;
225  double timeDiff, pulseBit;
226  LogDebug("HcalSiPMHitResponse") << "makeSiPMSignal for " << HcalDetId(id);
227 
228  for (unsigned int tbin(0); tbin < photonTimeBins.size(); ++tbin) {
229  pe = photonTimeBins[tbin];
230  sumPE += pe;
231  preciseBin = tbin;
232  sampleBin = preciseBin/nbins;
233  if (pe > 0) {
234  //skip saturation/recovery and pulse smearing for premix stage 1
236  signal[sampleBin] += pe;
237  signal.preciseAtMod(preciseBin) += pe;
238  elapsedTime += dt;
239  continue;
240  }
241 
242  hitPixels = theSiPM.hitCells(engine, pe, 0., elapsedTime);
243  sumHits += hitPixels;
244  LogDebug("HcalSiPMHitResponse") << " elapsedTime: " << elapsedTime
245  << " sampleBin: " << sampleBin
246  << " preciseBin: " << preciseBin
247  << " pe: " << pe
248  << " hitPixels: " << hitPixels ;
249  if (pars.doSiPMSmearing()) {
250  pulses.push_back( std::pair<double, double>(elapsedTime, hitPixels) );
251  } else {
252  signal[sampleBin] += hitPixels;
253  hitPixels *= invdt;
254  signal.preciseAtMod(preciseBin) += 0.6*hitPixels;
255  if (preciseBin > 0)
256  signal.preciseAtMod(preciseBin-1) += 0.2*hitPixels;
257  if (preciseBin < signal.preciseSize() -1)
258  signal.preciseAtMod(preciseBin+1) += 0.2*hitPixels;
259  }
260  }
261 
262  if (pars.doSiPMSmearing()) {
263  pulse = pulses.begin();
264  while (pulse != pulses.end()) {
265  timeDiff = elapsedTime - pulse->first;
266  pulseBit = sipmPulseShape(timeDiff)*pulse->second;
267  LogDebug("HcalSiPMHitResponse") << " pulse t: " << pulse->first
268  << " pulse A: " << pulse->second
269  << " timeDiff: " << timeDiff
270  << " pulseBit: " << pulseBit;
271  signal[sampleBin] += pulseBit;
272  signal.preciseAtMod(preciseBin) += pulseBit*invdt;
273 
274  if (timeDiff > 1 && sipmPulseShape(timeDiff) < 1e-7)
275  pulse = pulses.erase(pulse);
276  else
277  ++pulse;
278  }
279  }
280  elapsedTime += dt;
281  }
282 
283  return signal;
284 }
285 
286 void HcalSiPMHitResponse::setDetIds(const std::vector<DetId> & detIds) {
287  theDetIds = &detIds;
288 }
#define LogDebug(id)
std::vector< float > sipmNonlinearity(const DetId &detId) const
size
Write out results.
double sipmTau() const
float dt
Definition: AMPTWrapper.h:126
double time() const
Definition: PCaloHit.h:36
const std::vector< DetId > * theDetIds
virtual void finalizeHits(CLHEP::HepRandomEngine *) override
Finalize hits.
void setSaturationPars(const std::vector< float > &pars)
Definition: HcalSiPM.cc:190
virtual double photoelectronsToAnalog(const DetId &detId) const
double energy() const
Definition: PCaloHit.h:29
int presamples() const
access presample information
Definition: CaloSamples.h:36
virtual bool keepBlank() const
void resetPrecise()
Definition: CaloSamples.cc:27
int pixels(const DetId &detId) const
int preciseSize() const
get the size
Definition: CaloSamples.h:62
Main class for Parameters in different subdetectors.
virtual void addPEnoise(CLHEP::HepRandomEngine *engine)
const int keep
virtual bool accepts(const PCaloHit &hit) const =0
bool isNotFinite(T x)
Definition: isFinite.h:10
Creates electronics signals from hits.
virtual double hitCells(CLHEP::HepRandomEngine *, unsigned int pes, double tempDiff=0., double photonTime=0.)
Definition: HcalSiPM.cc:101
unsigned int signalShape(const DetId &detId) const
virtual const CaloSimParameters & simParameters(const DetId &id) const =0
void setNCells(int nCells)
Definition: HcalSiPM.cc:145
void setTau(double tau)
Definition: HcalSiPM.cc:152
bool doSiPMSmearing() const
virtual void add(const PCaloHit &hit, CLHEP::HepRandomEngine *) override
process a single SimHit
void setCrossTalk(double xtalk)
Definition: HcalSiPM.cc:158
virtual void setDetIds(const std::vector< DetId > &detIds)
unsigned int id() const
Definition: PCaloHit.h:43
double timeOfFlight(const DetId &detId) const
void setPresamples(int pre)
set presample information
Definition: CaloSamples.cc:31
static double generatePhotonTime(CLHEP::HepRandomEngine *engine)
int readoutFrameSize() const
for now, the LinearFrames and trhe digis will be one-to-one.
virtual int getReadoutFrameSize(const DetId &id) const
static constexpr float invDeltaTSiPM_
Definition: DetId.h:18
double analogSignalAmplitude(const DetId &id, float energy, const CaloSimParameters &parameters, CLHEP::HepRandomEngine *) const
std::vector< unsigned int > photonTimeHist
virtual CaloSamples makeBlankSignal(const DetId &detId) const
double sipmDarkCurrentuA(const DetId &detId) const
const CaloVSimParameterMap * theParameterMap
int size() const
get the size
Definition: CaloSamples.h:24
virtual void initializeHits() override
Initialize hits.
virtual CaloSamples makeSiPMSignal(DetId const &id, photonTimeHist const &photons, CLHEP::HepRandomEngine *)
float & preciseAtMod(int i)
mutable function to access precise samples
Definition: CaloSamples.h:31
virtual void add(const PCaloHit &hit, CLHEP::HepRandomEngine *)
process a single SimHit
double sipmCrossTalk(const DetId &detId) const
void setPrecise(int precisePresamples, float deltaT)
Definition: CaloSamples.h:66
static const double tzero[3]
HcalSiPMHitResponse(const CaloVSimParameterMap *parameterMap, const CaloShapes *shapes, bool PreMix1=false, bool HighFidelity=true)
const CaloVHitFilter * theHitFilter
DetId id() const
get the (generic) id
Definition: CaloSamples.h:21
photonTimeMap precisionTimedPhotons
int binOfMaximum() const
std::map< int, HcalSiPMShape > shapeMap