From 953c3fa97222a1b9b081b5aea16c08d4d1721204 Mon Sep 17 00:00:00 2001 From: leonarski_f Date: Mon, 3 Jun 2024 10:56:43 +0200 Subject: [PATCH] Updates after MAX IV experiment --- CMakeLists.txt | 1 + VERSION | 2 +- broker/JFJochBrokerHttp.cpp | 43 +++++- broker/JFJochBrokerHttp.h | 10 ++ broker/JFJochServices.cpp | 8 +- broker/JFJochServices.h | 4 +- broker/JFJochStateMachine.cpp | 64 +++++++- broker/JFJochStateMachine.h | 7 + broker/gen/api/DefaultApi.cpp | 82 +++++++++++ broker/gen/api/DefaultApi.h | 32 ++++ broker/gen/model/Preview_settings.cpp | 35 ++++- broker/gen/model/Preview_settings.h | 9 ++ broker/gen/model/Spot_finding_settings.cpp | 74 +++++++++- broker/gen/model/Spot_finding_settings.h | 22 ++- broker/jfjoch_api.yaml | 116 ++++++++++++++- broker/redoc-static.html | 82 +++++++++-- common/DiffractionExperiment.cpp | 3 +- common/DiffractionExperiment.h | 1 - common/PixelMask.cpp | 30 ++-- common/PixelMask.h | 15 +- common/Plot.h | 9 +- common/StatusVector.h | 6 + fpga/hls/spot_finder.cpp | 122 +++++++++++----- fpga/hls/spot_finder_mask.cpp | 4 +- fpga/pcie_driver/jfjoch_pcie_setup.c | 5 +- frame_serialize/CBORStream2Deserializer.cpp | 2 + frame_serialize/CBORStream2Serializer.cpp | 2 + frame_serialize/JFJochMessages.h | 1 + frontend_ui/package-lock.json | 10 +- frontend_ui/package.json | 8 +- .../src/components/DataProcessingPlots.tsx | 2 +- .../src/components/DataProcessingSettings.tsx | 64 +++++--- frontend_ui/src/components/PreviewImage.tsx | 17 ++- .../src/openapi/models/preview_settings.ts | 4 + .../openapi/models/spot_finding_settings.ts | 15 +- .../src/openapi/services/DefaultService.ts | 92 +++++++++++- image_analysis/CPUSpotFinder.cpp | 137 +++++++++++------- image_analysis/CPUSpotFinder.h | 9 +- image_analysis/IndexerWrapper.cpp | 42 +++--- image_analysis/IndexerWrapper.h | 4 +- image_analysis/MXAnalyzer.cpp | 93 ++++++++++-- image_analysis/MXAnalyzer.h | 14 ++ image_analysis/SpotFindingSettings.h | 7 +- jungfrau/JFCalibration.cpp | 2 +- preview/CMakeLists.txt | 4 +- preview/{WriteJPEG.cpp => JFJochJPEG.cpp} | 2 +- preview/{WriteJPEG.h => JFJochJPEG.h} | 0 preview/JFJochTIFF.cpp | 110 ++++++++++++++ preview/{WriteTIFF.h => JFJochTIFF.h} | 3 + preview/PreviewImage.cpp | 22 ++- preview/PreviewImage.h | 6 +- preview/WriteTIFF.cpp | 48 ------ receiver/JFJochReceiver.cpp | 17 ++- receiver/JFJochReceiver.h | 6 +- receiver/JFJochReceiverPlots.cpp | 25 ++-- receiver/JFJochReceiverPlots.h | 1 + receiver/JFJochReceiverService.cpp | 11 +- receiver/JFJochReceiverService.h | 4 +- receiver/JFJochReceiverTest.cpp | 4 +- tests/CBORTest.cpp | 2 + tests/FPGAIntegrationTest.cpp | 49 +++++-- tests/JFJochReceiverIntegrationTest.cpp | 8 +- tests/JFJochReceiverProcessingTest.cpp | 17 ++- tests/JPEGTest.cpp | 16 +- tests/PixelMaskTest.cpp | 105 +++++++++++++- tests/StreamWriterTest.cpp | 4 +- tests/TIFFTest.cpp | 29 +++- tools/jfjoch_spot_finding_test.cpp | 48 +++++- writer/HDF5DataFilePluginMX.cpp | 10 ++ writer/HDF5DataFilePluginMX.h | 2 +- 70 files changed, 1530 insertions(+), 334 deletions(-) rename preview/{WriteJPEG.cpp => JFJochJPEG.cpp} (98%) rename preview/{WriteJPEG.h => JFJochJPEG.h} (100%) create mode 100644 preview/JFJochTIFF.cpp rename preview/{WriteTIFF.h => JFJochTIFF.h} (66%) delete mode 100644 preview/WriteTIFF.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index acff982d..9a55ce29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,6 +161,7 @@ SET(CPACK_RPM_DRIVER-DKMS_PACKAGE_REQUIRES "dkms, gcc, bash, sed") SET(CPACK_RPM_DRIVER-DKMS_PACKAGE_ARCHITECTURE "noarch") SET(CPACK_RPM_DRIVER-DKMS_POST_INSTALL_SCRIPT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/fpga/pcie_driver/postinstall.sh) SET(CPACK_RPM_DRIVER-DKMS_PRE_UNINSTALL_SCRIPT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/fpga/pcie_driver/preuninstall.sh) +SET(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr/src) # Set The Vendor Name SET(CPACK_PACKAGE_VENDOR "Paul Scherrer Institut") diff --git a/VERSION b/VERSION index 99c6b2af..1ca197a0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.0_rc.6 +1.0.0_rc.7 diff --git a/broker/JFJochBrokerHttp.cpp b/broker/JFJochBrokerHttp.cpp index 7a5c6e61..b9fbf82f 100644 --- a/broker/JFJochBrokerHttp.cpp +++ b/broker/JFJochBrokerHttp.cpp @@ -4,6 +4,7 @@ #include #include "JFJochBrokerHttp.h" #include "gen/model/Error_message.h" +#include "../preview/JFJochTIFF.h" // From https://en.cppreference.com/w/cpp/string/byte/tolower inline std::string str_tolower(std::string s) { @@ -22,6 +23,10 @@ inline SpotFindingSettings Convert(const org::openapitools::server::model::Spot_ ret.enable = input.isEnable(); ret.indexing = input.isIndexing(); ret.indexing_tolerance = input.getIndexingTolerance(); + if (input.filterPowderRingsIsSet()) + ret.filter_spots_powder_ring = input.isFilterPowderRings(); + if (input.minSpotCountPowderRingIsSet()) + ret.min_spot_count_powder_ring = input.getMinSpotCountPowderRing(); return ret; } @@ -36,6 +41,8 @@ inline org::openapitools::server::model::Spot_finding_settings Convert(const Spo ret.setEnable(input.enable); ret.setIndexing(input.indexing); ret.setIndexingTolerance(input.indexing_tolerance); + ret.setFilterPowderRings(input.filter_spots_powder_ring); + ret.setMinSpotCountPowderRing(input.min_spot_count_powder_ring); return ret; } @@ -317,6 +324,7 @@ inline PreviewJPEGSettings Convert(const org::openapitools::server::model::Previ ret.saturation_value = input.getSaturation(); ret.show_roi = input.isShowRoi(); ret.show_indexed = input.isShowIndexed(); + ret.show_user_mask = input.isShowUserMask(); if (input.resolutionRingIsSet()) ret.resolution_ring = input.getResolutionRing(); return ret; @@ -655,18 +663,33 @@ void JFJochBrokerHttp::preview_image_tiff_get(Pistache::Http::ResponseWriter &re void JFJochBrokerHttp::config_internal_generator_image_put(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response) { int64_t image_number = 0; - auto number_query = request.query().get("number"); + auto number_query = request.query().get("id"); if (number_query) image_number = std::stoi(number_query.value()); if ((image_number < 0) || (image_number > 127)) - throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "image_number must be in range 0-127"); + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "id must be in range 0-127"); state_machine.LoadInternalGeneratorImage(request.body().data(), request.body().size(), image_number); logger.Info("Internal generator image #{} loaded", image_number); response.send(Pistache::Http::Code::Ok); } + +void JFJochBrokerHttp::config_internal_generator_image_tiff_put(const Pistache::Rest::Request &request, + Pistache::Http::ResponseWriter &response) { + int64_t image_number = 0; + auto number_query = request.query().get("id"); + if (number_query) + image_number = std::stoi(number_query.value()); + + if ((image_number < 0) || (image_number > 127)) + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "id must be in range 0-127"); + + state_machine.LoadInternalGeneratorImageTIFF(request.body(), image_number); + response.send(Pistache::Http::Code::Ok); +} + void JFJochBrokerHttp::roi_box_get(Pistache::Http::ResponseWriter &response) { ProcessOutput(Convert(state_machine.GetBoxROI()), response); } @@ -782,3 +805,19 @@ void JFJochBrokerHttp::plot_strong_pixel_get(const std::optional &binni Pistache::Http::ResponseWriter &response) { GenericPlot(PlotType::StrongPixels, binning, response); } + +void JFJochBrokerHttp::config_mask_tiff_get(Pistache::Http::ResponseWriter &response) { + std::string s = state_machine.GetFullPixelMaskTIFF(); + response.send(Pistache::Http::Code::Ok, s, Pistache::Http::Mime::MediaType::fromString("image/tiff")); +} + +void JFJochBrokerHttp::config_user_mask_tiff_get(Pistache::Http::ResponseWriter &response) { + std::string s = state_machine.GetUserPixelMaskTIFF(); + response.send(Pistache::Http::Code::Ok, s, Pistache::Http::Mime::MediaType::fromString("image/tiff")); +} + +void JFJochBrokerHttp::config_user_mask_tiff_put(const Pistache::Rest::Request &request, + Pistache::Http::ResponseWriter &response) { + state_machine.SetUserPixelMask(request.body()); + response.send(Pistache::Http::Code::Ok); +} diff --git a/broker/JFJochBrokerHttp.h b/broker/JFJochBrokerHttp.h index 48b2e497..397b918d 100644 --- a/broker/JFJochBrokerHttp.h +++ b/broker/JFJochBrokerHttp.h @@ -118,6 +118,16 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi { void xfel_event_code_get(Pistache::Http::ResponseWriter &response) override; void xfel_pulse_id_get(Pistache::Http::ResponseWriter &response) override; + void config_mask_tiff_get(Pistache::Http::ResponseWriter &response) override; + + void config_user_mask_tiff_get(Pistache::Http::ResponseWriter &response) override; + + void config_user_mask_tiff_put(const Pistache::Rest::Request &request, + Pistache::Http::ResponseWriter &response) override; + + void config_internal_generator_image_tiff_put(const Pistache::Rest::Request &request, + Pistache::Http::ResponseWriter &response) override; + void GetStaticFile(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); std::pair handleOperationException(const std::exception &ex) const noexcept override; diff --git a/broker/JFJochServices.cpp b/broker/JFJochServices.cpp index 4beef0ba..7fcaed33 100644 --- a/broker/JFJochServices.cpp +++ b/broker/JFJochServices.cpp @@ -5,15 +5,17 @@ JFJochServices::JFJochServices(Logger &in_logger) : logger(in_logger) {} -void JFJochServices::Start(const DiffractionExperiment& experiment, const JFCalibration &calibration) { +void JFJochServices::Start(const DiffractionExperiment& experiment, + const PixelMask &pixel_mask, + const JFCalibration &calibration) { logger.Info("Measurement start for: {}", experiment.GetFilePrefix()); if (receiver != nullptr) { logger.Info(" ... receiver start"); if (experiment.GetDetectorMode() == DetectorMode::Conversion) - receiver->Start(experiment, &calibration); + receiver->Start(experiment, pixel_mask, &calibration); else - receiver->Start(experiment, nullptr); + receiver->Start(experiment, pixel_mask, nullptr); if (detector && !experiment.IsUsingInternalPacketGen()) { logger.Info(" ... detector start"); diff --git a/broker/JFJochServices.h b/broker/JFJochServices.h index b0389261..eaa710e2 100644 --- a/broker/JFJochServices.h +++ b/broker/JFJochServices.h @@ -23,7 +23,9 @@ public: void On(const DiffractionExperiment& experiment); void Off(); void ConfigureDetector(const DiffractionExperiment& experiment); - void Start(const DiffractionExperiment& experiment, const JFCalibration &calibration); + void Start(const DiffractionExperiment& experiment, + const PixelMask &pixel_mask, + const JFCalibration &calibration); JFJochServicesOutput Stop(); void Cancel(); void Trigger(); diff --git a/broker/JFJochStateMachine.cpp b/broker/JFJochStateMachine.cpp index 09e0050b..ef0e22ca 100644 --- a/broker/JFJochStateMachine.cpp +++ b/broker/JFJochStateMachine.cpp @@ -3,7 +3,7 @@ #include #include "JFJochStateMachine.h" -#include "../preview/WriteTIFF.h" +#include "../preview/JFJochTIFF.h" void ApplyDetectorSettings(DiffractionExperiment& experiment, const DetectorSettings &settings) { auto tmp = experiment; @@ -66,8 +66,10 @@ void ApplyRadialIntegrationSettings(DiffractionExperiment& experiment, const Rad } JFJochStateMachine::JFJochStateMachine(JFJochServices &in_services, Logger &in_logger) -: services(in_services), logger(in_logger), -data_processing_settings(DiffractionExperiment::DefaultDataProcessingSettings()) { + : services(in_services), + logger(in_logger), + data_processing_settings(DiffractionExperiment::DefaultDataProcessingSettings()), + pixel_mask(experiment) { } @@ -126,6 +128,7 @@ void JFJochStateMachine::TakePedestalInternalAll(std::unique_lock &u } } services.ConfigureDetector(experiment); + pixel_mask.LoadDetectorBadPixelMask(calibration->CalculateMask()); } catch (const std::exception &e) { logger.Error("Pedestal sequence error {}", e.what()); state = JFJochState::Error; @@ -158,7 +161,7 @@ void JFJochStateMachine::TakePedestalInternalG0(std::unique_lock &ul state = JFJochState::Pedestal; services.ConfigureDetector(local_experiment); - services.Start(local_experiment, *calibration); + services.Start(local_experiment, pixel_mask, *calibration); services.Trigger(); @@ -197,7 +200,7 @@ void JFJochStateMachine::TakePedestalInternalG1(std::unique_lock &ul state = JFJochState::Pedestal; services.ConfigureDetector(local_experiment); - services.Start(local_experiment, *calibration); + services.Start(local_experiment, pixel_mask, *calibration); services.Trigger(); @@ -236,7 +239,7 @@ void JFJochStateMachine::TakePedestalInternalG2(std::unique_lock &ul state = JFJochState::Pedestal; services.ConfigureDetector(local_experiment); - services.Start(local_experiment, *calibration); + services.Start(local_experiment, pixel_mask, *calibration); services.Trigger(); @@ -326,7 +329,7 @@ void JFJochStateMachine::Start(const DatasetSettings& settings) { try { state = JFJochState::Busy; services.SetSpotFindingSettings(GetSpotFindingSettings()); - services.Start(experiment, *calibration); + services.Start(experiment, pixel_mask, *calibration); state = JFJochState::Measuring; measurement = std::async(std::launch::async, &JFJochStateMachine::MeasurementThread, this); @@ -562,6 +565,7 @@ void JFJochStateMachine::AddDetectorSetup(const DetectorSetup &setup) { experiment.Detector(setup); gain_calibration = setup.GetGainCalibration(); current_detector_setup = 0; + pixel_mask = PixelMask(setup); } detector_setup.emplace_back(setup); } @@ -599,6 +603,7 @@ void JFJochStateMachine::SelectDetector(int64_t id) { try { experiment.Detector(detector_setup[id]); gain_calibration = detector_setup[id].GetGainCalibration(); + pixel_mask = PixelMask(detector_setup[id]); state = JFJochState::Inactive; current_detector_setup = id; } catch (JFJochException &e) { @@ -705,6 +710,21 @@ void JFJochStateMachine::LoadInternalGeneratorImage(const void *data, size_t siz services.LoadInternalGeneratorImage(experiment, image, image_number); } +void JFJochStateMachine::LoadInternalGeneratorImageTIFF(const std::string &s, uint64_t image_number) { + std::unique_lock ul(m); + + if (state != JFJochState::Idle) + throw WrongDAQStateException ("Can change internal generator image only when detector in Idle state"); + + uint32_t cols, lines; + auto v = ReadTIFFFromString16(s, cols, lines); + if (((cols == experiment.GetXPixelsNum()) && (lines == experiment.GetYPixelsNum())) + || ((cols == RAW_MODULE_SIZE) && (lines == RAW_MODULE_LINES * experiment.GetModulesNum()))) + services.LoadInternalGeneratorImage(experiment, v, image_number); + else + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Image size doesn't match current detector"); +} + void JFJochStateMachine::SetBoxROI(const std::vector &input) { std::unique_lock ul(m); @@ -744,3 +764,33 @@ std::vector JFJochStateMachine::GetXFELEventCode() const { services.GetXFELEventCode(ret); return ret; } + +std::string JFJochStateMachine::GetFullPixelMaskTIFF() const { + std::unique_lock ul(m); + std::vector v = pixel_mask.GetMask(experiment); + return WriteTIFFToString(v.data(), experiment.GetXPixelsNum(), experiment.GetYPixelsNum(), + sizeof(uint32_t), false); +} + +std::string JFJochStateMachine::GetUserPixelMaskTIFF() const { + std::unique_lock ul(m); + std::vector v = pixel_mask.GetUserMask(experiment); + return WriteTIFFToString(v.data(), experiment.GetXPixelsNum(), experiment.GetYPixelsNum(), + sizeof(uint32_t), false); +} + +void JFJochStateMachine::SetUserPixelMask(const std::string &s) { + std::unique_lock ul(m); + + if (state != JFJochState::Idle) + throw WrongDAQStateException ("User mask can be only modified in Idle state"); + + try { + uint32_t cols, lines; + auto v = ReadTIFFFromString32(s, cols, lines); + pixel_mask.LoadUserMask(experiment, v); + } catch (const JFJochException &e) { + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, + "Problem handling user mask " + std::string(e.what())); + } +} diff --git a/broker/JFJochStateMachine.h b/broker/JFJochStateMachine.h index fb7f6d77..3d5132d1 100644 --- a/broker/JFJochStateMachine.h +++ b/broker/JFJochStateMachine.h @@ -98,6 +98,8 @@ class JFJochStateMachine { volatile JFJochState state = JFJochState::Inactive; volatile bool cancel_sequence = false; std::unique_ptr calibration; + PixelMask pixel_mask; + std::vector gain_calibration; std::vector detector_setup; int64_t current_detector_setup; @@ -172,6 +174,7 @@ public: std::string GetPedestalTIFF(size_t gain_level, size_t sc) const; void LoadInternalGeneratorImage(const void *data, size_t size, uint64_t image_number); + void LoadInternalGeneratorImageTIFF(const std::string &s, uint64_t image_number); // Not thread safe - only for configuration in serial context DiffractionExperiment& NotThreadSafe_Experiment(); @@ -187,6 +190,10 @@ public: std::vector GetXFELPulseID() const; std::vector GetXFELEventCode() const; + + std::string GetFullPixelMaskTIFF() const; + std::string GetUserPixelMaskTIFF() const; + void SetUserPixelMask(const std::string &v); }; diff --git a/broker/gen/api/DefaultApi.cpp b/broker/gen/api/DefaultApi.cpp index d223829b..00240d17 100644 --- a/broker/gen/api/DefaultApi.cpp +++ b/broker/gen/api/DefaultApi.cpp @@ -37,12 +37,16 @@ void DefaultApi::setupRoutes() { Routes::Get(*router, base + "/config/detector", Routes::bind(&DefaultApi::config_detector_get_handler, this)); Routes::Put(*router, base + "/config/detector", Routes::bind(&DefaultApi::config_detector_put_handler, this)); Routes::Put(*router, base + "/config/internal_generator_image", Routes::bind(&DefaultApi::config_internal_generator_image_put_handler, this)); + Routes::Put(*router, base + "/config/internal_generator_image.tiff", Routes::bind(&DefaultApi::config_internal_generator_image_tiff_put_handler, this)); + Routes::Get(*router, base + "/config/mask.tiff", Routes::bind(&DefaultApi::config_mask_tiff_get_handler, this)); Routes::Get(*router, base + "/config/rad_int", Routes::bind(&DefaultApi::config_rad_int_get_handler, this)); Routes::Put(*router, base + "/config/rad_int", Routes::bind(&DefaultApi::config_rad_int_put_handler, this)); Routes::Get(*router, base + "/config/select_detector", Routes::bind(&DefaultApi::config_select_detector_get_handler, this)); Routes::Put(*router, base + "/config/select_detector", Routes::bind(&DefaultApi::config_select_detector_put_handler, this)); Routes::Get(*router, base + "/config/spot_finding", Routes::bind(&DefaultApi::config_spot_finding_get_handler, this)); Routes::Put(*router, base + "/config/spot_finding", Routes::bind(&DefaultApi::config_spot_finding_put_handler, this)); + Routes::Get(*router, base + "/config/user_mask.tiff", Routes::bind(&DefaultApi::config_user_mask_tiff_get_handler, this)); + Routes::Put(*router, base + "/config/user_mask.tiff", Routes::bind(&DefaultApi::config_user_mask_tiff_put_handler, this)); Routes::Post(*router, base + "/deactivate", Routes::bind(&DefaultApi::deactivate_post_handler, this)); Routes::Get(*router, base + "/detector/status", Routes::bind(&DefaultApi::detector_status_get_handler, this)); Routes::Post(*router, base + "/initialize", Routes::bind(&DefaultApi::initialize_post_handler, this)); @@ -192,6 +196,45 @@ void DefaultApi::config_internal_generator_image_put_handler(const Pistache::Res response.send(Pistache::Http::Code::Internal_Server_Error, e.what()); } +} +void DefaultApi::config_internal_generator_image_tiff_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) { + try { + + try { + this->config_internal_generator_image_tiff_put(request, response); + } catch (Pistache::Http::HttpError &e) { + response.send(static_cast(e.code()), e.what()); + return; + } catch (std::exception &e) { + const std::pair errorInfo = this->handleOperationException(e); + response.send(errorInfo.first, errorInfo.second); + return; + } + + } catch (std::exception &e) { + response.send(Pistache::Http::Code::Internal_Server_Error, e.what()); + } + +} +void DefaultApi::config_mask_tiff_get_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) { + try { + + + try { + this->config_mask_tiff_get(response); + } catch (Pistache::Http::HttpError &e) { + response.send(static_cast(e.code()), e.what()); + return; + } catch (std::exception &e) { + const std::pair errorInfo = this->handleOperationException(e); + response.send(errorInfo.first, errorInfo.second); + return; + } + + } catch (std::exception &e) { + response.send(Pistache::Http::Code::Internal_Server_Error, e.what()); + } + } void DefaultApi::config_rad_int_get_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) { try { @@ -351,6 +394,45 @@ void DefaultApi::config_spot_finding_put_handler(const Pistache::Rest::Request & response.send(Pistache::Http::Code::Internal_Server_Error, e.what()); } +} +void DefaultApi::config_user_mask_tiff_get_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) { + try { + + + try { + this->config_user_mask_tiff_get(response); + } catch (Pistache::Http::HttpError &e) { + response.send(static_cast(e.code()), e.what()); + return; + } catch (std::exception &e) { + const std::pair errorInfo = this->handleOperationException(e); + response.send(errorInfo.first, errorInfo.second); + return; + } + + } catch (std::exception &e) { + response.send(Pistache::Http::Code::Internal_Server_Error, e.what()); + } + +} +void DefaultApi::config_user_mask_tiff_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) { + try { + + try { + this->config_user_mask_tiff_put(request, response); + } catch (Pistache::Http::HttpError &e) { + response.send(static_cast(e.code()), e.what()); + return; + } catch (std::exception &e) { + const std::pair errorInfo = this->handleOperationException(e); + response.send(errorInfo.first, errorInfo.second); + return; + } + + } catch (std::exception &e) { + response.send(Pistache::Http::Code::Internal_Server_Error, e.what()); + } + } void DefaultApi::deactivate_post_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) { try { diff --git a/broker/gen/api/DefaultApi.h b/broker/gen/api/DefaultApi.h index 4530c04f..3e3c474b 100644 --- a/broker/gen/api/DefaultApi.h +++ b/broker/gen/api/DefaultApi.h @@ -61,12 +61,16 @@ private: void config_detector_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void config_detector_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void config_internal_generator_image_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); + void config_internal_generator_image_tiff_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); + void config_mask_tiff_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void config_rad_int_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void config_rad_int_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void config_select_detector_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void config_select_detector_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void config_spot_finding_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void config_spot_finding_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); + void config_user_mask_tiff_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); + void config_user_mask_tiff_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void deactivate_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void detector_status_get_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); void initialize_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); @@ -150,6 +154,20 @@ private: /// virtual void config_internal_generator_image_put(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response) = 0; /// + /// Load TIFF image for internal FPGA generator + /// + /// + /// Load image for internal FPGA generator. This can only happen in Idle state of the detector. Requires TIFF with 16-bit integer numbers of size of detector in raw/converted coordinates (depending on detector settings). + /// + virtual void config_internal_generator_image_tiff_put(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response) = 0; + /// + /// Get mask of the detector + /// + /// + /// Get full pixel mask of the detector See NXmx standard for meaning of pixel values + /// + virtual void config_mask_tiff_get(Pistache::Http::ResponseWriter &response) = 0; + /// /// Get radial integration configuration /// /// @@ -195,6 +213,20 @@ private: /// (optional) virtual void config_spot_finding_put(const org::openapitools::server::model::Spot_finding_settings &spotFindingSettings, Pistache::Http::ResponseWriter &response) = 0; /// + /// Get user mask of the detector + /// + /// + /// Get user pixel mask of the detector in the actual detector coordinates: 0 - good pixel, 1 - masked + /// + virtual void config_user_mask_tiff_get(Pistache::Http::ResponseWriter &response) = 0; + /// + /// Upload user mask of the detector + /// + /// + /// Should be in `Idle` state. Upload user mask of the detector - this is for example to account for beam stop shadow or misbehaving regions. If detector is conversion mode the mask can be both in raw (1024x512; stacked modules) or converted coordinates. In the latter case - module gaps are ignored and don't need to be assigned value. Mask is expected as TIFF (4-byte; unsigned). 0 - good pixel, other value - masked User mask is stored in NXmx pixel mask (bit 8), as well as used in spot finding and azimuthal integration. User mask is not automatically applied - i.e. pixels with user mask will have a valid pixel value in the images. + /// + virtual void config_user_mask_tiff_put(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response) = 0; + /// /// Prepare detector to turn off /// /// diff --git a/broker/gen/model/Preview_settings.cpp b/broker/gen/model/Preview_settings.cpp index 68090ecb..9e4db3fa 100644 --- a/broker/gen/model/Preview_settings.cpp +++ b/broker/gen/model/Preview_settings.cpp @@ -26,11 +26,13 @@ Preview_settings::Preview_settings() m_Show_spotsIsSet = false; m_Show_roi = false; m_Show_roiIsSet = false; - m_Jpeg_quality = 0L; + m_Jpeg_quality = 100L; m_Jpeg_qualityIsSet = false; m_Show_indexed = false; m_Show_indexedIsSet = false; - m_Resolution_ring = 0.0f; + m_Show_user_mask = false; + m_Show_user_maskIsSet = false; + m_Resolution_ring = 0.1f; m_Resolution_ringIsSet = false; } @@ -92,7 +94,7 @@ bool Preview_settings::validate(std::stringstream& msg, const std::string& pathP } } - + if (resolutionRingIsSet()) { const float& value = m_Resolution_ring; @@ -136,6 +138,9 @@ bool Preview_settings::operator==(const Preview_settings& rhs) const ((!showIndexedIsSet() && !rhs.showIndexedIsSet()) || (showIndexedIsSet() && rhs.showIndexedIsSet() && isShowIndexed() == rhs.isShowIndexed())) && + ((!showUserMaskIsSet() && !rhs.showUserMaskIsSet()) || (showUserMaskIsSet() && rhs.showUserMaskIsSet() && isShowUserMask() == rhs.isShowUserMask())) && + + ((!resolutionRingIsSet() && !rhs.resolutionRingIsSet()) || (resolutionRingIsSet() && rhs.resolutionRingIsSet() && getResolutionRing() == rhs.getResolutionRing())) ; @@ -158,6 +163,8 @@ void to_json(nlohmann::json& j, const Preview_settings& o) j["jpeg_quality"] = o.m_Jpeg_quality; if(o.showIndexedIsSet()) j["show_indexed"] = o.m_Show_indexed; + if(o.showUserMaskIsSet()) + j["show_user_mask"] = o.m_Show_user_mask; if(o.resolutionRingIsSet()) j["resolution_ring"] = o.m_Resolution_ring; @@ -186,6 +193,11 @@ void from_json(const nlohmann::json& j, Preview_settings& o) j.at("show_indexed").get_to(o.m_Show_indexed); o.m_Show_indexedIsSet = true; } + if(j.find("show_user_mask") != j.end()) + { + j.at("show_user_mask").get_to(o.m_Show_user_mask); + o.m_Show_user_maskIsSet = true; + } if(j.find("resolution_ring") != j.end()) { j.at("resolution_ring").get_to(o.m_Resolution_ring); @@ -270,6 +282,23 @@ void Preview_settings::unsetShow_indexed() { m_Show_indexedIsSet = false; } +bool Preview_settings::isShowUserMask() const +{ + return m_Show_user_mask; +} +void Preview_settings::setShowUserMask(bool const value) +{ + m_Show_user_mask = value; + m_Show_user_maskIsSet = true; +} +bool Preview_settings::showUserMaskIsSet() const +{ + return m_Show_user_maskIsSet; +} +void Preview_settings::unsetShow_user_mask() +{ + m_Show_user_maskIsSet = false; +} float Preview_settings::getResolutionRing() const { return m_Resolution_ring; diff --git a/broker/gen/model/Preview_settings.h b/broker/gen/model/Preview_settings.h index c8311cc5..4d814e70 100644 --- a/broker/gen/model/Preview_settings.h +++ b/broker/gen/model/Preview_settings.h @@ -91,6 +91,13 @@ public: bool showIndexedIsSet() const; void unsetShow_indexed(); /// + /// Show user mask + /// + bool isShowUserMask() const; + void setShowUserMask(bool const value); + bool showUserMaskIsSet() const; + void unsetShow_user_mask(); + /// /// /// float getResolutionRing() const; @@ -111,6 +118,8 @@ protected: bool m_Jpeg_qualityIsSet; bool m_Show_indexed; bool m_Show_indexedIsSet; + bool m_Show_user_mask; + bool m_Show_user_maskIsSet; float m_Resolution_ring; bool m_Resolution_ringIsSet; diff --git a/broker/gen/model/Spot_finding_settings.cpp b/broker/gen/model/Spot_finding_settings.cpp index 1ad37c0b..98083b07 100644 --- a/broker/gen/model/Spot_finding_settings.cpp +++ b/broker/gen/model/Spot_finding_settings.cpp @@ -23,6 +23,10 @@ Spot_finding_settings::Spot_finding_settings() { m_Enable = true; m_Indexing = true; + m_Filter_powder_rings = false; + m_Filter_powder_ringsIsSet = false; + m_Min_spot_count_powder_ring = 20L; + m_Min_spot_count_powder_ringIsSet = false; m_Signal_to_noise_threshold = 0.0f; m_Photon_count_threshold = 0L; m_Min_pix_per_spot = 0L; @@ -52,7 +56,21 @@ bool Spot_finding_settings::validate(std::stringstream& msg, const std::string& bool success = true; const std::string _pathPrefix = pathPrefix.empty() ? "Spot_finding_settings" : pathPrefix; - + + if (minSpotCountPowderRingIsSet()) + { + const int64_t& value = m_Min_spot_count_powder_ring; + const std::string currentValuePath = _pathPrefix + ".minSpotCountPowderRing"; + + + if (value < 5ll) + { + success = false; + msg << currentValuePath << ": must be greater than or equal to 5;"; + } + + } + /* Signal_to_noise_threshold */ { const float& value = m_Signal_to_noise_threshold; @@ -142,6 +160,12 @@ bool Spot_finding_settings::operator==(const Spot_finding_settings& rhs) const (isIndexing() == rhs.isIndexing()) && + + ((!filterPowderRingsIsSet() && !rhs.filterPowderRingsIsSet()) || (filterPowderRingsIsSet() && rhs.filterPowderRingsIsSet() && isFilterPowderRings() == rhs.isFilterPowderRings())) && + + + ((!minSpotCountPowderRingIsSet() && !rhs.minSpotCountPowderRingIsSet()) || (minSpotCountPowderRingIsSet() && rhs.minSpotCountPowderRingIsSet() && getMinSpotCountPowderRing() == rhs.getMinSpotCountPowderRing())) && + (getSignalToNoiseThreshold() == rhs.getSignalToNoiseThreshold()) && @@ -176,6 +200,10 @@ void to_json(nlohmann::json& j, const Spot_finding_settings& o) j = nlohmann::json(); j["enable"] = o.m_Enable; j["indexing"] = o.m_Indexing; + if(o.filterPowderRingsIsSet()) + j["filter_powder_rings"] = o.m_Filter_powder_rings; + if(o.minSpotCountPowderRingIsSet()) + j["min_spot_count_powder_ring"] = o.m_Min_spot_count_powder_ring; j["signal_to_noise_threshold"] = o.m_Signal_to_noise_threshold; j["photon_count_threshold"] = o.m_Photon_count_threshold; j["min_pix_per_spot"] = o.m_Min_pix_per_spot; @@ -190,6 +218,16 @@ void from_json(const nlohmann::json& j, Spot_finding_settings& o) { j.at("enable").get_to(o.m_Enable); j.at("indexing").get_to(o.m_Indexing); + if(j.find("filter_powder_rings") != j.end()) + { + j.at("filter_powder_rings").get_to(o.m_Filter_powder_rings); + o.m_Filter_powder_ringsIsSet = true; + } + if(j.find("min_spot_count_powder_ring") != j.end()) + { + j.at("min_spot_count_powder_ring").get_to(o.m_Min_spot_count_powder_ring); + o.m_Min_spot_count_powder_ringIsSet = true; + } j.at("signal_to_noise_threshold").get_to(o.m_Signal_to_noise_threshold); j.at("photon_count_threshold").get_to(o.m_Photon_count_threshold); j.at("min_pix_per_spot").get_to(o.m_Min_pix_per_spot); @@ -216,6 +254,40 @@ void Spot_finding_settings::setIndexing(bool const value) { m_Indexing = value; } +bool Spot_finding_settings::isFilterPowderRings() const +{ + return m_Filter_powder_rings; +} +void Spot_finding_settings::setFilterPowderRings(bool const value) +{ + m_Filter_powder_rings = value; + m_Filter_powder_ringsIsSet = true; +} +bool Spot_finding_settings::filterPowderRingsIsSet() const +{ + return m_Filter_powder_ringsIsSet; +} +void Spot_finding_settings::unsetFilter_powder_rings() +{ + m_Filter_powder_ringsIsSet = false; +} +int64_t Spot_finding_settings::getMinSpotCountPowderRing() const +{ + return m_Min_spot_count_powder_ring; +} +void Spot_finding_settings::setMinSpotCountPowderRing(int64_t const value) +{ + m_Min_spot_count_powder_ring = value; + m_Min_spot_count_powder_ringIsSet = true; +} +bool Spot_finding_settings::minSpotCountPowderRingIsSet() const +{ + return m_Min_spot_count_powder_ringIsSet; +} +void Spot_finding_settings::unsetMin_spot_count_powder_ring() +{ + m_Min_spot_count_powder_ringIsSet = false; +} float Spot_finding_settings::getSignalToNoiseThreshold() const { return m_Signal_to_noise_threshold; diff --git a/broker/gen/model/Spot_finding_settings.h b/broker/gen/model/Spot_finding_settings.h index b556d4d7..c7640ef0 100644 --- a/broker/gen/model/Spot_finding_settings.h +++ b/broker/gen/model/Spot_finding_settings.h @@ -58,16 +58,30 @@ public: /// Spot_finding_settings members /// - /// Enable spot finding + /// Enable spot finding. This is temporary setting, i.e. can be changed anytime during data collection. Even if disabled spot finding information will still be send and written, though always with zero spots. /// bool isEnable() const; void setEnable(bool const value); /// - /// Enable indexing + /// Enable indexing. This is temporary setting, i.e. can be changed anytime during data collection. /// bool isIndexing() const; void setIndexing(bool const value); /// + /// Filter spots which form powder rings (e.g., ice rings) + /// + bool isFilterPowderRings() const; + void setFilterPowderRings(bool const value); + bool filterPowderRingsIsSet() const; + void unsetFilter_powder_rings(); + /// + /// Minimum number of spots to consider a thin resolution shell (0.01 A^-1) a powder ring and filter out. + /// + int64_t getMinSpotCountPowderRing() const; + void setMinSpotCountPowderRing(int64_t const value); + bool minSpotCountPowderRingIsSet() const; + void unsetMin_spot_count_powder_ring(); + /// /// /// float getSignalToNoiseThreshold() const; @@ -110,6 +124,10 @@ protected: bool m_Indexing; + bool m_Filter_powder_rings; + bool m_Filter_powder_ringsIsSet; + int64_t m_Min_spot_count_powder_ring; + bool m_Min_spot_count_powder_ringIsSet; float m_Signal_to_noise_threshold; int64_t m_Photon_count_threshold; diff --git a/broker/jfjoch_api.yaml b/broker/jfjoch_api.yaml index f30f520a..51fba6e0 100644 --- a/broker/jfjoch_api.yaml +++ b/broker/jfjoch_api.yaml @@ -333,11 +333,23 @@ components: enable: type: boolean default: true - description: Enable spot finding + description: | + Enable spot finding. This is temporary setting, i.e. can be changed anytime during data collection. + Even if disabled spot finding information will still be send and written, though always with zero spots. indexing: type: boolean default: true - description: Enable indexing + description: | + Enable indexing. This is temporary setting, i.e. can be changed anytime during data collection. + filter_powder_rings: + type: boolean + default: false + description: Filter spots which form powder rings (e.g., ice rings) + min_spot_count_powder_ring: + type: integer + format: int64 + minimum: 5 + description: Minimum number of spots to consider a thin resolution shell (0.01 A^-1) a powder ring and filter out. signal_to_noise_threshold: type: number format: float @@ -620,14 +632,21 @@ components: type: integer description: "Quality of JPEG image (100 - highest; 0 - lowest)" format: int64 + default: 100 minimum: 0 maximum: 100 show_indexed: type: boolean description: "Preview indexed images only" + default: false + show_user_mask: + type: boolean + description: "Show user mask" + default: false resolution_ring: type: number format: float + default: 0.1 minimum: 0.1 maximum: 100.0 error_message: @@ -967,9 +986,9 @@ paths: Requires binary blob with 16-bit integer numbers of size of detector in raw/converted coordinates (depending on detector settings). parameters: - - name: number + - name: id in: query - description: Image number to upload + description: Image id to upload required: false schema: type: integer @@ -992,6 +1011,38 @@ paths: schema: type: string description: Exception error + /config/internal_generator_image.tiff: + put: + summary: Load TIFF image for internal FPGA generator + description: | + Load image for internal FPGA generator. This can only happen in Idle state of the detector. + Requires TIFF with 16-bit integer numbers of size of detector in raw/converted coordinates + (depending on detector settings). + parameters: + - in: query + name: id + description: Image ID to upload + required: false + schema: + type: integer + minimum: 0 + maximum: 127 + requestBody: + content: + image/tiff: + schema: + type: string + format: binary + responses: + "200": + description: Everything OK + "400": + description: Input parsing or validation error + content: + text/plain: + schema: + type: string + description: Exception error /config/select_detector: put: summary: Select detector @@ -1564,6 +1615,63 @@ paths: format: binary "404": description: No preview image recorded so far + /config/mask.tiff: + get: + summary: Get mask of the detector + description: | + Get full pixel mask of the detector + See NXmx standard for meaning of pixel values + responses: + "200": + description: Pixel mask in TIFF format (4 byte; unsigned) + content: + image/tiff: + schema: + type: string + format: binary + /config/user_mask.tiff: + get: + summary: Get user mask of the detector + description: "Get user pixel mask of the detector in the actual detector coordinates: 0 - good pixel, 1 - masked" + responses: + "200": + description: User mask in TIFF format (4 byte; unsigned) + content: + image/tiff: + schema: + type: string + format: binary + put: + summary: Upload user mask of the detector + description: | + Should be in `Idle` state. + Upload user mask of the detector - this is for example to account for beam stop shadow or misbehaving regions. + If detector is conversion mode the mask can be both in raw (1024x512; stacked modules) or converted coordinates. + In the latter case - module gaps are ignored and don't need to be assigned value. + Mask is expected as TIFF (4-byte; unsigned). + 0 - good pixel, other value - masked + User mask is stored in NXmx pixel mask (bit 8), as well as used in spot finding and azimuthal integration. + User mask is not automatically applied - i.e. pixels with user mask will have a valid pixel value in the images. + requestBody: + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + "200": + description: All good + content: + image/tiff: + schema: + type: string + format: binary + "500": + description: Error within Jungfraujoch code - see output message. + content: + application/json: + schema: + $ref: '#/components/schemas/error_message' /preview/pedestal.tiff: get: parameters: diff --git a/broker/redoc-static.html b/broker/redoc-static.html index cca0b980..bbd2b6ba 100644 --- a/broker/redoc-static.html +++ b/broker/redoc-static.html @@ -341,7 +341,7 @@ data-styled.g137[id="sc-cMdfCE"]{content:"dvQijr,"}/*!sc*/ -

