Belle II Software  release-08-01-10
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 #include <klm/dataobjects/KLMElementNumbers.h>
16 
17 /* Basf2 headers. */
18 #include <framework/dataobjects/EventMetaData.h>
19 #include <framework/datastore/StoreObjPtr.h>
20 #include <framework/gearbox/Unit.h>
21 #include <framework/logging/Logger.h>
22 
23 /* ROOT headers. */
24 #include <TFile.h>
25 #include <TH1D.h>
26 #include <TRandom.h>
27 
28 /* C++ headers. */
29 #include <algorithm>
30 #include <string>
31 
32 using namespace Belle2;
33 
34 static const char MemErr[] = "Memory allocation error.";
35 
36 static bool compareKLMSimHits(const KLMSimHit* hit1, const KLMSimHit* hit2)
37 {
38  return hit1->getEnergyDeposit() < hit2->getEnergyDeposit();
39 }
40 
42 {
44  /*
45  * Here there is a memory leak in case of realloc() failure, but it does not
46  * matter because a fatal error is issued in this case.
47  */
49  (struct Photoelectron*)realloc(m_Photoelectrons,
50  size * sizeof(struct Photoelectron));
52  size * sizeof(int));
54  size * sizeof(int));
55  if (size != 0) {
56  if (m_Photoelectrons == nullptr || m_PhotoelectronIndex == nullptr ||
57  m_PhotoelectronIndex2 == nullptr)
58  B2FATAL(MemErr);
59  }
60 }
61 
64  ScintillatorFirmware* fitter,
65  double digitizationInitialTime, bool debug) :
66  m_Time(&(KLMTime::Instance())),
67  m_DigPar(digPar),
68  m_fitter(fitter),
69  m_DigitizationInitialTime(digitizationInitialTime),
70  m_Debug(debug),
71  m_FPGAStat(c_ScintillatorFirmwareNoSignal),
72  m_npe(0),
73  m_Energy(0),
74  m_MCTime(-1),
75  m_SiPMMCTime(-1)
76 {
77  int i;
78  const double samplingTime = m_DigPar->getADCSamplingTDCPeriods() *
80  /* cppcheck-suppress variableScope */
81  double time, attenuationTime;
82  m_histRange = m_DigPar->getNDigitizations() * samplingTime;
86  /* Amplitude arrays. */
87  m_amplitudeDirect = (float*)malloc(m_DigPar->getNDigitizations() *
88  sizeof(float));
89  if (m_amplitudeDirect == nullptr)
90  B2FATAL(MemErr);
91  m_amplitudeReflected = (float*)malloc(m_DigPar->getNDigitizations() *
92  sizeof(float));
93  if (m_amplitudeReflected == nullptr)
94  B2FATAL(MemErr);
95  m_amplitude = (float*)malloc(m_DigPar->getNDigitizations() * sizeof(float));
96  if (m_amplitude == nullptr)
97  B2FATAL(MemErr);
98  m_ADCAmplitude = (int*)malloc(m_DigPar->getNDigitizations() * sizeof(int));
99  if (m_ADCAmplitude == nullptr)
100  B2FATAL(MemErr);
101  m_SignalTimeDependence = (double*)malloc((m_DigPar->getNDigitizations() + 1) *
102  sizeof(double));
103  if (m_SignalTimeDependence == nullptr)
104  B2FATAL(MemErr);
106  sizeof(double));
107  if (m_SignalTimeDependenceDiff == nullptr)
108  B2FATAL(MemErr);
109  attenuationTime = 1.0 / m_DigPar->getPEAttenuationFrequency();
110  for (i = 0; i <= m_DigPar->getNDigitizations(); i++) {
111  time = samplingTime * i;
113  exp(-digPar->getPEAttenuationFrequency() * time) * attenuationTime /
114  samplingTime;
115  if (i > 0) {
118  }
119  }
120  m_Photoelectrons = nullptr;
121  m_PhotoelectronIndex = nullptr;
122  m_PhotoelectronIndex2 = nullptr;
124 }
125 
126 
128 {
129  free(m_amplitudeDirect);
130  free(m_amplitudeReflected);
131  free(m_amplitude);
132  free(m_ADCAmplitude);
133  free(m_SignalTimeDependence);
134  free(m_SignalTimeDependenceDiff);
135  free(m_Photoelectrons);
136  free(m_PhotoelectronIndex);
137  free(m_PhotoelectronIndex2);
138 }
139 
141  const KLMScintillatorFEEData* FEEData)
142 {
143  m_Pedestal = FEEData->getPedestal();
144  m_PhotoelectronAmplitude = FEEData->getPhotoelectronAmplitude();
145  m_Threshold = FEEData->getThreshold();
146 }
147 
149 {
150  m_MCTime = -1;
151  m_SiPMMCTime = -1;
152  m_npe = 0;
153  m_Energy = 0;
154  for (int i = 0; i < m_DigPar->getNDigitizations(); i++) {
155  if (m_Debug) {
156  m_amplitudeDirect[i] = 0;
157  m_amplitudeReflected[i] = 0;
158  } else
159  m_amplitude[i] = 0;
160  }
161 }
162 
164  const std::multimap<KLMChannelNumber, const KLMSimHit*>::iterator& firstHit,
165  const std::multimap<KLMChannelNumber, const KLMSimHit*>::iterator& end)
166 {
167  m_stripName = "strip_" + std::to_string(firstHit->first);
168  prepareSimulation();
170  const KLMSimHit* hit = firstHit->second;
171  double stripLength;
172  bool isBKLM = (hit->getSubdetector() == KLMElementNumbers::c_BKLM);
173  if (isBKLM) {
174  const bklm::Module* module =
175  geoPar->findModule(hit->getSection(), hit->getSector(), hit->getLayer());
176  stripLength =
177  2.0 * (hit->isPhiReadout() ?
178  module->getPhiScintHalfLength(hit->getStrip()) :
179  module->getZScintHalfLength(hit->getStrip()));
180  } else {
182  hit->getStrip()) / CLHEP::mm * Unit::mm;
183  }
184  std::vector<const KLMSimHit*> hits;
185  for (std::multimap<KLMChannelNumber, const KLMSimHit*>::iterator it = firstHit;
186  it != end; ++it)
187  hits.push_back(it->second);
188  std::sort(hits.begin(), hits.end(), compareKLMSimHits);
189  for (std::vector<const KLMSimHit*>::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, time;
197  if (isBKLM) {
198  sipmDistance = hit->getPropagationTime() *
199  m_DigPar->getFiberLightSpeed();
200  time = hit->getTime() + hit->getPropagationTime();
201  if (m_MCTime < 0) {
202  m_MCTime = hit->getTime();
203  m_SiPMMCTime = time;
204  } else {
205  if (hit->getTime() < m_MCTime)
206  m_MCTime = hit->getTime();
207  if (time < m_SiPMMCTime)
208  m_SiPMMCTime = time;
209  }
210  } else {
211  sipmDistance = 0.5 * stripLength - hit->getLocalPosition().X();
212  time = hit->getTime() + sipmDistance / m_DigPar->getFiberLightSpeed();
213  if (m_MCTime < 0)
214  m_MCTime = time;
215  else
216  m_MCTime = time < m_MCTime ? time : m_MCTime;
217  }
218  int generatedPhotons = gRandom->Poisson(nPhotons);
219  generatePhotoelectrons(stripLength, sipmDistance, generatedPhotons,
220  hit->getTime(), false);
221  if (m_DigPar->getMirrorReflectiveIndex() > 0) {
222  generatedPhotons = gRandom->Poisson(nPhotons);
223  generatePhotoelectrons(stripLength, sipmDistance, generatedPhotons,
224  hit->getTime(), true);
225  }
226  }
227  performSimulation();
228 }
229 
231 {
232  if (m_Debug) {
233  fillSiPMOutput(m_amplitudeDirect, true, false);
234  fillSiPMOutput(m_amplitudeReflected, false, true);
235  for (int i = 0; i < m_DigPar->getNDigitizations(); i++)
236  m_amplitude[i] = m_amplitudeDirect[i] + m_amplitudeReflected[i];
237  } else
238  fillSiPMOutput(m_amplitude, true, true);
239  /* SiPM noise and ADC. */
240  if (m_DigPar->getMeanSiPMNoise() > 0)
241  addRandomSiPMNoise();
242  simulateADC();
243  m_FPGAStat = m_fitter->fit(m_ADCAmplitude, m_Threshold, &m_FPGAFit);
244  if (m_FPGAStat != c_ScintillatorFirmwareSuccessfulFit)
245  return;
246  if (m_Debug) {
247  if (m_npe >= 10)
248  debugOutput();
249  }
250 }
251 
253 {
254  int i;
255  for (i = 0; i < m_DigPar->getNDigitizations(); i++)
256  m_amplitude[i] = m_amplitude[i] +
257  gRandom->Poisson(m_DigPar->getMeanSiPMNoise());
258 }
259 
261 {
262  int* currentIndexArray, *newIndexArray, *tmpIndexArray;
263  int i, i1, i2, i1Max, i2Max, j, mergeSize;
264  currentIndexArray = m_PhotoelectronIndex;
265  newIndexArray = m_PhotoelectronIndex2;
266  mergeSize = 1;
267  while (mergeSize < nPhotoelectrons) {
268  for (i = 0; i < nPhotoelectrons; i = i + 2 * mergeSize) {
269  i1 = i;
270  j = i;
271  i2 = i + mergeSize;
272  if (i2 > nPhotoelectrons)
273  i2 = nPhotoelectrons;
274  i1Max = i2;
275  i2Max = i2 + mergeSize;
276  if (i2Max > nPhotoelectrons)
277  i2Max = nPhotoelectrons;
278  while (i1 < i1Max || i2 < i2Max) {
279  if (i1 < i1Max) {
280  if (i2 < i2Max) {
281  if (m_Photoelectrons[currentIndexArray[i1]].bin <
282  m_Photoelectrons[currentIndexArray[i2]].bin) {
283  newIndexArray[j] = currentIndexArray[i1];
284  i1++;
285  } else {
286  newIndexArray[j] = currentIndexArray[i2];
287  i2++;
288  }
289  } else {
290  newIndexArray[j] = currentIndexArray[i1];
291  i1++;
292  }
293  } else {
294  newIndexArray[j] = currentIndexArray[i2];
295  i2++;
296  }
297  j++;
298  }
299  }
300  tmpIndexArray = currentIndexArray;
301  currentIndexArray = newIndexArray;
302  newIndexArray = tmpIndexArray;
303  mergeSize = mergeSize * 2;
304  }
305  return currentIndexArray;
306 }
307 
309  double stripLen, double distSiPM, int nPhotons, double timeShift,
310  bool isReflected)
311 {
312  const double samplingTime = m_DigPar->getADCSamplingTDCPeriods() *
313  m_Time->getTDCPeriod();
314  const double maxHitTime = m_DigPar->getNDigitizations() * samplingTime;
315  int i;
316  /* cppcheck-suppress variableScope */
317  double hitTime, deExcitationTime, cosTheta, hitDist, selection;
318  double inverseLightSpeed, inverseAttenuationLength;
319  inverseLightSpeed = 1.0 / m_DigPar->getFiberLightSpeed();
320  inverseAttenuationLength = 1.0 / m_DigPar->getAttenuationLength();
321  /* Generation of photoelectrons. */
322  for (i = 0; i < nPhotons; i++) {
323  if (m_npe >= m_PhotoelectronBufferSize)
324  reallocPhotoElectronBuffers(m_npe + 100);
325  cosTheta = gRandom->Uniform(m_DigPar->getMinCosTheta(), 1);
326  if (!isReflected)
327  hitDist = distSiPM / cosTheta;
328  else
329  hitDist = (2.0 * stripLen - distSiPM) / cosTheta;
330  /* Fiber absorption. */
331  selection = gRandom->Uniform();
332  if (selection > exp(-hitDist * inverseAttenuationLength))
333  continue;
334  /* Account for mirror reflective index. */
335  if (isReflected) {
336  selection = gRandom->Uniform();
337  if (selection > m_DigPar->getMirrorReflectiveIndex())
338  continue;
339  }
340  deExcitationTime =
341  gRandom->Exp(m_DigPar->getScintillatorDeExcitationTime()) +
342  gRandom->Exp(m_DigPar->getFiberDeExcitationTime());
343  hitTime = hitDist * inverseLightSpeed + deExcitationTime +
344  timeShift - m_DigitizationInitialTime;
345  if (hitTime >= maxHitTime)
346  continue;
347  if (hitTime >= 0)
348  m_Photoelectrons[m_npe].bin = floor(hitTime / samplingTime);
349  else
350  m_Photoelectrons[m_npe].bin = -1;
351  m_Photoelectrons[m_npe].expTime =
352  exp(m_DigPar->getPEAttenuationFrequency() * hitTime);
353  m_Photoelectrons[m_npe].isReflected = isReflected;
354  m_PhotoelectronIndex[m_npe] = m_npe;
355  m_npe++;
356  }
357 }
358 
359 /*
360  * ADC signal corresponding to a photoelectron is
361  *
362  * exp(-(t - tau) / t0),
363  *
364  * where tau is the hit time and t0 = 1.0 / m_DigPar->PEAttenuationFreq. Its
365  * integral from t1 to t2 is
366  *
367  * t0 * exp(-(t1 - tau) / t0) - t0 * exp(-(t2 - tau) / t0).
368  *
369  * The integration is performed over digitization bins from (t_dig * i) to
370  * (t_dig * (i + 1)), where t_dig = m_DigPar->ADCSamplingTDCPeriods() *
371  * m_Time->getTDCPeriod() and i is the bin number.
372  * The integrals are
373  *
374  * I1 = t0 - t0 * exp(-(t_dig * (i + 1) - tau) / t0)
375  *
376  * for the first signal bin (t_dig * i <= tau < t_dig * (i + 1)) and
377  *
378  * I2 = t0 * exp(-(t_dig * i - tau) / t0) -
379  * t0 * exp(-(t_dig * (i + 1) - tau) / t0)
380  *
381  * for the following bins. The integrals contain expressions that do not depend
382  * on the hit time and may be calculated preliminary:
383  *
384  * B1 = t0 * exp(-(t_dig * (i + 1) / t0)
385  *
386  * and
387  *
388  * B2 = t0 * exp(-(t_dig * i) / t0) - t0 * exp(-(t_dig * (i + 1)) / t0).
389  *
390  * In terms of B1 and B2 the integrals are equal to
391  *
392  * I1 = t0 - B1 * exp(tau / t0)
393  *
394  * and
395  *
396  * I2 = B2 * exp(tau / t0).
397  *
398  * The sum of integrals for all photoelectrons is
399  *
400  * I = \sum_{hits before this bin} B2 * exp(tau_j / t0) +
401  * \sum_{hits in this bin} t0 - B1 * exp(tau_j / t0),
402  *
403  * where tau_j is the time of j-th hit. The bin-dependent expresions B1 and B2
404  * are the same for all hits:
405  *
406  * I = B2 * \sum_{hits before this bin} exp(tau_j / t0) +
407  * N_i * t0 - B1 * \sum_{hits in this bin} exp(tau_j / t0).
408  *
409  * where N_i is the number of hits in this (i-th) bin.
410  *
411  * In order to get the approximation of the function value, the integrals
412  * over bins are normalized:
413  *
414  * I -> I / t_dig.
415  *
416  * The normalization (1 / t_dig) is included into the definitions of B1 and B2.
417  */
418 void KLM::ScintillatorSimulator::fillSiPMOutput(float* hist, bool useDirect,
419  bool useReflected)
420 {
421  /* cppcheck-suppress variableScope */
422  int i, bin, maxBin;
423  double attenuationTime, sig, expSum;
424  /* cppcheck-suppress variableScope */
425  int ind1, ind2, ind3;
426  int* indexArray;
427  if (m_npe == 0)
428  return;
429  attenuationTime = 1.0 / m_DigPar->getPEAttenuationFrequency();
430  indexArray = sortPhotoelectrons(m_npe);
431  ind1 = 0;
432  expSum = 0;
433  while (1) {
434  ind2 = ind1;
435  bin = m_Photoelectrons[indexArray[ind1]].bin;
436  while (1) {
437  ind2++;
438  if (ind2 == m_npe)
439  break;
440  if (bin != m_Photoelectrons[indexArray[ind2]].bin)
441  break;
442  }
443  /* Now ind1 .. ind2 - photoelectrons in current bin. */
444  for (ind3 = ind1; ind3 != ind2; ind3++) {
445  if (m_Photoelectrons[indexArray[ind3]].isReflected && !useReflected)
446  continue;
447  if (!m_Photoelectrons[indexArray[ind3]].isReflected && !useDirect)
448  continue;
449  if (bin >= 0) {
450  sig = attenuationTime - m_Photoelectrons[indexArray[ind3]].expTime *
451  m_SignalTimeDependence[bin + 1];
452  hist[bin] = hist[bin] + sig;
453  }
454  expSum = expSum + m_Photoelectrons[indexArray[ind3]].expTime;
455  }
456  if (ind2 == m_npe)
457  maxBin = m_DigPar->getNDigitizations() - 1;
458  else
459  maxBin = m_Photoelectrons[indexArray[ind2]].bin;
460  for (i = bin + 1; i <= maxBin; i++) {
461  sig = m_SignalTimeDependenceDiff[i] * expSum;
462  hist[i] = hist[i] + sig;
463  }
464  if (ind2 == m_npe)
465  break;
466  ind1 = ind2;
467  }
468 }
469 
471 {
472  int i;
473  /* cppcheck-suppress variableScope */
474  double amp;
475  if (m_Pedestal == 0 || m_PhotoelectronAmplitude == 0)
476  B2FATAL("Incorrect EKLM ADC simulation parameters.");
477  for (i = 0; i < m_DigPar->getNDigitizations(); i++) {
478  amp = m_Pedestal - m_PhotoelectronAmplitude * m_amplitude[i];
479  if (amp < m_DigPar->getADCSaturation())
480  amp = m_DigPar->getADCSaturation();
481  m_ADCAmplitude[i] = floor(amp);
482  }
483 }
484 
486 {
487  return &m_FPGAFit;
488 }
489 
490 enum KLM::ScintillatorFirmwareFitStatus KLM::ScintillatorSimulator::getFitStatus() const
491 {
492  return m_FPGAStat;
493 }
494 
496 {
497  double intg;
498  intg = m_FPGAFit.getAmplitude();
499  return intg * m_DigPar->getPEAttenuationFrequency() /
500  m_PhotoelectronAmplitude;
501 }
502 
504 {
505  return m_npe;
506 }
507 
509 {
510  return m_Energy;
511 }
512 
514 {
515  int i;
516  std::string str;
518  TFile* hfile = nullptr;
519  TH1D* histAmplitudeDirect = nullptr;
520  TH1D* histAmplitudeReflected = nullptr;
521  TH1D* histAmplitude = nullptr;
522  TH1D* histADCAmplitude = nullptr;
523  try {
524  histAmplitudeDirect =
525  new TH1D("histAmplitudeDirect", m_stripName.c_str(),
526  m_DigPar->getNDigitizations(), 0, m_histRange);
527  histAmplitudeReflected =
528  new TH1D("histAmplitudeReflected", m_stripName.c_str(),
529  m_DigPar->getNDigitizations(), 0, m_histRange);
530  histAmplitude =
531  new TH1D("histAmplitude", m_stripName.c_str(),
532  m_DigPar->getNDigitizations(), 0, m_histRange);
533  histADCAmplitude =
534  new TH1D("histADCAmplitude", m_stripName.c_str(),
535  m_DigPar->getNDigitizations(), 0, m_histRange);
536  } catch (std::bad_alloc& ba) {
537  B2FATAL(MemErr);
538  }
539  for (i = 0; i < m_DigPar->getNDigitizations(); i++) {
540  histAmplitudeDirect->SetBinContent(i + 1, m_amplitudeDirect[i]);
541  histAmplitudeReflected->SetBinContent(i + 1, m_amplitudeReflected[i]);
542  histAmplitude->SetBinContent(i + 1, m_amplitude[i]);
543  histADCAmplitude->SetBinContent(i + 1, m_ADCAmplitude[i]);
544  }
545  str = std::string("experiment_") + std::to_string(event->getExperiment()) +
546  "_run_" + std::to_string(event->getRun()) + "_event_" +
547  std::to_string(event->getEvent()) + "_" + m_stripName + ".root";
548  try {
549  hfile = new TFile(str.c_str(), "NEW");
550  } catch (std::bad_alloc& ba) {
551  B2FATAL(MemErr);
552  }
553  hfile->Append(histAmplitudeDirect);
554  hfile->Append(histAmplitudeReflected);
555  hfile->Append(histAmplitude);
556  hfile->Append(histADCAmplitude);
557  hfile->Write();
558  hfile->Close();
559 }
560 
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 simulation hit.
Definition: KLMSimHit.h:31
float getEnergyDeposit() const
Get energy deposit.
Definition: KLMSimHit.h:260
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.
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 simulate(const std::multimap< KLMChannelNumber, const KLMSimHit * >::iterator &firstHit, const std::multimap< KLMChannelNumber, const KLMSimHit * >::iterator &end)
Simulate a strip.
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:96
static const double mm
[millimeters]
Definition: Unit.h:70
Provides BKLM geometry parameters for simulation, reconstruction etc (from Gearbox or DataBase)
Definition: GeometryPar.h:37
const Module * findModule(int section, int sector, int layer) const
Get the pointer to the definition of a module.
Definition: GeometryPar.cc:721
static GeometryPar * instance(void)
Static method to get a reference to the singleton GeometryPar instance.
Definition: GeometryPar.cc:27
Define the geometry of a BKLM module Each sector [octant] contains Modules.
Definition: Module.h:76
Abstract base class for different kinds of events.