test
CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
HcalSiPMHitResponse.cc
Go to the documentation of this file.
14 
15 #include "CLHEP/Random/RandPoissonQ.h"
16 #include "CLHEP/Random/RandFlat.h"
17 
18 #include <math.h>
19 #include <list>
20 
22  const CaloShapes * shapes, bool PreMix1) :
23  CaloHitResponse(parameterMap, shapes), theSiPM(), theRecoveryTime(250.),
24  TIMEMULT(1), Y11RANGE(250), Y11MAX(0.04), Y11TIMETORISE(16.65), PreMixDigis(PreMix1) {
25  theSiPM = new HcalSiPM(2500);
26 }
27 
29  if (theSiPM)
30  delete theSiPM;
31 }
32 
34  precisionTimedPhotons.clear();
35 }
36 
37 void HcalSiPMHitResponse::finalizeHits(CLHEP::HepRandomEngine* engine) {
38  //do not add PE noise for initial premix
39  if(!PreMixDigis) addPEnoise(engine);
40 
41  photonTimeMap::iterator channelPhotons;
42  for (channelPhotons = precisionTimedPhotons.begin();
43  channelPhotons != precisionTimedPhotons.end();
44  ++channelPhotons) {
45  CaloSamples signal(makeSiPMSignal(channelPhotons->first,
46  channelPhotons->second,
47  engine));
48  bool keep( keepBlank() );
49  if (!keep) {
50  const unsigned int size ( signal.size() ) ;
51  if( 0 != size ) {
52  for( unsigned int i ( 0 ) ; i != size ; ++i ) {
53  keep = keep || signal[i] > 1.e-7 ;
54  }
55  }
56  }
57 
58  LogDebug("HcalSiPMHitResponse") << HcalDetId(signal.id()) << ' ' << signal;
59 
60  if (keep) add(signal);
61  }
62 }
63 
65  DetId id(signal.id());
66  CaloSamples * oldSignal = findSignal(id);
67  if (oldSignal == 0) {
68  theAnalogSignalMap[id] = signal;
69  } else {
70  (*oldSignal) += signal;
71  }
72 }
73 
74 void HcalSiPMHitResponse::add(const PCaloHit& hit, CLHEP::HepRandomEngine* engine) {
75  if (!edm::isNotFinite(hit.time()) &&
76  ((theHitFilter == 0) || (theHitFilter->accepts(hit)))) {
77  HcalDetId id(hit.id());
78  const HcalSimParameters& pars = dynamic_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
79  //divide out mean of crosstalk distribution 1/(1-lambda) = multiply by (1-lambda)
80  double signal(analogSignalAmplitude(id, hit.energy(), pars, engine)*(1-pars.sipmCrossTalk(id)));
81  unsigned int photons(signal + 0.5);
82  double tof( timeOfFlight(id) );
83  double time( hit.time() );
84  if(ignoreTime) time = tof;
85 
86  if (photons > 0)
87  if (precisionTimedPhotons.find(id)==precisionTimedPhotons.end()) {
88  precisionTimedPhotons.insert(
89  std::pair<DetId, photonTimeHist >(id,
91  pars.readoutFrameSize(), 0)
92  )
93  );
94  }
95 
96  LogDebug("HcalSiPMHitResponse") << id;
97  LogDebug("HcalSiPMHitResponse") << " fCtoGeV: " << pars.fCtoGeV(id)
98  << " samplingFactor: " << pars.samplingFactor(id)
99  << " photoelectronsToAnalog: " << pars.photoelectronsToAnalog(id)
100  << " simHitToPhotoelectrons: " << pars.simHitToPhotoelectrons(id);
101  LogDebug("HcalSiPMHitResponse") << " energy: " << hit.energy()
102  << " photons: " << photons
103  << " time: " << time;
104  LogDebug("HcalSiPMHitResponse") << " timePhase: " << pars.timePhase()
105  << " tof: " << tof
106  << " binOfMaximum: " << pars.binOfMaximum()
107  << " phaseShift: " << thePhaseShift_;
108  double tzero(0.0*Y11TIMETORISE + pars.timePhase() -
109  (time - tof) -
110  BUNCHSPACE*( pars.binOfMaximum() - thePhaseShift_));
111  LogDebug("HcalSiPMHitResponse") << " tzero: " << tzero;
112  double tzero_bin(-tzero/(theTDCParams.deltaT()/TIMEMULT));
113  LogDebug("HcalSiPMHitResponse") << " corrected tzero: " << tzero_bin << '\n';
114  double t_pe(0.);
115  int t_bin(0);
116  for (unsigned int pe(0); pe<photons; ++pe) {
117  t_pe = generatePhotonTime(engine);
118  t_bin = int(t_pe/(theTDCParams.deltaT()/TIMEMULT) + tzero_bin + 0.5);
119  LogDebug("HcalSiPMHitResponse") << "t_pe: " << t_pe << " t_pe + tzero: " << (t_pe+tzero_bin*(theTDCParams.deltaT()/TIMEMULT))
120  << " t_bin: " << t_bin << '\n';
121  if ((t_bin >= 0) &&
122  (static_cast<unsigned int>(t_bin) < precisionTimedPhotons[id].size()))
123  precisionTimedPhotons[id][t_bin] += 1;
124  }
125  }
126 }
127 
128 void HcalSiPMHitResponse::addPEnoise(CLHEP::HepRandomEngine* engine)
129 {
130  double const dt(theTDCParams.deltaT()/TIMEMULT);
131 
132  // Add SiPM dark current noise to all cells
133  for(std::vector<DetId>::const_iterator idItr = theDetIds->begin();
134  idItr != theDetIds->end(); ++idItr) {
135  HcalDetId id(*idItr);
136  const HcalSimParameters& pars =
137  static_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
138 
139  // uA * ns / (fC/pe) = pe!
140  double dc_pe_avg =
141  pars.sipmDarkCurrentuA(id) * dt /
142  pars.photoelectronsToAnalog(id);
143 
144  if (dc_pe_avg <= 0.) continue;
145 
146  int nPreciseBins = theTDCParams.nbins() * TIMEMULT * pars.readoutFrameSize();
147 
148  unsigned int sumnoisePE(0);
149  double elapsedTime(0.);
150  for (int tprecise(0); tprecise < nPreciseBins; ++tprecise) {
151  int noisepe = CLHEP::RandPoissonQ::shoot(engine, dc_pe_avg); // add dark current noise
152 
153  if (noisepe > 0) {
154  if (precisionTimedPhotons.find(id)==precisionTimedPhotons.end()) {
155  photonTimeHist photons(nPreciseBins, 0);
156  photons[tprecise] = noisepe;
157  precisionTimedPhotons.insert
158  (std::pair<DetId, photonTimeHist >(id, photons ) );
159  } else {
160  precisionTimedPhotons[id][tprecise] += noisepe;
161  }
162 
163  sumnoisePE += noisepe;
164  }
165  elapsedTime += dt;
166 
167  } // precise time loop
168 
169  LogDebug("HcalSiPMHitResponse") << id;
170  LogDebug("HcalSiPMHitResponse") << " total noise (PEs): " << sumnoisePE;
171 
172  } // detId loop
173 } // HcalSiPMHitResponse::addPEnoise()
174 
177  int preciseSize(parameters.readoutFrameSize()*theTDCParams.nbins());
178  CaloSamples result(detId, parameters.readoutFrameSize(), preciseSize);
179  result.setPresamples(parameters.binOfMaximum()-1);
180  result.setPrecise(result.presamples()*theTDCParams.nbins(),
181  theTDCParams.deltaT());
182  return result;
183 }
184 
186  photonTimeHist const& photonTimeBins,
187  CLHEP::HepRandomEngine* engine) const {
188  const HcalSimParameters& pars = static_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
189  theSiPM->setNCells(pars.pixels(id));
190  theSiPM->setTau(pars.sipmTau());
193 
194  //use to make signal
195  CaloSamples signal( makeBlankSignal(id) );
196  double const dt(theTDCParams.deltaT()/TIMEMULT);
197  double const invdt(1./theTDCParams.deltaT());
198  int sampleBin(0), preciseBin(0);
199  signal.resetPrecise();
200  unsigned int pe(0);
201  double hitPixels(0.), elapsedTime(0.);
202  unsigned int sumPE(0);
203  double sumHits(0.);
204 
205  HcalSiPMShape sipmPulseShape(pars.signalShape(id));
206 
207  std::list< std::pair<double, double> > pulses;
208  std::list< std::pair<double, double> >::iterator pulse;
209  double timeDiff, pulseBit;
210  LogDebug("HcalSiPMHitResponse") << "makeSiPMSignal for " << HcalDetId(id);
211 
212  for (unsigned int tbin(0); tbin < photonTimeBins.size(); ++tbin) {
213  pe = photonTimeBins[tbin];
214  sumPE += pe;
215  preciseBin = tbin/TIMEMULT;
216  sampleBin = preciseBin/theTDCParams.nbins();
217  if (pe > 0) {
218  hitPixels = theSiPM->hitCells(engine, pe, 0., elapsedTime);
219  sumHits += hitPixels;
220  LogDebug("HcalSiPMHitResponse") << " elapsedTime: " << elapsedTime
221  << " sampleBin: " << sampleBin
222  << " preciseBin: " << preciseBin
223  << " pe: " << pe
224  << " hitPixels: " << hitPixels ;
225  if (pars.doSiPMSmearing()) {
226  pulses.push_back( std::pair<double, double>(elapsedTime, hitPixels) );
227  } else {
228  signal[sampleBin] += hitPixels;
229  hitPixels *= invdt;
230  signal.preciseAtMod(preciseBin) += 0.6*hitPixels;
231  if (preciseBin > 0)
232  signal.preciseAtMod(preciseBin-1) += 0.2*hitPixels;
233  if (preciseBin < signal.preciseSize() -1)
234  signal.preciseAtMod(preciseBin+1) += 0.2*hitPixels;
235  }
236  }
237 
238  if (pars.doSiPMSmearing()) {
239  pulse = pulses.begin();
240  while (pulse != pulses.end()) {
241  timeDiff = elapsedTime - pulse->first;
242  pulseBit = sipmPulseShape(timeDiff)*pulse->second;
243  LogDebug("HcalSiPMHitResponse") << " pulse t: " << pulse->first
244  << " pulse A: " << pulse->second
245  << " timeDiff: " << timeDiff
246  << " pulseBit: " << pulseBit;
247  signal[sampleBin] += pulseBit;
248  signal.preciseAtMod(preciseBin) += pulseBit*invdt;
249 
250  if (timeDiff > 1 && sipmPulseShape(timeDiff) < 1e-7)
251  pulse = pulses.erase(pulse);
252  else
253  ++pulse;
254  }
255  }
256  elapsedTime += dt;
257  }
258 
259  return signal;
260 }
261 
262 double HcalSiPMHitResponse::generatePhotonTime(CLHEP::HepRandomEngine* engine) const {
263  double result(0.);
264  while (true) {
265  result = CLHEP::RandFlat::shoot(engine, Y11RANGE);
266  if (CLHEP::RandFlat::shoot(engine, Y11MAX) < Y11TimePDF(result))
267  return result;
268  }
269 }
270 
272  return exp(-0.0635-0.1518*t)*pow(t, 2.528)/2485.9;
273 }
274 
275 void HcalSiPMHitResponse::setDetIds(const std::vector<DetId> & detIds) {
276  theDetIds = &detIds;
277 }
#define LogDebug(id)
std::vector< float > sipmNonlinearity(const DetId &detId) const
double sipmTau() const
float dt
Definition: AMPTWrapper.h:126
int i
Definition: DBlmapReader.cc:9
float deltaT() const
A general implementation for the response of a SiPM.
Definition: HcalSiPM.h:22
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:189
virtual double photoelectronsToAnalog(const DetId &detId) const
double energy() const
Definition: PCaloHit.h:29
double generatePhotonTime(CLHEP::HepRandomEngine *) const
virtual bool keepBlank() const
static double Y11TimePDF(double t)
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)
tuple result
Definition: mps_fire.py:84
const int keep
bool isNotFinite(T x)
Definition: isFinite.h:10
virtual CaloSamples makeSiPMSignal(DetId const &id, photonTimeHist const &photons, CLHEP::HepRandomEngine *) const
Creates electronics signals from hits.
virtual double hitCells(CLHEP::HepRandomEngine *, unsigned int pes, double tempDiff=0., double photonTime=0.)
Definition: HcalSiPM.cc:100
unsigned int signalShape(const DetId &detId) const
void setNCells(int nCells)
Definition: HcalSiPM.cc:144
void setTau(double tau)
Definition: HcalSiPM.cc:151
bool doSiPMSmearing() const
virtual const CaloSimParameters & simParameters(const DetId &id) const =0
virtual void add(const PCaloHit &hit, CLHEP::HepRandomEngine *) override
process a single SimHit
void setCrossTalk(double xtalk)
Definition: HcalSiPM.cc:157
virtual void setDetIds(const std::vector< DetId > &detIds)
virtual bool accepts(const PCaloHit &hit) const =0
unsigned int id() const
Definition: PCaloHit.h:43
double timeOfFlight(const DetId &detId) const
int readoutFrameSize() const
for now, the LinearFrames and trhe digis will be one-to-one.
HcalTDCParameters theTDCParams
AnalogSignalMap theAnalogSignalMap
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.
CaloSamples * findSignal(const DetId &detId)
users can look for the signal for a given cell
float & preciseAtMod(int i)
mutable function to access precise samples
Definition: CaloSamples.h:31
double sipmCrossTalk(const DetId &detId) const
static const double tzero[3]
const CaloVHitFilter * theHitFilter
DetId id() const
get the (generic) id
Definition: CaloSamples.h:21
photonTimeMap precisionTimedPhotons
int binOfMaximum() const
tuple size
Write out results.
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
HcalSiPMHitResponse(const CaloVSimParameterMap *parameterMap, const CaloShapes *shapes, bool PreMix1=false)