McStas Readout Master 0.3.3
Loading...
Searching...
No Matches
writer.h
1#pragma once
2#include <cstring>
3#include "ReadoutClass.h"
4#include "enums.h"
5
6
7#ifdef WIN32
8// Export symbols if compile flags "READOUT_SHARED" and "READOUT_EXPORT" are set on Windows.
9 #ifdef READOUT_SHARED
10 #ifdef READOUT_EXPORT
11 #define RL_API __declspec(dllexport)
12 #else
13 #define RL_API __declspec(dllimport)
14 #endif
15 #else
16 // Disable definition if linking statically.
17 #define RL_API
18 #endif
19#else
20// Disable definition for non-Win32 systems.
21#define RL_API
22#endif
23
24
33class Writer{
34 std::string filename;
35 std::optional<HighFive::File> file;
36 std::optional<HighFive::DataSet> dataset;
37 std::optional<HighFive::DataType> datatype;
38 DetectorType detector{DetectorType::Reserved};
39 ReadoutType readout{ReadoutType::CAEN};
40 int verbosity{0};
41public:
42 RL_API DetectorType detector_type() const {return detector;}
43 RL_API void detector_type(const DetectorType type) {detector = type;}
44 RL_API ReadoutType readout_type() const {return readout;}
45 RL_API void readout_type(const ReadoutType type) {readout = type;}
46 RL_API void verbose(const int v) {verbosity = v;}
47
48 RL_API explicit Writer(
49 const std::string & filename,
50 const DetectorType detectorType,
51 const ReadoutType readoutType,
52 const std::string & dataset_name = "events"
53 )
54 : filename{filename}, detector{detectorType}, readout{readoutType} {
55 try {
56 file = HighFive::File(filename, HighFive::File::OpenOrCreate);
57 } catch (HighFive::Exception & ex) {
58 std::cout << "Error opening file " << filename << " for writing:\n" << ex.what();
59 file = std::nullopt;
60 return;
61 }
62
63 // we want to output an events list which can grow forever
64 auto dataspace = HighFive::DataSpace({0}, {HighFive::DataSpace::UNLIMITED});
65 // but should chunk file operations to avoid too much disk IO?
66 HighFive::DataSetCreateProps props;
67 props.add(HighFive::Chunking(std::vector<hsize_t>{100}));
68
69 auto hc_type = hdf_compound_type();
70 datatype = hc_type;
71 hc_type.commit(file.value(), readoutType_name(readout));
72 dataset = file.value().createDataSet(dataset_name, dataspace, hc_type, props);
73
74 // Assign useful information as attributes:
75 /* FIXME C++20 has char8_t but C++17 does not, so these strings _might_ already be chars
76 * instead of unsigned chars. If that's the case this lambda is a non-op.
77 */
78 auto u8str = [](const auto * p){return std::string(reinterpret_cast<const char *>(p));};
79 file->createAttribute<std::string>("program", "libreadout");
80 file->createAttribute<std::string>("version", u8str(libreadout::version::version_number));
81 file->createAttribute<std::string>("revision", u8str(libreadout::version::git_revision));
82 file->createAttribute<std::string>("events", dataset_name);
83 dataset->createAttribute("detector", detectorType_name(detector));
84 dataset->createAttribute("readout", readoutType_name(readout));
85 }
86
88 RL_API void saveReadout(const uint8_t Ring, const uint8_t FEN, const double tof, const double weight, const void * data){
89 if (!dataset.has_value()){
90 if (verbosity > 1) std::cout << "No readout saved to file due to no dataset available" << std::endl;
91 return;
92 }
93 switch (readoutType_from_detectorType(detector)) {
94 case ReadoutType::CAEN: return saveReadout(CAEN_event(Ring, FEN, tof, weight, static_cast<const CAEN_readout_t*>(data)));
95 case ReadoutType::TTLMonitor: return saveReadout(TTLMonitor_event(Ring, FEN, tof, weight, static_cast<const TTLMonitor_readout_t*>(data)));
96 case ReadoutType::CDT: return saveReadout(CDT_event(Ring, FEN, tof, weight, static_cast<const CDT_readout_t*>(data)));
97 case ReadoutType::VMM3: return saveReadout(VMM3_event(Ring, FEN, tof, weight, static_cast<const VMM3_readout_t*>(data)));
98 case ReadoutType::BM0: return saveReadout(BM0_event(Ring, FEN, tof, weight, static_cast<const BM0_readout_t*>(data)));
99 case ReadoutType::BM2: return saveReadout(BM2_event(Ring, FEN, tof, weight, static_cast<const BM2_readout_t*>(data)));
100 case ReadoutType::BMI: return saveReadout(BMI_event(Ring, FEN, tof, weight, static_cast<const BMI_readout_t*>(data)));
101 default: throw std::runtime_error("This readout data type not implemented yet!");
102 }
103 }
104
105 template<class T> void saveReadout(T data){
106 if (file.has_value() and dataset.has_value() and datatype.has_value()) {
107 auto & ds = dataset.value();
108 // the dataset should be 1-D ... hopefully that's true
109 auto pos = ds.getDimensions().back();
110 auto size = pos + 1;
111 ds.resize({size});
112 ds.select({pos}, {1}).write_raw(reinterpret_cast<const uint8_t *>(&data), datatype.value());
113 }
114 }
115
116private:
117 HighFive::CompoundType hdf_compound_type() const {
118 return ::hdf_compound_type(readout);
119 }
120};
UDP readout generator class.
Minimal beam-monitor readout event: channel only.
Position-resolving beam-monitor readout event: channel, x, y.
Integrating beam-monitor readout event: channel, sum, 24-bit ADC.
CAEN readout event: group channel and amplitudes A-D.
CDT (DREAM-family) readout event: output module, cathode, anode.
TTL beam-monitor readout event: channel, position, ADC.
VMM3 readout event: BC, OTADC, GEO, TDC, VMM, channel.
Legacy flat-file HDF5 writer used by the runtime-streaming Readout components.
Definition writer.h:33
RL_API void saveReadout(const uint8_t Ring, const uint8_t FEN, const double tof, const double weight, const void *data)
Append one event; data must point to the readout struct matching the configured ReadoutType.
Definition writer.h:88