From 1dfe08a141cac8fc2d2621b79066b6125aee42d3 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Wed, 5 Nov 2025 10:05:44 +0100 Subject: [PATCH] JFJochStateMachine: Implement improved calibration routines (to be field tested) --- broker/JFJochBrokerHttp.cpp | 2 +- broker/JFJochStateMachine.cpp | 104 +++++++++++++++---------------- broker/JFJochStateMachine.h | 5 +- broker/OpenAPIConvert.cpp | 2 +- tests/JFJochStateMachineTest.cpp | 6 +- 5 files changed, 60 insertions(+), 59 deletions(-) diff --git a/broker/JFJochBrokerHttp.cpp b/broker/JFJochBrokerHttp.cpp index 3816efbe..a6fc3ec8 100644 --- a/broker/JFJochBrokerHttp.cpp +++ b/broker/JFJochBrokerHttp.cpp @@ -82,7 +82,7 @@ void JFJochBrokerHttp::wait_till_done_post(const std::optional &timeout throw WrongDAQStateException(status.message.value_or("Unknown error")); case JFJochState::Measuring: case JFJochState::Busy: - case JFJochState::Pedestal: + case JFJochState::Calibration: response.send(Pistache::Http::Code::Gateway_Timeout); break; } diff --git a/broker/JFJochStateMachine.cpp b/broker/JFJochStateMachine.cpp index ef840fd4..8d55755f 100644 --- a/broker/JFJochStateMachine.cpp +++ b/broker/JFJochStateMachine.cpp @@ -11,9 +11,9 @@ JFJochStateMachine::JFJochStateMachine(const DiffractionExperiment& in_experiment, JFJochServices &in_services, Logger &in_logger) - : experiment(in_experiment), - logger(in_logger), + : logger(in_logger), services(in_services), + experiment(in_experiment), pixel_mask(experiment), current_detector_setup(0), data_processing_settings(DiffractionExperiment::DefaultDataProcessingSettings()), @@ -59,60 +59,60 @@ bool JFJochStateMachine::ImportPedestalG1G2(const JFJochReceiverOutput &receiver return true; } -void JFJochStateMachine::TakePedestalInternalAll(std::unique_lock &ul) { - if (experiment.GetDetectorSetup().GetDetectorType() != DetectorType::JUNGFRAU) { - try { - calibration.reset(); - logger.Info("Photon counting detector configuration"); - services.ConfigureDetector(experiment); - logger.Info(" ... done "); - SetState(JFJochState::Idle, - "Detector configured", - BrokerStatus::MessageSeverity::Success); - return; - } catch (const std::exception &e) { - logger.Error("Configuration error {}", e.what()); - SetState(JFJochState::Error, e.what(), BrokerStatus::MessageSeverity::Error); - throw; - } - } - - calibration = std::make_unique(experiment); - +void JFJochStateMachine::CalibrateJUNGFRAU(std::unique_lock &ul) { if (!gain_calibration.empty()) { if (gain_calibration.size() != experiment.GetModulesNum()) - throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Mismatch in gain files number"); + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, + "Mismatch in gain files number"); for (int i = 0; i < gain_calibration.size(); i++) calibration->GainCalibration(i) = gain_calibration[i]; } + TakePedestalInternalG0(ul); + if (!experiment.IsFixedGainG1()) { + for (int i = 0; i < experiment.GetStorageCellNumber(); i++) { + TakePedestalInternalG1(ul, i); + TakePedestalInternalG2(ul, i); + } + } + pixel_mask.LoadDetectorBadPixelMask(experiment, calibration.get()); +} + +void JFJochStateMachine::CalibrateDetector(std::unique_lock &ul) { cancel_sequence = false; - logger.Info("Pedestal sequence started"); + pixel_mask = PixelMask(experiment); + UpdatePixelMaskStatistics(pixel_mask.GetStatistics()); + logger.Info("Calibration sequence started"); try { - TakePedestalInternalG0(ul); - if (!experiment.IsFixedGainG1()) { - for (int i = 0; i < experiment.GetStorageCellNumber(); i++) { - TakePedestalInternalG1(ul, i); - TakePedestalInternalG2(ul, i); - } + if (experiment.GetDetectorType() == DetectorType::EIGER) { + // PSI EIGER - only reset calibration + calibration.reset(); + } else if (experiment.GetDetectorType() == DetectorType::DECTRIS) { + // DECTRIS - take dark data for mask + calibration.reset(); + TakeDarkMaskInternal(ul); + } else { + // PSI JUNGFRAU - take pedestal + calibration = std::make_unique(experiment); + CalibrateJUNGFRAU(ul); } - services.ConfigureDetector(experiment); - pixel_mask.LoadDetectorBadPixelMask(experiment, calibration.get()); + // Update pixel mask statistics UpdatePixelMaskStatistics(pixel_mask.GetStatistics()); - SetState(JFJochState::Idle, "Pedestal sequence done", BrokerStatus::MessageSeverity::Success); + // configure detector for standard operation + services.ConfigureDetector(experiment); } catch (const std::exception &e) { - logger.Error("Pedestal sequence error {}", e.what()); + logger.Error("Calibration sequence error {}", e.what()); SetState(JFJochState::Error, e.what(), BrokerStatus::MessageSeverity::Error); throw; } + SetState(JFJochState::Idle, "Calibration sequence done", BrokerStatus::MessageSeverity::Success); + logger.Info("Pedestal sequence done"); } void JFJochStateMachine::TakeDarkMaskInternal(std::unique_lock &ul) { - if (experiment.GetDarkMaskNumberOfFrames() == 0) - return; if (cancel_sequence) { SetState(JFJochState::Inactive, "Mask sequence cancelled", @@ -120,10 +120,15 @@ void JFJochStateMachine::TakeDarkMaskInternal(std::unique_lock &ul) return; } + services.LoadDetectorPixelMask(pixel_mask); + + if (experiment.GetDarkMaskNumberOfFrames() == 0) + return; + DiffractionExperiment local_experiment(experiment); local_experiment.Mode(DetectorMode::DarkMask); - SetState(JFJochState::Pedestal, "Dark sequence for mask calculation", BrokerStatus::MessageSeverity::Info); + SetState(JFJochState::Calibration, "Dark sequence for mask calculation", BrokerStatus::MessageSeverity::Info); services.ConfigureDetector(local_experiment); services.Start(local_experiment, pixel_mask, nullptr); @@ -136,9 +141,7 @@ void JFJochStateMachine::TakeDarkMaskInternal(std::unique_lock &ul) pixel_mask.LoadDarkBadPixelMask(mask_output.receiver_output.dark_mask_result); SetState(JFJochState::Idle); } else - SetState(JFJochState::Error, - "Mask not collected properly", - BrokerStatus::MessageSeverity::Error); + SetState(JFJochState::Error, "Mask not collected properly", BrokerStatus::MessageSeverity::Error); } void JFJochStateMachine::TakePedestalInternalG0(std::unique_lock &ul) { @@ -167,7 +170,7 @@ void JFJochStateMachine::TakePedestalInternalG0(std::unique_lock &ul if (local_experiment.GetPedestalG0Frames() == 0) return; - SetState(JFJochState::Pedestal, message, BrokerStatus::MessageSeverity::Info); + SetState(JFJochState::Calibration, message, BrokerStatus::MessageSeverity::Info); services.ConfigureDetector(local_experiment); services.Start(local_experiment, pixel_mask, calibration.get()); @@ -208,7 +211,7 @@ void JFJochStateMachine::TakePedestalInternalG1(std::unique_lock &ul return; - SetState(JFJochState::Pedestal, + SetState(JFJochState::Calibration, "Pedestal G1 SC" + std::to_string(storage_cell), BrokerStatus::MessageSeverity::Info); services.ConfigureDetector(local_experiment); @@ -248,7 +251,7 @@ void JFJochStateMachine::TakePedestalInternalG2(std::unique_lock &ul return; - SetState(JFJochState::Pedestal, + SetState(JFJochState::Calibration, "Pedestal G2 SC" + std::to_string(storage_cell), BrokerStatus::MessageSeverity::Info); services.ConfigureDetector(local_experiment); @@ -306,7 +309,7 @@ void JFJochStateMachine::Pedestal() { void JFJochStateMachine::PedestalThread(std::unique_lock ul) { - TakePedestalInternalAll(ul); + CalibrateDetector(ul); } void JFJochStateMachine::InitializeThread(std::unique_lock ul) { @@ -322,17 +325,14 @@ void JFJochStateMachine::InitializeThread(std::unique_lock ul) { ul.lock(); experiment = local_experiment; - detector_setup[current_detector_setup] = experiment.GetDetectorSetup(); - pixel_mask = PixelMask(experiment); - services.LoadDetectorPixelMask(pixel_mask); - UpdatePixelMaskStatistics(pixel_mask.GetStatistics()); + } catch (const std::exception &e) { logger.Error("Initialize error {}", e.what()); SetState(JFJochState::Error, e.what(), BrokerStatus::MessageSeverity::Error); throw; } - TakePedestalInternalAll(ul); + CalibrateDetector(ul); } void JFJochStateMachine::Trigger() { @@ -420,7 +420,7 @@ void JFJochStateMachine::MeasurementThread() { void JFJochStateMachine::Cancel() { // This is inconsistency in naming - need to solve later std::unique_lock ul(m); - if ((state == JFJochState::Pedestal) || (state == JFJochState::Measuring)) { + if ((state == JFJochState::Calibration) || (state == JFJochState::Measuring)) { services.Cancel(); cancel_sequence = true; } @@ -536,7 +536,7 @@ void JFJochStateMachine::LoadDetectorSettings(const DetectorSettings &settings) break; case JFJochState::Measuring: case JFJochState::Busy: - case JFJochState::Pedestal: + case JFJochState::Calibration: throw WrongDAQStateException("Cannot change detector settings during data collection"); } } @@ -691,7 +691,7 @@ bool JFJochStateMachine::IsRunning() const { return false; case JFJochState::Measuring: case JFJochState::Busy: - case JFJochState::Pedestal: + case JFJochState::Calibration: return true; default: throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "State unknown"); diff --git a/broker/JFJochStateMachine.h b/broker/JFJochStateMachine.h index 183c712a..1bc0eb8e 100644 --- a/broker/JFJochStateMachine.h +++ b/broker/JFJochStateMachine.h @@ -16,7 +16,7 @@ #include "JFJochServices.h" #include "../common/ROIMap.h" -enum class JFJochState {Inactive, Idle, Measuring, Error, Busy, Pedestal}; +enum class JFJochState {Inactive, Idle, Measuring, Error, Busy, Calibration}; struct BrokerStatus { JFJochState state = JFJochState::Inactive; @@ -141,7 +141,8 @@ class JFJochStateMachine { bool IsRunning() const; // Is state Busy/Pedestal/Measure void ResetError() noexcept; void TakeDarkMaskInternal(std::unique_lock &ul); - void TakePedestalInternalAll(std::unique_lock &ul); + void CalibrateDetector(std::unique_lock &ul); + void CalibrateJUNGFRAU(std::unique_lock &ul); void TakePedestalInternalG0(std::unique_lock &ul); void TakePedestalInternalG1(std::unique_lock &ul, int32_t storage_cell = 0); void TakePedestalInternalG2(std::unique_lock &ul, int32_t storage_cell = 0); diff --git a/broker/OpenAPIConvert.cpp b/broker/OpenAPIConvert.cpp index c5dd5c21..10a480c9 100644 --- a/broker/OpenAPIConvert.cpp +++ b/broker/OpenAPIConvert.cpp @@ -215,7 +215,7 @@ org::openapitools::server::model::Broker_status Convert(const BrokerStatus& inpu case JFJochState::Busy: ret.setState("Busy"); break; - case JFJochState::Pedestal: + case JFJochState::Calibration: ret.setState("Pedestal"); break; } diff --git a/tests/JFJochStateMachineTest.cpp b/tests/JFJochStateMachineTest.cpp index 78ab097b..1aba3055 100644 --- a/tests/JFJochStateMachineTest.cpp +++ b/tests/JFJochStateMachineTest.cpp @@ -37,14 +37,14 @@ TEST_CASE("JFJochStateMachine_State_Pedestal") { DatasetSettings setup; - state_machine.DebugOnly_SetState(JFJochState::Pedestal); + state_machine.DebugOnly_SetState(JFJochState::Calibration); - REQUIRE(state_machine.GetStatus().state == JFJochState::Pedestal); + REQUIRE(state_machine.GetStatus().state == JFJochState::Calibration); REQUIRE_THROWS(state_machine.Start(setup)); REQUIRE_THROWS(state_machine.Pedestal()); REQUIRE_THROWS(state_machine.Initialize()); - REQUIRE(state_machine.WaitTillMeasurementDone(std::chrono::milliseconds(1)).state == JFJochState::Pedestal); + REQUIRE(state_machine.WaitTillMeasurementDone(std::chrono::milliseconds(1)).state == JFJochState::Calibration); } TEST_CASE("JFJochStateMachine_State_Measure") {