Files
Jungfraujoch/broker/OpenAPIConvert.cpp
T
leonarski_fandClaude Opus 5 550f7c7d7b scan result: a grid scan's crystals and a calibration's geometry reach the stream, the file and the API
A grid scan and a powder calibration each produce an answer that is not a per-image number,
and neither had anywhere to go. ScanResult gains two top-level optionals, grid and
calibration, in the same idiom the three rotation_* members already use: a mode's payload is
present when that mode ran and absent otherwise. images stays required, so every existing
/result/scan client - the python client and the beamline scripts on it - is untouched.

No oneOf or discriminator. The spec contains none today, so polymorphism is unexercised across
all three generators at once, and the only thing it would buy is making "exactly one payload"
structurally true rather than true by convention. powder_calibration_output has been fully
specified and referenced by nothing since it was written; the calibration member reuses it.

The crystal list travels the same three hops a per-image quantity does. In the CBOR end
message grid_crystals is an array of maps keyed by field name - the shape a spot already uses
- so a reader that does not know a field skips it and the record survives a field being added;
the deserializer steps over an unknown key rather than reading its payload as the next one. In
the HDF5 master it is parallel 1-D datasets under /entry/MX/crystals, one per field, because
crystals are numbered rather than named and a group per crystal would put the index in the
path. The reader reads them back so a stored raster re-opens with what it found.

Nothing caps the list at one. A raster can find several crystals and the ordering carries the
answer: sorted by score, best first.

angle_deg is an axis, not a direction. It lies in [0, 180) and wraps, so 179 and 0 are
adjacent and two of these do not average arithmetically - a pair of nearly parallel needles
averaged across the wrap comes out as a right angle. That is stated at every layer it passes
through, since it is the kind of field a consumer will reach for without reading the producer.

The producer side is not wired yet: nothing fills ScanResult::grid or EndMessage::grid_crystals
here. The seam is receiver/JFJochReceiver.cpp, where rotation_lattice is filled in
EndDataCollection and GetFinalStatistics.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EFEJG6WBQv8th4UJFNe53N
2026-09-08 00:17:10 +02:00

