Files
Jungfraujoch/common/AzimuthalIntegrationSettings.h
leonarski_f 7f2ebd8209
Build Packages / Build documentation (push) Successful in 46s
Build Packages / Create release (push) Successful in 8s
Build Packages / build:portable:macos-arm64:nocuda (push) Successful in 5m25s
Build Packages / build:rugnux:linux-aarch64:cuda (push) Successful in 9m46s
Build Packages / build:portable:linux-x86_64:nocuda (push) Successful in 13m25s
Build Packages / build:portable:linux-x86_64:cuda (push) Successful in 16m41s
Build Packages / build:portable:windows-x86_64:nocuda (push) Successful in 23m46s
Build Packages / HDF5 consumer tests (DIALS, XDS) (push) Successful in 25m37s
Build Packages / build:jfjoch:rocky8:nocuda (push) Successful in 24m31s
Build Packages / build:portable:windows-x86_64:cuda (push) Successful in 28m9s
Build Packages / build:jfjoch:ubuntu2204:nocuda (push) Successful in 20m47s
Build Packages / build:jfjoch:rocky9:nocuda (push) Successful in 26m21s
Build Packages / build:jfjoch:ubuntu2404:nocuda (push) Successful in 27m36s
Build Packages / Generate python client (push) Successful in 31s
Build Packages / build:jfjoch:rocky8:cuda-sls9 (push) Successful in 29m27s
Build Packages / build:jfjoch:rocky9:cuda-sls9 (push) Successful in 31m46s
Build Packages / build:jfjoch:ubuntu2204:cuda (push) Successful in 25m22s
Build Packages / build:jfjoch:rocky8:cuda (push) Successful in 30m36s
Build Packages / build:jfjoch:rocky9:cuda (push) Successful in 31m49s
Build Packages / build:jfjoch:ubuntu2404:cuda (push) Successful in 23m57s
Build Packages / Unit tests (push) Successful in 1h47m52s
Build Packages / Validation Battery (push) Successful in 44m55s
v1.0.0-rc.184 (#95)
* Rugnux: Rotation processing recovers most of the speed lost since 1.0.0-rc.180; live processing in jfjoch_broker finishes sooner.
* Rugnux: More reliable rotation processing and indexing, including small molecules and supercells.
* Rugnux: More robust serial data and model refinement; molecular replacement handles multi-chain models.
* jfjoch_broker (experimental): Live serial processing keeps the detector geometry fixed for the whole run.
* jfjoch_broker: Pixel sum without an FPGA, a mask bit for inactive pixels, and several stability fixes.
* jfjoch_broker: Rotation indexing and quick integration moved to rugnux live mode; their API settings are deprecated and ignored.
* jfjoch_broker, Rugnux: Azimuthal integration can use logarithmic (log10) Q bins or a given number of bins, set from the API, the web interface and the Rugnux command line.
* jfjoch_viewer: Build and display fixes; the README is rewritten.

Reviewed-on: #95
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-11-10 22:06:51 +01:00

92 lines
4.6 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include "JFJochMath.h"
#include <optional>
#include <cstdint>
#include <vector>
// How the Q bins are laid out between low and high Q: equal steps in Q, or equal steps in log10(Q) -
// fine bins at low Q and coarse ones at high Q, for scattering whose features are at low Q.
enum class QBinSpacing {Linear, Log10};
class AzimuthalIntegrationSettings {
constexpr static float minQ_recipA = 1e-5;
constexpr static float maxQ_recipA = 10.0;
bool solid_angle_correction = true;
bool polarization_correction = true;
// Requested upper q limit. Unset means "as far as the detector reaches": DiffractionExperiment
// resolves it from the geometry (ResolveHighQ) whenever it hands these settings out, so
// high_q_recipA below - what the bins are built from - is always a concrete number. Not clipping
// detection at an arbitrary default matters for the adaptive spot finder, which bins pixels through
// this same q range and cannot see a pixel that falls outside it.
std::optional<float> requested_high_q_recipA;
float high_q_recipA = 5.0;
float low_q_recipA = 0.1;
float bkg_estimate_high_q_recipA = 2.0f * PI / 3.0;
float bkg_estimate_low_q_recipA = 2.0f * PI / 5.0;
QBinSpacing q_bin_spacing = QBinSpacing::Linear;
// Linear binning is given either by its Q spacing or by its number of Q bins; log10 binning only
// by the number of bins. Unset number: the spacing sets the bins.
float q_spacing = 0.01;
std::optional<int32_t> requested_q_bins;
// Width of a bin in the variable the bins are equally spaced in: Q, or log10(Q).
float bin_step = 0.01;
int32_t azim_bins = 1;
// Compute azimuthal integration on the CPU instead of the FPGA during the FPGA
// acquisition workflow. Lifts the FPGA bin-count limit and adds standard-deviation output.
bool force_cpu_in_fpga_workflow = false;
int32_t q_bins= 0;
int32_t total_bins = 0;
void UpdateBinCount();
// Where q falls on the bin scale: bin i spans [i, i + 1).
[[nodiscard]] float BinCoordinate(float q) const;
public:
AzimuthalIntegrationSettings();
AzimuthalIntegrationSettings& SolidAngleCorrection(bool input);
AzimuthalIntegrationSettings& PolarizationCorrection(bool input);
AzimuthalIntegrationSettings& QRange_recipA(float low, std::optional<float> high);
// Substitute the detector's own maximum q for an unset high q. No-op if one was requested.
void ResolveHighQ(float detector_max_q_recipA);
// Linear binning with this Q spacing.
AzimuthalIntegrationSettings& QSpacing_recipA(float input);
// Linear: exactly one of spacing and bin count may be given (neither keeps the current spacing).
// Log10: the bin count is required and a spacing is refused.
AzimuthalIntegrationSettings& QBinning(QBinSpacing type, std::optional<float> spacing,
std::optional<int32_t> q_bin_count);
AzimuthalIntegrationSettings& BkgEstimateQRange_recipA(float low, float high);
AzimuthalIntegrationSettings& AzimuthalBinCount(int32_t input);
AzimuthalIntegrationSettings& ForceCPUinFPGAWorkflow(bool input);
[[nodiscard]] bool IsSolidAngleCorrection() const;
[[nodiscard]] bool IsPolarizationCorrection() const;
[[nodiscard]] float GetHighQ_recipA() const;
[[nodiscard]] std::optional<float> GetRequestedHighQ_recipA() const;
[[nodiscard]] float GetLowQ_recipA() const;
// The width of a linear bin (as given, or as the bin count makes it). Under log10 binning it is the
// last linear spacing and means nothing about the bins - use GetQBinCentres_recipA.
[[nodiscard]] float GetQSpacing_recipA() const;
[[nodiscard]] QBinSpacing GetQBinSpacing() const;
// The spacing and the bin count as they were given; one of them is unset.
[[nodiscard]] std::optional<float> GetRequestedQSpacing_recipA() const;
[[nodiscard]] std::optional<int32_t> GetRequestedQBinCount() const;
// Centre of every Q bin: the mid-point of its edges on the bin scale.
[[nodiscard]] std::vector<double> GetQBinCentres_recipA() const;
[[nodiscard]] int32_t GetBinCount() const;
[[nodiscard]] int32_t GetQBinCount() const;
[[nodiscard]] int32_t GetAzimuthalBinCount() const;
[[nodiscard]] bool IsForceCPUinFPGAWorkflow() const;
[[nodiscard]] float GetBkgEstimateLowQ_recipA() const;
[[nodiscard]] float GetBkgEstimateHighQ_recipA() const;
[[nodiscard]] uint16_t QToBin(float q) const;
[[nodiscard]] uint16_t GetBin(float q, float phi_deg) const;
};