// Copyright (2019-2023) Paul Scherrer Institute #include "JFConversionFloatingPoint.h" #include "../common/RawToConvertedGeometry.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) {} inline float 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) { auto &gain_arr = gain_calibration.GetGainCalibration(); 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)); for (int i = 0; i < RAW_MODULE_SIZE; i++) { gain_g0[i] = one_over_gain_energy(gain_arr[i], energy); 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::ConvertModule(int16_t *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; float expected = PIXEL_OUT_LOST; switch (gainbits) { case 0: [[likely]] pedestal_subtracted_adu = adc - pedestal_g0[i]; expected = static_cast(pedestal_subtracted_adu) * gain_g0[i]; if (gain_g0[i] == 0.0) expected = INT16_MIN; break; case 0x4000: pedestal_subtracted_adu = adc - pedestal_g1[i]; expected = static_cast(pedestal_subtracted_adu) * gain_g1[i]; if (adc == 0) [[unlikely]] expected = PIXEL_OUT_G1_SATURATION; if (gain_g1[i] == 0.0) expected = INT16_MIN; break; case 0xc000: pedestal_subtracted_adu = adc - pedestal_g2[i]; expected = static_cast(pedestal_subtracted_adu) * gain_g2[i]; if (adc == 0) [[unlikely]] expected = PIXEL_OUT_SATURATION; else if (adc == 0x3fff) [[unlikely]] expected = PIXEL_OUT_0xFFFF; if (gain_g0[i] == 0.0) expected = INT16_MIN; break; default: expected = PIXEL_OUT_GAINBIT_2; break; } if (expected == INT16_MIN) dest[i] = PIXEL_OUT_LOST; else if (expected > INT16_MAX) dest[i] = INT16_MAX; else if (expected >= 0.0) [[likely]] dest[i] = static_cast(expected + 0.5f); else dest[i] = static_cast(expected - 0.5f); } } void JFConversionFloatingPoint::ConvertFP(float *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; float expected = PIXEL_OUT_LOST; 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 (gain_g0[i] == 0.0) expected = INT16_MIN, special_val = true; break; case 0x4000: pedestal_subtracted_adu = adc - pedestal_g1[i]; expected = static_cast(pedestal_subtracted_adu) * gain_g1[i]; if (adc == 0) expected = PIXEL_OUT_G1_SATURATION, special_val = true; if (gain_g1[i] == 0.0) expected = INT16_MIN, special_val = true; break; case 0xc000: pedestal_subtracted_adu = adc - pedestal_g2[i]; expected = static_cast(pedestal_subtracted_adu) * gain_g2[i]; if (adc == 0) expected = PIXEL_OUT_SATURATION, special_val = true; else if (adc == 0x3fff) expected = PIXEL_OUT_0xFFFF, special_val = true; if (gain_g2[i] == 0.0) expected = INT16_MIN, special_val = true; break; default: expected = PIXEL_OUT_GAINBIT_2, special_val = true;; break; } if ((expected > PIXEL_OUT_SATURATION) && !special_val) expected = PIXEL_OUT_SATURATION; dest[i] = expected; } }