1416 lines
63 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "../common/JFJochMath.h"
#include "../common/GitInfo.h"
#include "OpenAPIConvert.h"
// From https://en.cppreference.com/w/cpp/string/byte/tolower
std::string str_tolower(std::string s) {
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::tolower(c); });
return s;
}
SpotFindingSettings Convert(const org::openapitools::server::model::Spot_finding_settings &input) {
SpotFindingSettings ret{};
ret.signal_to_noise_threshold = input.getSignalToNoiseThreshold();
ret.photon_count_threshold = input.getPhotonCountThreshold();
ret.min_pix_per_spot = input.getMinPixPerSpot();
ret.max_pix_per_spot = input.getMaxPixPerSpot();
// Both limits are optional and unset means "no limit at that end". A value of 0 has meant the same
// thing since rc.161 and clients still send it that way, so fold it into the unset case here - the
// analysis code then has exactly one spelling for "no limit" and no zero to special-case.
if (input.highResolutionLimitIsSet() && input.getHighResolutionLimit() > 0)
ret.high_resolution_limit = input.getHighResolutionLimit();
if (input.lowResolutionLimitIsSet() && input.getLowResolutionLimit() > 0)
ret.low_resolution_limit = input.getLowResolutionLimit();
ret.enable = input.isEnable();
ret.indexing = input.isIndexing();
ret.quick_integration = input.isQuickIntegration();
ret.cutoff_spot_count_low_res = input.getHighResolutionLimitForSpotCountLowRes();
ret.ice_ring_width_Q_recipA = input.getIceRingWidthQRecipA();
if (input.highResGapQRecipAIsSet())
ret.high_res_gap_Q_recipA = input.getHighResGapQRecipA();
if (input.adaptiveThresholdIsSet())
ret.adaptive_threshold = input.isAdaptiveThreshold();
if (input.falsePixelsPerFrameIsSet())
ret.false_pixels_per_frame = input.getFalsePixelsPerFrame();
return ret;
}
org::openapitools::server::model::Spot_finding_settings Convert(const SpotFindingSettings &input) {
org::openapitools::server::model::Spot_finding_settings ret;
ret.setSignalToNoiseThreshold(input.signal_to_noise_threshold);
ret.setPhotonCountThreshold(input.photon_count_threshold);
ret.setMinPixPerSpot(input.min_pix_per_spot.value_or(2));
ret.setMaxPixPerSpot(input.max_pix_per_spot);
if (input.high_resolution_limit.has_value())
ret.setHighResolutionLimit(input.high_resolution_limit.value());
if (input.low_resolution_limit.has_value())
ret.setLowResolutionLimit(input.low_resolution_limit.value());
ret.setEnable(input.enable);
ret.setIndexing(input.indexing);
ret.setHighResolutionLimitForSpotCountLowRes(input.cutoff_spot_count_low_res);
ret.setQuickIntegration(input.quick_integration);
ret.setIceRingWidthQRecipA(input.ice_ring_width_Q_recipA);
if (input.high_res_gap_Q_recipA.has_value())
ret.setHighResGapQRecipA(input.high_res_gap_Q_recipA.value());
ret.setAdaptiveThreshold(input.adaptive_threshold);
ret.setFalsePixelsPerFrame(input.false_pixels_per_frame);
return ret;
}
org::openapitools::server::model::Measurement_statistics Convert(const MeasurementStatistics &input) {
org::openapitools::server::model::Measurement_statistics ret{};
if (!input.file_prefix.empty())
ret.setFilePrefix(input.file_prefix);
ret.setExperimentGroup(input.experiment_group);
ret.setImagesExpected(input.images_expected);
ret.setImagesCollected(input.images_collected);
ret.setImagesSent(input.images_sent);
ret.setImagesDiscardedLossyCompression(input.images_skipped);
ret.setMaxImageNumberSent(input.max_image_number_sent);
if (input.collection_efficiency)
ret.setCollectionEfficiency(input.collection_efficiency.value());
if (input.compression_ratio)
ret.setCompressionRatio(input.compression_ratio.value());
ret.setCancelled(input.cancelled);
if (input.max_receive_delay)
ret.setMaxReceiverDelay(input.max_receive_delay.value());
ret.setDetectorWidth(input.detector_width);
ret.setDetectorHeight(input.detector_height);
ret.setDetectorPixelDepth(input.detector_pixel_depth);
if (input.roi_beam_npixel)
ret.setRoiBeamPixels(input.roi_beam_npixel.value());
if (input.roi_beam_sum)
ret.setRoiBeamSum(input.roi_beam_sum.value());
if (input.error_pixels)
ret.setErrorPixels(input.error_pixels.value());
if (input.saturated_pixels)
ret.setSaturatedPixels(input.saturated_pixels.value());
if (input.indexing_rate)
ret.setIndexingRate(input.indexing_rate.value());
if (input.bkg_estimate)
ret.setBkgEstimate(input.bkg_estimate.value());
ret.setUnitCell(input.unit_cell);
ret.setRunNumber(input.run_number);
if (input.images_written)
ret.setImagesWritten(input.images_written.value());
return ret;
}
DetectorTiming Convert(const org::openapitools::server::model::Detector_timing& input) {
switch (input.getValue()) {
case org::openapitools::server::model::Detector_timing::eDetector_timing::AUTO:
return DetectorTiming::Auto;
case org::openapitools::server::model::Detector_timing::eDetector_timing::TRIGGER:
return DetectorTiming::Trigger;
case org::openapitools::server::model::Detector_timing::eDetector_timing::BURST:
return DetectorTiming::Burst;
case org::openapitools::server::model::Detector_timing::eDetector_timing::GATED:
return DetectorTiming::Gated;
default:
case org::openapitools::server::model::Detector_timing::eDetector_timing::INVALID_VALUE_OPENAPI_GENERATED:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "invalid input");
}
}
org::openapitools::server::model::Detector_timing Convert(DetectorTiming input) {
org::openapitools::server::model::Detector_timing val;
switch (input) {
case DetectorTiming::Auto:
val.setValue(org::openapitools::server::model::Detector_timing::eDetector_timing::AUTO);
break;
case DetectorTiming::Trigger:
val.setValue(org::openapitools::server::model::Detector_timing::eDetector_timing::TRIGGER);
break;
case DetectorTiming::Burst:
val.setValue(org::openapitools::server::model::Detector_timing::eDetector_timing::BURST);
break;
case DetectorTiming::Gated:
val.setValue(org::openapitools::server::model::Detector_timing::eDetector_timing::GATED);
break;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "invalid input");
}
return val;
}
DetectorSettings Convert(const org::openapitools::server::model::Detector_settings &input) {
DetectorSettings ret{};
if (input.countTimeUsIsSet())
ret.FrameTime(std::chrono::microseconds(input.getFrameTimeUs()),
std::chrono::microseconds(input.getCountTimeUs()));
else
ret.FrameTime(std::chrono::microseconds(input.getFrameTimeUs()));
ret.InternalGeneratorEnable(input.isInternalFrameGenerator());
ret.InternalGeneratorImages(input.getInternalFrameGeneratorImages());
ret.DetectorDelay(std::chrono::nanoseconds(input.getDetectorTriggerDelayNs()));
ret.StorageCells(input.getJungfrauStorageCellCount());
ret.StorageCellDelay(std::chrono::nanoseconds(input.getJungfrauStorageCellDelayNs()));
ret.FixGainG1(input.isJungfrauFixedGainG1());
ret.UseGainHG0(input.isJungfrauUseGainHg0());
ret.PedestalG0Frames(input.getJungfrauPedestalG0Frames());
ret.PedestalG1Frames(input.getJungfrauPedestalG1Frames());
ret.PedestalG2Frames(input.getJungfrauPedestalG2Frames());
ret.PedestalMinImageCount(input.getJungfrauPedestalMinImageCount());
if (input.eigerBitDepthIsSet())
ret.EigerBitDepth(input.getEigerBitDepth());
if (input.eigerThresholdKeVIsSet())
ret.EigerThreshold_keV(input.getEigerThresholdKeV());
if (input.timingIsSet())
ret.Timing(Convert(input.getTiming()));
else
ret.Timing(DetectorTiming::Trigger);
return ret;
}
org::openapitools::server::model::Detector_settings Convert(const DetectorSettings &input) {
org::openapitools::server::model::Detector_settings ret{};
ret.setFrameTimeUs(std::chrono::round<std::chrono::microseconds>(
std::chrono::duration<float>(input.GetFrameTime())).count());
if (input.GetCountTime().has_value())
ret.setCountTimeUs(std::chrono::round<std::chrono::microseconds>(
std::chrono::duration<float>(input.GetCountTime().value())
).count());
ret.setDetectorTriggerDelayNs(input.GetDetectorDelay().count());
ret.setInternalFrameGeneratorImages(input.GetInternalGeneratorImages());
ret.setInternalFrameGenerator(input.IsInternalGeneratorEnable());
ret.setJungfrauStorageCellCount(input.GetStorageCells());
ret.setJungfrauFixedGainG1(input.IsFixGainG1());
ret.setJungfrauUseGainHg0(input.IsUseGainHG0());
ret.setJungfrauPedestalG0Frames(input.GetPedestalG0Frames());
ret.setJungfrauPedestalG1Frames(input.GetPedestalG1Frames());
ret.setJungfrauPedestalG2Frames(input.GetPedestalG2Frames());
ret.setJungfrauPedestalMinImageCount(input.GetPedestalMinImageCount());
ret.setJungfrauStorageCellDelayNs(input.GetStorageCellDelay().count());
if (input.GetEigerThreshold_keV().has_value())
ret.setEigerThresholdKeV(input.GetEigerThreshold_keV().value());
if (input.GetEigerBitDepth().has_value())
ret.setEigerBitDepth(input.GetEigerBitDepth().value());
ret.setTiming(Convert(input.GetTiming()));
return ret;
}
org::openapitools::server::model::Broker_status Convert(const BrokerStatus& input) {
org::openapitools::server::model::Broker_status ret;
switch (input.state) {
case JFJochState::Inactive:
ret.setState("Inactive");
break;
case JFJochState::Idle:
ret.setState("Idle");
break;
case JFJochState::Measuring:
ret.setState("Measuring");
break;
case JFJochState::Error:
ret.setState("Error");
break;
case JFJochState::Busy:
ret.setState("Busy");
break;
case JFJochState::Calibration:
ret.setState("Pedestal");
break;
}
if (input.message.has_value())
ret.setMessage(input.message.value());
switch (input.message_severity) {
case BrokerStatus::MessageSeverity::Info:
ret.setMessageSeverity("info");
break;
case BrokerStatus::MessageSeverity::Success:
ret.setMessageSeverity("success");
break;
case BrokerStatus::MessageSeverity::Warning:
ret.setMessageSeverity("warning");
break;
default:
ret.setMessageSeverity("error");
break;
}
if (input.progress.has_value())
ret.setProgress(input.progress.value());
ret.setGpuCount(input.gpu_count);
ret.setBrokerVersion(input.broker_version);
return ret;
}
org::openapitools::server::model::Calibration_statistics_inner Convert(const JFCalibrationModuleStatistics& input) {
org::openapitools::server::model::Calibration_statistics_inner output;
output.setModuleNumber(input.module_number);
output.setMaskedPixels(input.bad_pixels);
output.setStorageCellNumber(input.storage_cell_number);
output.setGainG0Mean(input.gain_g0_mean);
output.setGainG1Mean(input.gain_g1_mean);
output.setGainG2Mean(input.gain_g2_mean);
output.setPedestalG0Mean(input.pedestal_g0_mean);
output.setPedestalG1Mean(input.pedestal_g1_mean);
output.setPedestalG2Mean(input.pedestal_g2_mean);
return output;
}
std::vector<org::openapitools::server::model::Calibration_statistics_inner> Convert(const std::vector<JFCalibrationModuleStatistics>& input) {
std::vector<org::openapitools::server::model::Calibration_statistics_inner> ret;
for (const auto &i: input)
ret.push_back(Convert(i));
return ret;
}
org::openapitools::server::model::Instrument_metadata Convert(const InstrumentMetadata& input) {
org::openapitools::server::model::Instrument_metadata output;
output.setInstrumentName(input.GetInstrumentName());
output.setSourceName(input.GetSourceName());
output.setSourceType(input.GetSourceType());
output.setPulsedSource(input.IsPulsedSource());
output.setElectronSource(input.IsElectronSource());
return output;
}
InstrumentMetadata Convert(const org::openapitools::server::model::Instrument_metadata &input) {
InstrumentMetadata output;
output.InstrumentName(input.getInstrumentName())
.SourceName(input.getSourceName())
.SourceType(input.getSourceType())
.PulsedSource(input.isPulsedSource())
.ElectronSource(input.isElectronSource());
return output;
}
org::openapitools::server::model::Detector_state Convert(DetectorState input) {
org::openapitools::server::model::Detector_state ret;
switch (input) {
case DetectorState::IDLE:
ret.setValue(org::openapitools::server::model::Detector_state::eDetector_state::IDLE);
break;
case DetectorState::ERROR:
ret.setValue(org::openapitools::server::model::Detector_state::eDetector_state::ERROR);
break;
case DetectorState::BUSY:
ret.setValue(org::openapitools::server::model::Detector_state::eDetector_state::BUSY);
break;
case DetectorState::WAITING:
ret.setValue(org::openapitools::server::model::Detector_state::eDetector_state::WAITING);
break;
default:
case DetectorState::NOT_CONNECTED:
ret.setValue(org::openapitools::server::model::Detector_state::eDetector_state::NOT_CONNECTED);
break;
}
return ret;
}
org::openapitools::server::model::Detector_power_state Convert(DetectorPowerState input) {
org::openapitools::server::model::Detector_power_state ret;
switch (input) {
case DetectorPowerState::ON:
ret.setValue(org::openapitools::server::model::Detector_power_state::eDetector_power_state::POWERON);
break;
case DetectorPowerState::PARTIAL:
ret.setValue(org::openapitools::server::model::Detector_power_state::eDetector_power_state::PARTIAL);
break;
default:
case DetectorPowerState::OFF:
ret.setValue(org::openapitools::server::model::Detector_power_state::eDetector_power_state::POWEROFF);
break;
}
return ret;
}
org::openapitools::server::model::Detector_status Convert(const DetectorStatus &input) {
org::openapitools::server::model::Detector_status output;
output.setServerVersion(input.detector_server_version);
output.setNumberOfTriggersLeft(input.remaining_triggers);
output.setFpgaTempDegC(input.temperature_fpga_degC);
output.setHighVoltageV(input.high_voltage_V);
output.setPowerchip(Convert(input.power_state));
output.setState(Convert(input.detector_state));
return output;
}
org::openapitools::server::model::Detector_type Convert(const DetectorType &input) {
org::openapitools::server::model::Detector_type dt;
switch (input) {
case DetectorType::EIGER:
dt.setValue(org::openapitools::server::model::Detector_type::eDetector_type::EIGER);
break;
case DetectorType::JUNGFRAU:
dt.setValue(org::openapitools::server::model::Detector_type::eDetector_type::JUNGFRAU);
break;
case DetectorType::DECTRIS:
dt.setValue(org::openapitools::server::model::Detector_type::eDetector_type::DECTRIS);
break;
}
return dt;
}
org::openapitools::server::model::Detector_list Convert(const DetectorList &input) {
org::openapitools::server::model::Detector_list ret;
std::vector<org::openapitools::server::model::Detector_list_element> dets;
for (int i = 0; i < input.detector.size(); i++) {
org::openapitools::server::model::Detector_list_element d;
d.setId(i);
d.setDescription(input.detector[i].description);
d.setNmodules(input.detector[i].nmodules);
d.setHeight(input.detector[i].height);
d.setWidth(input.detector[i].width);
d.setSerialNumber(input.detector[i].serial_number);
d.setBaseIpv4Addr(input.detector[i].base_ipv4_addr);
d.setUdpInterfaceCount(input.detector[i].udp_interface_count);
d.setMinFrameTimeNs(input.detector[i].min_frame_time.count());
d.setMinCountTimeNs(input.detector[i].min_count_time.count());
d.setReadoutTimeNs(input.detector[i].readout_time.count());
d.setPixelSizeMm(input.detector[i].pixel_size_mm);
d.setType(Convert(input.detector[i].detector_type));
dets.emplace_back(std::move(d));
}
ret.setDetectors(dets);
ret.setCurrentId(input.current_id);
return ret;
}
org::openapitools::server::model::Plots Convert(const MultiLinePlot& input) {
std::vector<org::openapitools::server::model::Plot> tmp(input.GetPlots().size());
for (int i = 0; i < input.GetPlots().size(); i++) {
tmp[i].setTitle(input.GetPlots()[i].title);
tmp[i].setX(input.GetPlots()[i].x);
tmp[i].setY(input.GetPlots()[i].y);
tmp[i].setZ(input.GetPlots()[i].z);
}
org::openapitools::server::model::Plots output;
output.setPlot(tmp);
org::openapitools::server::model::Plot_unit_x unit;
switch (input.GetUnits()) {
case MultiLinePlotUnits::ImageNumber:
unit.setValue(org::openapitools::server::model::Plot_unit_x::ePlot_unit_x::IMAGE_NUMBER);
break;
case MultiLinePlotUnits::Angle_deg:
unit.setValue(org::openapitools::server::model::Plot_unit_x::ePlot_unit_x::ANGLE_DEG);
break;
case MultiLinePlotUnits::Q_recipA:
unit.setValue(org::openapitools::server::model::Plot_unit_x::ePlot_unit_x::Q_RECIPA);
break;
case MultiLinePlotUnits::ADU:
unit.setValue(org::openapitools::server::model::Plot_unit_x::ePlot_unit_x::ADU);
break;
case MultiLinePlotUnits::d_A:
unit.setValue(org::openapitools::server::model::Plot_unit_x::ePlot_unit_x::D_A);
break;
case MultiLinePlotUnits::Grid_um:
unit.setValue(org::openapitools::server::model::Plot_unit_x::ePlot_unit_x::GRID_UM);
break;
default:
break;
}
output.setUnitX(unit);
if (input.GetSizeX().has_value())
output.setSizeX(input.GetSizeX().value());
if (input.GetSizeY().has_value())
output.setSizeY(input.GetSizeY().value());
return output;
}
AzimuthalIntegrationSettings Convert(const org::openapitools::server::model::Azim_int_settings& input) {
AzimuthalIntegrationSettings ret{};
ret.SolidAngleCorrection(input.isSolidAngleCorr());
ret.PolarizationCorrection(input.isPolarizationCorr());
ret.QSpacing_recipA(input.getQSpacing());
ret.QRange_recipA(input.getLowQRecipA(),
input.highQRecipAIsSet() ? std::optional<float>(input.getHighQRecipA())
: std::nullopt);
ret.AzimuthalBinCount(input.getAzimuthalBins());
ret.ForceCPUinFPGAWorkflow(input.isForceCpu());
return ret;
}
org::openapitools::server::model::Azim_int_settings Convert(const AzimuthalIntegrationSettings& settings) {
org::openapitools::server::model::Azim_int_settings ret{};
ret.setSolidAngleCorr(settings.IsSolidAngleCorrection());
ret.setPolarizationCorr(settings.IsPolarizationCorrection());
if (const auto high_q = settings.GetRequestedHighQ_recipA())
ret.setHighQRecipA(high_q.value());
ret.setLowQRecipA(settings.GetLowQ_recipA());
ret.setQSpacing(settings.GetQSpacing_recipA());
ret.setAzimuthalBins(settings.GetAzimuthalBinCount());
ret.setForceCpu(settings.IsForceCPUinFPGAWorkflow());
return ret;
}
ROIDefinition Convert(const org::openapitools::server::model::Roi_definitions& input) {
ROIDefinition output{};
for (const auto &i: input.getBox().getRois())
output.boxes.emplace_back(ROIBox(i.getName(), i.getMinXPxl(), i.getMaxXPxl(), i.getMinYPxl(), i.getMaxYPxl()));
for (const auto &i: input.getCircle().getRois())
output.circles.emplace_back(ROICircle(i.getName(), i.getCenterXPxl(), i.getCenterYPxl(), i.getRadiusPxl()));
for (const auto &i: input.getAzim().getRois()) {
// A sector needs both bounds; if only one is given, treat it as a full ring.
float phi_min = 0, phi_max = 0;
if (i.phiMinDegIsSet() && i.phiMaxDegIsSet()) {
phi_min = i.getPhiMinDeg();
phi_max = i.getPhiMaxDeg();
}
output.azimuthal.emplace_back(ROIAzimuthal(i.getName(),
(i.getQMaxRecipA() == 0.0) ? 0.0 : 2.0f * PI / i.getQMaxRecipA(),
(i.getQMinRecipA() == 0.0) ? 0.0 : 2.0f * PI / i.getQMinRecipA(),
phi_min, phi_max));
}
return output;
}
org::openapitools::server::model::Roi_circle_list Convert(const std::vector<ROICircle> &input) {
org::openapitools::server::model::Roi_circle_list ret{};
std::vector<org::openapitools::server::model::Roi_circle> tmp;
for (const auto &i: input) {
org::openapitools::server::model::Roi_circle elem;
elem.setName(i.GetName());
elem.setCenterXPxl(i.GetX());
elem.setCenterYPxl(i.GetY());
elem.setRadiusPxl(i.GetRadius_pxl());
tmp.emplace_back(elem);
}
ret.setRois(tmp);
return ret;
}
org::openapitools::server::model::Roi_azim_list Convert(const std::vector<ROIAzimuthal> &input) {
org::openapitools::server::model::Roi_azim_list ret{};
std::vector<org::openapitools::server::model::Roi_azimuthal> tmp;
for (const auto &i: input) {
org::openapitools::server::model::Roi_azimuthal elem;
elem.setName(i.GetName());
elem.setQMinRecipA(i.GetQMin_recipA());
elem.setQMaxRecipA(i.GetQMax_recipA());
if (i.HasPhi()) {
elem.setPhiMinDeg(i.GetPhiMin_deg());
elem.setPhiMaxDeg(i.GetPhiMax_deg());
}
tmp.emplace_back(elem);
}
ret.setRois(tmp);
return ret;
}
org::openapitools::server::model::Roi_box_list Convert(const std::vector<ROIBox> &input) {
org::openapitools::server::model::Roi_box_list ret{};
std::vector<org::openapitools::server::model::Roi_box> tmp;
for (const auto &i: input) {
org::openapitools::server::model::Roi_box elem;
elem.setName(i.GetName());
elem.setMinXPxl(i.GetXMin());
elem.setMaxXPxl(i.GetXMax());
elem.setMinYPxl(i.GetYMin());
elem.setMaxYPxl(i.GetYMax());
tmp.emplace_back(elem);
}
ret.setRois(tmp);
return ret;
}
org::openapitools::server::model::Roi_definitions Convert(const ROIDefinition &input) {
org::openapitools::server::model::Roi_definitions ret{};
ret.setCircle(Convert(input.circles));
ret.setBox(Convert(input.boxes));
ret.setAzim(Convert(input.azimuthal));
return ret;
}
ImageFormatSettings Convert(const org::openapitools::server::model::Image_format_settings& input) {
ImageFormatSettings ret{};
ret.GeometryTransformed(input.isGeometryTransform());
ret.AutoSummation(input.isSummation());
ret.JungfrauConversion(input.isJungfrauConversion());
ret.MaskChipEdges(input.isMaskChipEdges());
ret.MaskModuleEdges(input.isMaskModuleEdges());
ret.ApplyPixelMask(input.isApplyMask());
ret.PedestalG0RMSLimit(input.getJungfrauPedestalG0RmsLimit());
ret.MaskPixelsWithoutG0(input.isJungfrauMaskPixelsWithoutG0());
if (input.signedOutputIsSet())
ret.PixelSigned(input.isSignedOutput());
if (input.jungfrauConversionFactorKeVIsSet())
ret.JungfrauConvFactor_keV(input.getJungfrauConversionFactorKeV());
if (input.bitDepthImageIsSet())
ret.BitDepthImage(input.getBitDepthImage());
return ret;
}
org::openapitools::server::model::Image_format_settings Convert(const ImageFormatSettings& input) {
org::openapitools::server::model::Image_format_settings ret{};
ret.setGeometryTransform(input.IsGeometryTransformed());
ret.setSummation(input.IsAutoSummation());
ret.setJungfrauConversion(input.IsJungfrauConversion());
ret.setMaskChipEdges(input.IsMaskChipEdges());
ret.setMaskModuleEdges(input.IsMaskModuleEdges());
ret.setApplyMask(input.IsApplyPixelMask());
ret.setJungfrauMaskPixelsWithoutG0(input.IsMaskPixelsWithoutG0());
ret.setJungfrauPedestalG0RmsLimit(input.GetPedestalG0RMSLimit());
if (input.IsPixelSigned().has_value())
ret.setSignedOutput(input.IsPixelSigned().value());
if (input.GetJungfrauConvFactor_keV().has_value())
ret.setJungfrauConversionFactorKeV(input.GetJungfrauConvFactor_keV().value());
if (input.GetBitDepthImage().has_value())
ret.setBitDepthImage(input.GetBitDepthImage().value());
return ret;
}
Coord ConvertOpenAPI(const std::vector<float> &input) {
if (input.size() != 3)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Wrong size of Coord array");
return {input[0], input[1], input[2]};
}
GoniometerAxis Convert(const org::openapitools::server::model::Rotation_axis& input) {
std::optional<Coord> helical;
if (input.helicalStepUmIsSet())
helical = ConvertOpenAPI(input.getHelicalStepUm());
GoniometerAxis axis{input.getName(), input.getStart(), input.getStep(),
ConvertOpenAPI(input.getVector()), helical};
if (input.screeningWedgeDegIsSet())
axis.ScreeningWedge(input.getScreeningWedgeDeg());
return axis;
}
GridScanSettings Convert(const org::openapitools::server::model::Grid_scan& input) {
return {input.getNFast(), input.getStepXUm(), input.getStepYUm(), input.isSnake(), input.isVertical()};
}
DatasetSettings Convert(const org::openapitools::server::model::Dataset_settings& input) {
DatasetSettings ret;
ret.ImagesPerTrigger(input.getImagesPerTrigger());
ret.NumTriggers(input.getNtrigger());
if (input.runNumberIsSet())
ret.RunNumber(input.getRunNumber());
if (input.runNameIsSet())
ret.RunName(input.getRunName());
ret.ExperimentGroup(input.getExperimentGroup());
if (input.imageTimeUsIsSet())
ret.ImageTime(std::chrono::microseconds(input.getImageTimeUs()));
ret.BeamX_pxl(input.getBeamXPxl());
ret.BeamY_pxl(input.getBeamYPxl());
ret.DetectorDistance_mm(input.getDetectorDistanceMm());
ret.PhotonEnergy_keV(input.getIncidentEnergyKeV());
ret.FilePrefix(input.getFilePrefix());
if (!input.compressionIsSet())
ret.Compression(CompressionAlgorithm::BSHUF_LZ4);
else {
std::string compr = str_tolower(input.getCompression());
if (compr == "bslz4")
ret.Compression(CompressionAlgorithm::BSHUF_LZ4);
else if (compr == "bszstd")
ret.Compression(CompressionAlgorithm::BSHUF_ZSTD);
else if (compr == "bszstd_rle")
ret.Compression(CompressionAlgorithm::BSHUF_ZSTD_RLE);
else if (compr == "bszstd_rlehuf")
ret.Compression(CompressionAlgorithm::BSHUF_ZSTD_RLE_HUFF);
else if (compr == "none")
ret.Compression(CompressionAlgorithm::NO_COMPRESSION);
else
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Unknown compression");
}
if (input.poissonCompressionIsSet())
ret.LossyCompressionPoisson(input.getPoissonCompression());
if (input.unitCellIsSet())
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.TotalFlux(input.getTotalFlux());
if (input.beamSizeXUmIsSet())
ret.BeamSizeX_um(input.getBeamSizeXUm());
if (input.beamSizeYUmIsSet())
ret.BeamSizeY_um(input.getBeamSizeYUm());
if (input.transmissionIsSet())
ret.AttenuatorTransmission(input.getTransmission());
// Not alternatives: a grid scan is often collected at a given head position, so an axis and a
// grid can both be set. This used to drop the grid scan silently whenever an axis was present.
if (input.goniometerIsSet())
ret.Goniometer(Convert(input.getGoniometer()));
if (input.gridScanIsSet())
ret.GridScan(Convert(input.getGridScan()));
if (input.spaceGroupNumberIsSet())
ret.SpaceGroupNumber(input.getSpaceGroupNumber());
ret.SampleName(input.getSampleName());
ret.HeaderAppendix(input.getHeaderAppendix());
ret.ImageAppendix(input.getImageAppendix());
if (input.imagesPerFileIsSet())
ret.ImagesPerFile(input.getImagesPerFile());
if (input.dataReductionFactorSerialmxIsSet())
ret.LossyCompressionSerialMX(input.getDataReductionFactorSerialmx());
if (input.pixelValueLowThresholdIsSet())
ret.PixelValueLowThreshold(input.getPixelValueLowThreshold());
if (input.saveCalibrationIsSet())
ret.SaveCalibration(input.isSaveCalibration());
ret.WriteNXmxHDF5Master(input.isWriteNxmxHdf5Master());
if (input.polarizationFactorIsSet())
ret.PolarizationFactor(input.getPolarizationFactor());
ret.PoniRot1_rad(input.getPoniRot1Rad());
ret.PoniRot2_rad(input.getPoniRot2Rad());
ret.PoniRot3_rad(input.getPoniRot3Rad());
if (input.ringCurrentMAIsSet())
ret.RingCurrent_mA(input.getRingCurrentMA());
if (input.sampleTemperatureKIsSet())
ret.SampleTemperature_K(input.getSampleTemperatureK());
ret.SpotFindingEnable(input.isSpotFinding());
ret.MaxSpotCount(input.getMaxSpotCount());
ret.DetectIceRings(input.isDetectIceRings());
if (input.xrayFluorescenceSpectrumIsSet()) {
auto fl = input.getXrayFluorescenceSpectrum();
ret.FluorescenceSpectrum({fl.getEnergyEV(), fl.getData()});
}
if (input.smargonIsSet()) {
auto sm = input.getSmargon();
SmargonPosition smargon;
smargon.phi_deg = sm.getPhiDeg();
smargon.chi_deg = sm.getChiDeg();
if (sm.phiAxisIsSet())
smargon.phi_axis = ConvertOpenAPI(sm.getPhiAxis());
if (sm.chiAxisIsSet())
smargon.chi_axis = ConvertOpenAPI(sm.getChiAxis());
ret.Smargon(smargon);
}
return ret;
}
std::vector<org::openapitools::server::model::Fpga_status_inner> Convert(const std::vector<DeviceStatus> &input) {
std::vector<org::openapitools::server::model::Fpga_status_inner> ret;
for (const auto &d: input) {
org::openapitools::server::model::Fpga_status_inner tmp;
tmp.setPciDevId(d.device_number);
tmp.setSerialNumber(d.serial_number);
tmp.setFwVersion(d.fpga_firmware_version);
tmp.setBaseMacAddr(MacAddressToStr(d.fpga_default_mac_addr));
tmp.setPacketsSls(d.packets_sls);
tmp.setPacketsUdp(d.packets_udp);
tmp.setEthLinkCount(d.eth_link_count);
tmp.setEthLinkStatus(d.eth_link_status);
tmp.setFpgaTempC(static_cast<float>(d.fpga_temp_C));
tmp.setHbmTempC(static_cast<float>(d.hbm_0_temp_C));
tmp.setPowerUsageW(static_cast<float>(d.fpga_pcie_12V_I_mA * d.fpga_pcie_12V_V_mV + d.fpga_pcie_3p3V_I_mA
* d.fpga_pcie_3p3V_V_mV) / (1000.0f * 1000.0f));
tmp.setIdle(d.idle);
tmp.setPcieLinkSpeed(d.pcie_link_speed);
tmp.setPcieLinkWidth(d.pcie_link_width);
ret.emplace_back(std::move(tmp));
}
return ret;
}
ZMQPreviewSettings Convert(const org::openapitools::server::model::Zeromq_preview_settings &input) {
ZMQPreviewSettings ret;
if (input.isEnabled())
ret.period = std::chrono::milliseconds(input.getPeriodMs());
else
ret.period = {};
ret.address = "";
return ret;
}
ZMQMetadataSettings Convert(const org::openapitools::server::model::Zeromq_metadata_settings &input) {
ZMQMetadataSettings ret;
if (input.isEnabled())
ret.period = std::chrono::milliseconds(input.getPeriodMs());
else
ret.period = {};
ret.address = "";
return ret;
}
org::openapitools::server::model::Zeromq_preview_settings Convert(const ZMQPreviewSettings &settings) {
org::openapitools::server::model::Zeromq_preview_settings ret;
ret.setEnabled(settings.period.has_value());
if (settings.period.has_value())
ret.setPeriodMs(std::chrono::round<std::chrono::milliseconds>(settings.period.value()).count());
ret.setSocketAddress(settings.address);
return ret;
}
org::openapitools::server::model::Zeromq_metadata_settings Convert(const ZMQMetadataSettings &settings) {
org::openapitools::server::model::Zeromq_metadata_settings ret;
ret.setEnabled(settings.period.has_value());
if (settings.period.has_value())
ret.setPeriodMs(std::chrono::round<std::chrono::milliseconds>(settings.period.value()).count());
ret.setSocketAddress(settings.address);
return ret;
}
org::openapitools::server::model::Pixel_mask_statistics Convert(const PixelMaskStatistics& input) {
org::openapitools::server::model::Pixel_mask_statistics ret;
ret.setUserMask(input.user_mask);
ret.setWrongGain(input.error_pixel);
ret.setTooHighPedestalRms(input.noisy_pixel);
return ret;
}
org::openapitools::server::model::Image_buffer_status Convert(const ImageBufferStatus& input) {
org::openapitools::server::model::Image_buffer_status ret;
ret.setAvailableSlots(input.available_slots);
ret.setTotalSlots(input.total_slots);
ret.setImageNumbers(input.images_in_the_buffer);
ret.setMaxImageNumber(input.max_image_number);
ret.setMinImageNumber(input.min_image_number);
ret.setInPreparationSlots(input.preparation_slots);
ret.setInSendingSlots(input.sending_slots);
if (input.current_counter.has_value())
ret.setCurrentCounter(input.current_counter.value());
return ret;
}
ImageBufferStatus Convert(const org::openapitools::server::model::Image_buffer_status& input) {
ImageBufferStatus ret;
ret.available_slots = input.getAvailableSlots();
ret.total_slots = input.getTotalSlots();
ret.images_in_the_buffer = input.getImageNumbers();
ret.max_image_number = input.getMaxImageNumber();
ret.min_image_number = input.getMinImageNumber();
ret.sending_slots = input.getInSendingSlots();
ret.preparation_slots = input.getInPreparationSlots();
if (input.currentCounterIsSet())
ret.current_counter = input.getCurrentCounter();
return ret;
}
org::openapitools::server::model::File_writer_settings Convert(const FileWriterSettings& input) {
org::openapitools::server::model::File_writer_settings ret;
ret.setFormat(Convert(input.GetFileFormat()));
ret.setOverwrite(input.IsOverwriteExistingFiles());
return ret;
}
FileWriterSettings Convert(const org::openapitools::server::model::File_writer_settings &input) {
FileWriterSettings ret;
ret.OverwriteExistingFiles(input.isOverwrite());
ret.FileFormat(Convert(input.getFormat()));
return ret;
}
org::openapitools::server::model::File_writer_format Convert(FileWriterFormat input) {
org::openapitools::server::model::File_writer_format ret;
switch (input) {
case FileWriterFormat::DataOnly:
ret.setValue(org::openapitools::server::model::File_writer_format::eFile_writer_format::NXMXONLYDATA);
break;
case FileWriterFormat::NXmxLegacy:
ret.setValue(org::openapitools::server::model::File_writer_format::eFile_writer_format::NXMXLEGACY);
break;
case FileWriterFormat::NXmxVDS:
ret.setValue(org::openapitools::server::model::File_writer_format::eFile_writer_format::NXMXVDS);
break;
case FileWriterFormat::NXmxIntegrated:
ret.setValue(org::openapitools::server::model::File_writer_format::eFile_writer_format::NXMXINTEGRATED);
break;
case FileWriterFormat::NoFile:
ret.setValue(org::openapitools::server::model::File_writer_format::eFile_writer_format::NOFILEWRITTEN);
break;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Unknown file writer format enum value");
}
return ret;
}
FileWriterFormat Convert(const org::openapitools::server::model::File_writer_format& input) {
switch (input.getValue()) {
case org::openapitools::server::model::File_writer_format::eFile_writer_format::NXMXONLYDATA:
return FileWriterFormat::DataOnly;
case org::openapitools::server::model::File_writer_format::eFile_writer_format::NXMXLEGACY:
return FileWriterFormat::NXmxLegacy;
case org::openapitools::server::model::File_writer_format::eFile_writer_format::NXMXVDS:
return FileWriterFormat::NXmxVDS;
case org::openapitools::server::model::File_writer_format::eFile_writer_format::NXMXINTEGRATED:
return FileWriterFormat::NXmxIntegrated;
case org::openapitools::server::model::File_writer_format::eFile_writer_format::CBF:
case org::openapitools::server::model::File_writer_format::eFile_writer_format::TIFF:
// Deprecated, kept in the OpenAPI enum for back compatibility only - only HDF5 is written now.
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"CBF and TIFF file formats are no longer supported");
case org::openapitools::server::model::File_writer_format::eFile_writer_format::NOFILEWRITTEN:
return FileWriterFormat::NoFile;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Unknown file writer format enum value");
}
}
PlotType ConvertPlotType(const std::optional<std::string>& input) {
if (!input.has_value())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Plot type is compulsory paramater");
if (input == "bkg_estimate") return PlotType::BkgEstimate;
if (input == "spindle_blind_fraction") return PlotType::SpindleBlindFraction;
if (input == "ice_ring_score") return PlotType::IceRingScore;
if (input == "azint") return PlotType::AzInt;
if (input == "azint_1d") return PlotType::AzInt1D;
if (input == "spot_count") return PlotType::SpotCount;
if (input == "spot_count_low_res") return PlotType::SpotCountLowRes;
if (input == "spot_count_indexed") return PlotType::SpotCountIndexed;
if (input == "spot_count_ice") return PlotType::SpotCountIceRing;
if (input == "indexing_rate") return PlotType::IndexingRate;
if (input == "indexing_unit_cell_length") return PlotType::IndexingUnitCellLength;
if (input == "profile_radius") return PlotType::ProfileRadius;
if (input == "mosaicity") return PlotType::Mosaicity;
if (input == "b_factor") return PlotType::BFactor;
if (input == "indexing_unit_cell_angle") return PlotType::IndexingUnitCellAngle;
if (input == "error_pixels") return PlotType::ErrorPixels;
if (input == "strong_pixels") return PlotType::StrongPixels;
if (input == "saturated_pixels") return PlotType::SaturatedPixels;
if (input == "image_collection_efficiency") return PlotType::ImageCollectionEfficiency;
if (input == "receiver_delay") return PlotType::ReceiverDelay;
if (input == "receiver_free_send_buf") return PlotType::ReceiverFreeSendBuf;
if (input == "roi_sum") return PlotType::ROISum;
if (input == "roi_mean") return PlotType::ROIMean;
if (input == "roi_max_count") return PlotType::ROIMaxCount;
if (input == "roi_pixels") return PlotType::ROIPixels;
if (input == "roi_weighted_x") return PlotType::ROIWeightedX;
if (input == "roi_weighted_y") return PlotType::ROIWeightedY;
if (input == "packets_received") return PlotType::PacketsReceived;
if (input == "max_pixel_value") return PlotType::MaxValue;
if (input == "resolution_estimate") return PlotType::ResolutionEstimate;
if (input == "pixel_sum") return PlotType::PixelSum;
if (input == "processing_time") return PlotType::ImageProcessingTime;
if (input == "beam_center_x") return PlotType::RefinementBeamX;
if (input == "beam_center_y") return PlotType::RefinementBeamY;
if (input == "integrated_reflections") return PlotType::IntegratedReflections;
if (input == "image_scale_factor") return PlotType::ImageScaleFactor;
if (input == "image_scale_cc") return PlotType::ImageScaleCC;
if (input == "compression_ratio") return PlotType::CompressionRatio;
if (input == "indexing_lattice_count") return PlotType::IndexingLatticeCount;
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Plot type not recognized");
}
ColorScaleEnum ConvertColorScale(const std::optional<std::string> &input) {
std::string color = input.value_or("indigo");
if (color == "viridis")
return ColorScaleEnum::Viridis;
if (color == "bw")
return ColorScaleEnum::BW;
if (color == "wb")
return ColorScaleEnum::WB;
if (color == "green")
return ColorScaleEnum::Green;
if (color == "heat")
return ColorScaleEnum::Heat;
if (color == "indigo")
return ColorScaleEnum::Indigo;
if (color == "magma")
return ColorScaleEnum::Magma;
if (color == "inferno")
return ColorScaleEnum::Inferno;
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Color scale unknown");
}
IndexingSettings Convert(const org::openapitools::server::model::Indexing_settings &input) {
IndexingSettings ret;
switch (input.getAlgorithm().getValue()) {
case org::openapitools::server::model::Indexing_algorithm::eIndexing_algorithm::FFT:
ret.Algorithm(IndexingAlgorithmEnum::FFT);
break;
case org::openapitools::server::model::Indexing_algorithm::eIndexing_algorithm::FFTW:
ret.Algorithm(IndexingAlgorithmEnum::FFTW);
break;
case org::openapitools::server::model::Indexing_algorithm::eIndexing_algorithm::NONE:
ret.Algorithm(IndexingAlgorithmEnum::None);
break;
case org::openapitools::server::model::Indexing_algorithm::eIndexing_algorithm::FFBIDX:
ret.Algorithm(IndexingAlgorithmEnum::FFBIDX);
break;
case org::openapitools::server::model::Indexing_algorithm::eIndexing_algorithm::AUTO:
ret.Algorithm(IndexingAlgorithmEnum::Auto);
break;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Unknown indexing algorithm");
}
switch (input.getGeomRefinementAlgorithm().getValue()) {
case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::INVALID_VALUE_OPENAPI_GENERATED:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Unknown refinement algorithm");
break;
case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::BEAMCENTER:
ret.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::BeamCenter);
break;
case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::ORIENTATIONONLY:
ret.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::OrientationOnly);
break;
case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::FLEX:
ret.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::Flex);
break;
case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::NONE:
ret.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::None);
break;
}
ret.FFT_HighResolution_A(input.getFftHighResolutionA());
ret.FFT_MaxUnitCell_A(input.getFftMaxUnitCellA());
ret.FFT_MinUnitCell_A(input.getFftMinUnitCellA());
ret.FFT_NumVectors(input.getFftNumVectors());
ret.Tolerance(input.getTolerance());
ret.IndexingThreads(input.getThreadCount());
ret.UnitCellDistTolerance(input.getUnitCellDistTolerance());
ret.ViableCellMinSpots(input.getViableCellMinSpots());
ret.IndexIceRings(input.isIndexIceRings());
ret.RotationIndexing(input.isRotationIndexing());
ret.RotationIndexingAngularStride_deg(input.getRotationIndexingAngularStrideDeg());
ret.RotationIndexingMinAngularRange_deg(input.getRotationIndexingMinAngularRangeDeg());
ret.BlockingBehavior(input.isBlocking());
return ret;
}
org::openapitools::server::model::Indexing_settings Convert(const IndexingSettings &input) {
org::openapitools::server::model::Indexing_settings ret;
ret.setFftHighResolutionA(input.GetFFT_HighResolution_A());
ret.setFftMinUnitCellA(input.GetFFT_MinUnitCell_A());
ret.setFftMaxUnitCellA(input.GetFFT_MaxUnitCell_A());
ret.setFftNumVectors(input.GetFFT_NumVectors());
ret.setTolerance(input.GetTolerance());
ret.setThreadCount(input.GetIndexingThreads());
ret.setUnitCellDistTolerance(input.GetUnitCellDistTolerance());
ret.setViableCellMinSpots(input.GetViableCellMinSpots());
ret.setRotationIndexing(input.GetRotationIndexing());
ret.setRotationIndexingAngularStrideDeg(input.GetRotationIndexingAngularStride_deg());
ret.setRotationIndexingMinAngularRangeDeg(input.GetRotationIndexingMinAngularRange_deg());
ret.setBlocking(input.GetBlockingBehavior());
org::openapitools::server::model::Geom_refinement_algorithm refinement;
switch (input.GetGeomRefinementAlgorithm()) {
case GeomRefinementAlgorithmEnum::None:
refinement.setValue(org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::NONE);
break;
case GeomRefinementAlgorithmEnum::BeamCenter:
refinement.setValue(org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::BEAMCENTER);
break;
case GeomRefinementAlgorithmEnum::OrientationOnly:
refinement.setValue(org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::ORIENTATIONONLY);
break;
case GeomRefinementAlgorithmEnum::Flex:
refinement.setValue(org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::FLEX);
break;
}
ret.setGeomRefinementAlgorithm(refinement);
org::openapitools::server::model::Indexing_algorithm tmp;
switch (input.GetAlgorithm()) {
case IndexingAlgorithmEnum::Auto:
tmp.setValue(org::openapitools::server::model::Indexing_algorithm::eIndexing_algorithm::AUTO);
break;
case IndexingAlgorithmEnum::FFBIDX:
tmp.setValue(org::openapitools::server::model::Indexing_algorithm::eIndexing_algorithm::FFBIDX);
break;
case IndexingAlgorithmEnum::FFT:
tmp.setValue(org::openapitools::server::model::Indexing_algorithm::eIndexing_algorithm::FFT);
break;
case IndexingAlgorithmEnum::FFTW:
tmp.setValue(org::openapitools::server::model::Indexing_algorithm::eIndexing_algorithm::FFTW);
break;
case IndexingAlgorithmEnum::None:
tmp.setValue(org::openapitools::server::model::Indexing_algorithm::eIndexing_algorithm::NONE);
break;
}
ret.setAlgorithm(tmp);
ret.setIndexIceRings(input.GetIndexIceRings());
return ret;
}
BraggIntegrationSettings Convert(const org::openapitools::server::model::Bragg_integration_settings &input) {
BraggIntegrationSettings ret;
switch (input.getIntegrationModel().getValue()) {
case org::openapitools::server::model::Integration_model::eIntegration_model::PROFILEGAUSSIAN:
ret.Integrator(IntegratorMode::ProfileGaussian);
break;
case org::openapitools::server::model::Integration_model::eIntegration_model::PROFILEEMPIRICAL:
ret.Integrator(IntegratorMode::ProfileEmpirical);
break;
case org::openapitools::server::model::Integration_model::eIntegration_model::BOXSUM:
ret.Integrator(IntegratorMode::BoxSum);
break;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Unknown integration model");
}
// Always a concrete number online, never "derive it from the crystal": the generated model holds
// the schema's default when the request omits the field, so an absent max_hkl arrives here as that
// default rather than as an absent value. Deriving per crystal would make a live acquisition's
// per-image cost depend on whichever sample is mounted.
ret.MaxHKL(input.getMaxHkl());
return ret;
}
org::openapitools::server::model::Bragg_integration_settings Convert(const BraggIntegrationSettings &input) {
org::openapitools::server::model::Bragg_integration_settings ret;
org::openapitools::server::model::Integration_model tmp;
switch (input.GetIntegrator()) {
case IntegratorMode::ProfileGaussian:
tmp.setValue(org::openapitools::server::model::Integration_model::eIntegration_model::PROFILEGAUSSIAN);
break;
case IntegratorMode::ProfileEmpirical:
tmp.setValue(org::openapitools::server::model::Integration_model::eIntegration_model::PROFILEEMPIRICAL);
break;
case IntegratorMode::BoxSum:
tmp.setValue(org::openapitools::server::model::Integration_model::eIntegration_model::BOXSUM);
break;
}
ret.setIntegrationModel(tmp);
if (const auto max_hkl = input.GetMaxHKL())
ret.setMaxHkl(*max_hkl);
return ret;
}
AnalysisSettings Convert(const org::openapitools::server::model::Analysis_settings &input) {
AnalysisSettings ret;
// No default: the compiler must object here when a mode is added to the API, rather than let the
// new value fall through to whatever the last branch was. MXRotation is not in the API at all -
// jfjoch_broker has no rotation analysis path - so there is no case for it.
switch (input.getMode().getValue()) {
case org::openapitools::server::model::Analysis_mode::eAnalysis_mode::INVALID_VALUE_OPENAPI_GENERATED:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Unknown analysis mode");
case org::openapitools::server::model::Analysis_mode::eAnalysis_mode::NONE:
ret.Mode(AnalysisMode::None);
break;
case org::openapitools::server::model::Analysis_mode::eAnalysis_mode::MXSTILLS:
ret.Mode(AnalysisMode::MXStills);
break;
case org::openapitools::server::model::Analysis_mode::eAnalysis_mode::AZINT:
ret.Mode(AnalysisMode::Azint);
break;
case org::openapitools::server::model::Analysis_mode::eAnalysis_mode::GRID:
ret.Mode(AnalysisMode::Grid);
break;
case org::openapitools::server::model::Analysis_mode::eAnalysis_mode::POWDERCALIBRATION:
ret.Mode(AnalysisMode::PowderCalibration);
break;
}
if (input.calibrantIsSet())
ret.Calibrant(input.getCalibrant());
return ret;
}
org::openapitools::server::model::Analysis_settings Convert(const AnalysisSettings &input) {
org::openapitools::server::model::Analysis_settings ret;
org::openapitools::server::model::Analysis_mode tmp;
switch (input.GetMode()) {
case AnalysisMode::None:
tmp.setValue(org::openapitools::server::model::Analysis_mode::eAnalysis_mode::NONE);
break;
case AnalysisMode::MXStills:
tmp.setValue(org::openapitools::server::model::Analysis_mode::eAnalysis_mode::MXSTILLS);
break;
case AnalysisMode::Azint:
tmp.setValue(org::openapitools::server::model::Analysis_mode::eAnalysis_mode::AZINT);
break;
case AnalysisMode::Grid:
tmp.setValue(org::openapitools::server::model::Analysis_mode::eAnalysis_mode::GRID);
break;
case AnalysisMode::PowderCalibration:
tmp.setValue(org::openapitools::server::model::Analysis_mode::eAnalysis_mode::POWDERCALIBRATION);
break;
case AnalysisMode::MXRotation:
// Unreachable through the API: the setter refuses it, so it can never be stored. Reported
// rather than silently rewritten to stills, which would be the broker claiming to run an
// analysis it does not have.
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Rotation MX analysis cannot be reported by this API");
}
ret.setMode(tmp);
if (!input.GetCalibrant().empty())
ret.setCalibrant(input.GetCalibrant());
return ret;
}
org::openapitools::server::model::Powder_calibration_output Convert(const CalibrationResult &input) {
org::openapitools::server::model::Powder_calibration_output ret;
const auto &g = input.geometry;
// The geometry under this API's own property names, so it can be PUT back without translating a
// field. Same content as the <prefix>.json rugnux writes (WriteCalibrationJson).
org::openapitools::server::model::Dataset_settings settings;
settings.setBeamXPxl(g.GetBeamX_pxl());
settings.setBeamYPxl(g.GetBeamY_pxl());
settings.setDetectorDistanceMm(g.GetDetectorDistance_mm());
settings.setIncidentEnergyKeV(WVL_1A_IN_KEV / g.GetWavelength_A());
// The rotations go in together or not at all: omitting them would state a FLAT detector, since the
// schema's default is 0.0, rather than leave the tilt unstated.
if (g.GetPoniRot1_rad() != 0.0f || g.GetPoniRot2_rad() != 0.0f || g.GetPoniRot3_rad() != 0.0f) {
settings.setPoniRot1Rad(g.GetPoniRot1_rad());
settings.setPoniRot2Rad(g.GetPoniRot2_rad());
settings.setPoniRot3Rad(g.GetPoniRot3_rad());
}
ret.setDatasetSettings(settings);
org::openapitools::server::model::Powder_calibration_quality quality;
// The verdict first: a caller that reads nothing else must still not mistake a non-fit for a fit.
quality.setConverged(input.converged);
if (!input.converged)
quality.setNotConvergedReason(input.reason);
quality.setRingPoints(input.ring_points);
quality.setRmsRadialPxl(input.rms_radial_pxl);
quality.setBeamSigmaPxl(input.beam_sigma_pxl);
// Where the beam actually lands, which is not the PONI above once the detector is tilted.
const auto [direct_x, direct_y] = g.GetDirectBeam_pxl();
quality.setDirectBeamXPxl(direct_x);
quality.setDirectBeamYPxl(direct_y);
quality.setHeaderDistanceMm(input.header_distance_mm);
quality.setTiltRefined(input.tilt_refined);
quality.setTiltSignificance(input.tilt_significance);
if (input.seed_distance_mm > 0.0f)
quality.setRingSeedDistanceMm(input.seed_distance_mm);
if (input.uncertainty.valid) {
org::openapitools::server::model::Powder_calibration_fit_sigma sigma;
sigma.setBeamXPxl(input.uncertainty.sigma_beam_x_pxl);
sigma.setBeamYPxl(input.uncertainty.sigma_beam_y_pxl);
sigma.setDetectorDistanceMm(input.uncertainty.sigma_distance_mm);
if (input.uncertainty.sigma_rot1_rad > 0.0 || input.uncertainty.sigma_rot2_rad > 0.0) {
sigma.setPoniRot1Rad(input.uncertainty.sigma_rot1_rad);
sigma.setPoniRot2Rad(input.uncertainty.sigma_rot2_rad);
sigma.setCorrelationBeamXRot1(input.uncertainty.corr_beam_x_rot1);
sigma.setCorrelationBeamYRot2(input.uncertainty.corr_beam_y_rot2);
}
quality.setFitSigma(sigma);
}
if (input.spots_geometry) {
org::openapitools::server::model::Powder_calibration_spot_check cross;
cross.setBeamXPxl(input.spots_geometry->GetBeamX_pxl());
cross.setBeamYPxl(input.spots_geometry->GetBeamY_pxl());
cross.setDetectorDistanceMm(input.spots_geometry->GetDetectorDistance_mm());
cross.setDisagreementPxl(input.spots_disagreement_pxl);
quality.setSpotCrossCheck(cross);
}
ret.setCalibration(quality);
ret.setJfjochVersion(jfjoch_version());
return ret;
}
org::openapitools::server::model::Grid_scan_crystal Convert(const GridScanCrystal &input) {
org::openapitools::server::model::Grid_scan_crystal ret;
ret.setNx(input.nx);
ret.setNy(input.ny);
ret.setXUm(input.x_um);
ret.setYUm(input.y_um);
ret.setImageNumber(input.image_number);
ret.setMajorUm(input.major_um);
ret.setMinorUm(input.minor_um);
ret.setAngleDeg(input.angle_deg);
ret.setScore(input.score);
ret.setIceScore(input.ice_score);
ret.setResA(input.res_A);
ret.setNImages(input.n_images);
return ret;
}
org::openapitools::server::model::Scan_result Convert(const ScanResult& input) {
org::openapitools::server::model::Scan_result ret;
ret.setFilePrefix(input.file_prefix);
std::vector<org::openapitools::server::model::Scan_result_images_inner> v;
for (const auto &i : input.images) {
org::openapitools::server::model::Scan_result_images_inner tmp;
tmp.setEfficiency(i.collection_efficiency);
tmp.setNumber(i.number);
if (i.x.has_value())
tmp.setNx(i.x.value());
if (i.y.has_value())
tmp.setNy(i.y.value());
if (i.bkg.has_value())
tmp.setBkg(i.bkg.value());
if (i.spindle_blind.has_value())
tmp.setSpindleBlind(i.spindle_blind.value());
if (i.angle_deg.has_value())
tmp.setAngle(i.angle_deg.value());
if (i.pixel_sum.has_value())
tmp.setPixelSum(i.pixel_sum.value());
if (i.max_viable_pixel.has_value())
tmp.setMax(i.max_viable_pixel.value());
if (i.sat_pixels.has_value())
tmp.setSat(i.sat_pixels.value());
if (i.spot_count.has_value())
tmp.setSpots(i.spot_count.value());
if (i.spot_count_ice.has_value())
tmp.setSpotsIce(i.spot_count_ice.value());
if (i.ice_ring_score.has_value())
tmp.setIce(i.ice_ring_score.value());
if (i.spot_count_low_res.has_value())
tmp.setSpotsLowRes(i.spot_count_low_res.value());
if (i.spot_count_indexed.has_value())
tmp.setSpotsIndexed(i.spot_count_indexed.value());
if (i.indexing_solution.has_value())
tmp.setIndex(i.indexing_solution.value());
if (i.profile_radius.has_value())
tmp.setPr(i.profile_radius.value());
if (i.b_factor.has_value())
tmp.setB(i.b_factor.value());
if (i.uc.has_value()) {
org::openapitools::server::model::Unit_cell uc;
uc.setA(i.uc->a);
uc.setB(i.uc->b);
uc.setC(i.uc->c);
uc.setAlpha(i.uc->alpha);
uc.setBeta(i.uc->beta);
uc.setGamma(i.uc->gamma);
tmp.setUc(uc);
}
if (i.indexed_lattice_count.has_value())
tmp.setLattCount(i.indexed_lattice_count.value());
if (i.xfel_pulse_id.has_value())
tmp.setXfelPulseid(i.xfel_pulse_id.value());
if (i.res.has_value())
tmp.setRes(i.res.value());
v.emplace_back(std::move(tmp));
}
ret.setImages(v);
if (input.rotation_lattice) {
ret.setRotationCrystalLattice(input.rotation_lattice->GetVector());
org::openapitools::server::model::Unit_cell uc;
auto i_uc = input.rotation_lattice->GetUnitCell();
uc.setA(i_uc.a);
uc.setB(i_uc.b);
uc.setC(i_uc.c);
uc.setAlpha(i_uc.alpha);
uc.setBeta(i_uc.beta);
uc.setGamma(i_uc.gamma);
ret.setRotationUnitCell(uc);
}
if (input.rotation_crystal_system && input.rotation_centering)
ret.setRotationBravais(BravaisSymbol(*input.rotation_crystal_system, *input.rotation_centering));
// The two mode-specific payloads. Optional and independent, exactly as the rotation_* members
// above are: present when that mode ran, absent otherwise.
if (input.grid) {
org::openapitools::server::model::Grid_scan_result grid;
std::vector<org::openapitools::server::model::Grid_scan_crystal> crystals;
for (const auto &c : input.grid->crystals)
crystals.emplace_back(Convert(c));
grid.setCrystals(crystals);
grid.setBeamSizeXUm(input.grid->beam_size_x_um);
grid.setBeamSizeYUm(input.grid->beam_size_y_um);
ret.setGrid(grid);
}
if (input.calibration)
ret.setCalibration(Convert(input.calibration.value()));
return ret;
}
org::openapitools::server::model::Dark_mask_settings Convert(const DarkMaskSettings &input) {
org::openapitools::server::model::Dark_mask_settings ret{};
ret.setDetectorThresholdKeV(input.GetThreshold_keV());
ret.setFrameTimeUs(std::chrono::round<std::chrono::microseconds>(
std::chrono::duration<float>(input.GetFrameTime())
).count());
ret.setMaxFramesWithSignal(input.GetMaxFramesWithCounts());
ret.setMaxAllowedPixelCount(input.GetMaxCounts());
ret.setNumberOfFrames(input.GetNumberOfFrames());
return ret;
}
DarkMaskSettings Convert(const org::openapitools::server::model::Dark_mask_settings &input) {
DarkMaskSettings ret{};
ret.FrameTime(std::chrono::microseconds(input.getFrameTimeUs()))
.NumberOfFrames(input.getNumberOfFrames())
.MaxCounts(input.getMaxAllowedPixelCount())
.MaxFramesWithCounts(input.getMaxFramesWithSignal())
.Threshold_keV(input.getDetectorThresholdKeV());
return ret;
}
org::openapitools::server::model::Image_pusher_status Convert(const ImagePusherStatus& input) {
org::openapitools::server::model::Image_pusher_status ret;
ret.setAddr(input.address);
ret.setConnectedWriters(input.connected_writers);
org::openapitools::server::model::Image_pusher_type tmp;
switch (input.pusher_type) {
case ImagePusherType::HDF5:
tmp.setValue(org::openapitools::server::model::Image_pusher_type::eImage_pusher_type::HDF5);
break;
case ImagePusherType::CBOR:
tmp.setValue(org::openapitools::server::model::Image_pusher_type::eImage_pusher_type::CBOR);
break;
case ImagePusherType::TCP:
tmp.setValue(org::openapitools::server::model::Image_pusher_type::eImage_pusher_type::TCP);
break;
case ImagePusherType::ZMQ:
tmp.setValue(org::openapitools::server::model::Image_pusher_type::eImage_pusher_type::ZEROMQ);
break;
default:
tmp.setValue(org::openapitools::server::model::Image_pusher_type::eImage_pusher_type::NONE);
break;
}
ret.setPusherType(tmp);
if (input.images_written)
ret.setImagesWritten(input.images_written.value());
if (input.images_write_error)
ret.setImagesWriteError(input.images_write_error.value());
ret.setWriterFifoUtilization(input.writer_fifo_utilization);
return ret;
}