1pub mod analysis;
4pub mod io;
5pub mod dataclasses;
6pub mod command_factory;
7#[cfg(feature="telemetry")]
8pub mod telemetry;
9#[cfg(feature="liftof")]
10pub mod liftof;
11#[cfg(feature="liftof")]
12pub mod liftof_dataclasses;
13#[cfg(feature="liftof")]
14pub mod master_trigger;
15#[cfg(feature="caraspace-serial")]
16pub mod caraspace;
17#[cfg(feature="telemetry")]
18use telemetry_dataclasses::packets as tel_api;
19
20use std::env;
21
22use tof_dataclasses::events::EventStatus;
23use tof_dataclasses::commands::config::BuildStrategy;
24
25cfg_if::cfg_if! {
26 if #[cfg(feature = "telemetry")] {
27 use crate::telemetry::{
28 PyTelemetryPacket,
29 PyTelemetryPacketReader,
30 PyMergedEvent,
31 PyTrackerHit,
32 PyTrackerHitV2,
33 PyTrackerEvent,
34 PyTrackerPacket,
35 PyTrackerTempLeakPacket,
36 PyGPSPacket,
37 PyTrackerDAQTempPacket,
38 PyTrackerDAQHSKPacket,
39 PyTrackerEventIDEchoPacket,
40 };
41 }
42}
43
44cfg_if::cfg_if! {
45 if #[cfg(feature = "caraspace-serial")] {
46 use crate::caraspace::{
47 py_parse_u8,
48 py_parse_u16,
49 py_parse_u32,
50 py_parse_u64,
51 PyCRFrame,
52 PyCRReader,
53 PyCRWriter,
54 };
55 }
56}
57
58cfg_if::cfg_if! {
59 if #[cfg(feature = "liftof")] {
60 use crate::liftof::{
61 py_waveform_analysis,
62 wrap_prescale_to_u32,
63 wrap_calc_edep_simple,
64 wrap_fit_sine_sydney,
65 test_db,
66 PyLiftofSettings,
67 PyIPBus,
68 PyMasterTrigger
69 };
70 }
71}
72
73use pyo3::prelude::*;
74use pyo3::wrap_pymodule;
75use pyo3::exceptions::{
76 PyIOError,
77};
78
79use crate::analysis::*;
80use crate::dataclasses::*;
81use crate::io::*;
82use crate::command_factory::*;
83
84use tof_dataclasses::packets::PacketType;
86use tof_dataclasses::commands::TofCommandCode;
87use tof_dataclasses::events::master_trigger::{
88 LTBThreshold,
89 TriggerType
90};
91
92use tof_dataclasses::database::{
94 get_dsi_j_ch_pid_map,
95 DsiJChPidMapping,
96 RbChPidMapping,
97 get_rb_ch_pid_map,
98 get_rb_ch_pid_a_map,
99 get_rb_ch_pid_b_map,
100 Paddle,
101 TrackerStrip,
102 connect_to_db
103};
104
105#[pyfunction]
121#[pyo3(name="create_mtb_connection_to_pid_map")]
122fn py_create_mtb_connection_to_pid_map() -> PyResult<DsiJChPidMapping> {
123 let db_path = env::var("DATABASE_URL").unwrap_or_else(|_| "".to_string());
124 match connect_to_db(db_path) {
125 Err(err) => {
126 return Err(PyIOError::new_err(err.to_string()));
127 }
128 Ok(mut conn) => {
129 match Paddle::all(&mut conn) {
130 None => {
131 return Err(PyIOError::new_err("Unable to retrieve paddle information from DB!"));
132 }
133 Some(paddles) => {
134 let mapping = get_dsi_j_ch_pid_map(&paddles);
135 Ok(mapping)
136 }
137 }
138 }
139 }
140}
141
142#[pyfunction]
151#[pyo3(name="create_rb_ch_to_pid_map")]
152fn py_create_rb_ch_to_pid_map(db_path : String) -> PyResult<RbChPidMapping> {
153 match connect_to_db(db_path) {
154 Err(err) => {
155 return Err(PyIOError::new_err(err.to_string()));
156 }
157 Ok(mut conn) => {
158 match Paddle::all(&mut conn) {
159 None => {
160 return Err(PyIOError::new_err("Unable to retrieve paddle information from DB!"));
161 }
162 Some(paddles) => {
163 let mapping = get_rb_ch_pid_map(&paddles);
164 Ok(mapping)
165 }
166 }
167 }
168 }
169}
170
171#[pyfunction]
180#[pyo3(name="create_rb_ch_to_pid_a_map")]
181fn py_create_rb_ch_to_pid_a_map(db_path : String) -> PyResult<RbChPidMapping> {
182 match connect_to_db(db_path) {
183 Err(err) => {
184 return Err(PyIOError::new_err(err.to_string()));
185 }
186 Ok(mut conn) => {
187 match Paddle::all(&mut conn) {
188 None => {
189 return Err(PyIOError::new_err("Unable to retrieve paddle information from DB!"));
190 }
191 Some(paddles) => {
192 let mapping = get_rb_ch_pid_a_map(&paddles);
193 Ok(mapping)
194 }
195 }
196 }
197 }
198}
199
200
201#[pyfunction]
210#[pyo3(name="create_rb_ch_to_pid_b_map")]
211fn py_create_rb_ch_to_pid_b_map(db_path : String) -> PyResult<RbChPidMapping> {
212 match connect_to_db(db_path) {
213 Err(err) => {
214 return Err(PyIOError::new_err(err.to_string()));
215 }
216 Ok(mut conn) => {
217 match Paddle::all(&mut conn) {
218 None => {
219 return Err(PyIOError::new_err("Unable to retrieve paddle information from DB!"));
220 }
221 Some(paddles) => {
222 let mapping = get_rb_ch_pid_b_map(&paddles);
223 Ok(mapping)
224 }
225 }
226 }
227 }
228}
229
230
231#[pyfunction]
233#[pyo3(name="create_tracker_strip_map")]
234fn py_create_tracker_strip_map(db_path : String) -> PyResult<()> {
235 match connect_to_db(db_path) {
236 Err(err) => {
237 return Err(PyIOError::new_err(err.to_string()));
238 }
239 Ok(mut conn) => {
240 match TrackerStrip::all(&mut conn) {
241 None => {
242 return Err(PyIOError::new_err("Unable to retrieve tracker strip information from DB!"));
243 }
244 Some(strips) => {
245 for k in strips {
248 println!("Strip : {}", k);
249 }
250 Ok(())
251 }
252 }
253 }
254 }
255}
256
257#[pymodule]
258#[pyo3(name = "analysis")]
259fn tof_analysis<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
260 m.add_function(wrap_pyfunction!(py_get_periods, m)?)?;
261 m.add_function(wrap_pyfunction!(py_time2bin,m)?)?;
262 m.add_function(wrap_pyfunction!(py_find_peaks,m)?)?;
263 m.add_function(wrap_pyfunction!(py_find_peaks_zscore,m)?)?;
264 m.add_function(wrap_pyfunction!(py_integrate,m)?)?;
265 m.add_function(wrap_pyfunction!(py_interpolate_time,m)?)?;
266 m.add_function(wrap_pyfunction!(py_cfd_simple,m)?)?;
267 m.add_function(wrap_pyfunction!(py_find_zero_crossings,m)?)?;
268 Ok(())
269}
270
271#[pymodule]
272#[pyo3(name = "moni")]
273fn tof_moni<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
274 m.add_class::<PyPAMoniSeries>()?;
275 m.add_class::<PyPBMoniSeries>()?;
276 m.add_class::<PyRBMoniSeries>()?;
277 m.add_class::<PyMtbMoniSeries>()?;
278 m.add_class::<PyCPUMoniSeries>()?;
279 m.add_class::<PyLTBMoniSeries>()?;
280 m.add_class::<PyRBMoniData>()?;
281 m.add_class::<PyPAMoniData>()?;
282 m.add_class::<PyPBMoniData>()?;
283 m.add_class::<PyLTBMoniData>()?;
284 m.add_class::<PyMtbMoniData>()?;
285 m.add_class::<PyTofDetectorStatus>()?;
286 Ok(())
287}
288
289
290#[pymodule]
292#[pyo3(name = "io")]
293fn tof_io<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
294 m.add_function(wrap_pyfunction!(py_create_rb_ch_to_pid_map, m)?)?;
295 m.add_function(wrap_pyfunction!(py_create_rb_ch_to_pid_a_map, m)?)?;
296 m.add_function(wrap_pyfunction!(py_create_rb_ch_to_pid_b_map, m)?)?;
297 m.add_function(wrap_pyfunction!(py_create_mtb_connection_to_pid_map, m)?)?;
298 m.add_function(wrap_pyfunction!(py_create_tracker_strip_map, m)?)?;
299 m.add_function(wrap_pyfunction!(py_summarize_toffile, m)?)?;
300 m.add_class::<PyTofPacket>()?;
302 m.add_class::<PyTofPacketReader>()?;
303 m.add_class::<PacketType>()?;
304 Ok(())
305}
306
307#[pymodule]
309#[pyo3(name = "events")]
310fn tof_events<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
311 m.add_class::<PyMasterTriggerEvent>()?;
312 m.add_class::<PyRBEvent>()?;
313 m.add_class::<PyRBEventHeader>()?;
314 m.add_class::<PyTofEvent>()?;
315 m.add_class::<PyTofHit>()?;
316 m.add_class::<PyRBWaveform>()?;
317 m.add_class::<PyRBCalibration>()?;
318 m.add_class::<PyTofEventSummary>()?;
319 m.add_class::<LTBThreshold>()?;
320 m.add_class::<EventStatus>()?;
321 m.add_class::<TriggerType>()?;
322 Ok(())
323}
324
325cfg_if::cfg_if! {
326 if #[cfg(feature = "telemetry")] {
327 #[pymodule]
328 #[pyo3(name = "telemetry")]
329 fn py_telemetry<'_py> (m: &Bound<'_py, PyModule>) -> PyResult<()> {
330 m.add_class::<tel_api::TelemetryPacketType>()?;
332 m.add_class::<PyTelemetryPacket>()?;
333 m.add_class::<PyTelemetryPacketReader>()?;
334 m.add_class::<PyMergedEvent>()?;
335 m.add_class::<PyTrackerHit>()?;
339 m.add_class::<PyTrackerHitV2>()?;
340 m.add_class::<PyTrackerEvent>()?;
341 m.add_class::<PyTrackerPacket>()?;
342 m.add_class::<PyTrackerTempLeakPacket>()?;
343 m.add_class::<PyGPSPacket>()?;
344 m.add_class::<PyTrackerDAQTempPacket>()?;
345 m.add_class::<PyTrackerDAQHSKPacket>()?;
346 m.add_class::<PyTrackerEventIDEchoPacket>()?;
347 Ok(())
348 }
349 }
350}
351
352cfg_if::cfg_if! {
353 if #[cfg(feature = "liftof")] {
354 #[pymodule]
359 #[pyo3(name = "liftof")]
360 fn py_liftof<'_py> (m: &Bound<'_py, PyModule>) -> PyResult<()> {
361 m.add_function(wrap_pyfunction!(py_waveform_analysis,m)?)?;
362 m.add_function(wrap_pyfunction!(wrap_calc_edep_simple,m)?)?;
363 m.add_function(wrap_pyfunction!(test_db,m)?)?;
364 m.add_function(wrap_pyfunction!(wrap_prescale_to_u32,m)?)?;
365 m.add_function(wrap_pyfunction!(wrap_fit_sine_sydney,m)?)?;
366 m.add_class::<PyLiftofSettings>()?;
367 m.add_class::<PyIPBus>()?;
368 m.add_class::<PyMasterTrigger>()?;
369 Ok(())
370 }
371 }
372}
373
374cfg_if::cfg_if! {
375 if #[cfg(feature = "caraspace-serial")] {
376 #[pymodule]
377 #[pyo3(name = "caraspace")]
378 fn py_caraspace<'_py> (m: &Bound<'_py, PyModule>) -> PyResult<()> {
379 m.add_function(wrap_pyfunction!(py_parse_u8, m)?)?;
380 m.add_function(wrap_pyfunction!(py_parse_u16, m)?)?;
381 m.add_function(wrap_pyfunction!(py_parse_u32, m)?)?;
382 m.add_function(wrap_pyfunction!(py_parse_u64, m)?)?;
383 m.add_class::<PyCRFrame>()?;
385 m.add_class::<PyCRReader>()?;
386 m.add_class::<PyCRWriter>()?;
387 Ok(())
388 }
389 }
390}
391
392#[pymodule]
393#[pyo3(name = "factory")]
394fn tof_command_factory<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
395 m.add_function(wrap_pyfunction!(py_get_rbratmap_hardcoded, m)?)?;
396 m.add_function(wrap_pyfunction!(py_get_ratrbmap_hardcoded, m)?)?;
397 m.add_function(wrap_pyfunction!(py_get_ratpdumap_hardcoded, m)?)?;
398 m.add_function(wrap_pyfunction!(py_shutdown_rb, m)?)?;
399 m.add_function(wrap_pyfunction!(py_shutdown_all_rbs, m)?)?;
400 m.add_function(wrap_pyfunction!(py_shutdown_rat, m)?)?;
401 m.add_function(wrap_pyfunction!(py_shutdown_ratpair, m)?)?;
402 m.add_function(wrap_pyfunction!(py_shutdown_tofcpu, m)?)?;
403 m.add_function(wrap_pyfunction!(py_restart_liftofrb, m)?)?;
404 m.add_function(wrap_pyfunction!(py_start_run, m)?)?;
405 m.add_function(wrap_pyfunction!(py_stop_run, m)?)?;
406 m.add_function(wrap_pyfunction!(py_rb_calibration, m)?)?;
407 m.add_function(wrap_pyfunction!(py_change_triggerconfig, m)?)?;
408 m.add_function(wrap_pyfunction!(py_change_datapublisherconfig, m)?)?;
409 m.add_function(wrap_pyfunction!(py_change_tofeventbuilderconfig, m)?)?;
410 m.add_function(wrap_pyfunction!(py_change_tofrunconfig, m)?)?;
411 m.add_function(wrap_pyfunction!(py_change_tofrbconfig, m)?)?;
412 Ok(())
413}
414
415
416#[pymodule]
418#[pyo3(name = "commands")]
419fn tof_commands<'_py>(m: &Bound<'_py, PyModule>) -> PyResult<()> {
420 m.add_class::<TofCommandCode>()?;
421 m.add_class::<PyTofCommand>()?;
422
423 m.add_class::<BuildStrategy>()?;
424
425 m.add_class::<PyTriggerConfig>()?;
426 m.add_class::<PyAnalysisEngineConfig>()?;
427 m.add_class::<PyTOFEventBuilderConfig>()?;
428 m.add_class::<PyDataPublisherConfig>()?;
429 m.add_class::<PyTofRunConfig>()?;
430 m.add_class::<PyTofRBConfig>()?;
431
432 m.add_class::<PyHeartBeatDataSink>()?;
433 m.add_class::<PyMTBHeartbeat>()?;
434 m.add_class::<PyEVTBLDRHeartbeat>()?;
435 m.add_wrapped(wrap_pymodule!(tof_command_factory))?;
436 Ok(())
437}
438
439#[pymodule]
444#[pyo3(name = "go_pybindings")]
445fn go_pybindings<'_py>(m : &Bound<'_py, PyModule>) -> PyResult<()> { pyo3_log::init();
447 m.add_wrapped(wrap_pymodule!(tof_analysis))?;
449 m.add_wrapped(wrap_pymodule!(tof_moni))?;
450 m.add_wrapped(wrap_pymodule!(tof_io))?;
451 m.add_wrapped(wrap_pymodule!(tof_events))?;
452 m.add_wrapped(wrap_pymodule!(tof_commands))?;
453 #[cfg(feature="telemetry")]
454 m.add_wrapped(wrap_pymodule!(py_telemetry))?;
455 #[cfg(feature="liftof")]
456 m.add_wrapped(wrap_pymodule!(py_liftof))?;
457 #[cfg(feature="caraspace-serial")]
458 m.add_wrapped(wrap_pymodule!(py_caraspace))?;
459 Ok(())
460}