The pre-pass refines the centre and distance on the frames the image buffer holds. At a serial hit rate that is a few dozen indexed frames (20 of 363 on a 129.6k-frame JUNGFRAU 8M serial collection), with a buffer of 4 GB none (45 frames held), and on a fixed-target chip whose first wells are empty none at all: the collection was then analysed at the stated distance, 2.6% short on that collection, and merged to 1.93-1.96 A. Where a cell is given and the pre-pass fitted the geometry on fewer than 200 frames, StillsRunningGeometry refines it again from the spots and lattices of the frames as they are analysed: once 200 strong frames (20 indexed spots or more) are in, or 5000 indexed (empty frames do not count), the strongest are bundled and the geometry fitted once, as rugnux fits its sample, and the analysis switches to it (the analysis threads rebuild their analysis at the new geometry, a gate keeping new frames back until the switch has the geometry exclusive). A second round does the same on frames analysed at the first one's geometry. Two fits, a fixed cost. The frames analysed before the last switch are left out of the merge: their reflections were predicted at an earlier geometry and the images are not kept to integrate them again. DropIntegrationOutcome takes their cells out of the consensus too. The pre-pass reports how many frames its fit rested on (ProcessResult::stills_geometry_frames, recorded by RefineStillsGeometry; nothing it computes changes). jfjoch_stills_gpu_replay holds frames in half the buffer, as the receiver does, and gives the first images as empty frames with -e. On that collection, with the right cell (rugnux: 117.94 mm, 1.30 A, CC1/2 0.9946, R_split 0.062): - 4 GB buffer: 115.00 -> 117.78 -> 117.96 mm; 1.32 A, CC1/2 0.9962, R_split 0.070, 99.7%, merge 3.1 s after the last frame - 32 GB buffer: pre-pass 117.49 on 20 frames, then 117.93 -> 117.98 mm; 1.32 A, 0.9951, 0.070, 99.6%, 3.6 s (pre-pass alone: 1.35 A, 0.074) - first 30% of the frames empty: 115.00 -> 118.62 -> 118.06 mm; 1.35 A, 0.9913, 0.093, 99.7%, 2.2 s (before: 1.96 A; rugnux on the same 70% of the frames: 1.33 A, 0.9935, 0.079) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UqXYdL4qBGYRiSXSGXfCLu
67 lines
2.8 KiB
C++
67 lines
2.8 KiB
C++
// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include "StillsPrePass.h"
|
|
|
|
#include "../common/JFJochException.h"
|
|
#include "../reader/JFJochReader.h"
|
|
#include "../reader/JFJochStartMessageReader.h"
|
|
#include "../rugnux/RugnuxLive.h"
|
|
|
|
namespace {
|
|
// The held images as a collection of their own, numbered from 0 as the collection numbers them.
|
|
class HeldImageReader : public JFJochReader {
|
|
const std::map<int64_t, std::shared_ptr<HeldImage>> &images;
|
|
uint64_t number_of_images;
|
|
|
|
bool LoadImage_i(std::shared_ptr<JFJochReaderDataset> &dataset, DataMessage &message,
|
|
std::vector<uint8_t> &, int64_t image_number, bool) override {
|
|
const auto it = images.find(image_number);
|
|
if (!dataset || it == images.end())
|
|
return false;
|
|
message = it->second->message;
|
|
return true;
|
|
}
|
|
public:
|
|
HeldImageReader(const StartMessage &start, const std::map<int64_t, std::shared_ptr<HeldImage>> &in_images)
|
|
: images(in_images), number_of_images(in_images.empty() ? 0 : in_images.rbegin()->first + 1) {
|
|
SetStartMessage(DatasetFromStartMessage(start, default_experiment));
|
|
}
|
|
|
|
[[nodiscard]] uint64_t GetNumberOfImages() const override { return number_of_images; }
|
|
void Close() override {}
|
|
|
|
bool ReadRawImage(int64_t image_number, JFJochReaderRawImage &ret) override {
|
|
const auto it = images.find(image_number);
|
|
if (it == images.end())
|
|
return false;
|
|
ret.image = it->second->message.image;
|
|
return true;
|
|
}
|
|
|
|
std::vector<SpotToSave> ReadSpots(int64_t) const override { return {}; }
|
|
};
|
|
}
|
|
|
|
StillsPrePassResult RunStillsPrePass(const StartMessage &start, const std::map<int64_t, std::shared_ptr<HeldImage>> &images,
|
|
int nthreads) {
|
|
HeldImageReader reader(start, images);
|
|
const auto dataset = reader.GetDataset();
|
|
const RugnuxLiveSetup setup = MakeRugnuxStillsPrePassSetup(*dataset, nthreads);
|
|
|
|
Rugnux rugnux(reader, setup.experiment, *dataset->pixel_mask, setup.config);
|
|
const ProcessResult result = rugnux.Run();
|
|
Rugnux::ReleasePinnedPool();
|
|
|
|
return StillsPrePassResult{
|
|
// Where the beam lands: the receiver analyses with the detector square to it, as stated, and a tilt
|
|
// the run refined moves its PONI, not this.
|
|
.beam_x_pxl = static_cast<float>(result.used_direct_beam_x_pxl),
|
|
.beam_y_pxl = static_cast<float>(result.used_direct_beam_y_pxl),
|
|
.distance_mm = result.used_distance_mm,
|
|
.mask = rugnux.GetPixelMask(),
|
|
.images = images.size(),
|
|
.geometry_frames = result.stills_geometry_frames
|
|
};
|
|
}
|