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 get_mt_timestamp_abs(&self) -> u64 {
132 let gps = self.mt_tiu_gps32 as u64;
133 let mut timestamp = self.mt_timestamp as u64;
134 if timestamp < self.mt_tiu_timestamp as u64 {
135 timestamp += u32::MAX as u64 + 1;
137 }
138 let gps_mult = match 100_000_000u64.checked_mul(gps) {
139 Some(result) => result,
141 None => {
142 0 }
146 };
147 let ts = gps_mult + (timestamp - self.mt_tiu_timestamp as u64);
148 ts
149 }
150
151 pub fn move_hits(&mut self) {
158 let mut all_hits = Vec::<TofHit>::with_capacity(5);
159 for rbev in &mut self.rb_events {
160 all_hits.append(&mut rbev.hits);
161 }
162 self.hits = all_hits;
163 }
164
165 pub fn strip_rbevents(&mut self) {
170 if self.hits.len() == 0 {
171 self.move_hits();
172 }
173 self.rb_events.clear();
174 }
175
176 pub fn age(&self) -> u64 {
177 self.creation_time.elapsed().as_secs()
178 }
179
180 pub fn get_expected_rbs(&self, mapping : &HashMap<u8,u8>) -> Vec<u8> {
183 let mut expected_rbs = Vec::<u8>::new();
184 for k in self.get_rb_link_ids() {
185 match mapping.get(&k) {
186 None => {
187 error!("Seeing unassociated link id {k}");
188 }
189 Some(rb_id) => {
190 expected_rbs.push(*rb_id);
191 }
192 }
193 }
194 expected_rbs
195 }
196
197 pub fn is_complete(&mut self, exclude_rbs : Option<(&Vec<u8>,&DsiJChRbMapping)>) -> bool {
200 if exclude_rbs.is_none() {
201 return self.get_rb_link_ids().len() == self.rb_events.len();
202 } else {
203 let dead_rbs = exclude_rbs.unwrap();
204 let mut n_known_dead = 0usize;
205 let t_hits = self.get_trigger_hits();
206 for h in t_hits {
207 match dead_rbs.1.get(&h.0) {
208 None => {
209 continue;
210 }
211 Some(dsi) => {
212 match dsi.get(&h.1) {
213 None => {
214 continue;
215 }
216 Some(j) => {
217 match j.get(&h.2.0) {
218 None => {
219 continue;
220 }
221 Some(rb) => {
222 if dead_rbs.0.contains(&rb) {
223 n_known_dead += 1
224 }
225 }
226 }
227 }
228 }
229 }
230 }
231 } let n_rb_link_ids = self.get_rb_link_ids().len();
236 return n_rb_link_ids <= self.rb_events.len() + n_known_dead;
240 }
241 }
242
243 pub fn get_lost_hits(&self) -> u16 {
246 let mut lost_hits = 0u16;
247 for rbev in &self.rb_events {
248 if rbev.header.drs_lost_trigger() {
249 let mut nhits = rbev.header.get_nchan() as u16;
250 if nhits > 0 {
253 nhits -= 1;
254 }
255 lost_hits += nhits;
256 }
257 }
258 lost_hits
259 }
260
261
262 pub fn prepare_for_gcu(&mut self, strip_rbevents : bool) {
270 if strip_rbevents {
271 self.strip_rbevents();
272 }
273 self.version = ProtocolVersion::V1;
274 if self.n_hits_cbe == 0 && self.n_hits_umb == 0 && self.n_hits_cor == 0 {
275 self.calc_gcu_variables();
276 }
277 }
278
279 pub fn calc_gcu_variables(&mut self) {
282 if self.hits.len() == 0 {
283 for rbev in &self.rb_events {
284 for h in &rbev.hits {
285 if h.paddle_id <= 60 {
286 self.n_hits_cbe += 1;
287 self.tot_edep_cbe += h.get_edep();
288 }
289 else if h.paddle_id <= 108 && h.paddle_id > 60 {
290 self.n_hits_umb += 1;
291 self.tot_edep_umb += h.get_edep();
292 }
293 else {
294 self.n_hits_cor += 1;
295 self.tot_edep_cor += h.get_edep();
296 }
297 }
298 }
299 } else {
300 for h in &self.hits {
301 if h.paddle_id <= 60 {
302 self.n_hits_cbe += 1;
303 self.tot_edep_cbe += h.get_edep();
304 }
305 else if h.paddle_id <= 108 && h.paddle_id > 60 {
306 self.n_hits_umb += 1;
307 self.tot_edep_umb += h.get_edep();
308 }
309 else {
310 self.n_hits_cor += 1;
311 self.tot_edep_cor += h.get_edep();
312 }
313 }
314 }
315 }
316
317 pub fn decode_depr_tofevent_size_header(mask : &u32)
320 -> (usize, usize) {
321 let rb_event_len = (mask & 0xFF) as usize;
322 let miss_len = ((mask & 0xFF00) >> 8) as usize;
323 (rb_event_len, miss_len)
324 }
325
326 #[cfg(feature="database")]
331 pub fn set_timing_offsets(&mut self, offsets : &HashMap<u8, f32>) {
332 for h in self.hits.iter_mut() {
333 if offsets.contains_key(&h.paddle_id) {
334 h.timing_offset = offsets[&h.paddle_id];
335 }
336 }
337 }
338
339 pub fn lightspeed_cleaning(&mut self, t_err : f32) -> (Vec<u8>, Vec<f32>) {
351 if self.hits.len() == 0 {
353 return (Vec::<u8>::new(), Vec::<f32>::new());
354 }
355 let mut twindows = Vec::<f32>::new();
356 self.hits.sort_by(|a,b| (a.event_t0).partial_cmp(&b.event_t0).unwrap_or(Ordering::Greater));
357 let first_hit = self.hits[0].clone(); let mut clean_hits = Vec::<TofHit>::new();
361 let mut rm_hits = Vec::<u8>::new();
362 clean_hits.push(first_hit.clone());
364 let mut prior_hit = first_hit;
366 for h in self.hits.iter().skip(1) {
368 let min_tdiff_cvac = 1e9*1e-3*prior_hit.distance(h)/299792458.0;
369 let twindow = prior_hit.event_t0 + min_tdiff_cvac;
370
371 if h.event_t0 + 2.0*t_err < twindow {
380 rm_hits.push(h.paddle_id);
381 twindows.push(twindow);
382 continue;
383 }
384 prior_hit = h.clone();
400 clean_hits.push(*h);
401 }
402 self.hits = clean_hits;
403 (rm_hits, twindows)
404 }
405
406
407 pub fn remove_non_causal_hits(&mut self) -> Vec<u8> {
417 let mut clean_hits = Vec::<TofHit>::new();
418 let mut removed_pids = Vec::<u8>::new();
419 for h in &self.hits {
420 if h.obeys_causality() {
421 clean_hits.push(*h);
422 } else {
423 removed_pids.push(h.paddle_id);
424 }
425 }
426 self.hits = clean_hits;
427 removed_pids
428 }
429
430 #[cfg(feature="database")]
431 pub fn normalize_hit_times(&mut self) {
432 if self.hits.len() == 0 {
433 return;
434 }
435 if self.hits[0].event_t0 == 0.0 {
437 return;
438 }
439
440 let phase0 = self.hits[0].phase.to_f32();
441 for h in &mut self.hits {
442 let t0 = h.get_t0_uncorrected() + h.get_cable_delay();
443 let mut phase_diff = h.phase.to_f32() - phase0;
444 while phase_diff < - PI/2.0 {
445 phase_diff += 2.0*PI;
446 }
447 while phase_diff > PI/2.0 {
448 phase_diff -= 2.0*PI;
449 }
450 let t_shift = 50.0*phase_diff/(2.0*PI);
451 h.event_t0 = t0 + t_shift;
452 }
453 self.hits.sort_by(|a,b| (a.event_t0).total_cmp(&b.event_t0));
456 let t0_first_hit = self.hits[0].event_t0;
457 for h in self.hits.iter_mut() {
458 h.event_t0 -= t0_first_hit;
459 }
460 }
461
462 #[cfg(feature="database")]
463 pub fn set_paddles(&mut self, paddles : &HashMap<u8, TofPaddle>) {
464 let mut nerror = 0u8;
465 if paddles.is_empty() {
466 debug!("Unable to set paddles, empty map given!");
467 return;
468 }
469 if self.hits.len() == 0 {
470 for rbev in &mut self.rb_events {
471 for h in &mut rbev.hits {
472 match paddles.get(&h.paddle_id) {
473 None => {
474 error!("Got paddle id {} which is not in given map!", h.paddle_id);
475 nerror += 1;
476 continue;
477 }
478 Some(pdl) => {
479 h.set_paddle(pdl);
480 }
481 }
482 }
483 }
484 } else {
485 for h in &mut self.hits {
486 match paddles.get(&h.paddle_id) {
487 None => {
488 error!("Got paddle id {} which is not in given map!", h.paddle_id);
489 nerror += 1;
490 continue;
491 }
492 Some(pdl) => {
493 h.set_paddle(pdl);
494 }
495 }
496 }
497 }
498 if nerror == 0 {
499 self.paddles_set = true;
500 }
502 }
503
504 pub fn get_pointcloud(&self) -> Option<Vec<(f32,f32,f32,f32,f32)>> {
509 let mut pc = Vec::<(f32,f32,f32,f32,f32)>::new();
510 if !self.paddles_set {
511 error!("Before getting the pointcloud, paddle information needs to be set for this event. Call TofEvent;:set_paddle");
512 return None;
513 }
514 for h in &self.hits {
515 let result = (h.x, h.y, h.z, h.get_t0(), h.get_edep());
516 pc.push(result);
517 }
518 Some(pc)
519 }
520
521 #[cfg(feature="database")]
530 pub fn get_missing_paddles_hg(&self, pid_map : &DsiJChPidMapping) -> Vec<u8> {
531 let mut missing = Vec::<u8>::new();
532 for th in self.get_trigger_hits() {
533 if !pid_map.contains_key(&th.0) {
534 error!("Can't find {:?} in paddlemap!",th);
535 continue;
536 }
537 if !pid_map.get(&th.0).unwrap().contains_key(&th.1) {
538 error!("Can't find {:?} in paddlemap!",th);
539 continue;
540 }
541 if !pid_map.get(&th.0).unwrap().get(&th.1).unwrap().contains_key(&th.2.0) {
542 error!("Can't find {:?} in paddlemap!",th);
543 continue;
544 }
545 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
546 let mut found = false;
547 for h in &self.hits {
548 if h.paddle_id == pid {
549 found = true;
550 break
551 }
552 }
553 if !found {
554 missing.push(pid);
555 }
556 }
557 missing
558 }
559
560 #[cfg(feature="database")]
564 pub fn get_triggered_paddles(&self, pid_map : &DsiJChPidMapping) -> Vec<u8> {
565 let mut paddles = Vec::<u8>::with_capacity(3);
566 for th in &self.get_trigger_hits() {
567 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
568 paddles.push(pid);
569 }
570 paddles
571 }
572
573 pub fn get_rb_link_ids(&self) -> Vec<u8> {
575 let mut links = Vec::<u8>::new();
576 for k in 0..64 {
577 if (self.mtb_link_mask >> k) as u64 & 0x1 == 1 {
578 links.push(k as u8);
579 }
580 }
581 links
582 }
583
584 pub fn get_trigger_hits(&self) -> Vec<(u8, u8, (u8, u8), LTBThreshold)> {
597 let mut hits = Vec::<(u8,u8,(u8,u8),LTBThreshold)>::with_capacity(5);
598 let n_masks_needed = self.dsi_j_mask.count_ones();
600 if self.channel_mask.len() < n_masks_needed as usize {
601 error!("We need {} hit masks, but only have {}! This is bad!", n_masks_needed, self.channel_mask.len());
602 return hits;
603 }
604 let mut n_mask = 0;
605 trace!("Expecting {} hit masks", n_masks_needed);
606 trace!("ltb channels {:?}", self.dsi_j_mask);
607 trace!("hit masks {:?}", self.channel_mask);
608 for k in 0..32 {
612 if (self.dsi_j_mask >> k) as u32 & 0x1 == 1 {
613 let mut dsi = 0u8;
614 let mut j = 0u8;
615 if k < 5 {
616 dsi = 1;
617 j = k as u8 + 1;
618 } else if k < 10 {
619 dsi = 2;
620 j = k as u8 - 5 + 1;
621 } else if k < 15 {
622 dsi = 3;
623 j = k as u8- 10 + 1;
624 } else if k < 20 {
625 dsi = 4;
626 j = k as u8- 15 + 1;
627 } else if k < 25 {
628 dsi = 5;
629 j = k as u8 - 20 + 1;
630 }
631 let channels = self.channel_mask[n_mask];
635 for (i,ch) in LTB_CHANNELS.iter().enumerate() {
636 let ph_chn = PHYSICAL_CHANNELS[i];
638 let thresh_bits = ((channels & ch) >> (i*2)) as u8;
641 if thresh_bits > 0 { hits.push((dsi, j, ph_chn, LTBThreshold::from(thresh_bits)));
644 }
645 }
646 n_mask += 1;
647 } }
649 hits
650 }
651
652 pub fn get_trigger_sources(&self) -> Vec<TriggerType> {
654 TriggerType::transcode_trigger_sources(self.trigger_sources)
655 }
656
657 pub fn get_timestamp48(&self) -> u64 {
658 0x273000000000000 | (((self.timestamp16 as u64) << 32) | self.timestamp32 as u64)
661 }
662
663 pub fn get_edep_umbrella(&self) -> f32 {
668 let mut tot_edep = 0.0f32;
669 for h in &self.hits {
670 if h.paddle_id < 61 || h.paddle_id > 108 {
671 continue;
672 }
673 tot_edep += h.get_edep();
674 }
675 tot_edep
676 }
677
678 pub fn get_edep_cube(&self) -> f32 {
683 let mut tot_edep = 0.0f32;
684 for h in &self.hits {
685 if h.paddle_id > 60 {
686 continue;
687 }
688 tot_edep += h.get_edep();
689 }
690 tot_edep
691 }
692
693 pub fn get_edep_cortina(&self) -> f32 {
698 let mut tot_edep = 0.0f32;
699 for h in &self.hits {
700 if h.paddle_id < 109 {
701 continue;
702 }
703 tot_edep += h.get_edep();
704 }
705 tot_edep
706 }
707
708 pub fn get_edep(&self) -> f32 {
713 let mut tot_edep = 0.0f32;
714 for h in &self.hits {
715 tot_edep += h.get_edep();
716 }
717 tot_edep
718 }
719
720 pub fn get_nhits_umb(&self) -> usize {
721 let mut nhit = 0;
722 for h in &self.hits {
723 if h.paddle_id > 60 && h.paddle_id < 109 {
724 nhit += 1;
725 }
726 }
727 nhit
728 }
729
730 pub fn get_nhits_cbe(&self) -> usize {
731 let mut nhit = 0;
732 for h in &self.hits {
733 if h.paddle_id < 61 {
734 nhit += 1;
735 }
736 }
737 nhit
738 }
739
740 pub fn get_nhits_cor(&self) -> usize {
741 let mut nhit = 0;
742 for h in &self.hits {
743 if h.paddle_id > 108 {
744 nhit += 1;
745 }
746 }
747 nhit
748 }
749
750 pub fn get_nhits(&self) -> usize {
751 self.hits.len()
752 }
753
754 pub fn has_any_mangling(&self) -> bool {
757 for rbev in &self.rb_events {
758 if rbev.status == EventStatus::CellAndChnSyncErrors
759 || rbev.status == EventStatus::CellSyncErrors
760 || rbev.status == EventStatus::ChnSyncErrors {
761 return true;
762 }
763 }
764 false
765 }
766
767 pub fn get_waveforms(&self) -> Vec<RBWaveform> {
772 let mut wfs = Vec::<RBWaveform>::new();
773 for ev in &self.rb_events {
774 for wf in &ev.get_rbwaveforms() {
775 wfs.push(wf.clone());
776 }
777 }
778 wfs
779 }
780
781 pub fn set_packed_status_version(pack : &mut TofPacket, version : ProtocolVersion)
785 -> Result<(), SerializationError> {
786 if pack.packet_type != TofPacketType::TofEvent {
787 return Err(SerializationError::IncorrectPacketType);
788 }
789 let mut status_version = pack.payload[2];
790 status_version = status_version & 0x3f;
792 status_version = status_version | version.to_u8();
794 pack.payload[2] = status_version;
795 Ok(())
796 }
797
798 pub fn strip_packed_rbevents_for_pv3(pack : &mut TofPacket)
807 -> Result<(), SerializationError> {
808 if pack.packet_type != TofPacketType::TofEvent {
809 return Err(SerializationError::IncorrectPacketType);
810 }
811 let status_version = pack.payload[2];
812 let mut version = ProtocolVersion::from(status_version & 0xc0);
813 if version != ProtocolVersion::V3 {
814 error!("This operation can only be executed on {}, however, this is version {}!", ProtocolVersion::V3, version);
815 return Err(SerializationError::WrongProtocolVersion);
816 }
817 let mut pos = 0usize;
819 pos += 10; pos += 15; pos += 15;
822 if pack.payload.len() >= pos {
823 return Err(SerializationError::StreamTooShort);
824 }
825 let nmasks = parse_u8(&pack.payload, &mut pos);
826 for _ in 0..nmasks {
827 pos += 2;
828 }
829 pos += 8;
830 let nhits = parse_u16(&pack.payload,&mut pos);
831 for _ in 0..nhits {
833 pos += TofHit::SIZE;
834 }
839 pack.payload.truncate(pack.payload.len() - pos);
843 pack.payload.extend_from_slice(&Self::TAIL.to_le_bytes());
844 version = ProtocolVersion::V2;
845 Self::set_packed_status_version(pack, version)?;
846 Ok(())
847 }
848}
849
850impl TofPackable for TofEvent {
851 const TOF_PACKET_TYPE : TofPacketType = TofPacketType::TofEvent;
853 const TOF_PACKET_TYPE_ALT : TofPacketType = TofPacketType::TofEventDeprecated;
854}
855
856impl Serialization for TofEvent {
857
858 const HEAD : u16 = 43690; const TAIL : u16 = 21845; fn to_bytestream(&self) -> Vec<u8> {
862 let mut stream = Vec::<u8>::new();
863 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
864 let status_version = self.status as u8 | self.version.to_u8();
865 stream.push(status_version);
866 stream.extend_from_slice(&self.trigger_sources.to_le_bytes());
867 stream.extend_from_slice(&self.n_trigger_paddles.to_le_bytes());
868 stream.extend_from_slice(&self.event_id.to_le_bytes());
869 if self.version == ProtocolVersion::V1
871 || self.version == ProtocolVersion::V3 {
872 stream.extend_from_slice(&self.n_hits_umb .to_le_bytes());
873 stream.extend_from_slice(&self.n_hits_cbe .to_le_bytes());
874 stream.extend_from_slice(&self.n_hits_cor .to_le_bytes());
875 stream.extend_from_slice(&self.tot_edep_umb.to_le_bytes());
876 stream.extend_from_slice(&self.tot_edep_cbe.to_le_bytes());
877 stream.extend_from_slice(&self.tot_edep_cor.to_le_bytes());
878 }
879 stream.extend_from_slice(&(self.quality as u8).to_le_bytes());
880 stream.extend_from_slice(&self.timestamp32.to_le_bytes());
881 stream.extend_from_slice(&self.timestamp16.to_le_bytes());
882 stream.extend_from_slice(&self.run_id.to_le_bytes());
883 stream.extend_from_slice(&self.drs_dead_lost_hits.to_le_bytes());
884 stream.extend_from_slice(&self.dsi_j_mask.to_le_bytes());
885 let n_channel_masks = self.channel_mask.len();
886 stream.push(n_channel_masks as u8);
887 for k in 0..n_channel_masks {
888 stream.extend_from_slice(&self.channel_mask[k].to_le_bytes());
889 }
890 stream.extend_from_slice(&self.mtb_link_mask.to_le_bytes());
891 let nhits = self.hits.len() as u16;
892 stream.extend_from_slice(&nhits.to_le_bytes());
893 for k in 0..self.hits.len() {
894 stream.extend_from_slice(&self.hits[k].to_bytestream());
895 }
896 if self.version == ProtocolVersion::V2
899 || self.version == ProtocolVersion::V3 {
900 stream.push(self.rb_events.len() as u8);
901 for rbev in &self.rb_events {
902 stream.extend_from_slice(&rbev.to_bytestream());
903 }
904 }
905 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
906 stream
907 }
908
909 fn from_bytestream(stream : &Vec<u8>,
910 pos : &mut usize)
911 -> Result<Self, SerializationError>{
912 let mut event = Self::new();
913 let head = parse_u16(stream, pos);
914 if head != Self::HEAD {
915 error!("Decoding of HEAD failed! Got {} instead!", head);
916 return Err(SerializationError::HeadInvalid);
917 }
918
919 let status_version_u8 = parse_u8(stream, pos);
920 let status = EventStatus::from(status_version_u8 & 0x3f);
921 let version = ProtocolVersion::from(status_version_u8 & 0xc0);
922 event.status = status;
923 event.version = version;
924 event.trigger_sources = parse_u16(stream, pos);
925 event.n_trigger_paddles = parse_u8(stream, pos);
926 event.event_id = parse_u32(stream, pos);
927 if event.version == ProtocolVersion::V1
928 || event.version == ProtocolVersion::V3 {
929 event.n_hits_umb = parse_u8(stream, pos);
930 event.n_hits_cbe = parse_u8(stream, pos);
931 event.n_hits_cor = parse_u8(stream, pos);
932 event.tot_edep_umb = parse_f32(stream, pos);
933 event.tot_edep_cbe = parse_f32(stream, pos);
934 event.tot_edep_cor = parse_f32(stream, pos);
935 }
936 event.quality = EventQuality::from(parse_u8(stream, pos));
937 event.timestamp32 = parse_u32(stream, pos);
938 event.timestamp16 = parse_u16(stream, pos);
939 event.run_id = parse_u16(stream, pos);
940 event.drs_dead_lost_hits = parse_u16(stream, pos);
941 event.dsi_j_mask = parse_u32(stream, pos);
942 let n_channel_masks = parse_u8(stream, pos);
943 for _ in 0..n_channel_masks {
944 event.channel_mask.push(parse_u16(stream, pos));
945 }
946 event.mtb_link_mask = parse_u64(stream, pos);
947 let nhits = parse_u16(stream, pos);
948 if nhits > 160 {
950 error!("There are an abnormous amount of hits in this event!");
951 return Err(SerializationError::StreamTooLong);
952 }
953 for _ in 0..nhits {
954 event.hits.push(TofHit::from_bytestream(stream, pos)?);
955 }
956 if event.version == ProtocolVersion::V2
957 || event.version == ProtocolVersion::V3 {
958 let n_rb_events = parse_u8(stream, pos);
959 if n_rb_events > 0 {
960 for _ in 0..n_rb_events {
961 event.rb_events.push(RBEvent::from_bytestream(stream, pos)?);
962 }
963 }
964 }
965
966 let tail = parse_u16(stream, pos);
967 if tail != Self::TAIL {
968 error!("Decoding of TAIL failed for version {}! Got {} instead!", version, tail);
969 return Err(SerializationError::TailInvalid);
970 }
971 Ok(event)
972 }
973
974 fn from_bytestream_alt(stream : &Vec<u8>,
980 pos : &mut usize)
981 -> Result<Self, SerializationError> {
982 let head = parse_u16(stream, pos);
983 if head != TofEvent::HEAD {
984 return Err(SerializationError::HeadInvalid);
985 }
986 let mut te = Self::new();
987 let _compression_level = parse_u8(stream, pos);
989
990 te.quality = EventQuality::from(parse_u8(stream, pos));
991 *pos += 2; te.run_id = parse_u32(stream, pos) as u16;
997 *pos += 43 - 6;*pos += 2; let event_status = parse_u8 (stream, pos);
1002 te.status = EventStatus::from(event_status);
1003 if te.has_any_mangling() {
1004 te.status = EventStatus::AnyDataMangling;
1005 }
1006 te.event_id = parse_u32(stream, pos);
1007 let mtb_timestamp = parse_u32(stream, pos);
1008 let tiu_timestamp = parse_u32(stream, pos);
1009 let tiu_gps32 = parse_u32(stream, pos);
1010 let _tiu_gps16 = parse_u16(stream,pos);
1011 let _crc = parse_u32(stream, pos);
1012 let mt_timestamp = (mt_event_get_timestamp_abs48(mtb_timestamp, tiu_gps32, tiu_timestamp ) as f64/1000.0).floor() as u64;
1013 te.timestamp32 = (mt_timestamp & 0x00000000ffffffff ) as u32;
1014 te.timestamp16 = ((mt_timestamp & 0x0000ffff00000000 ) >> 32) as u16;
1015 te.trigger_sources = parse_u16(stream, pos);
1016 te.dsi_j_mask = parse_u32(stream, pos);
1017 let n_channel_masks = parse_u8(stream, pos);
1018 for _ in 0..n_channel_masks {
1019 te.channel_mask.push(parse_u16(stream, pos));
1020 }
1021
1022 te.mtb_link_mask = parse_u64(stream, pos);
1023 let mt_event_tail = parse_u16(stream, pos);
1024 if mt_event_tail != Self::TAIL {
1025 error!("Parsed TAIL from MT event is incorrect! Got {} instead of {} at pos {}", mt_event_tail, Self::TAIL, pos);
1027 }
1028 let v_sizes = Self::decode_depr_tofevent_size_header(&parse_u32(stream, pos));
1030 for _ in 0..v_sizes.0 {
1032 let next_rb_event = RBEvent::from_bytestream(stream, pos)?;
1035 te.rb_events.push(next_rb_event);
1037 }
1038 for rbev in &te.rb_events {
1044 for h in &rbev.hits {
1045 te.hits.push(*h);
1046 }
1047 }
1048 let tail = parse_u16(stream, pos);
1049 if tail != Self::TAIL {
1050 error!("Decoding of TAIL failed! Got {} instead!", tail);
1051 return Err(SerializationError::TailInvalid);
1052 }
1053 return Ok(te);
1054 }
1055}
1056
1057impl Default for TofEvent {
1058 fn default() -> Self {
1059 Self::new()
1060 }
1061}
1062
1063impl fmt::Display for TofEvent {
1064 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1065 let mut repr = format!("<TofEvent (version {})", self.version);
1066 repr += &(format!("\n EventID : {}", self.event_id));
1067 repr += &(format!("\n RunID : {}", self.run_id));
1068 repr += &(format!("\n EventStatus : {}", self.status));
1069 repr += &(format!("\n TriggerSources : {:?}", self.get_trigger_sources()));
1070 repr += &(format!("\n NTrigPaddles : {}", self.n_trigger_paddles));
1071 repr += &(format!("\n DRS dead hits : {}", self.drs_dead_lost_hits));
1072 repr += &(format!("\n timestamp32 : {}", self.timestamp32));
1073 repr += &(format!("\n timestamp16 : {}", self.timestamp16));
1074 repr += &(format!("\n |-> timestamp48 : {}", self.get_timestamp48()));
1075 repr += &(format!("\n |-> UNIX : {}", (1e-8) * self.get_timestamp48() as f64));
1076 repr += &(format!("\n |-> UTC : {}", get_utc_timestamp_from_unix((1e-8) * self.get_timestamp48() as f64).unwrap_or(String::from("INVALID"))));
1077 if self.version == ProtocolVersion::V1 {
1085 repr += "\n ---- V1 variables ----";
1086 repr += &(format!("\n n_hits_umb : {}", self.n_hits_umb ));
1087 repr += &(format!("\n n_hits_cbe : {}", self.n_hits_cbe ));
1088 repr += &(format!("\n n_hits_cor : {}", self.n_hits_cor ));
1089 repr += &(format!("\n tot_edep_umb : {}", self.tot_edep_umb));
1090 repr += &(format!("\n tot_edep_cbe : {}", self.tot_edep_cbe));
1091 repr += &(format!("\n tot_edep_cor : {}", self.tot_edep_cor));
1092 }
1093 repr += &(format!("\n ** ** TRIGGER HITS (DSI/J/CH) [{} LTBS] ** **", self.dsi_j_mask.count_ones()));
1094 for k in self.get_trigger_hits() {
1095 repr += &(format!("\n => {}/{}/({},{}) ({}) ", k.0, k.1, k.2.0, k.2.1, k.3));
1096 }
1097 repr += "\n ** ** MTB LINK IDs ** **";
1098 let mut mtblink_str = String::from("\n => ");
1099 for k in self.get_rb_link_ids() {
1100 mtblink_str += &(format!("{} ", k))
1101 }
1102 repr += &mtblink_str;
1103 repr += &(format!("\n == Trigger hits {}, expected RBEvents {}",
1104 self.get_trigger_hits().len(),
1105 self.get_rb_link_ids().len()));
1106 repr += &String::from("\n ** ** ** HITS ** ** **");
1107 for h in &self.hits {
1108 repr += &(format!("\n {}", h));
1109 }
1110 if self.rb_events.len() > 0 {
1111 repr += &format!("\n -- has {} RBEvents with waveforms!", self.rb_events.len());
1112 repr += "\n -- -- boards: ";
1113 for b in &self.rb_events {
1114 repr += &format!("{} ", b.header.rb_id);
1115 }
1116 }
1117 repr += ">";
1118 write!(f, "{}", repr)
1119 }
1120}
1121
1122#[cfg(feature="random")]
1123impl FromRandom for TofEvent {
1124
1125 fn from_random() -> Self {
1126 let mut event = Self::new();
1127 let mut rng = rand::rng();
1128 let status = EventStatus::from_random();
1129 let version = ProtocolVersion::from_random();
1130 if version == ProtocolVersion::V1 {
1131 event.n_hits_umb = rng.random::<u8>();
1132 event.n_hits_cbe = rng.random::<u8>();
1133 event.n_hits_cor = rng.random::<u8>();
1134 event.tot_edep_umb = rng.random::<f32>();
1135 event.tot_edep_cbe = rng.random::<f32>();
1136 event.tot_edep_cor = rng.random::<f32>();
1137 event.quality = EventQuality::from_random();
1138 }
1139 event.status = status;
1140 event.version = version;
1141 event.trigger_sources = rng.random::<u16>();
1143 event.n_trigger_paddles = rng.random::<u8>();
1144 event.event_id = rng.random::<u32>();
1145 event.timestamp32 = rng.random::<u32>();
1146 event.timestamp16 = rng.random::<u16>();
1147 event.drs_dead_lost_hits = rng.random::<u16>();
1148 event.dsi_j_mask = rng.random::<u32>();
1149 let n_channel_masks = rng.random::<u8>();
1150 for _ in 0..n_channel_masks {
1151 event.channel_mask.push(rng.random::<u16>());
1152 }
1153 event.mtb_link_mask = rng.random::<u64>();
1154 let nhits: u16 = rng.random_range(0..5);
1156 for _ in 0..nhits {
1157 event.hits.push(TofHit::from_random());
1158 }
1159 if event.version == ProtocolVersion::V2 {
1160 let n_rb_events = rng.random_range(0..4);
1161 for _ in 0..n_rb_events {
1162 event.rb_events.push(RBEvent::from_random());
1163 }
1164 }
1165 event
1166 }
1167}
1168
1169#[cfg(feature="pybindings")]
1172#[pymethods]
1173impl TofEvent {
1174
1175 #[pyo3(name="strip_rbevents")]
1176 fn strip_rbevents_py(&mut self) {
1177 self.strip_rbevents()
1178 }
1179
1180 #[pyo3(name="calc_gcu_variables")]
1183 fn calc_gcu_variables_py(&mut self) {
1184 self.calc_gcu_variables()
1185 }
1186
1187 fn copy(&self) -> Self {
1189 self.clone()
1190 }
1191
1192 #[pyo3(name="set_timing_offsets")]
1193 pub fn set_timing_offsets_py(&mut self, timing_offsets : HashMap<u8, f32>) {
1194 self.set_timing_offsets(&timing_offsets);
1195 }
1196
1197 #[pyo3(name="normalize_hit_times")]
1198 pub fn normalize_hit_times_py(&mut self) {
1199 self.normalize_hit_times();
1200 }
1201
1202 #[pyo3(name="lightspeed_cleaning")]
1210 pub fn lightspeed_cleaning_py(&mut self, t_err : f32) -> (Vec<u16>, Vec<f32>) {
1211 let mut pids = Vec::<u16>::new();
1214 let (pids_rm, twindows) = self.lightspeed_cleaning(t_err);
1215 for pid in pids_rm {
1216 pids.push(pid as u16);
1217 }
1218 (pids, twindows)
1219 }
1220
1221 #[getter]
1223 fn get_run_id(&self) -> u16 {
1224 self.run_id
1225 }
1226
1227 #[pyo3(name="remove_non_causal_hits")]
1232 fn remove_non_causal_hits_py(&mut self) -> Vec<u16> {
1233 let mut pids = Vec::<u16>::new();
1236 for pid in self.remove_non_causal_hits() {
1237 pids.push(pid as u16);
1238 }
1239 pids
1240 }
1241
1242 #[getter]
1243 fn pointcloud(&self) -> Option<Vec<(f32,f32,f32,f32,f32)>> {
1244 self.get_pointcloud()
1245 }
1246
1247 #[getter]
1248 #[pyo3(name="has_any_mangling")]
1249 fn has_any_mangling_py(&self) -> bool {
1250 self.has_any_mangling()
1251 }
1252
1253 #[getter]
1254 fn get_event_id(&self) -> u32 {
1255 self.event_id
1256 }
1257
1258 #[getter]
1259 fn get_event_status(&self) -> EventStatus {
1260 self.status
1261 }
1262
1263 #[pyo3(name="get_missing_paddles_hg")]
1266 fn get_missing_paddles_hg_py(&self, mapping : DsiJChPidMapping) -> Vec<u8> {
1267 self.get_missing_paddles_hg(&mapping)
1268 }
1269
1270 #[pyo3(name="get_triggered_paddles")]
1272 fn get_triggered_paddles_py(&self, mapping : DsiJChPidMapping) -> Vec<u8> {
1273 self.get_triggered_paddles(&mapping)
1274 }
1275
1276 #[getter]
1279 fn lost_hits(&self) -> u16 {
1280 self.drs_dead_lost_hits
1281 }
1282
1283 #[getter]
1286 fn rb_link_ids(&self) -> Vec<u32> {
1287 self.get_rb_link_ids().into_iter().map(|byte| byte as u32).collect()
1288 }
1289
1290 #[getter]
1292 fn get_rb_events(&self) -> Vec<RBEvent> {
1293 self.rb_events.clone()
1294 }
1295
1296 #[getter]
1298 pub fn trigger_hits(&self) -> PyResult<Vec<(u8, u8, (u8, u8), LTBThreshold)>> {
1299 Ok(self.get_trigger_hits())
1300 }
1301
1302 #[getter]
1305 pub fn trigger_sources(&self) -> Vec<TriggerType> {
1306 self.get_trigger_sources()
1307 }
1308
1309 #[getter]
1312 #[pyo3(name="trigger_sources_bytes")]
1313 pub fn get_trigger_sources_bytes_py(&self) -> u16 {
1314 self.trigger_sources
1315 }
1316
1317 #[pyo3(name="move_hits")]
1318 pub fn move_hits_py(&mut self) {
1319 self.move_hits()
1320 }
1321
1322 #[getter]
1323 #[pyo3(name="hits")]
1324 pub fn hits_py<'_py>(&self) -> Vec<TofHit> {
1325 self.hits.clone()
1329 }
1330
1331 #[getter]
1332 #[pyo3(name="hitmap")]
1333 pub fn hitmap<'_py>(&self) -> HashMap<u8,TofHit> {
1334 let mut hitmap = HashMap::<u8, TofHit>::new();
1338 for h in &self.hits {
1339 hitmap.insert(h.paddle_id, *h);
1340 }
1341 hitmap
1342 }
1343
1344 #[getter]
1349 #[pyo3(name="edep_umb")]
1350 pub fn get_edep_umbrella_py(&self) -> f32 {
1351 self.get_edep_umbrella()
1352 }
1353
1354 #[getter]
1359 #[pyo3(name="edep_cbe")]
1360 pub fn get_edep_cube_py(&self) -> f32 {
1361 self.get_edep_cube()
1362 }
1363
1364 #[getter]
1369 #[pyo3(name="edep_cor")]
1370 pub fn get_edep_cortina_py(&self) -> f32 {
1371 self.get_edep_cortina()
1372 }
1373
1374 #[getter]
1379 #[pyo3(name="edep")]
1380 pub fn get_edep_py(&self) -> f32 {
1381 self.get_edep()
1382 }
1383
1384 #[getter]
1385 #[pyo3(name="nhits")]
1386 pub fn nhits_py(&self) -> usize {
1387 self.get_nhits()
1388 }
1389
1390 #[getter]
1391 #[pyo3(name="dsi_j_mask")]
1392 pub fn get_dsi_j_mask_py(&self) -> u32 {
1393 self.dsi_j_mask
1394 }
1395
1396 #[getter]
1397 #[pyo3(name="channel_masks")]
1398 pub fn get_channel_masks_py(&self) -> Vec<u16> {
1399 self.channel_mask.clone()
1400 }
1401
1402 #[getter]
1403 #[pyo3(name="nhits_umb")]
1404 pub fn nhits_umb_py(&self) -> usize {
1405 self.get_nhits_umb()
1406 }
1407
1408 #[getter]
1409 #[pyo3(name="nhits_cbe")]
1410 fn get_nhits_cbe_py(&self) -> usize {
1411 self.get_nhits_cbe()
1412 }
1413
1414 #[getter]
1415 #[pyo3(name="nhits_cor")]
1416 fn get_nhits_cor_py(&self) -> usize {
1417 self.get_nhits_cor()
1418 }
1419
1420 #[getter]
1421 fn get_timestamp16(&self) -> u16 {
1422 self.timestamp16
1423 }
1424
1425 #[getter]
1426 fn get_timestamp32(&self) -> u32 {
1427 self.timestamp32
1428 }
1429
1430 #[getter]
1431 fn timestamp48(&self) -> u64 {
1432 self.get_timestamp48()
1433 }
1434
1435 #[getter]
1436 fn get_status(&self) -> EventStatus {
1437 self.status
1438 }
1439
1440 #[getter]
1441 #[pyo3(name="waveforms")]
1442 fn get_waveforms_py(&self) -> Vec<RBWaveform> {
1443 self.get_waveforms()
1444 }
1445
1446 #[staticmethod]
1447 #[pyo3(name = "set_packed_status_version")]
1448 fn set_packed_status_version_py(pack : &mut TofPacket, version : ProtocolVersion)
1449 -> PyResult<()> {
1450 match Self::set_packed_status_version(pack, version) {
1451 Err(err) => {
1452 let err_mesg = format!("Unable to set status version! {}", err);
1453 return Err(PyValueError::new_err(err_mesg));
1454 }
1455 Ok(_) => {
1456 return Ok(());
1457 }
1458 }
1459 }
1460
1461 #[staticmethod]
1462 #[pyo3(name = "strip_packed_rbevents_for_pv3")]
1463 fn strip_packed_rbevents_for_pv3_py(pack : &mut TofPacket)
1464 -> PyResult<()> {
1465 match Self::strip_packed_rbevents_for_pv3(pack) {
1466 Err(err) => {
1467 let err_msg = format!("Unable to strip packed rbevents{}", err);
1468 return Err(PyValueError::new_err(err_msg));
1469 }
1470 Ok(_) => {
1471 return Ok(());
1472 }
1473 }
1474 }
1475
1476 #[cfg(feature="database")]
1477 #[staticmethod]
1478 fn unpack(pack : &TofPacket) -> PyResult<Self> {
1479 if pack.packet_type != Self::TOF_PACKET_TYPE {
1480 let err_msg = format!("This is a packet of type {}, but we need type {}", pack.packet_type, Self::TOF_PACKET_TYPE);
1481 return Err(PyValueError::new_err(err_msg));
1482 }
1483 let mut pos = 0;
1484 let mut ev = Self::from_bytestream(&pack.payload,&mut pos)?;
1485 ev.set_paddles(&pack.tof_paddles);
1486 Ok(ev)
1487 }
1488}
1489
1490#[cfg(feature="pybindings")]
1491pythonize_packable!(TofEvent);
1492
1493#[test]
1496#[cfg(feature="random")]
1497fn packable_tofeventv0() {
1498 for _ in 0..500 {
1499 let mut data = TofEvent::from_random();
1500 if data.version != ProtocolVersion::Unknown {
1501 continue;
1502 }
1503 let mut test : TofEvent = data.pack().unpack().unwrap();
1504 let fix_time = Instant::now();
1511 test.creation_time = fix_time;
1512 data.creation_time = fix_time;
1513 for k in &mut data.rb_events {
1514 k.creation_time = None;
1515 }
1516 for k in &mut test.rb_events {
1517 k.creation_time = None;
1518 }
1519 for h in &mut test.hits {
1520 h.paddle_len = 0.0;
1521 h.coax_cable_time = 0.0;
1522 h.hart_cable_time = 0.0;
1523 h.x = 0.0;
1524 h.y = 0.0;
1525 h.z = 0.0;
1526 h.event_t0 = 0.0;
1527 }
1528 assert_eq!(data, test);
1529 }
1530}
1531
1532#[test]
1533#[cfg(feature="random")]
1534fn packable_tofeventv1() {
1535 for _ in 0..500 {
1536 let mut data = TofEvent::from_random();
1537 if data.version != ProtocolVersion::V1 {
1538 continue;
1539 }
1540 let mut test : TofEvent = data.pack().unpack().unwrap();
1541 let fix_time = Instant::now();
1546 test.creation_time = fix_time;
1547 data.creation_time = fix_time;
1548 for k in &mut data.rb_events {
1549 k.creation_time = None;
1550 }
1551 for k in &mut test.rb_events {
1552 k.creation_time = None;
1553 }
1554 for h in &mut test.hits {
1555 h.paddle_len = 0.0;
1556 h.coax_cable_time = 0.0;
1557 h.hart_cable_time = 0.0;
1558 h.x = 0.0;
1559 h.y = 0.0;
1560 h.z = 0.0;
1561 h.event_t0 = 0.0;
1562 }
1563 assert_eq!(data, test);
1564 }
1565}
1566
1567#[test]
1568#[cfg(feature="random")]
1569fn packable_tofeventv2() {
1570 for _ in 0..500 {
1571 let mut data = TofEvent::from_random();
1572 if data.version != ProtocolVersion::V2 {
1573 continue;
1574 }
1575 let mut test : TofEvent = data.pack().unpack().unwrap();
1576 let fix_time = Instant::now();
1581 test.creation_time = fix_time;
1582 data.creation_time = fix_time;
1583 for k in &mut data.rb_events {
1584 k.creation_time = None;
1585 }
1586 for k in &mut test.rb_events {
1587 k.creation_time = None;
1588 }
1589 for h in &mut test.hits {
1590 h.paddle_len = 0.0;
1591 h.coax_cable_time = 0.0;
1592 h.hart_cable_time = 0.0;
1593 h.x = 0.0;
1594 h.y = 0.0;
1595 h.z = 0.0;
1596 h.event_t0 = 0.0;
1597 }
1598 assert_eq!(data, test);
1599 }
1600}
1601
1602#[test]
1603#[cfg(feature="random")]
1604fn packable_tofeventv3() {
1605 for _ in 0..500 {
1606 let mut data = TofEvent::from_random();
1607 if data.version != ProtocolVersion::V3 {
1608 continue;
1609 }
1610 let mut test : TofEvent = data.pack().unpack().unwrap();
1611 let fix_time = Instant::now();
1616 test.creation_time = fix_time;
1617 data.creation_time = fix_time;
1618 for h in &mut test.hits {
1619 h.paddle_len = 0.0;
1620 h.coax_cable_time = 0.0;
1621 h.hart_cable_time = 0.0;
1622 h.x = 0.0;
1623 h.y = 0.0;
1624 h.z = 0.0;
1625 h.event_t0 = 0.0;
1626 }
1627 assert_eq!(data, test);
1628 }
1629}
1630
1631#[test]
1632#[cfg(feature="random")]
1633fn tofevent_move_hits() {
1634 let mut event = TofEvent::from_random();
1635 let mut n_hits_exp = 0usize;
1636 for rb in &event.rb_events {
1637 n_hits_exp += rb.hits.len();
1638 }
1639 event.hits.clear();
1640 event.move_hits();
1641 for rb in &event.rb_events {
1642 assert_eq!(rb.hits.len(),0);
1643 }
1644 assert_eq!(n_hits_exp, event.hits.len());
1645
1646}
1647
1648#[test]
1649#[cfg(feature="random")]
1650fn tofevent_striprbevents() {
1651 let mut event = TofEvent::from_random();
1652 let mut n_hits_exp = 0usize;
1653 for rb in &event.rb_events {
1654 n_hits_exp += rb.hits.len();
1655 }
1656 event.hits.clear();
1657 event.strip_rbevents();
1658 assert_eq!(event.rb_events.len(),0);
1659 assert_eq!(n_hits_exp, event.hits.len());
1660}
1661
1662