158 lines
6.0 KiB
C++
158 lines
6.0 KiB
C++
// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include "JFJochHttpReader.h"
|
|
|
|
#include <httplib/httplib.h>
|
|
#include <nlohmann/json.hpp>
|
|
#include "../frame_serialize/CBORStream2Deserializer.h"
|
|
#include "../broker/gen/model/Image_buffer_status.h"
|
|
#include "../broker/gen/model/Plots.h"
|
|
|
|
void JFJochHttpReader::Close() {
|
|
addr = "";
|
|
SetStartMessage({});
|
|
}
|
|
|
|
uint64_t JFJochHttpReader::GetNumberOfImages() const {
|
|
if (addr.empty())
|
|
return 0;
|
|
|
|
httplib::Client cli_cmd(addr);
|
|
|
|
auto res = cli_cmd.Get("/image_buffer/status");
|
|
if (!res || res->status != httplib::StatusCode::OK_200)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Could not get image buffer status");
|
|
|
|
try {
|
|
org::openapitools::server::model::Image_buffer_status status = nlohmann::json::parse(res->body);
|
|
return status.getMaxImageNumber() + 1;
|
|
} catch (std::exception &e) {
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Could not parse image buffer status");
|
|
}
|
|
}
|
|
|
|
void JFJochHttpReader::UpdateDataset() {
|
|
httplib::Client cli_cmd(addr);
|
|
|
|
auto res = cli_cmd.Get("/image_buffer/start.cbor");
|
|
|
|
if (!res || res->status != httplib::StatusCode::OK_200)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Could not get image buffer status");
|
|
try {
|
|
auto msg = CBORStream2Deserialize(res->body);
|
|
|
|
if (msg->msg_type != CBORImageType::START)
|
|
return;
|
|
|
|
auto dataset = std::make_shared<JFJochReaderDataset>();
|
|
|
|
// JFJochReader is always using int32_t
|
|
dataset->experiment.BitDepthImage(32);
|
|
dataset->experiment.PixelSigned(true);
|
|
dataset->experiment.FilePrefix(msg->start_message->file_prefix);
|
|
dataset->experiment.BeamX_pxl(msg->start_message->beam_center_x);
|
|
dataset->experiment.BeamY_pxl(msg->start_message->beam_center_y);
|
|
dataset->experiment.DetectorDistance_mm(msg->start_message->detector_distance * 1000.0);
|
|
dataset->az_int_bin_to_q = msg->start_message->az_int_bin_to_q;
|
|
dataset->az_int_bin_to_phi = msg->start_message->az_int_bin_to_phi;
|
|
dataset->q_bins = msg->start_message->az_int_q_bin_count.value_or(0);
|
|
dataset->azimuthal_bins = msg->start_message->az_int_phi_bin_count.value_or(0);
|
|
dataset->jfjoch_release = msg->start_message->jfjoch_release;
|
|
|
|
DetectorSetup detector = DetDECTRIS(msg->start_message->image_size_x, msg->start_message->image_size_y,
|
|
msg->start_message->detector_description, {});
|
|
detector.PixelSize_um(msg->start_message->pixel_size_x * 1e6);
|
|
detector.SaturationLimit(msg->start_message->saturation_value);
|
|
detector.MinFrameTime(std::chrono::microseconds(0));
|
|
detector.MinCountTime(std::chrono::microseconds(0));
|
|
detector.ReadOutTime(std::chrono::microseconds (0));
|
|
dataset->experiment.Detector(detector);
|
|
|
|
dataset->experiment.FrameTime(
|
|
std::chrono::microseconds(std::lround(msg->start_message->frame_time * 1e6)),
|
|
std::chrono::microseconds(std::lround(msg->start_message->count_time * 1e6))
|
|
);
|
|
|
|
if (!msg->start_message->pixel_mask.empty())
|
|
dataset->pixel_mask = PixelMask(msg->start_message->pixel_mask.begin()->second);
|
|
|
|
dataset->experiment.NumTriggers(1);
|
|
dataset->experiment.ImagesPerTrigger(msg->start_message->number_of_images);
|
|
dataset->experiment.SampleName(msg->start_message->sample_name);
|
|
dataset->experiment.SampleTemperature_K(msg->start_message->sample_temperature_K);
|
|
dataset->experiment.RingCurrent_mA(msg->start_message->ring_current_mA);
|
|
dataset->experiment.IncidentEnergy_keV(msg->start_message->incident_energy / 1000.0);
|
|
|
|
dataset->bkg_estimate = GetPlot("bkg_estimate");
|
|
dataset->spot_count = GetPlot("spot_count");
|
|
dataset->indexing_result = GetPlot("indexing_rate");
|
|
|
|
SetStartMessage(dataset);
|
|
} catch (std::exception &e) {
|
|
Close();
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Could not load dataset");
|
|
}
|
|
}
|
|
|
|
void JFJochHttpReader::ReadURL(const std::string &url) {
|
|
addr = url;
|
|
if (url.empty())
|
|
Close();
|
|
UpdateDataset();
|
|
}
|
|
|
|
std::shared_ptr<JFJochReaderImage> JFJochHttpReader::LoadImageInternal(int64_t image_number) {
|
|
if (addr.empty())
|
|
return {};
|
|
|
|
httplib::Client cli_cmd(addr);
|
|
|
|
// Always update dataset, as it might have changed from the last time
|
|
UpdateDataset();
|
|
|
|
auto res = cli_cmd.Get("/image_buffer/image.cbor?id=" + std::to_string(image_number));
|
|
|
|
if (!res || res->status != httplib::StatusCode::OK_200)
|
|
return {};
|
|
|
|
try {
|
|
auto msg = CBORStream2Deserialize(res->body);
|
|
|
|
if (msg->msg_type != CBORImageType::IMAGE)
|
|
return {};
|
|
|
|
return std::make_shared<JFJochReaderImage>(*msg->data_message, GetStartMessage());
|
|
} catch (std::exception &e) {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
std::vector<float> JFJochHttpReader::GetPlot(const std::string &plot_type, float fill_value) const {
|
|
if (addr.empty())
|
|
return {};
|
|
|
|
httplib::Client cli_cmd(addr);
|
|
auto res = cli_cmd.Get("/preview/plot?binning=1&experimental_coord=false&fill="
|
|
+ std::to_string(fill_value) + "&type=" + plot_type);
|
|
|
|
if (!res || res->status != httplib::StatusCode::OK_200)
|
|
return {};
|
|
|
|
try {
|
|
org::openapitools::server::model::Plots plots = nlohmann::json::parse(res->body);
|
|
auto plot_v = plots.getPlot();
|
|
if (plot_v.size() == 1)
|
|
return plot_v[0].getY();
|
|
else
|
|
return {};
|
|
} catch (nlohmann::json::parse_error &e) {
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Could not parse image buffer status");
|
|
}
|
|
}
|