epic-drich-beam-test-analysis
ePIC dRICH beam test analysis framework
Loading...
Searching...
No Matches
triggers.h
Go to the documentation of this file.
1
32#pragma once
33
34#include <string>
35#include <vector>
36#include <cstdint>
37#include <iostream>
38#include <toml++/toml.h>
39#include "TH2.h"
40
41// ============================================================
42// Trigger enum & compile-time metadata
43// ============================================================
44
65
68constexpr trigger_number all_default_triggers[] = {
77
79constexpr const char *default_names[] = {
80 "FIRST_FRAMES", "TIMING", "TRACKING",
81 "RING_FOUND", "STREAMING_RING_FOUND",
82 "HOUGH_RING_FOUND",
83 "START_OF_SPILL", "UNKNOWN"};
84
86constexpr int n_default_triggers = std::size(all_default_triggers);
88
95{
96 for (int i = 0; i < n_default_triggers; ++i)
97 if (all_default_triggers[i] == t)
98 return i;
99 return -1;
100}
101
102// ============================================================
103// Data structs
104// ============================================================
105
114{
115 uint8_t index;
116 uint16_t coarse;
117 float fine_time;
118
119 trigger_event() = default;
120
125 trigger_event(uint8_t idx)
126 : index(idx), coarse(0), fine_time(0.f) {}
127
133 trigger_event(uint8_t idx, uint16_t crs)
134 : index(idx), coarse(crs), fine_time(0.f) {}
135
142 trigger_event(uint8_t idx, uint16_t crs, float fine)
143 : index(idx), coarse(crs), fine_time(fine) {}
144};
145
153{
154 std::string name;
155 uint8_t index;
156 uint16_t delay;
157 uint16_t device;
158
159 trigger_config() = default;
160
168 trigger_config(const std::string &_name,
169 uint8_t _index,
170 uint16_t _delay,
171 uint16_t _device)
172 : name(_name), index(_index), delay(_delay), device(_device) {}
173};
174
175// ============================================================
176// Runtime trigger registry
177// ============================================================
178
187{
189 std::vector<std::pair<uint8_t, std::string>> triggers;
190
191 trigger_registry() = default;
192
202 explicit trigger_registry(const std::vector<trigger_config> &config_triggers)
203 {
204 for (const auto &t : config_triggers)
205 triggers.push_back({t.index, t.name});
206 for (int i = 0; i < n_default_triggers; ++i)
207 triggers.push_back({all_default_triggers[i], default_names[i]});
208 }
209
219 int index_of(uint8_t trigger_value) const
220 {
221 for (int i = 0; i < static_cast<int>(triggers.size()); ++i)
222 if (triggers[i].first == trigger_value)
223 return i;
224
225 std::cerr << "[WARN] trigger_registry: unknown trigger value "
226 << static_cast<int>(trigger_value)
227 << " — falling back to UNKNOWN\n";
229 }
230
236 std::string name_of(uint8_t trigger_value) const
237 {
238 return triggers[index_of(trigger_value)].second;
239 }
240
242 int size() const { return static_cast<int>(triggers.size()); }
243
252 void label_axes(TH2F *h) const
253 {
254 for (int i = 0; i < static_cast<int>(triggers.size()); ++i)
255 {
256 h->GetXaxis()->SetBinLabel(i + 1, triggers[i].second.c_str());
257 h->GetYaxis()->SetBinLabel(i + 1, triggers[i].second.c_str());
258 }
259 }
260};
261
262// ============================================================
263// TOML config reader
264// ============================================================
265
293inline std::vector<trigger_config>
294trigger_conf_reader(const std::string &config_file = "Data/triggers.toml")
295{
296 std::vector<trigger_config> triggers;
297
298 toml::table tbl;
299 try
300 {
301 tbl = toml::parse_file(config_file);
302 }
303 catch (const toml::parse_error &e)
304 {
305 std::cerr << "[ERROR] Failed to parse trigger config \"" << config_file
306 << "\": " << e.description() << "\n";
307 return triggers;
308 }
309
310 std::cout << "[INFO] Loaded trigger config: " << config_file << "\n";
311
312 auto arr = tbl.get_as<toml::array>("trigger");
313 if (!arr)
314 {
315 std::cerr << "[WARN] No [[trigger]] entries found in \"" << config_file << "\"\n";
316 return triggers;
317 }
318
319 // Tracks which indices in [0, 99] are already claimed.
320 // Flat bool array: O(1) insert/lookup, trivially sized for 100 slots.
321 bool used_indices[100] = {};
322
323 // Returns the earliest free slot in [0, 99], or -1 if all are taken.
324 auto earliest_free = [&]() -> int
325 {
326 for (int i = 0; i < 100; ++i)
327 if (!used_indices[i])
328 return i;
329 return -1;
330 };
331
332 for (const auto &node : *arr)
333 {
334 const auto *entry = node.as_table();
335 if (!entry)
336 continue;
337
338 // Validate all required keys are present
339 if (!entry->contains("name") || !entry->contains("index") ||
340 !entry->contains("device") || !entry->contains("delay"))
341 {
342 std::cerr << "[WARN] Skipping incomplete [[trigger]] entry (missing required key)\n";
343 continue;
344 }
345
346 trigger_config cfg;
347 cfg.name = entry->at("name").value_or(std::string{});
348 uint16_t raw_index = static_cast<uint16_t>(entry->at("index").value_or(0));
349 cfg.device = static_cast<uint16_t>(entry->at("device").value_or(0));
350 cfg.delay = static_cast<uint16_t>(entry->at("delay").value_or(0));
351
352 // Enforce [0, 99] index range — [100, 255] is reserved for built-in triggers.
353 // Also catches duplicates: an already-used in-range index is treated the same
354 // as an out-of-range one and gets reassigned to the earliest free slot.
355 bool out_of_range = raw_index > 99;
356 bool duplicate = !out_of_range && used_indices[raw_index];
357
358 if (out_of_range || duplicate)
359 {
360 int free_slot = earliest_free();
361 if (free_slot == -1)
362 {
363 std::cerr << "[ERROR] \"" << cfg.name << "\""
364 << (duplicate ? " has duplicate index " : " has out-of-range index ")
365 << raw_index
366 << " and no free slot remains in [0, 99] — entry dropped\n";
367 continue;
368 }
369
370 std::cerr << "[WARN] \"" << cfg.name << "\""
371 << (duplicate ? " has duplicate index " : " has out-of-range index ")
372 << raw_index << " (valid range: 0-99, unique)"
373 << " — reassigned to earliest available index " << free_slot << "\n";
374 raw_index = static_cast<uint16_t>(free_slot);
375 }
376
377 cfg.index = static_cast<uint8_t>(raw_index);
378 used_indices[cfg.index] = true;
379 triggers.push_back(cfg);
380
381 std::cout << "[INFO] " << cfg.name
382 << " | index=" << static_cast<int>(cfg.index)
383 << " | device=" << cfg.device
384 << " | delay=" << cfg.delay << "\n";
385 }
386
387 return triggers;
388}
Static configuration for a single trigger channel, loaded from TOML.
Definition triggers.h:153
uint8_t index
Trigger index in [0, 99] used in the data stream.
Definition triggers.h:155
std::string name
Human-readable trigger label (e.g. "luca_and_finger")
Definition triggers.h:154
uint16_t delay
Delay applied to this trigger channel (DAQ units)
Definition triggers.h:156
uint16_t device
Hardware device ID that produces this trigger.
Definition triggers.h:157
trigger_config(const std::string &_name, uint8_t _index, uint16_t _delay, uint16_t _device)
Construct from all fields.
Definition triggers.h:168
Per-event trigger data attached to a decoded data frame.
Definition triggers.h:114
float fine_time
Fine timestamp correction (ns)
Definition triggers.h:117
uint8_t index
Hardware trigger index.
Definition triggers.h:115
uint16_t coarse
Coarse timestamp (DAQ clock ticks)
Definition triggers.h:116
trigger_event(uint8_t idx)
Construct with index only; timestamps default to zero.
Definition triggers.h:125
trigger_event(uint8_t idx, uint16_t crs, float fine)
Construct with all fields.
Definition triggers.h:142
trigger_event(uint8_t idx, uint16_t crs)
Construct with index and coarse timestamp.
Definition triggers.h:133
Runtime lookup table that maps trigger values to names and positions.
Definition triggers.h:187
std::string name_of(uint8_t trigger_value) const
Returns the name associated with a trigger value.
Definition triggers.h:236
int index_of(uint8_t trigger_value) const
Returns the registry position for a given trigger value.
Definition triggers.h:219
trigger_registry(const std::vector< trigger_config > &config_triggers)
Build the registry from a list of config-defined triggers.
Definition triggers.h:202
int size() const
Definition triggers.h:242
void label_axes(TH2F *h) const
Labels both axes of a 2D ROOT histogram with trigger names.
Definition triggers.h:252
std::vector< std::pair< uint8_t, std::string > > triggers
Ordered list of {trigger value, name} pairs.
Definition triggers.h:189
constexpr int default_trigger_index(trigger_number t)
Returns the index of a trigger in the default table at compile time.
Definition triggers.h:94
std::vector< trigger_config > trigger_conf_reader(const std::string &config_file="Data/triggers.toml")
Reads trigger configuration from a TOML file.
Definition triggers.h:294
trigger_number
Enumeration of known hardware trigger types.
Definition triggers.h:55
@ _TRIGGER_FIRST_FRAMES_
First frames of a run.
Definition triggers.h:56
@ _TRIGGER_RING_FOUND_
Ring-finding trigger.
Definition triggers.h:59
@ _TRIGGER_HOUGH_RING_FOUND_
Hough-transform ring-finding trigger.
Definition triggers.h:61
@ _TRIGGER_TIMING_
Timing trigger.
Definition triggers.h:57
@ _TRIGGER_STREAMING_RING_FOUND_
Streaming ring-finding trigger.
Definition triggers.h:60
@ _TRIGGER_TRACKING_
Tracking trigger.
Definition triggers.h:58
@ _TRIGGER_UNKNOWN_
Unknown / unmapped trigger.
Definition triggers.h:63
@ _TRIGGER_START_OF_SPILL_
Start-of-spill signal.
Definition triggers.h:62