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 self.hits.len() == 0 {
466 for rbev in &mut self.rb_events {
467 for h in &mut rbev.hits {
468 match paddles.get(&h.paddle_id) {
469 None => {
470 error!("Got paddle id {} which is not in given map!", h.paddle_id);
471 nerror += 1;
472 continue;
473 }
474 Some(pdl) => {
475 h.set_paddle(pdl);
476 }
477 }
478 }
479 }
480 } else {
481 for h in &mut self.hits {
482 match paddles.get(&h.paddle_id) {
483 None => {
484 error!("Got paddle id {} which is not in given map!", h.paddle_id);
485 nerror += 1;
486 continue;
487 }
488 Some(pdl) => {
489 h.set_paddle(pdl);
490 }
491 }
492 }
493 }
494 if nerror == 0 {
495 self.paddles_set = true;
496 }
498 }
499
500 pub fn get_pointcloud(&self) -> Option<Vec<(f32,f32,f32,f32,f32)>> {
505 let mut pc = Vec::<(f32,f32,f32,f32,f32)>::new();
506 if !self.paddles_set {
507 error!("Before getting the pointcloud, paddle information needs to be set for this event. Call TofEvent;:set_paddle");
508 return None;
509 }
510 for h in &self.hits {
511 let result = (h.x, h.y, h.z, h.get_t0(), h.get_edep());
512 pc.push(result);
513 }
514 Some(pc)
515 }
516
517 #[cfg(feature="database")]
526 pub fn get_missing_paddles_hg(&self, pid_map : &DsiJChPidMapping) -> Vec<u8> {
527 let mut missing = Vec::<u8>::new();
528 for th in self.get_trigger_hits() {
529 if !pid_map.contains_key(&th.0) {
530 error!("Can't find {:?} in paddlemap!",th);
531 continue;
532 }
533 if !pid_map.get(&th.0).unwrap().contains_key(&th.1) {
534 error!("Can't find {:?} in paddlemap!",th);
535 continue;
536 }
537 if !pid_map.get(&th.0).unwrap().get(&th.1).unwrap().contains_key(&th.2.0) {
538 error!("Can't find {:?} in paddlemap!",th);
539 continue;
540 }
541 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
542 let mut found = false;
543 for h in &self.hits {
544 if h.paddle_id == pid {
545 found = true;
546 break
547 }
548 }
549 if !found {
550 missing.push(pid);
551 }
552 }
553 missing
554 }
555
556 #[cfg(feature="database")]
560 pub fn get_triggered_paddles(&self, pid_map : &DsiJChPidMapping) -> Vec<u8> {
561 let mut paddles = Vec::<u8>::with_capacity(3);
562 for th in &self.get_trigger_hits() {
563 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
564 paddles.push(pid);
565 }
566 paddles
567 }
568
569 pub fn get_rb_link_ids(&self) -> Vec<u8> {
571 let mut links = Vec::<u8>::new();
572 for k in 0..64 {
573 if (self.mtb_link_mask >> k) as u64 & 0x1 == 1 {
574 links.push(k as u8);
575 }
576 }
577 links
578 }
579
580 pub fn get_trigger_hits(&self) -> Vec<(u8, u8, (u8, u8), LTBThreshold)> {
593 let mut hits = Vec::<(u8,u8,(u8,u8),LTBThreshold)>::with_capacity(5);
594 let n_masks_needed = self.dsi_j_mask.count_ones();
596 if self.channel_mask.len() < n_masks_needed as usize {
597 error!("We need {} hit masks, but only have {}! This is bad!", n_masks_needed, self.channel_mask.len());
598 return hits;
599 }
600 let mut n_mask = 0;
601 trace!("Expecting {} hit masks", n_masks_needed);
602 trace!("ltb channels {:?}", self.dsi_j_mask);
603 trace!("hit masks {:?}", self.channel_mask);
604 for k in 0..32 {
608 if (self.dsi_j_mask >> k) as u32 & 0x1 == 1 {
609 let mut dsi = 0u8;
610 let mut j = 0u8;
611 if k < 5 {
612 dsi = 1;
613 j = k as u8 + 1;
614 } else if k < 10 {
615 dsi = 2;
616 j = k as u8 - 5 + 1;
617 } else if k < 15 {
618 dsi = 3;
619 j = k as u8- 10 + 1;
620 } else if k < 20 {
621 dsi = 4;
622 j = k as u8- 15 + 1;
623 } else if k < 25 {
624 dsi = 5;
625 j = k as u8 - 20 + 1;
626 }
627 let channels = self.channel_mask[n_mask];
631 for (i,ch) in LTB_CHANNELS.iter().enumerate() {
632 let ph_chn = PHYSICAL_CHANNELS[i];
634 let thresh_bits = ((channels & ch) >> (i*2)) as u8;
637 if thresh_bits > 0 { hits.push((dsi, j, ph_chn, LTBThreshold::from(thresh_bits)));
640 }
641 }
642 n_mask += 1;
643 } }
645 hits
646 }
647
648 pub fn get_trigger_sources(&self) -> Vec<TriggerType> {
650 TriggerType::transcode_trigger_sources(self.trigger_sources)
651 }
652
653 pub fn get_timestamp48(&self) -> u64 {
654 0x273000000000000 | (((self.timestamp16 as u64) << 32) | self.timestamp32 as u64)
655 }
656
657 pub fn get_edep_umbrella(&self) -> f32 {
662 let mut tot_edep = 0.0f32;
663 for h in &self.hits {
664 if h.paddle_id < 61 || h.paddle_id > 108 {
665 continue;
666 }
667 tot_edep += h.get_edep();
668 }
669 tot_edep
670 }
671
672 pub fn get_edep_cube(&self) -> f32 {
677 let mut tot_edep = 0.0f32;
678 for h in &self.hits {
679 if h.paddle_id > 60 {
680 continue;
681 }
682 tot_edep += h.get_edep();
683 }
684 tot_edep
685 }
686
687 pub fn get_edep_cortina(&self) -> f32 {
692 let mut tot_edep = 0.0f32;
693 for h in &self.hits {
694 if h.paddle_id < 109 {
695 continue;
696 }
697 tot_edep += h.get_edep();
698 }
699 tot_edep
700 }
701
702 pub fn get_edep(&self) -> f32 {
707 let mut tot_edep = 0.0f32;
708 for h in &self.hits {
709 tot_edep += h.get_edep();
710 }
711 tot_edep
712 }
713
714 pub fn get_nhits_umb(&self) -> usize {
715 let mut nhit = 0;
716 for h in &self.hits {
717 if h.paddle_id > 60 && h.paddle_id < 109 {
718 nhit += 1;
719 }
720 }
721 nhit
722 }
723
724 pub fn get_nhits_cbe(&self) -> usize {
725 let mut nhit = 0;
726 for h in &self.hits {
727 if h.paddle_id < 61 {
728 nhit += 1;
729 }
730 }
731 nhit
732 }
733
734 pub fn get_nhits_cor(&self) -> usize {
735 let mut nhit = 0;
736 for h in &self.hits {
737 if h.paddle_id > 108 {
738 nhit += 1;
739 }
740 }
741 nhit
742 }
743
744 pub fn get_nhits(&self) -> usize {
745 self.hits.len()
746 }
747
748 pub fn has_any_mangling(&self) -> bool {
751 for rbev in &self.rb_events {
752 if rbev.status == EventStatus::CellAndChnSyncErrors
753 || rbev.status == EventStatus::CellSyncErrors
754 || rbev.status == EventStatus::ChnSyncErrors {
755 return true;
756 }
757 }
758 false
759 }
760
761 pub fn get_waveforms(&self) -> Vec<RBWaveform> {
766 let mut wfs = Vec::<RBWaveform>::new();
767 for ev in &self.rb_events {
768 for wf in &ev.get_rbwaveforms() {
769 wfs.push(wf.clone());
770 }
771 }
772 wfs
773 }
774
775 pub fn set_packed_status_version(pack : &mut TofPacket, version : ProtocolVersion)
779 -> Result<(), SerializationError> {
780 if pack.packet_type != TofPacketType::TofEvent {
781 return Err(SerializationError::IncorrectPacketType);
782 }
783 let mut status_version = pack.payload[2];
784 status_version = status_version & 0x3f;
786 status_version = status_version | version.to_u8();
788 pack.payload[2] = status_version;
789 Ok(())
790 }
791
792 pub fn strip_packed_rbevents_for_pv3(pack : &mut TofPacket)
801 -> Result<(), SerializationError> {
802 if pack.packet_type != TofPacketType::TofEvent {
803 return Err(SerializationError::IncorrectPacketType);
804 }
805 let status_version = pack.payload[2];
806 let mut version = ProtocolVersion::from(status_version & 0xc0);
807 if version != ProtocolVersion::V3 {
808 error!("This operation can only be executed on {}, however, this is version {}!", ProtocolVersion::V3, version);
809 return Err(SerializationError::WrongProtocolVersion);
810 }
811 let mut pos = 0usize;
813 pos += 10; pos += 15; pos += 15;
816 if pack.payload.len() >= pos {
817 return Err(SerializationError::StreamTooShort);
818 }
819 let nmasks = parse_u8(&pack.payload, &mut pos);
820 for _ in 0..nmasks {
821 pos += 2;
822 }
823 pos += 8;
824 let nhits = parse_u16(&pack.payload,&mut pos);
825 for _ in 0..nhits {
827 pos += TofHit::SIZE;
828 }
833 pack.payload.truncate(pack.payload.len() - pos);
837 pack.payload.extend_from_slice(&Self::TAIL.to_le_bytes());
838 version = ProtocolVersion::V2;
839 Self::set_packed_status_version(pack, version)?;
840 Ok(())
841 }
842}
843
844impl TofPackable for TofEvent {
845 const TOF_PACKET_TYPE : TofPacketType = TofPacketType::TofEvent;
847 const TOF_PACKET_TYPE_ALT : TofPacketType = TofPacketType::TofEventDeprecated;
848}
849
850impl Serialization for TofEvent {
851
852 const HEAD : u16 = 43690; const TAIL : u16 = 21845; fn to_bytestream(&self) -> Vec<u8> {
856 let mut stream = Vec::<u8>::new();
857 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
858 let status_version = self.status as u8 | self.version.to_u8();
859 stream.push(status_version);
860 stream.extend_from_slice(&self.trigger_sources.to_le_bytes());
861 stream.extend_from_slice(&self.n_trigger_paddles.to_le_bytes());
862 stream.extend_from_slice(&self.event_id.to_le_bytes());
863 if self.version == ProtocolVersion::V1
865 || self.version == ProtocolVersion::V3 {
866 stream.extend_from_slice(&self.n_hits_umb .to_le_bytes());
867 stream.extend_from_slice(&self.n_hits_cbe .to_le_bytes());
868 stream.extend_from_slice(&self.n_hits_cor .to_le_bytes());
869 stream.extend_from_slice(&self.tot_edep_umb.to_le_bytes());
870 stream.extend_from_slice(&self.tot_edep_cbe.to_le_bytes());
871 stream.extend_from_slice(&self.tot_edep_cor.to_le_bytes());
872 }
873 stream.extend_from_slice(&(self.quality as u8).to_le_bytes());
874 stream.extend_from_slice(&self.timestamp32.to_le_bytes());
875 stream.extend_from_slice(&self.timestamp16.to_le_bytes());
876 stream.extend_from_slice(&self.run_id.to_le_bytes());
877 stream.extend_from_slice(&self.drs_dead_lost_hits.to_le_bytes());
878 stream.extend_from_slice(&self.dsi_j_mask.to_le_bytes());
879 let n_channel_masks = self.channel_mask.len();
880 stream.push(n_channel_masks as u8);
881 for k in 0..n_channel_masks {
882 stream.extend_from_slice(&self.channel_mask[k].to_le_bytes());
883 }
884 stream.extend_from_slice(&self.mtb_link_mask.to_le_bytes());
885 let nhits = self.hits.len() as u16;
886 stream.extend_from_slice(&nhits.to_le_bytes());
887 for k in 0..self.hits.len() {
888 stream.extend_from_slice(&self.hits[k].to_bytestream());
889 }
890 if self.version == ProtocolVersion::V2
893 || self.version == ProtocolVersion::V3 {
894 stream.push(self.rb_events.len() as u8);
895 for rbev in &self.rb_events {
896 stream.extend_from_slice(&rbev.to_bytestream());
897 }
898 }
899 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
900 stream
901 }
902
903 fn from_bytestream(stream : &Vec<u8>,
904 pos : &mut usize)
905 -> Result<Self, SerializationError>{
906 let mut event = Self::new();
907 let head = parse_u16(stream, pos);
908 if head != Self::HEAD {
909 error!("Decoding of HEAD failed! Got {} instead!", head);
910 return Err(SerializationError::HeadInvalid);
911 }
912
913 let status_version_u8 = parse_u8(stream, pos);
914 let status = EventStatus::from(status_version_u8 & 0x3f);
915 let version = ProtocolVersion::from(status_version_u8 & 0xc0);
916 event.status = status;
917 event.version = version;
918 event.trigger_sources = parse_u16(stream, pos);
919 event.n_trigger_paddles = parse_u8(stream, pos);
920 event.event_id = parse_u32(stream, pos);
921 if event.version == ProtocolVersion::V1
922 || event.version == ProtocolVersion::V3 {
923 event.n_hits_umb = parse_u8(stream, pos);
924 event.n_hits_cbe = parse_u8(stream, pos);
925 event.n_hits_cor = parse_u8(stream, pos);
926 event.tot_edep_umb = parse_f32(stream, pos);
927 event.tot_edep_cbe = parse_f32(stream, pos);
928 event.tot_edep_cor = parse_f32(stream, pos);
929 }
930 event.quality = EventQuality::from(parse_u8(stream, pos));
931 event.timestamp32 = parse_u32(stream, pos);
932 event.timestamp16 = parse_u16(stream, pos);
933 event.run_id = parse_u16(stream, pos);
934 event.drs_dead_lost_hits = parse_u16(stream, pos);
935 event.dsi_j_mask = parse_u32(stream, pos);
936 let n_channel_masks = parse_u8(stream, pos);
937 for _ in 0..n_channel_masks {
938 event.channel_mask.push(parse_u16(stream, pos));
939 }
940 event.mtb_link_mask = parse_u64(stream, pos);
941 let nhits = parse_u16(stream, pos);
942 if nhits > 160 {
944 error!("There are an abnormous amount of hits in this event!");
945 return Err(SerializationError::StreamTooLong);
946 }
947 for _ in 0..nhits {
948 event.hits.push(TofHit::from_bytestream(stream, pos)?);
949 }
950 if event.version == ProtocolVersion::V2
951 || event.version == ProtocolVersion::V3 {
952 let n_rb_events = parse_u8(stream, pos);
953 if n_rb_events > 0 {
954 for _ in 0..n_rb_events {
955 event.rb_events.push(RBEvent::from_bytestream(stream, pos)?);
956 }
957 }
958 }
959
960 let tail = parse_u16(stream, pos);
961 if tail != Self::TAIL {
962 error!("Decoding of TAIL failed for version {}! Got {} instead!", version, tail);
963 return Err(SerializationError::TailInvalid);
964 }
965 Ok(event)
966 }
967
968 fn from_bytestream_alt(stream : &Vec<u8>,
974 pos : &mut usize)
975 -> Result<Self, SerializationError> {
976 let head = parse_u16(stream, pos);
977 if head != TofEvent::HEAD {
978 return Err(SerializationError::HeadInvalid);
979 }
980 let mut te = Self::new();
981 let _compression_level = parse_u8(stream, pos);
983
984 te.quality = EventQuality::from(parse_u8(stream, pos));
985 *pos += 2; te.run_id = parse_u32(stream, pos) as u16;
991 *pos += 43 - 6;*pos += 2; let event_status = parse_u8 (stream, pos);
996 te.status = EventStatus::from(event_status);
997 if te.has_any_mangling() {
998 te.status = EventStatus::AnyDataMangling;
999 }
1000 te.event_id = parse_u32(stream, pos);
1001 let mtb_timestamp = parse_u32(stream, pos);
1002 let tiu_timestamp = parse_u32(stream, pos);
1003 let tiu_gps32 = parse_u32(stream, pos);
1004 let _tiu_gps16 = parse_u16(stream,pos);
1005 let _crc = parse_u32(stream, pos);
1006 let mt_timestamp = (mt_event_get_timestamp_abs48(mtb_timestamp, tiu_gps32, tiu_timestamp ) as f64/1000.0).floor() as u64;
1007 te.timestamp32 = (mt_timestamp & 0x00000000ffffffff ) as u32;
1008 te.timestamp16 = ((mt_timestamp & 0x0000ffff00000000 ) >> 32) as u16;
1009 te.trigger_sources = parse_u16(stream, pos);
1010 te.dsi_j_mask = parse_u32(stream, pos);
1011 let n_channel_masks = parse_u8(stream, pos);
1012 for _ in 0..n_channel_masks {
1013 te.channel_mask.push(parse_u16(stream, pos));
1014 }
1015
1016 te.mtb_link_mask = parse_u64(stream, pos);
1017 let mt_event_tail = parse_u16(stream, pos);
1018 if mt_event_tail != Self::TAIL {
1019 error!("Parsed TAIL from MT event is incorrect! Got {} instead of {} at pos {}", mt_event_tail, Self::TAIL, pos);
1021 }
1022 let v_sizes = Self::decode_depr_tofevent_size_header(&parse_u32(stream, pos));
1024 for _ in 0..v_sizes.0 {
1026 let next_rb_event = RBEvent::from_bytestream(stream, pos)?;
1029 te.rb_events.push(next_rb_event);
1031 }
1032 for rbev in &te.rb_events {
1038 for h in &rbev.hits {
1039 te.hits.push(*h);
1040 }
1041 }
1042 let tail = parse_u16(stream, pos);
1043 if tail != Self::TAIL {
1044 error!("Decoding of TAIL failed! Got {} instead!", tail);
1045 return Err(SerializationError::TailInvalid);
1046 }
1047 return Ok(te);
1048 }
1049}
1050
1051impl Default for TofEvent {
1052 fn default() -> Self {
1053 Self::new()
1054 }
1055}
1056
1057impl fmt::Display for TofEvent {
1058 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1059 let mut repr = format!("<TofEvent (version {})", self.version);
1060 repr += &(format!("\n EventID : {}", self.event_id));
1061 repr += &(format!("\n RunID : {}", self.run_id));
1062 repr += &(format!("\n EventStatus : {}", self.status));
1063 repr += &(format!("\n TriggerSources : {:?}", self.get_trigger_sources()));
1064 repr += &(format!("\n NTrigPaddles : {}", self.n_trigger_paddles));
1065 repr += &(format!("\n DRS dead hits : {}", self.drs_dead_lost_hits));
1066 repr += &(format!("\n timestamp32 : {}", self.timestamp32));
1067 repr += &(format!("\n timestamp16 : {}", self.timestamp16));
1068 repr += &(format!("\n |-> timestamp48 : {}", self.get_timestamp48()));
1069 if self.version == ProtocolVersion::V1 {
1077 repr += "\n ---- V1 variables ----";
1078 repr += &(format!("\n n_hits_umb : {}", self.n_hits_umb ));
1079 repr += &(format!("\n n_hits_cbe : {}", self.n_hits_cbe ));
1080 repr += &(format!("\n n_hits_cor : {}", self.n_hits_cor ));
1081 repr += &(format!("\n tot_edep_umb : {}", self.tot_edep_umb));
1082 repr += &(format!("\n tot_edep_cbe : {}", self.tot_edep_cbe));
1083 repr += &(format!("\n tot_edep_cor : {}", self.tot_edep_cor));
1084 }
1085 repr += &(format!("\n ** ** TRIGGER HITS (DSI/J/CH) [{} LTBS] ** **", self.dsi_j_mask.count_ones()));
1086 for k in self.get_trigger_hits() {
1087 repr += &(format!("\n => {}/{}/({},{}) ({}) ", k.0, k.1, k.2.0, k.2.1, k.3));
1088 }
1089 repr += "\n ** ** MTB LINK IDs ** **";
1090 let mut mtblink_str = String::from("\n => ");
1091 for k in self.get_rb_link_ids() {
1092 mtblink_str += &(format!("{} ", k))
1093 }
1094 repr += &mtblink_str;
1095 repr += &(format!("\n == Trigger hits {}, expected RBEvents {}",
1096 self.get_trigger_hits().len(),
1097 self.get_rb_link_ids().len()));
1098 repr += &String::from("\n ** ** ** HITS ** ** **");
1099 for h in &self.hits {
1100 repr += &(format!("\n {}", h));
1101 }
1102 if self.rb_events.len() > 0 {
1103 repr += &format!("\n -- has {} RBEvents with waveforms!", self.rb_events.len());
1104 repr += "\n -- -- boards: ";
1105 for b in &self.rb_events {
1106 repr += &format!("{} ", b.header.rb_id);
1107 }
1108 }
1109 repr += ">";
1110 write!(f, "{}", repr)
1111 }
1112}
1113
1114#[cfg(feature="random")]
1115impl FromRandom for TofEvent {
1116
1117 fn from_random() -> Self {
1118 let mut event = Self::new();
1119 let mut rng = rand::rng();
1120 let status = EventStatus::from_random();
1121 let version = ProtocolVersion::from_random();
1122 if version == ProtocolVersion::V1 {
1123 event.n_hits_umb = rng.random::<u8>();
1124 event.n_hits_cbe = rng.random::<u8>();
1125 event.n_hits_cor = rng.random::<u8>();
1126 event.tot_edep_umb = rng.random::<f32>();
1127 event.tot_edep_cbe = rng.random::<f32>();
1128 event.tot_edep_cor = rng.random::<f32>();
1129 event.quality = EventQuality::from_random();
1130 }
1131 event.status = status;
1132 event.version = version;
1133 event.trigger_sources = rng.random::<u16>();
1135 event.n_trigger_paddles = rng.random::<u8>();
1136 event.event_id = rng.random::<u32>();
1137 event.timestamp32 = rng.random::<u32>();
1138 event.timestamp16 = rng.random::<u16>();
1139 event.drs_dead_lost_hits = rng.random::<u16>();
1140 event.dsi_j_mask = rng.random::<u32>();
1141 let n_channel_masks = rng.random::<u8>();
1142 for _ in 0..n_channel_masks {
1143 event.channel_mask.push(rng.random::<u16>());
1144 }
1145 event.mtb_link_mask = rng.random::<u64>();
1146 let nhits: u16 = rng.random_range(0..5);
1148 for _ in 0..nhits {
1149 event.hits.push(TofHit::from_random());
1150 }
1151 if event.version == ProtocolVersion::V2 {
1152 let n_rb_events = rng.random_range(0..4);
1153 for _ in 0..n_rb_events {
1154 event.rb_events.push(RBEvent::from_random());
1155 }
1156 }
1157 event
1158 }
1159}
1160
1161#[cfg(feature="pybindings")]
1164#[pymethods]
1165impl TofEvent {
1166
1167 #[pyo3(name="strip_rbevents")]
1168 fn strip_rbevents_py(&mut self) {
1169 self.strip_rbevents()
1170 }
1171
1172 #[pyo3(name="calc_gcu_variables")]
1175 fn calc_gcu_variables_py(&mut self) {
1176 self.calc_gcu_variables()
1177 }
1178
1179 fn copy(&self) -> Self {
1181 self.clone()
1182 }
1183
1184 #[pyo3(name="set_timing_offsets")]
1185 pub fn set_timing_offsets_py(&mut self, timing_offsets : HashMap<u8, f32>) {
1186 self.set_timing_offsets(&timing_offsets);
1187 }
1188
1189 #[pyo3(name="normalize_hit_times")]
1190 pub fn normalize_hit_times_py(&mut self) {
1191 self.normalize_hit_times();
1192 }
1193
1194 #[pyo3(name="lightspeed_cleaning")]
1202 pub fn lightspeed_cleaning_py(&mut self, t_err : f32) -> (Vec<u16>, Vec<f32>) {
1203 let mut pids = Vec::<u16>::new();
1206 let (pids_rm, twindows) = self.lightspeed_cleaning(t_err);
1207 for pid in pids_rm {
1208 pids.push(pid as u16);
1209 }
1210 (pids, twindows)
1211 }
1212
1213 #[getter]
1215 fn get_run_id(&self) -> u16 {
1216 self.run_id
1217 }
1218
1219 #[pyo3(name="remove_non_causal_hits")]
1224 fn remove_non_causal_hits_py(&mut self) -> Vec<u16> {
1225 let mut pids = Vec::<u16>::new();
1228 for pid in self.remove_non_causal_hits() {
1229 pids.push(pid as u16);
1230 }
1231 pids
1232 }
1233
1234 #[getter]
1235 fn pointcloud(&self) -> Option<Vec<(f32,f32,f32,f32,f32)>> {
1236 self.get_pointcloud()
1237 }
1238
1239 #[getter]
1240 #[pyo3(name="has_any_mangling")]
1241 fn has_any_mangling_py(&self) -> bool {
1242 self.has_any_mangling()
1243 }
1244
1245 #[getter]
1246 fn get_event_id(&self) -> u32 {
1247 self.event_id
1248 }
1249
1250 #[getter]
1251 fn get_event_status(&self) -> EventStatus {
1252 self.status
1253 }
1254
1255 #[pyo3(name="get_missing_paddles_hg")]
1258 fn get_missing_paddles_hg_py(&self, mapping : DsiJChPidMapping) -> Vec<u8> {
1259 self.get_missing_paddles_hg(&mapping)
1260 }
1261
1262 #[pyo3(name="get_triggered_paddles")]
1264 fn get_triggered_paddles_py(&self, mapping : DsiJChPidMapping) -> Vec<u8> {
1265 self.get_triggered_paddles(&mapping)
1266 }
1267
1268 #[getter]
1271 fn lost_hits(&self) -> u16 {
1272 self.drs_dead_lost_hits
1273 }
1274
1275 #[getter]
1278 fn rb_link_ids(&self) -> Vec<u32> {
1279 self.get_rb_link_ids().into_iter().map(|byte| byte as u32).collect()
1280 }
1281
1282 #[getter]
1284 fn get_rb_events(&self) -> Vec<RBEvent> {
1285 self.rb_events.clone()
1286 }
1287
1288 #[getter]
1290 pub fn trigger_hits(&self) -> PyResult<Vec<(u8, u8, (u8, u8), LTBThreshold)>> {
1291 Ok(self.get_trigger_hits())
1292 }
1293
1294 #[getter]
1297 pub fn trigger_sources(&self) -> Vec<TriggerType> {
1298 self.get_trigger_sources()
1299 }
1300
1301 #[pyo3(name="move_hits")]
1302 pub fn move_hits_py(&mut self) {
1303 self.move_hits()
1304 }
1305
1306 #[getter]
1307 #[pyo3(name="hits")]
1308 pub fn hits_py<'_py>(&self) -> Vec<TofHit> {
1309 self.hits.clone()
1313 }
1314
1315 #[getter]
1316 #[pyo3(name="hitmap")]
1317 pub fn hitmap<'_py>(&self) -> HashMap<u8,TofHit> {
1318 let mut hitmap = HashMap::<u8, TofHit>::new();
1322 for h in &self.hits {
1323 hitmap.insert(h.paddle_id, *h);
1324 }
1325 hitmap
1326 }
1327
1328 #[getter]
1333 #[pyo3(name="edep_umb")]
1334 pub fn get_edep_umbrella_py(&self) -> f32 {
1335 self.get_edep_umbrella()
1336 }
1337
1338 #[getter]
1343 #[pyo3(name="edep_cbe")]
1344 pub fn get_edep_cube_py(&self) -> f32 {
1345 self.get_edep_cube()
1346 }
1347
1348 #[getter]
1353 #[pyo3(name="edep_cor")]
1354 pub fn get_edep_cortina_py(&self) -> f32 {
1355 self.get_edep_cortina()
1356 }
1357
1358 #[getter]
1363 #[pyo3(name="edep")]
1364 pub fn get_edep_py(&self) -> f32 {
1365 self.get_edep()
1366 }
1367
1368 #[getter]
1369 #[pyo3(name="nhits")]
1370 pub fn nhits_py(&self) -> usize {
1371 self.get_nhits()
1372 }
1373
1374 #[getter]
1375 #[pyo3(name="nhits_umb")]
1376 pub fn nhits_umb_py(&self) -> usize {
1377 self.get_nhits_umb()
1378 }
1379
1380 #[getter]
1381 #[pyo3(name="nhits_cbe")]
1382 fn get_nhits_cbe_py(&self) -> usize {
1383 self.get_nhits_cbe()
1384 }
1385
1386 #[getter]
1387 #[pyo3(name="nhits_cor")]
1388 fn get_nhits_cor_py(&self) -> usize {
1389 self.get_nhits_cor()
1390 }
1391
1392 #[getter]
1393 fn get_timestamp16(&self) -> u16 {
1394 self.timestamp16
1395 }
1396
1397 #[getter]
1398 fn get_timestamp32(&self) -> u32 {
1399 self.timestamp32
1400 }
1401
1402 #[getter]
1403 fn timestamp48(&self) -> u64 {
1404 self.get_timestamp48()
1405 }
1406
1407 #[getter]
1408 fn get_status(&self) -> EventStatus {
1409 self.status
1410 }
1411
1412 #[getter]
1413 #[pyo3(name="waveforms")]
1414 fn get_waveforms_py(&self) -> Vec<RBWaveform> {
1415 self.get_waveforms()
1416 }
1417
1418 #[staticmethod]
1419 #[pyo3(name = "set_packed_status_version")]
1420 fn set_packed_status_version_py(pack : &mut TofPacket, version : ProtocolVersion)
1421 -> PyResult<()> {
1422 match Self::set_packed_status_version(pack, version) {
1423 Err(err) => {
1424 let err_mesg = format!("Unable to set status version! {}", err);
1425 return Err(PyValueError::new_err(err_mesg));
1426 }
1427 Ok(_) => {
1428 return Ok(());
1429 }
1430 }
1431 }
1432
1433 #[staticmethod]
1434 #[pyo3(name = "strip_packed_rbevents_for_pv3")]
1435 fn strip_packed_rbevents_for_pv3_py(pack : &mut TofPacket)
1436 -> PyResult<()> {
1437 match Self::strip_packed_rbevents_for_pv3(pack) {
1438 Err(err) => {
1439 let err_msg = format!("Unable to strip packed rbevents{}", err);
1440 return Err(PyValueError::new_err(err_msg));
1441 }
1442 Ok(_) => {
1443 return Ok(());
1444 }
1445 }
1446 }
1447
1448 #[cfg(feature="database")]
1449 #[staticmethod]
1450 fn unpack(pack : &TofPacket) -> PyResult<Self> {
1451 if pack.packet_type != Self::TOF_PACKET_TYPE {
1452 let err_msg = format!("This is a packet of type {}, but we need type {}", pack.packet_type, Self::TOF_PACKET_TYPE);
1453 return Err(PyValueError::new_err(err_msg));
1454 }
1455 let mut pos = 0;
1456 let mut ev = Self::from_bytestream(&pack.payload,&mut pos)?;
1457 ev.set_paddles(&pack.tof_paddles);
1458 Ok(ev)
1459 }
1460}
1461
1462#[cfg(feature="pybindings")]
1463pythonize_packable!(TofEvent);
1464
1465#[test]
1468#[cfg(feature="random")]
1469fn packable_tofeventv0() {
1470 for _ in 0..500 {
1471 let mut data = TofEvent::from_random();
1472 if data.version != ProtocolVersion::Unknown {
1473 continue;
1474 }
1475 let mut test : TofEvent = data.pack().unpack().unwrap();
1476 let fix_time = Instant::now();
1483 test.creation_time = fix_time;
1484 data.creation_time = fix_time;
1485 for k in &mut data.rb_events {
1486 k.creation_time = None;
1487 }
1488 for k in &mut test.rb_events {
1489 k.creation_time = None;
1490 }
1491 for h in &mut test.hits {
1492 h.paddle_len = 0.0;
1493 h.coax_cable_time = 0.0;
1494 h.hart_cable_time = 0.0;
1495 h.x = 0.0;
1496 h.y = 0.0;
1497 h.z = 0.0;
1498 h.event_t0 = 0.0;
1499 }
1500 assert_eq!(data, test);
1501 }
1502}
1503
1504#[test]
1505#[cfg(feature="random")]
1506fn packable_tofeventv1() {
1507 for _ in 0..500 {
1508 let mut data = TofEvent::from_random();
1509 if data.version != ProtocolVersion::V1 {
1510 continue;
1511 }
1512 let mut test : TofEvent = data.pack().unpack().unwrap();
1513 let fix_time = Instant::now();
1518 test.creation_time = fix_time;
1519 data.creation_time = fix_time;
1520 for k in &mut data.rb_events {
1521 k.creation_time = None;
1522 }
1523 for k in &mut test.rb_events {
1524 k.creation_time = None;
1525 }
1526 for h in &mut test.hits {
1527 h.paddle_len = 0.0;
1528 h.coax_cable_time = 0.0;
1529 h.hart_cable_time = 0.0;
1530 h.x = 0.0;
1531 h.y = 0.0;
1532 h.z = 0.0;
1533 h.event_t0 = 0.0;
1534 }
1535 assert_eq!(data, test);
1536 }
1537}
1538
1539#[test]
1540#[cfg(feature="random")]
1541fn packable_tofeventv2() {
1542 for _ in 0..500 {
1543 let mut data = TofEvent::from_random();
1544 if data.version != ProtocolVersion::V2 {
1545 continue;
1546 }
1547 let mut test : TofEvent = data.pack().unpack().unwrap();
1548 let fix_time = Instant::now();
1553 test.creation_time = fix_time;
1554 data.creation_time = fix_time;
1555 for k in &mut data.rb_events {
1556 k.creation_time = None;
1557 }
1558 for k in &mut test.rb_events {
1559 k.creation_time = None;
1560 }
1561 for h in &mut test.hits {
1562 h.paddle_len = 0.0;
1563 h.coax_cable_time = 0.0;
1564 h.hart_cable_time = 0.0;
1565 h.x = 0.0;
1566 h.y = 0.0;
1567 h.z = 0.0;
1568 h.event_t0 = 0.0;
1569 }
1570 assert_eq!(data, test);
1571 }
1572}
1573
1574#[test]
1575#[cfg(feature="random")]
1576fn packable_tofeventv3() {
1577 for _ in 0..500 {
1578 let mut data = TofEvent::from_random();
1579 if data.version != ProtocolVersion::V3 {
1580 continue;
1581 }
1582 let mut test : TofEvent = data.pack().unpack().unwrap();
1583 let fix_time = Instant::now();
1588 test.creation_time = fix_time;
1589 data.creation_time = fix_time;
1590 for h in &mut test.hits {
1591 h.paddle_len = 0.0;
1592 h.coax_cable_time = 0.0;
1593 h.hart_cable_time = 0.0;
1594 h.x = 0.0;
1595 h.y = 0.0;
1596 h.z = 0.0;
1597 h.event_t0 = 0.0;
1598 }
1599 assert_eq!(data, test);
1600 }
1601}
1602
1603#[test]
1604#[cfg(feature="random")]
1605fn tofevent_move_hits() {
1606 let mut event = TofEvent::from_random();
1607 let mut n_hits_exp = 0usize;
1608 for rb in &event.rb_events {
1609 n_hits_exp += rb.hits.len();
1610 }
1611 event.hits.clear();
1612 event.move_hits();
1613 for rb in &event.rb_events {
1614 assert_eq!(rb.hits.len(),0);
1615 }
1616 assert_eq!(n_hits_exp, event.hits.len());
1617
1618}
1619
1620#[test]
1621#[cfg(feature="random")]
1622fn tofevent_striprbevents() {
1623 let mut event = TofEvent::from_random();
1624 let mut n_hits_exp = 0usize;
1625 for rb in &event.rb_events {
1626 n_hits_exp += rb.hits.len();
1627 }
1628 event.hits.clear();
1629 event.strip_rbevents();
1630 assert_eq!(event.rb_events.len(),0);
1631 assert_eq!(n_hits_exp, event.hits.len());
1632}
1633
1634