Files
Jungfraujoch/preview/ZMQMetadataSocket.cpp
leonarski_f 7f2ebd8209
Build Packages / Build documentation (push) Successful in 46s
Build Packages / Create release (push) Successful in 8s
Build Packages / build:portable:macos-arm64:nocuda (push) Successful in 5m25s
Build Packages / build:rugnux:linux-aarch64:cuda (push) Successful in 9m46s
Build Packages / build:portable:linux-x86_64:nocuda (push) Successful in 13m25s
Build Packages / build:portable:linux-x86_64:cuda (push) Successful in 16m41s
Build Packages / build:portable:windows-x86_64:nocuda (push) Successful in 23m46s
Build Packages / HDF5 consumer tests (DIALS, XDS) (push) Successful in 25m37s
Build Packages / build:jfjoch:rocky8:nocuda (push) Successful in 24m31s
Build Packages / build:portable:windows-x86_64:cuda (push) Successful in 28m9s
Build Packages / build:jfjoch:ubuntu2204:nocuda (push) Successful in 20m47s
Build Packages / build:jfjoch:rocky9:nocuda (push) Successful in 26m21s
Build Packages / build:jfjoch:ubuntu2404:nocuda (push) Successful in 27m36s
Build Packages / Generate python client (push) Successful in 31s
Build Packages / build:jfjoch:rocky8:cuda-sls9 (push) Successful in 29m27s
Build Packages / build:jfjoch:rocky9:cuda-sls9 (push) Successful in 31m46s
Build Packages / build:jfjoch:ubuntu2204:cuda (push) Successful in 25m22s
Build Packages / build:jfjoch:rocky8:cuda (push) Successful in 30m36s
Build Packages / build:jfjoch:rocky9:cuda (push) Successful in 31m49s
Build Packages / build:jfjoch:ubuntu2404:cuda (push) Successful in 23m57s
Build Packages / Unit tests (push) Successful in 1h47m52s
Build Packages / Validation Battery (push) Successful in 44m55s
v1.0.0-rc.184 (#95)
* Rugnux: Rotation processing recovers most of the speed lost since 1.0.0-rc.180; live processing in jfjoch_broker finishes sooner.
* Rugnux: More reliable rotation processing and indexing, including small molecules and supercells.
* Rugnux: More robust serial data and model refinement; molecular replacement handles multi-chain models.
* jfjoch_broker (experimental): Live serial processing keeps the detector geometry fixed for the whole run.
* jfjoch_broker: Pixel sum without an FPGA, a mask bit for inactive pixels, and several stability fixes.
* jfjoch_broker: Rotation indexing and quick integration moved to rugnux live mode; their API settings are deprecated and ignored.
* jfjoch_broker, Rugnux: Azimuthal integration can use logarithmic (log10) Q bins or a given number of bins, set from the API, the web interface and the Rugnux command line.
* jfjoch_viewer: Build and display fixes; the README is rewritten.

Reviewed-on: #95
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-11-10 22:06:51 +01:00

117 lines
3.9 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "ZMQMetadataSocket.h"
#include "../frame_serialize/CBORStream2Serializer.h"
#include "../common/ZMQWrappers.h"
#include "../common/Definitions.h"
#define MESSAGE_SIZE_FOR_IMAGE (20*1024) // 20 kB
ZMQMetadataSocket::ZMQMetadataSocket(const std::string &addr)
: metadata_message({}), socket(ZMQSocketType::Pub), counter(std::chrono::seconds(1)) {
socket.SendWaterMark(DefaultSendWatermark);
socket.Bind(addr);
first_image = true;
}
void ZMQMetadataSocket::StartDataCollection(const StartMessage &message) {
std::unique_lock ul(m);
metadata_message = MetadataMessage{};
if (buffer.size() < MESSAGE_SIZE_FOR_START_END)
buffer.resize(MESSAGE_SIZE_FOR_START_END);
CBORStream2Serializer serializer(buffer.data(), buffer.size());
serializer.SerializeSequenceStart(message);
socket.Send(buffer.data(), serializer.GetBufferSize(), true);
first_image = true;
}
// Called without m: serialising a batch must not hold up the image threads
void ZMQMetadataSocket::Send(const MetadataMessage &batch) {
size_t size = 0;
for (const auto &i: batch.images)
size += MESSAGE_SIZE_FOR_IMAGE + 16 * i.az_int_profile.size() + 9 * i.adu_histogram.size();
std::vector<uint8_t> batch_buffer(size);
CBORStream2Serializer serializer(batch_buffer.data(), batch_buffer.size());
serializer.SerializeMetadata(batch);
socket.Send(batch_buffer.data(), serializer.GetBufferSize(), false);
}
void ZMQMetadataSocket::AddDataMessage(const DataMessage &msg) {
// Disabled: nothing is kept
if (!counter.GetPeriod())
return;
// Spots, reflections and the image are not part of the metadata message
DataMessage copy = msg;
copy.spots = {};
copy.reflections = {};
copy.image = CompressedImage();
MetadataMessage batch;
{
std::unique_lock ul(m);
if (first_image) {
// GeneratePreview() is designed to fire on the first try. This would result however in situation where
// first metadata packet always contains only 1 image, and this is not desired behavior.
// Therefore, on first use there is one extra "artificial" check of generate preview, that starts the clock
counter.GeneratePreview();
metadata_message.run_name = msg.run_name;
metadata_message.run_number = msg.run_number;
first_image = false;
}
metadata_message.images.emplace_back(std::move(copy));
if (!counter.GeneratePreview())
return;
batch.run_name = metadata_message.run_name;
batch.run_number = metadata_message.run_number;
std::swap(batch.images, metadata_message.images);
}
Send(batch);
}
void ZMQMetadataSocket::EndDataCollection(const EndMessage &message) {
std::unique_lock ul(m);
if (!metadata_message.images.empty()) {
Send(metadata_message);
metadata_message.images.clear();
}
if (buffer.size() < MESSAGE_SIZE_FOR_START_END)
buffer.resize(MESSAGE_SIZE_FOR_START_END);
CBORStream2Serializer serializer(buffer.data(), buffer.size());
serializer.SerializeSequenceEnd(message);
socket.Send(buffer.data(), serializer.GetBufferSize(), true);
}
ZMQMetadataSocket &ZMQMetadataSocket::Period(const std::optional<std::chrono::microseconds> &period) {
counter.Period(period);
return *this;
}
ZMQMetadataSocket& ZMQMetadataSocket::ImportSettings(const ZMQMetadataSettings &settings) {
std::unique_lock ul(m);
Period(settings.period);
return *this;
}
ZMQMetadataSettings ZMQMetadataSocket::GetSettings() {
std::unique_lock ul(m);
return ZMQMetadataSettings{
.period = counter.GetPeriod(),
.address = socket.GetEndpointName()
};
}
std::string ZMQMetadataSocket::GetAddress() {
return socket.GetEndpointName();
}