1use std::collections::HashMap;
2
3use numpy::{
4 PyArray,
5 PyArray1,
6 PyArray2,
7};
8
9use pyo3_polars::{
10 PyDataFrame,
11 };
13
14use pyo3::Python;
15
16use tof_dataclasses::ProtocolVersion;
17use tof_dataclasses::io::TofPacketReader;
18#[cfg(feature = "caraspace-serial")]
19use caraspace::reader::CRReader;
20use tof_dataclasses::packets::{
21 TofPacket,
22 PacketType
23};
24use tof_dataclasses::database::DsiJChPidMapping;
25
26use tof_dataclasses::heartbeats::HeartBeatDataSink;
27use tof_dataclasses::heartbeats::MTBHeartbeat;
28use tof_dataclasses::heartbeats::EVTBLDRHeartbeat;
29
30#[cfg(feature="telemetry")]
31use crate::tel_api::TelemetryPacket;
32
33use tof_dataclasses::monitoring::{
34 MoniData,
35 MoniSeries,
36 PAMoniData,
37 PBMoniData,
38 RBMoniData,
39 MtbMoniData,
40 CPUMoniData,
41 LTBMoniData,
42};
43
44use tof_dataclasses::status::TofDetectorStatus;
45
46use tof_dataclasses::series::{
47 PAMoniDataSeries,
48 PBMoniDataSeries,
49 RBMoniDataSeries,
50 MtbMoniDataSeries,
51 CPUMoniDataSeries,
52 LTBMoniDataSeries,
53};
54
55use tof_dataclasses::events::{
56 TofEvent,
57 TofEventHeader,
58 TofEventSummary,
59 EventStatus,
60 TofHit,
61 MasterTriggerEvent,
62 RBEvent,
63 RBEventHeader,
64 RBWaveform
65};
66
67use tof_dataclasses::serialization::{
68 Serialization,
69 Packable
70};
71
72use tof_dataclasses::commands::{
73 TofCommandV2,
74 TofCommandCode
75};
76
77use tof_dataclasses::calibrations::{
78 RBCalibrations,
79 };
82
83use tof_dataclasses::commands::config::{
84 AnalysisEngineConfig,
85 RunConfig, TriggerConfig,
87 TOFEventBuilderConfig,
88 DataPublisherConfig,
89 TofRunConfig,
90 TofRBConfig,
91 BuildStrategy
92};
93
94use pyo3::prelude::*;
95use pyo3::exceptions::{
96 PyKeyError,
97 PyValueError,
98 PyIOError,
99};
100
101use tof_dataclasses::events::TriggerType;
102use tof_dataclasses::events::master_trigger::LTBThreshold;
103use tof_dataclasses::events::rb_event::RBPaddleID;
104
105#[pyclass]
132#[pyo3(name="RBPaddleID")]
133pub struct PyRBPaddleID {
134 pub pid : RBPaddleID
135}
136
137#[pymethods]
138impl PyRBPaddleID {
139
140 #[new]
141 fn new() -> Self {
142 Self {
143 pid : RBPaddleID::new()
144 }
145 }
146
147 fn to_u64(&self) -> u64 {
148 self.pid.to_u64()
149 }
150
151 fn get_order_flipped(&self, channel : u8) -> bool {
152 self.pid.get_order_flipped(channel)
153 }
154
155 fn get_order_str(&self, channel : u8) -> String {
156 self.pid.get_order_str(channel)
157 }
158
159 fn is_a(&self, channel : u8) -> bool {
160 self.pid.is_a(channel)
161 }
162
163 fn from_u64(&self, val : u64) -> Self {
164 let pid = RBPaddleID::from_u64(val);
165 Self {
166 pid
167 }
168 }
169
170 fn get_paddle_id(&self, channel : u8) -> (u8, bool) {
172 self.pid.get_paddle_id(channel)
173 }
174
175 fn __repr__(&self) -> PyResult<String> {
176 Ok(format!("<PyO3Wrapper: {}>", self.pid))
177 }
178}
179
180#[pyclass]
181#[pyo3(name="TofDetectorStatus")]
182pub struct PyTofDetectorStatus {
183 pub status : TofDetectorStatus
184}
185
186#[pymethods]
187impl PyTofDetectorStatus {
188
189 #[new]
190 fn new() -> Self {
191 let status = TofDetectorStatus::new();
192 Self {
193 status
194 }
195 }
196 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
200 let tp = packet.get_tp();
201 match tp.unpack::<TofDetectorStatus>() {
202 Ok(status) => {
203 self.status = status;
204 return Ok(());
205 }
206 Err(err) => {
207 let err_msg = format!("Unable to unpack TofPacket! {err}");
208 return Err(PyIOError::new_err(err_msg));
209 }
210 }
211 }
212
213 #[getter]
214 fn channels000_031(&self) -> u32 {
215 self.status.channels000_031
216 }
217
218 #[getter]
219 fn channels032_063(&self) -> u32 {
220 self.status.channels032_063
221 }
222
223 #[getter]
224 fn channels064_095(&self) -> u32 {
225 self.status.channels064_095
226 }
227
228 #[getter]
229 fn channels096_127(&self) -> u32 {
230 self.status.channels096_127
231 }
232
233 #[getter]
234 fn channels128_159(&self) -> u32 {
235 self.status.channels128_159
236 }
237
238 #[getter]
239 fn channels160_191(&self) -> u32 {
240 self.status.channels160_191
241 }
242
243 #[getter]
244 fn channels192_223(&self) -> u32 {
245 self.status.channels192_223
246 }
247
248 #[getter]
249 fn channels224_255(&self) -> u32 {
250 self.status.channels224_255
251 }
252
253 #[getter]
254 fn channels256_297(&self) -> u32 {
255 self.status.channels256_297
256 }
257
258 #[getter]
259 fn channels298_319(&self) -> u32 {
260 self.status.channels298_319
261 }
262
263 fn __repr__(&self) -> PyResult<String> {
264 Ok(format!("<PyO3Wrapper: {}>", self.status))
265 }
266}
267
268
269#[pyclass]
270#[pyo3(name="RunConfig")]
271pub struct PyRunConfig {
272 pub config : RunConfig
273}
274
275impl PyRunConfig {
276 pub fn set_config(&mut self, config : RunConfig) {
277 self.config = config
278 }
279}
280
281#[pymethods]
282impl PyRunConfig {
283 #[new]
284 fn new() -> Self {
285 let config = RunConfig::new();
286 Self {
287 config
288 }
289 }
290
291 #[getter]
292 fn get_runid(&self) -> PyResult<u32> {
293 Ok(self.config.runid)
294 }
295
296 #[setter]
297 fn set_runid(&mut self, runid: u32) -> PyResult<()> {
298 self.config.runid = runid;
299 Ok(())
300 }
301
302 fn to_bytestream(&self) -> Vec<u8> {
303 self.config.to_bytestream()
304 }
305
306 fn __repr__(&self) -> PyResult<String> {
307 Ok(format!("<PyO3Wrapper: {}>", self.config))
308 }
309}
310
311#[pyclass]
312#[pyo3(name="TofRunConfig")]
313pub struct PyTofRunConfig {
314 pub config : TofRunConfig
315}
316
317#[pymethods]
318impl PyTofRunConfig {
319
320 #[new]
321 fn new() -> Self {
322 let config = TofRunConfig::new();
323 Self {
324 config
325 }
326 }
327
328 #[getter]
329 pub fn get_runtime(&self) -> Option<u32> {
330 self.config.runtime
331 }
332
333 #[setter]
334 pub fn set_runtime(&mut self, secs : u32) {
335 self.config.set_runtime(secs);
336 }
337
338 fn to_bytestream(&self) -> Vec<u8> {
339 self.config.to_bytestream()
340 }
341
342 fn __getitem__<'a>(&self, py: Python<'a>, key: &str) -> PyResult<Option<Bound<'a,PyAny>>> {
343 match key {
344 "runtime" => Ok(Some(self.config.runtime.into_pyobject(py).unwrap())),
345 _ => Err(PyKeyError::new_err(format!("Key '{}' not found", key)))
346 }
347 }
348
349 fn __setitem__(&mut self, key: &str, value: &Bound<'_, PyAny>) -> PyResult<()> {
350 match key {
351 "runtime" => {
352 self.config.active_fields |= 1;
353 self.config.runtime = Some(value.extract::<u32>()?);
354 Ok(())
355 }
356 _ => Err(PyKeyError::new_err(format!("Key '{}' not found", key))),
357 }
358 }
359
360 fn __repr__(&self) -> PyResult<String> {
361 Ok(format!("<PyO3Wrapper: {}>", self.config))
362 }
363}
364
365#[pyclass]
366#[pyo3(name="TofRBConfig")]
367pub struct PyTofRBConfig {
368 pub config : TofRBConfig
369}
370
371#[pymethods]
372impl PyTofRBConfig {
373
374 #[new]
375 fn new() -> Self {
376 let config = TofRBConfig::new();
377 Self {
378 config
379 }
380 }
381
382 #[getter]
383 pub fn get_rb_moni_interval(&self) -> Option<u32> {
384 self.config.rb_moni_interval
385 }
386
387 #[setter]
388 pub fn set_rb_moni_interval(&mut self, secs : u32) {
389 self.config.set_rb_moni_interval(secs);
390 }
391
392 #[getter]
393 pub fn get_pa_moni_every_x(&self) -> Option<u32> {
394 self.config.pa_moni_every_x
395 }
396
397 #[setter]
398 pub fn set_pa_moni_every_x(&mut self, secs : u32) {
399 self.config.set_pa_moni_every_x(secs);
400 }
401
402 #[getter]
403 pub fn get_pb_moni_every_x(&self) -> Option<u32> {
404 self.config.pb_moni_every_x
405 }
406
407 #[setter]
408 pub fn set_pb_moni_every_x(&mut self, secs : u32) {
409 self.config.set_pb_moni_every_x(secs);
410 }
411
412 #[getter]
413 pub fn get_ltb_moni_every_x(&self) -> Option<u32> {
414 self.config.ltb_moni_every_x
415 }
416
417 #[setter]
418 pub fn set_ltb_moni_every_x(&mut self, secs : u32) {
419 self.config.set_ltb_moni_every_x(secs);
420 }
421
422 #[getter]
423 pub fn get_drs_deadtime_instead_fpga_temp(&self) -> Option<bool> {
424 self.config.drs_deadtime_instead_fpga_temp
425 }
426
427 #[setter]
428 pub fn set_drs_deadtime_instead_fpga_temp(&mut self, do_it : bool) {
429 self.config.set_drs_deadtime_instead_fpga_temp(do_it);
430 }
431
432 fn to_bytestream(&self) -> Vec<u8> {
433 self.config.to_bytestream()
434 }
435
436 fn __getitem__<'a>(&self, py: Python<'a>, key: &str) -> PyResult<Option<Bound<'a,PyAny>>> {
437 match key {
438 "rb_moni_interval" => Ok(Some(self.config.rb_moni_interval.into_pyobject(py).unwrap())),
439 "pa_moni_every_x" => Ok(Some(self.config.pa_moni_every_x .into_pyobject(py).unwrap())),
440 "pb_moni_every_x" => Ok(Some(self.config.pb_moni_every_x .into_pyobject(py).unwrap())),
441 "ltb_moni_every_x" => Ok(Some(self.config.ltb_moni_every_x.into_pyobject(py).unwrap())),
442 "drs_deadtime_instead_fpga_temp" => Ok(Some(self.config.drs_deadtime_instead_fpga_temp.into_pyobject(py).unwrap())),
443 _ => Err(PyKeyError::new_err(format!("Key '{}' not found", key)))
444 }
445 }
446
447 fn __setitem__(&mut self, key: &str, value: &Bound<'_, PyAny>) -> PyResult<()> {
448 match key {
449 "rb_moni_interval" => {
450 self.config.active_fields |= 1;
451 self.config.rb_moni_interval = Some(value.extract::<u32>()?);
452 Ok(())
453 }
454 "pa_moni_every_x" => {
455 self.config.active_fields |= 2;
456 self.config.pa_moni_every_x = Some(value.extract::<u32>()?);
457 Ok(())
458 }
459 "pb_moni_every_x" => {
460 self.config.active_fields |= 4;
461 self.config.pb_moni_every_x = Some(value.extract::<u32>()?);
462 Ok(())
463 }
464 "ltb_moni_every_x" => {
465 self.config.active_fields |= 8;
466 self.config.ltb_moni_every_x = Some(value.extract::<u32>()?);
467 Ok(())
468 }
469 "drs_deadtime_instead_fpga_temp" => {
470 self.config.active_fields |= 16;
471 self.config.drs_deadtime_instead_fpga_temp = Some(value.extract::<bool>()?);
472 Ok(())
473 }
474 _ => Err(PyKeyError::new_err(format!("Key '{}' not found", key))),
475 }
476 }
477
478 fn __repr__(&self) -> PyResult<String> {
479 Ok(format!("<PyO3Wrapper: {}>", self.config))
480 }
481}
482
483#[pyclass]
484#[pyo3(name="DataPublisherConfig")]
485pub struct PyDataPublisherConfig {
486 pub config : DataPublisherConfig
487}
488
489#[pymethods]
490impl PyDataPublisherConfig {
491 #[new]
492 fn new() -> Self {
493 let config = DataPublisherConfig::new();
494 Self {
495 config
496 }
497 }
498
499 #[getter]
500 pub fn get_mbytes_per_file(&self) -> Option<u16> {
501 self.config.mbytes_per_file
502 }
503
504 #[setter]
505 pub fn set_mbytes_per_file(&mut self, mbytes : u16) {
506 self.config.mbytes_per_file = Some(mbytes);
507 }
508
509 #[getter]
510 pub fn get_discard_event_fraction(&self) -> Option<f32> {
511 self.config.discard_event_fraction
512 }
513
514 #[setter]
515 pub fn set_discard_event_fraction(&mut self, frac : f32) {
516 self.config.discard_event_fraction = Some(frac);
517 }
518
519 #[getter]
520 pub fn get_send_mtb_event_packets(&self) -> Option<bool> {
521 self.config.send_mtb_event_packets
522 }
523
524 #[setter]
525 pub fn set_send_mtb_event_packets(&mut self, send : bool ) {
526 self.config.send_mtb_event_packets = Some(send);
527 }
528
529 #[getter]
530 pub fn get_send_rbwaveform_packets(&self) -> Option<bool> {
531 self.config.send_rbwaveform_packets
532 }
533
534 #[setter]
535 pub fn set_send_rbwaveform_packets(&mut self, send : bool ) {
536 self.config.send_rbwaveform_packets = Some(send);
537 }
538
539 #[getter]
540 pub fn get_send_rbwf_every_x_event(&self) -> Option<u32> {
541 self.config.send_rbwf_every_x_event
542 }
543
544 #[setter]
545 pub fn set_send_rbwf_every_x_event(&mut self, nevent : u32) {
546 self.config.send_rbwf_every_x_event = Some(nevent);
547 }
548
549 #[getter]
550 pub fn get_send_tof_summary_packets(&self) -> Option<bool> {
551 self.config.send_tof_summary_packets
552 }
553
554 #[setter]
555 pub fn set_send_tof_summary_packets(&mut self, send : bool ) {
556 self.config.send_tof_summary_packets = Some(send);
557 }
558
559 #[getter]
560 pub fn get_send_tof_event_packets(&self) -> Option<bool> {
561 self.config.send_tof_event_packets
562 }
563
564 #[setter]
565 pub fn set_send_tof_event_packets(&mut self, send : bool ) {
566 self.config.send_tof_event_packets = Some(send);
567 }
568
569 #[getter]
570 pub fn get_hb_send_interval(&self) -> Option<u16> {
571 self.config.hb_send_interval
572 }
573
574 #[setter]
575 pub fn set_hb_send_interfal(&mut self, interv : u16) {
576 self.config.hb_send_interval = Some(interv)
577 }
578
579 fn to_bytestream(&self) -> Vec<u8> {
580 self.config.to_bytestream()
581 }
582
583 fn __getitem__<'a>(&self, py: Python<'a>, key: &str) -> PyResult<Option<Bound<'a,PyAny>>> {
584 match key {
585 "mbytes_per_file" => Ok(Some(self.config.mbytes_per_file .into_pyobject(py).unwrap())),
586 "discard_event_fraction" => Ok(Some(self.config.discard_event_fraction .into_pyobject(py).unwrap())),
587 "send_mtb_event_packets" => Ok(Some(self.config.send_mtb_event_packets .into_pyobject(py).unwrap())),
588 "send_rbwaveform_packets" => Ok(Some(self.config.send_rbwaveform_packets .into_pyobject(py).unwrap())),
589 "send_rbwf_every_x_event" => Ok(Some(self.config.send_rbwf_every_x_event .into_pyobject(py).unwrap())),
590 "send_tof_summary_packets" => Ok(Some(self.config.send_tof_summary_packets.into_pyobject(py).unwrap())),
591 "send_tof_event_packets" => Ok(Some(self.config.send_tof_event_packets .into_pyobject(py).unwrap())),
592 "hb_send_interval" => Ok(Some(self.config.hb_send_interval .into_pyobject(py).unwrap())),
593 _ => Err(PyKeyError::new_err(format!("Key '{}' not found", key)))
594 }
595 }
596
597 fn __setitem__(&mut self, key: &str, value: &Bound<'_, PyAny>) -> PyResult<()> {
598 match key {
599 "mbytes_per_file" => {
600 self.config.active_fields |= 1;
601 self.config.mbytes_per_file = Some(value.extract::<u16>()?);
602 Ok(())
603 }
604 "discard_event_fraction" => {
605 self.config.active_fields |= 2;
606 self.config.discard_event_fraction = Some(value.extract::<f32>()?);
607 Ok(())
608 }
609 "send_mtb_event_packets" => {
610 self.config.active_fields |= 4;
611 self.config.send_mtb_event_packets = Some(value.extract::<bool>()?);
612 Ok(())
613 }
614 "send_rbwaveform_packets" => {
615 self.config.active_fields |= 8;
616 self.config.send_rbwaveform_packets = Some(value.extract::<bool>()?);
617 Ok(())
618 }
619 "send_rbwf_every_x_event" => {
620 self.config.active_fields |= 16;
621 self.config.send_rbwf_every_x_event = Some(value.extract::<u32>()?);
622 Ok(())
623 }
624 "send_tof_summary_packets" => {
625 self.config.active_fields |= 32;
626 self.config.send_tof_summary_packets = Some(value.extract::<bool>()?);
627 Ok(())
628 }
629 "send_tof_event_packets" => {
630 self.config.active_fields |= 64;
631 self.config.send_tof_event_packets = Some(value.extract::<bool>()?);
632 Ok(())
633 }
634 "hb_send_interval" => {
635 self.config.active_fields |= 128;
636 self.config.hb_send_interval = Some(value.extract::<u16>()?);
637 Ok(())
638 }
639 _ => Err(PyKeyError::new_err(format!("Key '{}' not found", key))),
640 }
641 }
642
643 fn __repr__(&self) -> PyResult<String> {
644 Ok(format!("<PyO3Wrapper: {}>", self.config))
645 }
646}
647
648#[pyclass]
649#[pyo3(name="TriggerConfig")]
650pub struct PyTriggerConfig {
651 pub config : TriggerConfig
652}
653
654#[pymethods]
655impl PyTriggerConfig {
656 #[new]
657 fn new() -> Self {
658 let cfg = TriggerConfig::new();
659 Self {
660 config : cfg
661 }
662 }
663
664 #[getter]
665 fn get_prescale(&self) -> Option<f32> {
666 self.config.prescale
667 }
668
669 #[setter]
670 fn set_prescale(&mut self, prescale: f32) -> PyResult<()> {
671 self.config.set_prescale (prescale);
672 Ok(())
673 }
674
675 #[getter]
676 fn get_gaps_trigger_use_beta(&self) -> Option<bool> {
677 self.config.gaps_trigger_use_beta
678 }
679
680 #[setter]
681 fn set_gaps_trigger_use_beta(&mut self, gaps_trigger_use_beta: bool) -> PyResult<()> {
682 self.config.set_gaps_trigger_use_beta(gaps_trigger_use_beta);
683 Ok(())
684 }
685
686 #[getter]
687 fn get_trigger_type(&self) -> Option<TriggerType> {
688 self.config.trigger_type
689 }
690
691 #[setter]
692 fn set_trigger_type(&mut self, trigger_type: TriggerType) -> PyResult<()> {
693 self.config.set_trigger_type(trigger_type);
694 Ok(())
695 }
696
697 #[getter]
698 fn get_use_combo_trigger(&self) -> Option<bool> {
699 self.config.use_combo_trigger
700 }
701 #[setter]
702 fn set_use_combo_trigger(&mut self, combo : bool) {
703 self.config.set_use_combo_trigger(combo);
704 }
705 #[getter]
706 fn get_combo_trigger_type(&self) -> Option<TriggerType> {
707 self.config.combo_trigger_type
708 }
709 #[setter]
710 fn set_combo_trigger_type(&mut self, combo_trigger_type : TriggerType) {
711 self.config.set_combo_trigger_type(combo_trigger_type);
712 }
713 #[getter]
714 fn get_combo_trigger_prescale(&self) -> Option<f32> {
715 self.config.combo_trigger_prescale
716 }
717 #[setter]
718 fn set_combo_trigger_prescale(&mut self, prescale : f32) {
719 self.config.set_combo_trigger_prescale(prescale);
720 }
721 #[getter]
722 fn get_trace_suppression(&self) -> Option<bool> {
723 self.config.trace_suppression
724 }
725 #[setter]
726 fn set_trace_suppression(&mut self, tsup : bool) {
727 self.config.set_trace_suppression(tsup);
728 }
729 #[getter]
730 fn get_mtb_moni_interval(&mut self) -> Option<u16> {
731 self.config.mtb_moni_interval
732 }
733 #[setter]
734 fn set_mtb_moni_interval(&mut self, moni_int : u16) {
735 self.config.set_mtb_moni_interval(moni_int);
736 }
737 #[getter]
738 fn get_tiu_ignore_busy(&self) -> Option<bool> {
739 self.config.tiu_ignore_busy
740 }
741
742 #[setter]
743 fn set_tiu_ignore_busy(&mut self, ignore_busy : bool) {
744 self.config.set_tiu_ignore_busy(ignore_busy);
745 }
746 #[getter]
747 fn get_hb_send_interval(&self) -> Option<u16> {
748 self.config.hb_send_interval
749 }
750
751 fn to_bytestream(&self) -> Vec<u8> {
752 self.config.to_bytestream()
753 }
754
755 #[setter]
756 fn set_hb_send_interval(&mut self, hb_int : Option<u16>) {
757 self.config.hb_send_interval = hb_int;
758 }
759
760 fn __getitem__<'a>(&self, py: Python<'a>, key: &str) -> PyResult<Option<Bound<'a,PyAny>>> {
761 match key {
762 "gaps_trigger_use_beta" => Ok(Some(self.config.gaps_trigger_use_beta .into_pyobject(py).unwrap())),
763 "prescale" => Ok(Some(self.config.prescale .into_pyobject(py).unwrap())),
764 "trigger_type" => Ok(Some(self.config.trigger_type .into_pyobject(py).unwrap())),
765 "use_combo_trigger" => Ok(Some(self.config.use_combo_trigger .into_pyobject(py).unwrap())),
766 "combo_trigger_type" => Ok(Some(self.config.combo_trigger_type .into_pyobject(py).unwrap())),
767 "combo_trigger_prescale" => Ok(Some(self.config.combo_trigger_prescale.into_pyobject(py).unwrap())),
768 "trace_suppression" => Ok(Some(self.config.trace_suppression .into_pyobject(py).unwrap())),
769 "mtb_moni_interval" => Ok(Some(self.config.mtb_moni_interval .into_pyobject(py).unwrap())),
770 "tiu_ignore_busy" => Ok(Some(self.config.tiu_ignore_busy .into_pyobject(py).unwrap())),
771 "hb_send_interval" => Ok(Some(self.config.hb_send_interval .into_pyobject(py).unwrap())),
772 _ => Err(PyKeyError::new_err(format!("Key '{}' not found", key)))
773 }
774 }
775
776 fn __setitem__(&mut self, key: &str, value: &Bound<'_, PyAny>) -> PyResult<()> {
777 match key {
778 "gaps_trigger_use_beta" => {
779 self.config.active_fields |= 1;
780 self.config.gaps_trigger_use_beta = Some(value.extract::<bool>()?);
781 Ok(())
782 }
783 "prescale" => {
784 self.config.active_fields |= 2;
785 self.config.prescale = Some(value.extract::<f32>()?);
786 Ok(())
787 }
788 "trigger_type" => {
789 self.config.active_fields |= 4;
790 self.config.trigger_type = Some(value.extract::<TriggerType>()?);
791 Ok(())
792 }
793 "use_combo_trigger" => {
794 self.config.active_fields |= 8;
795 self.config.use_combo_trigger = Some(value.extract::<bool>()?);
796 Ok(())
797 }
798 "combo_trigger_type" => {
799 self.config.active_fields |= 16;
800 self.config.combo_trigger_type = Some(value.extract::<TriggerType>()?);
801 Ok(())
802 }
803 "combo_trigger_prescale" => {
804 self.config.active_fields |= 32;
805 self.config.combo_trigger_prescale = Some(value.extract::<f32>()?);
806 Ok(())
807 }
808 "trace_suppression" => {
809 self.config.active_fields |= 64;
810 self.config.trace_suppression = Some(value.extract::<bool>()?);
811 Ok(())
812 }
813 "mtb_moni_interval" => {
814 self.config.active_fields |= 128;
815 self.config.mtb_moni_interval = Some(value.extract::<u16>()?);
816 Ok(())
817 }
818 "tiu_ignore_busy" => {
819 self.config.active_fields |= 256;
820 self.config.tiu_ignore_busy = Some(value.extract::<bool>()?);
821 Ok(())
822 }
823 "hb_send_interval" => {
824 self.config.active_fields |= 512;
825 self.config.hb_send_interval = Some(value.extract::<u16>()?);
826 Ok(())
827 }
828 _ => Err(PyKeyError::new_err(format!("Key '{}' not found", key))),
829 }
830 }
831
832 fn __repr__(&self) -> PyResult<String> {
833 Ok(format!("<PyO3Wrapper: {}>", self.config))
834 }
835
836}
837
838
839#[pyclass]
840#[pyo3(name="TOFEventBuilderConfig")]
841
842pub struct PyTOFEventBuilderConfig{
843 pub config : TOFEventBuilderConfig
844}
845
846#[pymethods]
853impl PyTOFEventBuilderConfig{
854 #[new]
855 fn new() -> Self {
856 let cfg: TOFEventBuilderConfig = TOFEventBuilderConfig::new();
857 Self {
858 config : cfg
859 }
860 }
861
862 #[getter]
863 fn get_greediness(&self) -> Option<u8> {
864 self.config.greediness
865 }
866
867 #[setter]
868 fn set_greediness(&mut self, greediness: u8) -> PyResult<()> {
869 self.config.set_greediness(greediness);
870 Ok(())
871 }
872
873 #[getter]
875 fn get_wait_nrb(&self) -> Option<u8> {
876 self.config.wait_nrb
877 }
878 #[setter]
879 fn set_wait_nrb(&mut self, wait_nrb: u8) -> PyResult<()> {
880 self.config.set_wait_nrb(wait_nrb);
881 Ok(())
882 }
883 #[getter]
885 fn get_cachesize(&self) -> Option<u32> {
886 self.config.cachesize
887 }
888 #[setter]
889 fn set_cachesize(&mut self, cachesize: u32) -> PyResult<()> {
890 self.config.set_cachesize(cachesize);
891 Ok(())
892 }
893 #[getter]
895 fn get_n_mte_per_loop(&self) -> Option<u32> {
896 self.config.n_mte_per_loop
897 }
898 #[setter]
899 fn set_n_mte_per_loop(&mut self, n_mte_per_loop: u32) -> PyResult<()> {
900 self.config.set_n_mte_per_loop(n_mte_per_loop);
901 Ok(())
902 }
903 #[getter]
905 fn get_n_rbe_per_loop(&self) -> Option<u32> {
906 self.config.n_rbe_per_loop
907 }
908 #[setter]
909 fn set_n_rbe_per_loop(&mut self, n_rbe_per_loop: u32) -> PyResult<()> {
910 self.config.set_n_rbe_per_loop(n_rbe_per_loop);
911 Ok(())
912 }
913 #[getter]
915 fn get_te_timeout_sec(&self) -> Option<u32> {
916 self.config.te_timeout_sec
917 }
918 #[setter]
919 fn set_te_timeout_sec(&mut self, te_timeout_sec: u32) -> PyResult<()> {
920 self.config.set_te_timeout_sec(te_timeout_sec);
921 Ok(())
922 }
923 #[getter]
925 fn get_sort_events(&self) -> Option<bool> {
926 self.config.sort_events
927 }
928 #[setter]
929 fn set_sort_events(&mut self, sort_events: bool) -> PyResult<()> {
930 self.config.set_sort_events(sort_events);
931 Ok(())
932 }
933 #[getter]
935 fn get_build_strategy(&self) -> Option<BuildStrategy> {
936 self.config.build_strategy
937 }
938
939 #[setter]
940 fn set_build_strategy(&mut self, build_strategy: BuildStrategy) -> PyResult<()> {
941 self.config.set_build_strategy(build_strategy);
942 Ok(())
943 }
944
945 #[getter]
946 fn get_hb_send_interval(&self) -> Option<u16> {
947 self.config.hb_send_interval
948 }
949
950 #[setter]
951 fn set_hb_send_interval(&mut self, hb_send_interval: u16) -> PyResult<()> {
952 self.config.set_hb_send_interval(hb_send_interval);
953 Ok(())
954 }
955
956 fn to_bytestream(&self) -> Vec<u8> {
957 self.config.to_bytestream()
958 }
959
960 fn __getitem__<'a>(&self, py: Python<'a>, key: &str) -> PyResult<Option<Bound<'a,PyAny>>> {
961 match key {
962 "cachesize" => Ok(Some(self.config.cachesize .into_pyobject(py).unwrap())),
963 "n_mte_per_loop" => Ok(Some(self.config.n_mte_per_loop .into_pyobject(py).unwrap())),
964 "n_rbe_per_loop" => Ok(Some(self.config.n_rbe_per_loop .into_pyobject(py).unwrap())),
965 "te_timeout_sec" => Ok(Some(self.config.te_timeout_sec .into_pyobject(py).unwrap())),
966 "sort_events" => Ok(Some(self.config.sort_events .into_pyobject(py).unwrap())),
967 "build_strategy" => Ok(Some(self.config.build_strategy .into_pyobject(py).unwrap())),
968 "wait_nrb" => Ok(Some(self.config.wait_nrb .into_pyobject(py).unwrap())),
969 "greediness" => Ok(Some(self.config.greediness .into_pyobject(py).unwrap())),
970 "hb_send_interval" => Ok(Some(self.config.hb_send_interval.into_pyobject(py).unwrap())),
971 _ => Err(PyKeyError::new_err(format!("Key '{}' not found", key)))
972 }
973 }
974
975 fn __setitem__(&mut self, key: &str, value: &Bound<'_, PyAny>) -> PyResult<()> {
976 match key {
977 "cachesize" => {
978 self.config.active_fields |= 1;
979 self.config.cachesize = Some(value.extract::<u32>()?);
980 Ok(())
981 }
982 "n_mte_per_loop" => {
983 self.config.active_fields |= 2;
984 self.config.n_mte_per_loop = Some(value.extract::<u32>()?);
985 Ok(())
986 }
987 "n_rbe_per_loop" => {
988 self.config.active_fields |= 4;
989 self.config.n_rbe_per_loop = Some(value.extract::<u32>()?);
990 Ok(())
991 }
992 "te_timeout_sec" => {
993 self.config.active_fields |= 8;
994 self.config.te_timeout_sec = Some(value.extract::<u32>()?);
995 Ok(())
996 }
997 "sort_events" => {
998 self.config.active_fields |= 16;
999 self.config.sort_events = Some(value.extract::<bool>()?);
1000 Ok(())
1001 }
1002 "build_strategy" => {
1003 self.config.active_fields |= 32;
1004 self.config.build_strategy = Some(value.extract::<BuildStrategy>()?);
1005 Ok(())
1006 }
1007 "wait_nrb" => {
1008 self.config.active_fields |= 64;
1009 self.config.wait_nrb = Some(value.extract::<u8>()?);
1010 Ok(())
1011 }
1012 "greediness" => {
1013 self.config.active_fields |= 128;
1014 self.config.greediness = Some(value.extract::<u8>()?);
1015 Ok(())
1016 }
1017 "hb_send_interval" => {
1018 self.config.active_fields |= 256;
1019 self.config.hb_send_interval = Some(value.extract::<u16>()?);
1020 Ok(())
1021 }
1022 _ => Err(PyKeyError::new_err(format!("Key '{}' not found", key))),
1023 }
1024 }
1025
1026 fn __repr__(&self) -> PyResult<String> {
1027 Ok(format!("<PyO3Wrapper: {}>", self.config))
1028 }
1029
1030}
1031
1032#[pyclass]
1033#[pyo3(name="AnalysisEngineConfig")]
1034pub struct PyAnalysisEngineConfig{
1035 pub config : AnalysisEngineConfig
1036}
1037
1038impl PyAnalysisEngineConfig {
1039 pub fn set_config(&mut self, cfg : AnalysisEngineConfig) {
1040 self.config = cfg;
1041 }
1042}
1043
1044#[pymethods]
1045impl PyAnalysisEngineConfig {
1046 #[new]
1047 fn new() -> Self {
1048 let cfg: AnalysisEngineConfig = AnalysisEngineConfig::new();
1049 Self {
1050 config : cfg
1051 }
1052 }
1053 #[getter]
1056 fn get_integration_start(&self) -> PyResult<f32> {
1057 Ok(self.config.integration_start)
1058 }
1059
1060 #[setter]
1061 fn set_integration_start(&mut self, integration_start: f32) -> PyResult<()> {
1062 self.config.integration_start = integration_start;
1063 Ok(())
1064 }
1065 #[getter]
1067 fn get_integration_window(&self) -> PyResult<f32> {
1068 Ok(self.config.integration_window)
1069 }
1070
1071 #[setter]
1072 fn set_integration_window(&mut self, integration_window: f32) -> PyResult<()> {
1073 self.config.integration_window = integration_window;
1074 Ok(())
1075 }
1076 #[getter]
1078 fn get_pedestal_thresh(&self) -> PyResult<f32> {
1079 Ok(self.config.pedestal_thresh)
1080 }
1081
1082 #[setter]
1083 fn set_pedestal_thresh(&mut self, pedestal_thresh: f32) -> PyResult<()> {
1084 self.config.pedestal_thresh = pedestal_thresh;
1085 Ok(())
1086 }
1087 #[getter]
1089 fn get_find_pks_t_start(&self) -> PyResult<f32> {
1090 Ok(self.config.find_pks_t_start)
1091 }
1092
1093 #[setter]
1094 fn set_find_pks_t_start(&mut self, find_pks_t_start: f32) -> PyResult<()> {
1095 self.config.find_pks_t_start = find_pks_t_start;
1096 Ok(())
1097 }
1098 #[getter]
1100 fn get_find_pks_t_window(&self) -> PyResult<f32> {
1101 Ok(self.config.find_pks_t_window)
1102 }
1103
1104 #[setter]
1105 fn set_find_pks_t_window(&mut self, find_pks_t_window: f32) -> PyResult<()> {
1106 self.config.find_pks_t_window = find_pks_t_window;
1107 Ok(())
1108 }
1109 #[getter]
1111 fn get_find_pks_thresh(&self) -> PyResult<f32> {
1112 Ok(self.config.find_pks_thresh)
1113 }
1114
1115 #[setter]
1116 fn set_find_pks_thresh(&mut self, find_pks_thresh: f32) -> PyResult<()> {
1117 self.config.find_pks_thresh = find_pks_thresh;
1118 Ok(())
1119 }
1120 #[getter]
1122 fn get_cfd_fraction(&self) -> PyResult<f32> {
1123 Ok(self.config.cfd_fraction)
1124 }
1125
1126 #[setter]
1127 fn set_cfd_fraction(&mut self, cfd_fraction: f32) -> PyResult<()> {
1128 self.config.cfd_fraction = cfd_fraction;
1129 Ok(())
1130 }
1131 #[getter]
1134 fn get_use_zscore(&self) -> PyResult<bool> {
1135 Ok(self.config.use_zscore)
1136 }
1137
1138 #[setter]
1139 fn set_use_zscore(&mut self, use_zscore: bool) -> PyResult<()> {
1140 self.config.use_zscore = use_zscore;
1141 Ok(())
1142 }
1143 #[getter]
1146 fn get_pedestal_begin_bin(&self) -> PyResult<usize> {
1147 Ok(self.config.pedestal_begin_bin)
1148 }
1149
1150 #[setter]
1151 fn set_pedestal_begin_bin(&mut self, pedestal_begin_bin: usize) -> PyResult<()> {
1152 self.config.pedestal_begin_bin = pedestal_begin_bin;
1153 Ok(())
1154 }
1155 #[getter]
1157 fn get_pedestal_win_bins(&self) -> PyResult<usize> {
1158 Ok(self.config.pedestal_win_bins)
1159 }
1160
1161 #[setter]
1162 fn set_pedestal_win_bins(&mut self, pedestal_win_bins: usize) -> PyResult<()> {
1163 self.config.pedestal_win_bins = pedestal_win_bins;
1164 Ok(())
1165 }
1166 #[getter]
1168 fn get_min_oeak_size(&self) -> PyResult<usize> {
1169 Ok(self.config.min_peak_size)
1170 }
1171
1172 #[setter]
1173 fn set_min_peak_size(&mut self, min_peak_size: usize) -> PyResult<()> {
1174 self.config.min_peak_size = min_peak_size;
1175 Ok(())
1176 }
1177 #[getter]
1179 fn get_max_peaks(&self) -> PyResult<usize> {
1180 Ok(self.config.max_peaks)
1181 }
1182
1183 #[setter]
1184 fn set_max_peaks(&mut self, max_peaks: usize) -> PyResult<()> {
1185 self.config.max_peaks = max_peaks;
1186 Ok(())
1187 }
1188
1189 fn __repr__(&self) -> PyResult<String> {
1190 Ok(format!("<PyO3Wrapper: {}>", self.config))
1191 }
1192}
1193
1194#[pyclass]
1195#[pyo3(name="TofCommand")]
1196pub struct PyTofCommand {
1197 pub command : TofCommandV2
1198}
1199
1200#[pymethods]
1201impl PyTofCommand {
1202 #[new]
1203 fn new() -> Self {
1204 let cmd = TofCommandV2::new();
1205 Self {
1206 command : cmd
1207 }
1208 }
1209
1210 #[getter]
1211 fn get_command_code(&mut self) -> TofCommandCode {
1212 self.command.command_code
1213 }
1214
1215 #[setter]
1216 fn set_command_code(&mut self, command_code : TofCommandCode) {
1217 self.command.command_code = command_code;
1218 }
1219
1220 fn wrap_n_pack(&self) -> Vec<u8> {
1226 self.pack().to_bytestream()
1227 }
1228
1229 fn get_cc_u8(&self) -> u8 {
1233 self.command.command_code as u8
1234 }
1235
1236 fn to_bytestream(&self) -> Vec<u8> {
1237 self.command.to_bytestream()
1238 }
1239
1240 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
1241 let tp = packet.get_tp();
1242 match tp.unpack::<TofCommandV2>() {
1243 Ok(cmd) => {
1244 self.command = cmd;
1245 return Ok(());
1246 }
1247 Err(err) => {
1248 let err_msg = format!("Unable to unpack TofPacket! {err}");
1249 return Err(PyIOError::new_err(err_msg));
1250 }
1251 }
1252 }
1253
1254 fn pack(&self) -> PyTofPacket {
1255 let packet = self.command.pack();
1256 let mut pytp = PyTofPacket::new();
1257 pytp.set_tp(packet);
1258 pytp
1259 }
1260
1261 fn __repr__(&self) -> PyResult<String> {
1266 Ok(format!("<PyO3Wrapper: {}>", self.command))
1267 }
1268}
1269
1270#[pyclass]
1271#[pyo3(name="RBCalibration")]
1272pub struct PyRBCalibration {
1273 pub cali : RBCalibrations,
1274}
1275
1276#[pymethods]
1277impl PyRBCalibration {
1278 #[new]
1279 fn new() -> Self {
1280 let cali = RBCalibrations::new(0);
1281 Self {
1282 cali,
1283 }
1284 }
1285
1286 #[getter]
1287 fn rb_id(&self) -> u8 {
1288 self.cali.rb_id
1289 }
1290
1291 #[getter]
1292 fn d_v(&self) -> f32 {
1293 self.cali.d_v
1294 }
1295
1296 #[getter]
1297 fn vcal_data(&self) -> Vec<PyRBEvent> {
1298 let mut events = Vec::<PyRBEvent>::with_capacity(1000);
1299 for ev in &self.cali.vcal_data {
1300 let mut pyev = PyRBEvent::new();
1301 pyev.set_event(ev.clone());
1302 events.push(pyev);
1303 }
1304 events
1305 }
1306
1307 #[getter]
1308 fn tcal_data(&self) -> Vec<PyRBEvent> {
1309 let mut events = Vec::<PyRBEvent>::with_capacity(1000);
1310 for ev in &self.cali.tcal_data {
1311 let mut pyev = PyRBEvent::new();
1312 pyev.set_event(ev.clone());
1313 events.push(pyev);
1314 }
1315 events
1316 }
1317
1318 #[getter]
1319 fn noi_data(&self) -> Vec<PyRBEvent> {
1320 let mut events = Vec::<PyRBEvent>::with_capacity(1000);
1321 for ev in &self.cali.noi_data {
1322 let mut pyev = PyRBEvent::new();
1323 pyev.set_event(ev.clone());
1324 events.push(pyev);
1325 }
1326 events
1327 }
1328
1329 #[getter]
1330 fn v_offsets<'_py>(&self, py: Python<'_py>) -> PyResult<Bound<'_py, PyArray2<f32>>> {
1331 let mut data = Vec::<Vec<f32>>::with_capacity(9);
1332 for ch in 0..9 {
1333 data.push(self.cali.v_offsets[ch].to_vec());
1334 }
1335 let pyarray = PyArray::from_vec2(py, &data).unwrap();
1336 Ok(pyarray)
1337 }
1338
1339 #[getter]
1340 fn v_dips<'_py>(&self, py: Python<'_py>) -> PyResult<Bound<'_py, PyArray2<f32>>> {
1341 let mut data = Vec::<Vec<f32>>::with_capacity(9);
1342 for ch in 0..9 {
1343 data.push(self.cali.v_dips[ch].to_vec());
1344 }
1345 let pyarray = PyArray::from_vec2(py, &data).unwrap();
1346 Ok(pyarray)
1347 }
1348
1349 #[getter]
1350 fn v_inc<'_py>(&self, py: Python<'_py>) -> PyResult<Bound<'_py, PyArray2<f32>>> {
1351 let mut data = Vec::<Vec<f32>>::with_capacity(9);
1352 for ch in 0..9 {
1353 data.push(self.cali.v_inc[ch].to_vec());
1354 }
1355 let pyarray = PyArray::from_vec2(py, &data).unwrap();
1356 Ok(pyarray)
1357 }
1358
1359 #[getter]
1360 fn tbin<'_py>(&self, py: Python<'_py>) -> PyResult<Bound<'_py, PyArray2<f32>>> {
1361 let mut data = Vec::<Vec<f32>>::with_capacity(9);
1362 for ch in 0..9 {
1363 data.push(self.cali.tbin[ch].to_vec());
1364 }
1365 let pyarray = PyArray::from_vec2(py, &data).unwrap();
1366 Ok(pyarray)
1367 }
1368
1369 #[pyo3(signature = (filename, discard_data = true))]
1377 fn from_file(&mut self, filename : String, discard_data : bool) -> PyResult<()> {
1378 let cali = RBCalibrations::from_file(filename, discard_data);
1379 match cali {
1380 Ok(c) => {
1381 self.cali = c;
1382 },
1383 Err(err) => {
1384 return Err(PyValueError::new_err(err.to_string()));
1385 }
1386 }
1387 Ok(())
1388 }
1389
1390 fn __repr__(&self) -> PyResult<String> {
1391 Ok(format!("<PyO3Wrapper: {}>", self.cali))
1392 }
1393}
1394
1395#[pyclass]
1405#[pyo3(name="PAMoniData")]
1406pub struct PyPAMoniData {
1407 moni : PAMoniData
1408}
1409
1410#[pymethods]
1411impl PyPAMoniData {
1412 #[new]
1413 fn new() -> Self {
1414 Self {
1415 moni : PAMoniData::new()
1416 }
1417 }
1418
1419 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
1420 let tp = packet.get_tp();
1421 match tp.unpack::<PAMoniData>() {
1422 Ok(moni) => {
1423 self.moni = moni;
1424 return Ok(());
1425 }
1426 Err(err) => {
1427 let err_msg = format!("Unable to unpack TofPacket! {err}");
1428 return Err(PyIOError::new_err(err_msg));
1429 }
1430 }
1431 }
1432
1433 #[getter]
1434 fn board_id(&self) -> u8 {
1435 self.moni.board_id
1436 }
1437
1438 #[getter]
1440 fn temps(&self) -> [f32;16] {
1441 self.moni.temps
1442 }
1443
1444 #[getter]
1446 fn biases(&self) -> [f32;16] {
1447 self.moni.biases
1448 }
1449
1450 fn __repr__(&self) -> PyResult<String> {
1451 Ok(format!("<PyO3Wrapper: {}>", self.moni))
1452 }
1453
1454 fn keys(&self) -> Vec<&'static str> {
1455 PAMoniData::keys()
1456 }
1457
1458 fn get(&self, varname : &str) -> PyResult<f32> {
1460 match self.moni.get(varname) {
1461 None => {
1462 let err_msg = format!("LTBMoniData does not have a key with name {}! See RBmoniData.keys() for a list of available keys!", varname);
1463 return Err(PyKeyError::new_err(err_msg));
1464 }
1465 Some(val) => {
1466 return Ok(val)
1467 }
1468 }
1469 }
1470}
1471
1472#[pyclass]
1473#[pyo3(name="PAMoniSeries")]
1474pub struct PyPAMoniSeries {
1475 pamoniseries : PAMoniDataSeries,
1476}
1477
1478#[pymethods]
1479impl PyPAMoniSeries {
1480 #[new]
1481 fn new() -> Self {
1482 let pamoniseries = PAMoniDataSeries::new();
1483 Self {
1484 pamoniseries,
1485 }
1486 }
1487
1488 fn from_file(&mut self, filename : String) -> PyResult<PyDataFrame> {
1489 let mut reader = TofPacketReader::new(filename);
1490 reader.filter = PacketType::PAMoniData;
1491 for tp in reader {
1492 if let Ok(moni) = tp.unpack::<PAMoniData>() {
1493 self.pamoniseries.add(moni);
1494 }
1495 }
1496 match self.pamoniseries.get_dataframe() {
1497 Ok(df) => {
1498 let pydf = PyDataFrame(df);
1499 return Ok(pydf);
1500 },
1501 Err(err) => {
1502 return Err(PyValueError::new_err(err.to_string()));
1503 }
1504 }
1505 }
1506}
1507
1508#[pyclass]
1509#[pyo3(name="PBMoniData")]
1510pub struct PyPBMoniData {
1511 moni : PBMoniData,
1512}
1513
1514#[pymethods]
1515impl PyPBMoniData {
1516 #[new]
1517 fn new() -> Self {
1518 Self {
1519 moni : PBMoniData::new()
1520 }
1521 }
1522
1523 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
1524 let tp = packet.get_tp();
1525 match tp.unpack::<PBMoniData>() {
1526 Ok(moni) => {
1527 self.moni = moni;
1528 return Ok(());
1529 }
1530 Err(err) => {
1531 let err_msg = format!("Unable to unpack TofPacket! {err}");
1532 return Err(PyIOError::new_err(err_msg));
1533 }
1534 }
1535 }
1536
1537 #[getter]
1538 fn board_id(&self) -> u8 {
1539 self.moni.board_id
1540 }
1541
1542 #[getter]
1543 fn p3v6_preamp_vcp(&self) -> [f32; 3] {
1544 self.moni.p3v6_preamp_vcp
1545 }
1546
1547 #[getter]
1548 fn n1v6_preamp_vcp(&self) -> [f32; 3] {
1549 self.moni.n1v6_preamp_vcp
1550 }
1551
1552 #[getter]
1553 fn p3v4f_ltb_vcp(&self) -> [f32; 3] {
1554 self.moni.p3v4f_ltb_vcp
1555 }
1556
1557 #[getter]
1558 fn p3v4d_ltb_vcp(&self) -> [f32; 3] {
1559 self.moni.p3v4d_ltb_vcp
1560 }
1561
1562 #[getter]
1563 fn p3v6_ltb_vcp(&self) -> [f32; 3] {
1564 self.moni.p3v6_ltb_vcp
1565 }
1566
1567 #[getter]
1568 fn n1v6_ltb_vcp(&self) -> [f32; 3] {
1569 self.moni.n1v6_ltb_vcp
1570 }
1571
1572 #[getter]
1573 fn pds_temp(&self) -> f32 {
1574 self.moni.pds_temp
1575 }
1576 #[getter]
1577 fn pas_temp(&self) -> f32 {
1578 self.moni.pas_temp
1579 }
1580 #[getter]
1581 fn nas_temp(&self) -> f32 {
1582 self.moni.nas_temp
1583 }
1584
1585 #[getter]
1586 fn shv_temp(&self) -> f32 {
1587 self.moni.shv_temp
1588 }
1589
1590 fn __repr__(&self) -> PyResult<String> {
1591 Ok(format!("<PyO3Wrapper: {}>", self.moni))
1592 }
1593
1594 fn keys(&self) -> Vec<&'static str> {
1595 PBMoniData::keys()
1596 }
1597
1598 fn get(&self, varname : &str) -> PyResult<f32> {
1600 match self.moni.get(varname) {
1601 None => {
1602 let err_msg = format!("LTBMoniData does not have a key with name {}! See RBmoniData.keys() for a list of available keys!", varname);
1603 return Err(PyKeyError::new_err(err_msg));
1604 }
1605 Some(val) => {
1606 return Ok(val)
1607 }
1608 }
1609 }
1610}
1611
1612#[pyclass]
1613#[pyo3(name="PBMoniSeries")]
1614pub struct PyPBMoniSeries {
1615 pbmoniseries : PBMoniDataSeries,
1616}
1617
1618#[pymethods]
1619impl PyPBMoniSeries {
1620 #[new]
1621 fn new() -> Self {
1622 let pbmoniseries = PBMoniDataSeries::new();
1623 Self {
1624 pbmoniseries,
1625 }
1626 }
1627
1628 fn from_file(&mut self, filename : String) -> PyResult<PyDataFrame> {
1629 let mut reader = TofPacketReader::new(filename);
1630 reader.filter = PacketType::PBMoniData;
1631 for tp in reader {
1632 if let Ok(moni) = tp.unpack::<PBMoniData>() {
1634 self.pbmoniseries.add(moni);
1635 }
1636 }
1638 match self.pbmoniseries.get_dataframe() {
1639 Ok(df) => {
1640 let pydf = PyDataFrame(df);
1641 return Ok(pydf);
1642 },
1643 Err(err) => {
1644 return Err(PyValueError::new_err(err.to_string()));
1645 }
1646 }
1647 }
1648}
1649
1650#[pyclass]
1651#[pyo3(name="LTBMoniData")]
1652pub struct PyLTBMoniData {
1653 moni : LTBMoniData,
1654}
1655
1656#[pymethods]
1657impl PyLTBMoniData {
1658 #[new]
1659 fn new() -> Self {
1660 let moni = LTBMoniData::new();
1661 Self {
1662 moni,
1663 }
1664 }
1665
1666 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
1667 let tp = packet.get_tp();
1668 match tp.unpack::<LTBMoniData>() {
1669 Ok(moni) => {
1670 self.moni = moni;
1671 return Ok(());
1672 }
1673 Err(err) => {
1674 let err_msg = format!("Unable to unpack TofPacket! {err}");
1675 return Err(PyIOError::new_err(err_msg));
1676 }
1677 }
1678 }
1679
1680 fn __repr__(&self) -> PyResult<String> {
1681 Ok(format!("<PyO3Wrapper: {}>", self.moni))
1682 }
1683
1684 fn keys(&self) -> Vec<&'static str> {
1685 LTBMoniData::keys()
1686 }
1687
1688 fn get(&self, varname : &str) -> PyResult<f32> {
1690 match self.moni.get(varname) {
1691 None => {
1692 let err_msg = format!("LTBMoniData does not have a key with name {}! See RBmoniData.keys() for a list of available keys!", varname);
1693 return Err(PyKeyError::new_err(err_msg));
1694 }
1695 Some(val) => {
1696 return Ok(val)
1697 }
1698 }
1699 }
1700
1701 #[getter]
1702 fn board_id (&self) -> u8 {
1703 self.moni.board_id
1704 }
1705
1706 #[getter]
1707 fn trenz_temp (&self) -> f32 {
1708 self.moni.trenz_temp
1709 }
1710
1711 #[getter]
1712 fn ltb_temp (&self) -> f32 {
1713 self.moni.ltb_temp
1714 }
1715 #[getter]
1716 fn thresh0 (&self) -> f32 {
1717 self.moni.thresh[0]
1718 }
1719 #[getter]
1720 fn thresh1 (&self) -> f32 {
1721 self.moni.thresh[1]
1722 }
1723 #[getter]
1724 fn thresh2 (&self) -> f32 {
1725 self.moni.thresh[2]
1726 }
1727}
1728
1729#[pyclass]
1730#[pyo3(name="RBMoniData")]
1731pub struct PyRBMoniData {
1732 moni : RBMoniData,
1733}
1734
1735#[pymethods]
1736impl PyRBMoniData {
1737 #[new]
1738 fn new() -> Self {
1739 let moni = RBMoniData::new();
1740 Self {
1741 moni,
1742 }
1743 }
1744
1745 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
1746 let tp = packet.get_tp();
1747 match tp.unpack::<RBMoniData>() {
1748 Ok(moni) => {
1749 self.moni = moni;
1750 return Ok(());
1751 }
1752 Err(err) => {
1753 let err_msg = format!("Unable to unpack TofPacket! {err}");
1754 return Err(PyIOError::new_err(err_msg));
1755 }
1756 }
1757 }
1758
1759 fn __repr__(&self) -> PyResult<String> {
1760 Ok(format!("<PyO3Wrapper: {}>", self.moni))
1761 }
1762
1763 fn keys(&self) -> Vec<&'static str> {
1764 RBMoniData::keys()
1765 }
1766
1767 fn get(&self, varname : &str) -> PyResult<f32> {
1769 match self.moni.get(varname) {
1770 None => {
1771 let err_msg = format!("RBMoniData does not have a key with name {}! See RBmoniData.keys() for a list of available keys!", varname);
1772 return Err(PyKeyError::new_err(err_msg));
1773 }
1774 Some(val) => {
1775 return Ok(val)
1776 }
1777 }
1778 }
1779
1780 #[getter]
1781 fn board_id (&self) -> u8 {
1782 self.moni.board_id
1783 }
1784 #[getter]
1785 fn rate (&self) -> u16 {
1786 self.moni.rate
1787 }
1788 #[getter]
1789 fn tmp_drs (&self) -> f32 {
1790 self.moni.tmp_drs
1791 }
1792 #[getter]
1793 fn tmp_clk (&self) -> f32 {
1794 self.moni.tmp_clk
1795 }
1796 #[getter]
1797 fn tmp_adc (&self) -> f32 {
1798 self.moni.tmp_adc
1799 }
1800 #[getter]
1801 fn tmp_zynq (&self) -> f32 {
1802 self.moni.tmp_zynq
1803 }
1804 #[getter]
1805 fn tmp_lis3mdltr (&self) -> f32 {
1806 self.moni.tmp_lis3mdltr
1807 }
1808
1809 #[getter]
1810 fn tmp_bm280 (&self) -> f32 {
1811 self.moni.tmp_bm280
1812 }
1813 #[getter]
1814 fn pressure (&self) -> f32 {
1815 self.moni.pressure
1816 }
1817 #[getter]
1818 fn humidity (&self) -> f32 {
1819 self.moni.humidity
1820 }
1821 #[getter]
1822 fn mag_x (&self) -> f32 {
1823 self.moni.mag_x
1824 }
1825 #[getter]
1826 fn mag_y (&self) -> f32 {
1827 self.moni.mag_y
1828 }
1829 #[getter]
1830 fn mag_z (&self) -> f32 {
1831 self.moni.mag_z
1832 }
1833 #[getter]
1834 fn drs_dvdd_voltage (&self) -> f32 {
1835 self.moni.drs_dvdd_voltage
1836 }
1837 #[getter]
1838 fn drs_dvdd_current (&self) -> f32 {
1839 self.moni.drs_dvdd_current
1840 }
1841 #[getter]
1842 fn drs_dvdd_power (&self) -> f32 {
1843 self.moni.drs_dvdd_power
1844 }
1845 #[getter]
1846 fn p3v3_voltage (&self) -> f32 {
1847 self.moni.p3v3_voltage
1848 }
1849 #[getter]
1850 fn p3v3_current (&self) -> f32 {
1851 self.moni.p3v3_current
1852 }
1853 #[getter]
1854 fn p3v3_power (&self) -> f32 {
1855 self.moni.p3v3_current
1856 }
1857 #[getter]
1858 fn zynq_voltage (&self) -> f32 {
1859 self.moni.zynq_voltage
1860 }
1861 #[getter]
1862 fn zynq_current (&self) -> f32 {
1863 self.moni.zynq_current
1864 }
1865 #[getter]
1866 fn zynq_power (&self) -> f32 {
1867 self.moni.zynq_power
1868 }
1869 #[getter]
1870 fn p3v5_voltage (&self) -> f32 {
1871 self.moni.p3v5_voltage
1872 }
1873 #[getter]
1874 fn p3v5_current (&self) -> f32 {
1875 self.moni.p3v5_current
1876 }
1877 #[getter]
1878 fn p3v5_power (&self) -> f32 {
1879 self.moni.p3v5_power
1880 }
1881 #[getter]
1882 fn adc_dvdd_voltage (&self) -> f32 {
1883 self.moni.adc_dvdd_voltage
1884 }
1885 #[getter]
1886 fn adc_dvdd_current (&self) -> f32 {
1887 self.moni.adc_dvdd_current
1888 }
1889 #[getter]
1890 fn adc_dvdd_power (&self) -> f32 {
1891 self.moni.adc_dvdd_power
1892 }
1893 #[getter]
1894 fn adc_avdd_voltage (&self) -> f32 {
1895 self.moni.adc_avdd_voltage
1896 }
1897 #[getter]
1898 fn adc_avdd_current (&self) -> f32 {
1899 self.moni.adc_avdd_current
1900 }
1901 #[getter]
1902 fn adc_avdd_power (&self) -> f32 {
1903 self.moni.adc_avdd_power
1904 }
1905 #[getter]
1906 fn drs_avdd_voltage (&self) -> f32 {
1907 self.moni.drs_avdd_voltage
1908 }
1909 #[getter]
1910 fn drs_avdd_current (&self) -> f32 {
1911 self.moni.drs_avdd_current
1912 }
1913 #[getter]
1914 fn drs_avdd_power (&self) -> f32 {
1915 self.moni.drs_avdd_power
1916 }
1917 #[getter]
1918 fn n1v5_voltage (&self) -> f32 {
1919 self.moni.n1v5_voltage
1920 }
1921 #[getter]
1922 fn n1v5_current (&self) -> f32 {
1923 self.moni.n1v5_current
1924 }
1925 #[getter]
1926 fn n1v5_power (&self) -> f32 {
1927 self.moni.n1v5_power
1928 }
1929}
1930
1931#[pyclass]
1932#[pyo3(name="RBMoniSeries")]
1933pub struct PyRBMoniSeries {
1934 rbmoniseries : RBMoniDataSeries,
1935}
1936
1937#[pymethods]
1938impl PyRBMoniSeries {
1939 #[new]
1940 fn new() -> Self {
1941 let rbmoniseries = RBMoniDataSeries::new();
1942 Self {
1943 rbmoniseries,
1944 }
1945 }
1946
1947 fn from_file(&mut self, filename : String) -> PyResult<PyDataFrame> {
1948 let mut reader = TofPacketReader::new(filename);
1949 reader.filter = PacketType::RBMoniData;
1950 for tp in reader {
1951 if let Ok(moni) = tp.unpack::<RBMoniData>() {
1952 self.rbmoniseries.add(moni);
1953 }
1954 }
1955 match self.rbmoniseries.get_dataframe() {
1956 Ok(df) => {
1957 let pydf = PyDataFrame(df);
1958 return Ok(pydf);
1959 },
1960 Err(err) => {
1961 return Err(PyValueError::new_err(err.to_string()));
1962 }
1963 }
1964 }
1965}
1966
1967#[pyclass]
1968#[pyo3(name="HeartbeatDataSink")]
1969
1970pub struct PyHeartBeatDataSink{
1971 pub config : HeartBeatDataSink
1972}
1973
1974impl PyHeartBeatDataSink {
1975 pub fn set_config(&mut self, cfg : HeartBeatDataSink) {
1976 self.config = cfg;
1977 }
1978}
1979#[pymethods]
1980impl PyHeartBeatDataSink{
1981 #[new]
1982 fn new() -> Self {
1983 let cfg: HeartBeatDataSink = HeartBeatDataSink::new();
1984 Self {
1985 config : cfg
1986 }
1987 }
1988 #[getter]
1990 fn get_met(&self) -> PyResult<u64> {
1991 Ok(self.config.met)
1992 }
1993 #[getter]
1995 fn get_n_packets_sent(&self) -> PyResult<u64> {
1996 Ok(self.config.n_packets_sent)
1997 }
1998 #[getter]
2000 fn get_n_packets_incoming(&self) -> PyResult<u64> {
2001 Ok(self.config.n_packets_incoming)
2002 }
2003 #[getter]
2005 fn get_n_bytes_written(&self) -> PyResult<u64> {
2006 Ok(self.config.n_bytes_written)
2007 }
2008 #[getter]
2010 fn get_n_evid_chunksize(&self) -> PyResult<u64> {
2011 Ok(self.config.n_evid_chunksize)
2012 }
2013 #[getter]
2015 fn get_evid_missing(&self) -> PyResult<u64> {
2016 Ok(self.config.evid_missing)
2017 }
2018 #[getter]
2020 fn get_evid_check_len(&self) -> PyResult<u64> {
2021 Ok(self.config.evid_check_len)
2022 }
2023 #[getter]
2025 fn get_n_pack_write_disk(&self) -> PyResult<u64> {
2026 Ok(self.config.n_pack_write_disk)
2027 }
2028
2029 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
2030 let tp = packet.get_tp();
2031 match tp.unpack::<HeartBeatDataSink>() {
2032 Ok(hb) => {
2033 self.config = hb;
2034 return Ok(());
2035 }
2036 Err(err) => {
2037 let err_msg = format!("Unable to unpack TofPacket! {err}");
2038 return Err(PyIOError::new_err(err_msg));
2039 }
2040 }
2041 }
2042 fn __repr__(&self) -> PyResult<String> {
2043 Ok(format!("<PyO3Wrapper: {}>", self.config))
2044 }
2045
2046}
2047
2048#[pyclass]
2049#[pyo3(name="MTBHeartbeat")]
2050pub struct PyMTBHeartbeat{
2051 pub config : MTBHeartbeat
2052}
2053
2054impl PyMTBHeartbeat {
2055 pub fn set_config(&mut self, cfg : MTBHeartbeat) {
2056 self.config = cfg;
2057 }
2058}
2059#[pymethods]
2060impl PyMTBHeartbeat {
2061 #[new]
2062 fn new () -> Self {
2063 let cfg: MTBHeartbeat = MTBHeartbeat::new();
2064 Self {
2065 config : cfg
2066 }
2067 }
2068 #[getter]
2069 fn get_total_elapsed(&self) -> PyResult<u64> {
2070 Ok(self.config.total_elapsed)
2071 }
2072 #[getter]
2073 fn get_n_events(&self) -> PyResult<u64> {
2074 Ok(self.config.n_events)
2075 }
2076 #[getter]
2077 fn get_evq_num_events_last(&self) -> PyResult<u64> {
2078 Ok(self.config.evq_num_events_last)
2079 }
2080 #[getter]
2081 fn get_evq_num_events_avg(&self) -> PyResult<u64> {
2082 Ok(self.config.evq_num_events_avg)
2083 }
2084 #[getter]
2085 fn get_n_ev_unsent(&self) -> PyResult<u64> {
2086 Ok(self.config.n_ev_unsent)
2087 }
2088 #[getter]
2089 fn get_n_ev_missed(&self) -> PyResult<u64> {
2090 Ok(self.config.n_ev_missed)
2091 }
2092 #[getter]
2093 fn get_trate(&self) -> PyResult<u64> {
2094 Ok(self.config.trate)
2095 }
2096 #[getter]
2097 fn get_lost_trate(&self) -> PyResult<u64> {
2098 Ok(self.config.lost_trate)
2099 }
2100
2101 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
2102 let tp = packet.get_tp();
2103 match tp.unpack::<MTBHeartbeat>() {
2104 Ok(hb) => {
2105 self.config = hb;
2106 return Ok(());
2107 }
2108 Err(err) => {
2109 let err_msg = format!("Unable to unpack TofPacket! {err}");
2110 return Err(PyIOError::new_err(err_msg));
2111 }
2112 }
2113 }
2114 fn __repr__(&self) -> PyResult<String> {
2115 Ok(format!("<PyO3Wrapper: {}>", self.config))
2116 }
2117}
2118#[pyclass]
2119#[pyo3(name="EVTBLDRHeartbeat")]
2120pub struct PyEVTBLDRHeartbeat {
2121 pub config : EVTBLDRHeartbeat
2122}
2123
2124impl PyEVTBLDRHeartbeat {
2125 pub fn set_config(&mut self, cfg : EVTBLDRHeartbeat) {
2126 self.config = cfg;
2127 }
2128}
2129#[pymethods]
2130impl PyEVTBLDRHeartbeat {
2131 #[new]
2132 fn new () -> Self {
2133 let hb: EVTBLDRHeartbeat = EVTBLDRHeartbeat::new();
2134 Self {
2135 config : hb
2136 }
2137 }
2138 #[getter]
2139 fn get_met_seconds(&self) -> PyResult<usize> {
2140 Ok(self.config.met_seconds)
2141 }
2142 #[getter]
2143 fn get_n_mte_received_tot(&self) -> PyResult<usize> {
2144 Ok(self.config.n_mte_received_tot)
2145 }
2146 #[getter]
2147 fn get_n_rbe_received_tot(&self) -> PyResult<usize> {
2148 Ok(self.config.n_rbe_received_tot )
2149 }
2150 #[getter]
2151 fn get_n_rbe_per_te(&self) -> PyResult<usize> {
2152 Ok(self.config.n_rbe_per_te)
2153 }
2154 #[getter]
2155 fn get_n_rbe_discarded_tot(&self) -> PyResult<usize> {
2156 Ok(self.config.n_rbe_discarded_tot)
2157 }
2158 #[getter]
2159 fn get_n_mte_skipped(&self) -> PyResult<usize> {
2160 Ok(self.config.n_mte_skipped)
2161 }
2162 #[getter]
2163 fn get_n_timed_out(&self) -> PyResult<usize> {
2164 Ok(self.config.n_timed_out)
2165 }
2166 #[getter]
2167 fn get_n_sent(&self) -> PyResult<usize> {
2168 Ok(self.config.n_sent)
2169 }
2170 #[getter]
2171 fn get_delta_mte_rbe(&self) -> PyResult<usize> {
2172 Ok(self.config.delta_mte_rbe)
2173 }
2174 #[getter]
2175 fn get_event_cache_size(&self) -> PyResult<usize> {
2176 Ok(self.config.event_cache_size)
2177 }
2178 #[getter]
2179 fn get_rbe_wo_mte(&self) -> PyResult<usize> {
2180 Ok(self.config.rbe_wo_mte)
2181 }
2182 #[getter]
2183 fn get_drs_bsy_lost_hg_hits(&self) -> PyResult<usize> {
2184 Ok(self.config.drs_bsy_lost_hg_hits)
2185 }
2186 #[getter]
2187 fn get_mte_receiver_cbc_len(&self) -> PyResult<usize> {
2188 Ok(self.config.mte_receiver_cbc_len)
2189 }
2190 #[getter]
2191 fn get_rbe_receiver_cbc_len(&self) -> PyResult<usize> {
2192 Ok(self.config.rbe_receiver_cbc_len)
2193 }
2194 #[getter]
2195 fn get_tp_sender_cbc_len(&self) -> PyResult<usize> {
2196 Ok(self.config.tp_sender_cbc_len)
2197 }
2198 #[getter]
2199 fn get_data_mangled_ev(&self) -> PyResult<usize> {
2200 Ok(self.config.data_mangled_ev)
2201 }
2202
2203 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
2204 let tp = packet.get_tp();
2205 match tp.unpack::<EVTBLDRHeartbeat>() {
2206 Ok(hb) => {
2207 self.config = hb;
2208 return Ok(());
2209 }
2210 Err(err) => {
2211 let err_msg = format!("Unable to unpack TofPacket! {err}");
2212 return Err(PyIOError::new_err(err_msg));
2213 }
2214 }
2215 }
2216 fn __repr__(&self) -> PyResult<String> {
2217 Ok(format!("<PyO3Wrapper: {}>", self.config))
2218 }
2219}
2220
2221#[pyclass]
2222#[pyo3(name="MtbMoniData")]
2223pub struct PyMtbMoniData {
2224 moni : MtbMoniData,
2225}
2226
2227impl PyMtbMoniData {
2228 pub fn set_moni(&mut self, moni : MtbMoniData) {
2229 self.moni = moni;
2230 }
2231}
2232
2233#[pymethods]
2234impl PyMtbMoniData {
2235
2236 #[new]
2237 fn new() -> Self {
2238 let moni = MtbMoniData::new();
2239 Self {
2240 moni,
2241 }
2242 }
2243
2244 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
2245 let tp = packet.get_tp();
2246 match tp.unpack::<MtbMoniData>() {
2247 Ok(moni) => {
2248 self.moni = moni;
2249 return Ok(());
2250 }
2251 Err(err) => {
2252 let err_msg = format!("Unable to unpack TofPacket! {err}");
2253 return Err(PyIOError::new_err(err_msg));
2254 }
2255 }
2256 }
2257
2258 #[getter]
2259 fn get_vccint(&self) -> f32 {
2260 MtbMoniData::adc_vcc_conversion(self.moni.vccint)
2261 }
2262
2263 #[getter]
2264 fn get_vccbram(&self) -> f32 {
2265 MtbMoniData::adc_vcc_conversion(self.moni.vccbram)
2266 }
2267
2268 #[getter]
2269 fn get_vccaux(&self) -> f32 {
2270 MtbMoniData::adc_vcc_conversion(self.moni.vccaux)
2271 }
2272
2273 #[getter]
2274 pub fn get_rate(&self) -> u16 {
2275 self.moni.rate
2276 }
2277
2278 #[getter]
2279 pub fn get_lost_rate(&self) -> u16 {
2280 self.moni.lost_rate
2281 }
2282
2283 #[getter]
2284 pub fn get_tiu_busy_len(&self) -> u32 {
2287 self.moni.tiu_busy_len * 10
2288 }
2289
2290 #[getter]
2291 pub fn get_daq_queue_len(&self) -> u16 {
2292 self.moni.daq_queue_len
2293 }
2294
2295 #[getter]
2296 pub fn get_tiu_emulation_mode(&self) -> bool {
2297 self.moni.get_tiu_emulation_mode()
2298 }
2299
2300 #[getter]
2301 pub fn get_tiu_use_aux_link(&self) -> bool {
2302 self.moni.get_tiu_use_aux_link()
2303 }
2304
2305 #[getter]
2306 pub fn get_tiu_bad(&self) -> bool {
2307 self.moni.get_tiu_bad()
2308 }
2309
2310 #[getter]
2311 pub fn get_tiu_busy_stuck(&self) -> bool {
2312 self.moni.get_tiu_busy_stuck()
2313 }
2314
2315 #[getter]
2316 pub fn get_tiu_ignore_busy(&self) -> bool {
2317 self.moni.get_tiu_ignore_busy()
2318 }
2319
2320
2321 #[getter]
2322 pub fn get_fpga_temp(&self) -> f32 {
2323 self.moni.get_fpga_temp()
2324 }
2325
2326
2327 fn __repr__(&self) -> PyResult<String> {
2328 Ok(format!("<PyO3Wrapper: {}>", self.moni))
2329 }
2330}
2331
2332
2333#[pyclass]
2334#[pyo3(name="MtbMoniSeries")]
2335pub struct PyMtbMoniSeries {
2336 mtbmoniseries : MtbMoniDataSeries,
2337}
2338
2339#[pymethods]
2340impl PyMtbMoniSeries {
2341 #[new]
2342 fn new() -> Self {
2343 let mtbmoniseries = MtbMoniDataSeries::new();
2344 Self {
2345 mtbmoniseries,
2346 }
2347 }
2348
2349 #[getter]
2352 fn timestamps(&self) -> Vec<u64> {
2353 self.mtbmoniseries.timestamps.clone()
2354 }
2355
2356 #[cfg(feature = "caraspace-serial")]
2357 fn add_crfile(&mut self, filename : String, source : String) {
2366 let mut reader = CRReader::new(filename).expect("Unable to open file!");
2367 let address = &source.clone();
2372 for frame in reader {
2373 if frame.has(address) {
2374 if source == "PacketType.MtbMoniData" {
2376 let moni_res = frame.get::<TofPacket>(source.clone()).unwrap().unpack::<MtbMoniData>();
2377 match moni_res {
2378 Err(err) => {
2379 println!("Error unpacking MtbMoniData! {err}")
2380 }
2381 Ok(moni) => {
2382 self.mtbmoniseries.add(moni);
2383 }
2384 }
2385 }
2386 if source == "TelemetryPacketType.AnyTofHK" {
2387 let hk_res = frame.get::<TelemetryPacket>(source.clone());
2388 match hk_res {
2389 Err(err) => {
2390 println!("Error unpacking MtbMoniData! {err}");
2391 }
2392 Ok(hk) => {
2393 let mut pos = 0;
2394 let gcutime = hk.header.get_gcutime() as u64;
2395 match TofPacket::from_bytestream(&hk.payload, &mut pos) {
2396 Err(err) => {
2397 println!("Error unpacking MtbMoniData! {err}");
2398 }
2399 Ok(tp) => {
2400 if tp.packet_type == PacketType::MonitorMtb {
2401 match tp.unpack::<MtbMoniData>() {
2402 Err(err) => {
2403 println!("Error unpacking MtbMoniData! {err}");
2404 }
2405 Ok(moni) => {
2406 self.mtbmoniseries.add(moni);
2407 self.mtbmoniseries.timestamps.push(gcutime);
2408 }
2409 }
2410 }
2411 }
2412 }
2413 }
2414 }
2415 }
2416 }
2417 }
2418 }
2419
2420 fn add_file(&mut self, filename : String) {
2422 let mut reader = TofPacketReader::new(filename);
2423 reader.filter = PacketType::MonitorMtb;
2424 for tp in reader {
2425 if let Ok(moni) = tp.unpack::<MtbMoniData>() {
2426 self.mtbmoniseries.add(moni);
2427 }
2428 }
2429 }
2430
2431 fn get_dataframe(&mut self) -> PyResult<PyDataFrame> {
2434 match self.mtbmoniseries.get_dataframe() {
2435 Ok(df) => {
2436 let pydf = PyDataFrame(df);
2437 return Ok(pydf);
2438 },
2439 Err(err) => {
2440 return Err(PyValueError::new_err(err.to_string()));
2441 }
2442 }
2443 }
2444
2445 fn from_file(&mut self, filename : String) -> PyResult<PyDataFrame> {
2447 let mut reader = TofPacketReader::new(filename);
2448 reader.filter = PacketType::MonitorMtb;
2449 for tp in reader {
2450 if let Ok(moni) = tp.unpack::<MtbMoniData>() {
2451 self.mtbmoniseries.add(moni);
2452 }
2453 }
2454 match self.mtbmoniseries.get_dataframe() {
2455 Ok(df) => {
2456 let pydf = PyDataFrame(df);
2457 return Ok(pydf);
2458 },
2459 Err(err) => {
2460 return Err(PyValueError::new_err(err.to_string()));
2461 }
2462 }
2463 }
2464}
2465
2466#[pyclass]
2467#[pyo3(name="CPUMoniSeries")]
2468pub struct PyCPUMoniSeries {
2469 cpumoniseries : CPUMoniDataSeries,
2470}
2471
2472#[pymethods]
2473impl PyCPUMoniSeries {
2474 #[new]
2475 fn new() -> Self {
2476 let cpumoniseries = CPUMoniDataSeries::new();
2477 Self {
2478 cpumoniseries,
2479 }
2480 }
2481
2482 fn from_file(&mut self, filename : String) -> PyResult<PyDataFrame> {
2483 let mut reader = TofPacketReader::new(filename);
2484 reader.filter = PacketType::CPUMoniData;
2485 for tp in reader {
2486 if let Ok(moni) = tp.unpack::<CPUMoniData>() {
2487 self.cpumoniseries.add(moni);
2488 }
2489 }
2490 match self.cpumoniseries.get_dataframe() {
2491 Ok(df) => {
2492 let pydf = PyDataFrame(df);
2493 return Ok(pydf);
2494 },
2495 Err(err) => {
2496 return Err(PyValueError::new_err(err.to_string()));
2497 }
2498 }
2499 }
2500}
2501
2502#[pyclass]
2503#[pyo3(name="LTBMoniSeries")]
2504pub struct PyLTBMoniSeries {
2505 ltbmoniseries : LTBMoniDataSeries,
2506}
2507
2508#[pymethods]
2509impl PyLTBMoniSeries {
2510 #[new]
2511 fn new() -> Self {
2512 let ltbmoniseries = LTBMoniDataSeries::new();
2513 Self {
2514 ltbmoniseries,
2515 }
2516 }
2517
2518 fn from_file(&mut self, filename : String) -> PyResult<PyDataFrame> {
2519 let mut reader = TofPacketReader::new(filename);
2520 reader.filter = PacketType::LTBMoniData;
2521 for tp in reader {
2522 if let Ok(moni) = tp.unpack::<LTBMoniData>() {
2523 self.ltbmoniseries.add(moni);
2524 }
2525 }
2526 match self.ltbmoniseries.get_dataframe() {
2527 Ok(df) => {
2528 let pydf = PyDataFrame(df);
2529 return Ok(pydf);
2530 },
2531 Err(err) => {
2532 return Err(PyValueError::new_err(err.to_string()));
2533 }
2534 }
2535 }
2536}
2537
2538
2539#[pyclass]
2540#[pyo3(name="TofPacket")]
2541#[derive(Clone)]
2542pub struct PyTofPacket {
2543 pub packet : TofPacket,
2544}
2545
2546impl PyTofPacket {
2547 pub fn set_tp(&mut self, tp : TofPacket) {
2548 self.packet = tp;
2549 }
2550
2551 pub fn get_tp(&self) -> &TofPacket {
2552 &self.packet
2553 }
2554}
2555
2556#[pymethods]
2557impl PyTofPacket {
2558 #[new]
2559 pub fn new() -> Self {
2560 Self {
2561 packet : TofPacket::new(),
2562 }
2563 }
2564
2565 #[getter]
2566 fn packet_type(&self) -> PacketType {
2567 self.packet.packet_type
2568 }
2569
2570 fn to_bytestream(&self) -> Vec<u8> {
2571 self.packet.to_bytestream()
2572 }
2573
2574 fn from_bytestream(&mut self, stream : Vec<u8>, mut pos : usize) -> PyResult<()>{
2575 match TofPacket::from_bytestream(&stream, &mut pos) {
2576 Ok(tp) => {
2577 self.packet = tp;
2578 return Ok(());
2579 }
2580 Err(err) => {
2581 let err_msg = format!("Unable to TofPacket from bytestream! {err}");
2582 return Err(PyIOError::new_err(err_msg));
2583 }
2584 }
2585 }
2586
2587 fn __repr__(&self) -> PyResult<String> {
2588 Ok(format!("<PyO3Wrapper: {}>", self.packet))
2589 }
2590}
2591
2592#[pyclass]
2593#[pyo3(name="MasterTriggerEvent")]
2594pub struct PyMasterTriggerEvent {
2595 event : MasterTriggerEvent,
2596}
2597
2598impl PyMasterTriggerEvent {
2599 pub fn set_event(&mut self,event : MasterTriggerEvent) {
2600 self.event = event;
2601 }
2602}
2603
2604#[pymethods]
2605impl PyMasterTriggerEvent {
2606
2607 #[new]
2608 pub fn new() -> Self {
2609 Self {
2610 event : MasterTriggerEvent::new(),
2611 }
2612 }
2613
2614 #[getter]
2615 fn event_id(&self) -> u32 {
2616 self.event.event_id
2617 }
2618
2619 #[getter]
2620 fn status(&self) -> EventStatus {
2621 self.event.event_status
2622 }
2623
2624 #[getter]
2626 pub fn rb_link_ids(&self) -> Vec<u8> {
2627 self.event.get_rb_link_ids()
2628 }
2629
2630 #[getter]
2643 pub fn trigger_hits(&self) -> PyResult<Vec<(u8, u8, (u8, u8), LTBThreshold)>> {
2644 Ok(self.event.get_trigger_hits())
2645 }
2646
2647 #[getter]
2648 pub fn timestamp_mtb(&self) -> u32 {
2649 self.event.timestamp
2650 }
2651
2652
2653 #[getter]
2654 pub fn timestamp_gps32(&self) -> u32 {
2655 self.event.tiu_gps32
2656 }
2657
2658 #[getter]
2659 pub fn timestamp_gps16(&self) -> u16 {
2660 self.event.tiu_gps16
2661 }
2662
2663 #[getter]
2664 pub fn timestamp_tiu(&self) -> u32 {
2665 self.event.tiu_timestamp
2666 }
2667
2668 #[getter]
2670 pub fn timestamp_abs48(&self) -> u64 {
2671 self.event.get_timestamp_abs48()
2672 }
2673
2674 #[getter]
2678 pub fn trigger_sources(&self) -> Vec<TriggerType> {
2679 self.event.get_trigger_sources()
2680 }
2681
2682 fn __repr__(&self) -> PyResult<String> {
2683 Ok(format!("<PyO3Wrapper: {}>", self.event))
2684 }
2685
2686}
2687
2688#[pyclass]
2693#[pyo3(name="RBEventHeader")]
2694pub struct PyRBEventHeader {
2695 header : RBEventHeader,
2696}
2697
2698impl PyRBEventHeader {
2699
2700 }
2720
2721#[pymethods]
2722impl PyRBEventHeader {
2723 #[new]
2724 pub fn new() -> Self {
2725 Self {
2726 header : RBEventHeader::new(),
2727 }
2728 }
2729
2730 #[getter]
2731 fn rb_id(&self) -> u8 {
2732 self.header.rb_id
2733 }
2734
2735 #[getter]
2736 fn event_id(&self) -> u32 {
2737 self.header.event_id
2738 }
2739
2740 #[getter]
2746 fn channel_mask(&self) -> u16 {
2747 self.header.get_channel_mask()
2748 }
2749
2750 #[getter]
2751 fn stop_cell(&self) -> u16 {
2752 self.header.stop_cell
2753 }
2754
2755 #[getter]
2756 fn fpga_temp(&self) -> f32 {
2757 self.header.get_fpga_temp()
2758 }
2759
2760 #[getter]
2761 fn drs_deadtime(&self) -> u16 {
2762 self.header.drs_deadtime
2763 }
2764
2765 #[getter]
2766 fn timestamp32(&self) -> u32 {
2767 self.header.timestamp32
2768 }
2769
2770 #[getter]
2771 fn timestamp16(&self) -> u16 {
2772 self.header.timestamp16
2773 }
2774
2775 fn get_channels(&self) -> Vec<u8> {
2780 self.header.get_channels()
2781 }
2782
2783 #[getter]
2784 pub fn is_event_fragment(&self) -> bool {
2785 self.header.is_event_fragment()
2786 }
2787
2788 #[getter]
2789 pub fn drs_lost_trigger(&self) -> bool {
2790 self.header.drs_lost_trigger()
2791 }
2792
2793 #[getter]
2794 fn lost_lock(&self) -> bool {
2795 self.header.lost_lock()
2796 }
2797
2798 #[getter]
2799 fn lost_lock_last_sec(&self) -> bool {
2800 self.header.lost_lock_last_sec()
2801 }
2802
2803 #[getter]
2804 fn is_locked(&self) -> bool {
2805 self.header.is_locked()
2806 }
2807
2808 #[getter]
2809 fn is_locked_last_sec(&self) -> bool {
2810 self.header.is_locked_last_sec()
2811 }
2812
2813
2814 fn __repr__(&self) -> PyResult<String> {
2815 Ok(format!("<PyO3Wrapper: {}>", self.header))
2816 }
2817
2818}
2819
2820#[pyclass]
2821#[pyo3(name="TofEventSummary")]
2822pub struct PyTofEventSummary {
2823 pub event : TofEventSummary,
2824}
2825
2826#[pymethods]
2827impl PyTofEventSummary {
2828 #[new]
2829 pub fn new() -> Self {
2830 Self {
2831 event : TofEventSummary::new(),
2832 }
2833 }
2834
2835 fn copy(&self) -> Self {
2837 let mut copy_event = PyTofEventSummary::new();
2838 copy_event.event = self.event.clone();
2839 copy_event
2840 }
2841
2842
2843 pub fn set_timing_offsets(&mut self, timing_offsets : HashMap<u8, f32>) {
2844 self.event.set_timing_offsets(&timing_offsets);
2845 }
2846
2847 pub fn normalize_hit_times(&mut self) {
2848 self.event.normalize_hit_times();
2849 }
2850
2851 pub fn lightspeed_cleaning(&mut self, t_err : f32) -> (Vec<u16>, Vec<f32>) {
2859 let mut pids = Vec::<u16>::new();
2862 let (pids_rm, twindows) = self.event.lightspeed_cleaning(t_err);
2863 for pid in pids_rm {
2864 pids.push(pid as u16);
2865 }
2866 (pids, twindows)
2867 }
2868
2869
2870 fn remove_non_causal_hits(&mut self) -> Vec<u16> {
2875 let mut pids = Vec::<u16>::new();
2878 for pid in self.event.remove_non_causal_hits() {
2879 pids.push(pid as u16);
2880 }
2881 pids
2882 }
2883
2884 #[getter]
2885 fn pointcloud(&self) -> Option<Vec<(f32,f32,f32,f32,f32)>> {
2886 self.event.get_pointcloud()
2887 }
2888
2889 #[getter]
2890 fn event_id(&self) -> u32 {
2891 self.event.event_id
2892 }
2893
2894 #[getter]
2895 fn event_status(&self) -> EventStatus {
2896 self.event.status
2897 }
2898
2899 fn get_missing_paddles_hg(&self, mapping : DsiJChPidMapping) -> Vec<u8> {
2902 self.event.get_missing_paddles_hg(&mapping)
2903 }
2904
2905 fn get_triggered_paddles(&self, mapping : DsiJChPidMapping) -> Vec<u8> {
2907 self.event.get_triggered_paddles(&mapping)
2908 }
2909
2910 #[getter]
2913 fn lost_hits(&self) -> u16 {
2914 self.event.drs_dead_lost_hits
2915 }
2916
2917 #[getter]
2920 fn rb_link_ids(&self) -> Vec<u8> {
2921 self.event.get_rb_link_ids()
2922 }
2923
2924 #[getter]
2926 pub fn trigger_hits(&self) -> PyResult<Vec<(u8, u8, (u8, u8), LTBThreshold)>> {
2927 Ok(self.event.get_trigger_hits())
2928 }
2929
2930 #[getter]
2933 pub fn trigger_sources(&self) -> Vec<TriggerType> {
2934 self.event.get_trigger_sources()
2935 }
2936
2937 #[getter]
2938 pub fn hits(&self) -> Vec<PyTofHit> {
2939 let mut hits = Vec::<PyTofHit>::new();
2940 for h in &self.event.hits {
2941 let mut pyhit = PyTofHit::new();
2942 pyhit.hit = h.clone();
2943 hits.push(pyhit);
2944 }
2945 hits
2946 }
2947
2948 #[getter]
2953 pub fn get_edep_umbrella(&self) -> f32 {
2954 self.event.get_edep_umbrella()
2955 }
2956
2957 #[getter]
2962 pub fn get_edep_cube(&self) -> f32 {
2963 self.event.get_edep_cube()
2964 }
2965
2966 #[getter]
2971 pub fn get_edep_cortina(&self) -> f32 {
2972 self.event.get_edep_cortina()
2973 }
2974
2975 #[getter]
2980 pub fn get_edep(&self) -> f32 {
2981 self.event.get_edep()
2982 }
2983
2984 #[getter]
2985 pub fn nhits(&self) -> usize {
2986 self.event.get_nhits()
2987 }
2988
2989 #[getter]
2990 pub fn nhits_umb(&self) -> usize {
2991 self.event.get_nhits_umb()
2992 }
2993
2994 #[getter]
2995 fn get_nhits_cbe(&self) -> usize {
2996 self.event.get_nhits_cbe()
2997 }
2998
2999 #[getter]
3000 fn get_nhits_cor(&self) -> usize {
3001 self.event.get_nhits_cor()
3002 }
3003
3004 #[getter]
3005 fn timestamp16(&self) -> u16 {
3006 self.event.timestamp16
3007 }
3008
3009 #[getter]
3010 fn timestamp32(&self) -> u32 {
3011 self.event.timestamp32
3012 }
3013
3014 #[getter]
3015 fn timestamp48(&self) -> u64 {
3016 self.event.get_timestamp48()
3017 }
3018
3019 #[getter]
3020 fn status(&self) -> EventStatus {
3021 self.event.status
3022 }
3023
3024 fn from_tofeventpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
3028 let tp = packet.get_tp();
3029 match TofEventSummary::from_tofeventpacket(tp) {
3030 Ok(event) => {
3031 self.event = event;
3032 return Ok(());
3033 }
3034 Err(err) => {
3035 let err_msg = format!("Unable to unpack TofPacket! {err}");
3036 return Err(PyIOError::new_err(err_msg));
3037 }
3038 }
3039 }
3040
3041 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
3043 let tp = packet.get_tp();
3044 match tp.unpack::<TofEventSummary>() {
3045 Ok(event) => {
3046 self.event = event;
3047 return Ok(());
3048 }
3049 Err(err) => {
3050 let err_msg = format!("Unable to unpack TofPacket! {err}");
3051 return Err(PyIOError::new_err(err_msg));
3052 }
3053 }
3054 }
3055
3056 fn pack(&self) -> PyTofPacket {
3058 let mut py_packet = PyTofPacket::new();
3059 py_packet.packet = self.event.pack();
3060 py_packet
3061 }
3062
3063
3064 fn __repr__(&self) -> PyResult<String> {
3065 Ok(format!("<PyO3Wrapper: {}>", self.event))
3066 }
3067}
3068
3069#[pyclass]
3070#[pyo3(name="TofEventHeader")]
3071#[derive(Debug, Clone)]
3072pub struct PyTofEventHeader {
3073 pub header : TofEventHeader
3074}
3075
3076impl PyTofEventHeader {
3077 fn __repr__(&self) -> PyResult<String> {
3078 Ok(format!("<PyO3Wrapper: {}>", self.header))
3079 }
3080}
3081
3082#[pyclass]
3083#[pyo3(name="TofEvent")]
3084#[derive(Debug, Clone)]
3085pub struct PyTofEvent {
3086 pub event : TofEvent,
3087}
3088
3089impl PyTofEvent {
3090 pub fn set_event(&mut self, event : TofEvent) {
3091 self.event = event;
3092 }
3093}
3094
3095
3096#[pymethods]
3097impl PyTofEvent {
3098 #[new]
3099 pub fn new() -> Self {
3100 Self {
3101 event : TofEvent::new(),
3102 }
3103 }
3104
3105 #[getter]
3106 fn has_any_mangling(&self) -> bool {
3107 self.event.has_any_mangling()
3108 }
3109
3110 fn copy(&self) -> Self {
3112 let mut copy_event = PyTofEvent::new();
3113 copy_event.event = self.event.clone();
3114 copy_event
3115 }
3116
3117 #[getter]
3118 fn pointcloud(&self) -> Option<Vec<(f32,f32,f32,f32,f32)>> {
3119 self.event.get_pointcloud()
3120 }
3121
3122 fn get_missing_paddles_hg(&self, mapping : DsiJChPidMapping) -> Vec<u8> {
3123 self.event.get_missing_paddles_hg(&mapping)
3124 }
3125
3126 fn get_missing_paddles_wf(&self, mapping : DsiJChPidMapping) -> Vec<u8> {
3127 self.event.get_missing_paddles_wf(&mapping)
3128 }
3129
3130 #[getter]
3131 fn event_id(&self) -> u32 {
3132 self.event.header.event_id
3133 }
3134
3135 #[getter]
3139 fn mastertriggerevent(&self) -> PyMasterTriggerEvent {
3140 let mut mte = PyMasterTriggerEvent::new();
3141 mte.set_event(self.event.mt_event.clone());
3142 mte
3143 }
3144
3145 #[getter]
3158 pub fn trigger_hits(&self) -> PyResult<Vec<(u8, u8, (u8, u8), LTBThreshold)>> {
3159 Ok(self.event.mt_event.get_trigger_hits())
3160 }
3161
3162 #[getter]
3165 fn rb_link_ids(&self) -> Vec<u8> {
3166 self.event.mt_event.get_rb_link_ids()
3167 }
3168
3169 #[getter]
3170 fn rbevents(&self) -> Vec<PyRBEvent> {
3171 let mut rbevents = Vec::<PyRBEvent>::with_capacity(5);
3173 for k in &self.event.rb_events {
3174 let mut pyrbevent = PyRBEvent::new();
3175 pyrbevent.set_event(k.clone());
3176 rbevents.push(pyrbevent);
3177 }
3178 rbevents
3179 }
3180
3181 #[getter]
3182 fn hits(&self) -> Vec<PyTofHit> {
3183 let mut hits = Vec::<PyTofHit>::new();
3184 for ev in &self.event.rb_events {
3185 for h in &ev.hits {
3186 let mut pyhit = PyTofHit::new();
3187 pyhit.hit = *h;
3188 hits.push(pyhit);
3189 }
3190 }
3191 hits
3192 }
3193
3194 #[getter]
3195 fn waveforms(&self) -> Vec<PyRBWaveform> {
3196 let mut wfs = Vec::<PyRBWaveform>::new();
3197 for wf in &self.event.get_rbwaveforms() {
3198 let mut pywf = PyRBWaveform::new();
3199 pywf.wf = wf.clone();
3200 wfs.push(pywf);
3201 }
3202 wfs
3203 }
3204
3205 fn get_summary(&self) -> PyTofEventSummary {
3206 let ts = self.event.get_summary();
3207 let mut pyts = PyTofEventSummary::new();
3208 pyts.event = ts;
3209 return pyts;
3210 }
3211
3212 fn pack(&self) -> PyTofPacket {
3213 let packet = self.event.pack();
3214 let mut pytp = PyTofPacket::new();
3215 pytp.set_tp(packet);
3216 pytp
3217 }
3218
3219 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
3220 let tp = packet.get_tp();
3221 if tp.packet_type != PacketType::TofEvent {
3222 let err_msg = format!("This packet is of type {} but needs to be of type 'TofEvent'!", tp.packet_type);
3223 return Err(PyValueError::new_err(err_msg));
3224 }
3225 match tp.unpack::<TofEvent>() {
3226 Ok(ev) => {
3227 self.event = ev;
3228 return Ok(());
3229 }
3230 Err(err) => {
3231 let err_msg = format!("Unable to unpack TofPacket! {err}");
3232 return Err(PyIOError::new_err(err_msg));
3233 }
3234 }
3235 }
3236
3237 #[pyo3(signature = (filename, start=0, nevents=0))]
3238 fn from_file(&self, filename : String, start : usize, nevents : usize) -> Vec<PyTofEvent> {
3239 let mut reader = TofPacketReader::new(filename);
3240 reader.filter = PacketType::TofEvent;
3241 reader.skip_ahead = start;
3242 reader.stop_after = nevents;
3243 let mut capacity = 1000;
3244 if nevents > 0 {
3245 capacity = nevents;
3246 }
3247 let mut events = Vec::<PyTofEvent>::with_capacity(capacity);
3248 while let Some(tp) = reader.get_next_packet() {
3249 if let Ok(ev) = tp.unpack::<TofEvent>() {
3251 let mut pyev = PyTofEvent::new();
3252 pyev.set_event(ev);
3253 events.push(pyev);
3254 } else {
3255 continue;
3256 }
3257 }
3258 events
3259 }
3260
3261 #[getter]
3262 pub fn nhits(&self) -> usize {
3263 self.event.get_nhits()
3264 }
3265
3266 #[getter]
3267 pub fn nhits_umb(&self) -> usize {
3268 self.event.get_nhits_umb()
3269 }
3270
3271 fn __repr__(&self) -> PyResult<String> {
3272 Ok(format!("<PyO3Wrapper: {}>", self.event))
3273 }
3274}
3275
3276
3277#[pyclass]
3278#[pyo3(name="RBEvent")]
3279pub struct PyRBEvent {
3280 event : RBEvent,
3281}
3282
3283impl PyRBEvent {
3284 pub fn set_event(&mut self, event : RBEvent) {
3285 self.event = event;
3286 }
3287}
3288
3289#[pymethods]
3290impl PyRBEvent {
3291 #[new]
3292 pub fn new() -> Self {
3293 Self {
3294 event : RBEvent::new(),
3295 }
3296 }
3297
3298 #[getter]
3299 fn status(&self) -> EventStatus {
3300 self.event.status
3301 }
3302
3303 fn get_waveform<'_py>(&self, py: Python<'_py>, channel : usize) -> PyResult<Bound<'_py, PyArray1<u16>>> {
3304 let wf = self.event.get_channel_by_id(channel).unwrap().clone();
3305 let arr = PyArray1::<u16>::from_vec(py, wf);
3306 Ok(arr)
3307 }
3308
3309 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
3321 let tp = packet.get_tp();
3322 match tp.unpack::<RBEvent>() {
3323 Ok(event) => {
3324 self.event = event;
3325 return Ok(());
3326 }
3327 Err(err) => {
3328 let err_msg = format!("Unable to unpack TofPacket! {err}");
3329 return Err(PyIOError::new_err(err_msg));
3330 }
3331 }
3332 }
3333
3334 #[getter]
3335 fn header(&self) -> PyRBEventHeader {
3336 let mut py_header = PyRBEventHeader::new();
3337 py_header.header = self.event.header.clone();
3339 py_header
3340 }
3341
3342 #[getter]
3343 fn waveforms(&self) -> Vec<PyRBWaveform> {
3344 let mut wfs = Vec::<PyRBWaveform>::new();
3345 for wf in &self.event.get_rbwaveforms() {
3346 let mut pywf = PyRBWaveform::new();
3347 pywf.wf = wf.clone();
3348 wfs.push(pywf);
3349 }
3350 wfs
3351 }
3352
3353 fn __repr__(&self) -> PyResult<String> {
3354 Ok(format!("<PyO3Wrapper: {}>", self.event))
3355 }
3356}
3357
3358#[pyclass]
3359#[pyo3(name="TofHit")]
3360pub struct PyTofHit {
3361 hit : TofHit,
3362}
3363
3364#[pymethods]
3365impl PyTofHit {
3366 #[new]
3367 fn new() -> Self {
3368 Self {
3369 hit : TofHit::new(),
3370 }
3371 }
3372
3373 pub fn set_timing_offset(&mut self, offset : f32) {
3374 self.hit.timing_offset = offset;
3375 }
3376
3377 pub fn distance(&self, other : &PyTofHit) -> f32 {
3383 self.hit.distance(&other.hit)
3385 }
3386
3387 fn set_paddle(&mut self, plen : f32, clen : f32, coax_cbl_time : f32, hart_cbl_time : f32 ) {
3390 self.hit.paddle_len = plen;
3391 self.hit.cable_len = clen;
3392 self.hit.coax_cable_time = coax_cbl_time;
3393 self.hit.hart_cable_time = hart_cbl_time;
3394 }
3395
3396 #[getter]
3397 fn x(&self) -> f32 {
3398 self.hit.x
3399 }
3400
3401 #[getter]
3402 fn y(&self) -> f32 {
3403 self.hit.y
3404 }
3405
3406 #[getter]
3407 fn z(&self) -> f32 {
3408 self.hit.z
3409 }
3410
3411 #[getter]
3412 fn get_t0_uncorrected(&self) -> f32 {
3413 self.hit.get_t0_uncorrected()
3414 }
3415
3416 #[getter]
3428 fn get_event_t0(&self) -> f32 {
3429 self.hit.get_t0()
3430 }
3431
3432 #[getter]
3433 fn get_obeys_causality(&self) -> bool {
3434 self.hit.obeys_causality()
3435 }
3436
3437 #[getter]
3438 fn get_coax_cbl_time(&self) -> f32 {
3439 self.hit.coax_cable_time
3440 }
3441
3442 #[getter]
3443 fn get_hart_cbl_time(&self) -> f32 {
3444 self.hit.hart_cable_time
3445 }
3446
3447 #[getter]
3453 fn t0(&self) -> f32 {
3454 self.hit.get_t0()
3455 }
3456
3457 #[getter]
3458 fn get_phase_delay(&self) -> f32 {
3459 self.hit.get_phase_delay()
3460 }
3461
3462 #[getter]
3463 fn get_cable_delay(&self) -> f32 {
3464 self.hit.get_cable_delay()
3465 }
3466
3467 #[getter]
3468 fn version(&self) -> ProtocolVersion {
3469 self.hit.version
3470 }
3471
3472 #[getter]
3473 fn phase(&self) -> f32 {
3474 self.hit.phase.to_f32()
3475 }
3476
3477 #[getter]
3478 fn baseline_a(&self) -> f32 {
3479 self.hit.baseline_a.to_f32()
3480 }
3481
3482 #[getter]
3483 fn baseline_a_rms(&self) -> f32 {
3484 self.hit.baseline_a_rms.to_f32()
3485 }
3486
3487 #[getter]
3488 fn baseline_b(&self) -> f32 {
3489 self.hit.baseline_b.to_f32()
3490 }
3491
3492 #[getter]
3493 fn baseline_b_rms(&self) -> f32 {
3494 self.hit.baseline_b_rms.to_f32()
3495 }
3496
3497 #[getter]
3498 fn peak_a(&self) -> f32 {
3499 self.hit.get_peak_a()
3500 }
3501
3502 #[getter]
3503 fn peak_b(&self) -> f32 {
3504 self.hit.get_peak_b()
3505 }
3506
3507 #[getter]
3508 fn charge_a(&self) -> f32 {
3509 self.hit.get_charge_a()
3510 }
3511
3512 #[getter]
3513 fn charge_b(&self) -> f32 {
3514 self.hit.get_charge_b()
3515 }
3516
3517 #[getter]
3518 fn time_a(&self) -> f32 {
3519 self.hit.get_time_a()
3520 }
3521
3522 #[getter]
3523 fn time_b(&self) -> f32 {
3524 self.hit.get_time_b()
3525 }
3526
3527 #[getter]
3533 fn pos(&self) -> f32 {
3534 self.hit.get_pos()
3535 }
3536
3537 #[getter]
3539 fn paddle_id(&self) -> u8 {
3540 self.hit.paddle_id
3541 }
3542
3543 #[getter]
3544 fn edep(&self) -> f32 {
3545 self.hit.get_edep()
3546 }
3547
3548 #[getter]
3549 fn get_paddle_len(&self) -> f32 {
3550 self.hit.paddle_len
3551 }
3552
3553 fn __repr__(&self) -> PyResult<String> {
3554 Ok(format!("<PyO3Wrapper: {}>", self.hit))
3555 }
3556}
3557
3558#[pyclass]
3559#[pyo3(name="RBWaveform")]
3560pub struct PyRBWaveform {
3561 pub wf : RBWaveform,
3562}
3563
3564#[pymethods]
3565impl PyRBWaveform {
3566 #[new]
3567 fn new() -> Self {
3568 Self {
3569 wf : RBWaveform::new(),
3570 }
3571 }
3572 fn get_tot_a(&self, threshold : f32) -> f32 {
3579 self.wf.time_over_threshold_a(threshold)
3580 }
3581
3582 fn get_tot_b(&self, threshold : f32) -> f32 {
3589 self.wf.time_over_threshold_b(threshold)
3590 }
3591
3592 fn calibrate(&mut self, cali : &PyRBCalibration) -> PyResult<()> {
3595 match self.wf.calibrate(&cali.cali) {
3596 Ok(_) => {
3597 return Ok(());
3598 }
3599 Err(err) => {
3600 return Err(PyValueError::new_err(err.to_string()));
3601 }
3602 }
3603 }
3604
3605 #[getter]
3607 fn paddle_id(&self) -> u8 {
3608 self.wf.paddle_id
3609 }
3610
3611 #[getter]
3612 fn rb_id(&self) -> u8 {
3613 self.wf.rb_id
3614 }
3615
3616 #[getter]
3617 fn event_id(&self) -> u32 {
3618 self.wf.event_id
3619 }
3620
3621 #[getter]
3622 fn rb_channel_a(&self) -> u8 {
3623 self.wf.rb_channel_a
3624 }
3625
3626 #[getter]
3627 fn rb_channel_b(&self) -> u8 {
3628 self.wf.rb_channel_b
3629 }
3630
3631 #[getter]
3632 fn stop_cell(&self) -> u16 {
3633 self.wf.stop_cell
3634 }
3635
3636 #[getter]
3637 fn adc_a<'_py>(&self, py: Python<'_py>) -> PyResult<Bound<'_py, PyArray1<u16>>> {
3638 let wf = self.wf.adc_a.clone();
3639 let arr = PyArray1::<u16>::from_vec(py, wf);
3640 Ok(arr)
3641 }
3642
3643 #[getter]
3644 fn adc_b<'_py>(&self, py: Python<'_py>) -> PyResult<Bound<'_py, PyArray1<u16>>> {
3645 let wf = self.wf.adc_b.clone();
3646 let arr = PyArray1::<u16>::from_vec(py, wf);
3647 Ok(arr)
3648 }
3649
3650 #[getter]
3651 fn voltages_a<'_py>(&self, py: Python<'_py>) -> PyResult<Bound<'_py, PyArray1<f32>>> {
3652 let wf = self.wf.voltages_a.clone();
3653 let arr = PyArray1::<f32>::from_vec(py, wf);
3654 Ok(arr)
3655 }
3656
3657 #[getter]
3658 fn times_a<'_py>(&self, py: Python<'_py>) -> PyResult<Bound<'_py, PyArray1<f32>>> {
3659 let times = self.wf.nanoseconds_a.clone();
3660 let arr = PyArray1::<f32>::from_vec(py, times);
3661 Ok(arr)
3662 }
3663
3664 #[getter]
3665 fn voltages_b<'_py>(&self, py: Python<'_py>) -> PyResult<Bound<'_py, PyArray1<f32>>> {
3666 let wf = self.wf.voltages_b.clone();
3667 let arr = PyArray1::<f32>::from_vec(py, wf);
3668 Ok(arr)
3669 }
3670
3671 #[getter]
3672 fn times_b<'_py>(&self, py: Python<'_py>) -> PyResult<Bound<'_py, PyArray1<f32>>> {
3673 let times = self.wf.nanoseconds_b.clone();
3674 let arr = PyArray1::<f32>::from_vec(py, times);
3675 Ok(arr)
3676 }
3677
3678 fn apply_spike_filter(&mut self) {
3679 self.wf.apply_spike_filter();
3680 }
3681
3682 fn from_tofpacket(&mut self, packet : &PyTofPacket) -> PyResult<()> {
3683 let tp = packet.get_tp();
3684 match tp.unpack::<RBWaveform>() {
3685 Ok(wf) => {
3686 self.wf = wf;
3687 return Ok(());
3688 }
3689 Err(err) => {
3690 let err_msg = format!("Unable to unpack TofPacket of type {} ! {err}", packet.get_tp().packet_type);
3691 return Err(PyIOError::new_err(err_msg));
3692 }
3693 }
3694 }
3695
3696 fn __repr__(&self) -> PyResult<String> {
3697 Ok(format!("<PyO3Wrapper: {}>", self.wf))
3698 }
3699}
3700
3701
3702