Everything OK

Response samples

Content type
application/json
{
  • "frame_time_us": 450,
  • "count_time_us": 0,
  • "storage_cell_count": 1,
  • "internal_frame_generator": false,
  • "internal_frame_generator_images": 1,
  • "collect_raw_data": false,
  • "pedestal_g0_frames": 0,
  • "pedestal_g1_frames": 0,
  • "pedestal_g2_frames": 0,
  • "storage_cell_delay_us": 0.1,
  • "detector_trigger_delay_us": 0.1,
  • "fixed_gain_g1": false,
  • "use_gain_hg0": false
}

Configure spot finding

Can be done anytime, also while data collection is running

-
Request Body schema: application/json
enable
required
boolean
Default: true

Enable spot finding

-
indexing
required
boolean
Default: true

Enable indexing

+
Request Body schema: application/json
enable
required
boolean
Default: true

Enable spot finding. This is temporary setting, i.e. can be changed anytime during data collection. +Even if disabled spot finding information will still be send and written, though always with zero spots.

+
indexing
required
boolean
Default: true

Enable indexing. This is temporary setting, i.e. can be changed anytime during data collection.

+
filter_powder_rings
boolean
Default: false

Filter spots which form powder rings (e.g., ice rings)

+
min_spot_count_powder_ring
integer <int64> >= 5
Default: 20

Minimum number of spots to consider a thin resolution shell (0.01 A^-1) a powder ring and filter out.

signal_to_noise_threshold
required
number <float> >= 0
photon_count_threshold
required
integer <int64> >= 0
min_pix_per_spot
required
integer <int64> >= 1
max_pix_per_spot
required
integer <int64> >= 1
high_resolution_limit
required
number <float>
low_resolution_limit
required
number <float>
indexing_tolerance
required
number <float> [ 0 .. 1 ]

Acceptance tolerance for spots after the indexing run - the larger the number, the more spots will be accepted

Responses

Request samples

Content type
application/json
{
  • "enable": true,
  • "indexing": true,
  • "signal_to_noise_threshold": 0.1,
  • "photon_count_threshold": 0,
  • "min_pix_per_spot": 1,
  • "max_pix_per_spot": 1,
  • "high_resolution_limit": 0.1,
  • "low_resolution_limit": 0.1,
  • "indexing_tolerance": 1
}

Get data processing configuration

Request samples

Content type
application/json
{
  • "enable": true,
  • "indexing": true,
  • "filter_powder_rings": false,
  • "min_spot_count_powder_ring": 20,
  • "signal_to_noise_threshold": 0.1,
  • "photon_count_threshold": 0,
  • "min_pix_per_spot": 1,
  • "max_pix_per_spot": 1,
  • "high_resolution_limit": 0.1,
  • "low_resolution_limit": 0.1,
  • "indexing_tolerance": 1
}

