Files
maliakal_dandGitHub c3ad3d2e73
Build and Deploy on local RHEL9 / build (push) Successful in 2m13s
Build on RHEL9 docker image / build (push) Successful in 3m53s
Build and Deploy on local RHEL8 / build (push) Successful in 4m58s
Build on RHEL8 docker image / build (push) Successful in 5m47s
Run Simulator Tests on local RHEL9 / build (push) Successful in 18m55s
Run Simulator Tests on local RHEL8 / build (push) Successful in 22m26s
Dev/rx disable datastream port (#1448)
- changed 
   - command from `datastream` to `udp_datastream` to be more specific
   - Detector API:
      - setNumberofUDPInterfaces(pos) =>setNumberofUDPInterfaces() # no position anymore
      - getDataStream(portPosition, pos) =>getUDPDataStream(portPosition, pos)
      - setDataStream(portPosition, pos) => setUDPDataStream(portPosition) # no position anymore
      
   - modified the dataprocessing thread: 
      - if gui or call back, start zmq processing (connecting sockets) before starting receiver (disabled ports sends dummy that the client zmq sockets are not ready for)
      - if only progress, starting progress processing thread after startReceiver
      -


- added
   - Detector API:
      - getRxDisabledUDPPortIndices()
      - getPortPositionList()  
   - allow disabling/enabling udp interface in receiver for Jungfrua/Moench when both udp interfaces is enabled  (This is to go fast, where only one half of the module matters)
   - write ports type and disabled ports to master file (tests for it as well)
   - tests for python commands as well
   - datastream command to deprecated commands
   - refactored tests to make the new parameters fit

* first draft of disabling data port at the receiver side. Todo: master file and stream for gui to use

* updated help in command

* formatting

* md5 unchanged

* fix test, check port position for detector type

* wip, udp port enable metadata in client, to:receiver, zmq streaming

* wip, master attributes

* wip, imple=> save only disabled ports with port index, 1 interface, is empty

* works in file. still needs refactoring

* updated writer versions

* udp ports type pass, disabled with api yet

* fixed disabled ports meta data as well

* fixed in developer via other PR

* renamed.more intuitive

* fix in gui that wont wait for disabled ports

* added tests for master file

* extra tests

* move the master fiel tests into its own tests with the disable marker for github tests

* refactoring

* python test

* more intuitive and doc

* release notes

* example for python

* back to before

* minor documentation fix and sending nports unnecessarily for getRxUDPPortDisableMetadata

* doc

* review fixes, 1. using std::array instead of vector, 2. moving udp_datastream command testing with different values into master attributes testing file because we test the master file

* minor

* review: update help

* progress printed before assigned

* try catch inside hdf5

* auto generated code for CLI and formatting

* missing packets should not be checked at github workflow level

* formatting

* improved python doc for udp_datastream help

* indent doc python done
2026-07-13 14:58:25 +02:00

335 lines
12 KiB
C++

// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
#include "Readers.h"
#include "sls/sls_detector_defs.h"
#include <iostream>
#ifdef HDF5C
#include "H5Cpp.h"
namespace sls::test::master_file {
using ns = std::chrono::nanoseconds;
static const std::string HDF5_GROUP = "/entry/instrument/detector/";
/* --safety checks-- */
inline void require_dataset(const H5Context &ctx, const std::string &name) {
const std::string full_name = HDF5_GROUP + name;
if (H5Lexists(ctx.file.getId(), full_name.c_str(), H5P_DEFAULT) <= 0) {
throw sls::RuntimeError("Missing HDF5 dataset: " + full_name);
}
}
inline void require_file_attribute(const H5Context &ctx,
const std::string &name) {
if (!H5Aexists_by_name(ctx.file.getId(), "/", name.c_str(), H5P_DEFAULT)) {
throw sls::RuntimeError("Missing HDF5 attribute: " + name);
}
}
/* --scalar reads-- */
template <> struct Reader<H5Context, int> {
static int read(const H5Context &ctx, const std::string &name,
AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError("int attribute access not supported for HDF5");
}
require_dataset(ctx, name);
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
int out{};
ds.read(&out, H5::PredType::NATIVE_INT);
return out;
}
};
template <> struct Reader<H5Context, uint32_t> {
static uint32_t read(const H5Context &ctx, const std::string &name,
AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError(
"uint32_t attribute access not supported for HDF5");
}
require_dataset(ctx, name);
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
uint32_t out{};
ds.read(&out, H5::PredType::STD_U32LE);
return out;
}
};
template <> struct Reader<H5Context, uint64_t> {
static uint64_t read(const H5Context &ctx, const std::string &name,
AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError(
"'uint64_t' attribute access not supported for HDF5");
}
uint64_t out{};
require_dataset(ctx, name);
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
ds.read(&out, H5::PredType::STD_U64LE);
return out;
}
};
template <> struct Reader<H5Context, double> {
static double read(const H5Context &ctx, const std::string &name,
AccessType access) {
double out{};
if (access == AccessType::Attribute) {
require_file_attribute(ctx, name);
auto attr = ctx.file.openAttribute(name);
attr.read(attr.getDataType(), &out);
return out;
}
// dataset
require_dataset(ctx, name);
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
ds.read(&out, H5::PredType::NATIVE_DOUBLE);
return out;
}
};
template <> struct Reader<H5Context, std::string> {
static std::string read(const H5Context &ctx, const std::string &name,
AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError(
"string attribute access not supported for HDF5");
}
require_dataset(ctx, name);
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
std::string out{};
ds.read(out, ds.getStrType());
return out;
}
};
/** complex types */
template <> struct Reader<H5Context, defs::xy> {
static defs::xy read(const H5Context &ctx, const std::string &name,
AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError(
"'defs::xy' attribute access not supported for HDF5");
}
require_dataset(ctx, name);
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
// define type
H5::CompType type(sizeof(defs::xy));
type.insertMember("x", HOFFSET(defs::xy, x), H5::PredType::NATIVE_INT);
type.insertMember("y", HOFFSET(defs::xy, y), H5::PredType::NATIVE_INT);
// read
defs::xy out{};
ds.read(&out, type);
return out;
}
};
inline hsize_t get_1d_size(const H5::DataSet &ds) {
H5::DataSpace space = ds.getSpace();
hsize_t dims[1];
space.getSimpleExtentDims(dims);
return dims[0];
}
template <> struct Reader<H5Context, std::vector<defs::ROI>> {
static std::vector<defs::ROI>
read(const H5Context &ctx, const std::string &name, AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError("'std::vector<defs::ROI>' attribute access not "
"supported for HDF5");
}
require_dataset(ctx, name);
// define type
H5::CompType type(sizeof(defs::ROI));
type.insertMember("xmin", HOFFSET(defs::ROI, xmin),
H5::PredType::NATIVE_INT);
type.insertMember("xmax", HOFFSET(defs::ROI, xmax),
H5::PredType::NATIVE_INT);
type.insertMember("ymin", HOFFSET(defs::ROI, ymin),
H5::PredType::NATIVE_INT);
type.insertMember("ymax", HOFFSET(defs::ROI, ymax),
H5::PredType::NATIVE_INT);
// read
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
auto len = get_1d_size(ds);
std::vector<defs::ROI> out{};
out.resize(len);
ds.read(out.data(), type);
return out;
}
};
template <> struct Reader<H5Context, defs::scanParameters> {
static defs::scanParameters
read(const H5Context &ctx, const std::string &name, AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError("'defs::scanParameters' attribute access not "
"supported for HDF5");
}
require_dataset(ctx, name);
// define type
H5::CompType type(sizeof(defs::scanParameters));
type.insertMember("enable", HOFFSET(defs::scanParameters, enable),
H5::PredType::NATIVE_INT);
type.insertMember("dacInd", HOFFSET(defs::scanParameters, dacInd),
H5::PredType::NATIVE_INT);
type.insertMember("startOffset",
HOFFSET(defs::scanParameters, startOffset),
H5::PredType::NATIVE_INT);
type.insertMember("stopOffset",
HOFFSET(defs::scanParameters, stopOffset),
H5::PredType::NATIVE_INT);
type.insertMember("stepSize", HOFFSET(defs::scanParameters, stepSize),
H5::PredType::NATIVE_INT);
type.insertMember("dacSettleTime_ns",
HOFFSET(defs::scanParameters, dacSettleTime_ns),
H5::PredType::STD_I64LE);
// read
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
defs::scanParameters out{};
ds.read(&out, type);
return out;
}
};
/** arrays/vectors/maps */
template <> struct Reader<H5Context, std::array<int, 3UL>> {
static std::array<int, 3UL>
read(const H5Context &ctx, const std::string &name, AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError("'std::array<int, 3UL>' attribute access not "
"supported for HDF5");
}
require_dataset(ctx, name);
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
auto len = get_1d_size(ds);
check_size(len, 3, name, "HDF5");
std::array<int, 3UL> out{};
ds.read(out.data(), H5::PredType::NATIVE_INT);
return out;
}
};
template <> struct Reader<H5Context, std::array<ns, 3UL>> {
static std::array<ns, 3UL>
read(const H5Context &ctx, const std::string &name, AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError("'std::array<ns, 3UL>' attribute access not "
"supported for HDF5");
}
require_dataset(ctx, name);
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
auto len = get_1d_size(ds);
check_size(len, 3, name, "HDF5");
// read int raw char buffer
std::vector<const char *> raw(len);
ds.read(raw.data(), ds.getStrType());
std::array<ns, 3UL> out{};
for (size_t i = 0; i != len; ++i) {
out[i] = StringTo<ns>(raw[i]);
}
return out;
}
};
template <> struct Reader<H5Context, std::vector<int>> {
static std::vector<int> read(const H5Context &ctx, const std::string &name,
AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError("'std::vector<int>' attribute access not "
"supported for HDF5");
}
require_dataset(ctx, name);
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
auto len = get_1d_size(ds);
std::vector<int> out{};
out.resize(len);
ds.read(out.data(), H5::PredType::NATIVE_INT);
return out;
}
};
template <> struct Reader<H5Context, std::vector<int64_t>> {
static std::vector<int64_t>
read(const H5Context &ctx, const std::string &name, AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError("'std::vector<int64_t>' attribute access not "
"supported for HDF5");
}
require_dataset(ctx, name);
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
auto len = get_1d_size(ds);
std::vector<int64_t> out{};
out.resize(len);
ds.read(out.data(), H5::PredType::STD_I64LE);
return out;
}
};
template <> struct Reader<H5Context, std::vector<std::string>> {
static std::vector<std::string>
read(const H5Context &ctx, const std::string &name, AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError(
"'std::vector<std::string>' attribute access not "
"supported for HDF5");
}
require_dataset(ctx, name);
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
H5::StrType strType(H5::PredType::C_S1, H5T_VARIABLE);
std::vector<const char *> raw;
raw.resize(get_1d_size(ds));
ds.read(raw.data(), strType);
std::vector<std::string> out;
out.reserve(raw.size());
for (auto c : raw) {
out.emplace_back(c);
}
return out;
}
};
template <> struct Reader<H5Context, std::map<std::string, std::string>> {
static std::map<std::string, std::string>
read(const H5Context &ctx, const std::string &name, AccessType access) {
if (access == AccessType::Attribute) {
throw RuntimeError("'std::map<std::string, std::string>' attribute "
"access not supported for HDF5");
}
require_dataset(ctx, name);
std::map<std::string, std::string> out{};
// dim
auto ds = ctx.file.openDataSet(HDF5_GROUP + name);
auto len = get_1d_size(ds);
// empty ds
if (len == 0) {
return out;
}
// define type
auto strType = ds.getStrType();
H5::CompType mapType(sizeof(char *) * 2);
mapType.insertMember("key", 0, strType);
mapType.insertMember("value", sizeof(char *), strType);
struct KeyValue {
const char *key;
const char *value;
};
// read
std::vector<KeyValue> kv_vector(len);
ds.read(kv_vector.data(), mapType);
for (const auto &kv : kv_vector) {
out[kv.key] = kv.value;
}
return out;
}
};
} // namespace sls::test::master_file
#endif