The low-Q headroom check and the detector-edge high Q are floored by the linear spacing only where one was given, and by the smallest allowed Q otherwise, instead of by a spacing log10 bins do not use. GetQSpacing_recipA says that under log10 it means nothing about the bins. GetQBinEdges_recipA, which only the tests used, is dropped: the tests state the edges from the documented formula. A test pins the far-edge clamp of linear-by-spacing bins on a two-row setting. The broker docs note that a GET carries q_bins and no q_spacing once bins are configured. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK
92 lines
4.6 KiB
C++
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;
|
|
};
|
|
|