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 m.add_function(wrap_pyfunction!(start_run, m)?)?;
179 m.add_function(wrap_pyfunction!(stop_run, m)?)?;
180 m.add_function(wrap_pyfunction!(restart_liftofrb, m)?)?;
181 m.add_function(wrap_pyfunction!(enable_verification_run, m)?)?;
182 m.add_function(wrap_pyfunction!(shutdown_all_rbs, m)?)?;
183 m.add_function(wrap_pyfunction!(shutdown_rat, m)?)?;
184 m.add_function(wrap_pyfunction!(shutdown_ratpair, m)?)?;
185 m.add_function(wrap_pyfunction!(shutdown_rb, m)?)?;
186 m.add_function(wrap_pyfunction!(shutdown_tofcpu, m)?)?;
187
188
189
190 Ok(())
191}
192
193#[cfg(feature="pybindings")]
194#[pymodule]
195#[pyo3(name = "tracker")]
196fn tracker_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
197 use crate::tracker::*;
198 m.add_function(wrap_pyfunction!(strip_lines, m)?)?;
200 Ok(())
201}
202
203#[cfg(feature="pybindings")]
204#[pymodule]
205#[pyo3(name = "calibration")]
206fn calibration_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
207 use crate::calibration::tof::*;
208 m.add_class::<RBCalibrations>()?;
209 Ok(())
210}
211
212#[cfg(feature="pybindings")]
213#[pymodule]
214#[pyo3(name = "events")]
215fn events_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
216 use crate::events::*;
217 m.add_class::<TofHit>()?;
218 m.add_class::<TrackerHit>()?;
219 m.add_class::<RBEventHeader>()?;
220 m.add_class::<RBEvent>()?;
221 m.add_class::<RBWaveform>()?;
222 m.add_class::<EventStatus>()?;
223 m.add_class::<DataType>()?;
224 m.add_class::<TofEvent>()?;
225 m.add_class::<TelemetryEvent>()?;
226 m.add_function(wrap_pyfunction!(strip_id, m)?)?;
227 m.add_class::<EventQuality>()?;
228 m.add_class::<TriggerType>()?;
229 m.add_class::<LTBThreshold>()?;
230 m.add_function(wrap_pyfunction!(mt_event_get_timestamp_abs48,m)?)?;
231 Ok(())
232}
233
234#[cfg(feature="pybindings")]
235#[pymodule]
236#[pyo3(name = "packets")]
237fn packets_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
238 use crate::packets::*;
239 m.add_class::<TofPacketType>()?;
240 m.add_class::<TofPacket>()?;
241 m.add_class::<TelemetryPacketType>()?;
242 m.add_class::<TelemetryPacket>()?;
243 m.add_class::<TelemetryPacketHeader>()?;
244 m.add_class::<TrackerHeader>()?;
245 m.add_function(wrap_pyfunction!(make_systime,m)?)?;
246 Ok(())
247}
248
249#[cfg(feature="pybindings")]
250#[pymodule]
251#[pyo3(name = "io")]
252fn io_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
253 use crate::io::*;
254 use crate::io::caraspace::*;
255 #[cfg(feature="root")]
256 use crate::io::root_reader::read_example;
257 use crate::io::caraspace::frame::get_all_telemetry_event_names;
258 #[cfg(feature="root")]
259 m.add_function(wrap_pyfunction!(read_example, m)?)?;
260 m.add_function(wrap_pyfunction!(get_all_telemetry_event_names, m)?)?;
261 m.add_function(wrap_pyfunction!(get_runfilename, m)?)?;
262 m.add_function(wrap_pyfunction!(get_califilename, m)?)?;
263 m.add_function(wrap_pyfunction!(list_path_contents_sorted_py, m)?)?;
264 m.add_function(wrap_pyfunction!(get_utc_timestamp, m)?)?;
265 m.add_function(wrap_pyfunction!(get_utc_date, m)?)?;
266 m.add_function(wrap_pyfunction!(get_rundata_from_file, m)?)?;
267 m.add_function(wrap_pyfunction!(get_datetime, m)?)?;
268 m.add_function(wrap_pyfunction!(get_unix_timestamp, m)?)?;
269 m.add_function(wrap_pyfunction!(get_unix_timestamp_from_telemetry, m)?)?;
270 m.add_class::<CRFrameObject>()?;
271 m.add_class::<CRFrameObjectType>()?;
272 m.add_class::<CRFrame>()?;
273 m.add_class::<DataSourceKind>()?;
274 m.add_class::<CRReader>()?;
275 m.add_class::<CRWriter>()?;
276 m.add_class::<TofPacketReader>()?;
277 m.add_class::<TelemetryPacketReader>()?;
278 Ok(())
280}
281
282#[cfg(feature="pybindings")]
283#[pymodule]
284#[pyo3(name = "monitoring")]
285fn monitoring_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
286 use crate::monitoring::*;
287 m.add_class::<EventBuilderHB>()?;
288 m.add_class::<EventBuilderHBSeries>()?;
289 m.add_class::<DataSinkHB>()?;
290 m.add_class::<DataSinkHBSeries>()?;
291 m.add_class::<MasterTriggerHB>()?;
292 m.add_class::<MasterTriggerHBSeries>()?;
293 m.add_class::<PAMoniData>()?;
294 m.add_class::<PAMoniDataSeries>()?;
295 m.add_class::<PBMoniData>()?;
296 m.add_class::<PBMoniDataSeries>()?;
297 m.add_class::<MtbMoniData>()?;
298 m.add_class::<MtbMoniDataSeries>()?;
299 m.add_class::<LTBMoniData>()?;
300 m.add_class::<LTBMoniDataSeries>()?;
301 m.add_class::<RBMoniData>()?;
302 m.add_class::<RBMoniDataSeries>()?;
303 m.add_class::<CPUMoniData>()?;
304 m.add_class::<CPUMoniDataSeries>()?;
305 m.add_class::<RunStatistics>()?;
306 Ok(())
307}
308
309#[cfg(feature="pybindings")]
310#[pymodule]
311#[pyo3(name = "stats")]
312fn stats_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
313 use crate::stats::py_gamma_pdf;
315 m.add_function(wrap_pyfunction!(py_gamma_pdf, m)?)?;
316 Ok(())
317}
318
319#[cfg(feature="pybindings")]
320#[pymodule]
321#[pyo3(name = "algo")]
322fn algo_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
323 use crate::tof::algorithms::*;
325 m.add_function(wrap_pyfunction!(get_max_value_idx_py, m)?)?;
326 m.add_function(wrap_pyfunction!(interpolate_time_py, m)?)?;
327 m.add_function(wrap_pyfunction!(fit_sine_simple_py, m)?)?;
328 Ok(())
329}
330
331#[cfg(feature="database")]
332#[cfg(feature="pybindings")]
333#[pymodule]
334#[pyo3(name = "db")]
335fn db_py<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
336 use crate::database::*;
337 m.add_class::<TofPaddle>()?;
338 m.add_class::<ReadoutBoard>()?;
339 m.add_class::<TrackerStrip>()?;
340 m.add_class::<TrackerStripMask>()?;
341 m.add_class::<TrackerStripPedestal>()?;
342 m.add_class::<TrackerStripTransferFunction>()?;
343 m.add_class::<TrackerStripCmnNoise>()?;
344 m.add_function(wrap_pyfunction!(get_all_rbids_in_db, m)?)?;
345 m.add_function(wrap_pyfunction!(get_hid_vid_map, m)?)?;
346 m.add_function(wrap_pyfunction!(get_vid_hid_map, m)?)?;
347 m.add_function(wrap_pyfunction!(get_dsi_j_ch_pid_map_py, m)?)?;
348 Ok(())
349}
350
351#[cfg(feature="pybindings")]
352#[pyfunction]
353fn get_version() -> &'static str {
354 return VERSION;
355}
356
357#[cfg(feature="pybindings")]
362#[pymodule]
363#[pyo3(name = "gondola_core")]
364fn gondola_core_py<'_py>(m : &Bound<'_py, PyModule>) -> PyResult<()> { pyo3_log::init();
366 m.add_function(wrap_pyfunction!(get_version, m)?)?;
367 m.add_wrapped(wrap_pymodule!(events_py))?;
368 m.add_wrapped(wrap_pymodule!(monitoring_py))?;
369 m.add_wrapped(wrap_pymodule!(packets_py))?;
370 m.add_wrapped(wrap_pymodule!(tof_py))?;
371 m.add_wrapped(wrap_pymodule!(tracker_py))?;
372 m.add_wrapped(wrap_pymodule!(io_py))?;
373 m.add_wrapped(wrap_pymodule!(db_py))?;
374 m.add_wrapped(wrap_pymodule!(stats_py))?;
375 m.add_wrapped(wrap_pymodule!(algo_py))?;
376 m.add_wrapped(wrap_pymodule!(calibration_py))?;
377 Ok(())
378}