12 #include <top/modules/TOPRawDigitConverter/TOPRawDigitConverterModule.h>
15 #include <framework/datastore/StoreArray.h>
16 #include <framework/datastore/StoreObjPtr.h>
19 #include <framework/logging/Logger.h>
22 #include <top/dataobjects/TOPRawDigit.h>
23 #include <top/dataobjects/TOPRawWaveform.h>
24 #include <top/dataobjects/TOPDigit.h>
25 #include <framework/dataobjects/EventMetaData.h>
27 #include <top/geometry/TOPGeometryPar.h>
54 setDescription(
"Converts row digits to digits and applies time calibration");
55 setPropertyFlags(c_ParallelProcessingCertified);
58 addParam(
"inputRawDigitsName", m_inputRawDigitsName,
59 "name of TOPRawDigit store array",
string(
""));
60 addParam(
"outputDigitsName", m_outputDigitsName,
61 "name of TOPDigit store array",
string(
""));
62 addParam(
"useSampleTimeCalibration", m_useSampleTimeCalibration,
63 "if true, use sample time calibration",
true);
64 addParam(
"useAsicShiftCalibration", m_useAsicShiftCalibration,
65 "if true, use ASIC shifts calibration",
true);
66 addParam(
"useChannelT0Calibration", m_useChannelT0Calibration,
67 "if true, use channel T0 calibration",
true);
68 addParam(
"useModuleT0Calibration", m_useModuleT0Calibration,
69 "if true, use module T0 calibration",
true);
70 addParam(
"useCommonT0Calibration", m_useCommonT0Calibration,
71 "if true, use common T0 calibration",
true);
72 addParam(
"useTimeWalkCalibration", m_useTimeWalkCalibration,
73 "if true, use time-walk calibration",
true);
74 addParam(
"pedestalRMS", m_pedestalRMS,
75 "r.m.s of pedestals [ADC counts], "
76 "if positive, timeError will be estimated from FE data. "
77 "This is the default value used if r.m.s is not available from DB.", 9.7);
78 addParam(
"minPulseWidth", m_minPulseWidth,
79 "minimal pulse width [ns] to flag digit as good", 1.0);
80 addParam(
"maxPulseWidth", m_maxPulseWidth,
81 "maximal pulse width [ns] to flag digit as good", 10.0);
82 addParam(
"minWidthXheight", m_minWidthXheight,
83 "minimal product of width and height [ns * ADC counts]", 100.0);
84 addParam(
"storageDepth", m_storageDepth,
85 "ASIC analog storage depth of Interim FE format (ignored in other formats)",
87 addParam(
"lookBackWindows", m_lookBackWindows,
88 "number of look back windows, if positive override the number from database",
90 addParam(
"setPhase", m_setPhase,
91 "if true, set (override) phase in TOPRawDigits",
true);
92 addParam(
"calibrationChannel", m_calibrationChannel,
93 "calpulse selection: ASIC channel (use -1 to turn off the selection)", -1);
94 addParam(
"calpulseWidthMin", m_calpulseWidthMin,
95 "calpulse selection: minimal width [ns]", 0.0);
96 addParam(
"calpulseWidthMax", m_calpulseWidthMax,
97 "calpulse selection: maximal width [ns]", 0.0);
98 addParam(
"calpulseHeightMin", m_calpulseHeightMin,
99 "calpulse selection: minimal height [ADC counts]", 0);
100 addParam(
"calpulseHeightMax", m_calpulseHeightMax,
101 "calpulse selection: maximal height [ADC counts]", 0);
102 addParam(
"calpulseTimeMin", m_calpulseTimeMin,
103 "calpulse selection (ON if max > min): minimal time [ns]", 0.0);
104 addParam(
"calpulseTimeMax", m_calpulseTimeMax,
105 "calpulse selection (ON if max > min): maximal time [ns]", 0.0);
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));
335 int deltaWindow = window - refWindow;
336 if (deltaWindow > 0) deltaWindow -= storageDepth;
337 int lookBackWindows = m_feSetting->getLookbackWindows();
338 if (m_lookBackWindows > 0) lookBackWindows = m_lookBackWindows;
339 lookBackWindows -= m_feSetting->getExtraWindows();
341 int nwin = lookBackWindows + deltaWindow;
342 int startWindow = refWindow - lookBackWindows;
343 if (startWindow < 0) startWindow += storageDepth;
344 window = startWindow;
347 rawTimeLeading += nwin * TOPRawDigit::c_WindowSize;
348 rawTimeFalling += nwin * TOPRawDigit::c_WindowSize;
353 unsigned short statusBits = 0;
354 const auto* sampleTimes = &m_sampleTimes;
355 if (m_useSampleTimeCalibration) {
356 sampleTimes = m_timebase->getSampleTimes(scrodID, channel % 128);
357 if (sampleTimes->isCalibrated()) {
358 statusBits |= TOPDigit::c_TimeBaseCalibrated;
362 double time = sampleTimes->getTime(window, rawTimeLeading) - timeOffset;
363 double width = sampleTimes->getDeltaTime(window, rawTimeFalling, rawTimeLeading);
366 double timeError = geo->getNominalTDC().getTimeJitter();
368 if (rawDigit.getDataType() == TOPRawDigit::c_MC) {
370 time -= geo->getNominalTDC().getOffset();
371 statusBits |= TOPDigit::c_OffsetSubtracted;
374 if (m_pedestalRMS > 0) {
375 double rmsNoise = m_pedestalRMS;
376 if (m_noises->isCalibrated(moduleID, channel)) {
377 rmsNoise = m_noises->getNoise(moduleID, channel);
379 double rawErr = rawDigit.getCFDLeadingTimeError(rmsNoise);
380 int sample =
static_cast<int>(rawTimeLeading);
381 if (rawTimeLeading < 0) sample--;
382 timeError = rawErr * sampleTimes->getTimeBin(window, sample);
385 auto pulseHeight = rawDigit.getValuePeak();
386 double timeErrorSq = timeError * timeError;
387 if (m_timeWalk.isValid()) timeErrorSq += m_timeWalk->getSigmaSq(pulseHeight);
389 if (m_useTimeWalkCalibration and m_timeWalk.isValid()) {
390 if (m_timeWalk->isCalibrated()) {
391 time -= m_timeWalk->getTimeWalk(pulseHeight);
394 if (m_useChannelT0Calibration) {
395 const auto& cal = m_channelT0;
396 if (cal->isCalibrated(moduleID, channel)) {
397 time -= cal->getT0(moduleID, channel);
398 double err = cal->getT0Error(moduleID, channel);
399 timeErrorSq += err * err;
400 statusBits |= TOPDigit::c_ChannelT0Calibrated;
403 if (m_useAsicShiftCalibration) {
404 auto asic = channel / 8;
405 if (m_asicShift->isCalibrated(moduleID, asic)) {
406 time -= m_asicShift->getT0(moduleID, asic);
409 if (m_useModuleT0Calibration) {
410 const auto& cal = m_moduleT0;
411 if (cal->isCalibrated(moduleID)) {
412 time -= cal->getT0(moduleID);
413 double err = cal->getT0Error(moduleID);
414 timeErrorSq += err * err;
415 statusBits |= TOPDigit::c_ModuleT0Calibrated;
418 if (m_useCommonT0Calibration) {
419 const auto& cal = m_commonT0;
420 if (cal->isCalibrated()) {
421 time -= cal->getT0();
422 double err = cal->getT0Error();
423 timeErrorSq += err * err;
424 statusBits |= TOPDigit::c_CommonT0Calibrated;
427 timeError = sqrt(timeErrorSq);
432 auto* digit = m_digits.appendNew(moduleID, pixelID, rawTimeLeading);
433 digit->setTime(time);
434 digit->setTimeError(timeError);
435 digit->setPulseHeight(rawDigit.getValuePeak());
436 digit->setIntegral(rawDigit.getIntegral());
437 digit->setPulseWidth(width);
438 digit->setChannel(channel);
439 digit->setFirstWindow(window);
440 digit->setStatus(statusBits);
441 digit->addRelationTo(&rawDigit);
443 if (not rawDigit.isFEValid() or rawDigit.isPedestalJump())
444 digit->setHitQuality(TOPDigit::c_Junk);
445 if (rawDigit.isAtWindowDiscontinuity(storageDepth))
446 digit->setHitQuality(TOPDigit::c_Junk);
447 if (digit->getPulseWidth() < m_minPulseWidth or
448 digit->getPulseWidth() > m_maxPulseWidth or
449 digit->getPulseWidth() * digit->getPulseHeight() < m_minWidthXheight)
450 digit->setHitQuality(TOPDigit::c_Junk);
455 unsigned calibrationChannel = m_calibrationChannel;
456 if (calibrationChannel < 8) {
457 for (
auto& digit : m_digits) {
458 if (digit.getHitQuality() != TOPDigit::c_Good)
continue;
459 if (digit.getASICChannel() != calibrationChannel)
continue;
460 if (digit.getPulseHeight() < m_calpulseHeightMin)
continue;
461 if (digit.getPulseHeight() > m_calpulseHeightMax)
continue;
462 if (digit.getPulseWidth() < m_calpulseWidthMin)
continue;
463 if (digit.getPulseWidth() > m_calpulseWidthMax)
continue;
464 if (m_calpulseTimeMax > m_calpulseTimeMin) {
465 if (digit.getTime() < m_calpulseTimeMin)
continue;
466 if (digit.getTime() > m_calpulseTimeMax)
continue;
468 digit.setHitQuality(TOPDigit::c_CalPulse);
475 void TOPRawDigitConverterModule::endRun()
479 void TOPRawDigitConverterModule::terminate()