1#[macro_use] extern crate log;
36
37pub mod prelude;
38#[cfg(feature="random")]
39pub mod random;
40pub mod constants;
41pub mod events;
42pub mod packets;
43pub mod version;
44pub mod io;
45pub mod calibration;
46pub mod errors;
47pub mod tof;
48pub mod tracker;
49pub mod monitoring;
50pub mod stats;
51#[cfg(feature="pybindings")]
52pub mod python;
53#[cfg(feature="database")]
54pub mod database;
55
56pub const VERSION: &str = env!("CARGO_PKG_VERSION");
58
59#[macro_export]
64macro_rules! expand_and_test_enum {
65 ($name:ident, $test_name:ident) => {
66 impl fmt::Display for $name {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 write!(f, "<{}: {}>",stringify!($name), self.as_ref())
69 }
70 }
71
72 impl From<u8> for $name {
73 fn from(value: u8) -> Self {
74 match Self::from_repr(value) {
75 None => {
76 return Self::Unknown;
77 }
78 Some(variant) => {
79 return variant;
80 }
81 }
82 }
83 }
84
85 #[cfg(feature="random")]
86 impl FromRandom for $name {
87 fn from_random() -> Self {
88 let mut choices = Vec::<Self>::new();
89 for k in Self::iter() {
90 choices.push(k);
91 }
92 let mut rng = rand::rng();
93 let idx = rng.random_range(0..choices.len());
94 choices[idx]
95 }
96 }
97
98 #[test]
99 fn $test_name() {
100 for _ in 0..100 {
101 let data = $name::from_random();
102 assert_eq!($name::from(data as u8), data);
103 }
104 }
105 };
106}
107
108use colored::{
113 Colorize,
114 ColoredString
115};
116use chrono::Utc;
117use log::Level;
118use std::io::Write;
119
120pub fn color_log(level : &Level) -> ColoredString {
122 match level {
123 Level::Error => String::from(" ERROR!").red(),
124 Level::Warn => String::from(" WARN ").yellow(),
125 Level::Info => String::from(" Info ").green(),
126 Level::Debug => String::from(" debug ").blue(),
127 Level::Trace => String::from(" trace ").cyan(),
128 }
129}
130
131pub fn init_env_logger() {
137 env_logger::builder()
138 .format(|buf, record| {
139 writeln!( buf, "[{ts} - {level}][{module_path}:{line}] {args}",
140 ts = Utc::now().format("%Y/%m/%d-%H:%M:%SUTC"),
141 level = color_log(&record.level()),
142 module_path = record.module_path().unwrap_or("<unknown>"),
143 line = record.line().unwrap_or(0),
144 args = record.args()
145 )
146 }).init();
147}
148
149#[cfg(feature="pybindings")]
153pub use pyo3::prelude::*;
154#[cfg(feature="pybindings")]
155pub use pyo3::wrap_pymodule;
156#[cfg(feature="pybindings")]
157pub use pyo3::wrap_pyfunction;
158
159#[cfg(feature="pybindings")]
160#[pymodule]
161#[pyo3(name = "tof")]
162fn tof_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
163 use crate::tof::*;
164 m.add_class::<RBPaddleID>()?;
165 m.add_class::<TofDetectorStatus>()?;
166 m.add_class::<TofCommandCode>()?;
167 m.add_class::<TofCommand>()?;
168 m.add_class::<TofOperationMode>()?;
169 m.add_class::<BuildStrategy>()?;
170 m.add_class::<PreampBiasConfig>()?;
171 m.add_class::<RBChannelMaskConfig>()?;
172 m.add_class::<TriggerConfig>()?;
173 m.add_class::<TofRunConfig>()?;
174 m.add_class::<TofCuts>()?;
175 m.add_class::<PyMasterTrigger>()?;
176 m.add_function(wrap_pyfunction!(to_board_id_string, m)?)?;
177 Ok(())
178}
179
180#[cfg(feature="pybindings")]
181#[pymodule]
182#[pyo3(name = "tracker")]
183fn tracker_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
184 use crate::tracker::*;
185 m.add_function(wrap_pyfunction!(strip_lines, m)?)?;
187 Ok(())
188}
189
190#[cfg(feature="pybindings")]
191#[pymodule]
192#[pyo3(name = "calibration")]
193fn calibration_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
194 use crate::calibration::tof::*;
195 m.add_class::<RBCalibrations>()?;
196 Ok(())
197}
198
199#[cfg(feature="pybindings")]
200#[pymodule]
201#[pyo3(name = "events")]
202fn events_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
203 use crate::events::*;
204 m.add_class::<TofHit>()?;
205 m.add_class::<TrackerHit>()?;
206 m.add_class::<RBEventHeader>()?;
207 m.add_class::<RBEvent>()?;
208 m.add_class::<RBWaveform>()?;
209 m.add_class::<EventStatus>()?;
210 m.add_class::<DataType>()?;
211 m.add_class::<TofEvent>()?;
212 m.add_class::<TelemetryEvent>()?;
213 m.add_function(wrap_pyfunction!(strip_id, m)?)?;
214 m.add_class::<EventQuality>()?;
215 m.add_class::<TriggerType>()?;
216 m.add_class::<LTBThreshold>()?;
217 m.add_function(wrap_pyfunction!(mt_event_get_timestamp_abs48,m)?)?;
218 Ok(())
219}
220
221#[cfg(feature="pybindings")]
222#[pymodule]
223#[pyo3(name = "packets")]
224fn packets_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
225 use crate::packets::*;
226 m.add_class::<TofPacketType>()?;
227 m.add_class::<TofPacket>()?;
228 m.add_class::<TelemetryPacketType>()?;
229 m.add_class::<TelemetryPacket>()?;
230 m.add_class::<TelemetryPacketHeader>()?;
231 m.add_class::<TrackerHeader>()?;
232 m.add_function(wrap_pyfunction!(make_systime,m)?)?;
233 Ok(())
234}
235
236#[cfg(feature="pybindings")]
237#[pymodule]
238#[pyo3(name = "io")]
239fn io_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
240 use crate::io::*;
241 use crate::io::caraspace::*;
242 #[cfg(feature="root")]
243 use crate::io::root_reader::read_example;
244 use crate::io::caraspace::frame::get_all_telemetry_event_names;
245 #[cfg(feature="root")]
246 m.add_function(wrap_pyfunction!(read_example, m)?)?;
247 m.add_function(wrap_pyfunction!(get_all_telemetry_event_names, m)?)?;
248 m.add_function(wrap_pyfunction!(get_runfilename, m)?)?;
249 m.add_function(wrap_pyfunction!(get_califilename, m)?)?;
250 m.add_function(wrap_pyfunction!(list_path_contents_sorted_py, m)?)?;
251 m.add_function(wrap_pyfunction!(get_utc_timestamp, m)?)?;
252 m.add_function(wrap_pyfunction!(get_utc_date, m)?)?;
253 m.add_function(wrap_pyfunction!(get_rundata_from_file, m)?)?;
254 m.add_function(wrap_pyfunction!(get_datetime, m)?)?;
255 m.add_function(wrap_pyfunction!(get_unix_timestamp, m)?)?;
256 m.add_function(wrap_pyfunction!(get_unix_timestamp_from_telemetry, m)?)?;
257 m.add_class::<CRFrameObject>()?;
258 m.add_class::<CRFrameObjectType>()?;
259 m.add_class::<CRFrame>()?;
260 m.add_class::<DataSourceKind>()?;
261 m.add_class::<CRReader>()?;
262 m.add_class::<CRWriter>()?;
263 m.add_class::<TofPacketReader>()?;
264 m.add_class::<TelemetryPacketReader>()?;
265 Ok(())
267}
268
269#[cfg(feature="pybindings")]
270#[pymodule]
271#[pyo3(name = "monitoring")]
272fn monitoring_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
273 use crate::monitoring::*;
274 m.add_class::<EventBuilderHB>()?;
275 m.add_class::<EventBuilderHBSeries>()?;
276 m.add_class::<DataSinkHB>()?;
277 m.add_class::<DataSinkHBSeries>()?;
278 m.add_class::<MasterTriggerHB>()?;
279 m.add_class::<MasterTriggerHBSeries>()?;
280 m.add_class::<PAMoniData>()?;
281 m.add_class::<PAMoniDataSeries>()?;
282 m.add_class::<PBMoniData>()?;
283 m.add_class::<PBMoniDataSeries>()?;
284 m.add_class::<MtbMoniData>()?;
285 m.add_class::<MtbMoniDataSeries>()?;
286 m.add_class::<LTBMoniData>()?;
287 m.add_class::<LTBMoniDataSeries>()?;
288 m.add_class::<RBMoniData>()?;
289 m.add_class::<RBMoniDataSeries>()?;
290 m.add_class::<CPUMoniData>()?;
291 m.add_class::<CPUMoniDataSeries>()?;
292 m.add_class::<RunStatistics>()?;
293 Ok(())
294}
295
296#[cfg(feature="pybindings")]
297#[pymodule]
298#[pyo3(name = "stats")]
299fn stats_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
300 use crate::stats::py_gamma_pdf;
302 m.add_function(wrap_pyfunction!(py_gamma_pdf, m)?)?;
303 Ok(())
304}
305
306#[cfg(feature="pybindings")]
307#[pymodule]
308#[pyo3(name = "algo")]
309fn algo_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
310 use crate::tof::algorithms::*;
312 m.add_function(wrap_pyfunction!(get_max_value_idx_py, m)?)?;
313 m.add_function(wrap_pyfunction!(interpolate_time_py, m)?)?;
314 m.add_function(wrap_pyfunction!(fit_sine_simple_py, m)?)?;
315 Ok(())
316}
317
318#[cfg(feature="database")]
319#[cfg(feature="pybindings")]
320#[pymodule]
321#[pyo3(name = "db")]
322fn db_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
323 use crate::database::*;
324 m.add_class::<TofPaddle>()?;
325 m.add_class::<ReadoutBoard>()?;
326 m.add_class::<TrackerStrip>()?;
327 m.add_class::<TrackerStripMask>()?;
328 m.add_class::<TrackerStripPedestal>()?;
329 m.add_class::<TrackerStripTransferFunction>()?;
330 m.add_class::<TrackerStripCmnNoise>()?;
331 m.add_function(wrap_pyfunction!(get_all_rbids_in_db, m)?)?;
332 m.add_function(wrap_pyfunction!(get_hid_vid_map, m)?)?;
333 m.add_function(wrap_pyfunction!(get_vid_hid_map, m)?)?;
334 m.add_function(wrap_pyfunction!(get_dsi_j_ch_pid_map_py, m)?)?;
335 Ok(())
336}
337
338#[cfg(feature="pybindings")]
339#[pyfunction]
340fn get_version() -> &'static str {
341 return VERSION;
342}
343
344#[cfg(feature="pybindings")]
349#[pymodule]
350#[pyo3(name = "gondola_core")]
351fn gondola_core_py<'_py>(m : &Bound<'_py, PyModule>) -> PyResult<()> { pyo3_log::init();
353 m.add_function(wrap_pyfunction!(get_version, m)?)?;
354 m.add_wrapped(wrap_pymodule!(events_py))?;
355 m.add_wrapped(wrap_pymodule!(monitoring_py))?;
356 m.add_wrapped(wrap_pymodule!(packets_py))?;
357 m.add_wrapped(wrap_pymodule!(tof_py))?;
358 m.add_wrapped(wrap_pymodule!(tracker_py))?;
359 m.add_wrapped(wrap_pymodule!(io_py))?;
360 m.add_wrapped(wrap_pymodule!(db_py))?;
361 m.add_wrapped(wrap_pymodule!(stats_py))?;
362 m.add_wrapped(wrap_pymodule!(algo_py))?;
363 m.add_wrapped(wrap_pymodule!(calibration_py))?;
364 Ok(())
365}