Broker: Q binning settings through the API and the config JSON
q_binning (linear|log10) and q_bins are read and returned; q_spacing is now optional. Linear binning takes q_spacing or q_bins, not both (neither keeps the 0.01 1/A default); log10 needs q_bins and refuses q_spacing; a refused combination is a 400 with the reason. GET returns the spacing or the bin count that was set, and the binning. Clients that send only q_spacing work unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK
This commit is contained in:
1 parent
bf1461acd5
commit
d0a7d6a314
2 files changed
+88
-2
No files matched your search
@@ -450,7 +450,13 @@ AzimuthalIntegrationSettings Convert(const org::openapitools::server::model::Azi
|
||||
AzimuthalIntegrationSettings ret{};
|
||||
ret.SolidAngleCorrection(input.isSolidAngleCorr());
|
||||
ret.PolarizationCorrection(input.isPolarizationCorr());
|
||||
ret.QSpacing_recipA(input.getQSpacing());
|
||||
QBinSpacing spacing = QBinSpacing::Linear;
|
||||
if (input.qBinningIsSet()
|
||||
&& input.getQBinning().getValue() == org::openapitools::server::model::Q_binning::eQ_binning::LOG10)
|
||||
spacing = QBinSpacing::Log10;
|
||||
ret.QBinning(spacing,
|
||||
input.qSpacingIsSet() ? std::optional<float>(input.getQSpacing()) : std::nullopt,
|
||||
input.qBinsIsSet() ? std::optional<int32_t>(input.getQBins()) : std::nullopt);
|
||||
ret.QRange_recipA(input.getLowQRecipA(),
|
||||
input.highQRecipAIsSet() ? std::optional<float>(input.getHighQRecipA())
|
||||
: std::nullopt);
|
||||
@@ -466,7 +472,15 @@ org::openapitools::server::model::Azim_int_settings Convert(const AzimuthalInteg
|
||||
if (const auto high_q = settings.GetRequestedHighQ_recipA())
|
||||
ret.setHighQRecipA(high_q.value());
|
||||
ret.setLowQRecipA(settings.GetLowQ_recipA());
|
||||
ret.setQSpacing(settings.GetQSpacing_recipA());
|
||||
if (const auto q_spacing = settings.GetRequestedQSpacing_recipA())
|
||||
ret.setQSpacing(q_spacing.value());
|
||||
if (const auto q_bins = settings.GetRequestedQBinCount())
|
||||
ret.setQBins(q_bins.value());
|
||||
org::openapitools::server::model::Q_binning q_binning;
|
||||
q_binning.setValue(settings.GetQBinSpacing() == QBinSpacing::Log10
|
||||
? org::openapitools::server::model::Q_binning::eQ_binning::LOG10
|
||||
: org::openapitools::server::model::Q_binning::eQ_binning::LINEAR);
|
||||
ret.setQBinning(q_binning);
|
||||
ret.setAzimuthalBins(settings.GetAzimuthalBinCount());
|
||||
ret.setForceCpu(settings.IsForceCPUinFPGAWorkflow());
|
||||
return ret;
|
||||
|
||||
@@ -1262,3 +1262,75 @@ TEST_CASE("DiffractionExperiment_GridScanAtStationaryAxis", "[DiffractionExperim
|
||||
CHECK(!settings.GetGoniometer()->IsScanning());
|
||||
CHECK(settings.GetGoniometer()->GetStart_deg() == Catch::Approx(90.0f));
|
||||
}
|
||||
|
||||
// The Q binning through the OpenAPI model, both ways. A client that only knows q_spacing keeps
|
||||
// working, and what comes back is what was set.
|
||||
TEST_CASE("DiffractionExperiment_AzIntegration_QBinning_OpenAPI", "[DiffractionExperiment]") {
|
||||
auto parse = [](const char *json) {
|
||||
org::openapitools::server::model::Azim_int_settings model;
|
||||
from_json(nlohmann::json::parse(json), model);
|
||||
return model;
|
||||
};
|
||||
|
||||
SECTION("Linear by spacing, as before") {
|
||||
const auto s = Convert(parse(R"({"solid_angle_corr": true, "polarization_corr": true,
|
||||
"low_q_recipA": 0.1, "high_q_recipA": 4.0, "q_spacing": 0.00087})"));
|
||||
CHECK(s.GetQBinSpacing() == QBinSpacing::Linear);
|
||||
CHECK(s.GetQSpacing_recipA() == 0.00087f);
|
||||
CHECK(s.GetQBinCount() == static_cast<int32_t>(std::ceil((4.0f - 0.1f) / 0.00087f)));
|
||||
const auto back = Convert(s);
|
||||
REQUIRE(back.qSpacingIsSet());
|
||||
CHECK(back.getQSpacing() == 0.00087f);
|
||||
CHECK(!back.qBinsIsSet());
|
||||
CHECK(back.getQBinning().getValue() == org::openapitools::server::model::Q_binning::eQ_binning::LINEAR);
|
||||
}
|
||||
|
||||
SECTION("Neither spacing nor bin count: default spacing") {
|
||||
const auto s = Convert(parse(R"({"solid_angle_corr": true, "polarization_corr": true,
|
||||
"low_q_recipA": 0.1, "high_q_recipA": 4.0})"));
|
||||
CHECK(s.GetQSpacing_recipA() == 0.01f);
|
||||
CHECK(s.GetQBinCount() == static_cast<int32_t>(std::ceil((4.0f - 0.1f) / 0.01f)));
|
||||
}
|
||||
|
||||
SECTION("Linear by bin count") {
|
||||
const auto s = Convert(parse(R"({"solid_angle_corr": true, "polarization_corr": true,
|
||||
"low_q_recipA": 0.1, "high_q_recipA": 4.1, "q_bins": 80})"));
|
||||
CHECK(s.GetQBinCount() == 80);
|
||||
CHECK(s.GetQSpacing_recipA() == Catch::Approx(0.05));
|
||||
const auto back = Convert(s);
|
||||
CHECK(!back.qSpacingIsSet());
|
||||
REQUIRE(back.qBinsIsSet());
|
||||
CHECK(back.getQBins() == 80);
|
||||
}
|
||||
|
||||
SECTION("Log10") {
|
||||
const auto s = Convert(parse(R"({"solid_angle_corr": true, "polarization_corr": true,
|
||||
"low_q_recipA": 0.001, "high_q_recipA": 1.0,
|
||||
"q_binning": "log10", "q_bins": 300})"));
|
||||
CHECK(s.GetQBinSpacing() == QBinSpacing::Log10);
|
||||
CHECK(s.GetQBinCount() == 300);
|
||||
const auto back = Convert(s);
|
||||
CHECK(back.getQBinning().getValue() == org::openapitools::server::model::Q_binning::eQ_binning::LOG10);
|
||||
CHECK(!back.qSpacingIsSet());
|
||||
CHECK(back.getQBins() == 300);
|
||||
|
||||
// Through a DiffractionExperiment, which is how the broker keeps them.
|
||||
DiffractionExperiment x;
|
||||
x.ImportAzimuthalIntegrationSettings(s);
|
||||
CHECK(x.GetAzimuthalIntegrationSettings().GetQBinSpacing() == QBinSpacing::Log10);
|
||||
CHECK(Convert(x.GetAzimuthalIntegrationSettings()).getQBins() == 300);
|
||||
}
|
||||
|
||||
SECTION("Refused combinations") {
|
||||
CHECK_THROWS_WITH(Convert(parse(R"({"solid_angle_corr": true, "polarization_corr": true,
|
||||
"low_q_recipA": 0.1, "q_spacing": 0.01, "q_bins": 100})")),
|
||||
Catch::Matchers::ContainsSubstring("not both"));
|
||||
CHECK_THROWS_WITH(Convert(parse(R"({"solid_angle_corr": true, "polarization_corr": true,
|
||||
"low_q_recipA": 0.1, "q_binning": "log10"})")),
|
||||
Catch::Matchers::ContainsSubstring("needs the number of Q bins"));
|
||||
CHECK_THROWS_WITH(Convert(parse(R"({"solid_angle_corr": true, "polarization_corr": true,
|
||||
"low_q_recipA": 0.1, "q_binning": "log10",
|
||||
"q_spacing": 0.01, "q_bins": 100})")),
|
||||
Catch::Matchers::ContainsSubstring("only to linear"));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user