1pub mod tof_hit;
5pub use tof_hit::TofHit;
6
7pub mod rb_waveform;
8pub use rb_waveform::RBWaveform;
9
10pub mod rb_event_header;
11pub use rb_event_header::RBEventHeader;
12
13pub mod tof_event;
14pub use tof_event::TofEvent;
15
16pub mod rb_event;
17pub use rb_event::{
18 RBEvent,
19 unpack_traces
20};
21
22pub mod tracker_hit;
23pub use tracker_hit::TrackerHit;
24
25pub mod tracker_daq_event;
26pub use tracker_daq_event::TrackerDAQEvent;
27
28pub mod tracker_daq_event_packet;
29pub use tracker_daq_event_packet::TrackerDAQEventPacket;
30
31pub mod telemetry_event;
32pub use telemetry_event::TelemetryEvent;
33
34pub mod mc_hit;
35pub use mc_hit::McHit;
36
37pub mod mc_track;
38pub use mc_track::McTrack;
39
40pub mod mc_event;
41pub use mc_event::McEvent;
42
43pub mod mc_tree;
44pub use mc_tree::McTree;
45
46use std::fmt;
47
48use strum_macros::{
49 AsRefStr,
50 FromRepr,
51 EnumIter
52};
53#[cfg(feature="random")]
56use strum::IntoEnumIterator;
57use crate::expand_and_test_enum;
58
59#[cfg(feature="pybindings")]
60use pyo3::prelude::*;
61
62#[cfg(feature="random")]
63use crate::random::FromRandom;
64#[cfg(feature="random")]
65use rand::Rng;
66
67pub const LTB_CH0 : u16 = 0x3 ;
69pub const LTB_CH1 : u16 = 0xc ;
71pub const LTB_CH2 : u16 = 0x30 ;
73pub const LTB_CH3 : u16 = 0xc0 ;
75pub const LTB_CH4 : u16 = 0x300 ;
77pub const LTB_CH5 : u16 = 0xc00 ;
79pub const LTB_CH6 : u16 = 0x3000;
81pub const LTB_CH7 : u16 = 0xc000;
83pub const LTB_CHANNELS : [u16;8] = [
85 LTB_CH0,
86 LTB_CH1,
87 LTB_CH2,
88 LTB_CH3,
89 LTB_CH4,
90 LTB_CH5,
91 LTB_CH6,
92 LTB_CH7
93];
94
95pub const PHYSICAL_CHANNELS : [(u8, u8); 8] = [(1u8, 2u8), (3u8,4u8), (5u8, 6u8), (7u8, 8u8),
97 (9u8, 10u8), (11u8,12u8), (13u8, 14u8), (15u8, 16u8)];
98
99
100#[cfg_attr(feature="pybindings", pyfunction)]
111pub fn strip_id(layer : u8, row :u8, module : u8, channel : u8) -> u32 {
112 channel as u32 + (module as u32)*100 + (row as u32)*10000 + (layer as u32)*100000
113}
114
115#[cfg_attr(feature="pybindings", pyfunction)]
118pub fn mt_event_get_timestamp_abs48(mtb_timestamp : u32, gps_timestamp : u32, tiu_timestamp : u32) -> u64 {
119 let gps = gps_timestamp as u64;
120 let mut timestamp = mtb_timestamp as u64;
121 if timestamp < tiu_timestamp as u64 {
122 timestamp += u32::MAX as u64 + 1;
124 }
125 let gps_mult = match 100_000_000u64.checked_mul(gps) {
126 Some(result) => result,
128 None => {
129 0 }
133 };
134
135 let ts = gps_mult + (timestamp - tiu_timestamp as u64);
136 ts
137}
138
139#[derive(Debug, Copy, Clone, PartialEq,FromRepr, AsRefStr, EnumIter)]
140#[repr(u8)]
141#[cfg_attr(feature = "pybindings", pyclass(eq, eq_int))]
142pub enum EventQuality {
143 Unknown = 0u8,
144 Silver = 10u8,
145 Gold = 20u8,
146 Diamond = 30u8,
147 FourLeafClover = 40u8,
148}
149
150expand_and_test_enum!(EventQuality, test_eventquality_repr);
151
152#[derive(Debug, Copy, Clone, PartialEq,FromRepr, AsRefStr, EnumIter)]
155#[repr(u8)]
156#[cfg_attr(feature = "pybindings", pyclass(eq, eq_int))]
157pub enum HitQuality {
158 Unknown = 0,
160 Mangled = 1,
162 MissingHit = 2,
163 LowPedPlusPedRMS = 3, LowRMSgrThree = 4, LowElenaCuts = 5, Low = 10, MidPedRMS = 11, MidPos = 12, MidPedRMSandPos = 13, MidPosSat = 14, MidPosSatReprocess= 15,
174 MidPosReprocess = 16,
175 Mid = 20, HighSat = 21, High = 30, ReprocessHighSat = 31,
183 ReprocessHigh = 40,
184 }
186
187expand_and_test_enum!(HitQuality, test_hitquality_repr);
188
189#[derive(Debug, Copy, Clone, PartialEq,FromRepr, AsRefStr, EnumIter, serde::Serialize, serde::Deserialize)]
198#[repr(u8)]
199#[cfg_attr(feature = "pybindings", pyclass(eq, eq_int))]
200pub enum TriggerType {
201 Unknown = 0u8,
202 Any = 1u8,
204 Track = 2u8,
206 TrackCentral = 3u8,
207 Gaps = 4u8,
212 Gaps633 = 5u8,
213 Gaps422 = 6u8,
214 Gaps211 = 7u8,
215 TrackUmbCentral = 8u8,
216 Gaps1044 = 9u8,
217 UmbCube = 21u8,
220 UmbCubeZ = 22u8,
222 UmbCorCube = 23u8,
224 CorCubeSide = 24u8,
226 Umb3Cube = 25u8,
228 Poisson = 100u8,
230 Forced = 101u8,
231 FixedRate = 102u8,
232 ConfigurableTrigger = 200u8,
236}
237
238impl TriggerType {
239
240 pub fn transcode_trigger_sources(trigger_sources : u16) -> Vec<Self> {
243 let mut t_types = Vec::<Self>::new();
244 let gaps_trigger = trigger_sources >> 5 & 0x1 == 1;
245 if gaps_trigger {
246 t_types.push(TriggerType::Gaps);
247 }
248 let any_trigger = trigger_sources >> 6 & 0x1 == 1;
249 if any_trigger {
250 t_types.push(TriggerType::Any);
251 }
252 let forced_trigger = trigger_sources >> 7 & 0x1 == 1;
253 if forced_trigger {
254 t_types.push(TriggerType::Forced);
255 }
256 let track_trigger = trigger_sources >> 8 & 0x1 == 1;
257 if track_trigger {
258 t_types.push(TriggerType::Track);
259 }
260 let central_track_trigger
261 = trigger_sources >> 9 & 0x1 == 1;
262 if central_track_trigger {
263 t_types.push(TriggerType::TrackCentral);
264 }
265 t_types
266 }
267
268 pub fn to_u8(&self) -> u8 {
269 match self {
270 TriggerType::Unknown => {
271 return 0;
272 }
273 TriggerType::Poisson => {
274 return 100;
275 }
276 TriggerType::Forced => {
277 return 101;
278 }
279 TriggerType::FixedRate => {
280 return 102;
281 }
282 TriggerType::Any => {
283 return 1;
284 }
285 TriggerType::Track => {
286 return 2;
287 }
288 TriggerType::TrackCentral => {
289 return 3;
290 }
291 TriggerType::Gaps => {
292 return 4;
293 }
294 TriggerType::Gaps633 => {
295 return 5;
296 }
297 TriggerType::Gaps422 => {
298 return 6;
299 }
300 TriggerType::Gaps211 => {
301 return 7;
302 }
303 TriggerType::TrackUmbCentral => {
304 return 8;
305 }
306 TriggerType::Gaps1044 => {
307 return 9;
308 }
309 TriggerType::UmbCube => {
310 return 21;
311 }
312 TriggerType::UmbCubeZ => {
313 return 22;
314 }
315 TriggerType::UmbCorCube => {
316 return 23;
317 }
318 TriggerType::CorCubeSide => {
319 return 24;
320 }
321 TriggerType::Umb3Cube => {
322 return 25;
323 }
324 TriggerType::ConfigurableTrigger => {
325 return 200;
326 }
327 }
328 }
329}
330
331#[cfg(feature="pybindings")]
332#[pymethods]
333impl TriggerType {
334 #[staticmethod]
335 #[pyo3(name="transcode_trigger_sources")]
336 fn transcode_trigger_sources_py(trigger_sources : u16) -> Vec<Self> {
337 TriggerType::transcode_trigger_sources(trigger_sources)
338 }
339}
340
341expand_and_test_enum!(TriggerType, test_triggertype_repr);
342
343#[derive(Debug, Copy, Clone, PartialEq,FromRepr, AsRefStr, EnumIter)]
348#[cfg_attr(feature = "pybindings", pyclass(eq, eq_int))]
349#[repr(u8)]
350pub enum LTBThreshold {
351 NoHit = 0u8,
352 Hit = 1u8,
354 Beta = 2u8,
356 Veto = 3u8,
358 Unknown = 255u8
361}
362
363expand_and_test_enum!(LTBThreshold, test_ltbthreshold_repr);
364
365#[derive(Debug, Copy, Clone, PartialEq, Hash, Eq, FromRepr, AsRefStr, EnumIter)]
368#[repr(u8)]
369#[cfg_attr(feature = "pybindings", pyclass(eq, eq_int))]
370pub enum EventStatus {
371 Unknown = 0u8,
372 CRC32Wrong = 10u8,
373 TailWrong = 11u8,
374 ChannelIDWrong = 12u8,
375 CellSyncErrors = 13u8,
378 ChnSyncErrors = 14u8,
381 CellAndChnSyncErrors = 15u8,
384 AnyDataMangling = 16u8,
387 KnownDeadRB = 17u8,
391 IncompleteReadout = 21u8,
392 IncompatibleData = 22u8,
395 EventTimeOut = 23u8,
397 NoChannel9 = 24u8,
399 RBEventWacky = 25u8,
401 GoodNoCRCOrErrBitCheck = 39u8,
402 GoodNoCRCCheck = 40u8,
405 GoodNoErrBitCheck = 41u8,
408 Perfect = 42u8
409}
410
411#[cfg(feature = "pybindings")]
415#[pymethods]
416impl EventStatus {
417
418 #[getter]
419 fn __hash__(&self) -> usize {
420 (*self as u8) as usize
421 }
422}
423
424
425expand_and_test_enum!(EventStatus, test_eventstatus_repr);
426
427#[derive(Debug, Copy, Clone, PartialEq,FromRepr, AsRefStr, EnumIter, serde::Deserialize, serde::Serialize)]
434#[cfg_attr(feature = "pybindings", pyclass(eq, eq_int))]
435#[repr(u8)]
436pub enum DataType {
437 Unknown = 0u8,
438 VoltageCalibration = 10u8,
439 TimingCalibration = 20u8,
440 Noi = 30u8,
441 Physics = 40u8,
442 RBTriggerPeriodic = 50u8,
443 RBTriggerPoisson = 60u8,
444 MTBTriggerPoisson = 70u8,
445 }
447
448expand_and_test_enum!(DataType, test_datatype_repr);
449
450