Get data processing configuration

Can be done anytime

Responses

Response samples

Content type
application/json
{
  • "enable": true,
  • "indexing": true,
  • "signal_to_noise_threshold": 0.1,
  • "photon_count_threshold": 0,
  • "min_pix_per_spot": 1,
  • "max_pix_per_spot": 1,
  • "high_resolution_limit": 0.1,
  • "low_resolution_limit": 0.1,
  • "indexing_tolerance": 1
}

Configure radial integration

Response samples

Content type
application/json
{
  • "enable": true,
  • "indexing": true,
  • "filter_powder_rings": false,
  • "min_spot_count_powder_ring": 20,
  • "signal_to_noise_threshold": 0.1,
  • "photon_count_threshold": 0,
  • "min_pix_per_spot": 1,
  • "max_pix_per_spot": 1,
  • "high_resolution_limit": 0.1,
  • "low_resolution_limit": 0.1,
  • "indexing_tolerance": 1
}

Configure radial integration

Can be done when detector is Inactive or Idle

Request Body schema: application/json
polarization_factor
number <float> [ -1 .. 1 ]

If polarization factor is provided, than polarization correction is enabled.

@@ -581,13 +587,25 @@ Requires binary blob with 16-bit integer numbers of size of detector in raw/conv " class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS">

