1use crate::prelude::*;
5use std::f32::consts::PI;
6
7#[derive(Debug,Copy,Clone,PartialEq)]
11pub struct Peak {
12 pub paddle_end_id : u16,
13 pub time : f32,
14 pub charge : f32,
15 pub height : f32
16}
17
18impl Peak {
19 pub fn new() -> Self {
20 Self {
21 paddle_end_id : 40,
23 time : 0.0,
24 charge : 0.0,
25 height : 0.0,
26 }
27 }
28}
29
30impl Default for Peak {
31 fn default() -> Self {
32 Self::new()
33 }
34}
35
36impl fmt::Display for Peak {
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 write!(f, "<Peak:
39 p_end_id : {:.2}
40 time // charge // height : {:.2} // {:.2} // {:.2}>",
41 self.paddle_end_id,
42 self.time,
43 self.charge,
44 self.height)
45 }
46}
47
48#[derive(Debug,Copy,Clone,PartialEq)]
63#[cfg_attr(feature = "pybindings", pyclass)]
64pub struct TofHit {
65
66 pub paddle_id : u8,
71 pub time_a : f16,
72 pub time_b : f16,
73 pub peak_a : f16,
74 pub peak_b : f16,
75 pub charge_a : f16,
76 pub charge_b : f16,
77 pub version : ProtocolVersion,
78 pub quality : EventQuality,
80 pub baseline_a : f16,
81 pub baseline_a_rms : f16,
82 pub baseline_b : f16,
83 pub baseline_b_rms : f16,
84 pub phase : f16,
86 pub tot_low_a : f16,
87 pub tot_low_b : f16,
88 pub tot_high_a : f16,
89 pub tot_high_b : f16,
90 pub tot_slp_low_a : f16,
91 pub tot_slp_low_b : f16,
92 pub tot_slp_high_a : f16,
93 pub tot_slp_high_b : f16,
94 pub paddle_len : f32,
101 pub timing_offset : f32,
103 pub coax_cable_time: f32,
104 pub hart_cable_time: f32,
105 pub event_t0 : f32,
108 pub x : f32,
109 pub y : f32,
110 pub z : f32,
111
112 pub valid : bool,
115}
116
117impl TofHit {
119 pub fn new() -> Self {
120 Self{
121 paddle_id : 0,
122 time_a : f16::from_f32(0.0),
123 time_b : f16::from_f32(0.0),
124 peak_a : f16::from_f32(0.0),
125 peak_b : f16::from_f32(0.0),
126 charge_a : f16::from_f32(0.0),
127 charge_b : f16::from_f32(0.0),
128 paddle_len : f32::NAN,
129 timing_offset : 0.0,
130 coax_cable_time : f32::NAN,
131 hart_cable_time : f32::NAN,
132 event_t0 : f32::NAN,
133 x : f32::NAN,
134 y : f32::NAN,
135 z : f32::NAN,
136
137 valid : true,
138 version : ProtocolVersion::V1,
140 quality : EventQuality::Unknown,
141 baseline_a : f16::from_f32(0.0),
142 baseline_a_rms : f16::from_f32(0.0),
143 baseline_b : f16::from_f32(0.0),
144 baseline_b_rms : f16::from_f32(0.0),
145 phase : f16::from_f32(0.0),
146 tot_low_a : f16::from_f32(0.0),
147 tot_low_b : f16::from_f32(0.0),
148 tot_high_a : f16::from_f32(0.0),
149 tot_high_b : f16::from_f32(0.0),
150 tot_slp_low_a : f16::from_f32(0.0),
151 tot_slp_low_b : f16::from_f32(0.0),
152 tot_slp_high_a : f16::from_f32(0.0),
153 tot_slp_high_b : f16::from_f32(0.0),
154 }
155 }
156
157 pub fn add_peak(&mut self, peak : &Peak) {
161 if self.paddle_id != TofHit::get_pid(peak.paddle_end_id) {
162 }
164 if peak.paddle_end_id < 1000 {
165 error!("Invalide paddle end id {}", peak.paddle_end_id);
166 }
167 if peak.paddle_end_id > 2000 {
168 self.set_time_b (peak.time);
169 self.set_peak_b (peak.height);
170 self.set_charge_b(peak.charge);
171 } else if peak.paddle_end_id < 2000 {
172 self.set_time_a (peak.time);
173 self.set_peak_a (peak.height);
174 self.set_charge_a(peak.charge);
175 }
176 }
177
178 pub fn set_time_b(&mut self, t : f32) {
180 self.time_b = f16::from_f32(t)
181 }
182
183 pub fn set_time_a(&mut self, t : f32) {
184 self.time_a = f16::from_f32(t);
185 }
186
187 pub fn set_peak_a(&mut self, p : f32) {
188 self.peak_a = f16::from_f32(p)
189 }
190
191 pub fn set_peak_b(&mut self, p : f32) {
192 self.peak_b = f16::from_f32(p)
193 }
194
195 pub fn set_charge_a(&mut self, c : f32) {
196 self.charge_a = f16::from_f32(c)
197 }
198
199 pub fn set_charge_b(&mut self, c : f32) {
200 self.charge_b = f16::from_f32(c)
201 }
202}
203
204#[cfg(feature="pybindings")]
208#[pymethods]
209impl TofHit {
210
211 #[getter]
213 #[pyo3(name="paddle_id")]
214 fn paddle_id_py(&self) -> u8 {
215 self.paddle_id
216 }
217
218 #[getter]
219 #[pyo3(name="timing_offset")]
220 fn get_timing_offset(&self) -> f32 {
221 self.timing_offset
222 }
223
224 #[getter]
228 #[pyo3(name="paddle_len")]
229 fn get_paddle_len_py(&self) -> f32 {
230 self.paddle_len
231 }
232
233 #[pyo3(name="set_paddle")]
236 fn set_paddle_py(&mut self, paddle : &TofPaddle) -> PyResult<()> {
238 Ok(self.set_paddle(paddle)?)
239 }
240
241 #[getter]
244 #[pyo3(name="coax_cbl_time")]
245 fn get_coax_cbl_time(&self) -> f32 {
246 self.coax_cable_time
247 }
248
249 #[getter]
252 #[pyo3(name="hart_cbl_time")]
253 fn get_hart_cbl_time(&self) -> f32 {
254 self.hart_cable_time
255 }
256
257 #[getter]
266 #[pyo3(name="pos")]
267 fn get_pos_py(&self) -> f32 {
268 self.get_pos()
269 }
270
271 #[getter]
272 #[pyo3(name="x")]
273 fn x_py(&self) -> f32 {
274 self.x
275 }
276
277 #[getter]
278 #[pyo3(name="y")]
279 fn y_py(&self) -> f32 {
280 self.y
281 }
282
283 #[getter]
284 #[pyo3(name="z")]
285 fn z_py(&self) -> f32 {
286 self.z
287 }
288
289 #[getter]
290 #[pyo3(name="version")]
291 fn version_py(&self) -> ProtocolVersion {
292 self.version
293 }
294
295 #[getter]
296 #[pyo3(name="phase")]
297 fn phase_py(&self) -> f32 {
298 self.phase.to_f32()
299 }
300
301 #[getter]
302 #[pyo3(name="phase_ns")]
303 fn phase_ns_py(&self) -> f32 {
304 self.get_phase_ns()
305 }
306
307 #[getter]
308 #[pyo3(name="cable_delay")]
309 fn get_cable_delay_py(&self) -> f32 {
311 self.get_cable_delay()
312 }
313
314 #[getter]
317 #[pyo3(name="phase_delay")]
318 fn get_phase_delay_py(&self) -> f32 {
319 self.get_phase_delay()
320 }
321
322 #[getter]
327 #[pyo3(name="t0")]
328 fn get_t0_py(&self) -> f32 {
329 self.get_global_t0()
330 }
331
332 #[getter]
344 #[pyo3(name="event_t0")]
345 fn get_event_t0_py(&self) -> f32 {
346 self.get_global_t0()
348 }
349
350 #[getter]
356 #[pyo3(name="t0_uncorrected")]
357 fn get_t0_uncorrected_py(&self) -> f32 {
358 self.get_t0_uncorrected()
359 }
360
361 #[getter]
363 #[pyo3(name="edep")]
364 fn get_edep_py(&self) -> f32 {
365 self.get_edep()
366 }
367
368 #[getter]
370 #[pyo3(name="edep_att")]
371 fn get_edep_att_py(&self) -> f32 {
372 self.get_edep_att()
373 }
374
375 #[getter]
377 #[pyo3(name="edep_att_birk")]
378 fn get_edep_att_birk_py(&self) -> f32 {
379 self.get_edep_birk()
380 }
381
382 #[getter]
384 #[pyo3(name="time_a")]
385 fn get_time_a_py(&self) -> f32 {
386 self.get_time_a()
387 }
388
389 #[getter]
391 #[pyo3(name="time_b")]
392 fn get_time_b_py(&self) -> f32 {
393 self.get_time_b()
394 }
395
396 #[getter]
397 #[pyo3(name="TOT_low_a")]
398 fn get_tot_low_a_py(&self) -> f32 {
399 self.get_tot_low_a()
400 }
401
402 #[getter]
403 #[pyo3(name="TOT_low_b")]
404 fn get_tot_low_b_py(&self) -> f32 {
405 self.get_tot_low_b()
406 }
407
408 #[getter]
409 #[pyo3(name="TOT_high_a")]
410 fn get_tot_high_a_py(&self) -> f32 {
411 self.get_tot_high_a()
412 }
413
414 #[getter]
415 #[pyo3(name="TOT_high_b")]
416 fn get_tot_high_b_py(&self) -> f32 {
417 self.get_tot_high_b()
418 }
419
420 #[getter]
421 #[pyo3(name="TOT_slp_low_a")]
422 fn get_tot_slp_low_a_py(&self) -> f32 {
423 self.get_tot_slp_low_a()
424 }
425
426 #[getter]
427 #[pyo3(name="TOT_slp_low_b")]
428 fn get_tot_slp_low_b_py(&self) -> f32 {
429 self.get_tot_slp_low_b()
430 }
431
432 #[getter]
433 #[pyo3(name="TOT_slp_high_a")]
434 fn get_tot_slp_high_a_py(&self) -> f32 {
435 self.get_tot_slp_high_a()
436 }
437
438 #[getter]
439 #[pyo3(name="TOT_slp_high_b")]
440 fn get_tot_slp_high_b_py(&self) -> f32 {
441 self.get_tot_slp_high_b()
442 }
443
444 #[getter]
445 #[pyo3(name="peak_a")]
446 fn get_peak_a_py(&self) -> f32 {
447 self.get_peak_a()
448 }
449
450 #[getter]
451 #[pyo3(name="peak_b")]
452 fn get_peak_b_py(&self) -> f32 {
453 self.get_peak_b()
454 }
455
456 #[getter]
457 #[pyo3(name="charge_a")]
458 fn get_charge_a_py(&self) -> f32 {
459 self.get_charge_a()
460 }
461
462 #[getter]
463 #[pyo3(name="charge_b")]
464 fn get_charge_b_py(&self) -> f32 {
465 self.get_charge_b()
466 }
467
468 #[getter]
469 #[pyo3(name="baseline_a")]
470 fn get_bl_a_py(&self) -> f32 {
471 self.get_bl_a()
472 }
473
474 #[getter]
475 #[pyo3(name="baseline_b")]
476 fn get_bl_b_py(&self) -> f32 {
477 self.get_bl_b()
478 }
479
480 #[getter]
481 #[pyo3(name="baseline_a_rms")]
482 fn get_bl_a_rms_py(&self) -> f32 {
483 self.get_bl_a_rms()
484 }
485
486 #[getter]
487 #[pyo3(name="baseline_b_rms")]
488 fn get_bl_b_rms_py(&self) -> f32 {
489 self.get_bl_b_rms()
490 }
491}
492
493#[cfg_attr(feature="pybindings", pymethods)]
497impl TofHit {
498 pub fn distance(&self, other : &TofHit) -> f32 {
504 ((self.x - other.x).powi(2) + (self.y - other.y).powi(2) + (self.z - other.z).powi(2)).sqrt()
505 }
506
507 pub fn obeys_causality(&self) -> bool {
511 (self.paddle_len/(10.0*C_LIGHT_PADDLE)) - f32::abs(self.time_a.to_f32() - self.time_b.to_f32()) > 0.0
512 && self.get_t0_uncorrected() > 0.0
513 }
514}
515
516#[cfg(feature="pybindings")]
517pythonize!(TofHit);
518
519impl TofHit {
521
522 pub fn get_pos(&self) -> f32 {
531 let t0 = self.get_t0_uncorrected();
532 let clean_t_a = self.time_a.to_f32() - t0;
533 return clean_t_a*C_LIGHT_PADDLE*10.0;
534 }
535
536 pub fn get_cable_delay(&self) -> f32 {
538 self.hart_cable_time - self.coax_cable_time
539 }
540
541 pub fn get_phase_delay(&self) -> f32 {
544 let freq : f32 = 20.0e6;
545 let phase = self.phase.to_f32();
546 (phase/(2.0*PI*freq))*1.0e9f32
557 }
558
559 pub fn get_global_t0(&self) -> f32 {
564 self.event_t0 }
567
568 pub fn get_t0_uncorrected(&self) -> f32 {
574 0.5*(self.time_a.to_f32() + self.time_b.to_f32() - (self.paddle_len/(10.0*C_LIGHT_PADDLE)))
575 }
576
577 pub fn get_edep(&self) -> f32 {
579 (1.29/34.3)*(self.peak_a.to_f32() + self.peak_b.to_f32()) / 2.0
580 }
581
582 pub fn get_edep_att(&self) -> f32 {
584 let x0 = self.get_pos();
585 let att_a = ((3.9-0.00126*(x0)).exp()+22.15) / ((3.9).exp()+22.15);
586 let att_b = ((3.9-0.00126*(self.paddle_len - x0)).exp()+22.15) / ((3.9).exp()+22.15);
587 let edep = 0.0159 * (self.get_peak_a()/att_a + self.get_peak_b()/att_b) / 2.; return edep;
589 }
590
591 pub fn get_edep_birk(&self) -> f32 {
592 let x0 = self.get_pos();
593 let att_a = ((3.9-0.00126*(x0)).exp()+22.15) / ((3.9).exp()+22.15);
594 let att_b = ((3.9-0.00126*(self.paddle_len - x0)).exp()+22.15) / ((3.9).exp()+22.15);
595 let v = (self.get_peak_a()/att_a + self.get_peak_b()/att_b) / 2.0;
596 let edep = -1000.0*v/(21.0*v - 35260.0);
597 return edep;
598 }
599
600 pub fn get_time_a(&self) -> f32 {
602 self.time_a.to_f32()
603 }
604
605 pub fn get_time_b(&self) -> f32 {
607 self.time_b.to_f32()
608 }
609
610 pub fn get_tot_low_a(&self) -> f32 {
611 self.tot_low_a.to_f32()
612 }
613
614 pub fn get_tot_low_b(&self) -> f32 {
615 self.tot_low_b.to_f32()
616 }
617
618 pub fn get_tot_high_a(&self) -> f32 {
619 self.tot_high_a.to_f32()
620 }
621
622 pub fn get_tot_high_b(&self) -> f32 {
623 self.tot_high_b.to_f32()
624 }
625
626 pub fn get_tot_slp_low_a(&self) -> f32 {
627 self.tot_slp_low_a.to_f32()
628 }
629
630 pub fn get_tot_slp_low_b(&self) -> f32 {
631 self.tot_slp_low_b.to_f32()
632 }
633
634 pub fn get_tot_slp_high_a(&self) -> f32 {
635 self.tot_slp_high_a.to_f32()
636 }
637 pub fn get_tot_slp_high_b(&self) -> f32 {
638 self.tot_slp_high_b.to_f32()
639 }
640 pub fn get_peak_a(&self) -> f32 {
641 self.peak_a.to_f32()
642 }
643
644 pub fn get_peak_b(&self) -> f32 {
645 self.peak_b.to_f32()
646 }
647
648 pub fn get_charge_a(&self) -> f32 {
649 self.charge_a.to_f32()
650 }
651
652 pub fn get_charge_b(&self) -> f32 {
653 self.charge_b.to_f32()
654 }
655
656 pub fn get_bl_a(&self) -> f32 {
657 self.baseline_a.to_f32()
658 }
659
660 pub fn get_bl_b(&self) -> f32 {
661 self.baseline_b.to_f32()
662 }
663
664 pub fn get_bl_a_rms(&self) -> f32 {
665 self.baseline_a_rms.to_f32()
666 }
667
668 pub fn get_bl_b_rms(&self) -> f32 {
669 self.baseline_b_rms.to_f32()
670 }
671
672
673 pub fn get_pid(paddle_end_id : u16) -> u8 {
684 if paddle_end_id < 1000 {
685 return 0;
686 }
687 if paddle_end_id > 2000 {
688 return (paddle_end_id - 2000) as u8;
689 }
690 if paddle_end_id < 2000 {
691 return (paddle_end_id - 1000) as u8;
692 }
693 return 0;
694 }
695
696 pub fn get_phase_ns(&self) -> f32 {
699 let mut phase_ns = 50.0*self.phase.to_f32()/(2.0*PI);
700 phase_ns += 50.0;
706 phase_ns
707 }
708
709 pub fn get_phase_rollovers(&self) -> i16 {
710 let mut phase = self.phase.to_f32();
711 let mut ro = 0i16;
712 while phase < PI/2.0 {
713 phase += PI/2.0;
714 ro += 1;
715 }
716 while phase > PI/2.0 {
717 phase -= PI/2.0;
718 ro -= 1;
719 }
720 ro
721 }
722
723
724}
725
726#[cfg(feature="database")]
727impl TofHit {
728 pub fn set_paddle(&mut self, paddle : &TofPaddle) -> Result<(), UserError> {
729 if self.paddle_id != paddle.paddle_id as u8 {
730 return Err(UserError::WrongPaddleId);
731 }
732 self.coax_cable_time = paddle.coax_cable_time;
733 self.hart_cable_time = paddle.harting_cable_time;
734 self.paddle_len = paddle.length * 10.0; let pr = paddle.principal();
736 let rel_pos = self.get_pos();
738 let pos = (paddle.global_pos_x_l0_A*10.0 + pr.0*rel_pos,
739 paddle.global_pos_y_l0_A*10.0 + pr.1*rel_pos,
740 paddle.global_pos_z_l0_A*10.0 + pr.2*rel_pos);
741 self.x = pos.0;
742 self.y = pos.1;
743 self.z = pos.2;
744 Ok(())
745 }
746}
747
748impl TofHit {
752 pub fn get_t0_with_local_corrections(&self) -> f32 {
753 self.get_t0_uncorrected() + self.get_cable_delay() + self.get_phase_ns()
754 }
755}
756
757
758impl Default for TofHit {
762 fn default() -> Self {
763 Self::new()
764 }
765}
766
767impl fmt::Display for TofHit {
768 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
769 let mut paddle_info = String::from("");
770 if self.paddle_len == 0.0 {
771 paddle_info = String::from("NOT SET!");
772 }
773 write!(f, "<TofHit (version : {}):
774 Paddle ID {}
775 Peak:
776 LE Time A/B {:.2} {:.2}
777 Height A/B {:.2} {:.2}
778 Charge A/B {:.2} {:.2}
779 ** time over threshold information
780 Lo TOT A/B {:.2} {:.2}
781 Hi TOT A/B {:.2} {:.2}
782 Lo Slope A/B {:.2} {:.2}
783 Hi Slope A/B {:.2} {:.2}
784 ** paddle {} **
785 Length {:.2}
786 Timing offset {:.2} (ns)
787 Coax cbl time {:.2}
788 Hart cbl time {:.2}
789 ** reconstructed interaction
790 energy_dep {:.2}
791 edep_att {:.2}
792 pos_across {:.2}
793 t0 (uncorr) {:.2}
794 t0 (local c) {:.2}
795 t0 (global c) {:.2}
796 ev t0 [DEPR] {:.2}
797 x, y, z {:.2} {:.2} {:.2}
798 ** V1 variables
799 phase (ch9) {:.4}
800 n phs ro {}
801 baseline A/B {:.2} {:.2}
802 bl. RMS A/B {:.2} {:.2}>",
803 self.version,
804 self.paddle_id,
805 self.get_time_a(),
806 self.get_time_b(),
807 self.get_peak_a(),
808 self.get_peak_b(),
809 self.get_charge_a(),
810 self.get_charge_b(),
811 self.get_tot_low_a(),
812 self.get_tot_low_b(),
813 self.get_tot_high_a(),
814 self.get_tot_high_b(),
815 self.get_tot_slp_low_a(),
816 self.get_tot_slp_low_b(),
817 self.get_tot_slp_high_a(),
818 self.get_tot_slp_high_b(),
819 paddle_info,
820 self.paddle_len,
821 self.timing_offset,
822 self.coax_cable_time,
823 self.hart_cable_time,
824 self.get_edep(),
825 self.get_edep_att(),
826 self.get_pos(),
827 self.get_t0_uncorrected(),
829 self.get_t0_with_local_corrections(),
830 self.get_global_t0(),
831 self.event_t0,
832 self.x,
833 self.y,
834 self.z,
835 self.phase,
836 self.get_phase_rollovers(),
837 self.baseline_a,
838 self.baseline_b,
839 self.baseline_a_rms,
840 self.baseline_b_rms,
841 )
842 }
843}
844
845impl Serialization for TofHit {
846
847 const HEAD : u16 = 61680; const TAIL : u16 = 3855;
849 const SIZE : usize = 44; fn to_bytestream(&self) -> Vec<u8> {
862
863 let mut bytestream = Vec::<u8>::with_capacity(Self::SIZE);
864 bytestream.extend_from_slice(&Self::HEAD.to_le_bytes());
865 bytestream.push(self.paddle_id);
866 bytestream.extend_from_slice(&self.time_a .to_le_bytes());
867 bytestream.extend_from_slice(&self.time_b .to_le_bytes());
868 bytestream.extend_from_slice(&self.peak_a .to_le_bytes());
869 bytestream.extend_from_slice(&self.peak_b .to_le_bytes());
870 bytestream.extend_from_slice(&self.charge_a .to_le_bytes());
871 bytestream.extend_from_slice(&self.charge_b .to_le_bytes());
872 bytestream.extend_from_slice(&self.tot_low_a .to_le_bytes());
873 bytestream.extend_from_slice(&self.baseline_a .to_le_bytes());
874 bytestream.extend_from_slice(&self.baseline_a_rms.to_le_bytes());
875 bytestream.extend_from_slice(&self.phase .to_le_bytes());
876 let quality_version = self.quality as u8 | self.version.to_u8();
877 bytestream.push(quality_version);
878 bytestream.extend_from_slice(&self.baseline_b .to_le_bytes());
880 bytestream.extend_from_slice(&self.baseline_b_rms.to_le_bytes());
881 bytestream.extend_from_slice(&self.tot_low_b .to_le_bytes());
882 bytestream.extend_from_slice(&self.tot_high_a .to_le_bytes());
883 bytestream.extend_from_slice(&self.tot_high_b .to_le_bytes());
884 bytestream.extend_from_slice(&self.tot_slp_low_a.to_le_bytes());
885 bytestream.extend_from_slice(&self.tot_slp_low_b.to_le_bytes());
886 bytestream.extend_from_slice(&self.tot_slp_high_a.to_le_bytes());
887 bytestream.extend_from_slice(&self.tot_slp_high_b.to_le_bytes());
888 bytestream.extend_from_slice(&Self::TAIL .to_le_bytes());
889 bytestream
890 }
891
892
893 fn from_bytestream(stream : &Vec<u8>, pos : &mut usize)
900 -> Result<Self, SerializationError> {
901 let mut pp = Self::new();
902 let mut version_lt_011 = false;
903 let (size,_,__) = Self::guess_size(stream, *pos, 28)?;
904 if size == 30 {
905 version_lt_011 = true;
906 let head = parse_u16(stream, pos);
907 if head != Self::HEAD {
908 error!("Decoding of HEAD failed! Got {} instead!", head);
909 return Err(SerializationError::HeadInvalid);
910 }
911 } else {
912 Self::verify_fixed(stream, pos)?;
913 }
914 pp.valid = true;
917 pp.paddle_id = parse_u8(stream, pos);
918 pp.time_a = parse_f16(stream, pos);
919 pp.time_b = parse_f16(stream, pos);
920 pp.peak_a = parse_f16(stream, pos);
921 pp.peak_b = parse_f16(stream, pos);
922 pp.charge_a = parse_f16(stream, pos);
923 pp.charge_b = parse_f16(stream, pos);
924 pp.tot_low_a = parse_f16(stream, pos);
925 pp.baseline_a = parse_f16(stream, pos);
926 pp.baseline_a_rms = parse_f16(stream, pos);
927 let mut phase_vec = Vec::<u8>::new();
928 phase_vec.push(parse_u8(stream, pos));
929 phase_vec.push(parse_u8(stream, pos));
930 pp.phase = parse_f16(&phase_vec, &mut 0);
931 let quality_version_u8 = parse_u8(stream, pos);
932 let quality = EventQuality::from(quality_version_u8 & 0x3f);
933 let version = ProtocolVersion::from(quality_version_u8 & 0xc0);
934 pp.version = version;
935 pp.quality = quality;
936 match pp.version {
937 ProtocolVersion::V1 => {
938 }
939 _ => ()
940 }
941 pp.baseline_b = parse_f16(stream, pos);
942 pp.baseline_b_rms = parse_f16(stream, pos);
943 if !version_lt_011 {
944 pp.tot_low_b = parse_f16(stream, pos);
945 pp.tot_high_a = parse_f16(stream, pos);
946 pp.tot_high_b = parse_f16(stream, pos);
947 pp.tot_slp_low_a = parse_f16(stream, pos);
948 pp.tot_slp_low_b = parse_f16(stream, pos);
949 pp.tot_slp_high_a = parse_f16(stream, pos);
950 pp.tot_slp_high_b = parse_f16(stream, pos);
951 *pos += 2; } else {
953 let tail = parse_u16(stream, pos);
954 if tail != Self::TAIL {
955 error!("Decoding of TAIL failed for version {}! Got {} instead!", version, tail);
956 return Err(SerializationError::TailInvalid);
957 }
958 }
959 Ok(pp)
960 }
961}
962
963#[cfg(feature="random")]
964impl FromRandom for TofHit {
965 fn from_random() -> TofHit {
966 let mut pp = TofHit::new();
967 let mut rng = rand::rng();
968 let version_lt_011 = rng.random::<bool>();
970
971 pp.paddle_id = rng.random_range(0..161);
972 pp.time_a = f16::from_f32(rng.random::<f32>());
973 pp.time_b = f16::from_f32(rng.random::<f32>());
974 pp.peak_a = f16::from_f32(rng.random::<f32>());
975 pp.peak_b = f16::from_f32(rng.random::<f32>());
976 pp.charge_a = f16::from_f32(rng.random::<f32>());
977 pp.charge_b = f16::from_f32(rng.random::<f32>());
978 pp.version = ProtocolVersion::from_random();
979 pp.quality = EventQuality::from_random();
980 pp.baseline_a = f16::from_f32(rng.random::<f32>());
981 pp.baseline_a_rms = f16::from_f32(rng.random::<f32>());
982 pp.baseline_b = f16::from_f32(rng.random::<f32>());
983 pp.baseline_b_rms = f16::from_f32(rng.random::<f32>());
984 pp.phase = f16::from_f32(rng.random::<f32>());
985
986 if !version_lt_011 {
987 pp.tot_low_a = f16::from_f32(rng.random::<f32>());
988 pp.tot_low_b = f16::from_f32(rng.random::<f32>());
989 pp.tot_high_a = f16::from_f32(rng.random::<f32>());
990 pp.tot_high_b = f16::from_f32(rng.random::<f32>());
991 pp.tot_slp_low_a = f16::from_f32(rng.random::<f32>());
992 pp.tot_slp_low_b = f16::from_f32(rng.random::<f32>());
993 pp.tot_slp_high_a = f16::from_f32(rng.random::<f32>());
994 pp.tot_slp_high_b = f16::from_f32(rng.random::<f32>());
995 }
996 pp.paddle_len = 0.0;
997 pp.coax_cable_time = 0.0;
998 pp.hart_cable_time = 0.0;
999 pp.x = 0.0;
1000 pp.y = 0.0;
1001 pp.z = 0.0;
1002 pp.event_t0 = 0.0;
1003 pp
1004 }
1005}
1006
1007#[cfg(feature = "random")]
1010#[test]
1011fn serialization_tofhit() {
1012 for _ in 0..100 {
1013 let mut pos = 0;
1014 let data = TofHit::from_random();
1015 let mut test = TofHit::from_bytestream(&data.to_bytestream(),&mut pos).unwrap();
1016 test.paddle_len = 0.0;
1019 test.coax_cable_time = 0.0;
1020 test.hart_cable_time = 0.0;
1021 test.x = 0.0;
1022 test.y = 0.0;
1023 test.z = 0.0;
1024 test.event_t0 = 0.0;
1025 assert_eq!(pos, TofHit::SIZE);
1026 assert_eq!(data, test);
1027 }
1028}