1use crate::prelude::*;
6
7#[cfg(feature="database")]
8use std::f32::consts::PI;
9use std::cmp::Ordering;
10
11#[derive(Debug, Clone, PartialEq)]
31#[cfg_attr(feature="pybindings", pyclass)]
32pub struct TofEvent {
33 pub status : EventStatus,
34 pub version : ProtocolVersion,
43 pub quality : EventQuality,
44 pub trigger_sources : u16,
45
46 pub n_trigger_paddles : u8,
50 pub event_id : u32,
51 pub run_id : u16,
52 pub timestamp32 : u32,
53 pub timestamp16 : u16,
54 pub drs_dead_lost_hits : u16,
58 pub dsi_j_mask : u32,
59 pub channel_mask : Vec<u16>,
60 pub mtb_link_mask : u64,
61 pub hits : Vec<TofHit>,
62 pub mt_trigger_sources : u16,
67 pub mt_tiu_gps16 : u16,
68 pub mt_tiu_gps32 : u32,
69 pub mt_timestamp : u32,
70 pub mt_tiu_timestamp : u32,
71 pub n_hits_umb : u8,
75 pub n_hits_cbe : u8,
76 pub n_hits_cor : u8,
77 pub tot_edep_umb : f32,
78 pub tot_edep_cbe : f32,
79 pub tot_edep_cor : f32,
80 pub paddles_set : bool,
81 pub rb_events : Vec<RBEvent>,
85 pub creation_time : Instant,
87 pub write_to_disk : bool,
88}
89
90impl TofEvent {
91
92 pub fn new() -> Self {
93 Self {
94 status : EventStatus::Unknown,
95 version : ProtocolVersion::Unknown,
96 n_hits_umb : 0,
97 n_hits_cbe : 0,
98 n_hits_cor : 0,
99 tot_edep_umb : 0.0,
100 tot_edep_cbe : 0.0,
101 tot_edep_cor : 0.0,
102 quality : EventQuality::Unknown,
103 trigger_sources : 0,
104 n_trigger_paddles : 0,
105 event_id : 0,
106 run_id : 0,
107 timestamp32 : 0,
108 timestamp16 : 0,
109 drs_dead_lost_hits : 0,
110 dsi_j_mask : 0,
111 channel_mask : Vec::<u16>::new(),
112 mtb_link_mask : 0,
113 hits : Vec::<TofHit>::new(),
114 mt_trigger_sources : 0,
115 mt_tiu_gps16 : 0,
116 mt_tiu_gps32 : 0,
117 mt_timestamp : 0,
118 mt_tiu_timestamp : 0,
119 paddles_set : false,
120 rb_events : Vec::<RBEvent>::new(),
121 creation_time : Instant::now(),
122 write_to_disk : true,
123 }
124 }
125
126 pub fn elena_cuts(hit : &TofHit) -> bool {
130 let peak_cut = 10.0f32;
131 let charge_cut = 5.0f32;
132 let time_sat = 490.032;
133
134 let hit_a = hit.time_a.to_f32() > 0.1
135 && hit.time_a.to_f32() < time_sat
136 && hit.peak_a.to_f32() > peak_cut
137 && hit.charge_a.to_f32() > charge_cut;
138 let hit_b = hit.time_b.to_f32() > 0.1
139 && hit.time_b.to_f32() < time_sat
140 && hit.peak_b.to_f32() > peak_cut
141 && hit.charge_b.to_f32() > charge_cut;
142
143 return hit_a && hit_b;
144 }
145
146 pub fn remove_elena_hits(&mut self, no_return : bool) -> Option<Vec<TofHit>> {
154 if !no_return {
155 let mut removed = Vec::<TofHit>::new();
156 for h in &self.hits {
157 if Self::elena_cuts(h) {
158 removed.push(h.clone());
159 }
160 }
161 self.hits.retain(|h| Self::elena_cuts(h));
162 return Some(removed);
163 } else {
164 self.hits.retain(|h| Self::elena_cuts(h));
165 return None;
166 }
167 }
168
169
170 pub fn get_tof(&mut self) -> Option<(f32,f32,f32,f32,f32)> {
184 self.normalize_hit_times();
187 let mut outer_h = Vec::<TofHit>::new();
188 let mut inner_h = Vec::<TofHit>::new();
189 for h in &self.hits {
190 if h.paddle_id < 61 {
191 inner_h.push(*h);
192 } else {
193 outer_h.push(*h);
194 }
195 }
196 if inner_h.len() == 0 || outer_h.len() == 0 {
197 return None;
198 }
199 inner_h .sort_by(|a,b| (a.get_t0_with_local_corrections()).partial_cmp(&&b.get_t0_with_local_corrections()).unwrap_or(Ordering::Greater));
200 outer_h .sort_by(|a,b| (a.get_t0_with_local_corrections()).partial_cmp(&&b.get_t0_with_local_corrections()).unwrap_or(Ordering::Greater));
201 let dist = inner_h[0].distance(&outer_h[0])/1000.0;
203 let t0 = inner_h[0].get_t0_with_local_corrections() - inner_h[0].get_phase_ns() - inner_h[0].timing_offset;
205 let t1 = outer_h[0].get_t0_with_local_corrections() - outer_h[0].get_phase_ns() - outer_h[0].timing_offset;
206 let mut pd = inner_h[0].get_phase_ns() - outer_h[0].get_phase_ns();
207 if pd > 25.0 {
208 pd -= 50.0;
209 }
210 if pd < -25.0 {
211 pd += 50.0;
212 }
213 let tof = t0 - t1 + pd;
214 let beta = dist.abs()/(tof*1e-9)/299792458.0;
219 let hart_diff = inner_h[0].hart_cable_time - outer_h[0].hart_cable_time;
221 Some((tof, beta, pd, dist, hart_diff))
222 }
223
224 pub fn get_mt_timestamp_abs(&self) -> u64 {
230 let gps = self.mt_tiu_gps32 as u64;
231 let mut timestamp = self.mt_timestamp as u64;
232 if timestamp < self.mt_tiu_timestamp as u64 {
233 timestamp += u32::MAX as u64 + 1;
235 }
236 let gps_mult = match 100_000_000u64.checked_mul(gps) {
237 Some(result) => result,
239 None => {
240 0 }
244 };
245 let ts = gps_mult + (timestamp - self.mt_tiu_timestamp as u64);
246 ts
247 }
248
249 pub fn move_hits(&mut self) {
256 let mut all_hits = Vec::<TofHit>::with_capacity(5);
257 for rbev in &mut self.rb_events {
258 all_hits.append(&mut rbev.hits);
259 }
260 self.hits = all_hits;
261 }
262
263 pub fn strip_rbevents(&mut self) {
268 if self.hits.len() == 0 {
269 self.move_hits();
270 }
271 self.rb_events.clear();
272 }
273
274 pub fn age(&self) -> u64 {
280 self.creation_time.elapsed().as_secs()
281 }
282
283 pub fn get_expected_rbs(&self, mapping : &HashMap<u8,u8>) -> Vec<u8> {
286 let mut expected_rbs = Vec::<u8>::new();
287 for k in self.get_rb_link_ids() {
288 match mapping.get(&k) {
289 None => {
290 error!("Seeing unassociated link id {k}");
291 }
292 Some(rb_id) => {
293 expected_rbs.push(*rb_id);
294 }
295 }
296 }
297 expected_rbs
298 }
299
300 pub fn is_complete(&mut self, exclude_rbs : Option<(&Vec<u8>,&DsiJChRbMapping)>) -> bool {
303 if exclude_rbs.is_none() {
304 return self.get_rb_link_ids().len() == self.rb_events.len();
305 } else {
306 let dead_rbs = exclude_rbs.unwrap();
307 let mut n_known_dead = 0usize;
308 let t_hits = self.get_trigger_hits();
309 for h in t_hits {
310 match dead_rbs.1.get(&h.0) {
311 None => {
312 continue;
313 }
314 Some(dsi) => {
315 match dsi.get(&h.1) {
316 None => {
317 continue;
318 }
319 Some(j) => {
320 match j.get(&h.2.0) {
321 None => {
322 continue;
323 }
324 Some(rb) => {
325 if dead_rbs.0.contains(&rb) {
326 n_known_dead += 1
327 }
328 }
329 }
330 }
331 }
332 }
333 }
334 } let n_rb_link_ids = self.get_rb_link_ids().len();
339 return n_rb_link_ids <= self.rb_events.len() + n_known_dead;
343 }
344 }
345
346 pub fn get_lost_hits(&self) -> u16 {
349 let mut lost_hits = 0u16;
350 for rbev in &self.rb_events {
351 if rbev.header.drs_lost_trigger() {
352 let mut nhits = rbev.header.get_nchan() as u16;
353 if nhits > 0 {
356 nhits -= 1;
357 }
358 lost_hits += nhits;
359 }
360 }
361 lost_hits
362 }
363
364
365 pub fn prepare_for_gcu(&mut self, strip_rbevents : bool) {
373 if strip_rbevents {
374 self.strip_rbevents();
375 }
376 self.version = ProtocolVersion::V1;
377 if self.n_hits_cbe == 0 && self.n_hits_umb == 0 && self.n_hits_cor == 0 {
378 self.calc_gcu_variables();
379 }
380 }
381
382 pub fn calc_gcu_variables(&mut self) {
385 if self.hits.len() == 0 {
386 for rbev in &self.rb_events {
387 for h in &rbev.hits {
388 if h.paddle_id <= 60 {
389 self.n_hits_cbe += 1;
390 self.tot_edep_cbe += h.get_edep();
391 }
392 else if h.paddle_id <= 108 && h.paddle_id > 60 {
393 self.n_hits_umb += 1;
394 self.tot_edep_umb += h.get_edep();
395 }
396 else {
397 self.n_hits_cor += 1;
398 self.tot_edep_cor += h.get_edep();
399 }
400 }
401 }
402 } else {
403 for h in &self.hits {
404 if h.paddle_id <= 60 {
405 self.n_hits_cbe += 1;
406 self.tot_edep_cbe += h.get_edep();
407 }
408 else if h.paddle_id <= 108 && h.paddle_id > 60 {
409 self.n_hits_umb += 1;
410 self.tot_edep_umb += h.get_edep();
411 }
412 else {
413 self.n_hits_cor += 1;
414 self.tot_edep_cor += h.get_edep();
415 }
416 }
417 }
418 }
419
420 pub fn decode_depr_tofevent_size_header(mask : &u32)
423 -> (usize, usize) {
424 let rb_event_len = (mask & 0xFF) as usize;
425 let miss_len = ((mask & 0xFF00) >> 8) as usize;
426 (rb_event_len, miss_len)
427 }
428
429 #[cfg(feature="database")]
439 pub fn set_timing_offsets(&mut self, offsets : &HashMap<u8, f32>) {
440 for h in self.hits.iter_mut() {
441 if offsets.contains_key(&h.paddle_id) {
442 h.timing_offset = offsets[&h.paddle_id];
443 }
444 }
445 }
446
447 pub fn lightspeed_cleaning(&mut self, t_err : f32) -> (Vec<u8>, Vec<f32>) {
459 if self.hits.len() == 0 {
461 return (Vec::<u8>::new(), Vec::<f32>::new());
462 }
463 let mut twindows = Vec::<f32>::new();
464 self.hits.sort_by(|a,b| (a.event_t0).partial_cmp(&b.event_t0).unwrap_or(Ordering::Greater));
465 let first_hit = self.hits[0].clone(); let mut clean_hits = Vec::<TofHit>::new();
469 let mut rm_hits = Vec::<u8>::new();
470 clean_hits.push(first_hit.clone());
472 let mut prior_hit = first_hit;
474 for h in self.hits.iter().skip(1) {
476 let min_tdiff_cvac = 1e9*1e-3*prior_hit.distance(h)/299792458.0;
477 let twindow = prior_hit.event_t0 + min_tdiff_cvac;
478
479 if h.event_t0 + 2.0*t_err < twindow {
488 rm_hits.push(h.paddle_id);
489 twindows.push(twindow);
490 continue;
491 }
492 prior_hit = h.clone();
508 clean_hits.push(*h);
509 }
510 self.hits = clean_hits;
511 (rm_hits, twindows)
512 }
513
514
515 pub fn remove_non_causal_hits(&mut self) -> Vec<u8> {
525 let mut clean_hits = Vec::<TofHit>::new();
526 let mut removed_pids = Vec::<u8>::new();
527 for h in &self.hits {
528 if h.obeys_causality() {
529 clean_hits.push(*h);
530 } else {
531 removed_pids.push(h.paddle_id);
532 }
533 }
534 self.hits = clean_hits;
535 removed_pids
536 }
537
538 #[cfg(feature="database")]
547 pub fn normalize_hit_times(&mut self) {
548 if self.hits.len() == 0 {
549 return;
550 }
551 if self.hits[0].event_t0 == 0.0 {
553 return;
554 }
555
556 let phase0 = self.hits[0].phase.to_f32();
557 for h in &mut self.hits {
561 let t0 = h.get_t0_uncorrected() + h.get_cable_delay();
562 let mut phase_diff = h.phase.to_f32() - phase0;
564 while phase_diff < - PI/2.0 {
565 phase_diff += 2.0*PI;
566 }
567 while phase_diff > PI/2.0 {
568 phase_diff -= 2.0*PI;
569 }
570 let t_shift = 50.0*phase_diff/(2.0*PI);
571 h.event_t0 = t0 + t_shift - h.timing_offset;
572 }
573 self.hits.sort_by(|a,b| (a.event_t0).total_cmp(&b.event_t0));
576 let t0_first_hit = self.hits[0].event_t0;
577 for h in self.hits.iter_mut() {
578 h.event_t0 -= t0_first_hit;
579 }
580 }
581
582 #[cfg(feature="database")]
591 pub fn set_paddles(&mut self, paddles : &HashMap<u8, TofPaddle>) {
592 let mut nerror = 0u8;
593 if paddles.is_empty() {
594 debug!("Unable to set paddles, empty map given!");
595 return;
596 }
597 if self.hits.len() == 0 {
598 for rbev in &mut self.rb_events {
599 for h in &mut rbev.hits {
600 match paddles.get(&h.paddle_id) {
601 None => {
602 error!("Got paddle id {} which is not in given map!", h.paddle_id);
603 nerror += 1;
604 continue;
605 }
606 Some(pdl) => {
607 h.set_paddle(pdl);
608 }
609 }
610 }
611 }
612 } else {
613 for h in &mut self.hits {
614 match paddles.get(&h.paddle_id) {
615 None => {
616 error!("Got paddle id {} which is not in given map!", h.paddle_id);
617 nerror += 1;
618 continue;
619 }
620 Some(pdl) => {
621 h.set_paddle(pdl);
622 }
623 }
624 }
625 }
626 if nerror == 0 {
627 self.paddles_set = true;
628 }
630 }
631
632 pub fn get_pointcloud(&self) -> Option<Vec<(f32,f32,f32,f32,f32)>> {
641 let mut pc = Vec::<(f32,f32,f32,f32,f32)>::new();
642 if !self.paddles_set {
643 error!("Before getting the pointcloud, paddle information needs to be set for this event. Call TofEvent;:set_paddle");
644 return None;
645 }
646 for h in &self.hits {
647 let result = (h.x, h.y, h.z, h.event_t0, h.get_edep());
648 pc.push(result);
649 }
650 Some(pc)
651 }
652
653 #[cfg(feature="database")]
662 pub fn get_missing_paddles_hg(&self, pid_map : &DsiJChPidMapping) -> Vec<u8> {
663 let mut missing = Vec::<u8>::new();
664 for th in self.get_trigger_hits() {
665 if !pid_map.contains_key(&th.0) {
666 error!("Can't find {:?} in paddlemap!",th);
667 continue;
668 }
669 if !pid_map.get(&th.0).unwrap().contains_key(&th.1) {
670 error!("Can't find {:?} in paddlemap!",th);
671 continue;
672 }
673 if !pid_map.get(&th.0).unwrap().get(&th.1).unwrap().contains_key(&th.2.0) {
674 error!("Can't find {:?} in paddlemap!",th);
675 continue;
676 }
677 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
678 let mut found = false;
679 for h in &self.hits {
680 if h.paddle_id == pid {
681 found = true;
682 break
683 }
684 }
685 if !found {
686 missing.push(pid);
687 }
688 }
689 missing
690 }
691
692 #[cfg(feature="database")]
696 pub fn get_triggered_paddles(&self, pid_map : &DsiJChPidMapping) -> Vec<u8> {
697 let mut paddles = Vec::<u8>::with_capacity(3);
698 for th in &self.get_trigger_hits() {
699 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
700 paddles.push(pid);
701 }
702 paddles
703 }
704
705 pub fn get_rb_link_ids(&self) -> Vec<u8> {
707 let mut links = Vec::<u8>::new();
708 for k in 0..64 {
709 if (self.mtb_link_mask >> k) as u64 & 0x1 == 1 {
710 links.push(k as u8);
711 }
712 }
713 links
714 }
715
716 pub fn get_trigger_hits(&self) -> Vec<(u8, u8, (u8, u8), LTBThreshold)> {
729 let mut hits = Vec::<(u8,u8,(u8,u8),LTBThreshold)>::with_capacity(5);
730 let n_masks_needed = self.dsi_j_mask.count_ones();
732 if self.channel_mask.len() < n_masks_needed as usize {
733 error!("We need {} hit masks, but only have {}! This is bad!", n_masks_needed, self.channel_mask.len());
734 return hits;
735 }
736 let mut n_mask = 0;
737 trace!("Expecting {} hit masks", n_masks_needed);
738 trace!("ltb channels {:?}", self.dsi_j_mask);
739 trace!("hit masks {:?}", self.channel_mask);
740 for k in 0..32 {
744 if (self.dsi_j_mask >> k) as u32 & 0x1 == 1 {
745 let mut dsi = 0u8;
746 let mut j = 0u8;
747 if k < 5 {
748 dsi = 1;
749 j = k as u8 + 1;
750 } else if k < 10 {
751 dsi = 2;
752 j = k as u8 - 5 + 1;
753 } else if k < 15 {
754 dsi = 3;
755 j = k as u8- 10 + 1;
756 } else if k < 20 {
757 dsi = 4;
758 j = k as u8- 15 + 1;
759 } else if k < 25 {
760 dsi = 5;
761 j = k as u8 - 20 + 1;
762 }
763 let channels = self.channel_mask[n_mask];
767 for (i,ch) in LTB_CHANNELS.iter().enumerate() {
768 let ph_chn = PHYSICAL_CHANNELS[i];
770 let thresh_bits = ((channels & ch) >> (i*2)) as u8;
773 if thresh_bits > 0 { hits.push((dsi, j, ph_chn, LTBThreshold::from(thresh_bits)));
776 }
777 }
778 n_mask += 1;
779 } }
781 hits
782 }
783
784 pub fn get_trigger_sources(&self) -> Vec<TriggerType> {
786 TriggerType::transcode_trigger_sources(self.trigger_sources)
787 }
788
789 pub fn get_timestamp48(&self) -> u64 {
790 0x273000000000000 | (((self.timestamp16 as u64) << 32) | self.timestamp32 as u64)
793 }
794
795 pub fn get_edep_umbrella(&self) -> f32 {
800 let mut tot_edep = 0.0f32;
801 for h in &self.hits {
802 if h.paddle_id < 61 || h.paddle_id > 108 {
803 continue;
804 }
805 tot_edep += h.get_edep();
806 }
807 tot_edep
808 }
809
810 pub fn get_edep_cube(&self) -> f32 {
815 let mut tot_edep = 0.0f32;
816 for h in &self.hits {
817 if h.paddle_id > 60 {
818 continue;
819 }
820 tot_edep += h.get_edep();
821 }
822 tot_edep
823 }
824
825 pub fn get_edep_cortina(&self) -> f32 {
830 let mut tot_edep = 0.0f32;
831 for h in &self.hits {
832 if h.paddle_id < 109 {
833 continue;
834 }
835 tot_edep += h.get_edep();
836 }
837 tot_edep
838 }
839
840 pub fn get_edep(&self) -> f32 {
845 let mut tot_edep = 0.0f32;
846 for h in &self.hits {
847 tot_edep += h.get_edep();
848 }
849 tot_edep
850 }
851
852 pub fn get_nhits_umb(&self) -> usize {
854 let mut nhit = 0;
855 for h in &self.hits {
856 if h.paddle_id > 60 && h.paddle_id < 109 {
857 nhit += 1;
858 }
859 }
860 nhit
861 }
862
863 pub fn get_nhits_cbe(&self) -> usize {
865 let mut nhit = 0;
866 for h in &self.hits {
867 if h.paddle_id < 61 {
868 nhit += 1;
869 }
870 }
871 nhit
872 }
873
874 pub fn get_nhits_cor(&self) -> usize {
875 let mut nhit = 0;
876 for h in &self.hits {
877 if h.paddle_id > 108 {
878 nhit += 1;
879 }
880 }
881 nhit
882 }
883
884 pub fn get_nhits(&self) -> usize {
885 self.hits.len()
886 }
887
888 pub fn has_any_mangling(&self) -> bool {
891 for rbev in &self.rb_events {
892 if rbev.status == EventStatus::CellAndChnSyncErrors
893 || rbev.status == EventStatus::CellSyncErrors
894 || rbev.status == EventStatus::ChnSyncErrors {
895 return true;
896 }
897 }
898 false
899 }
900
901 pub fn get_waveforms(&self) -> Vec<RBWaveform> {
906 let mut wfs = Vec::<RBWaveform>::new();
907 for ev in &self.rb_events {
908 for wf in &ev.get_rbwaveforms() {
909 wfs.push(wf.clone());
910 }
911 }
912 wfs
913 }
914
915 pub fn set_packed_status_version(pack : &mut TofPacket, version : ProtocolVersion)
919 -> Result<(), SerializationError> {
920 if pack.packet_type != TofPacketType::TofEvent {
921 return Err(SerializationError::IncorrectPacketType);
922 }
923 let mut status_version = pack.payload[2];
924 status_version = status_version & 0x3f;
926 status_version = status_version | version.to_u8();
928 pack.payload[2] = status_version;
929 Ok(())
930 }
931
932 pub fn strip_packed_rbevents_for_pv3(pack : &mut TofPacket)
941 -> Result<(), SerializationError> {
942 if pack.packet_type != TofPacketType::TofEvent {
943 return Err(SerializationError::IncorrectPacketType);
944 }
945 let status_version = pack.payload[2];
946 let mut version = ProtocolVersion::from(status_version & 0xc0);
947 if version != ProtocolVersion::V3 {
948 error!("This operation can only be executed on {}, however, this is version {}!", ProtocolVersion::V3, version);
949 return Err(SerializationError::WrongProtocolVersion);
950 }
951 let mut pos = 0usize;
953 pos += 10; pos += 15; pos += 15;
956 if pack.payload.len() >= pos {
957 return Err(SerializationError::StreamTooShort);
958 }
959 let nmasks = parse_u8(&pack.payload, &mut pos);
960 for _ in 0..nmasks {
961 pos += 2;
962 }
963 pos += 8;
964 let nhits = parse_u16(&pack.payload,&mut pos);
965 for _ in 0..nhits {
967 pos += TofHit::SIZE;
968 }
973 pack.payload.truncate(pack.payload.len() - pos);
977 pack.payload.extend_from_slice(&Self::TAIL.to_le_bytes());
978 version = ProtocolVersion::V2;
979 Self::set_packed_status_version(pack, version)?;
980 Ok(())
981 }
982}
983
984impl TofPackable for TofEvent {
985 const TOF_PACKET_TYPE : TofPacketType = TofPacketType::TofEvent;
987 const TOF_PACKET_TYPE_ALT : TofPacketType = TofPacketType::TofEventDeprecated;
988}
989
990impl Serialization for TofEvent {
991
992 const HEAD : u16 = 43690; const TAIL : u16 = 21845; fn to_bytestream(&self) -> Vec<u8> {
996 let mut stream = Vec::<u8>::new();
997 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
998 let status_version = self.status as u8 | self.version.to_u8();
999 stream.push(status_version);
1000 stream.extend_from_slice(&self.trigger_sources.to_le_bytes());
1001 stream.extend_from_slice(&self.n_trigger_paddles.to_le_bytes());
1002 stream.extend_from_slice(&self.event_id.to_le_bytes());
1003 if self.version == ProtocolVersion::V1
1005 || self.version == ProtocolVersion::V3 {
1006 stream.extend_from_slice(&self.n_hits_umb .to_le_bytes());
1007 stream.extend_from_slice(&self.n_hits_cbe .to_le_bytes());
1008 stream.extend_from_slice(&self.n_hits_cor .to_le_bytes());
1009 stream.extend_from_slice(&self.tot_edep_umb.to_le_bytes());
1010 stream.extend_from_slice(&self.tot_edep_cbe.to_le_bytes());
1011 stream.extend_from_slice(&self.tot_edep_cor.to_le_bytes());
1012 }
1013 stream.extend_from_slice(&(self.quality as u8).to_le_bytes());
1014 stream.extend_from_slice(&self.timestamp32.to_le_bytes());
1015 stream.extend_from_slice(&self.timestamp16.to_le_bytes());
1016 stream.extend_from_slice(&self.run_id.to_le_bytes());
1017 stream.extend_from_slice(&self.drs_dead_lost_hits.to_le_bytes());
1018 stream.extend_from_slice(&self.dsi_j_mask.to_le_bytes());
1019 let n_channel_masks = self.channel_mask.len();
1020 stream.push(n_channel_masks as u8);
1021 for k in 0..n_channel_masks {
1022 stream.extend_from_slice(&self.channel_mask[k].to_le_bytes());
1023 }
1024 stream.extend_from_slice(&self.mtb_link_mask.to_le_bytes());
1025 let nhits = self.hits.len() as u16;
1026 stream.extend_from_slice(&nhits.to_le_bytes());
1027 for k in 0..self.hits.len() {
1028 stream.extend_from_slice(&self.hits[k].to_bytestream());
1029 }
1030 if self.version == ProtocolVersion::V2
1033 || self.version == ProtocolVersion::V3 {
1034 stream.push(self.rb_events.len() as u8);
1035 for rbev in &self.rb_events {
1036 stream.extend_from_slice(&rbev.to_bytestream());
1037 }
1038 }
1039 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
1040 stream
1041 }
1042
1043 fn from_bytestream(stream : &Vec<u8>,
1044 pos : &mut usize)
1045 -> Result<Self, SerializationError>{
1046 let mut event = Self::new();
1047 let head = parse_u16(stream, pos);
1048 if head != Self::HEAD {
1049 error!("Decoding of HEAD failed! Got {} instead!", head);
1050 return Err(SerializationError::HeadInvalid);
1051 }
1052
1053 let status_version_u8 = parse_u8(stream, pos);
1054 let status = EventStatus::from(status_version_u8 & 0x3f);
1055 let version = ProtocolVersion::from(status_version_u8 & 0xc0);
1056 event.status = status;
1057 event.version = version;
1058 event.trigger_sources = parse_u16(stream, pos);
1059 event.n_trigger_paddles = parse_u8(stream, pos);
1060 event.event_id = parse_u32(stream, pos);
1061 if event.version == ProtocolVersion::V1
1062 || event.version == ProtocolVersion::V3 {
1063 event.n_hits_umb = parse_u8(stream, pos);
1064 event.n_hits_cbe = parse_u8(stream, pos);
1065 event.n_hits_cor = parse_u8(stream, pos);
1066 event.tot_edep_umb = parse_f32(stream, pos);
1067 event.tot_edep_cbe = parse_f32(stream, pos);
1068 event.tot_edep_cor = parse_f32(stream, pos);
1069 }
1070 event.quality = EventQuality::from(parse_u8(stream, pos));
1071 event.timestamp32 = parse_u32(stream, pos);
1072 event.timestamp16 = parse_u16(stream, pos);
1073 event.run_id = parse_u16(stream, pos);
1074 event.drs_dead_lost_hits = parse_u16(stream, pos);
1075 event.dsi_j_mask = parse_u32(stream, pos);
1076 let n_channel_masks = parse_u8(stream, pos);
1077 for _ in 0..n_channel_masks {
1078 event.channel_mask.push(parse_u16(stream, pos));
1079 }
1080 event.mtb_link_mask = parse_u64(stream, pos);
1081 let nhits = parse_u16(stream, pos);
1082 if nhits > 160 {
1084 error!("There are an abnormous amount of hits in this event!");
1085 return Err(SerializationError::StreamTooLong);
1086 }
1087 for _ in 0..nhits {
1088 event.hits.push(TofHit::from_bytestream(stream, pos)?);
1089 }
1090 if event.version == ProtocolVersion::V2
1091 || event.version == ProtocolVersion::V3 {
1092 let n_rb_events = parse_u8(stream, pos);
1093 if n_rb_events > 0 {
1094 for _ in 0..n_rb_events {
1095 event.rb_events.push(RBEvent::from_bytestream(stream, pos)?);
1096 }
1097 }
1098 }
1099
1100 let tail = parse_u16(stream, pos);
1101 if tail != Self::TAIL {
1102 error!("Decoding of TAIL failed for version {}! Got {} instead!", version, tail);
1103 return Err(SerializationError::TailInvalid);
1104 }
1105 Ok(event)
1106 }
1107
1108 fn from_bytestream_alt(stream : &Vec<u8>,
1114 pos : &mut usize)
1115 -> Result<Self, SerializationError> {
1116 let head = parse_u16(stream, pos);
1117 if head != TofEvent::HEAD {
1118 return Err(SerializationError::HeadInvalid);
1119 }
1120 let mut te = Self::new();
1121 let _compression_level = parse_u8(stream, pos);
1123
1124 te.quality = EventQuality::from(parse_u8(stream, pos));
1125 *pos += 2; te.run_id = parse_u32(stream, pos) as u16;
1131 *pos += 43 - 6;*pos += 2; let event_status = parse_u8 (stream, pos);
1136 te.status = EventStatus::from(event_status);
1137 if te.has_any_mangling() {
1138 te.status = EventStatus::AnyDataMangling;
1139 }
1140 te.event_id = parse_u32(stream, pos);
1141 let mtb_timestamp = parse_u32(stream, pos);
1142 let tiu_timestamp = parse_u32(stream, pos);
1143 let tiu_gps32 = parse_u32(stream, pos);
1144 let _tiu_gps16 = parse_u16(stream,pos);
1145 let _crc = parse_u32(stream, pos);
1146 let mt_timestamp = (mt_event_get_timestamp_abs48(mtb_timestamp, tiu_gps32, tiu_timestamp ) as f64/1000.0).floor() as u64;
1147 te.timestamp32 = (mt_timestamp & 0x00000000ffffffff ) as u32;
1148 te.timestamp16 = ((mt_timestamp & 0x0000ffff00000000 ) >> 32) as u16;
1149 te.trigger_sources = parse_u16(stream, pos);
1150 te.dsi_j_mask = parse_u32(stream, pos);
1151 let n_channel_masks = parse_u8(stream, pos);
1152 for _ in 0..n_channel_masks {
1153 te.channel_mask.push(parse_u16(stream, pos));
1154 }
1155
1156 te.mtb_link_mask = parse_u64(stream, pos);
1157 let mt_event_tail = parse_u16(stream, pos);
1158 if mt_event_tail != Self::TAIL {
1159 error!("Parsed TAIL from MT event is incorrect! Got {} instead of {} at pos {}", mt_event_tail, Self::TAIL, pos);
1161 }
1162 let v_sizes = Self::decode_depr_tofevent_size_header(&parse_u32(stream, pos));
1164 for _ in 0..v_sizes.0 {
1166 let next_rb_event = RBEvent::from_bytestream(stream, pos)?;
1169 te.rb_events.push(next_rb_event);
1171 }
1172 for rbev in &te.rb_events {
1178 for h in &rbev.hits {
1179 te.hits.push(*h);
1180 }
1181 }
1182 let tail = parse_u16(stream, pos);
1183 if tail != Self::TAIL {
1184 error!("Decoding of TAIL failed! Got {} instead!", tail);
1185 return Err(SerializationError::TailInvalid);
1186 }
1187 return Ok(te);
1188 }
1189}
1190
1191impl Default for TofEvent {
1192 fn default() -> Self {
1193 Self::new()
1194 }
1195}
1196
1197impl fmt::Display for TofEvent {
1198 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1199 let mut repr = format!("<TofEvent (version {})", self.version);
1200 repr += &(format!("\n EventID : {}", self.event_id));
1201 repr += &(format!("\n RunID : {}", self.run_id));
1202 repr += &(format!("\n EventStatus : {}", self.status));
1203 repr += &(format!("\n TriggerSources : {:?}", self.get_trigger_sources()));
1204 repr += &(format!("\n NTrigPaddles : {}", self.n_trigger_paddles));
1205 repr += &(format!("\n DRS dead hits : {}", self.drs_dead_lost_hits));
1206 repr += &(format!("\n timestamp32 : {}", self.timestamp32));
1207 repr += &(format!("\n timestamp16 : {}", self.timestamp16));
1208 repr += &(format!("\n |-> timestamp48 : {}", self.get_timestamp48()));
1209 repr += &(format!("\n |-> UNIX : {}", (1e-8) * self.get_timestamp48() as f64));
1210 repr += &(format!("\n |-> UTC : {}", get_utc_timestamp_from_unix((1e-8) * self.get_timestamp48() as f64).unwrap_or(String::from("INVALID"))));
1211 if self.version == ProtocolVersion::V1 {
1219 repr += "\n ---- V1 variables ----";
1220 repr += &(format!("\n n_hits_umb : {}", self.n_hits_umb ));
1221 repr += &(format!("\n n_hits_cbe : {}", self.n_hits_cbe ));
1222 repr += &(format!("\n n_hits_cor : {}", self.n_hits_cor ));
1223 repr += &(format!("\n tot_edep_umb : {}", self.tot_edep_umb));
1224 repr += &(format!("\n tot_edep_cbe : {}", self.tot_edep_cbe));
1225 repr += &(format!("\n tot_edep_cor : {}", self.tot_edep_cor));
1226 }
1227 repr += &(format!("\n ** ** TRIGGER HITS (DSI/J/CH) [{} LTBS] ** **", self.dsi_j_mask.count_ones()));
1228 for k in self.get_trigger_hits() {
1229 repr += &(format!("\n => {}/{}/({},{}) ({}) ", k.0, k.1, k.2.0, k.2.1, k.3));
1230 }
1231 repr += "\n ** ** MTB LINK IDs ** **";
1232 let mut mtblink_str = String::from("\n => ");
1233 for k in self.get_rb_link_ids() {
1234 mtblink_str += &(format!("{} ", k))
1235 }
1236 repr += &mtblink_str;
1237 repr += &(format!("\n == Trigger hits {}, expected RBEvents {}",
1238 self.get_trigger_hits().len(),
1239 self.get_rb_link_ids().len()));
1240 repr += &String::from("\n ** ** ** HITS ** ** **");
1241 for h in &self.hits {
1242 repr += &(format!("\n {}", h));
1243 }
1244 if self.rb_events.len() > 0 {
1245 repr += &format!("\n -- has {} RBEvents with waveforms!", self.rb_events.len());
1246 repr += "\n -- -- boards: ";
1247 for b in &self.rb_events {
1248 repr += &format!("{} ", b.header.rb_id);
1249 }
1250 }
1251 repr += ">";
1252 write!(f, "{}", repr)
1253 }
1254}
1255
1256#[cfg(feature="random")]
1257impl FromRandom for TofEvent {
1258
1259 fn from_random() -> Self {
1260 let mut event = Self::new();
1261 let mut rng = rand::rng();
1262 let status = EventStatus::from_random();
1263 let version = ProtocolVersion::from_random();
1264 if version == ProtocolVersion::V1 {
1265 event.n_hits_umb = rng.random::<u8>();
1266 event.n_hits_cbe = rng.random::<u8>();
1267 event.n_hits_cor = rng.random::<u8>();
1268 event.tot_edep_umb = rng.random::<f32>();
1269 event.tot_edep_cbe = rng.random::<f32>();
1270 event.tot_edep_cor = rng.random::<f32>();
1271 event.quality = EventQuality::from_random();
1272 }
1273 event.status = status;
1274 event.version = version;
1275 event.trigger_sources = rng.random::<u16>();
1277 event.n_trigger_paddles = rng.random::<u8>();
1278 event.event_id = rng.random::<u32>();
1279 event.timestamp32 = rng.random::<u32>();
1280 event.timestamp16 = rng.random::<u16>();
1281 event.drs_dead_lost_hits = rng.random::<u16>();
1282 event.dsi_j_mask = rng.random::<u32>();
1283 let n_channel_masks = rng.random::<u8>();
1284 for _ in 0..n_channel_masks {
1285 event.channel_mask.push(rng.random::<u16>());
1286 }
1287 event.mtb_link_mask = rng.random::<u64>();
1288 let nhits: u16 = rng.random_range(0..5);
1290 for _ in 0..nhits {
1291 event.hits.push(TofHit::from_random());
1292 }
1293 if event.version == ProtocolVersion::V2 {
1294 let n_rb_events = rng.random_range(0..4);
1295 for _ in 0..n_rb_events {
1296 event.rb_events.push(RBEvent::from_random());
1297 }
1298 }
1299 event
1300 }
1301}
1302
1303#[cfg(feature="pybindings")]
1306#[pymethods]
1307impl TofEvent {
1308
1309 #[getter]
1310 #[pyo3(name="tof")]
1311 fn get_tof_py(&mut self) -> Option<(f32,f32,f32,f32,f32)> {
1312 self.get_tof()
1313 }
1314
1315 #[pyo3(name="strip_rbevents")]
1316 fn strip_rbevents_py(&mut self) {
1317 self.strip_rbevents()
1318 }
1319
1320 #[pyo3(name="calc_gcu_variables")]
1323 fn calc_gcu_variables_py(&mut self) {
1324 self.calc_gcu_variables()
1325 }
1326
1327 fn copy(&self) -> Self {
1329 self.clone()
1330 }
1331
1332 #[pyo3(name="set_timing_offsets")]
1342 pub fn set_timing_offsets_py(&mut self, timing_offsets : HashMap<u8, f32>) {
1343 self.set_timing_offsets(&timing_offsets);
1344 }
1345
1346 #[pyo3(name="normalize_hit_times")]
1355 pub fn normalize_hit_times_py(&mut self) {
1356 self.normalize_hit_times();
1357 }
1358
1359 #[pyo3(name="lightspeed_cleaning")]
1367 pub fn lightspeed_cleaning_py(&mut self, t_err : f32) -> (Vec<u16>, Vec<f32>) {
1368 let mut pids = Vec::<u16>::new();
1371 let (pids_rm, twindows) = self.lightspeed_cleaning(t_err);
1372 for pid in pids_rm {
1373 pids.push(pid as u16);
1374 }
1375 (pids, twindows)
1376 }
1377
1378 #[getter]
1380 fn get_run_id(&self) -> u16 {
1381 self.run_id
1382 }
1383
1384 #[pyo3(name="remove_non_causal_hits")]
1389 fn remove_non_causal_hits_py(&mut self) -> Vec<u16> {
1390 let mut pids = Vec::<u16>::new();
1393 for pid in self.remove_non_causal_hits() {
1394 pids.push(pid as u16);
1395 }
1396 pids
1397 }
1398
1399 #[getter]
1410 #[pyo3(name="pointcloud")]
1411 fn get_pointcloud_py(&self) -> Option<Vec<(f32,f32,f32,f32,f32)>> {
1412 self.get_pointcloud()
1413 }
1414
1415 #[getter]
1416 #[pyo3(name="has_any_mangling")]
1417 fn has_any_mangling_py(&self) -> bool {
1418 self.has_any_mangling()
1419 }
1420
1421 #[getter]
1422 fn get_event_id(&self) -> u32 {
1423 self.event_id
1424 }
1425
1426 #[getter]
1427 fn get_event_status(&self) -> EventStatus {
1428 self.status
1429 }
1430
1431 #[pyo3(name="get_missing_paddles_hg")]
1434 fn get_missing_paddles_hg_py(&self, mapping : DsiJChPidMapping) -> Vec<u8> {
1435 self.get_missing_paddles_hg(&mapping)
1436 }
1437
1438 #[pyo3(name="get_triggered_paddles")]
1440 fn get_triggered_paddles_py(&self, mapping : DsiJChPidMapping) -> Vec<u8> {
1441 self.get_triggered_paddles(&mapping)
1442 }
1443
1444 #[getter]
1447 fn lost_hits(&self) -> u16 {
1448 self.drs_dead_lost_hits
1449 }
1450
1451 #[getter]
1454 fn rb_link_ids(&self) -> Vec<u32> {
1455 self.get_rb_link_ids().into_iter().map(|byte| byte as u32).collect()
1456 }
1457
1458 #[getter]
1460 fn get_rb_events(&self) -> Vec<RBEvent> {
1461 self.rb_events.clone()
1462 }
1463
1464 #[getter]
1466 pub fn trigger_hits(&self) -> PyResult<Vec<(u8, u8, (u8, u8), LTBThreshold)>> {
1467 Ok(self.get_trigger_hits())
1468 }
1469
1470 #[getter]
1473 pub fn trigger_sources(&self) -> Vec<TriggerType> {
1474 self.get_trigger_sources()
1475 }
1476
1477 #[getter]
1480 #[pyo3(name="trigger_sources_bytes")]
1481 pub fn get_trigger_sources_bytes_py(&self) -> u16 {
1482 self.trigger_sources
1483 }
1484
1485 #[pyo3(name="move_hits")]
1486 pub fn move_hits_py(&mut self) {
1487 self.move_hits()
1488 }
1489
1490 #[getter]
1491 #[pyo3(name="hits")]
1492 pub fn hits_py<'_py>(&self) -> Vec<TofHit> {
1493 self.hits.clone()
1497 }
1498
1499 #[getter]
1500 #[pyo3(name="hitmap")]
1501 pub fn hitmap<'_py>(&self) -> HashMap<u8,TofHit> {
1502 let mut hitmap = HashMap::<u8, TofHit>::new();
1506 for h in &self.hits {
1507 hitmap.insert(h.paddle_id, *h);
1508 }
1509 hitmap
1510 }
1511
1512 #[getter]
1517 #[pyo3(name="edep_umb")]
1518 pub fn get_edep_umbrella_py(&self) -> f32 {
1519 self.get_edep_umbrella()
1520 }
1521
1522 #[getter]
1527 #[pyo3(name="edep_cbe")]
1528 pub fn get_edep_cube_py(&self) -> f32 {
1529 self.get_edep_cube()
1530 }
1531
1532 #[getter]
1537 #[pyo3(name="edep_cor")]
1538 pub fn get_edep_cortina_py(&self) -> f32 {
1539 self.get_edep_cortina()
1540 }
1541
1542 #[getter]
1547 #[pyo3(name="edep")]
1548 pub fn get_edep_py(&self) -> f32 {
1549 self.get_edep()
1550 }
1551
1552 #[getter]
1553 #[pyo3(name="nhits")]
1554 pub fn nhits_py(&self) -> usize {
1555 self.get_nhits()
1556 }
1557
1558 #[getter]
1559 #[pyo3(name="dsi_j_mask")]
1560 pub fn get_dsi_j_mask_py(&self) -> u32 {
1561 self.dsi_j_mask
1562 }
1563
1564 #[getter]
1565 #[pyo3(name="channel_masks")]
1566 pub fn get_channel_masks_py(&self) -> Vec<u16> {
1567 self.channel_mask.clone()
1568 }
1569
1570 #[getter]
1571 #[pyo3(name="nhits_umb")]
1572 pub fn nhits_umb_py(&self) -> usize {
1573 self.get_nhits_umb()
1574 }
1575
1576 #[getter]
1577 #[pyo3(name="nhits_cbe")]
1578 fn get_nhits_cbe_py(&self) -> usize {
1579 self.get_nhits_cbe()
1580 }
1581
1582 #[getter]
1583 #[pyo3(name="nhits_cor")]
1584 fn get_nhits_cor_py(&self) -> usize {
1585 self.get_nhits_cor()
1586 }
1587
1588 #[getter]
1589 fn get_timestamp16(&self) -> u16 {
1590 self.timestamp16
1591 }
1592
1593 #[getter]
1594 fn get_timestamp32(&self) -> u32 {
1595 self.timestamp32
1596 }
1597
1598 #[getter]
1599 fn timestamp48(&self) -> u64 {
1600 self.get_timestamp48()
1601 }
1602
1603 #[getter]
1604 fn get_status(&self) -> EventStatus {
1605 self.status
1606 }
1607
1608 #[getter]
1609 #[pyo3(name="waveforms")]
1610 fn get_waveforms_py(&self) -> Vec<RBWaveform> {
1611 self.get_waveforms()
1612 }
1613
1614 #[staticmethod]
1615 #[pyo3(name = "set_packed_status_version")]
1616 fn set_packed_status_version_py(pack : &mut TofPacket, version : ProtocolVersion)
1617 -> PyResult<()> {
1618 match Self::set_packed_status_version(pack, version) {
1619 Err(err) => {
1620 let err_mesg = format!("Unable to set status version! {}", err);
1621 return Err(PyValueError::new_err(err_mesg));
1622 }
1623 Ok(_) => {
1624 return Ok(());
1625 }
1626 }
1627 }
1628
1629 #[staticmethod]
1630 #[pyo3(name = "strip_packed_rbevents_for_pv3")]
1631 fn strip_packed_rbevents_for_pv3_py(pack : &mut TofPacket)
1632 -> PyResult<()> {
1633 match Self::strip_packed_rbevents_for_pv3(pack) {
1634 Err(err) => {
1635 let err_msg = format!("Unable to strip packed rbevents{}", err);
1636 return Err(PyValueError::new_err(err_msg));
1637 }
1638 Ok(_) => {
1639 return Ok(());
1640 }
1641 }
1642 }
1643
1644 #[cfg(feature="database")]
1645 #[staticmethod]
1646 fn unpack(pack : &TofPacket) -> PyResult<Self> {
1647 if pack.packet_type != Self::TOF_PACKET_TYPE {
1648 let err_msg = format!("This is a packet of type {}, but we need type {}", pack.packet_type, Self::TOF_PACKET_TYPE);
1649 return Err(PyValueError::new_err(err_msg));
1650 }
1651 let mut pos = 0;
1652 let mut ev = Self::from_bytestream(&pack.payload,&mut pos)?;
1653 ev.set_paddles(&pack.tof_paddles);
1654 Ok(ev)
1655 }
1656}
1657
1658#[cfg(feature="pybindings")]
1659pythonize_packable!(TofEvent);
1660
1661#[test]
1664#[cfg(feature="random")]
1665fn packable_tofeventv0() {
1666 for _ in 0..500 {
1667 let mut data = TofEvent::from_random();
1668 if data.version != ProtocolVersion::Unknown {
1669 continue;
1670 }
1671 let mut test : TofEvent = data.pack().unpack().unwrap();
1672 let fix_time = Instant::now();
1679 test.creation_time = fix_time;
1680 data.creation_time = fix_time;
1681 for k in &mut data.rb_events {
1682 k.creation_time = None;
1683 }
1684 for k in &mut test.rb_events {
1685 k.creation_time = None;
1686 }
1687 for h in &mut test.hits {
1688 h.paddle_len = 0.0;
1689 h.coax_cable_time = 0.0;
1690 h.hart_cable_time = 0.0;
1691 h.x = 0.0;
1692 h.y = 0.0;
1693 h.z = 0.0;
1694 h.event_t0 = 0.0;
1695 }
1696 assert_eq!(data, test);
1697 }
1698}
1699
1700#[test]
1701#[cfg(feature="random")]
1702fn packable_tofeventv1() {
1703 for _ in 0..500 {
1704 let mut data = TofEvent::from_random();
1705 if data.version != ProtocolVersion::V1 {
1706 continue;
1707 }
1708 let mut test : TofEvent = data.pack().unpack().unwrap();
1709 let fix_time = Instant::now();
1714 test.creation_time = fix_time;
1715 data.creation_time = fix_time;
1716 for k in &mut data.rb_events {
1717 k.creation_time = None;
1718 }
1719 for k in &mut test.rb_events {
1720 k.creation_time = None;
1721 }
1722 for h in &mut test.hits {
1723 h.paddle_len = 0.0;
1724 h.coax_cable_time = 0.0;
1725 h.hart_cable_time = 0.0;
1726 h.x = 0.0;
1727 h.y = 0.0;
1728 h.z = 0.0;
1729 h.event_t0 = 0.0;
1730 }
1731 assert_eq!(data, test);
1732 }
1733}
1734
1735#[test]
1736#[cfg(feature="random")]
1737fn packable_tofeventv2() {
1738 for _ in 0..500 {
1739 let mut data = TofEvent::from_random();
1740 if data.version != ProtocolVersion::V2 {
1741 continue;
1742 }
1743 let mut test : TofEvent = data.pack().unpack().unwrap();
1744 let fix_time = Instant::now();
1749 test.creation_time = fix_time;
1750 data.creation_time = fix_time;
1751 for k in &mut data.rb_events {
1752 k.creation_time = None;
1753 }
1754 for k in &mut test.rb_events {
1755 k.creation_time = None;
1756 }
1757 for h in &mut test.hits {
1758 h.paddle_len = 0.0;
1759 h.coax_cable_time = 0.0;
1760 h.hart_cable_time = 0.0;
1761 h.x = 0.0;
1762 h.y = 0.0;
1763 h.z = 0.0;
1764 h.event_t0 = 0.0;
1765 }
1766 assert_eq!(data, test);
1767 }
1768}
1769
1770#[test]
1771#[cfg(feature="random")]
1772fn packable_tofeventv3() {
1773 for _ in 0..500 {
1774 let mut data = TofEvent::from_random();
1775 if data.version != ProtocolVersion::V3 {
1776 continue;
1777 }
1778 let mut test : TofEvent = data.pack().unpack().unwrap();
1779 let fix_time = Instant::now();
1784 test.creation_time = fix_time;
1785 data.creation_time = fix_time;
1786 for h in &mut test.hits {
1787 h.paddle_len = 0.0;
1788 h.coax_cable_time = 0.0;
1789 h.hart_cable_time = 0.0;
1790 h.x = 0.0;
1791 h.y = 0.0;
1792 h.z = 0.0;
1793 h.event_t0 = 0.0;
1794 }
1795 assert_eq!(data, test);
1796 }
1797}
1798
1799#[test]
1800#[cfg(feature="random")]
1801fn tofevent_move_hits() {
1802 let mut event = TofEvent::from_random();
1803 let mut n_hits_exp = 0usize;
1804 for rb in &event.rb_events {
1805 n_hits_exp += rb.hits.len();
1806 }
1807 event.hits.clear();
1808 event.move_hits();
1809 for rb in &event.rb_events {
1810 assert_eq!(rb.hits.len(),0);
1811 }
1812 assert_eq!(n_hits_exp, event.hits.len());
1813
1814}
1815
1816#[test]
1817#[cfg(feature="random")]
1818fn tofevent_striprbevents() {
1819 let mut event = TofEvent::from_random();
1820 let mut n_hits_exp = 0usize;
1821 for rb in &event.rb_events {
1822 n_hits_exp += rb.hits.len();
1823 }
1824 event.hits.clear();
1825 event.strip_rbevents();
1826 assert_eq!(event.rb_events.len(),0);
1827 assert_eq!(n_hits_exp, event.hits.len());
1828}
1829
1830