Load image for internal FPGA generator. This can only happen in Idle state of the detector. Requires binary blob with 16-bit integer numbers of size of detector in raw/converted coordinates (depending on detector settings).

-
query Parameters
number
integer <int64> [ 0 .. 127 ]

Image number to upload

+
query Parameters
id
integer <int64> [ 0 .. 127 ]

Image id to upload

Request Body schema: application/octet-stream
string <binary>

Responses

Select detector

Load TIFF image for internal FPGA generator

Load image for internal FPGA generator. This can only happen in Idle state of the detector. +Requires TIFF with 16-bit integer numbers of size of detector in raw/converted coordinates +(depending on detector settings).

+
query Parameters
id
integer [ 0 .. 127 ]

Image ID to upload

+
Request Body schema: image/tiff
string <binary>

Responses

Select detector

Jungfraujoch allows to control multiple detectors and/or region-of-interests. @@ -759,11 +777,13 @@ Changing detector will set detector to Inactive state and will requ " class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg">

Show spot finding results on the image

show_roi
boolean
Default: false

Show ROI areas on the image

-
jpeg_quality
integer <int64> [ 0 .. 100 ]
jpeg_quality
integer <int64> [ 0 .. 100 ]
Default: 100

Quality of JPEG image (100 - highest; 0 - lowest)

