McStas Readout Master 0.3.3
Loading...
Searching...
No Matches
hdf_interface.h
1#pragma once
2#include <chrono>
3#include <thread>
4
5#include <highfive/H5File.hpp>
6#include <highfive/H5DataSet.hpp>
7#include <highfive/H5DataSpace.hpp>
8
9#include "Readout.h"
11#include "enums.h"
12
13#ifdef WIN32
14// Export symbols if compile flags "READOUT_SHARED" and "READOUT_EXPORT" are set on Windows.
15 #ifdef READOUT_SHARED
16 #ifdef READOUT_EXPORT
17 #define RL_API __declspec(dllexport)
18 #else
19 #define RL_API __declspec(dllimport)
20 #endif
21 #else
22 // Disable definition if linking statically.
23 #define RL_API
24 #endif
25#else
26// Disable definition for non-Win32 systems.
27#define RL_API
28#endif
29
33class RL_API Event{
34public:
35 uint8_t ring;
36 uint8_t fen;
37 double time;
38 double weight;
39 Event() = default;
40 Event(uint8_t ring, uint8_t fen, double time, double weight)
41 : ring(ring), fen(fen), time(time), weight(weight) {}
42};
43
45class RL_API CAEN_event: public Event {
46public:
47 uint8_t channel;
48 uint16_t a;
49 uint16_t b;
50 uint16_t c;
51 uint16_t d;
52 explicit CAEN_event() = default;
53 CAEN_event(uint8_t r, uint8_t f, double t, double w, const CAEN_readout * ro)
54 : Event(r, f, t, w), channel{ro->channel}, a{ro->a}, b{ro->b}, c{ro->c}, d{ro->d} {}
55 template<class T> void add(T & readout) const {
56 auto r = CAEN_readout{channel, a, b, c, d};
57 readout.addReadout(ring, fen, time, weight, static_cast<void *>(&r));
58// std::this_thread::sleep_for(std::chrono::milliseconds(10));
59 }
60};
61
63class RL_API TTLMonitor_event: public Event {
64public:
65 uint8_t channel;
66 uint8_t pos;
67 uint16_t adc;
68 explicit TTLMonitor_event() = default;
69 TTLMonitor_event(uint8_t r, uint8_t f, double t, double w, const TTLMonitor_readout * p)
70 : Event(r, f, t, w), channel{p->channel}, pos{p->pos}, adc{p->adc} {}
71 template<class T> void add(T & readout) const {
72 auto r = TTLMonitor_readout{channel, pos, adc};
73 readout.addReadout(ring, fen, time, weight, static_cast<void *>(&r));
74// std::this_thread::sleep_for(std::chrono::milliseconds(10));
75 }
76};
77
79class RL_API CDT_event: public Event {
80public:
81 uint8_t om;
82 uint8_t cathode;
83 uint8_t anode;
84 explicit CDT_event() = default;
85 CDT_event(uint8_t r, uint8_t f, double t, double w, const CDT_readout * p)
86 : Event(r, f, t, w), om{p->om}, cathode{p->cathode}, anode{p->anode} {}
87 template<class T> void add(T & readout) const {
88 auto r = CDT_readout{om, cathode, anode};
89 readout.addReadout(ring, fen, time, weight, static_cast<void *>(&r));
90// std::this_thread::sleep_for(std::chrono::milliseconds(10));
91 }
92};
93
95class RL_API VMM3_event: public Event {
96public:
97 uint16_t bc;
98 uint16_t otadc;
99 uint8_t geo;
100 uint8_t tdc;
101 uint8_t vmm;
102 uint8_t channel;
103 explicit VMM3_event() = default;
104 VMM3_event(uint8_t r, uint8_t f, double t, double w, const VMM3_readout * p)
105 : Event(r, f, t, w), bc{p->bc}, otadc{p->otadc}, geo{p->geo}, tdc{p->tdc}, vmm{p->vmm}, channel{p->channel} {}
106 template<class T> void add(T & readout) const {
107 auto r = VMM3_readout{bc, otadc, geo, tdc, vmm, channel};
108 readout.addReadout(ring, fen, time, weight, static_cast<void *>(&r));
109// std::this_thread::sleep_for(std::chrono::milliseconds(10));
110 }
111};
112
114class RL_API BM0_event: public Event {
115public:
116 uint8_t channel;
117 explicit BM0_event() = default;
118 BM0_event(uint8_t r, uint8_t f, double t, double w, const BM0_readout * p)
119 : Event(r, f, t, w), channel{p->channel} {}
120 template<class T> void add(T & readout) const {
121 auto r = BM0_readout{channel};
122 readout.addReadout(ring, fen, time, weight, static_cast<void *>(&r));
123 }
124};
125
127class RL_API BM2_event: public Event {
128public:
129 uint8_t channel;
130 uint16_t pos_x;
131 uint16_t pos_y;
132 explicit BM2_event() = default;
133 BM2_event(uint8_t r, uint8_t f, double t, double w, const BM2_readout * p)
134 : Event(r, f, t, w), channel{p->channel} , pos_x{p->pos_x}, pos_y{p->pos_y} {}
135 template<class T> void add(T & readout) const {
136 auto r = BM2_readout{channel, pos_x, pos_y};
137 readout.addReadout(ring, fen, time, weight, static_cast<void *>(&r));
138 }
139};
140
142class RL_API BMI_event: public Event {
143public:
144 uint8_t channel;
145 uint8_t sum;
146 uint32_t adc; // 24 bit ADC value, but stored in a 32-bit integer for alignment reasons
147 explicit BMI_event() = default;
148 BMI_event(uint8_t r, uint8_t f, double t, double w, const BMI_readout * p)
149 : Event(r, f, t, w), channel{p->channel} , sum{p->sum}, adc{p->adc} {}
150 template<class T> void add(T & readout) const {
151 auto r = BMI_readout{channel, sum, adc};
152 readout.addReadout(ring, fen, time, weight, static_cast<void *>(&r));
153 }
154};
155
156
157inline HighFive::CompoundType create_compound_caen_readout(){
158 return {
159 {"ring", HighFive::create_datatype<uint8_t>()},
160 {"FEN", HighFive::create_datatype<uint8_t>()},
161 {"time", HighFive::create_datatype<double>()},
162 {"weight", HighFive::create_datatype<double>()},
163 {"channel", HighFive::create_datatype<uint8_t>()},
164 {"a", HighFive::create_datatype<uint16_t>()},
165 {"b", HighFive::create_datatype<uint16_t>()},
166 {"c", HighFive::create_datatype<uint16_t>()},
167 {"d", HighFive::create_datatype<uint16_t>()},
168 };
169}
170
171inline HighFive::CompoundType create_compound_ttlmonitor_readout(){
172 return {
173 {"ring", HighFive::create_datatype<uint8_t>()},
174 {"FEN", HighFive::create_datatype<uint8_t>()},
175 {"time", HighFive::create_datatype<double>()},
176 {"weight", HighFive::create_datatype<double>()},
177 {"channel", HighFive::create_datatype<uint8_t>()},
178 {"pos", HighFive::create_datatype<uint8_t>()},
179 {"adc", HighFive::create_datatype<uint16_t>()},
180 };
181}
182
183inline HighFive::CompoundType create_compound_dream_readout(){
184 return {
185 {"ring", HighFive::create_datatype<uint8_t>()},
186 {"FEN", HighFive::create_datatype<uint8_t>()},
187 {"time", HighFive::create_datatype<double>()},
188 {"weight", HighFive::create_datatype<double>()},
189 {"om", HighFive::create_datatype<uint8_t>()},
190 {"cathode", HighFive::create_datatype<uint8_t>()},
191 {"anode", HighFive::create_datatype<uint8_t>()},
192 };
193}
194
195inline HighFive::CompoundType create_compound_vmm3_readout(){
196 return {
197 {"ring", HighFive::create_datatype<uint8_t>()},
198 {"FEN", HighFive::create_datatype<uint8_t>()},
199 {"time", HighFive::create_datatype<double>()},
200 {"weight", HighFive::create_datatype<double>()},
201 {"bc", HighFive::create_datatype<uint16_t>()},
202 {"otadc", HighFive::create_datatype<uint16_t>()},
203 {"geo", HighFive::create_datatype<uint8_t>()},
204 {"tdc", HighFive::create_datatype<uint8_t>()},
205 {"vmm", HighFive::create_datatype<uint8_t>()},
206 {"channel", HighFive::create_datatype<uint8_t>()},
207 };
208}
209
210inline HighFive::CompoundType create_compound_bm0_readout(){
211 return {
212 {"ring", HighFive::create_datatype<uint8_t>()},
213 {"FEN", HighFive::create_datatype<uint8_t>()},
214 {"time", HighFive::create_datatype<double>()},
215 {"weight", HighFive::create_datatype<double>()},
216 {"channel", HighFive::create_datatype<uint8_t>()},
217 };
218}
219
220inline HighFive::CompoundType create_compound_bm2_readout(){
221 return {
222 {"ring", HighFive::create_datatype<uint8_t>()},
223 {"FEN", HighFive::create_datatype<uint8_t>()},
224 {"time", HighFive::create_datatype<double>()},
225 {"weight", HighFive::create_datatype<double>()},
226 {"channel", HighFive::create_datatype<uint8_t>()},
227 {"pos_x", HighFive::create_datatype<uint16_t>()},
228 {"pos_y", HighFive::create_datatype<uint16_t>()},
229 };
230}
231
232inline HighFive::CompoundType create_compound_bmi_readout(){
233 return {
234 {"ring", HighFive::create_datatype<uint8_t>()},
235 {"FEN", HighFive::create_datatype<uint8_t>()},
236 {"time", HighFive::create_datatype<double>()},
237 {"weight", HighFive::create_datatype<double>()},
238 {"channel", HighFive::create_datatype<uint8_t>()},
239 {"sum", HighFive::create_datatype<uint8_t>()},
240 {"adc", HighFive::create_datatype<uint32_t>()},
241 };
242}
243
244namespace HighFive {
245 template<> inline DataType create_datatype<CAEN_event>(){return create_compound_caen_readout();}
246 template<> inline DataType create_datatype<TTLMonitor_event>(){return create_compound_ttlmonitor_readout();}
247 template<> inline DataType create_datatype<CDT_event>(){return create_compound_dream_readout();}
248 template<> inline DataType create_datatype<VMM3_event>(){return create_compound_vmm3_readout();}
249 template<> inline DataType create_datatype<BM0_event>(){return create_compound_bm0_readout();}
250 template<> inline DataType create_datatype<BM2_event>(){return create_compound_bm2_readout();}
251 template<> inline DataType create_datatype<BMI_event>(){return create_compound_bmi_readout();}
252}
253
255inline HighFive::CompoundType hdf_compound_type(const ReadoutType readout) {
256 switch (readout) {
257 case ReadoutType::CAEN: return create_compound_caen_readout();
258 case ReadoutType::TTLMonitor: return create_compound_ttlmonitor_readout();
259 case ReadoutType::CDT: return create_compound_dream_readout();
260 case ReadoutType::VMM3: return create_compound_vmm3_readout();
261 case ReadoutType::BM0: return create_compound_bm0_readout();
262 case ReadoutType::BM2: return create_compound_bm2_readout();
263 case ReadoutType::BMI: return create_compound_bmi_readout();
264 default: throw std::runtime_error("Saving this readout type is not implemented yet!");
265 }
266}
267
269inline HighFive::DataType hdf5_type_for(const std::string& canonical_type) {
270 if (canonical_type == "int8_t") return HighFive::create_datatype<int8_t>();
271 if (canonical_type == "int16_t") return HighFive::create_datatype<int16_t>();
272 if (canonical_type == "int32_t") return HighFive::create_datatype<int32_t>();
273 if (canonical_type == "int64_t") return HighFive::create_datatype<int64_t>();
274 if (canonical_type == "uint8_t") return HighFive::create_datatype<uint8_t>();
275 if (canonical_type == "uint16_t") return HighFive::create_datatype<uint16_t>();
276 if (canonical_type == "uint32_t") return HighFive::create_datatype<uint32_t>();
277 if (canonical_type == "uint64_t") return HighFive::create_datatype<uint64_t>();
278 if (canonical_type == "float") return HighFive::create_datatype<float>();
279 if (canonical_type == "double") return HighFive::create_datatype<double>();
280 throw std::runtime_error("No HDF5 type mapping for: " + canonical_type);
281}
282
287inline HighFive::CompoundType build_hdf5_compound_type(const TypeSchema & schema) {
288 std::vector<HighFive::CompoundType::member_def> members;
289 members.reserve(schema.fields.size());
290
291 for (const auto& field : schema.fields) {
292 if (field.array_count > 0) {
293 throw std::runtime_error(
294 "build_hdf5_compound_type: array fields are not supported (field: " + field.name + ")"
295 );
296 }
297 members.push_back({field.name, hdf5_type_for(field.type), field.offset});
298 }
299
300 return HighFive::CompoundType(members, schema.total_size);
301}
Umbrella header for the C API used by the McStas components.
Parser for C struct type descriptions into a runtime type schema.
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.
Common fields of every stored readout event: routing (ring, FEN), time-of-flight, and the statistical...
TTL beam-monitor readout event: channel, position, ADC.
Complete description of a parsed struct.
VMM3 readout event: BC, OTADC, GEO, TDC, VMM, channel.