// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include #include "JFConversionFloatingPoint.h" JFConversionFloatingPoint::JFConversionFloatingPoint() : gain_g0(RAW_MODULE_SIZE), gain_g1(RAW_MODULE_SIZE), gain_g2(RAW_MODULE_SIZE), pedestal_g0(RAW_MODULE_SIZE), pedestal_g1(RAW_MODULE_SIZE), pedestal_g2(RAW_MODULE_SIZE) {} JFConversionFloatingPoint::JFConversionFloatingPoint(const DiffractionExperiment &experiment) : JFConversionFloatingPoint() { threshold = experiment.GetPixelValueLowThreshold(); summation = experiment.GetSummation(); pixel_signed = experiment.IsPixelSigned(); fixed_g1 = experiment.IsFixedGainG1(); if (experiment.GetByteDepthImage() == 2) { if (pixel_signed) { err_pixel = INT16_MIN; overload_pixel = INT16_MAX; overload_value = overload_pixel; } else { err_pixel = UINT16_MAX; overload_pixel = UINT16_MAX; overload_value = overload_pixel; } } else if (experiment.GetByteDepthImage() == 4) { if (pixel_signed) { err_pixel = INT32_MIN; overload_pixel = INT32_MAX; overload_value = INT24_MAX; } else { err_pixel = UINT32_MAX; overload_pixel = UINT32_MAX; overload_value = INT24_MAX; } } else if (experiment.GetByteDepthImage() == 1) { if (pixel_signed) { err_pixel = INT8_MIN; overload_pixel = INT8_MAX; overload_value = overload_pixel; } else { err_pixel = UINT8_MAX; overload_pixel = UINT8_MAX; overload_value = overload_pixel; } } } inline double one_over_gain_energy(double gain_factor, double energy) { double tmp = gain_factor * energy; if (!std::isfinite(tmp) || (tmp == 0.0)) return 0.0; else return static_cast(1.0 / (gain_factor * energy)); } void JFConversionFloatingPoint::Setup(const JFModuleGainCalibration &gain_calibration, const JFModulePedestal &in_pedestal_g0, const JFModulePedestal &in_pedestal_g1, const JFModulePedestal &in_pedestal_g2, double energy, bool using_gain_hg0) { memcpy(pedestal_g0.data(), in_pedestal_g0.GetPedestal(), RAW_MODULE_SIZE * sizeof(uint16_t)); memcpy(pedestal_g1.data(), in_pedestal_g1.GetPedestal(), RAW_MODULE_SIZE * sizeof(uint16_t)); memcpy(pedestal_g2.data(), in_pedestal_g2.GetPedestal(), RAW_MODULE_SIZE * sizeof(uint16_t)); auto &gain_arr = gain_calibration.GetGainCalibration(); for (int i = 0; i < RAW_MODULE_SIZE; i++) { if (using_gain_hg0) gain_g0[i] = one_over_gain_energy(gain_arr[i + 3 * RAW_MODULE_SIZE], energy); else gain_g0[i] = one_over_gain_energy(gain_arr[i], energy); if (fixed_g1) gain_g1[i] = one_over_gain_energy(gain_arr[i + RAW_MODULE_SIZE], energy) * -1.0 * JFModuleGainCalibration::fixed_g1_gain_coeff; else gain_g1[i] = one_over_gain_energy(gain_arr[i + RAW_MODULE_SIZE], energy); gain_g2[i] = one_over_gain_energy(gain_arr[i + 2 * RAW_MODULE_SIZE], energy); } } void JFConversionFloatingPoint::ConvertFP(double *dest, const uint16_t *source) { for (size_t i = 0; i < RAW_MODULE_SIZE; i++) { uint16_t gainbits = source[i] & 0xc000; uint16_t adc = source[i] & 0x3fff; int16_t pedestal_subtracted_adu; double expected = err_pixel; bool special_val = false; switch (gainbits) { case 0: pedestal_subtracted_adu = adc - pedestal_g0[i]; expected = static_cast(pedestal_subtracted_adu) * gain_g0[i]; if (fixed_g1 || (gain_g0[i] == 0.0) || (adc == 0x0000) || (adc == 0x3fff)) expected = err_pixel, special_val = true; break; case 0x4000: pedestal_subtracted_adu = adc - pedestal_g1[i]; expected = static_cast(pedestal_subtracted_adu) * gain_g1[i]; if (adc == 0x000) expected = err_pixel, special_val = true; if (fixed_g1 && (adc == 0x3fff)) expected = overload_pixel, special_val = true; if (gain_g1[i] == 0.0) expected = err_pixel, special_val = true; break; case 0xc000: pedestal_subtracted_adu = adc - pedestal_g2[i]; expected = static_cast(pedestal_subtracted_adu) * gain_g2[i]; if (fixed_g1 || (gain_g2[i] == 0.0) || (adc == 0x3fff)) expected = err_pixel, special_val = true; else if (adc == 0x0000) expected = overload_pixel, special_val = true; break; default: expected = err_pixel, special_val = true;; break; } if (threshold && (std::lround(expected) < threshold) && !special_val) expected = 0; if ((summation > 1) && !special_val) expected *= summation; if ((expected >= overload_value) && !special_val) expected = overload_pixel; if ((!pixel_signed) && (expected < 0)) dest[i] = 0; else dest[i] = expected; } }