// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #include "JFJochServices.h" #include "../common/JFJochException.h" #include "../detector_control/SLSDetectorWrapper.h" #include "../detector_control/DectrisDetectorWrapper.h" JFJochServices::JFJochServices(Logger &in_logger) : logger(in_logger) {} void JFJochServices::Start(const DiffractionExperiment& experiment, const PixelMask &pixel_mask, const JFCalibration *calibration) { logger.Info("Measurement start for: {}", experiment.GetFilePrefix()); cannot_stop_detector = false; if (receiver != nullptr) { logger.Info(" ... receiver start"); receiver->Start(experiment, pixel_mask, calibration); if (detector && !experiment.IsUsingInternalPacketGen()) { logger.Info(" ... detector start"); detector->Start(experiment); } } logger.Info(" Done!"); } void JFJochServices::Off() { if (detector) { detector->Deactivate(); detector.reset(); } } void JFJochServices::On(DiffractionExperiment &x) { if (x.IsUsingInternalPacketGen() || (receiver == nullptr)) { detector.reset(); } else { logger.Info("Detector on"); switch (x.GetDetectorType()) { case DetectorType::EIGER: case DetectorType::JUNGFRAU: detector = std::make_unique(); break; case DetectorType::DECTRIS: detector = std::make_unique(); break; } detector->Initialize(x, receiver->GetNetworkConfig()); logger.Info(" ... done"); } } JFJochServicesOutput JFJochServices::Stop() { JFJochServicesOutput ret; std::unique_ptr exception; bool detector_error = false; if (receiver != nullptr) { try { if (detector) { logger.Info("Wait for detector idle"); DetectorState state = detector->GetState(); while ((!cannot_stop_detector) && ((state == DetectorState::WAITING) || (state == DetectorState::BUSY))) { // check detector state every 5 ms std::this_thread::sleep_for(std::chrono::milliseconds(5)); state = detector->GetState(); } if (state == DetectorState::IDLE) { logger.Info(" ... detector idle"); receiver->Cancel(true); // cancel silently } else { logger.Error(" ... detector in error state"); receiver->Cancel(false); detector_error = true; } } logger.Info("Wait for receiver done"); ret.receiver_output = receiver->Stop(); logger.Info(" ... Receiver efficiency: {} % Max delay: {} Compression ratio {}x", static_cast(ret.receiver_output.efficiency * 100.0), ret.receiver_output.status.max_receive_delay.value_or(0), static_cast(std::round(ret.receiver_output.status.compressed_ratio.value_or(1)))); if (ret.receiver_output.efficiency < 1.0) { for (int i = 0; i < ret.receiver_output.received_packets.size(); i++) { if (ret.receiver_output.received_packets[i] != ret.receiver_output.expected_packets[i]) logger.Info(" ... Module: {} Packets received: {} out of {}", i, ret.receiver_output.received_packets[i], ret.receiver_output.expected_packets[i]); } } } catch (const JFJochException &e) { logger.Error(" ... finished with error {}", e.what()); exception = std::make_unique(e); } logger.Info("Receiver finished with success"); } else { logger.Info("No receiver - sleeping for 30 seconds"); std::this_thread::sleep_for(std::chrono::seconds(30)); logger.Info("Sleep done"); } if (exception) throw JFJochException(*exception); if (detector_error) throw JFJochException(JFJochExceptionCategory::Detector, "Error in detector operation"); return ret; } void JFJochServices::Cancel() { if (detector) { // Best effort - if detector cannot be stopped, this is OK, important to still stop receiver try { detector->Stop(); } catch (...) { cannot_stop_detector = true; } } if (receiver != nullptr) receiver->Cancel(false); } JFJochServices &JFJochServices::Receiver(JFJochReceiverService *input) { receiver = input; return *this; } std::optional JFJochServices::GetReceiverStatus() const { if (receiver == nullptr) return {}; return receiver->GetStatus(); } std::optional JFJochServices::GetReceiverProgress() const { if (receiver == nullptr) return {}; return receiver->GetProgress(); } MultiLinePlot JFJochServices::GetPlots(const PlotRequest &request) { if (receiver == nullptr) return {}; return receiver->GetDataProcessingPlot(request); } void JFJochServices::GetPlotRaw(std::vector &v, PlotType type, const std::string &roi) { if (receiver != nullptr) receiver->GetPlotRaw(v, type, roi); } void JFJochServices::SetSpotFindingSettings(const SpotFindingSettings &settings) { if (receiver) receiver->SetSpotFindingSettings(settings); } void JFJochServices::Trigger() { if (detector && (receiver != nullptr)) detector->Trigger(); } std::optional JFJochServices::GetDetectorStatus() const { if (detector) return detector->GetStatus(); else return {}; } std::string JFJochServices::GetPreviewJPEG(const PreviewImageSettings &settings, int64_t image_number) const { if (receiver != nullptr) return receiver->GetJPEGFromBuffer(settings, image_number); else return {}; } std::string JFJochServices::GetPreviewTIFF(int64_t image_number) const { if (receiver != nullptr) return receiver->GetTIFFFromBuffer(image_number); else return ""; } void JFJochServices::ConfigureDetector(const DiffractionExperiment &experiment) { if (detector) detector->Configure(experiment); } void JFJochServices::LoadInternalGeneratorImage(const DiffractionExperiment &experiment, const std::vector &image, uint64_t image_number) { if (receiver) receiver->LoadInternalGeneratorImage(experiment, image, image_number); } void JFJochServices::GetXFELPulseID(std::vector &v) const { if (receiver) receiver->GetXFELPulseID(v); } void JFJochServices::GetXFELEventCode(std::vector &v) const { if (receiver) receiver->GetXFELPulseID(v); } std::vector JFJochServices::GetDeviceStatus() const { std::vector ret; if (receiver) ret = receiver->GetDeviceStatus(); return ret; } ZMQPreviewSettings JFJochServices::GetPreviewSocketSettings() { if (receiver) return receiver->GetPreviewSocketSettings(); return {}; } ZMQMetadataSettings JFJochServices::GetMetadataSocketSettings() { if (receiver) return receiver->GetMetadataSocketSettings(); return {}; } void JFJochServices::SetPreviewSocketSettings(const ZMQPreviewSettings &input) { if (receiver) receiver->PreviewSocketSettings(input); } void JFJochServices::SetMetadataSocketSettings(const ZMQMetadataSettings &input) { if (receiver) receiver->MetadataSocketSettings(input); } void JFJochServices::GetStartMessageFromBuffer(std::vector &v) { if (receiver) return receiver->GetStartMessageFromBuffer(v); } bool JFJochServices::GetImageFromBuffer(std::vector &v, int64_t image_number) { if (receiver) return receiver->GetImageFromBuffer(v, image_number); return false; } ImageBufferStatus JFJochServices::GetImageBufferStatus() const { if (receiver) return receiver->GetImageBufferStatus(); else return ImageBufferStatus{.total_slots = 0, .available_slots = 0}; } void JFJochServices::ClearImageBuffer() const { if (receiver) receiver->ClearImageBuffer(); } void JFJochServices::LoadDetectorPixelMask(PixelMask &mask) { if (detector) detector->LoadPixelMask(mask); } void JFJochServices::SetupIndexing(const IndexingSettings &input) { if (receiver) receiver->Indexing(input); }