Files
Jungfraujoch/common/ScanResultGenerator.cpp
T
leonarski_f d6389e12da
Build Packages / Unit tests (push) Skipped
Build Packages / build:windows:nocuda (push) Successful in 15m31s
Build Packages / build:viewer-tgz:cpu (push) Successful in 5m46s
Build Packages / build:viewer-tgz:cuda (push) Successful in 6m9s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 9m25s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 10m21s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 9m41s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 9m18s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 10m26s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 11m33s
Build Packages / build:rpm (rocky8) (push) Successful in 10m32s
Build Packages / build:rpm (rocky9) (push) Successful in 12m23s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m50s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 10m12s
Build Packages / DIALS test (push) Successful in 12m6s
Build Packages / XDS test (durin plugin) (push) Successful in 8m15s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m12s
Build Packages / XDS test (neggia plugin) (push) Successful in 5m35s
Build Packages / Generate python client (push) Successful in 27s
Build Packages / Build documentation (push) Successful in 54s
Build Packages / Create release (push) Skipped
Build Packages / build:windows:cuda (push) Successful in 12m37s
v1.0.0-rc.156 (#66)
This is an UNSTABLE release. It includes many experimental features, as well as many AI generated fixes. We recommend using rc.152 for production use.

* jfjoch_process: Major rotation (rot3d) data processing overhaul - robust profile-fit integration, Cauchy-loss scaling with optional absorption surface, de-novo indexing and space-group/centering determination fixes, and merging statistics + ISa in the mmCIF output.
* jfjoch_process: Add EXPERIMENTAL ice-ring detection (--detect-ice-rings) that excludes ice reflections from scaling.
* Compression: Add BSHUF_ZSTD_RLE_HUFF, make compression size-aware (drop frames that don't fit rather than aborting), and add the jfjoch_recompress tool.
* jfjoch_viewer: Report "Multiple lattices detected" and grey out "Analyze dataset" on a live connection.
* jfjoch_broker: Write smargon chi/phi goniometer positions to NXmx; read sensor thickness/material from HDF5 metadata.
* CI: Build Windows (CUDA and non-CUDA) installers.Reviewed-on: #66

Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-07-03 19:18:56 +02:00

145 lines
6.3 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include <algorithm>
#include <cmath>
#include "ScanResultGenerator.h"
namespace {
template<class T>
T value_or_zero(const std::optional<T>& v) {
return v.value_or(static_cast<T>(0));
}
}
ScanResultGenerator::ScanResultGenerator(const DiffractionExperiment &experiment) {
grid_scan = experiment.GetGridScan();
goniometer_axis = experiment.GetGoniometer();
if (grid_scan)
v.resize(grid_scan->GetNElem());
else
v.resize(experiment.GetImageNum());
file_prefix = experiment.GetFilePrefix();
}
void ScanResultGenerator::Add(const DataMessage &message) {
std::unique_lock ul(m);
int64_t image_number = message.number;
if (grid_scan)
image_number = grid_scan->Rearrange(image_number);
if (image_number >= 0 && static_cast<size_t>(image_number) < v.size()) {
if (grid_scan) {
v[image_number].x = grid_scan->GetElementPosX_step(message.number);
v[image_number].y = grid_scan->GetElementPosY_step(message.number);
} else if (goniometer_axis) {
v[image_number].angle_deg = goniometer_axis->GetAngle_deg(message.number);
}
v[image_number].number = message.number;
v[image_number].pixel_sum = message.pixel_sum;
v[image_number].collection_efficiency = message.image_collection_efficiency.value_or(1.0);
v[image_number].bkg = message.bkg_estimate;
v[image_number].spot_count = message.spot_count;
v[image_number].indexing_solution = message.indexing_result;
v[image_number].indexed_lattice_count = message.indexing_lattice_count;
v[image_number].profile_radius = message.profile_radius;
v[image_number].mosaicity = message.mosaicity_deg;
v[image_number].b_factor = message.b_factor;
v[image_number].uc = message.indexing_unit_cell;
v[image_number].xfel_pulse_id = message.xfel_pulse_id;
v[image_number].err_pixels = message.error_pixel_count;
v[image_number].min_viable_pixel = message.min_viable_pixel_value;
v[image_number].max_viable_pixel = message.max_viable_pixel_value;
v[image_number].sat_pixels = message.saturated_pixel_count;
v[image_number].spot_count_ice = message.spot_count_ice_rings;
v[image_number].spot_count_low_res = message.spot_count_low_res;
v[image_number].spot_count_indexed = message.spot_count_indexed;
v[image_number].res = message.resolution_estimate;
v[image_number].integrated_reflections = message.integrated_reflections;
v[image_number].image_scale_factor = message.image_scale_factor;
v[image_number].image_scale_cc = message.image_scale_cc;
v[image_number].ice_ring_score = message.ice_ring_score;
if (message.lattice_type)
v[image_number].niggli_class = message.lattice_type->niggli_class;
}
}
ScanResult ScanResultGenerator::GetResult() const {
std::unique_lock ul(m);
ScanResult ret;
ret.file_prefix = file_prefix;
ret.images = v;
return ret;
}
void ScanResultGenerator::FillEndMessage(EndMessage &message) const {
std::unique_lock ul(m);
size_t n = 0;
for (const auto &e: v) {
if (e.number >= 0)
n = std::max(n, static_cast<size_t>(e.number) + 1);
}
if (n == 0)
return;
message.data_collection_efficiency.resize(n);
message.spot_count.resize(n);
message.spot_count_ice_ring.resize(n);
message.spot_count_low_res.resize(n);
message.spot_count_indexed.resize(n);
message.image_indexed.resize(n);
message.v_bkg_estimate.resize(n);
message.profile_radius.resize(n);
message.mosaicity.resize(n);
message.bFactor.resize(n);
message.resolution_estimate.resize(n);
message.min_viable_pixel_value.resize(n);
message.max_viable_pixel_value.resize(n);
message.saturated_pixel_count.resize(n);
message.error_pixel_count.resize(n);
message.image_scale_factor.resize(n);
message.image_scale_cc.resize(n);
message.ice_ring_score.resize(n);
message.integrated_reflections.resize(n);
message.niggli_class.resize(n);
message.pixel_sum.resize(n);
message.indexed_lattice_count.resize(n);
for (const auto &e: v) {
if (e.number < 0)
continue;
const auto number = static_cast<size_t>(e.number);
if (number >= n)
continue;
message.data_collection_efficiency[number] = e.collection_efficiency;
message.spot_count[number] = static_cast<int32_t>(value_or_zero(e.spot_count));
message.spot_count_ice_ring[number] = static_cast<int32_t>(value_or_zero(e.spot_count_ice));
message.spot_count_low_res[number] = static_cast<int32_t>(value_or_zero(e.spot_count_low_res));
message.spot_count_indexed[number] = static_cast<int32_t>(value_or_zero(e.spot_count_indexed));
message.image_indexed[number] = static_cast<uint8_t>(e.indexing_solution.value_or(0));
message.v_bkg_estimate[number] = e.bkg.value_or(NAN);
message.profile_radius[number] = e.profile_radius.value_or(NAN);
message.mosaicity[number] = e.mosaicity.value_or(NAN);
message.bFactor[number] = e.b_factor.value_or(NAN);
message.resolution_estimate[number] = e.res.value_or(NAN);
message.min_viable_pixel_value[number] = value_or_zero(e.min_viable_pixel);
message.max_viable_pixel_value[number] = value_or_zero(e.max_viable_pixel);
message.saturated_pixel_count[number] = static_cast<int32_t>(value_or_zero(e.sat_pixels));
message.error_pixel_count[number] = static_cast<int32_t>(value_or_zero(e.err_pixels));
message.image_scale_factor[number] = e.image_scale_factor.value_or(NAN);
message.image_scale_cc[number] = e.image_scale_cc.value_or(NAN);
message.ice_ring_score[number] = e.ice_ring_score.value_or(NAN);
message.integrated_reflections[number] = static_cast<int32_t>(value_or_zero(e.integrated_reflections));
message.niggli_class[number] = static_cast<uint8_t>(value_or_zero(e.niggli_class));
message.pixel_sum[number] = value_or_zero(e.pixel_sum);
message.indexed_lattice_count[number] = static_cast<int32_t>(value_or_zero(e.indexed_lattice_count));
}
}