// Copyright (2019-2022) Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-or-later #include "JFPedestalCalc.h" #include "../common/JFJochException.h" JFPedestalCalc::JFPedestalCalc(const DiffractionExperiment & experiment, int64_t in_lines, int64_t in_line0) { if ((in_lines <= 0) || (in_line0 < 0) || (in_lines + in_line0 > RAW_MODULE_LINES)) throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Mismatch in lines number"); lines = in_lines; line0 = in_line0; currPedestal.resize(RAW_MODULE_COLS*lines, 0); wrongCount.resize(RAW_MODULE_COLS*lines, 0); switch (experiment.GetDetectorMode()) { case DetectorMode::PedestalG1: gain_level = 1; break; case DetectorMode::PedestalG2: gain_level = 2; break; default: gain_level = 0; break; } } template void JFPedestalCalc::AnalyzeImage(const uint16_t *raw_image) { if (image_number < window_size) { for (int i = 0; i < lines * RAW_MODULE_COLS; i++) { uint16_t adc = raw_image[i + line0 * RAW_MODULE_COLS] & 0x3FFF; uint16_t gain = raw_image[i + line0 * RAW_MODULE_COLS] & 0xC000; if (gain != GAIN_BIT) wrongCount[i] ++; currPedestal[i] += adc; } } else { for (int i = 0; i < lines * RAW_MODULE_COLS; i++) { uint16_t adc = raw_image[i + line0 * RAW_MODULE_COLS] & 0x3FFF; uint16_t gain = raw_image[i + line0 * RAW_MODULE_COLS] & 0xC000; if (gain != GAIN_BIT) wrongCount[i]++; else { // Don't include wrong gains into moving average currPedestal[i] += adc - currPedestal[i] / window_size; } } } } void JFPedestalCalc::AnalyzeImage(const uint16_t *raw_image) { switch (gain_level) { case 0: AnalyzeImage<0>(raw_image); break; case 1: AnalyzeImage<0x4000>(raw_image); break; case 2: AnalyzeImage<0xc000>(raw_image); break; default: break; } image_number++; } void JFPedestalCalc::Export(JFModulePedestal &calibration, size_t allowed_wrong_gains) { auto calib_mask = calibration.GetPedestalMask(); auto calib_pedestal = calibration.GetPedestal(); for (int i = 0; i < lines * RAW_MODULE_COLS; i++) { float tmp = currPedestal[i] / window_size; // Minimally, full window size needs to be recorded to give viable pedestal if ((image_number < window_size) || (wrongCount[i] > allowed_wrong_gains)) { calib_mask[i + line0 * RAW_MODULE_COLS] |= 1U << (gain_level + 1); calib_pedestal[i + line0 * RAW_MODULE_COLS] = 16384; } else { calib_mask[i + line0 * RAW_MODULE_COLS] &= ~(1U << (gain_level + 1)); calib_pedestal[i + line0 * RAW_MODULE_COLS] = static_cast(std::lround(tmp)); } } }