138 lines
5.5 KiB
C++
138 lines
5.5 KiB
C++
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include <cstring>
|
|
|
|
#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<float>(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<double>(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<double>(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<double>(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;
|
|
}
|
|
}
|