101 lines
3.7 KiB
C++
101 lines
3.7 KiB
C++
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include "ImageMetadata.h"
|
|
#include <cmath>
|
|
|
|
inline uint64_t convert_pulse_id(double pulse_id) {
|
|
if (!std::isfinite(pulse_id))
|
|
return UINT64_MAX;
|
|
double integer_part;
|
|
double fractional_part = std::modf(pulse_id, &integer_part);
|
|
if (fractional_part != 0.0)
|
|
return UINT64_MAX;
|
|
return static_cast<uint64_t>(integer_part);
|
|
}
|
|
|
|
ImageMetadata::ImageMetadata(const DiffractionExperiment &experiment)
|
|
: pulsed_source(experiment.IsPulsedSource()) {
|
|
roi_map_name = experiment.ROI().GetROINameMap();
|
|
for (const auto &[x,y]: roi_map_name)
|
|
rois[x] = ROIMessage{.max_count = INT64_MIN};
|
|
}
|
|
|
|
void ImageMetadata::Process(const DeviceOutput *output) {
|
|
std::unique_lock ul(m);
|
|
|
|
uint64_t module_pulse_id = convert_pulse_id(output->module_statistics.pulse_id);
|
|
if (!first_module_loaded) {
|
|
xfel_pulse_id = module_pulse_id;
|
|
jf_info = output->module_statistics.debug;
|
|
storage_cell = (jf_info >> 8) & 0xF;
|
|
xfel_event_code = (jf_info >> 16) & UINT8_MAX;
|
|
timestamp = output->module_statistics.timestamp;
|
|
exptime = output->module_statistics.exptime;
|
|
max_value = INT64_MIN;
|
|
min_value = INT64_MAX;
|
|
|
|
first_module_loaded = true;
|
|
} else {
|
|
if (pulsed_source && (module_pulse_id != xfel_pulse_id)) {
|
|
metadata_consistent = false;
|
|
xfel_pulse_id = UINT64_MAX; // mark clearly inconsistent frames
|
|
}
|
|
}
|
|
saturated_pixels += output->module_statistics.saturated_pixels;
|
|
error_pixels += output->module_statistics.err_pixels;
|
|
strong_pixels += output->spot_finding_result.strong_pixel_count;
|
|
packets_collected += output->module_statistics.packet_count;
|
|
|
|
if (output->module_statistics.max_value > max_value)
|
|
max_value = output->module_statistics.max_value;
|
|
|
|
if (output->module_statistics.load_calibration_destination < min_value)
|
|
min_value = output->module_statistics.load_calibration_destination;
|
|
|
|
for (const auto &[key, val]: roi_map_name) {
|
|
rois[key].sum += output->roi_counts[val].sum;
|
|
rois[key].sum_square += output->roi_counts[val].sum2;
|
|
rois[key].pixels += output->roi_counts[val].good_pixels;
|
|
if (output->roi_counts[val].max_value > rois[key].max_count)
|
|
rois[key].max_count = output->roi_counts[val].max_value;
|
|
}
|
|
}
|
|
|
|
bool ImageMetadata::IsBunchIDConsistent() const {
|
|
return metadata_consistent;
|
|
}
|
|
|
|
void ImageMetadata::Export(DataMessage &message, uint64_t packets_expected_per_image) const {
|
|
std::unique_lock ul(m);
|
|
|
|
if (pulsed_source) {
|
|
message.xfel_pulse_id = xfel_pulse_id;
|
|
message.xfel_event_code = xfel_event_code;
|
|
}
|
|
message.jf_info = jf_info;
|
|
message.storage_cell = storage_cell;
|
|
message.timestamp = timestamp;
|
|
message.timestamp_base = 10*1000*1000;
|
|
message.exptime = exptime;
|
|
message.exptime_base = 10*1000*1000;
|
|
message.saturated_pixel_count = saturated_pixels;
|
|
message.error_pixel_count = error_pixels;
|
|
message.strong_pixel_count = strong_pixels;
|
|
message.packets_received = packets_collected;
|
|
message.packets_expected = packets_expected_per_image;
|
|
|
|
if (min_value != INT64_MAX)
|
|
message.min_viable_pixel_value = min_value;
|
|
if (max_value != INT64_MIN)
|
|
message.max_viable_pixel_value = max_value;
|
|
|
|
if ((packets_collected > 0) && (packets_expected_per_image > 0))
|
|
message.image_collection_efficiency = static_cast<double>(packets_collected)
|
|
/ static_cast<double>(packets_expected_per_image);
|
|
else
|
|
message.image_collection_efficiency = 0.0f;
|
|
|
|
message.roi = rois;
|
|
}
|