Live stills: the q range stays fixed when the running refinement moves the geometry
An azimuthal q range with no high limit reaches the detector's edge, which depends on the distance. When the running geometry refinement moved the distance, the rebuilt mapping could have a different number of bins from the start message and the run's profile. Adding the next frame's profile then threw "Error combining two radial integration profiles" and cancelled the collection. The q range is now frozen at its current value when the geometry moves. The replay tool adds up the frames' profiles as the receiver does, so this path is exercised there; it ignored them before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c407e690fd
commit
df861de7fb
4 files changed
+51
-3
No files matched your search
@@ -337,6 +337,13 @@ void StillsGPUAnalysis::AnalysisThread() {
|
||||
}
|
||||
}
|
||||
|
||||
void MoveStillsGeometry(DiffractionExperiment &experiment, float beam_x_pxl, float beam_y_pxl, float distance_mm) {
|
||||
AzimuthalIntegrationSettings azint = experiment.GetAzimuthalIntegrationSettings();
|
||||
azint.QRange_recipA(azint.GetLowQ_recipA(), azint.GetHighQ_recipA());
|
||||
experiment.ImportAzimuthalIntegrationSettings(azint);
|
||||
experiment.BeamX_pxl(beam_x_pxl).BeamY_pxl(beam_y_pxl).DetectorDistance_mm(distance_mm);
|
||||
}
|
||||
|
||||
void StillsGPUAnalysis::SwitchGeometry() {
|
||||
// One fit, in the analysis thread that offered the last frame it needed; the others go on meanwhile.
|
||||
const auto t0 = std::chrono::steady_clock::now();
|
||||
@@ -361,8 +368,8 @@ void StillsGPUAnalysis::SwitchGeometry() {
|
||||
}
|
||||
{
|
||||
std::unique_lock ul(geometry_mutex);
|
||||
setup.experiment.BeamX_pxl(static_cast<float>(r->beam_x_px)).BeamY_pxl(static_cast<float>(r->beam_y_px))
|
||||
.DetectorDistance_mm(static_cast<float>(r->distance_mm));
|
||||
MoveStillsGeometry(setup.experiment, static_cast<float>(r->beam_x_px), static_cast<float>(r->beam_y_px),
|
||||
static_cast<float>(r->distance_mm));
|
||||
retired_mappings.push_back(std::move(setup.mapping));
|
||||
setup.mapping = std::make_unique<AzimuthalIntegrationMapping>(setup.experiment, setup.mask);
|
||||
++geometry_epoch;
|
||||
|
||||
@@ -51,6 +51,10 @@
|
||||
// switches to that geometry as each of GEOMETRY_ROUNDS fits is made. The frames analysed before the last
|
||||
// switch are not merged (their reflections were predicted at an earlier geometry; the images are gone); where
|
||||
// no fit can be made they are merged as analysed.
|
||||
// Moves the analysis to a refined geometry during the run. The q range stays where it was, also one left to
|
||||
// reach the detector's edge: the start message and the run's profile are binned on it.
|
||||
void MoveStillsGeometry(DiffractionExperiment &experiment, float beam_x_pxl, float beam_y_pxl, float distance_mm);
|
||||
|
||||
class StillsGPUAnalysis {
|
||||
public:
|
||||
// Enough frames for the distance to be refined at a serial hit rate: of 100 frames of a collection indexed
|
||||
|
||||
@@ -125,3 +125,30 @@ TEST_CASE("StillsGPUAnalysis_FailingFrameDoesNotStopAnalysis", "[StillsGPUAnalys
|
||||
CHECK(s.steps.back().duration_s);
|
||||
CHECK(buffer.GetStatus().preparation_slots == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("StillsGPUAnalysis_MovedGeometryKeepsTheProfileBins", "[StillsGPUAnalysis]") {
|
||||
DiffractionExperiment x = StillsExperiment();
|
||||
const PixelMask mask(x);
|
||||
const AzimuthalIntegrationMapping before(x, mask);
|
||||
AzimuthalIntegrationProfile run_profile(before);
|
||||
|
||||
// Left to itself the high q follows the detector's edge, and with it the number of bins.
|
||||
DiffractionExperiment unfrozen = x;
|
||||
unfrozen.DetectorDistance_mm(120);
|
||||
REQUIRE(AzimuthalIntegrationMapping(unfrozen, mask).GetBinNumber() != before.GetBinNumber());
|
||||
|
||||
MoveStillsGeometry(x, 510, 260, 120);
|
||||
CHECK(x.GetDetectorDistance_mm() == Catch::Approx(120));
|
||||
CHECK(x.GetBeamX_pxl() == Catch::Approx(510));
|
||||
CHECK(x.GetBeamY_pxl() == Catch::Approx(260));
|
||||
|
||||
const AzimuthalIntegrationMapping after(x, mask);
|
||||
CHECK(after.GetBinNumber() == before.GetBinNumber());
|
||||
CHECK(after.GetBinToQ() == before.GetBinToQ());
|
||||
const AzimuthalIntegrationProfile frame_profile(after);
|
||||
CHECK_NOTHROW(run_profile += frame_profile);
|
||||
|
||||
// A second move stays on the same bins.
|
||||
MoveStillsGeometry(x, 505, 255, 90);
|
||||
CHECK(AzimuthalIntegrationMapping(x, mask).GetBinToQ() == before.GetBinToQ());
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <getopt.h>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include "../common/ImageBuffer.h"
|
||||
#include "../common/Logger.h"
|
||||
@@ -142,9 +144,12 @@ int main(int argc, char **argv) {
|
||||
const auto t0 = std::chrono::steady_clock::now();
|
||||
{
|
||||
// As the receiver: half the buffer for the frames waiting, the other half for those sent.
|
||||
std::mutex run_profile_mutex;
|
||||
std::unique_ptr<AzimuthalIntegrationProfile> run_profile;
|
||||
StillsGPUAnalysis gpu(x, mask, start, &pool, nthreads, buffer.GetStatus().total_slots / 2, logger,
|
||||
[&](const StillsGPUAnalysis::Setup &s) {
|
||||
t_ready = std::chrono::steady_clock::now();
|
||||
run_profile = std::make_unique<AzimuthalIntegrationProfile>(*s.mapping);
|
||||
const auto &m = s.mask.GetMask();
|
||||
std::ofstream f(prefix + "_mask.u32", std::ios::binary);
|
||||
f.write(reinterpret_cast<const char *>(m.data()), m.size() * sizeof(uint32_t));
|
||||
@@ -152,7 +157,12 @@ int main(int argc, char **argv) {
|
||||
std::chrono::duration<double>(t_ready - t0).count(),
|
||||
s.experiment.GetBeamX_pxl(), s.experiment.GetBeamY_pxl());
|
||||
},
|
||||
[&](DataMessage &m, const AzimuthalIntegrationProfile &) {
|
||||
[&](DataMessage &m, const AzimuthalIntegrationProfile &profile) {
|
||||
{
|
||||
// As the receiver's plots do: the frames' profiles add up over the run.
|
||||
std::unique_lock ul(run_profile_mutex);
|
||||
*run_profile += profile;
|
||||
}
|
||||
++analysed;
|
||||
spots += static_cast<int64_t>(m.spots.size());
|
||||
processing_s += m.processing_time_s.value_or(0.0f);
|
||||
|
||||
Reference in new issue
Block a user