-
show_indexed
boolean
show_indexed
boolean
Default: false

Preview indexed images only

-
resolution_ring
number <float> [ 0.1 .. 100 ]

Responses

show_user_mask
boolean
Default: false

Show user mask

+
resolution_ring
number <float> [ 0.1 .. 100 ]
Default: 0.1

Responses

Request samples

Content type
application/json
{
  • "saturation": 65535,
  • "show_spots": true,
  • "show_roi": false,
  • "jpeg_quality": 100,
  • "show_indexed": true,
  • "resolution_ring": 0.1
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Get last preview image in JPEG format using default settings

Responses

Request samples

Content type
application/json
{
  • "saturation": 65535,
  • "show_spots": true,
  • "show_roi": false,
  • "jpeg_quality": 100,
  • "show_indexed": false,
  • "show_user_mask": false,
  • "resolution_ring": 0.1
}

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Get last preview image in JPEG format using default settings

Responses

Get pedestal G0 in TIFF format

query Parameters
gain_level
required
integer

Get mask of the detector

Get full pixel mask of the detector +See NXmx standard for meaning of pixel values

+

Responses

Get user mask of the detector

Get user pixel mask of the detector in the actual detector coordinates: 0 - good pixel, 1 - masked

+

Responses

Upload user mask of the detector

Should be in Idle state. +Upload user mask of the detector - this is for example to account for beam stop shadow or misbehaving regions. +If detector is conversion mode the mask can be both in raw (1024x512; stacked modules) or converted coordinates. +In the latter case - module gaps are ignored and don't need to be assigned value. +Mask is expected as TIFF (4-byte; unsigned). +0 - good pixel, other value - masked +User mask is stored in NXmx pixel mask (bit 8), as well as used in spot finding and azimuthal integration. +User mask is not automatically applied - i.e. pixels with user mask will have a valid pixel value in the images.

+
Request Body schema: application/octet-stream
string <binary>

Responses

Response samples

Content type
application/json
{
  • "msg": "Detector in wrong state",
  • "reason": "WrongDAQState"
}

Get pedestal G0 in TIFF format

query Parameters
gain_level
required
integer

Gain level (0, 1, 2)

sc
integer

Storage cell number

@@ -795,7 +845,7 @@ Changing detector will set detector to Inactive state and will requ " class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS sc-ckdEwu LxEPk">

No calibration recorded so far