diff --git a/acquisition_device/AcquisitionDevice.cpp b/acquisition_device/AcquisitionDevice.cpp index e71e0554..4a61dba6 100644 --- a/acquisition_device/AcquisitionDevice.cpp +++ b/acquisition_device/AcquisitionDevice.cpp @@ -291,6 +291,7 @@ void AcquisitionDevice::RunInternalGenerator(const DiffractionExperiment &experi config.debug = INT_PKT_GEN_DEBUG; config.dest_mac_addr = MacAddressFromStr(GetMACAddress()); config.dest_ipv4_addr = IPv4AddressFromStr(GetIPv4Address()); + config.images_in_memory = experiment.GetInternalPacketGeneratorImages() - 1; switch (experiment.GetDetectorSetup().GetDetectorType()) { case DetectorType::JUNGFRAU: config.detector_type = SLS_DETECTOR_TYPE_JUNGFRAU; diff --git a/broker/JFJochBrokerHttp.cpp b/broker/JFJochBrokerHttp.cpp index 87a6ebde..825c6394 100644 --- a/broker/JFJochBrokerHttp.cpp +++ b/broker/JFJochBrokerHttp.cpp @@ -85,10 +85,12 @@ inline DetectorSettings Convert(const org::openapitools::server::model::Detector ret.pedestal_g1_frames = input.getPedestalG1Frames(); if (input.pedestalG2FramesIsSet()) ret.pedestal_g2_frames = input.getPedestalG2Frames(); - if (input.storageCellDelayNsIsSet()) - ret.storage_cell_delay_ns = input.getStorageCellDelayNs(); - if (input.detectorTriggerDelayNsIsSet()) - ret.detector_delay_ns = input.getDetectorTriggerDelayNs(); + if (input.storageCellDelayUsIsSet() && std::isfinite(input.getStorageCellDelayUs())) + ret.storage_cell_delay_ns = std::round(input.getStorageCellDelayUs() * 1000.0f); + if (input.detectorTriggerDelayUsIsSet() && std::isfinite(input.getDetectorTriggerDelayUs())) + ret.detector_delay_ns = std::round(input.getDetectorTriggerDelayUs() * 1000.0f); + if (input.internalFrameGeneratorImagesIsSet()) + ret.internal_packet_generator_images = input.getInternalFrameGeneratorImages(); return ret; } @@ -97,20 +99,28 @@ inline org::openapitools::server::model::Detector_settings Convert(const Detecto org::openapitools::server::model::Detector_settings ret{}; ret.setFrameTimeUs(input.frame_time_us); - ret.setCountTimeUs(input.count_time_us.value()); + if (input.count_time_us) + ret.setCountTimeUs(input.count_time_us.value()); ret.setStorageCellCount(input.storage_cell_count); ret.setInternalFrameGenerator(input.use_internal_packet_generator); ret.setCollectRawData(input.collect_raw_data); ret.setFixedGainG1(input.fixed_gain_g1); ret.setUseGainHg0(input.use_gain_hg0); - ret.setPedestalG0Frames(input.pedestal_g0_frames.value()); - ret.setPedestalG1Frames(input.pedestal_g1_frames.value()); - ret.setPedestalG2Frames(input.pedestal_g2_frames.value()); - ret.setStorageCellDelayNs(input.storage_cell_delay_ns.value()); - ret.setDetectorTriggerDelayNs(input.detector_delay_ns.value()); + if (input.pedestal_g0_frames) + ret.setPedestalG0Frames(input.pedestal_g0_frames.value()); + if (input.pedestal_g1_frames) + ret.setPedestalG1Frames(input.pedestal_g1_frames.value()); + if (input.pedestal_g2_frames) + ret.setPedestalG2Frames(input.pedestal_g2_frames.value()); + if (input.storage_cell_delay_ns) + ret.setStorageCellDelayUs(static_cast(input.storage_cell_delay_ns.value()) / 1000.0f); + if (input.detector_delay_ns) + ret.setDetectorTriggerDelayUs(static_cast(input.detector_delay_ns.value()) / 1000.0f); + if (input.internal_packet_generator_images) + ret.setInternalFrameGeneratorImages(input.internal_packet_generator_images.value()); return ret; } @@ -276,92 +286,91 @@ inline org::openapitools::server::model::Preview_settings Convert(const PreviewJ inline DatasetSettings Convert(const org::openapitools::server::model::Dataset_settings& input) { DatasetSettings ret; - ret.images_per_trigger = input.getImagesPerTrigger(); - ret.ntrigger = input.ntriggerIsSet() ? input.getNtrigger() : 1; + ret.ImagesPerTrigger(input.getImagesPerTrigger()); + ret.NumTriggers(input.getNtrigger()); if (!input.fpgaOutputIsSet()) - ret.fpga_pixel_output = FPGAPixelOutput::Auto; + ret.FPGAOutputMode(FPGAPixelOutput::Auto); else { std::string out = str_tolower(input.getFpgaOutput()); if (out == "auto") - ret.fpga_pixel_output = FPGAPixelOutput::Auto; + ret.FPGAOutputMode(FPGAPixelOutput::Auto); else if (out == "int16") - ret.fpga_pixel_output = FPGAPixelOutput::Int16; + ret.FPGAOutputMode(FPGAPixelOutput::Int16); else if (out == "uint16") - ret.fpga_pixel_output = FPGAPixelOutput::Uint16; + ret.FPGAOutputMode(FPGAPixelOutput::Uint16); else if (out == "int32") - ret.fpga_pixel_output = FPGAPixelOutput::Int32; + ret.FPGAOutputMode(FPGAPixelOutput::Int32); else if (out == "uint32") - ret.fpga_pixel_output = FPGAPixelOutput::Uint32; + ret.FPGAOutputMode(FPGAPixelOutput::Uint32); else throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Unknown output format"); } - ret.summation = input.summationIsSet() ? input.getSummation() : 1; - ret.beam_x_pxl = input.getBeamXPxl(); - ret.beam_y_pxl = input.getBeamYPxl(); - ret.detector_distance_mm = input.getDetectorDistanceMm(); - ret.photon_energy_keV = input.getPhotonEnergyKeV(); + ret.Summation(input.getSummation()); + ret.BeamX_pxl(input.getBeamXPxl()); + ret.BeamY_pxl(input.getBeamYPxl()); + ret.DetectorDistance_mm(input.getDetectorDistanceMm()); + ret.PhotonEnergy_keV(input.getPhotonEnergyKeV()); - ret.photon_energy_multiplier = input.getPhotonEnergyMultiplier(); + ret.PhotonEnergyMultiplayer(input.getPhotonEnergyMultiplier()); - ret.file_prefix = input.filePrefixIsSet() ? input.getFilePrefix() : ""; - ret.data_file_count = input.dataFileCountIsSet() ? input.getDataFileCount() : 1; + ret.FilePrefix(input.getFilePrefix()); + ret.DataFileCount(input.getDataFileCount()); if (!input.compressionIsSet()) - ret.compression = CompressionAlgorithm::BSHUF_LZ4; + ret.Compression(CompressionAlgorithm::BSHUF_LZ4); else { std::string compr = str_tolower(input.getCompression()); if (compr == "bslz4") - ret.compression = CompressionAlgorithm::BSHUF_LZ4; + ret.Compression(CompressionAlgorithm::BSHUF_LZ4); else if (compr == "bszstd") - ret.compression = CompressionAlgorithm::BSHUF_ZSTD; + ret.Compression(CompressionAlgorithm::BSHUF_ZSTD); else if (compr == "bszstd_rle") - ret.compression = CompressionAlgorithm::BSHUF_ZSTD_RLE; + ret.Compression(CompressionAlgorithm::BSHUF_ZSTD_RLE); else if (compr == "none") - ret.compression = CompressionAlgorithm::NO_COMPRESSION; + ret.Compression(CompressionAlgorithm::NO_COMPRESSION); else throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Unknown compression"); } if (input.unitCellIsSet()) - ret.unit_cell = UnitCell{ + ret.SetUnitCell(UnitCell{ .a = input.getUnitCell().getA(), .b = input.getUnitCell().getB(), .c = input.getUnitCell().getC(), .alpha = input.getUnitCell().getAlpha(), .beta = input.getUnitCell().getBeta(), .gamma = input.getUnitCell().getGamma() - }; + }); if (input.totalFluxIsSet()) - ret.total_flux = input.getTotalFlux(); + ret.TotalFlux(input.getTotalFlux()); if (input.transmissionIsSet()) - ret.attenuator_transmission = input.getTransmission(); + ret.AttenuatorTransmission(input.getTransmission()); if (input.omegaIsSet()) { - ret.omega_step = input.getOmega().getStep(); - ret.omega_start = input.getOmega().getStart(); + ret.OmegaStep(input.getOmega().getStep()); + ret.OmegaStart(input.getOmega().getStart()); if (input.getOmega().getVector().size() == 3) { auto v = input.getOmega().getVector(); - ret.omega_axis = Coord(v[0], v[1], v[2]); - } else - ret.omega_axis = Coord(0, 0, 0); + ret.OmegaAxis(Coord(v[0], v[1], v[2])); + } } if (input.roiSumAreaIsSet()) { - ret.roi_sum_area = ROIRectangle{ + ret.ROISummation(ROIRectangle{ .x_min = static_cast(input.getRoiSumArea().getXMin()), .x_max = static_cast(input.getRoiSumArea().getXMax()), .y_min = static_cast(input.getRoiSumArea().getYMin()), .y_max = static_cast(input.getRoiSumArea().getYMax()) - }; + }); } - ret.space_group_number = input.spaceGroupNumberIsSet() ? input.getSpaceGroupNumber() : 0; - ret.sample_name = input.getSampleName(); - ret.header_appendix = input.getHeaderAppendix(); - ret.image_appendix = input.getImageAppendix(); - ret.save_calibration = input.saveCalibrationIsSet() && input.isSaveCalibration(); + ret.SpaceGroupNumber(input.getSpaceGroupNumber()); + ret.SampleName(input.getSampleName()); + ret.HeaderAppendix(input.getHeaderAppendix()); + ret.ImageAppendix(input.getImageAppendix()); + ret.SaveCalibration(input.isSaveCalibration()); return ret; } @@ -712,3 +721,18 @@ void JFJochBrokerHttp::plot_resolution_estimate_histogram_get(Pistache::Http::Re auto plot = state_machine.GetPlots(req); ProcessOutput(Convert(plot), response); } + +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"); + 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"); + + 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); +} \ No newline at end of file diff --git a/broker/JFJochBrokerHttp.h b/broker/JFJochBrokerHttp.h index 28497432..b638ecc6 100644 --- a/broker/JFJochBrokerHttp.h +++ b/broker/JFJochBrokerHttp.h @@ -104,6 +104,8 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi { void preview_jpeg_settings_put(const org::openapitools::server::model::Preview_settings &previewSettings, Pistache::Http::ResponseWriter &response) override; + void config_internal_generator_image_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/JFJochBrokerParser.cpp b/broker/JFJochBrokerParser.cpp index cdf960c7..6d62cfb3 100644 --- a/broker/JFJochBrokerParser.cpp +++ b/broker/JFJochBrokerParser.cpp @@ -294,6 +294,9 @@ void ParseFacilityConfiguration(const nlohmann::json &input, const std::string& experiment.DetectorDelay(GET_TIME(j, "detector_trigger_delay_us")); experiment.FrameTime(GET_TIME(j, "frame_time_us"), GET_TIME(j, "count_time_us")); experiment.PreviewPeriod(GET_TIME(j, "preview_period_us")); + experiment.UseInternalPacketGenerator(GET_BOOL(j, "internal_frame_generator", false)); + if (experiment.IsUsingInternalPacketGen()) + experiment.ConversionOnFPGA(false); experiment.IPv4BaseAddr(GET_STR(j, "detector_ipv4")); } else @@ -306,22 +309,20 @@ void ParseAcquisitionDeviceGroup(const nlohmann::json &input, const std::string& const auto &j = input[tag]; std::string dev_type = GET_STR(j, "type"); - bool use_4x10g = GET_BOOL(j, "use_4x10g", false); - int64_t buffer_size = GET_I64(j, "buffer_size", 1024); - int64_t dev_count = GET_I64(j, "count", 1); - - if ((dev_count < 1) || (dev_count > 8)) - throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Device count must be between 1 to 8"); - - if ((buffer_size < 16) || (buffer_size > 65536)) - throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Buffer size must be in range 16-65536"); if (dev_type == "pcie") { - for (int i = 0; i < dev_count; i++) - aq_devices.AddPCIeDevice("/dev/jfjoch" + std::to_string(i)); + std::vector devices = GET_STR_ARR(j, "devices"); + if (devices.empty()) + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, + "At least one PCIe device must be provided"); + for (auto &d: devices) + aq_devices.AddPCIeDevice(d); } else if (dev_type == "hls") { - if (dev_count > 1) - throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Device count must be 1 for HLS"); + int64_t buffer_size = GET_I64(j, "buffer_size", 1024); + + if ((buffer_size < 16) || (buffer_size > 65536)) + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Buffer size must be in range 16-65536"); + aq_devices.AddHLSDevice(buffer_size); } else throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Device type unknown"); diff --git a/broker/JFJochServices.cpp b/broker/JFJochServices.cpp index 6e2e1bed..335e20ff 100644 --- a/broker/JFJochServices.cpp +++ b/broker/JFJochServices.cpp @@ -30,12 +30,17 @@ void JFJochServices::Off() { } void JFJochServices::On(const DiffractionExperiment &x) { - logger.Info("Detector on"); + if (x.IsUsingInternalPacketGen() || (receiver == nullptr)) { + detector.reset(); + } else { + logger.Info("Detector on"); - if (detector && (receiver != nullptr)) + if (!detector) + detector = std::make_unique(); detector->Initialize(x, receiver->GetNetworkConfig()); - logger.Info(" ... done"); + logger.Info(" ... done"); + } } JFJochServicesOutput JFJochServices::Stop() { @@ -105,12 +110,6 @@ JFJochServices &JFJochServices::Receiver(JFJochReceiverService *input) { return *this; } -JFJochServices &JFJochServices::Detector() { - detector = std::make_unique(); - logger.Info("Using detector service"); - return *this; -} - std::optional JFJochServices::GetReceiverStatus() { if (receiver == nullptr) return {}; @@ -174,3 +173,10 @@ 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); +} diff --git a/broker/JFJochServices.h b/broker/JFJochServices.h index 536033f6..c749d0cc 100644 --- a/broker/JFJochServices.h +++ b/broker/JFJochServices.h @@ -28,13 +28,15 @@ public: void Cancel(); void Trigger(); + void LoadInternalGeneratorImage(const DiffractionExperiment &experiment, + const std::vector &image, + uint64_t image_number); std::optional GetReceiverStatus(); Plot GetPlots(const PlotRequest &request); RadialIntegrationProfiles GetRadialIntegrationProfiles(); void SetSpotFindingSettings(const SpotFindingSettings &settings); JFJochServices& Receiver(JFJochReceiverService *input); - JFJochServices& Detector(); std::optional GetDetectorStatus() const; diff --git a/broker/JFJochStateMachine.cpp b/broker/JFJochStateMachine.cpp index f9f3362b..68527c91 100644 --- a/broker/JFJochStateMachine.cpp +++ b/broker/JFJochStateMachine.cpp @@ -4,50 +4,6 @@ #include "JFJochStateMachine.h" -void LoadDatasetSettings(DiffractionExperiment& experiment, const DatasetSettings &settings) { - // Save DatasetSettings - if something goes wrong, restore old settings - auto tmp = experiment; - - try { - if (experiment.IsPulsedSource() && (settings.images_per_trigger != 1)) - throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, - "No point to set image_per_trigger for a pulsed source"); - experiment.ImagesPerTrigger(settings.images_per_trigger); - experiment.NumTriggers(settings.ntrigger); - experiment.BeamX_pxl(settings.beam_x_pxl); - experiment.BeamY_pxl(settings.beam_y_pxl); - experiment.DetectorDistance_mm(settings.detector_distance_mm); - experiment.PhotonEnergy_keV(settings.photon_energy_keV); - experiment.PhotonEnergyMultiplayer(settings.photon_energy_multiplier); - experiment.FilePrefix(settings.file_prefix); - experiment.DataFileCount(settings.data_file_count); - experiment.SetUnitCell(settings.unit_cell); - experiment.AttenuatorTransmission(settings.attenuator_transmission); - experiment.TotalFlux(settings.total_flux); - experiment.SpaceGroupNumber(settings.space_group_number); - experiment.SampleName(settings.sample_name); - experiment.Compression(settings.compression); - experiment.SaveCalibration(settings.save_calibration); - experiment.OmegaStart(settings.omega_start).OmegaStep(settings.omega_step); - if (settings.omega_axis.Length() == 0.0f) - experiment.OmegaAxis(); - else - experiment.OmegaAxis(settings.omega_axis); - - experiment.ImageAppendix(settings.image_appendix); - experiment.HeaderAppendix(settings.header_appendix); - if (settings.summation == 0) - experiment.Summation(1); - else - experiment.Summation(settings.summation); - experiment.FPGAOutputMode(settings.fpga_pixel_output); - experiment.ROISummation(settings.roi_sum_area); - } catch (...) { - experiment = tmp; - throw; - } -} - void ApplyDetectorSettings(DiffractionExperiment& experiment, const DetectorSettings &settings) { auto tmp = experiment; try { @@ -58,7 +14,10 @@ void ApplyDetectorSettings(DiffractionExperiment& experiment, const DetectorSett experiment.FrameTime(std::chrono::microseconds(settings.frame_time_us)); experiment.StorageCells(settings.storage_cell_count); + experiment.UseInternalPacketGenerator(settings.use_internal_packet_generator); + // If internal packet generator is used --> no conversion on FPGA + experiment.ConversionOnFPGA(!settings.use_internal_packet_generator); if (settings.collect_raw_data) experiment.Mode(DetectorMode::Raw); @@ -78,6 +37,8 @@ void ApplyDetectorSettings(DiffractionExperiment& experiment, const DetectorSett experiment.StorageCellDelay(std::chrono::nanoseconds(settings.storage_cell_delay_ns.value())); if (settings.detector_delay_ns) experiment.DetectorDelay(std::chrono::nanoseconds(settings.detector_delay_ns.value())); + if (settings.internal_packet_generator_images) + experiment.InternalPacketGeneratorImages(settings.internal_packet_generator_images.value()); } catch (...) { experiment = tmp; throw; @@ -345,9 +306,7 @@ void JFJochStateMachine::Start(const DatasetSettings& settings) { if (measurement.valid()) measurement.get(); // In case measurement was running - clear thread - auto mod_settings = settings; - SetDatasetDefaults(mod_settings); - LoadDatasetSettings(experiment, mod_settings); + experiment.ImportDatasetSettings(settings); ClearAndSetMeasurementStatistics(); @@ -373,13 +332,6 @@ void JFJochStateMachine::Start(const DatasetSettings& settings) { } } -void JFJochStateMachine::SetDatasetDefaults(DatasetSettings &settings) { - if (settings.detector_distance_mm <= 0) - settings.detector_distance_mm = 100.0; - if (settings.ntrigger <= 0) - settings.ntrigger = 1; -} - void JFJochStateMachine::WaitTillMeasurementDone() { std::unique_lock ul(m); @@ -530,6 +482,7 @@ DetectorSettings JFJochStateMachine::GetDetectorSettings() const { ret.detector_delay_ns = experiment.GetDetectorDelay().count(); ret.fixed_gain_g1 = experiment.IsFixedGainG1(); ret.use_gain_hg0 = experiment.IsUsingGainHG0(); + ret.internal_packet_generator_images = experiment.GetInternalPacketGeneratorImages(); return ret; } @@ -717,3 +670,23 @@ std::string JFJochStateMachine::GetPreviewJPEG() const { std::string JFJochStateMachine::GetPreviewTIFF(bool calibration) const { return services.GetPreviewTIFF(calibration); } + +void JFJochStateMachine::LoadInternalGeneratorImage(const void *data, size_t size, 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"); + + if ((size != experiment.GetPixelsNum() * sizeof(uint16_t)) + && (size != experiment.GetModulesNum() * RAW_MODULE_SIZE * sizeof(uint16_t))) + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Image size doesn't match current detector"); + + if (image_number >= experiment.GetInternalPacketGeneratorImages()) + throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, + "Image for internal generator out of bounds"); + + std::vector image(size / sizeof(uint16_t)); + memcpy(image.data(), data, size); + + services.LoadInternalGeneratorImage(experiment, image, image_number); +} diff --git a/broker/JFJochStateMachine.h b/broker/JFJochStateMachine.h index c8b1fd25..4b9e4014 100644 --- a/broker/JFJochStateMachine.h +++ b/broker/JFJochStateMachine.h @@ -55,43 +55,6 @@ struct MeasurementStatistics { float bkg_estimate; }; -struct DatasetSettings { - int64_t images_per_trigger; - int64_t ntrigger; - - FPGAPixelOutput fpga_pixel_output; - int64_t summation; - - float beam_x_pxl; - float beam_y_pxl; - float detector_distance_mm; - float photon_energy_keV; - - float photon_energy_multiplier; - - std::string file_prefix; - int64_t data_file_count; - - CompressionAlgorithm compression; - - std::string sample_name; - std::optional unit_cell; - int64_t space_group_number; - - bool save_calibration; - std::optional total_flux; - std::optional attenuator_transmission; - - std::optional omega_step; - float omega_start; - Coord omega_axis; - - std::string image_appendix; - std::string header_appendix; - - std::optional roi_sum_area; -}; - struct DetectorSettings { int64_t frame_time_us; std::optional count_time_us; @@ -107,6 +70,7 @@ struct DetectorSettings { std::optional storage_cell_delay_ns; std::optional detector_delay_ns; + std::optional internal_packet_generator_images; }; @@ -118,8 +82,6 @@ struct RadialIntegrationSettings { float q_spacing; }; -void LoadDatasetSettings(DiffractionExperiment& experiment, const DatasetSettings &settings); - class JFJochStateMachine { Logger &logger; JFJochServices &services; @@ -156,7 +118,6 @@ class JFJochStateMachine { PreviewJPEGSettings preview_jpeg_settings; // Private functions assume that lock m is acquired - void SetDatasetDefaults(DatasetSettings& settings); void MeasurementThread(); void PedestalThread(std::unique_lock ul); void InitializeThread(std::unique_lock ul); @@ -214,6 +175,8 @@ public: std::string GetPreviewJPEG() const; std::string GetPreviewTIFF(bool calibration) const; + void LoadInternalGeneratorImage(const void *data, size_t size, uint64_t image_number); + // Not thread safe - only for configuration in serial context DiffractionExperiment& NotThreadSafe_Experiment(); diff --git a/broker/gen/api/DefaultApi.cpp b/broker/gen/api/DefaultApi.cpp index b9248fd2..de8cd8dd 100644 --- a/broker/gen/api/DefaultApi.cpp +++ b/broker/gen/api/DefaultApi.cpp @@ -36,6 +36,7 @@ void DefaultApi::setupRoutes() { Routes::Post(*router, base + "/cancel", Routes::bind(&DefaultApi::cancel_post_handler, this)); 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::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)); @@ -165,6 +166,25 @@ void DefaultApi::config_detector_put_handler(const Pistache::Rest::Request &requ response.send(Pistache::Http::Code::Internal_Server_Error, e.what()); } +} +void DefaultApi::config_internal_generator_image_put_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) { + try { + + try { + this->config_internal_generator_image_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_rad_int_get_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 202dadf7..14f3cc2b 100644 --- a/broker/gen/api/DefaultApi.h +++ b/broker/gen/api/DefaultApi.h @@ -60,6 +60,7 @@ private: void cancel_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response); 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_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); @@ -135,6 +136,13 @@ private: /// (optional) virtual void config_detector_put(const org::openapitools::server::model::Detector_settings &detectorSettings, Pistache::Http::ResponseWriter &response) = 0; /// + /// Load binary image for internal FPGA generator + /// + /// + /// 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). + /// + virtual void config_internal_generator_image_put(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response) = 0; + /// /// Get radial integration configuration /// /// diff --git a/broker/gen/model/Detector_settings.cpp b/broker/gen/model/Detector_settings.cpp index 7d5f43b0..24b4a9bc 100644 --- a/broker/gen/model/Detector_settings.cpp +++ b/broker/gen/model/Detector_settings.cpp @@ -28,6 +28,8 @@ Detector_settings::Detector_settings() m_Storage_cell_countIsSet = false; m_Internal_frame_generator = false; m_Internal_frame_generatorIsSet = false; + m_Internal_frame_generator_images = 1L; + m_Internal_frame_generator_imagesIsSet = false; m_Collect_raw_data = false; m_Collect_raw_dataIsSet = false; m_Pedestal_g0_frames = 0L; @@ -36,10 +38,10 @@ Detector_settings::Detector_settings() m_Pedestal_g1_framesIsSet = false; m_Pedestal_g2_frames = 0L; m_Pedestal_g2_framesIsSet = false; - m_Storage_cell_delay_ns = 0L; - m_Storage_cell_delay_nsIsSet = false; - m_Detector_trigger_delay_ns = 0L; - m_Detector_trigger_delay_nsIsSet = false; + m_Storage_cell_delay_us = 0.0f; + m_Storage_cell_delay_usIsSet = false; + m_Detector_trigger_delay_us = 0.0f; + m_Detector_trigger_delay_usIsSet = false; m_Fixed_gain_g1 = false; m_Fixed_gain_g1IsSet = false; m_Use_gain_hg0 = false; @@ -99,7 +101,26 @@ bool Detector_settings::validate(std::stringstream& msg, const std::string& path } } - + + if (internalFrameGeneratorImagesIsSet()) + { + const int64_t& value = m_Internal_frame_generator_images; + const std::string currentValuePath = _pathPrefix + ".internalFrameGeneratorImages"; + + + if (value < 1ll) + { + success = false; + msg << currentValuePath << ": must be greater than or equal to 1;"; + } + if (value > 128ll) + { + success = false; + msg << currentValuePath << ": must be less than or equal to 128;"; + } + + } + if (pedestalG0FramesIsSet()) { const int64_t& value = m_Pedestal_g0_frames; @@ -163,6 +184,9 @@ bool Detector_settings::operator==(const Detector_settings& rhs) const ((!internalFrameGeneratorIsSet() && !rhs.internalFrameGeneratorIsSet()) || (internalFrameGeneratorIsSet() && rhs.internalFrameGeneratorIsSet() && isInternalFrameGenerator() == rhs.isInternalFrameGenerator())) && + ((!internalFrameGeneratorImagesIsSet() && !rhs.internalFrameGeneratorImagesIsSet()) || (internalFrameGeneratorImagesIsSet() && rhs.internalFrameGeneratorImagesIsSet() && getInternalFrameGeneratorImages() == rhs.getInternalFrameGeneratorImages())) && + + ((!collectRawDataIsSet() && !rhs.collectRawDataIsSet()) || (collectRawDataIsSet() && rhs.collectRawDataIsSet() && isCollectRawData() == rhs.isCollectRawData())) && @@ -175,10 +199,10 @@ bool Detector_settings::operator==(const Detector_settings& rhs) const ((!pedestalG2FramesIsSet() && !rhs.pedestalG2FramesIsSet()) || (pedestalG2FramesIsSet() && rhs.pedestalG2FramesIsSet() && getPedestalG2Frames() == rhs.getPedestalG2Frames())) && - ((!storageCellDelayNsIsSet() && !rhs.storageCellDelayNsIsSet()) || (storageCellDelayNsIsSet() && rhs.storageCellDelayNsIsSet() && getStorageCellDelayNs() == rhs.getStorageCellDelayNs())) && + ((!storageCellDelayUsIsSet() && !rhs.storageCellDelayUsIsSet()) || (storageCellDelayUsIsSet() && rhs.storageCellDelayUsIsSet() && getStorageCellDelayUs() == rhs.getStorageCellDelayUs())) && - ((!detectorTriggerDelayNsIsSet() && !rhs.detectorTriggerDelayNsIsSet()) || (detectorTriggerDelayNsIsSet() && rhs.detectorTriggerDelayNsIsSet() && getDetectorTriggerDelayNs() == rhs.getDetectorTriggerDelayNs())) && + ((!detectorTriggerDelayUsIsSet() && !rhs.detectorTriggerDelayUsIsSet()) || (detectorTriggerDelayUsIsSet() && rhs.detectorTriggerDelayUsIsSet() && getDetectorTriggerDelayUs() == rhs.getDetectorTriggerDelayUs())) && ((!fixedGainG1IsSet() && !rhs.fixedGainG1IsSet()) || (fixedGainG1IsSet() && rhs.fixedGainG1IsSet() && isFixedGainG1() == rhs.isFixedGainG1())) && @@ -204,6 +228,8 @@ void to_json(nlohmann::json& j, const Detector_settings& o) j["storage_cell_count"] = o.m_Storage_cell_count; if(o.internalFrameGeneratorIsSet()) j["internal_frame_generator"] = o.m_Internal_frame_generator; + if(o.internalFrameGeneratorImagesIsSet()) + j["internal_frame_generator_images"] = o.m_Internal_frame_generator_images; if(o.collectRawDataIsSet()) j["collect_raw_data"] = o.m_Collect_raw_data; if(o.pedestalG0FramesIsSet()) @@ -212,10 +238,10 @@ void to_json(nlohmann::json& j, const Detector_settings& o) j["pedestal_g1_frames"] = o.m_Pedestal_g1_frames; if(o.pedestalG2FramesIsSet()) j["pedestal_g2_frames"] = o.m_Pedestal_g2_frames; - if(o.storageCellDelayNsIsSet()) - j["storage_cell_delay_ns"] = o.m_Storage_cell_delay_ns; - if(o.detectorTriggerDelayNsIsSet()) - j["detector_trigger_delay_ns"] = o.m_Detector_trigger_delay_ns; + if(o.storageCellDelayUsIsSet()) + j["storage_cell_delay_us"] = o.m_Storage_cell_delay_us; + if(o.detectorTriggerDelayUsIsSet()) + j["detector_trigger_delay_us"] = o.m_Detector_trigger_delay_us; if(o.fixedGainG1IsSet()) j["fixed_gain_g1"] = o.m_Fixed_gain_g1; if(o.useGainHg0IsSet()) @@ -241,6 +267,11 @@ void from_json(const nlohmann::json& j, Detector_settings& o) j.at("internal_frame_generator").get_to(o.m_Internal_frame_generator); o.m_Internal_frame_generatorIsSet = true; } + if(j.find("internal_frame_generator_images") != j.end()) + { + j.at("internal_frame_generator_images").get_to(o.m_Internal_frame_generator_images); + o.m_Internal_frame_generator_imagesIsSet = true; + } if(j.find("collect_raw_data") != j.end()) { j.at("collect_raw_data").get_to(o.m_Collect_raw_data); @@ -261,15 +292,15 @@ void from_json(const nlohmann::json& j, Detector_settings& o) j.at("pedestal_g2_frames").get_to(o.m_Pedestal_g2_frames); o.m_Pedestal_g2_framesIsSet = true; } - if(j.find("storage_cell_delay_ns") != j.end()) + if(j.find("storage_cell_delay_us") != j.end()) { - j.at("storage_cell_delay_ns").get_to(o.m_Storage_cell_delay_ns); - o.m_Storage_cell_delay_nsIsSet = true; + j.at("storage_cell_delay_us").get_to(o.m_Storage_cell_delay_us); + o.m_Storage_cell_delay_usIsSet = true; } - if(j.find("detector_trigger_delay_ns") != j.end()) + if(j.find("detector_trigger_delay_us") != j.end()) { - j.at("detector_trigger_delay_ns").get_to(o.m_Detector_trigger_delay_ns); - o.m_Detector_trigger_delay_nsIsSet = true; + j.at("detector_trigger_delay_us").get_to(o.m_Detector_trigger_delay_us); + o.m_Detector_trigger_delay_usIsSet = true; } if(j.find("fixed_gain_g1") != j.end()) { @@ -343,6 +374,23 @@ void Detector_settings::unsetInternal_frame_generator() { m_Internal_frame_generatorIsSet = false; } +int64_t Detector_settings::getInternalFrameGeneratorImages() const +{ + return m_Internal_frame_generator_images; +} +void Detector_settings::setInternalFrameGeneratorImages(int64_t const value) +{ + m_Internal_frame_generator_images = value; + m_Internal_frame_generator_imagesIsSet = true; +} +bool Detector_settings::internalFrameGeneratorImagesIsSet() const +{ + return m_Internal_frame_generator_imagesIsSet; +} +void Detector_settings::unsetInternal_frame_generator_images() +{ + m_Internal_frame_generator_imagesIsSet = false; +} bool Detector_settings::isCollectRawData() const { return m_Collect_raw_data; @@ -411,39 +459,39 @@ void Detector_settings::unsetPedestal_g2_frames() { m_Pedestal_g2_framesIsSet = false; } -int64_t Detector_settings::getStorageCellDelayNs() const +float Detector_settings::getStorageCellDelayUs() const { - return m_Storage_cell_delay_ns; + return m_Storage_cell_delay_us; } -void Detector_settings::setStorageCellDelayNs(int64_t const value) +void Detector_settings::setStorageCellDelayUs(float const value) { - m_Storage_cell_delay_ns = value; - m_Storage_cell_delay_nsIsSet = true; + m_Storage_cell_delay_us = value; + m_Storage_cell_delay_usIsSet = true; } -bool Detector_settings::storageCellDelayNsIsSet() const +bool Detector_settings::storageCellDelayUsIsSet() const { - return m_Storage_cell_delay_nsIsSet; + return m_Storage_cell_delay_usIsSet; } -void Detector_settings::unsetStorage_cell_delay_ns() +void Detector_settings::unsetStorage_cell_delay_us() { - m_Storage_cell_delay_nsIsSet = false; + m_Storage_cell_delay_usIsSet = false; } -int64_t Detector_settings::getDetectorTriggerDelayNs() const +float Detector_settings::getDetectorTriggerDelayUs() const { - return m_Detector_trigger_delay_ns; + return m_Detector_trigger_delay_us; } -void Detector_settings::setDetectorTriggerDelayNs(int64_t const value) +void Detector_settings::setDetectorTriggerDelayUs(float const value) { - m_Detector_trigger_delay_ns = value; - m_Detector_trigger_delay_nsIsSet = true; + m_Detector_trigger_delay_us = value; + m_Detector_trigger_delay_usIsSet = true; } -bool Detector_settings::detectorTriggerDelayNsIsSet() const +bool Detector_settings::detectorTriggerDelayUsIsSet() const { - return m_Detector_trigger_delay_nsIsSet; + return m_Detector_trigger_delay_usIsSet; } -void Detector_settings::unsetDetector_trigger_delay_ns() +void Detector_settings::unsetDetector_trigger_delay_us() { - m_Detector_trigger_delay_nsIsSet = false; + m_Detector_trigger_delay_usIsSet = false; } bool Detector_settings::isFixedGainG1() const { diff --git a/broker/gen/model/Detector_settings.h b/broker/gen/model/Detector_settings.h index d8daf9fd..5f32ff88 100644 --- a/broker/gen/model/Detector_settings.h +++ b/broker/gen/model/Detector_settings.h @@ -84,6 +84,13 @@ public: bool internalFrameGeneratorIsSet() const; void unsetInternal_frame_generator(); /// + /// + /// + int64_t getInternalFrameGeneratorImages() const; + void setInternalFrameGeneratorImages(int64_t const value); + bool internalFrameGeneratorImagesIsSet() const; + void unsetInternal_frame_generator_images(); + /// /// Turn off conversion of pixel read-out to photon count /// bool isCollectRawData() const; @@ -112,19 +119,19 @@ public: bool pedestalG2FramesIsSet() const; void unsetPedestal_g2_frames(); /// - /// Delay between two storage cells + /// Delay between two storage cells [us] /// - int64_t getStorageCellDelayNs() const; - void setStorageCellDelayNs(int64_t const value); - bool storageCellDelayNsIsSet() const; - void unsetStorage_cell_delay_ns(); + float getStorageCellDelayUs() const; + void setStorageCellDelayUs(float const value); + bool storageCellDelayUsIsSet() const; + void unsetStorage_cell_delay_us(); /// - /// Delay between TTL trigger and acquisition start + /// Delay between TTL trigger and acquisition start [us] /// - int64_t getDetectorTriggerDelayNs() const; - void setDetectorTriggerDelayNs(int64_t const value); - bool detectorTriggerDelayNsIsSet() const; - void unsetDetector_trigger_delay_ns(); + float getDetectorTriggerDelayUs() const; + void setDetectorTriggerDelayUs(float const value); + bool detectorTriggerDelayUsIsSet() const; + void unsetDetector_trigger_delay_us(); /// /// Fix gain to G1 (can be useful for storage cells) /// @@ -151,6 +158,8 @@ protected: bool m_Storage_cell_countIsSet; bool m_Internal_frame_generator; bool m_Internal_frame_generatorIsSet; + int64_t m_Internal_frame_generator_images; + bool m_Internal_frame_generator_imagesIsSet; bool m_Collect_raw_data; bool m_Collect_raw_dataIsSet; int64_t m_Pedestal_g0_frames; @@ -159,10 +168,10 @@ protected: bool m_Pedestal_g1_framesIsSet; int64_t m_Pedestal_g2_frames; bool m_Pedestal_g2_framesIsSet; - int64_t m_Storage_cell_delay_ns; - bool m_Storage_cell_delay_nsIsSet; - int64_t m_Detector_trigger_delay_ns; - bool m_Detector_trigger_delay_nsIsSet; + float m_Storage_cell_delay_us; + bool m_Storage_cell_delay_usIsSet; + float m_Detector_trigger_delay_us; + bool m_Detector_trigger_delay_usIsSet; bool m_Fixed_gain_g1; bool m_Fixed_gain_g1IsSet; bool m_Use_gain_hg0; diff --git a/broker/jfjoch_api.yaml b/broker/jfjoch_api.yaml index f5390f08..31c55719 100644 --- a/broker/jfjoch_api.yaml +++ b/broker/jfjoch_api.yaml @@ -238,18 +238,11 @@ components: state: type: string description: Current state of the detector - enum: - - Idle - - Waiting - - Busy - - Error + enum: ["Idle", "Waiting", "Busy", "Error"] powerchip: type: string description: Power on of ASICs - enum: - - On - - Off - - Partial + enum: ["On", "Off", "Partial"] server_version: type: string description: Detector server (on read-out boards) version @@ -293,6 +286,12 @@ components: type: boolean default: false description: Use internal frame generator in FPGA instead of getting data from a real detector + internal_frame_generator_images: + type: integer + format: int64 + default: 1 + minimum: 1 + maximum: 128 collect_raw_data: type: boolean default: false @@ -309,14 +308,14 @@ components: type: integer format: int64 minimum: 0 - storage_cell_delay_ns: - type: integer - format: int64 - description: Delay between two storage cells - detector_trigger_delay_ns: - type: integer - format: int64 - description: Delay between TTL trigger and acquisition start + storage_cell_delay_us: + type: number + format: float + description: Delay between two storage cells [us] + detector_trigger_delay_us: + type: number + format: float + description: Delay between TTL trigger and acquisition start [us] fixed_gain_g1: type: boolean default: false @@ -481,9 +480,7 @@ components: detector_pixel_depth: type: integer format: int64 - enum: - - 2 - - 4 + enum: [2, 4] bkg_estimate: type: number format: float @@ -494,13 +491,7 @@ components: properties: state: type: string - enum: - - Inactive - - Idle - - Busy - - Measuring - - Pedestal - - Error + enum: ["Inactive", "Idle", "Busy", "Measuring", "Pedestal", "Error"] progress: type: number format: float @@ -626,10 +617,7 @@ components: reason: type: string description: "Enumerate field for automated analysis" - enum: - - WrongDAQState - - Other - + enum: ["WrongDAQState", "Other"] paths: /initialize: @@ -865,7 +853,39 @@ paths: application/json: schema: $ref: '#/components/schemas/rad_int_settings' - + /config/internal_generator_image: + put: + summary: Load binary image for internal FPGA generator + description: | + 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). + parameters: + - name: number + in: query + description: Image number to upload + required: false + schema: + type: integer + format: int64 + minimum: 0 + maximum: 127 + requestBody: + content: + application/octet-stream: + 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 diff --git a/broker/jfjoch_broker.cpp b/broker/jfjoch_broker.cpp index 3430fdf8..47aee013 100644 --- a/broker/jfjoch_broker.cpp +++ b/broker/jfjoch_broker.cpp @@ -79,7 +79,7 @@ int main (int argc, char **argv) { experiment.MaskChipEdges(true).MaskModuleEdges(true); AcquisitionDeviceGroup aq_devices; - ParseAcquisitionDeviceGroup(input, "devices", aq_devices); + ParseAcquisitionDeviceGroup(input, "receiver", aq_devices); if (aq_devices.size() > 0) { experiment.DataStreams(aq_devices.size()); image_pusher = std::make_unique(context, ParseStringArray(input, "zmq_image_addr")); @@ -112,7 +112,7 @@ int main (int argc, char **argv) { auto router = std::make_shared(); - auto opts = Pistache::Http::Endpoint::options().threads(8); + auto opts = Pistache::Http::Endpoint::options().threads(8).maxRequestSize(64*1024*1024); opts.flags(Pistache::Tcp::Options::ReuseAddr); httpEndpoint->init(opts); @@ -128,10 +128,8 @@ int main (int argc, char **argv) { aq_devices.EnableLogging(&logger); } - if (receiver) { + if (receiver) broker.Services().Receiver(receiver.get()); - broker.Services().Detector(); - } httpEndpoint->setHandler(router->handler()); httpEndpoint->serve(); diff --git a/broker/redoc-static.html b/broker/redoc-static.html index 1714d90c..537b5d12 100644 --- a/broker/redoc-static.html +++ b/broker/redoc-static.html @@ -341,7 +341,7 @@ data-styled.g137[id="sc-cMdfCE"]{content:"dvQijr,"}/*!sc*/ -

