Files
Jungfraujoch/jungfrau/JFConversionFloatingPoint.cpp

155 lines
6.0 KiB
C++

// Copyright (2019-2023) Paul Scherrer Institute
#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() {
summation = experiment.GetSummation();
pixel_signed = experiment.IsPixelSigned();
if (experiment.GetPixelDepth() == 2) {
if (pixel_signed) {
err_pixel = INT16_MIN;
overload_pixel = INT16_MAX;
} else {
err_pixel = UINT16_MAX;
overload_pixel = UINT16_MAX;
}
} else if (experiment.GetPixelDepth() == 4) {
if (pixel_signed) {
err_pixel = INT32_MIN;
overload_pixel = INT32_MAX;
} else {
err_pixel = UINT32_MAX;
overload_pixel = UINT32_MAX;
}
}
}
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) {
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;
double expected = PIXEL_OUT_LOST;
switch (gainbits) {
case 0:
[[likely]]
pedestal_subtracted_adu = adc - pedestal_g0[i];
expected = static_cast<double>(pedestal_subtracted_adu) * gain_g0[i];
if (gain_g0[i] == 0.0)
expected = err_pixel;
break;
case 0x4000:
pedestal_subtracted_adu = adc - pedestal_g1[i];
expected = static_cast<double>(pedestal_subtracted_adu) * gain_g1[i];
if (adc == 0) [[unlikely]] expected = err_pixel;
if (gain_g1[i] == 0.0)
expected = err_pixel;
break;
case 0xc000:
pedestal_subtracted_adu = adc - pedestal_g2[i];
expected = static_cast<double>(pedestal_subtracted_adu) * gain_g2[i];
if (adc == 0) [[unlikely]] expected = overload_pixel;
else if (adc == 0x3fff) [[unlikely]] expected = err_pixel;
if (gain_g0[i] == 0.0)
expected = err_pixel;
break;
default:
expected = err_pixel;
break;
}
if (expected == err_pixel)
dest[i] = err_pixel;
else if (expected > overload_pixel)
dest[i] = overload_pixel;
else if (expected >= 0.0)
[[likely]]
dest[i] = static_cast<uint16_t>(expected + 0.5f);
else
dest[i] = static_cast<uint16_t>(expected - 0.5f);
}
}
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 (gain_g0[i] == 0.0)
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 == 0) expected = err_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 (adc == 0) expected = overload_pixel, special_val = true;
else if (adc == 0x3fff) expected = err_pixel, special_val = true;
if (gain_g2[i] == 0.0)
expected = err_pixel, special_val = true;
break;
default:
expected = err_pixel, special_val = true;;
break;
}
if ((summation > 1) && !special_val)
expected *= summation;
if ((expected > overload_pixel) && !special_val)
expected = overload_pixel;
if ((!pixel_signed) && (expected < 0))
dest[i] = 0;
else
dest[i] = expected;
}
}