GPU analysis of converted frames: rugnux's stills spot finder

The live analysis indexed 56.3% of the frames of a serial lysozyme run where
offline rugnux indexes 59.3% of the same frames. The whole gap is the spot
finder: the broker's default fixed threshold with two-pixel minimum spots
against rugnux's adaptive threshold that keeps single-pixel spots. With
those two settings (on top of the broker's others) the live analysis
indexes 59.3% of all 24960 frames, as offline; the sustained rate is
unchanged (~1080 Hz on the workstation). The pre-pass decided the centre and
the mask with the same spot finder.

jfjoch_stills_gpu_replay analyses as the receiver does; -F keeps the
broker's fixed-threshold finder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UqXYdJKPUFLoeAchjzv3x4
This commit is contained in:
leonarski_fandClaude Opus 5.5 committed 2026-11-02 19:29:18 +01:00
1 parent 6195e71210
commit 72eccd6b71
2 files changed
+21 -3

No files matched your search

+9 -1
View File
@@ -136,7 +136,15 @@ JFJochReceiverFPGA::JFJochReceiverFPGA(const DiffractionExperiment &in_experimen
SendCalibration();
},
[this](DataMessage &m, const AzimuthalIntegrationProfile &p) { GPUSink(m, p); },
[this] { return GetSpotFindingSettings(); });
[this] {
// The broker's settings, with the spot finder rugnux uses on stills (the pre-pass
// decided the centre and mask with it): adaptive threshold, single-pixel spots kept.
// With the broker's default fixed threshold 3 points fewer frames index.
SpotFindingSettings s = GetSpotFindingSettings();
s.adaptive_threshold = true;
s.min_pix_per_spot = std::nullopt;
return s;
});
} else {
SendStartMessage();
SendCalibration();
+12 -2
View File
@@ -29,6 +29,7 @@ void print_usage() {
std::cout << " -N <num> analysis threads (default 16)" << std::endl;
std::cout << " -x <px>, -y <px> beam centre, overriding the file" << std::endl;
std::cout << " -C <a,b,c,alpha,beta,gamma> unit cell of the collection" << std::endl;
std::cout << " -F the broker's default fixed-threshold spot finder (default: adaptive, as the receiver)" << std::endl;
std::cout << " -c leave the file's unit cell out of the collection" << std::endl;
}
@@ -44,9 +45,10 @@ int main(int argc, char **argv) {
std::optional<float> beam_x, beam_y;
std::optional<UnitCell> cell;
bool no_cell = false;
bool fixed_threshold = false;
int opt;
while ((opt = getopt(argc, argv, "o:s:n:r:N:x:y:C:c")) != -1) {
while ((opt = getopt(argc, argv, "o:s:n:r:N:x:y:C:cF")) != -1) {
switch (opt) {
case 'o': prefix = optarg; break;
case 's': first = atoll(optarg); break;
@@ -56,6 +58,7 @@ int main(int argc, char **argv) {
case 'x': beam_x = atof(optarg); break;
case 'y': beam_y = atof(optarg); break;
case 'c': no_cell = true; break;
case 'F': fixed_threshold = true; break;
case 'C': {
UnitCell c{};
if (sscanf(optarg, "%f,%f,%f,%f,%f,%f", &c.a, &c.b, &c.c, &c.alpha, &c.beta, &c.gamma) != 6) {
@@ -104,6 +107,13 @@ int main(int argc, char **argv) {
start.pixel_signed = stored.is_signed;
start.pixel_mask["default"] = mask.GetMask(x);
SpotFindingSettings spot_finding = DiffractionExperiment::DefaultDataProcessingSettings();
// As JFJochReceiverFPGA analyses converted frames.
if (!fixed_threshold) {
spot_finding.adaptive_threshold = true;
spot_finding.min_pix_per_spot = std::nullopt;
}
IndexerThreadPool pool(x.GetIndexingSettings());
std::atomic<int64_t> analysed = 0, indexed = 0;
@@ -125,7 +135,7 @@ int main(int argc, char **argv) {
if (m.indexing_result.value_or(false))
++indexed;
},
[] { return DiffractionExperiment::DefaultDataProcessingSettings(); });
[&] { return spot_finding; });
JFJochReaderRawImage raw;
for (int64_t i = 0; i < n; i++) {