Belle II Software  release-08-01-10
TOPDigitizerModule.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 <top/modules/TOPDigitizer/TOPDigitizerModule.h>
11 
12 // TOP headers.
13 #include <top/geometry/TOPGeometryPar.h>
14 #include <top/modules/TOPDigitizer/TimeDigitizer.h>
15 
16 // framework - DataStore
17 #include <framework/datastore/DataStore.h>
18 #include <framework/datastore/StoreArray.h>
19 #include <framework/datastore/StoreObjPtr.h>
20 
21 // framework aux
22 #include <framework/logging/Logger.h>
23 
24 // ROOT
25 #include <TRandom.h>
26 
27 #include <map>
28 
29 using namespace std;
30 
31 namespace Belle2 {
37  using namespace TOP;
38 
39  //-----------------------------------------------------------------
41  //-----------------------------------------------------------------
42 
43  REG_MODULE(TOPDigitizer);
44 
45 
46  //-----------------------------------------------------------------
47  // Implementation
48  //-----------------------------------------------------------------
49 
50  TOPDigitizerModule::TOPDigitizerModule() : Module()
51  {
52  // Set description()
53  setDescription("Digitize TOPSimHits");
55 
56  // Add parameters
57  addParam("timeZeroJitter", m_timeZeroJitter,
58  "r.m.s of T0 jitter [ns]", 15e-3);
59  addParam("electronicJitter", m_electronicJitter,
60  "r.m.s of electronic jitter [ns], "
61  "if negative the one from TOPNominalTDC is used. "
62  "This parameter is ignored in the full waveform digitization.", -1.0);
63  addParam("darkNoise", m_darkNoise,
64  "uniformly distributed dark noise (hits per module)", 0.0);
65  addParam("ADCx0", m_ADCx0,
66  "pulse height distribution parameter [ADC counts]", 204.1);
67  addParam("ADCp1", m_ADCp1,
68  "pulse height distribution parameter (must be non-negative)", 1.0);
69  addParam("ADCp2", m_ADCp2,
70  "pulse height distribution parameter (must be non-negative)", 1.025);
71  addParam("ADCmax", m_ADCmax,
72  "pulse height distribution upper bound [ADC counts]", 2000.0);
73  addParam("rmsNoise", m_rmsNoise,
74  "r.m.s of noise [ADC counts]", 9.7);
75  addParam("threshold", m_threshold,
76  "pulse height threshold [ADC counts]", 40);
77  addParam("hysteresis", m_hysteresis,
78  "pulse height threshold hysteresis [ADC counts]", 10);
79  addParam("thresholdCount", m_thresholdCount,
80  "minimal number of samples above threshold", 3);
81  addParam("useWaveforms", m_useWaveforms,
82  "if true, use full waveform digitization", true);
83  addParam("allChannels", m_allChannels,
84  "if true, make waveforms for all 8192 channels "
85  "(note: this will slow-down digitization)", false);
86  addParam("useDatabase", m_useDatabase,
87  "if true, use channel dependent constants from database (incl. time base)",
88  true);
89  addParam("useSampleTimeCalibration", m_useSampleTimeCalibration,
90  "if true, use only time base calibration from database "
91  "(has no effect if useDatabase = True)", false);
92  addParam("simulateTTS", m_simulateTTS,
93  "if true, simulate time transition spread. "
94  "Should be always switched ON, except for some dedicated timing studies.",
95  true);
96  addParam("minWidthXheight", m_minWidthXheight,
97  "minimal product of width and height [ns * ADC counts]", 100.0);
98  addParam("lookBackWindows", m_lookBackWindows,
99  "number of look back windows, if positive override the number from database", 0);
100  }
101 
102 
104  {
105  // input from datastore
106  m_simHits.isRequired();
107  m_simCalPulses.isOptional();
109  m_simClockState.isOptional();
110 
111  // output to datastore
112  m_rawDigits.registerInDataStore();
113  m_digits.registerInDataStore();
114  m_digits.registerRelationTo(m_simHits);
115  m_digits.registerRelationTo(m_mcParticles);
116  m_digits.registerRelationTo(m_rawDigits);
117  m_waveforms.registerInDataStore(DataStore::c_DontWriteOut);
118  m_rawDigits.registerRelationTo(m_waveforms, DataStore::c_Event,
120 
121  // geometry and nominal data
122  const auto* geo = TOPGeometryPar::Instance()->getGeometry();
123 
124  if (m_electronicJitter < 0) {
125  m_electronicJitter = geo->getNominalTDC().getTimeJitter();
126  }
127 
128  // set pile-up and double hit resolution times (needed for BG overlay)
129  TOPDigit::setDoubleHitResolution(geo->getNominalTDC().getDoubleHitResolution());
130  TOPDigit::setPileupTime(geo->getNominalTDC().getPileupTime());
131 
132  // default sample times (equidistant)
133  m_syncTimeBase = geo->getNominalTDC().getSyncTimeBase();
134  m_sampleTimes.setTimeAxis(m_syncTimeBase); // equidistant time base
135 
136  // default pulse height generator
138 
139  }
140 
141 
143  {
144  StoreObjPtr<EventMetaData> evtMetaData;
145 
146  // check availability of mappers
147  const auto& channelMapper = TOPGeometryPar::Instance()->getChannelMapper();
148  if (not channelMapper.isValid()) {
149  B2FATAL("No valid channel mapper found for run "
150  << evtMetaData->getRun()
151  << " of experiment " << evtMetaData->getExperiment());
152  }
153  const auto& frontEndMapper = TOPGeometryPar::Instance()->getFrontEndMapper();
154  if (not frontEndMapper.isValid()) {
155  B2FATAL("No valid front-end mapper found for run "
156  << evtMetaData->getRun()
157  << " of experiment " << evtMetaData->getExperiment());
158  }
159 
160  // check availability of constants in database
161  if (m_useDatabase) {
162  if (not m_timebases.isValid()) {
163  B2FATAL("Sample time calibration constants requested but not available for run "
164  << evtMetaData->getRun()
165  << " of experiment " << evtMetaData->getExperiment());
166  }
167  if (not m_channelT0.isValid()) {
168  B2FATAL("Channel T0 calibration constants requested but not available for run "
169  << evtMetaData->getRun()
170  << " of experiment " << evtMetaData->getExperiment());
171  }
172  if (not m_asicShift.isValid()) {
173  B2FATAL("ASIC shifts calibration requested but not available for run "
174  << evtMetaData->getRun()
175  << " of experiment " << evtMetaData->getExperiment());
176  }
177  if (not m_moduleT0.isValid()) {
178  B2FATAL("Module T0 calibration constants requested but not available for run "
179  << evtMetaData->getRun()
180  << " of experiment " << evtMetaData->getExperiment());
181  }
182  if (not m_commonT0.isValid()) {
183  B2FATAL("Common T0 calibration constants requested but not available for run "
184  << evtMetaData->getRun()
185  << " of experiment " << evtMetaData->getExperiment());
186  }
187  if (not m_pulseHeights.isValid()) {
188  B2FATAL("Pulse height calibration constants requested but not available for run "
189  << evtMetaData->getRun()
190  << " of experiment " << evtMetaData->getExperiment());
191  }
192  if (not m_thresholds.isValid()) {
193  B2FATAL("Channel thresholds requested but not available for run "
194  << evtMetaData->getRun()
195  << " of experiment " << evtMetaData->getExperiment());
196  }
197  if (not m_noises.isValid()) {
198  B2FATAL("Channel noise levels requested but not available for run "
199  << evtMetaData->getRun()
200  << " of experiment " << evtMetaData->getExperiment());
201  }
202  if (m_timeWalk.isValid()) {
204  } else {
206  // B2FATAL("Time-walk parameters requested but not available for run "
207  B2WARNING("Time-walk parameters not available for run "
208  << evtMetaData->getRun()
209  << " of experiment " << evtMetaData->getExperiment());
210  }
211  } else if (m_useSampleTimeCalibration) {
212  if (not m_timebases.isValid()) {
213  B2FATAL("Sample time calibration constants requested but not available for run "
214  << evtMetaData->getRun()
215  << " of experiment " << evtMetaData->getExperiment());
216  }
217  }
218 
219  // check availability of front-end settings
220  if (not m_feSetting.isValid()) {
221  B2FATAL("Front-end settings are not available for run "
222  << evtMetaData->getRun()
223  << " of experiment " << evtMetaData->getExperiment());
224  }
225 
226  // pass a parameter to TimeDigitizer
227  TimeDigitizer::setReadoutWindows(m_feSetting->getReadoutWindows());
228  if ((evtMetaData->getExperiment() > 0 and evtMetaData->getExperiment() < 5) or
229  evtMetaData->getExperiment() == 1002) {
230  TimeDigitizer::maskSamples(true); // phase-2: mask samples at window boundaries
231  } else {
232  TimeDigitizer::maskSamples(false); // phase-3: no masking
233  }
234 
235  }
236 
238  {
239 
240  // get or generate revo9 count
241  unsigned revo9cnt = 0;
242  if (m_simClockState.isValid()) {
243  revo9cnt = m_simClockState->getRevo9Count();
244  } else {
245  revo9cnt = gRandom->Integer(11520);
246  }
247 
248  // from revo9 count determine trigger time offset and the number of offset windows
249  double SSTfrac = (revo9cnt % 6) / 6.0;
250  double offset = m_feSetting->getOffset() / 24.0;
251  double trgTimeOffset = (SSTfrac + offset) * m_syncTimeBase; // in [ns]
252  int offsetWindows = m_feSetting->getWindowShift(revo9cnt);
253  TimeDigitizer::setOffsetWindows(offsetWindows);
254 
255  // from revo9 and write depths determine reference window, phase and storage depth
256  int SSTcnt = revo9cnt / 6;
257  int refWindow = SSTcnt * 2; // same as lastWriteAddr
258  const auto& writeDepths = m_feSetting->getWriteDepths();
259  if (writeDepths.empty()) {
260  B2ERROR("TOPDigitzer: vector of write depths is empty. No digitization possible");
261  return;
262  }
263  int lastDepth = writeDepths.back();
264  unsigned phase = 0;
265  for (auto depth : writeDepths) {
266  SSTcnt -= depth;
267  if (SSTcnt < 0) break;
268  phase++;
269  refWindow = SSTcnt * 2;
270  lastDepth = depth;
271  }
272  unsigned storageDepth = lastDepth * 2;
273  TimeDigitizer::setStorageDepth(storageDepth);
274 
275  // from reference window and lookback determine first of the readout windows
276  int lookBackWindows = m_feSetting->getLookbackWindows();
277  if (m_lookBackWindows > 0) lookBackWindows = m_lookBackWindows;
278  lookBackWindows -= m_feSetting->getExtraWindows();
279  int window = refWindow - lookBackWindows;
280  if (window < 0) window += storageDepth;
282 
283  // geometry and nominal data
284  const auto* geo = TOPGeometryPar::Instance()->getGeometry();
285 
286  // time range for digitization
287  double timeMin = geo->getSignalShape().getTMin() + offsetWindows * m_syncTimeBase / 2;
288  double timeMax = geo->getSignalShape().getTMax() +
289  (m_feSetting->getReadoutWindows() + offsetWindows) * m_syncTimeBase / 2;
290 
291  // simulate start time jitter
292  double startTimeJitter = gRandom->Gaus(0, m_timeZeroJitter);
293 
294  // get electronic efficiency
295  double electronicEfficiency = geo->getNominalTDC().getEfficiency();
296 
297  // define pixels with time digitizers
298  std::map<unsigned, TimeDigitizer> pixels;
299  typedef std::map<unsigned, TimeDigitizer>::iterator Iterator;
300 
301  // add simulated hits to time digitizers
302 
303  for (const auto& simHit : m_simHits) {
304  if (not m_useWaveforms) {
305  // simulate electronic efficiency
306  if (gRandom->Rndm() > electronicEfficiency) continue;
307  }
308  // do spatial digitization
309  double x = simHit.getX();
310  double y = simHit.getY();
311  int pmtID = simHit.getPmtID();
312  int moduleID = simHit.getModuleID();
313  if (not geo->isModuleIDValid(moduleID)) continue;
314  int pixelID = geo->getModule(moduleID).getPMTArray().getPixelID(x, y, pmtID);
315  if (pixelID == 0) continue;
316 
317  // add start time jitter and generated TTS to photon time
318  double time = simHit.getTime() + startTimeJitter;
319  if (m_simulateTTS) {
320  const auto& tts = TOPGeometryPar::Instance()->getTTS(moduleID, pmtID);
321  time += tts.generateTTS();
322  }
323 
324  // get time offset for a given pixel
325  auto timeOffset = getTimeOffset(trgTimeOffset, moduleID, pixelID);
326 
327  // time range cut (to speed up digitization)
328  if (time + timeOffset.value < timeMin + timeOffset.timeShift) continue;
329  if (time + timeOffset.value > timeMax + timeOffset.timeShift) continue;
330 
331  // generate pulse height
332  double pulseHeight = generatePulseHeight(moduleID, pixelID);
333  auto hitType = TimeDigitizer::c_Hit;
334 
335  // add time and pulse height to digitizer of a given pixel
336  TimeDigitizer digitizer(moduleID, pixelID, timeOffset.value, timeOffset.error,
337  timeOffset.windowShift, m_rmsNoise, m_sampleTimes);
338  if (not digitizer.isValid()) continue;
339  unsigned id = digitizer.getUniqueID();
340  Iterator it = pixels.insert(pair<unsigned, TimeDigitizer>(id, digitizer)).first;
341  it->second.addTimeOfHit(time, pulseHeight, hitType, &simHit);
342  }
343 
344  // add calibration pulses
345 
346  for (const auto& simCalPulses : m_simCalPulses) {
347  auto moduleID = simCalPulses.getModuleID();
348  auto pixelID = simCalPulses.getPixelID();
349  auto pulseHeight = simCalPulses.getAmplitude();
350  auto time = simCalPulses.getTime();
351  auto hitType = TimeDigitizer::c_CalPulse;
352 
353  // get time offset for a given pixel
354  auto timeOffset = getTimeOffset(trgTimeOffset, moduleID, pixelID);
355 
356  // time range cut (to speed up digitization)
357  if (time + timeOffset.value < timeMin + timeOffset.timeShift) continue;
358  if (time + timeOffset.value > timeMax + timeOffset.timeShift) continue;
359 
360  // add time and pulse height to digitizer of a given pixel
361  TimeDigitizer digitizer(moduleID, pixelID, timeOffset.value, timeOffset.error,
362  timeOffset.windowShift, m_rmsNoise, m_sampleTimes);
363  if (not digitizer.isValid()) continue;
364  unsigned id = digitizer.getUniqueID();
365  Iterator it = pixels.insert(pair<unsigned, TimeDigitizer>(id, digitizer)).first;
366  it->second.addTimeOfHit(time, pulseHeight, hitType);
367  }
368 
369  // add randomly distributed dark noise (maybe not needed anymore?)
370 
371  if (m_darkNoise > 0) {
372  int numModules = geo->getNumModules();
373  for (int moduleID = 1; moduleID <= numModules; moduleID++) {
374  int numPixels = geo->getModule(moduleID).getPMTArray().getNumPixels();
375  int numHits = gRandom->Poisson(m_darkNoise);
376  for (int i = 0; i < numHits; i++) {
377  int pixelID = int(gRandom->Rndm() * numPixels) + 1;
378  double time = (timeMax - timeMin) * gRandom->Rndm() + timeMin;
379  double pulseHeight = generatePulseHeight(moduleID, pixelID);
380  auto hitType = TimeDigitizer::c_Hit;
381  auto timeOffset = getTimeOffset(trgTimeOffset, moduleID, pixelID);
382  time += timeOffset.timeShift;
383  time -= timeOffset.value;
384  TimeDigitizer digitizer(moduleID, pixelID, timeOffset.value, timeOffset.error,
385  timeOffset.windowShift, m_rmsNoise, m_sampleTimes);
386  if (not digitizer.isValid()) continue;
387  unsigned id = digitizer.getUniqueID();
388  Iterator it = pixels.insert(pair<unsigned, TimeDigitizer>(id, digitizer)).first;
389  it->second.addTimeOfHit(time, pulseHeight, hitType);
390  }
391  }
392  }
393 
394  // if making waveforms for all channels, add missing digitizers.
395 
396  if (m_allChannels) {
397  int numModules = geo->getNumModules();
398  for (int moduleID = 1; moduleID <= numModules; moduleID++) {
399  int numPixels = geo->getModule(moduleID).getPMTArray().getNumPixels();
400  for (int pixelID = 1; pixelID <= numPixels; pixelID++) {
401  auto timeOffset = getTimeOffset(trgTimeOffset, moduleID, pixelID);
402  TimeDigitizer digitizer(moduleID, pixelID, timeOffset.value, timeOffset.error,
403  timeOffset.windowShift, m_rmsNoise, m_sampleTimes);
404  if (not digitizer.isValid()) continue;
405  unsigned id = digitizer.getUniqueID();
406  pixels.insert(pair<unsigned, TimeDigitizer>(id, digitizer));
407  }
408  }
409  }
410 
411  // replace equidistant time base with calibrated one if available
412 
414  for (auto& pixel : pixels) {
415  auto& digitizer = pixel.second;
416  const auto* sampleTimes = m_timebases->getSampleTimes(digitizer.getScrodID(),
417  digitizer.getChannel());
418  if (not sampleTimes) continue;
419  if (sampleTimes->isCalibrated()) digitizer.setSampleTimes(sampleTimes);
420  }
421  }
422 
423  // replace default noise level with channel dependent one if available,
424 
425  if (m_useDatabase) {
426  for (auto& pixel : pixels) {
427  auto& digitizer = pixel.second;
428  auto moduleID = digitizer.getModuleID();
429  auto channel = digitizer.getChannel();
430  auto rmsNoise = m_noises->getNoise(moduleID, channel);
431  if (rmsNoise > 0) {
432  digitizer.setNoise(rmsNoise);
433  }
434  }
435  }
436 
437  // digitize in time
438 
439  for (auto& pixel : pixels) {
440  const auto& digitizer = pixel.second;
441  int threshold = m_threshold;
442  if (m_useDatabase) { // use channel dependent ones
443  threshold = m_thresholds->getThr(digitizer.getModuleID(), digitizer.getChannel());
444  if (threshold <= 0) threshold = m_threshold; // not available, use the default
445  }
446  if (m_useWaveforms) {
447  digitizer.digitize(m_waveforms, m_rawDigits, m_digits,
448  threshold, m_hysteresis, m_thresholdCount);
449  } else {
450  digitizer.digitize(m_rawDigits, m_digits,
452  }
453  }
454 
455  // set additional info
456 
457  for (auto& rawDigit : m_rawDigits) {
458  rawDigit.setRevo9Counter(revo9cnt);
459  rawDigit.setPhase(phase);
460  rawDigit.setLastWriteAddr(refWindow);
461  rawDigit.setLookBackWindows(lookBackWindows);
462  rawDigit.setOfflineFlag();
463  }
464 
465  for (auto& waveform : m_waveforms) {
466  waveform.setRevo9Counter(revo9cnt);
467  waveform.setOffsetWindows(offsetWindows);
468  }
469 
470  // set calibration flags
471 
472  if (m_useDatabase) {
473  for (auto& digit : m_digits) {
474  if (m_channelT0->isCalibrated(digit.getModuleID(), digit.getChannel())) {
475  digit.addStatus(TOPDigit::c_ChannelT0Calibrated);
476  }
477  if (m_moduleT0->isCalibrated(digit.getModuleID())) {
478  digit.addStatus(TOPDigit::c_ModuleT0Calibrated);
479  }
480  if (m_commonT0->isCalibrated()) {
481  digit.addStatus(TOPDigit::c_CommonT0Calibrated);
482  }
483  }
484  }
485 
486  // cut on product of pulse width and height, as for data in TOPRawDigitConverter
487 
488  for (auto& digit : m_digits) {
489  if (digit.getPulseWidth() * digit.getPulseHeight() < m_minWidthXheight)
490  digit.setHitQuality(TOPDigit::c_Junk);
491  }
492 
493  }
494 
495 
497  int moduleID,
498  int pixelID)
499  {
500  double timeOffset = trgOffset;
501  double calErrorSq = 0;
502  int winShift = 0;
503  double timeShift = 0;
504  if (m_useDatabase) {
505  const auto& channelMapper = TOPGeometryPar::Instance()->getChannelMapper();
506  auto channel = channelMapper.getChannel(pixelID);
507  if (m_channelT0->isCalibrated(moduleID, channel)) {
508  timeOffset += m_channelT0->getT0(moduleID, channel);
509  double err = m_channelT0->getT0Error(moduleID, channel);
510  calErrorSq += err * err;
511  }
512  auto asic = channel / 8;
513  if (m_asicShift->isCalibrated(moduleID, asic)) {
514  timeOffset += m_asicShift->getT0(moduleID, asic);
515  winShift = lround(m_asicShift->getT0(moduleID, asic) / m_syncTimeBase * 2);
516  timeShift = winShift * m_syncTimeBase / 2;
517  }
518  if (m_moduleT0->isCalibrated(moduleID)) {
519  timeOffset += m_moduleT0->getT0(moduleID);
520  double err = m_moduleT0->getT0Error(moduleID);
521  calErrorSq += err * err;
522  }
523  if (m_commonT0->isCalibrated()) {
524  timeOffset += m_commonT0->getT0();
525  double err = m_commonT0->getT0Error();
526  calErrorSq += err * err;
527  }
528  }
529  return TimeOffset(timeOffset, calErrorSq, winShift, timeShift);
530  }
531 
532 
533  double TOPDigitizerModule::generatePulseHeight(int moduleID, int pixelID) const
534  {
535  if (m_useDatabase) {
536  const auto& channelMapper = TOPGeometryPar::Instance()->getChannelMapper();
537  auto channel = channelMapper.getChannel(pixelID);
538  if (m_pulseHeights->isCalibrated(moduleID, channel)) {
539  const auto& par = m_pulseHeights->getParameters(moduleID, channel);
540  PulseHeightGenerator generator(par.x0, par.p1, par.p2, m_ADCmax);
541  return generator.generate();
542  }
543  }
544 
546  }
547 
549 } // end Belle2 namespace
550 
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
Definition: DataStore.h:71
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition: DataStore.h:59
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
bool isOptional(const std::string &name="")
Tell the DataStore about an optional input.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
static void setDoubleHitResolution(double time)
Sets double hit resolution.
Definition: TOPDigit.h:87
static void setPileupTime(double time)
Sets pile-up time.
Definition: TOPDigit.h:93
double m_ADCx0
pulse height distribution parameter [ADC counts]
StoreArray< TOPRawWaveform > m_waveforms
collection of waveforms
double m_electronicJitter
r.m.s of electronic jitter
StoreArray< TOPRawDigit > m_rawDigits
collection of raw digits
int m_lookBackWindows
number of "look back" windows
DBObjPtr< TOPCalAsicShift > m_asicShift
ASIC shifts calibration constants.
DBObjPtr< TOPFrontEndSetting > m_feSetting
front-end settings
double m_rmsNoise
r.m.s of noise [ADC counts]
int m_hysteresis
pulse height threshold hysteresis [ADC counts]
DBObjPtr< TOPCalCommonT0 > m_commonT0
common T0 calibration constants
TOP::PulseHeightGenerator m_pulseHeightGenerator
default generator
bool m_useSampleTimeCalibration
if true, use time base calibration
StoreArray< TOPSimCalPulse > m_simCalPulses
collection of simuated cal pulses
double m_timeZeroJitter
r.m.s of T0 jitter
double m_ADCmax
pulse height upper bound of range [ADC counts]
bool m_simulateTTS
if true, add TTS to simulated hits
double m_ADCp2
pulse height distribution parameter, must be positive
DBObjPtr< TOPCalChannelT0 > m_channelT0
channel T0 calibration constants
bool m_allChannels
if true, always make waveforms for all channels
int m_threshold
pulse height threshold [ADC counts]
DBObjPtr< TOPCalChannelNoise > m_noises
channel noise levels (r.m.s)
double m_ADCp1
pulse height distribution parameter, must be non-negative
double m_syncTimeBase
SSTin period.
bool m_useWaveforms
if true, use full waveform digitization
OptionalDBObjPtr< TOPCalTimeWalk > m_timeWalk
time-walk calibration constants
DBObjPtr< TOPCalChannelThreshold > m_thresholds
channel thresholds
DBObjPtr< TOPCalTimebase > m_timebases
sample times from database
StoreArray< TOPDigit > m_digits
collection of digits
DBObjPtr< TOPCalModuleT0 > m_moduleT0
module T0 calibration constants
int m_thresholdCount
minimal number of samples above threshold
StoreArray< MCParticle > m_mcParticles
collection of MC particles
bool m_useDatabase
if true, use calibration constants from database
double m_minWidthXheight
minimal width * height [ns * ADC counts]
DBObjPtr< TOPCalChannelPulseHeight > m_pulseHeights
pulse height param.
double m_darkNoise
uniform dark noise (hits per bar)
StoreObjPtr< SimClockState > m_simClockState
generated hardware clock state
StoreArray< TOPSimHit > m_simHits
collection of simuated hits
TOPSampleTimes m_sampleTimes
equidistant sample times
const TOPSignalShape & getSignalShape() const
Returns single photon signal shape.
Definition: TOPGeometry.h:224
double getTMin() const
Returns time of the first waveform sample.
Generates pulse height according to distribution: P(x) = (x/x0)^p1 * exp(-(x/x0)^p2),...
double generate() const
Returns generated pulse height.
const TOPGeometry * getGeometry() const
Returns pointer to geometry object using basf2 units.
const FrontEndMapper & getFrontEndMapper() const
Returns front-end mapper (mapping of SCROD's to positions within TOP modules)
static TOPGeometryPar * Instance()
Static method to obtain the pointer to its instance.
const TOPNominalTTS & getTTS(int moduleID, int pmtID) const
Returns TTS of a PMT at given position.
const ChannelMapper & getChannelMapper() const
Returns default channel mapper (mapping of channels to pixels)
Time digitization of simulated hits in a single electronic channel.
Definition: TimeDigitizer.h:33
static void setReadoutWindows(unsigned numWin)
Sets the number of readout windows.
Definition: TimeDigitizer.h:80
static void maskSamples(bool maskThem)
Mask samples at the end of a window to emulate phase-2 data.
Definition: TimeDigitizer.h:98
static void setStorageDepth(unsigned storageDepth)
Sets storage depth.
Definition: TimeDigitizer.h:74
static void setTimeWalk(DBObjPtr< TOPCalTimeWalk > *timeWalk)
Stores pointer to time walk DB object defined in TOPDigitizerModule.
static void setOffsetWindows(int offsetWin)
Sets the number of windows before the first ASIC window.
Definition: TimeDigitizer.h:86
static void setFirstWindow(unsigned window)
Sets first ASIC window.
Definition: TimeDigitizer.h:92
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
double generatePulseHeight(int moduleID, int pixelID) const
Generates and returns pulse height.
virtual void initialize() override
Initialize the Module.
virtual void event() override
Event processor.
TimeOffset getTimeOffset(double trgOffset, int moduleID, int pixelID)
Returns a complete time offset by adding time mis-calibration to trgOffset.
virtual void beginRun() override
Called when entering a new run.
map< unsigned, size_t >::const_iterator Iterator
Iteratior for m_map.
void setTimeAxis(double syncTimeBase)
Sets equidistant time axis (uncalibrated).
Abstract base class for different kinds of events.
Utility structure for time offset.