10 #include <top/modules/TOPRawDigitConverter/TOPRawDigitConverterModule.h>
13 #include <framework/datastore/StoreArray.h>
14 #include <framework/datastore/StoreObjPtr.h>
17 #include <framework/logging/Logger.h>
20 #include <top/dataobjects/TOPRawDigit.h>
21 #include <top/dataobjects/TOPRawWaveform.h>
22 #include <top/dataobjects/TOPDigit.h>
23 #include <framework/dataobjects/EventMetaData.h>
25 #include <top/geometry/TOPGeometryPar.h>
52 setDescription(
"Converts row digits to digits and applies time calibration");
53 setPropertyFlags(c_ParallelProcessingCertified);
56 addParam(
"inputRawDigitsName", m_inputRawDigitsName,
57 "name of TOPRawDigit store array",
string(
""));
58 addParam(
"outputDigitsName", m_outputDigitsName,
59 "name of TOPDigit store array",
string(
""));
60 addParam(
"useSampleTimeCalibration", m_useSampleTimeCalibration,
61 "if true, use sample time calibration",
true);
62 addParam(
"useAsicShiftCalibration", m_useAsicShiftCalibration,
63 "if true, use ASIC shifts calibration",
true);
64 addParam(
"useChannelT0Calibration", m_useChannelT0Calibration,
65 "if true, use channel T0 calibration",
true);
66 addParam(
"useModuleT0Calibration", m_useModuleT0Calibration,
67 "if true, use module T0 calibration",
true);
68 addParam(
"useCommonT0Calibration", m_useCommonT0Calibration,
69 "if true, use common T0 calibration",
true);
70 addParam(
"useTimeWalkCalibration", m_useTimeWalkCalibration,
71 "if true, use time-walk calibration",
true);
72 addParam(
"pedestalRMS", m_pedestalRMS,
73 "r.m.s of pedestals [ADC counts], "
74 "if positive, timeError will be estimated from FE data. "
75 "This is the default value used if r.m.s is not available from DB.", 9.7);
76 addParam(
"minPulseWidth", m_minPulseWidth,
77 "minimal pulse width [ns] to flag digit as good", 1.0);
78 addParam(
"maxPulseWidth", m_maxPulseWidth,
79 "maximal pulse width [ns] to flag digit as good", 10.0);
80 addParam(
"minWidthXheight", m_minWidthXheight,
81 "minimal product of width and height [ns * ADC counts]", 100.0);
82 addParam(
"storageDepth", m_storageDepth,
83 "ASIC analog storage depth of Interim FE format (ignored in other formats)",
85 addParam(
"lookBackWindows", m_lookBackWindows,
86 "number of look back windows, if positive override the number from database",
88 addParam(
"setPhase", m_setPhase,
89 "if true, set (override) phase in TOPRawDigits",
true);
90 addParam(
"calibrationChannel", m_calibrationChannel,
91 "calpulse selection: ASIC channel (use -1 to turn off the selection)", -1);
92 addParam(
"calpulseWidthMin", m_calpulseWidthMin,
93 "calpulse selection: minimal width [ns]", 0.0);
94 addParam(
"calpulseWidthMax", m_calpulseWidthMax,
95 "calpulse selection: maximal width [ns]", 0.0);
96 addParam(
"calpulseHeightMin", m_calpulseHeightMin,
97 "calpulse selection: minimal height [ADC counts]", 0);
98 addParam(
"calpulseHeightMax", m_calpulseHeightMax,
99 "calpulse selection: maximal height [ADC counts]", 0);
100 addParam(
"calpulseTimeMin", m_calpulseTimeMin,
101 "calpulse selection (ON if max > min): minimal time [ns]", 0.0);
102 addParam(
"calpulseTimeMax", m_calpulseTimeMax,
103 "calpulse selection (ON if max > min): maximal time [ns]", 0.0);
104 addParam(
"addRelations", m_addRelations,
"if true, make relations to TOPRawDigits",
true);
109 TOPRawDigitConverterModule::~TOPRawDigitConverterModule()
114 void TOPRawDigitConverterModule::initialize()
118 m_rawDigits.isRequired(m_inputRawDigitsName);
119 m_eventDebugs.isOptional();
120 m_digits.registerInDataStore(m_outputDigitsName);
121 m_digits.registerRelationTo(m_rawDigits);
122 m_asicMask.registerInDataStore();
125 const auto* geo = TOPGeometryPar::Instance()->getGeometry();
126 m_syncTimeBase = geo->getNominalTDC().getSyncTimeBase();
127 m_sampleTimes.setTimeAxis(m_syncTimeBase);
132 void TOPRawDigitConverterModule::beginRun()
139 if (m_useSampleTimeCalibration) {
140 if (not m_timebase.isValid()) {
141 B2FATAL(
"Sample time calibration requested but not available for run "
142 << evtMetaData->getRun()
143 <<
" of experiment " << evtMetaData->getExperiment());
146 if (m_useChannelT0Calibration) {
147 if (not m_channelT0.isValid()) {
148 B2FATAL(
"Channel T0 calibration requested but not available for run "
149 << evtMetaData->getRun()
150 <<
" of experiment " << evtMetaData->getExperiment());
153 if (m_useAsicShiftCalibration) {
154 if (not m_asicShift.isValid()) {
155 B2FATAL(
"ASIC shifts calibration requested but not available for run "
156 << evtMetaData->getRun()
157 <<
" of experiment " << evtMetaData->getExperiment());
160 if (m_useModuleT0Calibration) {
161 if (not m_moduleT0.isValid()) {
162 B2FATAL(
"Module T0 calibration requested but not available for run "
163 << evtMetaData->getRun()
164 <<
" of experiment " << evtMetaData->getExperiment());
167 if (m_useCommonT0Calibration) {
168 if (not m_commonT0.isValid()) {
169 B2FATAL(
"Common T0 calibration requested but not available for run "
170 << evtMetaData->getRun()
171 <<
" of experiment " << evtMetaData->getExperiment());
174 if (not m_timeWalk.isValid()) {
176 B2WARNING(
"Time-walk calibration is not available for run "
177 << evtMetaData->getRun()
178 <<
" of experiment " << evtMetaData->getExperiment());
180 if (m_pedestalRMS > 0 and not m_noises.isValid()) {
181 B2FATAL(
"Channel noise levels are not available for run "
182 << evtMetaData->getRun()
183 <<
" of experiment " << evtMetaData->getExperiment());
186 if (not m_feSetting.isValid()) {
187 B2FATAL(
"Front-end settings are not available for run "
188 << evtMetaData->getRun()
189 <<
" of experiment " << evtMetaData->getExperiment());
195 void TOPRawDigitConverterModule::event()
200 const auto& feMapper = TOPGeometryPar::Instance()->getFrontEndMapper();
201 const auto& chMapper = TOPGeometryPar::Instance()->getChannelMapper();
202 const auto* geo = TOPGeometryPar::Instance()->getGeometry();
210 for (
auto& rawDigit : m_rawDigits) {
212 if (waveform and rawDigit.getStorageWindows().empty()) {
220 if (m_eventDebugs.getEntries() > 0) {
221 std::vector<unsigned short> masks(64, 0xFFFF);
222 for (
const auto& eventDebug : m_eventDebugs) {
223 auto scrodID = eventDebug.getScrodID();
224 const auto* feemap = feMapper.getMap(scrodID);
226 B2WARNING(
"TOPRawDigitConverter: No front-end map available."
227 <<
LogVar(
"scrodID", scrodID));
230 auto moduleID = feemap->getModuleID();
231 auto boardstack = feemap->getBoardstackNumber();
232 unsigned bs = (moduleID - 1) * 4 + boardstack;
234 masks[bs] = eventDebug.getAsicMask();
236 B2ERROR(
"TOPRawDigitConverter: Invalid global boardstack number."
240 m_asicMask->set(masks);
245 for (
const auto& rawDigit : m_rawDigits) {
247 if (rawDigit.getErrorFlags() != 0)
continue;
251 auto scrodID = rawDigit.getScrodID();
252 const auto* feemap = feMapper.getMap(scrodID);
254 B2WARNING(
"TOPRawDigitConverter: No front-end map available."
255 <<
LogVar(
"scrodID", scrodID));
258 auto moduleID = feemap->getModuleID();
259 auto boardstack = feemap->getBoardstackNumber();
260 auto channel = chMapper.getChannel(boardstack,
261 rawDigit.getCarrierNumber(),
262 rawDigit.getASICNumber(),
263 rawDigit.getASICChannel());
264 auto pixelID = chMapper.getPixelID(channel);
268 double rawTimeLeading = rawDigit.getCFDLeadingTime();
269 double rawTimeFalling = rawDigit.getCFDFallingTime();
273 int window = rawDigit.getASICWindow();
277 double timeOffset = 0;
278 int storageDepth = m_storageDepth;
279 if (rawDigit.getDataType() == TOPRawDigit::c_Interim) {
282 rawTimeLeading = rawDigit.correctTime(rawTimeLeading, m_storageDepth);
283 rawTimeFalling = rawDigit.correctTime(rawTimeFalling, m_storageDepth);
286 int lastWriteAddr = rawDigit.getLastWriteAddr();
287 int nback = lastWriteAddr - window;
288 if (nback < 0) nback += m_storageDepth;
289 int lookBackWindows = m_feSetting->getLookbackWindows();
290 if (m_lookBackWindows > 0) lookBackWindows = m_lookBackWindows;
291 int nwin = lookBackWindows - nback;
293 if (window < 0) window += m_storageDepth;
294 if (window >= (
int) m_storageDepth) window -= m_storageDepth;
297 rawTimeLeading += nwin * TOPRawDigit::c_WindowSize;
298 rawTimeFalling += nwin * TOPRawDigit::c_WindowSize;
299 }
else if (rawDigit.getDataType() == TOPRawDigit::c_ProductionDebug) {
302 int revo9cnt = rawDigit.getRevo9Counter();
303 int SSTcnt = revo9cnt / 6;
304 double SSTfrac = (revo9cnt % 6) / 6.0;
305 double offset = m_feSetting->getOffset() / 24.0;
306 timeOffset = (SSTfrac + offset) * m_syncTimeBase;
309 int refWindow = SSTcnt * 2;
310 const auto& writeDepths = m_feSetting->getWriteDepths();
311 if (writeDepths.empty()) {
312 B2ERROR(
"TOPRawDigitConverter: vector of write depths is empty. Return!");
315 int lastDepth = writeDepths.back();
317 for (
auto depth : writeDepths) {
319 if (SSTcnt < 0)
break;
321 refWindow = SSTcnt * 2;
324 if (m_setPhase)
const_cast<TOPRawDigit&
>(rawDigit).setPhase(phase);
325 storageDepth = lastDepth * 2;
327 if (window >= storageDepth) {
328 B2WARNING(
"TOPRawDigitConverter: window number greater than storage depth."
329 <<
LogVar(
"window number", window)
330 <<
LogVar(
"storage depth", storageDepth)
331 <<
LogVar(
"refWindow", refWindow)
332 <<
LogVar(
"phase", phase));
337 int deltaWindow = window - refWindow;
338 if (deltaWindow > 0) deltaWindow -= storageDepth;
339 int lookBackWindows = m_feSetting->getLookbackWindows();
340 if (m_lookBackWindows > 0) lookBackWindows = m_lookBackWindows;
341 lookBackWindows -= m_feSetting->getExtraWindows();
343 int nwin = lookBackWindows + deltaWindow;
344 int startWindow = refWindow - lookBackWindows;
345 if (startWindow < 0) startWindow += storageDepth;
346 window = startWindow;
349 rawTimeLeading += nwin * TOPRawDigit::c_WindowSize;
350 rawTimeFalling += nwin * TOPRawDigit::c_WindowSize;
355 unsigned short statusBits = 0;
356 const auto* sampleTimes = &m_sampleTimes;
357 if (m_useSampleTimeCalibration) {
358 sampleTimes = m_timebase->getSampleTimes(scrodID, channel % 128);
359 if (sampleTimes->isCalibrated()) {
360 statusBits |= TOPDigit::c_TimeBaseCalibrated;
364 double time = sampleTimes->getTime(window, rawTimeLeading) - timeOffset;
365 double width = sampleTimes->getDeltaTime(window, rawTimeFalling, rawTimeLeading);
368 double timeError = geo->getNominalTDC().getTimeJitter();
370 if (rawDigit.getDataType() == TOPRawDigit::c_MC) {
372 time -= geo->getNominalTDC().getOffset();
373 statusBits |= TOPDigit::c_OffsetSubtracted;
376 if (m_pedestalRMS > 0) {
377 double rmsNoise = m_pedestalRMS;
378 if (m_noises->isCalibrated(moduleID, channel)) {
379 rmsNoise = m_noises->getNoise(moduleID, channel);
381 double rawErr = rawDigit.getCFDLeadingTimeError(rmsNoise);
382 int sample =
static_cast<int>(rawTimeLeading);
383 if (rawTimeLeading < 0) sample--;
384 timeError = rawErr * sampleTimes->getTimeBin(window, sample);
387 auto pulseHeight = rawDigit.getValuePeak();
388 double timeErrorSq = timeError * timeError;
389 if (m_timeWalk.isValid()) timeErrorSq += m_timeWalk->getSigmaSq(pulseHeight);
391 if (m_useTimeWalkCalibration and m_timeWalk.isValid()) {
392 if (m_timeWalk->isCalibrated()) {
393 time -= m_timeWalk->getTimeWalk(pulseHeight);
396 if (m_useChannelT0Calibration) {
397 const auto& cal = m_channelT0;
398 if (cal->isCalibrated(moduleID, channel)) {
399 time -= cal->getT0(moduleID, channel);
400 double err = cal->getT0Error(moduleID, channel);
401 timeErrorSq += err * err;
402 statusBits |= TOPDigit::c_ChannelT0Calibrated;
405 if (m_useAsicShiftCalibration) {
406 auto asic = channel / 8;
407 if (m_asicShift->isCalibrated(moduleID, asic)) {
408 time -= m_asicShift->getT0(moduleID, asic);
411 if (m_useModuleT0Calibration) {
412 const auto& cal = m_moduleT0;
413 if (cal->isCalibrated(moduleID)) {
414 time -= cal->getT0(moduleID);
415 double err = cal->getT0Error(moduleID);
416 timeErrorSq += err * err;
417 statusBits |= TOPDigit::c_ModuleT0Calibrated;
420 if (m_useCommonT0Calibration) {
421 const auto& cal = m_commonT0;
422 if (cal->isCalibrated()) {
423 time -= cal->getT0();
424 double err = cal->getT0Error();
425 timeErrorSq += err * err;
426 statusBits |= TOPDigit::c_CommonT0Calibrated;
429 timeError = sqrt(timeErrorSq);
434 auto* digit = m_digits.appendNew(moduleID, pixelID, rawTimeLeading);
435 digit->setTime(time);
436 digit->setTimeError(timeError);
437 digit->setPulseHeight(rawDigit.getValuePeak());
438 digit->setIntegral(rawDigit.getIntegral());
439 digit->setPulseWidth(width);
440 digit->setChannel(channel);
441 digit->setFirstWindow(window);
442 digit->setStatus(statusBits);
443 if (m_addRelations) digit->addRelationTo(&rawDigit);
445 if (not rawDigit.isFEValid() or rawDigit.isPedestalJump())
446 digit->setHitQuality(TOPDigit::c_Junk);
447 if (rawDigit.isAtWindowDiscontinuity(storageDepth))
448 digit->setHitQuality(TOPDigit::c_Junk);
449 if (digit->getPulseWidth() < m_minPulseWidth or
450 digit->getPulseWidth() > m_maxPulseWidth or
451 digit->getPulseWidth() * digit->getPulseHeight() < m_minWidthXheight)
452 digit->setHitQuality(TOPDigit::c_Junk);
457 unsigned calibrationChannel = m_calibrationChannel;
458 if (calibrationChannel < 8) {
459 for (
auto& digit : m_digits) {
460 if (digit.getHitQuality() != TOPDigit::c_Good)
continue;
461 if (digit.getASICChannel() != calibrationChannel)
continue;
462 if (digit.getPulseHeight() < m_calpulseHeightMin)
continue;
463 if (digit.getPulseHeight() > m_calpulseHeightMax)
continue;
464 if (digit.getPulseWidth() < m_calpulseWidthMin)
continue;
465 if (digit.getPulseWidth() > m_calpulseWidthMax)
continue;
466 if (m_calpulseTimeMax > m_calpulseTimeMin) {
467 if (digit.getTime() < m_calpulseTimeMin)
continue;
468 if (digit.getTime() > m_calpulseTimeMax)
continue;
470 digit.setHitQuality(TOPDigit::c_CalPulse);
477 void TOPRawDigitConverterModule::endRun()
481 void TOPRawDigitConverterModule::terminate()
Type-safe access to single objects in the data store.
TOPRawDigits to TOPDigits converter.
Class to store unpacked raw data (hits in feature-extraction format) It provides also calculation of ...
Class to store variables with their name which were sent to the logging service.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.