Integration time of the detector. If not provided count time will be set to maximum value for a given frame time.

storage_cell_count
integer <int64> [ 1 .. 16 ]
Default: 1
internal_frame_generator
boolean
Default: false

Use internal frame generator in FPGA instead of getting data from a real detector

-
collect_raw_data
boolean
Default: false
internal_frame_generator_images
integer <int64> [ 1 .. 128 ]
Default: 1
collect_raw_data
boolean
Default: false

Turn off conversion of pixel read-out to photon count

-
pedestal_g0_frames
integer <int64> >= 0
pedestal_g1_frames
integer <int64> >= 0
pedestal_g2_frames
integer <int64> >= 0
storage_cell_delay_ns
integer <int64>

Delay between two storage cells

-
detector_trigger_delay_ns
integer <int64>

Delay between TTL trigger and acquisition start

+
pedestal_g0_frames
integer <int64> >= 0
pedestal_g1_frames
integer <int64> >= 0
pedestal_g2_frames
integer <int64> >= 0
storage_cell_delay_us
number <float>

Delay between two storage cells [us]

+
detector_trigger_delay_us
number <float>

Delay between TTL trigger and acquisition start [us]

fixed_gain_g1
boolean
Default: false

Fix gain to G1 (can be useful for storage cells)

use_gain_hg0
boolean
Default: false

Input parsing or validation error

Request samples

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

Response samples

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

Get detector configuration

Request 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
}

Response samples

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

Get detector configuration

Can be done anytime

Responses

Response samples

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

Configure spot finding

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
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>
preview_indexed_only
boolean
Default: false

Responses

Responses

Response samples

Content type
application/json
{
  • "polarization_factor": -1,
  • "solid_angle_corr": true,
  • "high_q_recipA": 0.1,
  • "low_q_recipA": 0.1,
  • "q_spacing": 0.1
}

Select detector

Response samples

Content type
application/json
{
  • "polarization_factor": -1,
  • "solid_angle_corr": true,
  • "high_q_recipA": 0.1,
  • "low_q_recipA": 0.1,
  • "q_spacing": 0.1
}

Load binary image for internal FPGA generator

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

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

Responses

Select detector

Jungfraujoch allows to control multiple detectors and/or region-of-interests. @@ -703,7 +715,7 @@ Changing detector will set detector to Inactive state and will requ " class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS sc-ckdEwu LxEPk">

No preview image recorded so far