Merge branch 'rc187-live-fix-backend' into rc186-merge2

This commit is contained in:
leonarski_f committed 2026-11-12 19:33:29 +01:00
commit f487aa3ab2
16 files changed
+75 -16

No files matched your search

+2 -1
View File
@@ -730,7 +730,8 @@ DatasetSettings Convert(const org::openapitools::server::model::Dataset_settings
ret.SpotFindingEnable(input.isSpotFinding());
ret.MaxSpotCount(input.getMaxSpotCount());
ret.DetectIceRings(input.isDetectIceRings());
if (input.detectIceRingsIsSet())
ret.DetectIceRings(input.isDetectIceRings());
if (input.xrayFluorescenceSpectrumIsSet()) {
auto fl = input.getXrayFluorescenceSpectrum();
+1 -1
View File
@@ -325,7 +325,7 @@ public:
bool maxSpotCountIsSet() const;
void unsetMax_spot_count();
/// <summary>
/// Flag spots as ice rings and reduce their effect on indexing
/// Flag spots as ice rings and reduce their effect on indexing. Left out, the broker&#39;s own spot finding treats no spot as an ice ring, rugnux live decides as a bare &#x60;rugnux&#x60; would (on for a rotation sweep, off for stills), and the master file carries no &#x60;detect_ice_rings&#x60;.
/// </summary>
bool isDetectIceRings() const;
void setDetectIceRings(bool const value);
+2 -2
View File
@@ -162,12 +162,12 @@ public:
bool isaIsSet() const;
void unsetIsa();
/// <summary>
/// Answer of the early lattice probe on the first 60 degrees; empty until it answers
/// Answer of the early lattice probe on the first 60 degrees; empty until it answers, and the run&#39;s own lattice once the run has indexed
/// </summary>
std::string getProbe() const;
void setProbe(std::string const& value);
/// <summary>
/// When the probe answered, since the first image
/// When the probe answered (or the run indexed), since the first image
/// </summary>
double getProbeS() const;
void setProbeS(double const value);
+6 -3
View File
@@ -671,7 +671,10 @@ components:
description: Maximum number of spots that are saved/used for indexing; spots with highest intensity are selected
detect_ice_rings:
type: boolean
description: Flag spots as ice rings and reduce their effect on indexing
description: |
Flag spots as ice rings and reduce their effect on indexing. Left out, the broker's own
spot finding treats no spot as an ice ring, rugnux live decides as a bare `rugnux` would (on
for a rotation sweep, off for stills), and the master file carries no `detect_ice_rings`.
async_start:
type: boolean
default: false
@@ -3345,11 +3348,11 @@ components:
description: ISa of the error model; absent until the run is over, or where it was not determined
probe:
type: string
description: Answer of the early lattice probe on the first 60 degrees; empty until it answers
description: Answer of the early lattice probe on the first 60 degrees; empty until it answers, and the run's own lattice once the run has indexed
probe_s:
type: number
format: double
description: When the probe answered, since the first image
description: When the probe answered (or the run indexed), since the first image
start_to_first_image_s:
type: number
format: double
+4 -2
View File
@@ -30,8 +30,6 @@ DatasetSettings::DatasetSettings() {
poni_rot_3_rad = 0.0f;
max_spot_count = std::min(MAX_SPOT_COUNT, 250);
detect_ice_rings = false;
}
DatasetSettings &DatasetSettings::ImagesPerTrigger(int64_t input) {
@@ -542,6 +540,10 @@ DatasetSettings & DatasetSettings::DetectIceRings(bool input) {
}
bool DatasetSettings::IsDetectIceRings() const {
return detect_ice_rings.value_or(false);
}
std::optional<bool> DatasetSettings::GetDetectIceRings() const {
return detect_ice_rings;
}
+5 -2
View File
@@ -75,7 +75,9 @@ class DatasetSettings {
bool spot_finding_enable;
int64_t max_spot_count;
bool detect_ice_rings; // Enable special handling of ice rings
// Special handling of ice rings; unset where the user did not ask either way, so that the analysis takes its own
// default (rugnux: on for a rotation sweep, off for stills) and the master file carries no detect_ice_rings
std::optional<bool> detect_ice_rings;
XrayFluorescenceSpectrum fluorescence_spectrum;
std::optional<SmargonPosition> smargon_position;
@@ -186,7 +188,8 @@ public:
bool IsSpotFindingEnabled() const;
int64_t GetMaxSpotCount() const;
bool IsDetectIceRings() const;
bool IsDetectIceRings() const; // false where unset
std::optional<bool> GetDetectIceRings() const;
const XrayFluorescenceSpectrum &GetFluorescenceSpectrum() const;
std::optional<SmargonPosition> GetSmargonPosition() const;
};
+1 -1
View File
@@ -773,7 +773,7 @@ void DiffractionExperiment::FillMessage(StartMessage &message) const {
message.poni_rot2 = dataset.GetPoniRot2_rad();
message.poni_rot3 = dataset.GetPoniRot3_rad();
message.detect_ice_rings = dataset.IsDetectIceRings();
message.detect_ice_rings = dataset.GetDetectIceRings();
message.channels = {"default"};
+10
View File
@@ -7,6 +7,7 @@
#include "spdlog/fmt/bin_to_hex.h"
#include <map>
#include <set>
#include "Logger.h"
#include "GitInfo.h"
@@ -64,6 +65,15 @@ Logger::Logger(const std::string &service_name, const std::string &file_name) {
spdlog_logger = std::make_shared<spdlog::logger>(service_name, std::begin(sinks), std::end(sinks));
if (const auto it = service_levels.find(service_name); it != service_levels.end())
spdlog_logger->set_level(it->second);
{
// The version line goes out once per service: a run makes many loggers of one service (every FFT indexer
// is one). Function-local, as a static Logger (jfjoch_writer's) is made before this file's own statics.
static std::mutex version_mutex;
static std::set<std::string> version_logged;
std::unique_lock ul(version_mutex);
if (!version_logged.insert(service_name).second)
return;
}
if (jfjoch_git_sha1().empty())
spdlog_logger->info("Version {} {}", jfjoch_version(), variant);
else
+1 -1
View File
@@ -120,7 +120,7 @@ There are minor differences at the moment:
| - xfel_pulse_id | uint64 | Pulse IDs are recorded for images | |
| - ring_current_mA | float | Ring current at the start of the measurement | |
| - sample_temperature_K | float | Sample temperature \[K\] | |
| - detect_ice_rings | bool | Ice ring detection feature is enabled | |
| - detect_ice_rings | bool | Ice ring detection feature is enabled; absent where the dataset settings left it unset (rugnux then decides) | |
| - indexing_algorithm | string | Indexing algorithm used on-the-fly; allowed values: ffbidx, fft, fftw, none | |
| - geom_refinement_algorithm | string | Post-indexing detector geometry refinement algorithm; allowed values: none, beam_center | |
| - poni_rot1 | float | Tilt of the detector rot1 according to PyFAI PONI convention \[rad\] | |
+6 -1
View File
@@ -74,7 +74,12 @@ namespace {
}
void OnProgress(uint64_t done, uint64_t total) override { status.Progress(done, total); }
void OnStep(const std::string &title) override { status.Step(title); }
void OnNote(const std::string &text) override { status.Note(text); }
void OnNote(const std::string &text) override {
status.Note(text);
// The run has its lattice (RugnuxFirstPassAccept): the probe's answer on the first degrees is overtaken
if (text.starts_with("lattice "))
status.Lattice("lattice on the sweep: " + text.substr(8));
}
};
std::string StateName(RugnuxLiveState state) {
+1
View File
@@ -66,6 +66,7 @@ void JFJochReceiverRugnuxStills::OnImage(uint32_t id, DataMessage &message, std:
logger.Error("Dropping image {} - the collection has {} images", message.number, experiment.GetImageNum());
return;
}
live_status.ImageReceived(received);
CountImage(message);
const size_t size = message.image.GetCompressedSize();
+11
View File
@@ -86,6 +86,7 @@ void RugnuxLiveStatus::Start(int64_t images_expected, std::optional<double> expe
snapshot.expected_collection_s = expected_collection_s;
start = start_received;
last_image.reset();
lattice = false;
}
void RugnuxLiveStatus::ImageReceived(std::chrono::steady_clock::time_point received) {
@@ -226,10 +227,19 @@ void RugnuxLiveStatus::Cut(const std::string &reason) {
void RugnuxLiveStatus::Probe(const std::string &text) {
std::unique_lock ul(status_mutex);
if (lattice)
return;
snapshot.probe = text;
snapshot.probe_s = Now();
}
void RugnuxLiveStatus::Lattice(const std::string &text) {
std::unique_lock ul(status_mutex);
snapshot.probe = text;
snapshot.probe_s = Now();
lattice = true;
}
void RugnuxLiveStatus::Warning(const std::string &text) {
std::unique_lock ul(status_mutex);
snapshot.warnings.push_back(text);
@@ -246,6 +256,7 @@ void RugnuxLiveStatus::Clear() {
std::unique_lock ul(status_mutex);
snapshot = RugnuxLiveSnapshot{};
last_image.reset();
lattice = false;
}
RugnuxLiveSnapshot RugnuxLiveStatus::Get() const {
+3
View File
@@ -181,6 +181,7 @@ class RugnuxLiveStatus {
// Kept since the START message, shifted to the first image by Get().
std::chrono::steady_clock::time_point start;
std::optional<std::chrono::steady_clock::time_point> last_image;
bool lattice = false; // the run has its lattice: the probe's answer is overtaken
double Since(std::chrono::steady_clock::time_point t) const;
double Now() const;
void CloseStep();
@@ -204,7 +205,9 @@ public:
// The collection is over: last_image_s is set, and the last image's time is returned (none if no image came).
std::optional<std::chrono::steady_clock::time_point> LastImage();
void Cut(const std::string &reason);
// The probe's answer, unless the run has its lattice already; Lattice: the run's, in the probe's place
void Probe(const std::string &text);
void Lattice(const std::string &text);
void Warning(const std::string &text);
void Structure(std::shared_ptr<const RugnuxStructure> structure,
std::shared_ptr<const RugnuxStructure> refined_structure = nullptr);
-1
View File
@@ -67,7 +67,6 @@ void StillsGPUAnalysis::Publish() {
}
void StillsGPUAnalysis::Hold(const std::shared_ptr<HeldImage> &image) {
status.ImageReceived(std::chrono::steady_clock::now());
queue.PutBlocking(image);
{
std::unique_lock ul(prepass_mutex);
+19
View File
@@ -54,6 +54,25 @@ TEST_CASE("RugnuxLiveStatus_BeforeFirstImage", "[RugnuxLive]") {
CHECK(!status.LastImage());
}
TEST_CASE("RugnuxLiveStatus_RunLatticeOvertakesProbe", "[RugnuxLive]") {
RugnuxLiveStatus status;
status.Start(10, 1.0, std::chrono::steady_clock::now());
// The probe answers first, the run indexes later: the banner is the run's
status.Probe("no lattice on the first 60 deg");
CHECK(status.Get().probe == "no lattice on the first 60 deg");
status.Lattice("lattice on the sweep: monoclinic P: 35.00 29.00 63.00 90.0 105.0 90.0");
CHECK(status.Get().probe.starts_with("lattice on the sweep"));
// The run indexed before the probe answered: the probe's answer is not shown
status.Probe("no lattice on the first 60 deg");
CHECK(status.Get().probe.starts_with("lattice on the sweep"));
// The next collection starts afresh
status.Start(10, 1.0, std::chrono::steady_clock::now());
status.Probe("no lattice on the first 60 deg");
CHECK(status.Get().probe == "no lattice on the first 60 deg");
}
TEST_CASE("RugnuxLiveStatus_Clear", "[RugnuxLive]") {
RugnuxLiveStatus status;
status.Start(10, 1.0, std::chrono::steady_clock::now() - 2s);
+3 -1
View File
@@ -114,8 +114,10 @@ TEST_CASE("StillsGPUAnalysis_FailingFrameDoesNotStopAnalysis", "[StillsGPUAnalys
};
StillsGPUAnalysis gpu(x, mask, Start(x), nullptr, 1, 100, logger, sink, status);
// The frames carry no image, so their analysis fails too - they are passed on all the same.
for (int i = 0; i < 3; i++)
for (int i = 0; i < 3; i++) {
status.ImageReceived(std::chrono::steady_clock::now()); // as the receiver does before it holds a frame
gpu.Hold(Frame(buffer, i));
}
REQUIRE_NOTHROW(gpu.Finish());
CHECK(sunk == 3);
// The outcome waits for everything to be written, and comes after the latency.