10#include <top/modules/TOPDigitizer/TOPDigitizerModule.h>
13#include <top/geometry/TOPGeometryPar.h>
14#include <top/modules/TOPDigitizer/TimeDigitizer.h>
17#include <framework/datastore/DataStore.h>
18#include <framework/datastore/StoreArray.h>
19#include <framework/datastore/StoreObjPtr.h>
22#include <framework/logging/Logger.h>
58 "r.m.s of T0 jitter [ns]", 15e-3);
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);
64 "uniformly distributed dark noise (hits per module)", 0.0);
66 "pulse height distribution parameter [ADC counts]", 204.1);
68 "pulse height distribution parameter (must be non-negative)", 1.0);
70 "pulse height distribution parameter (must be non-negative)", 1.025);
72 "pulse height distribution upper bound [ADC counts]", 2000.0);
74 "r.m.s of noise [ADC counts]", 9.7);
76 "pulse height threshold [ADC counts]", 40);
78 "pulse height threshold hysteresis [ADC counts]", 10);
80 "minimal number of samples above threshold", 3);
82 "if true, use full waveform digitization",
true);
84 "if true, make waveforms for all 8192 channels "
85 "(note: this will slow-down digitization)",
false);
87 "if true, use channel dependent constants from database (incl. time base)",
90 "if true, use only time base calibration from database "
91 "(has no effect if useDatabase = True)",
false);
93 "if true, simulate time transition spread. "
94 "Should be always switched ON, except for some dedicated timing studies.",
97 "minimal product of width and height [ns * ADC counts]", 100.0);
99 "number of look back windows, if positive override the number from database", 0);
148 if (not channelMapper.isValid()) {
149 B2FATAL(
"No valid channel mapper found for run "
150 << evtMetaData->getRun()
151 <<
" of experiment " << evtMetaData->getExperiment());
154 if (not frontEndMapper.isValid()) {
155 B2FATAL(
"No valid front-end mapper found for run "
156 << evtMetaData->getRun()
157 <<
" of experiment " << evtMetaData->getExperiment());
163 B2FATAL(
"Sample time calibration constants requested but not available for run "
164 << evtMetaData->getRun()
165 <<
" of experiment " << evtMetaData->getExperiment());
168 B2FATAL(
"Channel T0 calibration constants requested but not available for run "
169 << evtMetaData->getRun()
170 <<
" of experiment " << evtMetaData->getExperiment());
173 B2FATAL(
"ASIC shifts calibration requested but not available for run "
174 << evtMetaData->getRun()
175 <<
" of experiment " << evtMetaData->getExperiment());
178 B2FATAL(
"Module T0 calibration constants requested but not available for run "
179 << evtMetaData->getRun()
180 <<
" of experiment " << evtMetaData->getExperiment());
183 B2FATAL(
"Common T0 calibration constants requested but not available for run "
184 << evtMetaData->getRun()
185 <<
" of experiment " << evtMetaData->getExperiment());
188 B2FATAL(
"Pulse height calibration constants requested but not available for run "
189 << evtMetaData->getRun()
190 <<
" of experiment " << evtMetaData->getExperiment());
193 B2FATAL(
"Channel thresholds requested but not available for run "
194 << evtMetaData->getRun()
195 <<
" of experiment " << evtMetaData->getExperiment());
198 B2FATAL(
"Channel noise levels requested but not available for run "
199 << evtMetaData->getRun()
200 <<
" of experiment " << evtMetaData->getExperiment());
207 B2WARNING(
"Time-walk parameters not available for run "
208 << evtMetaData->getRun()
209 <<
" of experiment " << evtMetaData->getExperiment());
213 B2FATAL(
"Sample time calibration constants requested but not available for run "
214 << evtMetaData->getRun()
215 <<
" of experiment " << evtMetaData->getExperiment());
221 B2FATAL(
"Front-end settings are not available for run "
222 << evtMetaData->getRun()
223 <<
" of experiment " << evtMetaData->getExperiment());
228 if ((evtMetaData->getExperiment() > 0 and evtMetaData->getExperiment() < 5) or
229 evtMetaData->getExperiment() == 1002) {
241 unsigned revo9cnt = 0;
245 revo9cnt = gRandom->Integer(11520);
249 double SSTfrac = (revo9cnt % 6) / 6.0;
252 int offsetWindows =
m_feSetting->getWindowShift(revo9cnt);
256 int SSTcnt = revo9cnt / 6;
257 int refWindow = SSTcnt * 2;
258 const auto& writeDepths =
m_feSetting->getWriteDepths();
259 if (writeDepths.empty()) {
260 B2ERROR(
"TOPDigitzer: vector of write depths is empty. No digitization possible");
263 int lastDepth = writeDepths.back();
265 for (
auto depth : writeDepths) {
267 if (SSTcnt < 0)
break;
269 refWindow = SSTcnt * 2;
272 unsigned storageDepth = lastDepth * 2;
276 int lookBackWindows =
m_feSetting->getLookbackWindows();
279 int window = refWindow - lookBackWindows;
280 if (window < 0) window += storageDepth;
288 double timeMax = geo->getSignalShape().getTMax() +
295 double electronicEfficiency = geo->getNominalTDC().getEfficiency();
298 std::map<unsigned, TimeDigitizer> pixels;
299 typedef std::map<unsigned, TimeDigitizer>::iterator
Iterator;
306 if (gRandom->Rndm() > electronicEfficiency)
continue;
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;
318 double time = simHit.getTime() + startTimeJitter;
321 time += tts.generateTTS();
325 auto timeOffset =
getTimeOffset(trgTimeOffset, moduleID, pixelID);
328 if (time + timeOffset.value < timeMin + timeOffset.timeShift)
continue;
329 if (time + timeOffset.value > timeMax + timeOffset.timeShift)
continue;
333 auto hitType = TimeDigitizer::c_Hit;
336 TimeDigitizer digitizer(moduleID, pixelID, timeOffset.value, timeOffset.error,
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);
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;
354 auto timeOffset =
getTimeOffset(trgTimeOffset, moduleID, pixelID);
357 if (time + timeOffset.value < timeMin + timeOffset.timeShift)
continue;
358 if (time + timeOffset.value > timeMax + timeOffset.timeShift)
continue;
361 TimeDigitizer digitizer(moduleID, pixelID, timeOffset.value, timeOffset.error,
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);
372 int numModules = geo->getNumModules();
373 for (
int moduleID = 1; moduleID <= numModules; moduleID++) {
374 int numPixels = geo->getModule(moduleID).getPMTArray().getNumPixels();
376 for (
int i = 0; i < numHits; i++) {
377 int pixelID = int(gRandom->Rndm() * numPixels) + 1;
378 double time = (timeMax - timeMin) * gRandom->Rndm() + timeMin;
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,
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);
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,
404 if (not digitizer.isValid())
continue;
405 unsigned id = digitizer.getUniqueID();
406 pixels.insert(pair<unsigned, TimeDigitizer>(
id, digitizer));
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);
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);
432 digitizer.setNoise(rmsNoise);
439 for (
auto& pixel : pixels) {
440 const auto& digitizer = pixel.second;
443 threshold =
m_thresholds->getThr(digitizer.getModuleID(), digitizer.getChannel());
458 rawDigit.setRevo9Counter(revo9cnt);
459 rawDigit.setPhase(phase);
460 rawDigit.setLastWriteAddr(refWindow);
461 rawDigit.setLookBackWindows(lookBackWindows);
462 rawDigit.setOfflineFlag();
466 waveform.setRevo9Counter(revo9cnt);
467 waveform.setOffsetWindows(offsetWindows);
474 if (
m_channelT0->isCalibrated(digit.getModuleID(), digit.getChannel())) {
475 digit.addStatus(TOPDigit::c_ChannelT0Calibrated);
477 if (
m_moduleT0->isCalibrated(digit.getModuleID())) {
478 digit.addStatus(TOPDigit::c_ModuleT0Calibrated);
481 digit.addStatus(TOPDigit::c_CommonT0Calibrated);
490 digit.setHitQuality(TOPDigit::c_Junk);
500 double timeOffset = trgOffset;
501 double calErrorSq = 0;
503 double timeShift = 0;
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;
512 auto asic = channel / 8;
520 double err =
m_moduleT0->getT0Error(moduleID);
521 calErrorSq += err * err;
526 calErrorSq += err * err;
529 return TimeOffset(timeOffset, calErrorSq, winShift, timeShift);
537 auto channel = channelMapper.getChannel(pixelID);
539 const auto& par =
m_pulseHeights->getParameters(moduleID, channel);
541 return generator.generate();
@ c_DontWriteOut
Object/array should be NOT saved by output modules.
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
void setDescription(const std::string &description)
Sets the description of the module.
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
bool isOptional(const std::string &name="")
Tell the DataStore about an optional input.
Type-safe access to single objects in the data store.
static void setDoubleHitResolution(double time)
Sets double hit resolution.
static void setPileupTime(double time)
Sets pile-up time.
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.
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 ChannelMapper & getChannelMapper() const
Returns default channel mapper (mapping of channels to pixels)
static TOPGeometryPar * Instance()
Static method to obtain the pointer to its instance.
const FrontEndMapper & getFrontEndMapper() const
Returns front-end mapper (mapping of SCROD's to positions within TOP modules)
const TOPNominalTTS & getTTS(int moduleID, int pmtID) const
Returns TTS of a PMT at given position.
Time digitization of simulated hits in a single electronic channel.
static void setReadoutWindows(unsigned numWin)
Sets the number of readout windows.
static void maskSamples(bool maskThem)
Mask samples at the end of a window to emulate phase-2 data.
static void setStorageDepth(unsigned storageDepth)
Sets storage depth.
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.
static void setFirstWindow(unsigned window)
Sets first ASIC window.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
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.
TOPDigitizerModule()
Constructor.
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.