v1.0.0_rc.11

This commit is contained in:
2024-06-30 17:48:35 +02:00
parent 53b5a304d3
commit 3035d9e144
93 changed files with 586 additions and 213 deletions

View File

@@ -251,6 +251,7 @@ synthesis:vivado_pcie_100g:
- fpga/pcie_driver/jfjoch_fpga.h
tags:
- vivado
retry: 1
artifacts:
paths:
- "jfjoch_fpga_pcie_100g.mcs"
@@ -284,6 +285,7 @@ synthesis:vivado_pcie_8x10g:
allow_failure: true
tags:
- vivado
retry: 1
artifacts:
paths:
- "jfjoch_fpga_pcie_8x10g.mcs"

View File

@@ -1 +1 @@
1.0.0_rc.10
1.0.0_rc.11

View File

@@ -475,8 +475,21 @@ void JFJochBrokerHttp::status_get(Pistache::Http::ResponseWriter &response) {
ProcessOutput(Convert(state_machine.GetStatus()), response);
}
void JFJochBrokerHttp::wait_till_done_post(Pistache::Http::ResponseWriter &response) {
auto state = state_machine.WaitTillMeasurementDone(std::chrono::seconds(5));
void JFJochBrokerHttp::wait_till_done_post(const std::optional<int32_t> &timeout,
Pistache::Http::ResponseWriter &response) {
JFJochState state;
if (!timeout)
state = state_machine.WaitTillMeasurementDone(std::chrono::minutes(1));
else if ((timeout.value() > 3600) || (timeout.value() < 0)) {
response.send(Pistache::Http::Code::Bad_Request);
return;
} else if (timeout.value() == 0)
state = state_machine.GetState();
else
state = state_machine.WaitTillMeasurementDone(std::chrono::seconds(timeout.value()));
switch (state) {
case JFJochState::Idle:
response.send(Pistache::Http::Code::Ok);

View File

@@ -90,7 +90,7 @@ class JFJochBrokerHttp : public org::openapitools::server::api::DefaultApi {
void status_get(Pistache::Http::ResponseWriter &response) override;
void wait_till_done_post(Pistache::Http::ResponseWriter &response) override;
void wait_till_done_post(const std::optional<int32_t> &timeoutMs, Pistache::Http::ResponseWriter &response) override;
void trigger_post(Pistache::Http::ResponseWriter &response) override;
void pedestal_post(Pistache::Http::ResponseWriter &response) override;

View File

@@ -2,6 +2,8 @@
#include "JFJochBrokerParser.h"
#include "../common/NetworkAddressConvert.h"
#include "../frame_serialize/ZMQStream2Pusher.h"
#include "../frame_serialize/DumpCBORToFilePusher.h"
inline bool CHECK_ARRAY(const nlohmann::json &j, const std::string& tag) {
if (j.contains(tag)) {
@@ -183,6 +185,7 @@ inline int64_t TimeToUs(const std::string &unit) {
inline std::chrono::microseconds GET_TIME(const nlohmann::json &j, const std::string& tag) {
if (j.contains(tag)) {
// If no units provided for time, this is always microsecond
if (j[tag].is_number())
return std::chrono::microseconds (std::lround(j[tag].get<double>() * 1000.0 * 1000.0));
else if (j[tag].is_string()) {
@@ -300,6 +303,35 @@ void ParseDetectorSetup(const nlohmann::json &j, const std::string& tag, JFJochB
throw JFJochException(JFJochExceptionCategory::JSON, "Detector setup not found");
}
void ParseImagePusher(const nlohmann::json &input, std::unique_ptr<ImagePusher> &image_pusher) {
std::string pusher_type = ParseString(input, "stream_type", "zmq");
if (pusher_type == "zmq") {
int32_t zmq_send_watermark = ParseInt32(input, "zmq_send_watermark", 100);
int32_t zmq_send_buffer_size = ParseInt32(input, "zmq_send_buffer_size", -1);
auto tmp = std::make_unique<ZMQStream2Pusher>(ParseStringArray(input, "zmq_image_addr"),
zmq_send_watermark,
zmq_send_buffer_size);
std::string preview_addr = ParseString(input, "zmq_preview_addr", "");
if (!preview_addr.empty())
tmp->PreviewSocket(preview_addr);
if (input.contains("zmq_preview_period"))
tmp->PreviewCounterPeriod(GET_TIME(input, "zmq_preview_period"));
std::string writer_notification_addr = ParseString(input, "zmq_writer_notification_addr", "");
if (!writer_notification_addr.empty())
tmp->WriterNotificationSocket(writer_notification_addr);
image_pusher = std::move(tmp);
} else if (pusher_type == "dump_cbor") {
image_pusher = std::make_unique<DumpCBORToFilePusher>();
} else
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"stream_type allowed: zmq (default), dump_cbor");
}
void ParseFacilityConfiguration(const nlohmann::json &input, const std::string& tag, DiffractionExperiment &experiment) {
if (CHECK_OBJECT(input, tag)) {
auto j = input[tag];
@@ -328,12 +360,11 @@ void ParseFacilityConfiguration(const nlohmann::json &input, const std::string&
experiment.PedestalG1Frames(GET_I64(j, "pedestal_g1_frames"));
if (j.contains("pedestal_g2_frames"))
experiment.PedestalG2Frames(GET_I64(j, "pedestal_g2_frames"));
if (j.contains("detector_trigger_delay_us"))
experiment.DetectorDelay(GET_TIME(j, "detector_trigger_delay_us"));
if (j.contains("detector_trigger_delay"))
experiment.DetectorDelay(GET_TIME(j, "detector_trigger_delay"));
experiment.FrameTime(GET_TIME(j, "frame_time"), GET_TIME(j, "count_time"));
experiment.FrameTime(GET_TIME(j, "frame_time_us"), GET_TIME(j, "count_time_us"));
if (j.contains("preview_period_us"))
experiment.PreviewPeriod(GET_TIME(j, "preview_period_us"));
experiment.UseInternalPacketGenerator(GET_BOOL(j, "internal_frame_generator", false));
if (experiment.IsUsingInternalPacketGen())
experiment.ConversionOnFPGA(false);

View File

@@ -14,6 +14,7 @@ DetectorGeometry ParseDetectorGeometry(const nlohmann::json &j);
DetectorSetup ParseDetectorSetup(const nlohmann::json &j);
void ParseDetectorSetup(const nlohmann::json &j, const std::string& tag, JFJochBrokerHttp& broker);
void ParseFacilityConfiguration(const nlohmann::json &j, const std::string& tag, DiffractionExperiment &experiment);
void ParseImagePusher(const nlohmann::json &j, std::unique_ptr<ImagePusher> &image_pusher);
void ParseAcquisitionDeviceGroup(const nlohmann::json &input, const std::string& tag, AcquisitionDeviceGroup &aq_devices);
std::vector<std::string> ParseStringArray(const nlohmann::json &input, const std::string& tag);

View File

@@ -340,12 +340,6 @@ void JFJochStateMachine::Start(const DatasetSettings& settings) {
}
}
void JFJochStateMachine::WaitTillMeasurementDone() {
std::unique_lock<std::mutex> ul(m);
c.wait(ul, [&] { return !IsRunning(); });
}
void JFJochStateMachine::MeasurementThread() {
try {
auto tmp_output = services.Stop();
@@ -659,6 +653,14 @@ bool JFJochStateMachine::IsRunning() const {
}
}
JFJochState JFJochStateMachine::WaitTillMeasurementDone() {
std::unique_lock<std::mutex> ul(m);
c.wait(ul, [&] { return !IsRunning(); });
return state;
}
JFJochState JFJochStateMachine::WaitTillMeasurementDone(std::chrono::milliseconds timeout) {
std::unique_lock<std::mutex> ul(m);

View File

@@ -141,7 +141,7 @@ public:
void Pedestal();
void Deactivate();
void Start(const DatasetSettings& settings);
void WaitTillMeasurementDone();
JFJochState WaitTillMeasurementDone();
JFJochState WaitTillMeasurementDone(std::chrono::milliseconds timeout);
void Trigger();

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -1275,12 +1275,22 @@ void DefaultApi::version_get_handler(const Pistache::Rest::Request &, Pistache::
}
}
void DefaultApi::wait_till_done_post_handler(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response) {
void DefaultApi::wait_till_done_post_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {
try {
// Getting the query params
auto timeoutQuery = request.query().get("timeout");
std::optional<int32_t> timeout;
if(timeoutQuery.has_value()){
int32_t valueQuery_instance;
if(fromStringValue(timeoutQuery.value(), valueQuery_instance)){
timeout = valueQuery_instance;
}
}
try {
this->wait_till_done_post(response);
this->wait_till_done_post(timeout, response);
} catch (Pistache::Http::HttpError &e) {
response.send(static_cast<Pistache::Http::Code>(e.code()), e.what());
return;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -479,9 +479,10 @@ private:
/// Wait for acquisition done
/// </summary>
/// <remarks>
/// Block execution of external script till initialization, data collection or pedestal is finished. Running this command does not affect (cancel) running data collection, it is only to ensure synchronous execution of other software. To not block web server for a long period of time, the procedure is provided with a timeout of 5 seconds.
/// Block execution of external script till initialization, data collection or pedestal is finished. Running this command does not affect (cancel) running data collection, it is only to ensure synchronous execution of other software. To not block web server for a indefinite period of time, the procedure is provided with a timeout. Extending timeout is possible, but requires to ensure safety that client will not close the connection and retry the connection.
/// </remarks>
virtual void wait_till_done_post(Pistache::Http::ResponseWriter &response) = 0;
/// <param name="timeout">Timeout in seconds (0 &#x3D;&#x3D; immediate response) (optional, default to 60)</param>
virtual void wait_till_done_post(const std::optional<int32_t> &timeout, Pistache::Http::ResponseWriter &response) = 0;
/// <summary>
/// Return XFEL event codes for the current data acquisition
/// </summary>

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -38,6 +38,7 @@ Dataset_settings::Dataset_settings()
m_Space_group_number = 0L;
m_Space_group_numberIsSet = false;
m_Sample_name = "";
m_Sample_nameIsSet = false;
m_Fpga_output = "auto";
m_Fpga_outputIsSet = false;
m_Compression = "bslz4";
@@ -295,8 +296,8 @@ bool Dataset_settings::operator==(const Dataset_settings& rhs) const
((!spaceGroupNumberIsSet() && !rhs.spaceGroupNumberIsSet()) || (spaceGroupNumberIsSet() && rhs.spaceGroupNumberIsSet() && getSpaceGroupNumber() == rhs.getSpaceGroupNumber())) &&
(getSampleName() == rhs.getSampleName())
&&
((!sampleNameIsSet() && !rhs.sampleNameIsSet()) || (sampleNameIsSet() && rhs.sampleNameIsSet() && getSampleName() == rhs.getSampleName())) &&
((!fpgaOutputIsSet() && !rhs.fpgaOutputIsSet()) || (fpgaOutputIsSet() && rhs.fpgaOutputIsSet() && getFpgaOutput() == rhs.getFpgaOutput())) &&
@@ -364,7 +365,8 @@ void to_json(nlohmann::json& j, const Dataset_settings& o)
j["images_per_file"] = o.m_Images_per_file;
if(o.spaceGroupNumberIsSet())
j["space_group_number"] = o.m_Space_group_number;
j["sample_name"] = o.m_Sample_name;
if(o.sampleNameIsSet())
j["sample_name"] = o.m_Sample_name;
if(o.fpgaOutputIsSet())
j["fpga_output"] = o.m_Fpga_output;
if(o.compressionIsSet())
@@ -430,7 +432,11 @@ void from_json(const nlohmann::json& j, Dataset_settings& o)
j.at("space_group_number").get_to(o.m_Space_group_number);
o.m_Space_group_numberIsSet = true;
}
j.at("sample_name").get_to(o.m_Sample_name);
if(j.find("sample_name") != j.end())
{
j.at("sample_name").get_to(o.m_Sample_name);
o.m_Sample_nameIsSet = true;
}
if(j.find("fpga_output") != j.end())
{
j.at("fpga_output").get_to(o.m_Fpga_output);
@@ -640,6 +646,15 @@ std::string Dataset_settings::getSampleName() const
void Dataset_settings::setSampleName(std::string const& value)
{
m_Sample_name = value;
m_Sample_nameIsSet = true;
}
bool Dataset_settings::sampleNameIsSet() const
{
return m_Sample_nameIsSet;
}
void Dataset_settings::unsetSample_name()
{
m_Sample_nameIsSet = false;
}
std::string Dataset_settings::getFpgaOutput() const
{

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -76,7 +76,7 @@ public:
bool ntriggerIsSet() const;
void unsetNtrigger();
/// <summary>
/// Image time. If not provided (or zero value) the frame time is assumed as default. For JUNGFRAU, image time must be multiple of frame time, up to 256 * frame_time. In XFEL mode: summation happens for frames collected with multiple triggers. Ignored for storage cells and if raw data are saved.
/// Image time. If not provided (or zero value) the frame time is assumed as default. Image time must be multiple of frame time; max value is 256 * frame_time. In XFEL mode: summation happens for frames collected with multiple triggers. Ignored for storage cells and if raw data are saved.
/// </summary>
int64_t getImageTimeUs() const;
void setImageTimeUs(int64_t const value);
@@ -128,6 +128,8 @@ public:
/// </summary>
std::string getSampleName() const;
void setSampleName(std::string const& value);
bool sampleNameIsSet() const;
void unsetSample_name();
/// <summary>
/// FPGA output data type
/// </summary>
@@ -244,7 +246,7 @@ protected:
int64_t m_Space_group_number;
bool m_Space_group_numberIsSet;
std::string m_Sample_name;
bool m_Sample_nameIsSet;
std::string m_Fpga_output;
bool m_Fpga_outputIsSet;
std::string m_Compression;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch
* Jungfraujoch Broker Web API
*
* The version of the OpenAPI document: 1.0.0_rc.10
* The version of the OpenAPI document: 1.0.0_rc.11
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@ openapi: 3.0.3
info:
title: Jungfraujoch
description: Jungfraujoch Broker Web API
version: 1.0.0_rc.10
version: 1.0.0_rc.11
contact:
email: filip.leonarski@psi.ch
components:
@@ -45,7 +45,6 @@ components:
- beam_y_pxl
- detector_distance_mm
- incident_energy_keV
- sample_name
properties:
images_per_trigger:
type: integer
@@ -117,6 +116,7 @@ components:
maximum: 194
sample_name:
type: string
default: ""
description: |
/entry/sample/name in NXmx
Sample name
@@ -853,22 +853,37 @@ paths:
/wait_till_done:
post:
summary: Wait for acquisition done
parameters:
- in: query
name: timeout
required: false
schema:
type: integer
default: 60
minimum: 0
maximum: 3600
description: Timeout in seconds (0 == immediate response)
description: |
Block execution of external script till initialization, data collection or pedestal is finished.
Running this command does not affect (cancel) running data collection, it is only to ensure synchronous execution of other software.
To not block web server for a long period of time, the procedure is provided with a timeout of 5 seconds.
To not block web server for a indefinite period of time, the procedure is provided with a timeout.
Extending timeout is possible, but requires to ensure safety that client will not close the connection and retry the connection.
responses:
"200":
description: Detector in `Idle` state, another data collection can start immediately
"400":
description: Timeout parameter out of bounds
"500":
description: Error within Jungfraujoch code - see output message.
content:
application/json:
schema:
$ref: '#/components/schemas/error_message'
"502":
description: Detector is inactive mode
"504":
description: 5 second timeout reached, need to restart operation
description: Timeout reached, need to restart operation
/trigger:
post:

View File

@@ -12,8 +12,6 @@
#include "JFJochBrokerHttp.h"
#include "JFJochBrokerParser.h"
#include "../frame_serialize/ZMQStream2Pusher.h"
#include "../frame_serialize/DumpCBORToFilePusher.h"
static Pistache::Http::Endpoint *httpEndpoint;
@@ -81,25 +79,7 @@ int main (int argc, char **argv) {
if (aq_devices.size() > 0) {
experiment.DataStreams(aq_devices.size());
std::string pusher_type = ParseString(input, "stream_type", "zmq");
if (pusher_type == "zmq") {
int32_t zmq_send_watermark = ParseInt32(input, "zmq_send_watermark", 100);
int32_t zmq_send_buffer_size = ParseInt32(input, "zmq_send_buffer_size", -1);
auto tmp = std::make_unique<ZMQStream2Pusher>(ParseStringArray(input, "zmq_image_addr"),
zmq_send_watermark,
zmq_send_buffer_size);
std::string preview_addr = ParseString(input, "zmq_preview_addr", "");
if (!preview_addr.empty())
tmp->PreviewSocket(preview_addr);
image_pusher = std::move(tmp);
} else if (pusher_type == "dump_cbor") {
image_pusher = std::make_unique<DumpCBORToFilePusher>();
} else
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"stream_type allowed: zmq (default), dump_cbor");
ParseImagePusher(input, image_pusher);
int32_t send_buffer_size_MiB = ParseInt32(input, "send_buffer_size_MiB", 2048);
receiver = std::make_unique<JFJochReceiverService>(aq_devices, logger, *image_pusher, send_buffer_size_MiB);

File diff suppressed because one or more lines are too long

View File

@@ -100,6 +100,8 @@ class DiffractionExperiment {
int64_t max_spot_count;
int64_t summation;
std::string detector_update_zmq_addr;
public:
// Public methods are atomic
DiffractionExperiment();

View File

@@ -65,14 +65,14 @@ void DetectorWrapper::Initialize(const DiffractionExperiment& experiment,
det.setSourceUDPIP(sls::IpAddr(cfg.ipv4_src_addr_1), {i});
det.setSourceUDPMAC(sls::MacAddr(BASE_DETECTOR_MAC + i * 2), {i});
det.setDestinationUDPPort(cfg.udp_dest_port_1, i);
det.setDestinationUDPPort(cfg.udp_dest_port_1 + 2 * i, i);
det.setDestinationUDPIP(sls::IpAddr(cfg.ipv4_dest_addr_1), {i});
det.setDestinationUDPMAC(sls::MacAddr(cfg.mac_addr_dest_1), {i});
if (experiment.GetUDPInterfaceCount() == 2) {
det.setSourceUDPIP2(sls::IpAddr(cfg.ipv4_src_addr_2), {i});
det.setSourceUDPMAC2(sls::MacAddr(BASE_DETECTOR_MAC + i * 2 + 1), {i});
det.setDestinationUDPPort2(cfg.udp_dest_port_2, i);
det.setDestinationUDPPort2(cfg.udp_dest_port_2 + 2 * i + 1, i);
det.setDestinationUDPIP2(sls::IpAddr(cfg.ipv4_dest_addr_2), {i});
det.setDestinationUDPMAC2(sls::MacAddr(cfg.mac_addr_dest_2), {i});
}
@@ -100,8 +100,8 @@ void DetectorWrapper::Initialize(const DiffractionExperiment& experiment,
auto &cfg = mod_cfg[i];
det.setDestinationUDPPort(cfg.udp_dest_port_1, 2 * i);
det.setDestinationUDPPort2(cfg.udp_dest_port_1, 2 * i + 1);
det.setDestinationUDPPort(cfg.udp_dest_port_1 + 2 * i, 2 * i);
det.setDestinationUDPPort2(cfg.udp_dest_port_1 + 2 * i + 1, 2 * i + 1);
det.setSourceUDPIP(sls::IpAddr(cfg.ipv4_src_addr_1), {2 * i, 2 * i + 1});
det.setDestinationUDPIP(sls::IpAddr(cfg.ipv4_dest_addr_1), {2 * i, 2 * i + 1});
det.setDestinationUDPMAC(sls::MacAddr(cfg.mac_addr_dest_1), {2 * i, 2 * i + 1});

View File

@@ -8,13 +8,13 @@
"pedestal_g0_frames": 2000,
"pedestal_g1_frames": 300,
"pedestal_g2_frames": 300,
"frame_time_us": "500 us",
"count_time_us": "480 us",
"preview_period_us": "1 s",
"frame_time": "500 us",
"count_time": "480 us",
"detector_ipv4": "10.10.85.0"
},
"frontend_directory":"/home/jungfrau/nextgendcu/frontend/build",
"numa_policy": "n2g2",
"zmq_preview_period": "1 s",
"zmq_image_addr": ["tcp://0.0.0.0:5500", "tcp://0.0.0.0:5501", "tcp://0.0.0.0:5502", "tcp://0.0.0.0:5503"],
"receiver_threads": 64,
"receiver": {

View File

@@ -8,15 +8,16 @@
"pedestal_g0_frames": 2000,
"pedestal_g1_frames": 300,
"pedestal_g2_frames": 300,
"frame_time_us": "10 ms",
"count_time_us": "10 us",
"preview_period_us": "1 s",
"frame_time": "10 ms",
"count_time": "10 us",
"detector_ipv4": "10.3.30.155",
"pulsed_source": true
},
"frontend_directory":"/home/jungfrau/nextgendcu/frontend/build",
"numa_policy": "n2g4",
"zmq_image_addr": ["tcp://0.0.0.0:5500"],
"zmq_preview_period": "1 s",
"receiver_threads": 64,
"receiver": {
"type": "pcie",

View File

@@ -8,9 +8,8 @@
"pedestal_g0_frames": 0,
"pedestal_g1_frames": 0,
"pedestal_g2_frames": 0,
"frame_time_us": "1000 us",
"count_time_us": "980 us",
"preview_period_us": "1 s",
"frame_time": "1000 us",
"count_time": "980 us",
"detector_ipv4": "10.10.85.20",
"internal_frame_generator": true
},
@@ -20,6 +19,9 @@
},
"frontend_directory": "../../frontend_ui/build/",
"zmq_image_addr": ["tcp://0.0.0.0:5500"],
"zmq_preview_addr": "tcp://0.0.0.0:5501",
"zmq_preview_period": "1 s",
"zmq_writer_notification_addr": "ipc://*",
"detectors": [
{
"standard_geometry": {

View File

@@ -659,7 +659,10 @@ namespace {
message.experiment_group = j["experiment_group"];
if (j.contains("jfjoch_release"))
message.jfjoch_release = j["jfjoch_release"];
if (j.contains("socket_number"))
message.socket_number = j["socket_number"];
if (j.contains("writer_notification_zmq_addr"))
message.writer_notification_zmq_addr = j["writer_notification_zmq_addr"];
} catch (const std::exception &e) {
throw JFJochException(JFJochExceptionCategory::CBORError,
"Cannot parse user_data as valid JSON " + std::string(e.what()));

View File

@@ -321,9 +321,13 @@ inline void CBOR_ENC_START_USER_DATA(CborEncoder& encoder, const char* key,
j["write_master_file"] = message.write_master_file.value();
if (message.data_reduction_factor_serialmx)
j["data_reduction_factor_serialmx"] = message.data_reduction_factor_serialmx.value();
if (message.experiment_group)
j["experiment_group"] = message.experiment_group.value();
j["experiment_group"] = message.experiment_group;
j["jfjoch_release"] = message.jfjoch_release;
if (message.socket_number)
j["socket_number"] = message.socket_number.value();
j["writer_notification_zmq_addr"] = message.writer_notification_zmq_addr;
auto str = j.dump();
CBOR_ENC(encoder, key, str);

View File

@@ -21,6 +21,7 @@ ADD_LIBRARY(ImagePusher STATIC
ImagePusher.cpp ImagePusher.h
TestImagePusher.cpp TestImagePusher.h
ZMQStream2Pusher.cpp ZMQStream2Pusher.h
ZMQWriterNotificationPuller.cpp ZMQWriterNotificationPuller.h
DumpCBORToFilePusher.cpp
DumpCBORToFilePusher.h)

View File

@@ -15,3 +15,9 @@ void PrepareCBORImage(DataMessage& message,
message.image.algorithm = experiment.GetCompressionAlgorithm();
message.image.channel = "default";
}
void ImagePusher::Finalize() {}
std::string ImagePusher::GetWriterNotificationSocketAddress() const {
return "socket1234";
}

View File

@@ -11,6 +11,7 @@
#include "CBORStream2Serializer.h"
#include "JFJochMessages.h"
#include "../common/ZeroCopyReturnValue.h"
#include "../common/Logger.h"
void PrepareCBORImage(DataMessage& message,
const DiffractionExperiment &experiment,
@@ -24,6 +25,9 @@ public:
virtual void SendImage(const uint8_t *image_data, size_t image_size, int64_t image_number,
ZeroCopyReturnValue *z) = 0;
virtual bool SendCalibration(const CompressedImage& message) = 0;
virtual void Finalize(); // Ensure that all streams are closed, can throw exception
virtual std::string GetWriterNotificationSocketAddress() const;
virtual ~ImagePusher() = default;
};

View File

@@ -142,6 +142,7 @@ struct StartMessage {
std::string detector_serial_number;
std::string run_name;
uint64_t run_number;
std::vector<std::string> gain_file_names;
std::vector<std::string> roi_names;
@@ -175,9 +176,12 @@ struct StartMessage {
nlohmann::json user_data;
std::optional<float> data_reduction_factor_serialmx;
std::optional<std::string> experiment_group;
std::string experiment_group;
std::string jfjoch_release;
std::optional<uint64_t> socket_number; // This is number of socket in ZeroMQ
std::string writer_notification_zmq_addr; // Socket to inform detector on writer done
};
struct EndMessage {

View File

@@ -13,58 +13,60 @@ There are minor differences at the moment:
## Start message
| Field name | Type | Description | Present in DECTRIS format |
|---------------------------|-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------|:-------------------------:|
| type | String | value "start" | X |
| magic_number | uint64 | Number used to describe version of the Jungfraujoch data interface - to allow to detect inconsistency between sender and receiver | |
| detector_distance | float | Detector distance \[m\] | |
| detector_translation | float | Detector translation vector \[m\] | X |
| beam_center_x | float | Beam center in X direction \[pixels\] | X |
| beam_center_y | float | Beam center in Y direction \[pixels\] | X |
| number_of_images | uint64 | Number of images in the series | X |
| image_size_x | uint64 | Image width \[pixels\] | X |
| image_size_y | uint64 | Image height \[pixels\] | X |
| incident_energy | float | X-ray energy \[eV\] | X |
| incident_wavelength | float | X-ray wavelength \[Angstrom\] | X |
| frame_time | float | Frame time, if multiple frames per trigger \[s\] | X |
| count_time | float | Exposure time \[s\] | X |
| saturation_value | int64 | Maximum valid sample value | X |
| error_value | int64 | Value used in images to describe pixels that are in error state or missing | |
| pixel_size_x | float | Pixel width \[m\] | X |
| pixel_size_y | float | Pixel height \[m\] | X |
| sensor_thickness | float | Sensor thickness \[m\] | X |
| sensor_material | string | Sensor material | X |
| arm_data | data | Approximate date of arming | X |
| pixel_mask_enabled | bool | Pixel mask applied on images | X |
| detector_description | string | Name of the detector | X |
| series_unique_id | string | Unique text ID of the series (run_name parameter) | X |
| series_id | uint64 | Unique numeric ID of the series (run_number parameter) | X |
| goniometer | Map | See [DECTRIS documentation](https://github.com/dectris/documentation/tree/main/stream_v2) - only one axis is supported | X |
| pixel_mask | Map(string -> Image) | Pixel mask - multiple in case of storage cells | X |
| channels | Array(string) | List of image channels | X |
| max_spot_count | uint64 | Maximum number of spots identified in spot finding | |
| storage_cell_number | uint64 | Number of storage cells used by JUNGFRAU | |
| image_dtype | string | Pixel bit type (e.g. uint16) | X |
| unit_cell | Array(6 * float) (optional) | Unit cell of the system: a, b, c \[angstrom\] and alpha, beta, gamma \[degree\] | |
| az_int_bin_number | uint64 | Number of azimuthal integration bins | |
| az_int_bin_to_q | Array(float) | Q value for each azimuthal integration bin \[angstrom^-1\] | |
| summation | uint64 | Factor of frame summation | |
| user_data | string | JSON serialized to string that can contain the following fields: | X |
| - user | any valid JSON | Value of header_appendix provided at collection start to Jungfraujoch | |
| - source_name | string | Facility name | |
| - source_name_short | string | Facility name (short) | |
| - source_type | string (optional) | Type of X-ray source (use NXsource/type values, for example "Synchrotron X-ray Source" or "Free-Electron Laser") | |
| - instrument_name | string | Instrument name | |
| - instrument_name_short | string | Instrument name (short) | |
| - attenuator_transmission | float (optional) | Attenuator transmission \[\] | |
| - total_flux | float (optional) | Total flux \[ph/s\] | |
| - data_file_count | uint64 | Number of used data files | |
| - file_prefix | string | File prefix | |
| - sample_name | string | Name of the sample | |
| - rotation_axis | Array(float) | Rotation axis vector (array of size 3) | |
| - space_group_number | uint64 | Space group number | |
| - write_master_file | bool | With multiple sockets, it selects which socket will provide master file | |
| - experiment_group | string | ID of instrument user, e.g., p-group (SLS/SwissFEL) or proposal number | |
| Field name | Type | Description | Present in DECTRIS format |
|--------------------------------|-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------|:-------------------------:|
| type | String | value "start" | X |
| magic_number | uint64 | Number used to describe version of the Jungfraujoch data interface - to allow to detect inconsistency between sender and receiver | |
| detector_distance | float | Detector distance \[m\] | |
| detector_translation | float | Detector translation vector \[m\] | X |
| beam_center_x | float | Beam center in X direction \[pixels\] | X |
| beam_center_y | float | Beam center in Y direction \[pixels\] | X |
| number_of_images | uint64 | Number of images in the series | X |
| image_size_x | uint64 | Image width \[pixels\] | X |
| image_size_y | uint64 | Image height \[pixels\] | X |
| incident_energy | float | X-ray energy \[eV\] | X |
| incident_wavelength | float | X-ray wavelength \[Angstrom\] | X |
| frame_time | float | Frame time, if multiple frames per trigger \[s\] | X |
| count_time | float | Exposure time \[s\] | X |
| saturation_value | int64 | Maximum valid sample value | X |
| error_value | int64 | Value used in images to describe pixels that are in error state or missing | |
| pixel_size_x | float | Pixel width \[m\] | X |
| pixel_size_y | float | Pixel height \[m\] | X |
| sensor_thickness | float | Sensor thickness \[m\] | X |
| sensor_material | string | Sensor material | X |
| arm_data | data | Approximate date of arming | X |
| pixel_mask_enabled | bool | Pixel mask applied on images | X |
| detector_description | string | Name of the detector | X |
| series_unique_id | string | Unique text ID of the series (run_name parameter) | X |
| series_id | uint64 | Unique numeric ID of the series (run_number parameter) | X |
| goniometer | Map | See [DECTRIS documentation](https://github.com/dectris/documentation/tree/main/stream_v2) - only one axis is supported | X |
| pixel_mask | Map(string -> Image) | Pixel mask - multiple in case of storage cells | X |
| channels | Array(string) | List of image channels | X |
| max_spot_count | uint64 | Maximum number of spots identified in spot finding | |
| storage_cell_number | uint64 | Number of storage cells used by JUNGFRAU | |
| image_dtype | string | Pixel bit type (e.g. uint16) | X |
| unit_cell | Array(6 * float) (optional) | Unit cell of the system: a, b, c \[angstrom\] and alpha, beta, gamma \[degree\] | |
| az_int_bin_number | uint64 | Number of azimuthal integration bins | |
| az_int_bin_to_q | Array(float) | Q value for each azimuthal integration bin \[angstrom^-1\] | |
| summation | uint64 | Factor of frame summation | |
| user_data | string | JSON serialized to string that can contain the following fields: | X |
| - user | any valid JSON | Value of header_appendix provided at collection start to Jungfraujoch | |
| - source_name | string | Facility name | |
| - source_name_short | string | Facility name (short) | |
| - source_type | string (optional) | Type of X-ray source (use NXsource/type values, for example "Synchrotron X-ray Source" or "Free-Electron Laser") | |
| - instrument_name | string | Instrument name | |
| - instrument_name_short | string | Instrument name (short) | |
| - attenuator_transmission | float (optional) | Attenuator transmission \[\] | |
| - total_flux | float (optional) | Total flux \[ph/s\] | |
| - data_file_count | uint64 | Number of used data files | |
| - file_prefix | string | File prefix | |
| - sample_name | string | Name of the sample | |
| - rotation_axis | Array(float) | Rotation axis vector (array of size 3) | |
| - space_group_number | uint64 | Space group number | |
| - write_master_file | bool | With multiple sockets, it selects which socket will provide master file | |
| - writer_notification_zmq_addr | string | ZeroMQ address to inform `jfjoch_broker` about writers that finished operation | |
| - socket_number | uint64 | Number of ZeroMQ socket (on `jfjoch_broker` side) used for transmission | |
| - experiment_group | string | ID of instrument user, e.g., p-group (SLS/SwissFEL) or proposal number | |
See [DECTRIS documentation](https://github.com/dectris/documentation/tree/main/stream_v2) for definition of Image as MultiDimArray with optional compression.

View File

@@ -55,17 +55,17 @@ void ZMQStream2Pusher::StartDataCollection(StartMessage& message) {
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Images per file cannot be zero or negative");
images_per_file = message.images_per_file;
run_number = message.run_number;
run_name = message.run_name;
serializer.SerializeSequenceStart(message);
for (auto &s: socket) {
if (!s->Send(serialization_buffer.data(), serializer.GetBufferSize(), true))
throw JFJochException(JFJochExceptionCategory::ZeroMQ, "Timeout on pushing start message on addr "
+ s->GetEndpointName());
if (message.write_master_file) {
for (int i = 0; i < socket.size(); i++) {
message.socket_number = i;
if (i > 0)
message.write_master_file = false;
serializer.SerializeSequenceStart(message);
}
serializer.SerializeSequenceStart(message);
if (!socket[i]->Send(serialization_buffer.data(), serializer.GetBufferSize(), true))
throw JFJochException(JFJochExceptionCategory::ZeroMQ, "Timeout on pushing start message on addr "
+ socket[i]->GetEndpointName());
}
if (preview_socket)
@@ -115,3 +115,36 @@ std::string ZMQStream2Pusher::GetPreviewAddress() {
else
return "";
}
void ZMQStream2Pusher::Finalize() {
if (writer_notification_socket) {
for (int i = 0; i < socket.size(); i++) {
auto n = writer_notification_socket->Receive(run_number, run_name);
if (!n)
throw JFJochException(JFJochExceptionCategory::FileWriteError, "No notification received from writer");
else if (n->socket_number >= socket.size())
throw JFJochException(JFJochExceptionCategory::FileWriteError, "Wrong socket number provided in the message");
else if (!n->ok)
throw JFJochException(JFJochExceptionCategory::FileWriteError, "Writer (socket "
+ socket[n->socket_number]->GetEndpointName()
+ ") finished with error");
}
}
}
std::string ZMQStream2Pusher::GetWriterNotificationSocketAddress() const {
if (writer_notification_socket)
return writer_notification_socket->GetEndpointName();
else
return "";
}
ZMQStream2Pusher &ZMQStream2Pusher::WriterNotificationSocket(const std::string &addr) {
writer_notification_socket = std::make_unique<ZMQWriterNotificationPuller>(addr);
return *this;
}
ZMQStream2Pusher &ZMQStream2Pusher::PreviewCounterPeriod(std::chrono::microseconds input) {
preview_counter.Period(input);
return *this;
}

View File

@@ -8,6 +8,7 @@
#include "ImagePusher.h"
#include "../common/ZMQWrappers.h"
#include "../preview/PreviewCounter.h"
#include "ZMQWriterNotificationPuller.h"
class ZMQStream2Pusher : public ImagePusher {
std::vector<uint8_t> serialization_buffer;
@@ -18,13 +19,19 @@ class ZMQStream2Pusher : public ImagePusher {
std::unique_ptr<ZMQSocket> preview_socket;
PreviewCounter preview_counter;
std::unique_ptr<ZMQWriterNotificationPuller> writer_notification_socket;
int64_t images_per_file = 1;
uint64_t run_number = 0;
std::string run_name;
public:
explicit ZMQStream2Pusher(const std::vector<std::string>& addr,
int32_t send_buffer_high_watermark = -1,
int32_t send_buffer_size = -1);
ZMQStream2Pusher& PreviewSocket(const std::string& addr);
ZMQStream2Pusher& WriterNotificationSocket(const std::string& addr);
ZMQStream2Pusher& PreviewCounterPeriod(std::chrono::microseconds input);
std::string GetPreviewAddress();
std::vector<std::string> GetAddress();
@@ -37,6 +44,9 @@ public:
// Thread-safe
void SendImage(const uint8_t *image_data, size_t image_size, int64_t image_number, ZeroCopyReturnValue *z) override;
bool SendImage(const uint8_t *image_data, size_t image_size, int64_t image_number) override;
void Finalize() override;
std::string GetWriterNotificationSocketAddress() const override;
};
#endif //JUNGFRAUJOCH_ZMQSTREAM2PUSHER_H

View File

@@ -0,0 +1,34 @@
// Copyright (2019-2024) Paul Scherrer Institute
#include "ZMQWriterNotificationPuller.h"
#include "nlohmann/json.hpp"
ZMQWriterNotificationPuller::ZMQWriterNotificationPuller(const std::string &addr, std::chrono::milliseconds timeout)
: socket(ZMQSocketType::Pull) {
socket.ReceiveTimeout(timeout);
socket.Bind(addr);
}
std::optional<ZMQWriterNotificationOutput> ZMQWriterNotificationPuller::Receive(uint64_t run_number, const std::string &run_name) {
ZMQMessage msg;
// Loop to ensure that messages with wrong run_number or run_name are filtered
while (socket.Receive(msg)) {
try {
nlohmann::json j = nlohmann::json::parse(std::string((char *) msg.data(), msg.size()));
if ((j["run_number"] == run_number) && (j["run_name"] == run_name)) {
ZMQWriterNotificationOutput ret{};
ret.ok = j["ok"];
ret.processed_images = j["processed_images"];
ret.socket_number = j["socket_number"];
return ret;
}
} catch (const std::exception &e) {
// Cannot parse properly
}
}
return {};
}
std::string ZMQWriterNotificationPuller::GetEndpointName() {
return socket.GetEndpointName();
}

View File

@@ -0,0 +1,28 @@
// Copyright (2019-2024) Paul Scherrer Institute
// Copyright (2019-2024) Paul Scherrer Institute
#ifndef JFJOCH_ZMQWRITERNOTIFICATIONPULLER_H
#define JFJOCH_ZMQWRITERNOTIFICATIONPULLER_H
#include <optional>
#include "../common/ZMQWrappers.h"
struct ZMQWriterNotificationOutput {
bool ok;
uint64_t socket_number;
uint64_t processed_images;
};
class ZMQWriterNotificationPuller {
ZMQSocket socket;
public:
ZMQWriterNotificationPuller(const std::string& addr, std::chrono::milliseconds timeout = std::chrono::seconds(15));
std::string GetEndpointName();
std::optional<ZMQWriterNotificationOutput> Receive(uint64_t run_number, const std::string &run_name);
};
#endif //JFJOCH_ZMQWRITERNOTIFICATIONPULLER_H

View File

@@ -18,3 +18,8 @@ bool PreviewCounter::GeneratePreview() {
} else
return false;
}
PreviewCounter &PreviewCounter::Period(std::chrono::microseconds in_period) {
period = in_period;
return *this;
}

View File

@@ -14,6 +14,7 @@ class PreviewCounter {
public:
PreviewCounter(std::chrono::microseconds period);
bool GeneratePreview();
PreviewCounter& Period(std::chrono::microseconds period);
};
#endif //JUNGFRAUJOCH_PREVIEWCOUNTER_H

View File

@@ -108,6 +108,7 @@ void JFJochReceiver::SendStartMessage(const PixelMask &pixel_mask) {
message.az_int_bin_number = az_int_mapping.GetBinNumber();
message.az_int_bin_to_q = az_int_mapping.GetBinToQ();
message.write_master_file = true;
message.writer_notification_zmq_addr = image_pusher.GetWriterNotificationSocketAddress();
std::vector<uint32_t> nexus_mask;
nexus_mask = pixel_mask.GetMask(experiment);
@@ -493,6 +494,10 @@ void JFJochReceiver::FinalizeMeasurement() {
throw JFJochException(JFJochExceptionCategory::ZeroMQ, "Send commands not finalized in 10 seconds");
}
logger.Info("Receiving data done");
image_pusher.Finalize();
logger.Info("Writing process finalized");
}
void JFJochReceiver::SetSpotFindingSettings(const SpotFindingSettings &in_spot_finding_settings) {

View File

@@ -69,7 +69,9 @@ TEST_CASE("CBORSerialize_Start", "[CBOR]") {
.user_data = R"({"pi":3.1415, "z":"string"})"_json,
.data_reduction_factor_serialmx = 0.75,
.experiment_group = "p10001",
.jfjoch_release = "1.4.98"
.jfjoch_release = "1.4.98",
.socket_number = 3,
.writer_notification_zmq_addr = "tcp://1.2.3.4:5678"
};
REQUIRE_NOTHROW(serializer.SerializeSequenceStart(message));
@@ -153,6 +155,8 @@ TEST_CASE("CBORSerialize_Start", "[CBOR]") {
CHECK(output_message.data_reduction_factor_serialmx == message.data_reduction_factor_serialmx);
CHECK(output_message.experiment_group == message.experiment_group);
CHECK(output_message.jfjoch_release == message.jfjoch_release);
CHECK(output_message.socket_number == message.socket_number);
CHECK(output_message.writer_notification_zmq_addr == message.writer_notification_zmq_addr);
}
TEST_CASE("CBORSerialize_Start_PixelMask", "[CBOR]") {

View File

@@ -182,16 +182,15 @@ TEST_CASE("JFJochBrokerParser_ParseFacilityConfiguration") {
{
"cfg": {
"source_name": "Swiss Light Source",
"source_type": "XFEL",
"source_name_short": "SLS",
"instrument_name": "X06SA VESPA",
"instrument_name_short": "VESPA",
"pedestal_g0_frames": 5000,
"pedestal_g1_frames": 333,
"pedestal_g2_frames": 333,
"frame_time_us": 0.0012,
"count_time_us": "950 us",
"spot_finding_period_us": " 2 ms",
"preview_period_us": "1 s",
"frame_time": 0.0012,
"count_time": "950 us",
"detector_ipv4": "10.10.25.0"
}
}
@@ -200,6 +199,7 @@ TEST_CASE("JFJochBrokerParser_ParseFacilityConfiguration") {
DiffractionExperiment x(DetectorGeometry(8));
ParseFacilityConfiguration(j, "cfg", x);
REQUIRE(x.GetSourceName() == "Swiss Light Source");
REQUIRE(x.GetSourceType() == "XFEL");
REQUIRE(x.GetSourceNameShort() == "SLS");
REQUIRE(x.GetInstrumentName() == "X06SA VESPA");
REQUIRE(x.GetInstrumentNameShort() == "VESPA");

View File

@@ -54,6 +54,8 @@ TEST_CASE("JFJochIntegrationTest_ZMQ_lysozyme_spot_and_index", "[JFJochReceiver]
aq_devices.Add(std::move(test));
ZMQStream2Pusher pusher({"ipc://*"});
pusher.WriterNotificationSocket("ipc://*");
StreamWriter writer(logger, pusher.GetAddress()[0]);
auto writer_future = std::async(std::launch::async, &StreamWriter::Run, &writer);

View File

@@ -6,6 +6,7 @@
#include "../writer/StreamWriter.h"
#include "../frame_serialize/ZMQStream2Pusher.h"
#include "../receiver/JFJochReceiverService.h"
#include "../frame_serialize/ZMQWriterNotificationPuller.h"
TEST_CASE("StreamWriterTest_ZMQ","[JFJochWriter]") {
RegisterHDF5Filter();
@@ -61,3 +62,59 @@ TEST_CASE("StreamWriterTest_ZMQ","[JFJochWriter]") {
REQUIRE(std::filesystem::remove("subdir/JFJochWriterTest_data_000001.h5"));
REQUIRE(std::filesystem::remove("subdir"));
}
TEST_CASE("StreamWriterTest_ZMQ_Update","[JFJochWriter]") {
RegisterHDF5Filter();
Logger logger("test");
DatasetSettings d;
d.FilePrefix("subdir/JFJochWriterTest").NumTriggers(1).ImagesPerTrigger(5).RunName("run1").RunNumber(256);
DiffractionExperiment x(DetectorGeometry(2));
x.UseInternalPacketGenerator(true).Mode(DetectorMode::Raw).PedestalG0Frames(0).ImportDatasetSettings(d);
PixelMask pixel_mask(x);
JFModuleGainCalibration gain;
AcquisitionDeviceGroup aq_devices;
for (int i = 0; i < x.GetDataStreamsNum(); i++)
aq_devices.AddHLSDevice(64);
ZMQStream2Pusher pusher ({"ipc://*"});
pusher.WriterNotificationSocket("ipc://*");
JFJochReceiverService fpga_receiver_service(aq_devices, logger, pusher);
JFJochReceiverOutput receiver_output;
std::unique_ptr<StreamWriter> writer;
REQUIRE(x.GetImageNum() == 5);
auto pusher_addr = pusher.GetAddress();
REQUIRE(pusher_addr.size() == 1);
REQUIRE_NOTHROW(writer = std::make_unique<StreamWriter>(logger, pusher_addr[0]));
CHECK (writer->GetStatistics().state == StreamWriterState::Idle);
REQUIRE_NOTHROW(fpga_receiver_service.Start(x, pixel_mask, nullptr));
REQUIRE_NOTHROW(writer->Run());
REQUIRE_NOTHROW(receiver_output = fpga_receiver_service.Stop());
CHECK(receiver_output.status.images_sent == 5);
CHECK(writer->GetStatistics().state == StreamWriterState::Idle);
CHECK(writer->GetStatistics().processed_images == 5);
CHECK(writer->GetStatistics().file_prefix == x.GetFilePrefix());
// HDF5 file can be opened
std::unique_ptr<HDF5ReadOnlyFile> file;
REQUIRE_NOTHROW(file = std::make_unique<HDF5ReadOnlyFile>("subdir/JFJochWriterTest_data_000001.h5"));
std::unique_ptr<HDF5DataSet> dataset;
REQUIRE_NOTHROW(dataset = std::make_unique<HDF5DataSet>(*file, "/entry/data/data"));
std::unique_ptr<HDF5DataSpace> dataspace;
REQUIRE_NOTHROW(dataspace = std::make_unique<HDF5DataSpace>(*dataset));
REQUIRE(dataspace->GetNumOfDimensions() == 3);
REQUIRE(dataspace->GetDimensions()[0] == 5);
REQUIRE(dataspace->GetDimensions()[1] == RAW_MODULE_COLS);
REQUIRE(dataspace->GetDimensions()[2] == 2*RAW_MODULE_LINES);
REQUIRE(std::filesystem::remove("subdir/JFJochWriterTest_master.h5"));
REQUIRE(std::filesystem::remove("subdir/JFJochWriterTest_data_000001.h5"));
REQUIRE(std::filesystem::remove("subdir"));
}

View File

@@ -228,7 +228,8 @@ void NXmx::Metrology(const StartMessage &start) {
void NXmx::Sample(const StartMessage &start, const EndMessage &end) {
HDF5Group group(*hdf5_file, "/entry/sample");
group.NXClass("NXsample");
group.SaveScalar("name", start.sample_name);
if (!start.sample_name.empty())
group.SaveScalar("name", start.sample_name);
if (start.space_group_number > 0)
group.SaveScalar("space_group", start.space_group_number);

View File

@@ -68,8 +68,8 @@ void HDF5Writer::AddStats(const std::optional<HDF5DataFileStatistics>& s) {
j["run_number"] = start_message.run_number;
j["run_name"] = start_message.run_name;
if (start_message.experiment_group)
j["experiment_group"] = start_message.experiment_group.value();
if (!start_message.experiment_group.empty())
j["experiment_group"] = start_message.experiment_group;
if (start_message.unit_cell) {
j["unit_cell"]["a"] = start_message.unit_cell->a;

View File

@@ -13,7 +13,7 @@ void JFJochWriterHttp::status_get(Pistache::Http::ResponseWriter &response) {
resp_struct.setFilePrefix(stat.file_prefix);
resp_struct.setRunName(stat.run_name);
resp_struct.setRunNumber(stat.run_number);
resp_struct.setSocketNumber(stat.socket_number);
switch (stat.state) {
case StreamWriterState::Idle:
resp_struct.setState("idle");
@@ -24,6 +24,9 @@ void JFJochWriterHttp::status_get(Pistache::Http::ResponseWriter &response) {
case StreamWriterState::Receiving:
resp_struct.setState("receiving");
break;
case StreamWriterState::Error:
resp_struct.setState("error");
break;
}
nlohmann::json j = resp_struct;

View File

@@ -12,7 +12,9 @@ StreamWriter::StreamWriter(Logger &in_logger,
const std::string &in_file_done_address)
: image_puller(repub_address),
logger(in_logger),
file_done_address(in_file_done_address) {
file_done_address(in_file_done_address),
socket_number(0),
run_number(0) {
image_puller.Connect(zmq_addr);
logger.Info("Connected via ZMQ to {}", zmq_addr);
}
@@ -53,6 +55,12 @@ void StreamWriter::CollectImages(std::vector<HDF5DataFileStatistics> &v) {
if (!image_puller_output.cbor->start_message->write_master_file || image_puller_output.cbor->start_message->write_master_file.value())
master_file = std::make_unique<NXmx>(*image_puller_output.cbor->start_message);
socket_number = 0;
if (image_puller_output.cbor->start_message->socket_number)
socket_number = image_puller_output.cbor->start_message->socket_number.value();
std::string detector_update_zmq_addr = image_puller_output.cbor->start_message->writer_notification_zmq_addr;
bool first_image = true;
run = WaitForImage();
while (run && image_puller_output.cbor->calibration) {
@@ -77,6 +85,8 @@ void StreamWriter::CollectImages(std::vector<HDF5DataFileStatistics> &v) {
run = WaitForImage();
}
bool clean_end = false;
if (run && image_puller_output.cbor->end_message) {
end_time = std::chrono::system_clock::now();
@@ -85,11 +95,35 @@ void StreamWriter::CollectImages(std::vector<HDF5DataFileStatistics> &v) {
if (master_file)
master_file->Finalize(*image_puller_output.cbor->end_message);
master_file.reset();
state = StreamWriterState::Idle;
clean_end = true;
}
master_file.reset();
v = writer.Finalize();
state = clean_end ? StreamWriterState::Idle : StreamWriterState::Error;
if (!detector_update_zmq_addr.empty()) {
nlohmann::json j;
auto stats = GetStatistics();
j["socket_number"] = socket_number;
j["ok"] = clean_end ? true : false;
j["processed_images"] = processed_images.load();
j["socket_number"] = stats.socket_number;
j["run_number"] = stats.run_number;
j["run_name"] = stats.run_name;
j["performance_MBs"] = stats.performance_MBs;
try {
ZMQSocket s(ZMQSocketType::Push);
s.SendTimeout(std::chrono::seconds(1));
s.Connect(detector_update_zmq_addr);
s.Send(j.dump());
} catch (const JFJochException &e) {
logger.ErrorException(e);
}
}
}
void StreamWriter::Cancel() {
@@ -126,7 +160,6 @@ bool StreamWriter::WaitForImage() {
StreamWriterStatistics StreamWriter::GetStatistics() const {
float perf_MBs = 0.0f, perf_Hz = 0.0f;
if ((state != StreamWriterState::Started) && (processed_images > 0)) {
int64_t time_us;
if (state == StreamWriterState::Idle)
@@ -146,6 +179,7 @@ StreamWriterStatistics StreamWriter::GetStatistics() const {
.file_prefix = file_prefix,
.run_name = run_name,
.run_number = run_number,
.socket_number = socket_number,
.state = state
};
}

View File

@@ -8,7 +8,7 @@
#include "ZMQImagePuller.h"
#include "HDF5DataFile.h"
enum class StreamWriterState {Idle, Started, Receiving};
enum class StreamWriterState {Idle, Started, Receiving, Error};
struct StreamWriterStatistics {
uint64_t processed_images;
@@ -17,6 +17,7 @@ struct StreamWriterStatistics {
std::string file_prefix;
std::string run_name;
uint64_t run_number;
uint64_t socket_number;
StreamWriterState state;
};
@@ -39,6 +40,7 @@ class StreamWriter {
std::string file_prefix;
std::string run_name;
uint64_t run_number;
uint64_t socket_number;
ZMQImagePuller image_puller;
Logger &logger;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch writer
* Jungfraujoch Writer Web API
*
* The version of the OpenAPI document: 1.0.0.rc_10
* The version of the OpenAPI document: 1.0.0.rc_11
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch writer
* Jungfraujoch Writer Web API
*
* The version of the OpenAPI document: 1.0.0.rc_10
* The version of the OpenAPI document: 1.0.0.rc_11
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch writer
* Jungfraujoch Writer Web API
*
* The version of the OpenAPI document: 1.0.0.rc_10
* The version of the OpenAPI document: 1.0.0.rc_11
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch writer
* Jungfraujoch Writer Web API
*
* The version of the OpenAPI document: 1.0.0.rc_10
* The version of the OpenAPI document: 1.0.0.rc_11
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).

View File

@@ -2,7 +2,7 @@
* Jungfraujoch writer
* Jungfraujoch Writer Web API
*
* The version of the OpenAPI document: 1.0.0.rc_10
* The version of the OpenAPI document: 1.0.0.rc_11
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -33,6 +33,8 @@ Writer_statistics::Writer_statistics()
m_Run_nameIsSet = false;
m_File_prefix = "";
m_File_prefixIsSet = false;
m_Socket_number = 0L;
m_Socket_numberIsSet = false;
m_State = "";
m_StateIsSet = false;
@@ -57,7 +59,7 @@ bool Writer_statistics::validate(std::stringstream& msg, const std::string& path
bool success = true;
const std::string _pathPrefix = pathPrefix.empty() ? "Writer_statistics" : pathPrefix;
return success;
}
@@ -85,6 +87,9 @@ bool Writer_statistics::operator==(const Writer_statistics& rhs) const
((!filePrefixIsSet() && !rhs.filePrefixIsSet()) || (filePrefixIsSet() && rhs.filePrefixIsSet() && getFilePrefix() == rhs.getFilePrefix())) &&
((!socketNumberIsSet() && !rhs.socketNumberIsSet()) || (socketNumberIsSet() && rhs.socketNumberIsSet() && getSocketNumber() == rhs.getSocketNumber())) &&
((!stateIsSet() && !rhs.stateIsSet()) || (stateIsSet() && rhs.stateIsSet() && getState() == rhs.getState()))
;
@@ -110,6 +115,8 @@ void to_json(nlohmann::json& j, const Writer_statistics& o)
j["run_name"] = o.m_Run_name;
if(o.filePrefixIsSet())
j["file_prefix"] = o.m_File_prefix;
if(o.socketNumberIsSet())
j["socket_number"] = o.m_Socket_number;
if(o.stateIsSet())
j["state"] = o.m_State;
@@ -147,6 +154,11 @@ void from_json(const nlohmann::json& j, Writer_statistics& o)
j.at("file_prefix").get_to(o.m_File_prefix);
o.m_File_prefixIsSet = true;
}
if(j.find("socket_number") != j.end())
{
j.at("socket_number").get_to(o.m_Socket_number);
o.m_Socket_numberIsSet = true;
}
if(j.find("state") != j.end())
{
j.at("state").get_to(o.m_State);
@@ -257,6 +269,23 @@ void Writer_statistics::unsetFile_prefix()
{
m_File_prefixIsSet = false;
}
int64_t Writer_statistics::getSocketNumber() const
{
return m_Socket_number;
}
void Writer_statistics::setSocketNumber(int64_t const value)
{
m_Socket_number = value;
m_Socket_numberIsSet = true;
}
bool Writer_statistics::socketNumberIsSet() const
{
return m_Socket_numberIsSet;
}
void Writer_statistics::unsetSocket_number()
{
m_Socket_numberIsSet = false;
}
std::string Writer_statistics::getState() const
{
return m_State;

View File

@@ -2,7 +2,7 @@
* Jungfraujoch writer
* Jungfraujoch Writer Web API
*
* The version of the OpenAPI document: 1.0.0.rc_10
* The version of the OpenAPI document: 1.0.0.rc_11
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -101,6 +101,13 @@ public:
bool filePrefixIsSet() const;
void unsetFile_prefix();
/// <summary>
/// Number of socket on &#x60;jfjoch_broker&#x60; side for the current/last data collection
/// </summary>
int64_t getSocketNumber() const;
void setSocketNumber(int64_t const value);
bool socketNumberIsSet() const;
void unsetSocket_number();
/// <summary>
///
/// </summary>
std::string getState() const;
@@ -123,6 +130,8 @@ protected:
bool m_Run_nameIsSet;
std::string m_File_prefix;
bool m_File_prefixIsSet;
int64_t m_Socket_number;
bool m_Socket_numberIsSet;
std::string m_State;
bool m_StateIsSet;

View File

@@ -286,11 +286,11 @@ data-styled.g137[id="sc-cMdfCE"]{content:"dvQijr,"}/*!sc*/
55.627 l 55.6165,55.627 -231.245496,231.24803 c -127.185,127.1864
-231.5279,231.248 -231.873,231.248 -0.3451,0 -104.688,
-104.0616 -231.873,-231.248 z
" fill="currentColor"></path></g></svg></div></div><div class="sc-dxfTlo cOuMek api-content"><div class="sc-eDLKkx hNzKJC"><div class="sc-iBdnpw fsPUig"><div class="sc-hLQSwg gikxZY api-info"><h1 class="sc-fsYfdN sc-eFyDpN gqLiaw ObWVe">Jungfraujoch writer<!-- --> <span>(<!-- -->1.0.0<!-- -->)</span></h1><p>Download OpenAPI specification<!-- -->:<a download="openapi.json" target="_blank" class="sc-crHHJw iGcmRf">Download</a></p><div class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS"></div><div data-role="redoc-summary" html="" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS"></div><div data-role="redoc-description" html="&lt;p&gt;Jungfraujoch Writer Web API&lt;/p&gt;
" fill="currentColor"></path></g></svg></div></div><div class="sc-dxfTlo cOuMek api-content"><div class="sc-eDLKkx hNzKJC"><div class="sc-iBdnpw fsPUig"><div class="sc-hLQSwg gikxZY api-info"><h1 class="sc-fsYfdN sc-eFyDpN gqLiaw ObWVe">Jungfraujoch writer<!-- --> <span>(<!-- -->1.0.0.rc_11<!-- -->)</span></h1><p>Download OpenAPI specification<!-- -->:<a download="openapi.json" target="_blank" class="sc-crHHJw iGcmRf">Download</a></p><div class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS"></div><div data-role="redoc-summary" html="" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS"></div><div data-role="redoc-description" html="&lt;p&gt;Jungfraujoch Writer Web API&lt;/p&gt;
" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS"><p>Jungfraujoch Writer Web API</p>
</div></div></div></div><div id="/paths/~1status/get" data-section-id="/paths/~1status/get" class="sc-eDLKkx cSNAXN"><div class="sc-iBdnpw fsPUig"><div class="sc-hLQSwg gikxZY"><h2 class="sc-qZrbh gwJLUj"><a class="sc-csKJxZ fNhImz" href="#/paths/~1status/get" aria-label="/paths/~1status/get"></a>Get writer status<!-- --> </h2><div><h3 class="sc-fYitVF duKVDl">Responses</h3><div><button class="sc-hsaIUA fIqGlH"><svg class="sc-eTNRI hUWsvg" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg><strong class="sc-gWQvRS ePkkgX">200<!-- --> </strong><div html="&lt;p&gt;Statistics of the last measurement&lt;/p&gt;
" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS sc-ckdEwu LxEPk"><p>Statistics of the last measurement</p>
</div></button></div></div></div><div class="sc-jTQCzO sc-gLLuof imiXRU jGdkPR"><div class="sc-bPrlCs cIsduN"><button class="sc-GkLId bclCVA"><span type="get" class="sc-jYnQyy eIFDdZ http-verb get">get</span><span class="sc-fYrVWQ gllLir">/status</span><svg class="sc-eTNRI exoGJA" style="margin-right:-25px" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button><div aria-hidden="true" class="sc-eGgGjL hsEiws"><div class="sc-fnpiog jerStl"><div html="" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg"></div><div tabindex="0" role="button"><div class="sc-lkDHyp etvaCd"><span></span>/status</div></div></div></div></div><div><h3 class="sc-kFCroH klfnyk"> <!-- -->Response samples<!-- --> </h3><div class="sc-cyZbeP jSWvqu" data-rttabs="true"><ul class="react-tabs__tab-list" role="tablist"><li class="tab-success react-tabs__tab--selected" role="tab" id="react-tabs-0" aria-selected="true" aria-disabled="false" aria-controls="react-tabs-1" tabindex="0" data-rttab="true">200</li></ul><div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="react-tabs-1" aria-labelledby="react-tabs-0"><div><div class="sc-cPtzlb jBjImi"><span class="sc-bCvmQg eTZsJr">Content type</span><div class="sc-dQmiwx jCmKdj">application/json</div></div><div class="sc-hVcFVo jeLSWq"><div class="sc-cSxRuM fOJBdW"><div class="sc-gjLLEI iwAAMv"><button><div class="sc-jdHILj krcPXE">Copy</div></button></div><div class="sc-iKOmoZ WVNwY sc-jMbVJB DqFKH"><div class="redoc-json"><code><button class="collapser" aria-label="collapse"></button><span class="token punctuation">{</span><span class="ellipsis"></span><ul class="obj collapsible"><li><div class="hoverable "><span class="property token string">"nimages"</span>: <span class="token number">0</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"performance_MBs"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"performance_Hz"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"file_prefix"</span>: <span class="token string">&quot;string&quot;</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"state"</span>: <span class="token string">&quot;idle&quot;</span></div></li></ul><span class="token punctuation">}</span></code></div></div></div></div></div></div></div></div></div></div></div><div id="/paths/~1cancel/post" data-section-id="/paths/~1cancel/post" class="sc-eDLKkx cSNAXN"><div class="sc-iBdnpw fsPUig"><div class="sc-hLQSwg gikxZY"><h2 class="sc-qZrbh gwJLUj"><a class="sc-csKJxZ fNhImz" href="#/paths/~1cancel/post" aria-label="/paths/~1cancel/post"></a>Cancel running data collection<!-- --> </h2><div class="sc-eYFTNc dZbpPF"><div html="&lt;p&gt;It only instructs writer to cancel, but doesn&amp;#39;t wait for cancellation actually happening.
</div></button></div></div></div><div class="sc-jTQCzO sc-gLLuof imiXRU jGdkPR"><div class="sc-bPrlCs cIsduN"><button class="sc-GkLId bclCVA"><span type="get" class="sc-jYnQyy eIFDdZ http-verb get">get</span><span class="sc-fYrVWQ gllLir">/status</span><svg class="sc-eTNRI exoGJA" style="margin-right:-25px" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button><div aria-hidden="true" class="sc-eGgGjL hsEiws"><div class="sc-fnpiog jerStl"><div html="" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg"></div><div tabindex="0" role="button"><div class="sc-lkDHyp etvaCd"><span></span>/status</div></div></div></div></div><div><h3 class="sc-kFCroH klfnyk"> <!-- -->Response samples<!-- --> </h3><div class="sc-cyZbeP jSWvqu" data-rttabs="true"><ul class="react-tabs__tab-list" role="tablist"><li class="tab-success react-tabs__tab--selected" role="tab" id="react-tabs-0" aria-selected="true" aria-disabled="false" aria-controls="react-tabs-1" tabindex="0" data-rttab="true">200</li></ul><div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="react-tabs-1" aria-labelledby="react-tabs-0"><div><div class="sc-cPtzlb jBjImi"><span class="sc-bCvmQg eTZsJr">Content type</span><div class="sc-dQmiwx jCmKdj">application/json</div></div><div class="sc-hVcFVo jeLSWq"><div class="sc-cSxRuM fOJBdW"><div class="sc-gjLLEI iwAAMv"><button><div class="sc-jdHILj krcPXE">Copy</div></button></div><div class="sc-iKOmoZ WVNwY sc-jMbVJB DqFKH"><div class="redoc-json"><code><button class="collapser" aria-label="collapse"></button><span class="token punctuation">{</span><span class="ellipsis"></span><ul class="obj collapsible"><li><div class="hoverable "><span class="property token string">"nimages"</span>: <span class="token number">0</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"performance_MBs"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"performance_Hz"</span>: <span class="token number">0.1</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"run_number"</span>: <span class="token number">0</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"run_name"</span>: <span class="token string">&quot;string&quot;</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"file_prefix"</span>: <span class="token string">&quot;string&quot;</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"socket_number"</span>: <span class="token number">0</span><span class="token punctuation">,</span></div></li><li><div class="hoverable "><span class="property token string">"state"</span>: <span class="token string">&quot;idle&quot;</span></div></li></ul><span class="token punctuation">}</span></code></div></div></div></div></div></div></div></div></div></div></div><div id="/paths/~1cancel/post" data-section-id="/paths/~1cancel/post" class="sc-eDLKkx cSNAXN"><div class="sc-iBdnpw fsPUig"><div class="sc-hLQSwg gikxZY"><h2 class="sc-qZrbh gwJLUj"><a class="sc-csKJxZ fNhImz" href="#/paths/~1cancel/post" aria-label="/paths/~1cancel/post"></a>Cancel running data collection<!-- --> </h2><div class="sc-eYFTNc dZbpPF"><div html="&lt;p&gt;It only instructs writer to cancel, but doesn&amp;#39;t wait for cancellation actually happening.
It still requires to call &lt;code&gt;/wait_till_done&lt;/code&gt;&lt;/p&gt;
" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS"><p>It only instructs writer to cancel, but doesn&#39;t wait for cancellation actually happening.
It still requires to call <code>/wait_till_done</code></p>
@@ -300,7 +300,7 @@ It still requires to call <code>/wait_till_done</code></p>
" class="sc-iKOmoZ sc-cCzLxZ WVNwY VEBGS sc-ckdEwu LxEPk"><p>Release number of Jungfraujoch</p>
</div></button></div></div></div><div class="sc-jTQCzO sc-gLLuof imiXRU jGdkPR"><div class="sc-bPrlCs cIsduN"><button class="sc-GkLId bclCVA"><span type="get" class="sc-jYnQyy eIFDdZ http-verb get">get</span><span class="sc-fYrVWQ gllLir">/version</span><svg class="sc-eTNRI exoGJA" style="margin-right:-25px" version="1.1" viewBox="0 0 24 24" x="0" xmlns="http://www.w3.org/2000/svg" y="0" aria-hidden="true"><polygon points="17.3 8.3 12 13.6 6.7 8.3 5.3 9.7 12 16.4 18.7 9.7 "></polygon></svg></button><div aria-hidden="true" class="sc-eGgGjL hsEiws"><div class="sc-fnpiog jerStl"><div html="" class="sc-iKOmoZ sc-cCzLxZ WVNwY jaVotg"></div><div tabindex="0" role="button"><div class="sc-lkDHyp etvaCd"><span></span>/version</div></div></div></div></div></div></div></div></div><div class="sc-juusvx bsunyy"></div></div></div>
<script>
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.0.3","info":{"title":"Jungfraujoch writer","description":"Jungfraujoch Writer Web API","version":"1.0.0"},"components":{"schemas":{"writer_statistics":{"type":"object","properties":{"nimages":{"type":"integer","format":"int64","description":"Number of images written"},"performance_MBs":{"type":"number","format":"float","description":"Performance in MB/s"},"performance_Hz":{"type":"number","format":"float","description":"Performance in images/s"},"file_prefix":{"type":"string","description":"File prefix for the last written dataset"},"state":{"type":"string","enum":["idle","started","receiving"]}}}}},"paths":{"/status":{"get":{"summary":"Get writer status","responses":{"200":{"description":"Statistics of the last measurement","content":{"application/json":{"schema":{"$ref":"#/components/schemas/writer_statistics"}}}}}}},"/cancel":{"post":{"summary":"Cancel running data collection","description":"It only instructs writer to cancel, but doesn't wait for cancellation actually happening.\nIt still requires to call `/wait_till_done`\n","responses":{"200":{"description":"Cancel message acknowledged"}}}},"/version":{"get":{"responses":{"200":{"description":"Release number of Jungfraujoch","content":{"text/plain":{"schema":{"type":"string","example":"1.0.0"}}}}}}}}}},"searchIndex":{"store":["/paths/~1status/get","/paths/~1cancel/post","/paths/~1version/get"],"index":{"version":"2.3.9","fields":["title","description"],"fieldVectors":[["title/0",[0,0.499,1,0.499]],["description/0",[1,0.699]],["title/1",[2,0.364,3,0.759,4,0.759,5,0.759]],["description/1",[0,0.284,2,0.55,6,0.593,7,0.593,8,0.593,9,0.593,10,0.593,11,0.593,12,0.593,13,0.593,14,0.593]],["title/2",[15,0.613]],["description/2",[15,0.699]]],"invertedIndex":[["actual",{"_index":9,"title":{},"description":{"1":{}}}],["call",{"_index":13,"title":{},"description":{"1":{}}}],["cancel",{"_index":2,"title":{"1":{}},"description":{"1":{}}}],["collect",{"_index":5,"title":{"1":{}},"description":{}}],["data",{"_index":4,"title":{"1":{}},"description":{}}],["doesn't",{"_index":7,"title":{},"description":{"1":{}}}],["happen",{"_index":10,"title":{},"description":{"1":{}}}],["instruct",{"_index":6,"title":{},"description":{"1":{}}}],["requir",{"_index":12,"title":{},"description":{"1":{}}}],["run",{"_index":3,"title":{"1":{}},"description":{}}],["statu",{"_index":1,"title":{"0":{}},"description":{"0":{}}}],["still",{"_index":11,"title":{},"description":{"1":{}}}],["version",{"_index":15,"title":{"2":{}},"description":{"2":{}}}],["wait",{"_index":8,"title":{},"description":{"1":{}}}],["wait_till_don",{"_index":14,"title":{},"description":{"1":{}}}],["writer",{"_index":0,"title":{"0":{}},"description":{"1":{}}}]],"pipeline":[]}},"options":{}};
const __redoc_state = {"menu":{"activeItemIdx":-1},"spec":{"data":{"openapi":"3.0.3","info":{"title":"Jungfraujoch writer","description":"Jungfraujoch Writer Web API","version":"1.0.0.rc_11"},"components":{"schemas":{"writer_statistics":{"type":"object","properties":{"nimages":{"type":"integer","format":"int64","description":"Number of images written"},"performance_MBs":{"type":"number","format":"float","description":"Performance in MB/s"},"performance_Hz":{"type":"number","format":"float","description":"Performance in images/s"},"run_number":{"type":"integer","format":"int64"},"run_name":{"type":"string"},"file_prefix":{"type":"string","description":"File prefix for the last written dataset"},"socket_number":{"type":"integer","format":"int64","description":"Number of socket on `jfjoch_broker` side for the current/last data collection"},"state":{"type":"string","enum":["idle","started","receiving","error"]}}}}},"paths":{"/status":{"get":{"summary":"Get writer status","responses":{"200":{"description":"Statistics of the last measurement","content":{"application/json":{"schema":{"$ref":"#/components/schemas/writer_statistics"}}}}}}},"/cancel":{"post":{"summary":"Cancel running data collection","description":"It only instructs writer to cancel, but doesn't wait for cancellation actually happening.\nIt still requires to call `/wait_till_done`\n","responses":{"200":{"description":"Cancel message acknowledged"}}}},"/version":{"get":{"responses":{"200":{"description":"Release number of Jungfraujoch","content":{"text/plain":{"schema":{"type":"string","example":"1.0.0"}}}}}}}}}},"searchIndex":{"store":["/paths/~1status/get","/paths/~1cancel/post","/paths/~1version/get"],"index":{"version":"2.3.9","fields":["title","description"],"fieldVectors":[["title/0",[0,0.499,1,0.499]],["description/0",[1,0.699]],["title/1",[2,0.364,3,0.759,4,0.759,5,0.759]],["description/1",[0,0.284,2,0.55,6,0.593,7,0.593,8,0.593,9,0.593,10,0.593,11,0.593,12,0.593,13,0.593,14,0.593]],["title/2",[15,0.613]],["description/2",[15,0.699]]],"invertedIndex":[["actual",{"_index":9,"title":{},"description":{"1":{}}}],["call",{"_index":13,"title":{},"description":{"1":{}}}],["cancel",{"_index":2,"title":{"1":{}},"description":{"1":{}}}],["collect",{"_index":5,"title":{"1":{}},"description":{}}],["data",{"_index":4,"title":{"1":{}},"description":{}}],["doesn't",{"_index":7,"title":{},"description":{"1":{}}}],["happen",{"_index":10,"title":{},"description":{"1":{}}}],["instruct",{"_index":6,"title":{},"description":{"1":{}}}],["requir",{"_index":12,"title":{},"description":{"1":{}}}],["run",{"_index":3,"title":{"1":{}},"description":{}}],["statu",{"_index":1,"title":{"0":{}},"description":{"0":{}}}],["still",{"_index":11,"title":{},"description":{"1":{}}}],["version",{"_index":15,"title":{"2":{}},"description":{"2":{}}}],["wait",{"_index":8,"title":{},"description":{"1":{}}}],["wait_till_don",{"_index":14,"title":{},"description":{"1":{}}}],["writer",{"_index":0,"title":{"0":{}},"description":{"1":{}}}]],"pipeline":[]}},"options":{}};
var container = document.getElementById('redoc');
Redoc.hydrate(__redoc_state, container);

View File

@@ -2,7 +2,7 @@ openapi: 3.0.3
info:
title: Jungfraujoch writer
description: Jungfraujoch Writer Web API
version: 1.0.0.rc_10
version: 1.0.0.rc_11
components:
schemas:
writer_statistics:
@@ -28,12 +28,17 @@ components:
file_prefix:
type: string
description: File prefix for the last written dataset
socket_number:
type: integer
format: int64
description: Number of socket on `jfjoch_broker` side for the current/last data collection
state:
type: string
enum:
- idle
- started
- receiving
- error
paths:
/status:
get: