Belle II Software  release-06-01-15
ScintillatorSimulator.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 /* Own header. */
10 #include <klm/simulation/ScintillatorSimulator.h>
11 
12 /* KLM headers. */
13 #include <klm/bklm/geometry/GeometryPar.h>
14 #include <klm/eklm/geometry/GeometryData.h>
15 
16 /* Belle 2 headers. */
17 #include <framework/dataobjects/EventMetaData.h>
18 #include <framework/datastore/StoreObjPtr.h>
19 #include <framework/gearbox/Unit.h>
20 #include <framework/logging/Logger.h>
21 
22 /* ROOT headers. */
23 #include <TFile.h>
24 #include <TH1D.h>
25 #include <TRandom.h>
26 
27 /* C++ headers. */
28 #include <algorithm>
29 #include <string>
30 
31 using namespace Belle2;
32 
33 static const char MemErr[] = "Memory allocation error.";
34 
35 static bool compareBKLMSimHits(const BKLMSimHit* hit1, const BKLMSimHit* hit2)
36 {
37  return hit1->getEnergyDeposit() < hit2->getEnergyDeposit();
38 }
39 
40 static bool compareEKLMSimHits(const EKLMSimHit* hit1, const EKLMSimHit* hit2)
41 {
42  return hit1->getEnergyDeposit() < hit2->getEnergyDeposit();
43 }
44 
46 {
48  /*
49  * Here there is a memory leak in case of realloc() failure, but it does not
50  * matter because a fatal error is issued in this case.
51  */
52  /* cppcheck-suppress memleakOnRealloc */
54  (struct Photoelectron*)realloc(m_Photoelectrons,
55  size * sizeof(struct Photoelectron));
56  /* cppcheck-suppress memleakOnRealloc */
58  size * sizeof(int));
59  /* cppcheck-suppress memleakOnRealloc */
61  size * sizeof(int));
62  if (size != 0) {
63  if (m_Photoelectrons == nullptr || m_PhotoelectronIndex == nullptr ||
64  m_PhotoelectronIndex2 == nullptr)
65  B2FATAL(MemErr);
66  }
67 }
68 
71  ScintillatorFirmware* fitter,
72  double digitizationInitialTime, bool debug) :
73  m_Time(&(KLMTime::Instance())),
74  m_DigPar(digPar),
75  m_fitter(fitter),
76  m_DigitizationInitialTime(digitizationInitialTime),
77  m_Debug(debug),
78  m_FPGAStat(c_ScintillatorFirmwareNoSignal),
79  m_npe(0),
80  m_Energy(0),
81  m_MCTime(-1),
82  m_SiPMMCTime(-1)
83 {
84  int i;
85  const double samplingTime = m_DigPar->getADCSamplingTDCPeriods() *
87  /* cppcheck-suppress variableScope */
88  double time, attenuationTime;
89  m_histRange = m_DigPar->getNDigitizations() * samplingTime;
93  /* Amplitude arrays. */
94  m_amplitudeDirect = (float*)malloc(m_DigPar->getNDigitizations() *
95  sizeof(float));
96  if (m_amplitudeDirect == nullptr)
97  B2FATAL(MemErr);
98  m_amplitudeReflected = (float*)malloc(m_DigPar->getNDigitizations() *
99  sizeof(float));
100  if (m_amplitudeReflected == nullptr)
101  B2FATAL(MemErr);
102  m_amplitude = (float*)malloc(m_DigPar->getNDigitizations() * sizeof(float));
103  if (m_amplitude == nullptr)
104  B2FATAL(MemErr);
105  m_ADCAmplitude = (int*)malloc(m_DigPar->getNDigitizations() * sizeof(int));
106  if (m_ADCAmplitude == nullptr)
107  B2FATAL(MemErr);
108  m_SignalTimeDependence = (double*)malloc((m_DigPar->getNDigitizations() + 1) *
109  sizeof(double));
110  if (m_SignalTimeDependence == nullptr)
111  B2FATAL(MemErr);
113  sizeof(double));
114  if (m_SignalTimeDependenceDiff == nullptr)
115  B2FATAL(MemErr);
116  attenuationTime = 1.0 / m_DigPar->getPEAttenuationFrequency();
117  for (i = 0; i <= m_DigPar->getNDigitizations(); i++) {
118  time = samplingTime * i;
120  exp(-digPar->getPEAttenuationFrequency() * time) * attenuationTime /
121  samplingTime;
122  if (i > 0) {
125  }
126  }
127  m_Photoelectrons = nullptr;
128  m_PhotoelectronIndex = nullptr;
129  m_PhotoelectronIndex2 = nullptr;
131 }
132 
133 
135 {
136  free(m_amplitudeDirect);
137  free(m_amplitudeReflected);
138  free(m_amplitude);
139  free(m_ADCAmplitude);
140  free(m_SignalTimeDependence);
141  free(m_SignalTimeDependenceDiff);
142  free(m_Photoelectrons);
143  free(m_PhotoelectronIndex);
144  free(m_PhotoelectronIndex2);
145 }
146 
148  const KLMScintillatorFEEData* FEEData)
149 {
150  m_Pedestal = FEEData->getPedestal();
151  m_PhotoelectronAmplitude = FEEData->getPhotoelectronAmplitude();
152  m_Threshold = FEEData->getThreshold();
153 }
154 
156 {
157  m_MCTime = -1;
158  m_SiPMMCTime = -1;
159  m_npe = 0;
160  m_Energy = 0;
161  for (int i = 0; i < m_DigPar->getNDigitizations(); i++) {
162  if (m_Debug) {
163  m_amplitudeDirect[i] = 0;
164  m_amplitudeReflected[i] = 0;
165  } else
166  m_amplitude[i] = 0;
167  }
168 }
169 
171  const std::multimap<KLMChannelNumber, const BKLMSimHit*>::iterator& firstHit,
172  const std::multimap<KLMChannelNumber, const BKLMSimHit*>::iterator& end)
173 {
174  m_stripName = "strip_" + std::to_string(firstHit->first);
175  prepareSimulation();
177  const BKLMSimHit* hit = firstHit->second;
178  const bklm::Module* module =
179  geoPar->findModule(hit->getSection(), hit->getSector(), hit->getLayer());
180  double stripLength =
181  2.0 * (hit->isPhiReadout() ?
182  module->getPhiScintHalfLength(hit->getStrip()) :
183  module->getZScintHalfLength(hit->getStrip()));
184  std::vector<const BKLMSimHit*> hits;
185  for (std::multimap<KLMChannelNumber, const BKLMSimHit*>::iterator it = firstHit;
186  it != end; ++it)
187  hits.push_back(it->second);
188  std::sort(hits.begin(), hits.end(), compareBKLMSimHits);
189  for (std::vector<const BKLMSimHit*>::iterator it = hits.begin();
190  it != hits.end(); ++it) {
191  hit = *it;
192  m_Energy = m_Energy + hit->getEnergyDeposit();
193  /* Poisson mean for number of photons. */
194  double nPhotons = hit->getEnergyDeposit() * m_DigPar->getNPEperMeV();
195  /* Fill histograms. */
196  double sipmDistance = hit->getPropagationTime() *
197  m_DigPar->getFiberLightSpeed();
198  double time = hit->getTime() + hit->getPropagationTime();
199  if (m_MCTime < 0) {
200  m_MCTime = hit->getTime();
201  m_SiPMMCTime = time;
202  } else {
203  if (hit->getTime() < m_MCTime)
204  m_MCTime = hit->getTime();
205  if (time < m_SiPMMCTime)
206  m_SiPMMCTime = time;
207  }
208  int generatedPhotons = gRandom->Poisson(nPhotons);
209  generatePhotoelectrons(stripLength, sipmDistance, generatedPhotons,
210  hit->getTime(), false);
211  if (m_DigPar->getMirrorReflectiveIndex() > 0) {
212  generatedPhotons = gRandom->Poisson(nPhotons);
213  generatePhotoelectrons(stripLength, sipmDistance, generatedPhotons,
214  hit->getTime(), true);
215  }
216  }
217  performSimulation();
218 }
219 
221  const std::multimap<KLMChannelNumber, const EKLMSimHit*>::iterator& firstHit,
222  const std::multimap<KLMChannelNumber, const EKLMSimHit*>::iterator& end)
223 {
224  m_stripName = "strip_" + std::to_string(firstHit->first);
225  prepareSimulation();
226  const EKLMSimHit* hit = firstHit->second;
227  double stripLength = EKLM::GeometryData::Instance().getStripLength(
228  hit->getStrip()) / CLHEP::mm * Unit::mm;
229  std::vector<const EKLMSimHit*> hits;
230  for (std::multimap<KLMChannelNumber, const EKLMSimHit*>::iterator it = firstHit;
231  it != end; ++it)
232  hits.push_back(it->second);
233  std::sort(hits.begin(), hits.end(), compareEKLMSimHits);
234  for (std::vector<const EKLMSimHit*>::iterator it = hits.begin();
235  it != hits.end(); ++it) {
236  hit = *it;
237  m_Energy = m_Energy + hit->getEnergyDeposit();
238  /* Poisson mean for number of photons. */
239  double nPhotons = hit->getEnergyDeposit() * m_DigPar->getNPEperMeV();
240  /* Fill histograms. */
241  double sipmDistance = 0.5 * stripLength - hit->getLocalPosition().x();
242  double time = hit->getTime() +
243  sipmDistance / m_DigPar->getFiberLightSpeed();
244  if (m_MCTime < 0)
245  m_MCTime = time;
246  else
247  m_MCTime = time < m_MCTime ? time : m_MCTime;
248  int generatedPhotons = gRandom->Poisson(nPhotons);
249  generatePhotoelectrons(stripLength, sipmDistance, generatedPhotons,
250  hit->getTime(), false);
251  if (m_DigPar->getMirrorReflectiveIndex() > 0) {
252  generatedPhotons = gRandom->Poisson(nPhotons);
253  generatePhotoelectrons(stripLength, sipmDistance, generatedPhotons,
254  hit->getTime(), true);
255  }
256  }
257  performSimulation();
258 }
259 
261 {
262  if (m_Debug) {
263  fillSiPMOutput(m_amplitudeDirect, true, false);
264  fillSiPMOutput(m_amplitudeReflected, false, true);
265  for (int i = 0; i < m_DigPar->getNDigitizations(); i++)
266  m_amplitude[i] = m_amplitudeDirect[i] + m_amplitudeReflected[i];
267  } else
268  fillSiPMOutput(m_amplitude, true, true);
269  /* SiPM noise and ADC. */
270  if (m_DigPar->getMeanSiPMNoise() > 0)
271  addRandomSiPMNoise();
272  simulateADC();
273  m_FPGAStat = m_fitter->fit(m_ADCAmplitude, m_Threshold, &m_FPGAFit);
274  if (m_FPGAStat != c_ScintillatorFirmwareSuccessfulFit)
275  return;
276  if (m_Debug) {
277  if (m_npe >= 10)
278  debugOutput();
279  }
280 }
281 
283 {
284  int i;
285  for (i = 0; i < m_DigPar->getNDigitizations(); i++)
286  m_amplitude[i] = m_amplitude[i] +
287  gRandom->Poisson(m_DigPar->getMeanSiPMNoise());
288 }
289 
291 {
292  int* currentIndexArray, *newIndexArray, *tmpIndexArray;
293  int i, i1, i2, i1Max, i2Max, j, mergeSize;
294  currentIndexArray = m_PhotoelectronIndex;
295  newIndexArray = m_PhotoelectronIndex2;
296  mergeSize = 1;
297  while (mergeSize < nPhotoelectrons) {
298  for (i = 0; i < nPhotoelectrons; i = i + 2 * mergeSize) {
299  i1 = i;
300  j = i;
301  i2 = i + mergeSize;
302  if (i2 > nPhotoelectrons)
303  i2 = nPhotoelectrons;
304  i1Max = i2;
305  i2Max = i2 + mergeSize;
306  if (i2Max > nPhotoelectrons)
307  i2Max = nPhotoelectrons;
308  while (i1 < i1Max || i2 < i2Max) {
309  if (i1 < i1Max) {
310  if (i2 < i2Max) {
311  if (m_Photoelectrons[currentIndexArray[i1]].bin <
312  m_Photoelectrons[currentIndexArray[i2]].bin) {
313  newIndexArray[j] = currentIndexArray[i1];
314  i1++;
315  } else {
316  newIndexArray[j] = currentIndexArray[i2];
317  i2++;
318  }
319  } else {
320  newIndexArray[j] = currentIndexArray[i1];
321  i1++;
322  }
323  } else {
324  newIndexArray[j] = currentIndexArray[i2];
325  i2++;
326  }
327  j++;
328  }
329  }
330  tmpIndexArray = currentIndexArray;
331  currentIndexArray = newIndexArray;
332  newIndexArray = tmpIndexArray;
333  mergeSize = mergeSize * 2;
334  }
335  return currentIndexArray;
336 }
337 
339  double stripLen, double distSiPM, int nPhotons, double timeShift,
340  bool isReflected)
341 {
342  const double samplingTime = m_DigPar->getADCSamplingTDCPeriods() *
343  m_Time->getTDCPeriod();
344  const double maxHitTime = m_DigPar->getNDigitizations() * samplingTime;
345  int i;
346  /* cppcheck-suppress variableScope */
347  double hitTime, deExcitationTime, cosTheta, hitDist, selection;
348  double inverseLightSpeed, inverseAttenuationLength;
349  inverseLightSpeed = 1.0 / m_DigPar->getFiberLightSpeed();
350  inverseAttenuationLength = 1.0 / m_DigPar->getAttenuationLength();
351  /* Generation of photoelectrons. */
352  for (i = 0; i < nPhotons; i++) {
353  if (m_npe >= m_PhotoelectronBufferSize)
354  reallocPhotoElectronBuffers(m_npe + 100);
355  cosTheta = gRandom->Uniform(m_DigPar->getMinCosTheta(), 1);
356  if (!isReflected)
357  hitDist = distSiPM / cosTheta;
358  else
359  hitDist = (2.0 * stripLen - distSiPM) / cosTheta;
360  /* Fiber absorption. */
361  selection = gRandom->Uniform();
362  if (selection > exp(-hitDist * inverseAttenuationLength))
363  continue;
364  /* Account for mirror reflective index. */
365  if (isReflected) {
366  selection = gRandom->Uniform();
367  if (selection > m_DigPar->getMirrorReflectiveIndex())
368  continue;
369  }
370  deExcitationTime =
371  gRandom->Exp(m_DigPar->getScintillatorDeExcitationTime()) +
372  gRandom->Exp(m_DigPar->getFiberDeExcitationTime());
373  hitTime = hitDist * inverseLightSpeed + deExcitationTime +
374  timeShift - m_DigitizationInitialTime;
375  if (hitTime >= maxHitTime)
376  continue;
377  if (hitTime >= 0)
378  m_Photoelectrons[m_npe].bin = floor(hitTime / samplingTime);
379  else
380  m_Photoelectrons[m_npe].bin = -1;
381  m_Photoelectrons[m_npe].expTime =
382  exp(m_DigPar->getPEAttenuationFrequency() * hitTime);
383  m_Photoelectrons[m_npe].isReflected = isReflected;
384  m_PhotoelectronIndex[m_npe] = m_npe;
385  m_npe++;
386  }
387 }
388 
389 /*
390  * ADC signal corresponding to a photoelectron is
391  *
392  * exp(-(t - tau) / t0),
393  *
394  * where tau is the hit time and t0 = 1.0 / m_DigPar->PEAttenuationFreq. Its
395  * integral from t1 to t2 is
396  *
397  * t0 * exp(-(t1 - tau) / t0) - t0 * exp(-(t2 - tau) / t0).
398  *
399  * The integration is performed over digitization bins from (t_dig * i) to
400  * (t_dig * (i + 1)), where t_dig = m_DigPar->ADCSamplingTDCPeriods() *
401  * m_Time->getTDCPeriod() and i is the bin number.
402  * The integrals are
403  *
404  * I1 = t0 - t0 * exp(-(t_dig * (i + 1) - tau) / t0)
405  *
406  * for the first signal bin (t_dig * i <= tau < t_dig * (i + 1)) and
407  *
408  * I2 = t0 * exp(-(t_dig * i - tau) / t0) -
409  * t0 * exp(-(t_dig * (i + 1) - tau) / t0)
410  *
411  * for the following bins. The integrals contain expressions that do not depend
412  * on the hit time and may be calculated preliminary:
413  *
414  * B1 = t0 * exp(-(t_dig * (i + 1) / t0)
415  *
416  * and
417  *
418  * B2 = t0 * exp(-(t_dig * i) / t0) - t0 * exp(-(t_dig * (i + 1)) / t0).
419  *
420  * In terms of B1 and B2 the integrals are equal to
421  *
422  * I1 = t0 - B1 * exp(tau / t0)
423  *
424  * and
425  *
426  * I2 = B2 * exp(tau / t0).
427  *
428  * The sum of integrals for all photoelectrons is
429  *
430  * I = \sum_{hits before this bin} B2 * exp(tau_j / t0) +
431  * \sum_{hits in this bin} t0 - B1 * exp(tau_j / t0),
432  *
433  * where tau_j is the time of j-th hit. The bin-dependent expresions B1 and B2
434  * are the same for all hits:
435  *
436  * I = B2 * \sum_{hits before this bin} exp(tau_j / t0) +
437  * N_i * t0 - B1 * \sum_{hits in this bin} exp(tau_j / t0).
438  *
439  * where N_i is the number of hits in this (i-th) bin.
440  *
441  * In order to get the approximation of the function value, the integrals
442  * over bins are normalized:
443  *
444  * I -> I / t_dig.
445  *
446  * The normalization (1 / t_dig) is included into the definitions of B1 and B2.
447  */
448 void KLM::ScintillatorSimulator::fillSiPMOutput(float* hist, bool useDirect,
449  bool useReflected)
450 {
451  /* cppcheck-suppress variableScope */
452  int i, bin, maxBin;
453  double attenuationTime, sig, expSum;
454  /* cppcheck-suppress variableScope */
455  int ind1, ind2, ind3;
456  int* indexArray;
457  if (m_npe == 0)
458  return;
459  attenuationTime = 1.0 / m_DigPar->getPEAttenuationFrequency();
460  indexArray = sortPhotoelectrons(m_npe);
461  ind1 = 0;
462  expSum = 0;
463  while (1) {
464  ind2 = ind1;
465  bin = m_Photoelectrons[indexArray[ind1]].bin;
466  while (1) {
467  ind2++;
468  if (ind2 == m_npe)
469  break;
470  if (bin != m_Photoelectrons[indexArray[ind2]].bin)
471  break;
472  }
473  /* Now ind1 .. ind2 - photoelectrons in current bin. */
474  for (ind3 = ind1; ind3 != ind2; ind3++) {
475  if (m_Photoelectrons[indexArray[ind3]].isReflected && !useReflected)
476  continue;
477  if (!m_Photoelectrons[indexArray[ind3]].isReflected && !useDirect)
478  continue;
479  if (bin >= 0) {
480  sig = attenuationTime - m_Photoelectrons[indexArray[ind3]].expTime *
481  m_SignalTimeDependence[bin + 1];
482  hist[bin] = hist[bin] + sig;
483  }
484  expSum = expSum + m_Photoelectrons[indexArray[ind3]].expTime;
485  }
486  if (ind2 == m_npe)
487  maxBin = m_DigPar->getNDigitizations() - 1;
488  else
489  maxBin = m_Photoelectrons[indexArray[ind2]].bin;
490  for (i = bin + 1; i <= maxBin; i++) {
491  sig = m_SignalTimeDependenceDiff[i] * expSum;
492  hist[i] = hist[i] + sig;
493  }
494  if (ind2 == m_npe)
495  break;
496  ind1 = ind2;
497  }
498 }
499 
501 {
502  int i;
503  /* cppcheck-suppress variableScope */
504  double amp;
505  if (m_Pedestal == 0 || m_PhotoelectronAmplitude == 0)
506  B2FATAL("Incorrect EKLM ADC simulation parameters.");
507  for (i = 0; i < m_DigPar->getNDigitizations(); i++) {
508  amp = m_Pedestal - m_PhotoelectronAmplitude * m_amplitude[i];
509  if (amp < m_DigPar->getADCSaturation())
510  amp = m_DigPar->getADCSaturation();
511  m_ADCAmplitude[i] = floor(amp);
512  }
513 }
514 
516 {
517  return &m_FPGAFit;
518 }
519 
520 enum KLM::ScintillatorFirmwareFitStatus KLM::ScintillatorSimulator::getFitStatus() const
521 {
522  return m_FPGAStat;
523 }
524 
526 {
527  double intg;
528  intg = m_FPGAFit.getAmplitude();
529  return intg * m_DigPar->getPEAttenuationFrequency() /
530  m_PhotoelectronAmplitude;
531 }
532 
534 {
535  return m_npe;
536 }
537 
539 {
540  return m_Energy;
541 }
542 
544 {
545  int i;
546  std::string str;
548  TFile* hfile = nullptr;
549  TH1D* histAmplitudeDirect = nullptr;
550  TH1D* histAmplitudeReflected = nullptr;
551  TH1D* histAmplitude = nullptr;
552  TH1D* histADCAmplitude = nullptr;
553  try {
554  histAmplitudeDirect =
555  new TH1D("histAmplitudeDirect", m_stripName.c_str(),
556  m_DigPar->getNDigitizations(), 0, m_histRange);
557  histAmplitudeReflected =
558  new TH1D("histAmplitudeReflected", m_stripName.c_str(),
559  m_DigPar->getNDigitizations(), 0, m_histRange);
560  histAmplitude =
561  new TH1D("histAmplitude", m_stripName.c_str(),
562  m_DigPar->getNDigitizations(), 0, m_histRange);
563  histADCAmplitude =
564  new TH1D("histADCAmplitude", m_stripName.c_str(),
565  m_DigPar->getNDigitizations(), 0, m_histRange);
566  } catch (std::bad_alloc& ba) {
567  B2FATAL(MemErr);
568  }
569  for (i = 0; i < m_DigPar->getNDigitizations(); i++) {
570  histAmplitudeDirect->SetBinContent(i + 1, m_amplitudeDirect[i]);
571  histAmplitudeReflected->SetBinContent(i + 1, m_amplitudeReflected[i]);
572  histAmplitude->SetBinContent(i + 1, m_amplitude[i]);
573  histADCAmplitude->SetBinContent(i + 1, m_ADCAmplitude[i]);
574  }
575  str = std::string("experiment_") + std::to_string(event->getExperiment()) +
576  "_run_" + std::to_string(event->getRun()) + "_event_" +
577  std::to_string(event->getEvent()) + "_" + m_stripName + ".root";
578  try {
579  hfile = new TFile(str.c_str(), "NEW");
580  } catch (std::bad_alloc& ba) {
581  B2FATAL(MemErr);
582  }
583  hfile->Append(histAmplitudeDirect);
584  hfile->Append(histAmplitudeReflected);
585  hfile->Append(histAmplitude);
586  hfile->Append(histADCAmplitude);
587  hfile->Write();
588  hfile->Close();
589 }
590 
Store one simulation hit as a ROOT object.
Definition: BKLMSimHit.h:25
double getEnergyDeposit() const
Get energy deposition.
Definition: BKLMSimHit.h:145
float getEnergyDeposit() const
Get energy deposit.
Definition: EKLMHitBase.h:100
Class EKLMSimHit stores information on particular Geant step; using information from TrackID and Pare...
Definition: EKLMSimHit.h:32
static const GeometryData & Instance(enum DataSource dataSource=c_Database, const GearDir *gearDir=nullptr)
Instantiation.
Definition: GeometryData.cc:33
double getStripLength(int strip) const
Get strip length.
Definition: GeometryData.h:71
Class to store KLM scintillator simulation parameters in the database.
float getPEAttenuationFrequency() const
Get attenuation frequency of a single photoelectron pulse.
int getADCThreshold() const
Get ADC readout corresponding to saturation.
float getADCPEAmplitude() const
Get ADC photoelectron amplitude.
int getADCSamplingTDCPeriods() const
Get ADC sampling time in TDC periods.
int getNDigitizations() const
Get number of digitizations (points) in one sample.
int getThreshold() const
Get threshold.
float getPhotoelectronAmplitude() const
Get photoelectron amplitude.
float getPedestal() const
Get pedestal.
KLM time conversion.
Definition: KLMTime.h:27
double getTDCPeriod() const
Get TDC period.
Definition: KLMTime.h:45
void setFEEData(const KLMScintillatorFEEData *FEEData)
Set FEE data.
int * m_PhotoelectronIndex2
Buffer for photoelectron indices.
float * m_amplitudeReflected
Analog amplitude (reflected).
void debugOutput()
Debug output (signal and fit result histograms).
enum ScintillatorFirmwareFitStatus getFitStatus() const
Get fit status.
double * m_SignalTimeDependence
Buffer for signal time dependence calculation.
void generatePhotoelectrons(double stripLen, double distSiPM, int nPhotons, double timeShift, bool isReflected)
Generate photoelectrons.
double * m_SignalTimeDependenceDiff
Buffer for signal time dependence calculation.
float * m_amplitudeDirect
Analog amplitude (direct).
void addRandomSiPMNoise()
Add random noise to the signal (amplitude-dependend).
void simulateADC()
Simulate ADC (create digital signal from analog),.
void prepareSimulation()
Prepare simulation.
void simulate(const std::multimap< KLMChannelNumber, const BKLMSimHit * >::iterator &firstHit, const std::multimap< KLMChannelNumber, const BKLMSimHit * >::iterator &end)
Simulate BKLM strip.
double getEnergy()
Get total energy deposited in the strip (sum over ssimulation hits).
double m_histRange
Time range, (number of digitizations) * (ADC sampling time).
void reallocPhotoElectronBuffers(int size)
Reallocate photoelectron buffers.
double getNPhotoelectrons()
Get number of photoelectrons (fit result).
struct Photoelectron * m_Photoelectrons
Buffer for photoelectron data.
KLMScintillatorFirmwareFitResult * getFPGAFit()
Get fit data.
void performSimulation()
Perform common simulation stage.
double m_PhotoelectronAmplitude
Photoelectron amplitude.
int getNGeneratedPhotoelectrons()
Get generated number of photoelectrons.
int * m_PhotoelectronIndex
Buffer for photoelectron indices.
void fillSiPMOutput(float *hist, bool useDirect, bool useReflected)
Fill SiPM output.
int * sortPhotoelectrons(int nPhotoelectrons)
Sort photoelectrons.
int m_PhotoelectronBufferSize
Size of photoelectron data buffer.
ScintillatorSimulator(const KLMScintillatorDigitizationParameters *digPar, ScintillatorFirmware *fitter, double digitizationInitialTime, bool debug)
Constructor.
const KLMScintillatorDigitizationParameters * m_DigPar
Parameters.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
static const double mm
[millimeters]
Definition: Unit.h:70
Provides BKLM geometry parameters for simulation, reconstruction etc (from Gearbox or DataBase)
Definition: GeometryPar.h:38
const Module * findModule(int section, int sector, int layer) const
Get the pointer to the definition of a module.
Definition: GeometryPar.cc:727
static GeometryPar * instance(void)
Static method to get a reference to the singleton GeometryPar instance.
Definition: GeometryPar.cc:28
Define the geometry of a BKLM module Each sector [octant] contains Modules.
Definition: Module.h:76
Abstract base class for different kinds of events.