mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2026-07-16 05:14:30 +02:00
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
- 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
335 lines
12 KiB
C++
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 |