1use std::time::Instant;
5use std::fmt;
6use std::f32::consts::PI;
7use std::cmp::Ordering;
8
9cfg_if::cfg_if! {
10 if #[cfg(feature = "random")] {
11 use crate::FromRandom;
12 use rand::Rng;
13 }
14}
15
16use crate::serialization::{
17 Serialization,
18 Packable,
19 parse_u8,
20 parse_u16,
21 parse_u32,
22 parse_u64,
23 parse_f32,
24 search_for_u16
25};
26
27use crate::packets::{
28 TofPacket,
29 PacketType
30};
31
32use crate::errors::SerializationError;
33
34use crate::events::{
35 MasterTriggerEvent,
36 RBEvent,
37 TofHit,
38 RBWaveform,
39 TriggerType,
41 EventStatus,
42 transcode_trigger_sources,
43};
44
45use crate::events::master_trigger::{
46 LTBThreshold,
47 LTB_CHANNELS
48};
49
50use crate::ProtocolVersion;
51
52cfg_if::cfg_if! {
53 if #[cfg(feature = "database")] {
54 use crate::database::DsiJChPidMapping;
55 use crate::database::Paddle;
56 use std::collections::HashMap;
57 }
58}
59
60#[derive(Debug, Copy, Clone, PartialEq, serde::Deserialize, serde::Serialize)]
65#[repr(u8)]
66pub enum CompressionLevel {
67 Unknown = 0u8,
68 None = 10u8,
69}
70
71impl fmt::Display for CompressionLevel {
72 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73 let r = serde_json::to_string(self).unwrap_or(
74 String::from("Error: cannot unwrap this CompressionLevel"));
75 write!(f, "<CompressionLevel: {}>", r)
76 }
77}
78
79impl From<u8> for CompressionLevel {
80 fn from(value: u8) -> Self {
81 match value {
82 0u8 => CompressionLevel::Unknown,
83 10u8 => CompressionLevel::None,
84 _ => CompressionLevel::Unknown
85 }
86 }
87}
88
89#[derive(Debug, Copy, Clone, PartialEq, serde::Deserialize, serde::Serialize)]
90#[repr(u8)]
91pub enum EventQuality {
92 Unknown = 0u8,
93 Silver = 10u8,
94 Gold = 20u8,
95 Diamond = 30u8,
96 FourLeafClover = 40u8,
97}
98
99impl fmt::Display for EventQuality {
100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 let r = serde_json::to_string(self).unwrap_or(
102 String::from("Error: cannot unwrap this EventQuality"));
103 write!(f, "<EventQuality: {}>", r)
104 }
105}
106
107impl From<u8> for EventQuality {
108 fn from(value: u8) -> Self {
109 match value {
110 0u8 => EventQuality::Unknown,
111 10u8 => EventQuality::Silver,
112 20u8 => EventQuality::Gold,
113 30u8 => EventQuality::Diamond,
114 40u8 => EventQuality::FourLeafClover,
115 _ => EventQuality::Unknown
116 }
117 }
118}
119
120#[derive(Debug, Clone)]
123pub struct TofEvent {
124
125 pub compression_level : CompressionLevel,
126 pub quality : EventQuality,
127 pub header : TofEventHeader,
128 pub mt_event : MasterTriggerEvent,
129 pub rb_events : Vec::<RBEvent>,
130 pub creation_time : Instant,
134 pub write_to_disk : bool,
135 pub paddles_set : bool
136}
137
138impl fmt::Display for TofEvent {
139 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140 write!(f,
141"<TofEvent:
142 quality : {}
143 {}
144 {}
145 n RBEvents : {}>"
146 ,self.quality,
147 self.header,
148 self.mt_event,
149 self.rb_events.len())
150 }
151}
152
153impl Default for TofEvent {
154 fn default() -> Self {
155 Self::new()
156 }
157}
158
159impl TofEvent {
160
161 pub fn new() -> Self {
162 let creation_time = Instant::now();
163 Self {
164 compression_level : CompressionLevel::Unknown,
165 quality : EventQuality::Unknown,
166 header : TofEventHeader::new(),
167 mt_event : MasterTriggerEvent::new(),
168 rb_events : Vec::<RBEvent>::new(),
169 creation_time : creation_time,
171 write_to_disk : true,
172 paddles_set : false
173 }
174 }
175
176
177 #[cfg(feature="database")]
178 pub fn set_paddles(&mut self, paddles : &HashMap<u8, Paddle>) {
179 let mut nerror = 0u8;
180 for ev in &mut self.rb_events {
181 for h in &mut ev.hits {
182 match paddles.get(&h.paddle_id) {
183 None => {
184 error!("Got paddle id {} which is not in given map!", h.paddle_id);
185 nerror += 1;
186 continue;
187 }
188 Some(pdl) => {
189 h.set_paddle(pdl);
190 }
191 }
192 }
193 }
194 if nerror == 0 {
195 self.paddles_set = true;
196 }
197 }
198
199 pub fn get_pointcloud(&self) -> Option<Vec<(f32,f32,f32,f32,f32)>> {
204 let mut pc = Vec::<(f32,f32,f32,f32,f32)>::new();
205 if !self.paddles_set {
206 error!("Before getting the pointcloud, paddle information needs to be set for this event. Call TofEventSummary;:set_paddle");
207 return None;
208 }
209 for rbev in &self.rb_events {
210 for h in &rbev.hits {
211 let result = (h.x, h.y, h.z, h.get_t0(), h.get_edep());
212 pc.push(result);
213 }
214 }
215 Some(pc)
216 }
217
218 #[cfg(feature="database")]
227 pub fn get_missing_paddles_hg(&self, pid_map : &DsiJChPidMapping) -> Vec<u8> {
228 let mut missing = Vec::<u8>::new();
229 for th in self.mt_event.get_trigger_hits() {
230 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
231 let mut found = false;
232 for h in self.get_hits() {
233 if h.paddle_id == pid {
234 found = true;
235 break
236 }
237 }
238 if !found {
239 missing.push(pid);
240 }
241 }
242 missing
243 }
244
245 #[cfg(feature="database")]
254 pub fn get_extra_paddles_hg(&self, pid_map : &DsiJChPidMapping) -> Vec<u8> {
255 let mut extra = Vec::<u8>::new();
256 let mut trigger_pids = Vec::<u8>::new();
257 for th in self.mt_event.get_trigger_hits() {
258 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
259 trigger_pids.push(pid);
260 }
261 for h in self.get_hits() {
262 if !trigger_pids.contains(&h.paddle_id) {
263 extra.push(h.paddle_id);
264 }
265 }
266 extra
267 }
268
269 #[cfg(feature="database")]
275 pub fn get_missing_paddles_wf(&self, pid_map : &DsiJChPidMapping) -> Vec<u8> {
276 let mut missing = Vec::<u8>::new();
277 let wf_pids = self.get_waveform_pids();
278 for th in self.mt_event.get_trigger_hits() {
279 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
280 let mut found = false;
282 for wf_pid in &wf_pids {
283 if *wf_pid == pid {
284 found = true;
285 break
286 }
287 }
288 if !found {
289 missing.push(pid);
290 }
291 }
292 missing
293 }
294
295 #[cfg(feature="database")]
299 pub fn get_triggered_paddles(&self, pid_map : DsiJChPidMapping) -> Vec<u8> {
300 let mut paddles = Vec::<u8>::with_capacity(3);
301 for th in self.mt_event.get_trigger_hits() {
302 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
303 paddles.push(pid);
304 }
305 paddles
306 }
307
308
309 pub fn extract_event_id_from_stream(stream : &Vec<u8>)
310 -> Result<u32, SerializationError> {
311 let evid = parse_u32(stream, &mut 12);
313 Ok(evid)
314 }
315
316 pub fn age(&self) -> u64 {
317 self.creation_time.elapsed().as_secs()
318 }
319
320 pub fn is_complete(&self) -> bool {
323 self.mt_event.get_rb_link_ids().len() == self.rb_events.len()
324 }
325
326 pub fn is_complete_masked(&self, mtb_link_ids_excluded : &Vec::<u8>) -> bool {
329 let mut expected_events = 0usize;
330 for k in &self.mt_event.get_rb_link_ids() {
331 if !mtb_link_ids_excluded.contains(k) {
332 expected_events += 1
333 }
334 }
335 self.rb_events.len() == expected_events
336 }
337
338 pub fn construct_sizes_header(&self) -> u32 {
343 let rb_event_len = self.rb_events.len() as u32;
344 let miss_len = 0u32;
347 let mut mask = 0u32;
348 mask = mask | rb_event_len;
349 mask = mask | (miss_len << 8);
350 mask
351 }
352
353 pub fn decode_size_header(mask : &u32)
354 -> (usize, usize) {
355 let rb_event_len = (mask & 0xFF) as usize;
356 let miss_len = ((mask & 0xFF00) >> 8) as usize;
357 (rb_event_len, miss_len)
358 }
359
360 pub fn get_combined_vector_sizes(&self) -> usize {
361 self.rb_events.len()
362 }
364
365 pub fn get_rbwaveforms(&self) -> Vec<RBWaveform> {
367 let mut wf = Vec::<RBWaveform>::new();
368 for ev in &self.rb_events {
369 wf.extend_from_slice(&ev.get_rbwaveforms());
370 }
371 wf
372 }
373
374 pub fn get_waveforms(&self) -> Vec<RBWaveform> {
379 let mut wfs = Vec::<RBWaveform>::new();
380 for ev in &self.rb_events {
381 for wf in &ev.get_rbwaveforms() {
382 wfs.push(wf.clone());
383 }
384 }
385 wfs
386 }
387
388 pub fn get_waveform_pids(&self) -> Vec<u8> {
390 let mut pids = Vec::<u8>::new();
391 for ev in &self.rb_events {
392 for wf in &ev.get_rbwaveforms() {
393 pids.push(wf.paddle_id)
394 }
395 }
396 pids
397 }
398
399 pub fn get_hits(&self) -> Vec<TofHit> {
401 let mut hits = Vec::<TofHit>::new();
402 for ev in &self.rb_events {
403 for h in &ev.hits {
404 hits.push(*h);
405 }
406 }
407 hits
408 }
409
410 pub fn has_any_mangling(&self) -> bool {
413 for rbev in &self.rb_events {
414 if rbev.status == EventStatus::CellAndChnSyncErrors
415 || rbev.status == EventStatus::CellSyncErrors
416 || rbev.status == EventStatus::ChnSyncErrors {
417 return true;
418 }
419 }
420 false
421 }
422
423 pub fn get_summary(&self) -> TofEventSummary {
424 let mut summary = TofEventSummary::new();
425 summary.status = self.mt_event.event_status;
427 if self.has_any_mangling() {
428 summary.status = EventStatus::AnyDataMangling;
429 }
430 summary.trigger_sources = self.mt_event.trigger_source;
432 summary.n_trigger_paddles = self.mt_event.get_trigger_hits().len() as u8;
433 summary.event_id = self.header.event_id;
434 summary.run_id = (self.header.run_id & 0x0000ffff) as u16;
436 summary.version = ProtocolVersion::V1;
439 let mt_timestamp = (self.mt_event.get_timestamp_abs48() as f64/1000.0).floor() as u64;
440 summary.timestamp32 = (mt_timestamp & 0x00000000ffffffff ) as u32;
441 summary.timestamp16 = ((mt_timestamp & 0x0000ffff00000000 ) >> 32) as u16;
442 summary.dsi_j_mask = self.mt_event.dsi_j_mask;
445 summary.channel_mask = self.mt_event.channel_mask.clone();
446 summary.mtb_link_mask = self.mt_event.mtb_link_mask;
447 summary.drs_dead_lost_hits = self.get_lost_hits();
448 summary.hits = Vec::<TofHit>::new();
449 for ev in &self.rb_events {
450 for hit in &ev.hits {
451 let h = hit.clone();
452 if summary.version == ProtocolVersion::V1 {
453 if h.paddle_id <= 60 {
454 summary.n_hits_cbe += 1;
455 summary.tot_edep_cbe += h.get_edep();
456 }
457 else if h.paddle_id <= 108 && h.paddle_id > 60 {
458 summary.n_hits_umb += 1;
459 summary.tot_edep_umb += h.get_edep();
460 }
461 else {
462 summary.n_hits_cor += 1;
463 summary.tot_edep_cor += h.get_edep();
464 }
465 }
466 summary.hits.push(h);
467 }
468 }
469 #[cfg(feature="database")]
470 summary.normalize_hit_times();
471 summary
472 }
473
474 pub fn get_lost_hits(&self) -> u16 {
477 let mut lost_hits = 0u16;
478 for rbev in &self.rb_events {
479 if rbev.header.drs_lost_trigger() {
480 let mut nhits = rbev.header.get_nchan() as u16;
481 if nhits > 0 {
482 nhits -= 1;
483 }
484 lost_hits += nhits;
485 }
486 }
487 lost_hits
488 }
489
490 pub fn get_nhits_umb(&self) -> usize {
491 let mut nhit = 0;
492 for h in &self.get_hits() {
493 if h.paddle_id > 60 && h.paddle_id < 109 {
494 nhit += 1;
495 }
496 }
497 nhit
498 }
499
500 pub fn get_nhits_cbe(&self) -> usize {
501 let mut nhit = 0;
502 for h in &self.get_hits() {
503 if h.paddle_id < 61 {
504 nhit += 1;
505 }
506 }
507 nhit
508 }
509
510 pub fn get_nhits_cor(&self) -> usize {
511 let mut nhit = 0;
512 for h in &self.get_hits() {
513 if h.paddle_id > 108 {
514 nhit += 1;
515 }
516 }
517 nhit
518 }
519
520 pub fn get_nhits(&self) -> usize {
521 self.get_hits().len()
522 }
523}
524
525impl Packable for TofEvent {
526 const PACKET_TYPE : PacketType = PacketType::TofEvent;
527}
528
529impl Serialization for TofEvent {
530
531 const HEAD : u16 = 43690; const TAIL : u16 = 21845; fn to_bytestream(&self) -> Vec<u8> {
536 let mut stream = Vec::<u8>::new();
537 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
538 stream.extend_from_slice(&(self.compression_level as u8).to_le_bytes());
539 stream.extend_from_slice(&(self.quality as u8).to_le_bytes());
540 stream.extend_from_slice(&self.header.to_bytestream());
541 stream.extend_from_slice(&self.mt_event.to_bytestream());
542 let sizes_header = self.construct_sizes_header();
543 stream.extend_from_slice(&sizes_header.to_le_bytes());
544 for k in 0..self.rb_events.len() {
545 stream.extend_from_slice(&self.rb_events[k].to_bytestream());
546 }
547 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
551 stream
552 }
553
554 fn from_bytestream(stream : &Vec<u8>,
555 pos : &mut usize)
556 -> Result<Self, SerializationError>{
557 let mut event = Self::new();
558 let head_pos = search_for_u16(Self::HEAD, stream, *pos)?;
559 *pos = head_pos + 2;
560 event.compression_level = CompressionLevel::try_from(parse_u8(stream, pos)).unwrap();
561 event.quality = EventQuality::try_from(parse_u8(stream, pos)).unwrap();
562 event.header = TofEventHeader::from_bytestream(stream, pos)?;
563 event.mt_event = MasterTriggerEvent::from_bytestream(stream, pos)?;
564 let v_sizes = Self::decode_size_header(&parse_u32(stream, pos));
565 for k in 0..v_sizes.0 {
566 match RBEvent::from_bytestream(stream, pos) {
567 Err(err) => error!("Expected RBEvent {} of {}, but got serialization error {}!", k, v_sizes.0, err),
568 Ok(ev) => {
569 event.rb_events.push(ev);
570 }
571 }
572 }
573 let tail = parse_u16(stream, pos);
574 if tail != Self::TAIL {
575 error!("Decoding of TAIL failed! Got {} instead!", tail);
576 }
577 Ok(event)
578 }
579}
580
581#[cfg(feature="random")]
582impl FromRandom for TofEvent {
583
584 fn from_random() -> Self {
585 let mut event = Self::new();
586 event.mt_event = MasterTriggerEvent::from_random();
587 event.header = TofEventHeader::from_random();
588 let mut rng = rand::thread_rng();
589 let n_boards = rng.gen_range(1..41) as u8;
590 for _ in 0..n_boards {
593 event.rb_events.push(RBEvent::from_random());
594 }
595 event
602 }
603}
604
605impl From<MasterTriggerEvent> for TofEvent {
606 fn from(mte : MasterTriggerEvent) -> Self {
607 let mut te : TofEvent = Default::default();
608 te.mt_event = mte;
609 te.header.event_id = te.mt_event.event_id;
610 te
611 }
612}
613
614#[derive(Debug, Clone, PartialEq)]
616pub struct TofEventHeader {
617
618 pub run_id : u32,
619 pub event_id : u32,
620 pub drs_dead_lost_hits : u8,
622 pub rsvd0 : u8,
623 pub timestamp_32 : u32,
625 pub timestamp_16 : u16, pub primary_beta : u16,
630 pub primary_beta_unc : u16,
631 pub primary_charge : u16,
632 pub primary_charge_unc : u16,
633 pub primary_outer_tof_x : u16,
634 pub primary_outer_tof_y : u16,
635 pub primary_outer_tof_z : u16,
636 pub primary_inner_tof_x : u16,
637 pub primary_inner_tof_y : u16,
638 pub primary_inner_tof_z : u16, pub trigger_info : u8,
646 pub ctr_etx : u8,
647
648 pub n_paddles : u8, }
656
657impl TofEventHeader {
658
659 pub fn new() -> Self {
660 Self {
661 run_id : 0,
662 event_id : 0,
663 drs_dead_lost_hits : 0,
664 rsvd0 : 0,
665 timestamp_32 : 0,
666 timestamp_16 : 0,
667 primary_beta : 0,
668 primary_beta_unc : 0,
669 primary_charge : 0,
670 primary_charge_unc : 0,
671 primary_outer_tof_x : 0,
672 primary_outer_tof_y : 0,
673 primary_outer_tof_z : 0,
674 primary_inner_tof_x : 0,
675 primary_inner_tof_y : 0,
676 primary_inner_tof_z : 0,
677 trigger_info : 0,
680 ctr_etx : 0,
681 n_paddles : 0
682 }
683 }
684}
685
686impl Serialization for TofEventHeader {
687 const HEAD : u16 = 0xAAAA;
688 const TAIL : u16 = 0x5555;
689 const SIZE : usize = 43;
690
691 fn from_bytestream(stream : &Vec<u8>, pos : &mut usize)
692 -> Result<Self, SerializationError> {
693 Self::verify_fixed(stream, pos)?;
694 let mut event = Self::new();
695 event.run_id = parse_u32(stream, pos);
696 event.event_id = parse_u32(stream, pos);
697 event.timestamp_32 = parse_u32(stream, pos);
698 event.timestamp_16 = parse_u16(stream, pos);
699 event.primary_beta = parse_u16(stream, pos);
700 event.primary_beta_unc = parse_u16(stream, pos);
701 event.primary_charge = parse_u16(stream, pos);
702 event.primary_charge_unc = parse_u16(stream, pos);
703 event.primary_outer_tof_x = parse_u16(stream, pos);
704 event.primary_outer_tof_y = parse_u16(stream, pos);
705 event.primary_outer_tof_z = parse_u16(stream, pos);
706 event.primary_inner_tof_x = parse_u16(stream, pos);
707 event.primary_inner_tof_y = parse_u16(stream, pos);
708 event.primary_inner_tof_z = parse_u16(stream, pos);
709 event.drs_dead_lost_hits = parse_u8(stream, pos);
710 event.rsvd0 = parse_u8(stream, pos);
711 event.trigger_info = parse_u8(stream, pos);
714 event.ctr_etx = parse_u8(stream, pos);
715 event.n_paddles = parse_u8(stream, pos);
716 *pos += 2;
717 Ok(event)
718 }
719
720 fn to_bytestream(&self) -> Vec<u8> {
721 let mut bytestream = Vec::<u8>::with_capacity(Self::SIZE);
722 bytestream.extend_from_slice(&Self::HEAD .to_le_bytes());
723 bytestream.extend_from_slice(&self.run_id .to_le_bytes());
724 bytestream.extend_from_slice(&self.event_id .to_le_bytes());
725 bytestream.extend_from_slice(&self.timestamp_32 .to_le_bytes());
726 bytestream.extend_from_slice(&self.timestamp_16 .to_le_bytes());
727 bytestream.extend_from_slice(&self.primary_beta .to_le_bytes());
728 bytestream.extend_from_slice(&self.primary_beta_unc .to_le_bytes());
729 bytestream.extend_from_slice(&self.primary_charge .to_le_bytes());
730 bytestream.extend_from_slice(&self.primary_charge_unc .to_le_bytes());
731 bytestream.extend_from_slice(&self.primary_outer_tof_x .to_le_bytes());
732 bytestream.extend_from_slice(&self.primary_outer_tof_y .to_le_bytes());
733 bytestream.extend_from_slice(&self.primary_outer_tof_z .to_le_bytes());
734 bytestream.extend_from_slice(&self.primary_inner_tof_x .to_le_bytes());
735 bytestream.extend_from_slice(&self.primary_inner_tof_y .to_le_bytes());
736 bytestream.extend_from_slice(&self.primary_inner_tof_z .to_le_bytes());
737 bytestream.extend_from_slice(&self.drs_dead_lost_hits .to_le_bytes());
741 bytestream.extend_from_slice(&self.rsvd0 .to_le_bytes());
742 bytestream.extend_from_slice(&self.trigger_info .to_le_bytes());
743 bytestream.extend_from_slice(&self.ctr_etx .to_le_bytes());
744 bytestream.extend_from_slice(&self.n_paddles .to_le_bytes());
745 bytestream.extend_from_slice(&Self::TAIL .to_le_bytes());
746 bytestream
747 }
748}
749
750
751impl Default for TofEventHeader {
752 fn default() -> Self {
753 Self::new()
754 }
755}
756
757impl From<&MasterTriggerEvent> for TofEventHeader {
758 fn from(mte : &MasterTriggerEvent) -> Self {
759 let mut te = Self::new();
760 te.event_id = mte.event_id;
761 te.timestamp_32 = mte.timestamp;
762 te.n_paddles = mte.get_trigger_hits().len() as u8;
763 te
764 }
765}
766
767impl fmt::Display for TofEventHeader {
768 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
769 let mut repr = String::from("<TofEventHeader");
770 repr += &(format!("\n Run ID : {}", self.run_id ));
771 repr += &(format!("\n Event ID : {}", self.event_id ));
772 repr += &(format!("\n Timestamp 32 : {}", self.timestamp_32 ));
773 repr += &(format!("\n Timestamp 16 : {}", self.timestamp_16 ));
774 repr += &(format!("\n DRS LOST HITS : {}", self.drs_dead_lost_hits ));
775 repr += &(format!("\n Prim. Beta : {}", self.primary_beta ));
776 repr += &(format!("\n Prim. Beta Unc : {}", self.primary_beta_unc ));
777 repr += &(format!("\n Prim. Charge : {}", self.primary_charge ));
778 repr += &(format!("\n Prim. Charge unc : {}", self.primary_charge_unc ));
779 repr += &(format!("\n Prim. Outer Tof X : {}", self.primary_outer_tof_x ));
780 repr += &(format!("\n Prim. Outer Tof Y : {}", self.primary_outer_tof_y ));
781 repr += &(format!("\n Prim. Outer Tof Z : {}", self.primary_outer_tof_z ));
782 repr += &(format!("\n Prim. Inner Tof X : {}", self.primary_inner_tof_x ));
783 repr += &(format!("\n Prim. Inner Tof Y : {}", self.primary_inner_tof_y ));
784 repr += &(format!("\n Prim. Inner Tof Z : {}", self.primary_inner_tof_z ));
785 repr += &(format!("\n TriggerInfo : {}", self.trigger_info ));
788 repr += &(format!("\n Ctr ETX : {}", self.ctr_etx ));
789 repr += &(format!("\n NPaddles : {}", self.n_paddles ));
790 repr += ">";
791 write!(f,"{}", repr)
792 }
793}
794
795#[cfg(feature="random")]
796impl FromRandom for TofEventHeader {
797
798 fn from_random() -> Self {
799 let mut rng = rand::thread_rng();
800 Self {
801 run_id : rng.gen::<u32>(),
802 event_id : rng.gen::<u32>(),
803 drs_dead_lost_hits : rng.gen::<u8>(),
804 rsvd0 : rng.gen::<u8>(),
805 timestamp_32 : rng.gen::<u32>(),
806 timestamp_16 : rng.gen::<u16>(),
807 primary_beta : rng.gen::<u16>(),
808 primary_beta_unc : rng.gen::<u16>(),
809 primary_charge : rng.gen::<u16>(),
810 primary_charge_unc : rng.gen::<u16>(),
811 primary_outer_tof_x : rng.gen::<u16>(),
812 primary_outer_tof_y : rng.gen::<u16>(),
813 primary_outer_tof_z : rng.gen::<u16>(),
814 primary_inner_tof_x : rng.gen::<u16>(),
815 primary_inner_tof_y : rng.gen::<u16>(),
816 primary_inner_tof_z : rng.gen::<u16>(),
817 trigger_info : rng.gen::<u8>(),
818 ctr_etx : rng.gen::<u8>(),
819 n_paddles : rng.gen::<u8>()
820 }
821 }
822}
823
824#[derive(Debug, Clone, PartialEq)]
830pub struct TofEventSummary {
831 pub status : EventStatus,
832 pub version : ProtocolVersion,
833 pub quality : u8,
834 pub trigger_sources : u16,
835
836 pub n_trigger_paddles : u8,
840 pub event_id : u32,
841 pub run_id : u16,
844 pub timestamp32 : u32,
845 pub timestamp16 : u16,
846 pub primary_beta : u16,
849 pub primary_charge : u16,
852 pub drs_dead_lost_hits : u16,
856 pub dsi_j_mask : u32,
857 pub channel_mask : Vec<u16>,
858 pub mtb_link_mask : u64,
859 pub hits : Vec<TofHit>,
860 pub n_hits_umb : u8,
864 pub n_hits_cbe : u8,
865 pub n_hits_cor : u8,
866 pub tot_edep_umb : f32,
867 pub tot_edep_cbe : f32,
868 pub tot_edep_cor : f32,
869 pub paddles_set : bool,
870}
871
872impl TofEventSummary {
873
874 pub fn new() -> Self {
875 Self {
876 status : EventStatus::Unknown,
877 version : ProtocolVersion::Unknown,
878 n_hits_umb : 0,
879 n_hits_cbe : 0,
880 n_hits_cor : 0,
881 tot_edep_umb : 0.0,
882 tot_edep_cbe : 0.0,
883 tot_edep_cor : 0.0,
884 quality : 0,
885 trigger_sources : 0,
886 n_trigger_paddles : 0,
887 event_id : 0,
888 run_id : 0,
889 timestamp32 : 0,
890 timestamp16 : 0,
891 primary_beta : 0,
892 primary_charge : 0,
893 drs_dead_lost_hits : 0,
894 dsi_j_mask : 0,
895 channel_mask : Vec::<u16>::new(),
896 mtb_link_mask : 0,
897 hits : Vec::<TofHit>::new(),
898 paddles_set : false,
899 }
900 }
901
902 #[cfg(feature="database")]
907 pub fn set_timing_offsets(&mut self, offsets : &HashMap<u8, f32>) {
908 for h in self.hits.iter_mut() {
909 if offsets.contains_key(&h.paddle_id) {
910 h.timing_offset = offsets[&h.paddle_id];
911 }
912 }
913 }
914
915 pub fn lightspeed_cleaning(&mut self, t_err : f32) -> (Vec<u8>, Vec<f32>) {
927 if self.hits.len() == 0 {
929 return (Vec::<u8>::new(), Vec::<f32>::new());
930 }
931 let mut twindows = Vec::<f32>::new();
932
933 self.hits.sort_by(|a,b| (a.event_t0).partial_cmp(&b.event_t0).unwrap());
934 let first_hit = self.hits[0].clone(); let mut clean_hits = Vec::<TofHit>::new();
938 let mut rm_hits = Vec::<u8>::new();
939 clean_hits.push(first_hit.clone());
941 let mut prior_hit = first_hit;
943 for h in self.hits.iter().skip(1) {
945 let mut min_tdiff_cvac = 1e9*1e-3*prior_hit.distance(h)/299792458.0;
946 let twindow = prior_hit.event_t0 + min_tdiff_cvac;
947
948
949 if h.event_t0 + 2.0*t_err < twindow {
958 rm_hits.push(h.paddle_id);
959 twindows.push(twindow);
960 continue;
961 }
962 prior_hit = h.clone();
978 clean_hits.push(*h);
979 }
980 self.hits = clean_hits;
981 (rm_hits, twindows)
982 }
983
984
985 pub fn remove_non_causal_hits(&mut self) -> Vec<u8> {
995 let mut clean_hits = Vec::<TofHit>::new();
996 let mut removed_pids = Vec::<u8>::new();
997 for h in &self.hits {
998 if h.obeys_causality() {
999 clean_hits.push(*h);
1000 } else {
1001 removed_pids.push(h.paddle_id);
1002 }
1003 }
1004 self.hits = clean_hits;
1005 removed_pids
1006 }
1007
1008 #[cfg(feature="database")]
1009 pub fn normalize_hit_times(&mut self) {
1010 if self.hits.len() == 0 {
1011 return;
1012 }
1013 if self.hits[0].event_t0 == 0.0 {
1015 return;
1016 }
1017
1018 let phase0 = self.hits[0].phase.to_f32();
1019 for h in &mut self.hits {
1020 let t0 = h.get_t0_uncorrected() + h.get_cable_delay();
1021 let mut phase_diff = h.phase.to_f32() - phase0;
1022 while phase_diff < - PI/2.0 {
1023 phase_diff += 2.0*PI;
1024 }
1025 while phase_diff > PI/2.0 {
1026 phase_diff -= 2.0*PI;
1027 }
1028 let t_shift = 50.0*phase_diff/(2.0*PI);
1029 h.event_t0 = t0 + t_shift;
1030 }
1031 self.hits.sort_by(|a,b| (a.event_t0).partial_cmp(&b.event_t0).unwrap_or(Ordering::Greater));
1034 let t0_first_hit = self.hits[0].event_t0;
1035 for h in self.hits.iter_mut() {
1036 h.event_t0 -= t0_first_hit
1037 }
1038 }
1039
1040 #[cfg(feature="database")]
1041 pub fn set_paddles(&mut self, paddles : &HashMap<u8, Paddle>) {
1042 let mut nerror = 0u8;
1043 for h in &mut self.hits {
1044 match paddles.get(&h.paddle_id) {
1045 None => {
1046 error!("Got paddle id {} which is not in given map!", h.paddle_id);
1047 nerror += 1;
1048 continue;
1049 }
1050 Some(pdl) => {
1051 h.set_paddle(pdl);
1052 }
1053 }
1054 }
1055 if nerror == 0 {
1056 self.paddles_set = true;
1057 }
1058 }
1059
1060 pub fn get_pointcloud(&self) -> Option<Vec<(f32,f32,f32,f32,f32)>> {
1065 let mut pc = Vec::<(f32,f32,f32,f32,f32)>::new();
1066 if !self.paddles_set {
1067 error!("Before getting the pointcloud, paddle information needs to be set for this event. Call TofEventSummary;:set_paddle");
1068 return None;
1069 }
1070 for h in &self.hits {
1071 let result = (h.x, h.y, h.z, h.get_t0(), h.get_edep());
1072 pc.push(result);
1073 }
1074 Some(pc)
1075 }
1076
1077 #[cfg(feature="database")]
1086 pub fn get_missing_paddles_hg(&self, pid_map : &DsiJChPidMapping) -> Vec<u8> {
1087 let mut missing = Vec::<u8>::new();
1088 for th in self.get_trigger_hits() {
1089 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
1090 let mut found = false;
1091 for h in &self.hits {
1092 if h.paddle_id == pid {
1093 found = true;
1094 break
1095 }
1096 }
1097 if !found {
1098 missing.push(pid);
1099 }
1100 }
1101 missing
1102 }
1103
1104 #[cfg(feature="database")]
1108 pub fn get_triggered_paddles(&self, pid_map : &DsiJChPidMapping) -> Vec<u8> {
1109 let mut paddles = Vec::<u8>::with_capacity(3);
1110 for th in &self.get_trigger_hits() {
1111 let pid = pid_map.get(&th.0).unwrap().get(&th.1).unwrap().get(&th.2.0).unwrap().0;
1112 paddles.push(pid);
1113 }
1114 paddles
1115 }
1116
1117 pub fn get_rb_link_ids(&self) -> Vec<u8> {
1119 let mut links = Vec::<u8>::new();
1120 for k in 0..64 {
1121 if (self.mtb_link_mask >> k) as u64 & 0x1 == 1 {
1122 links.push(k as u8);
1123 }
1124 }
1125 links
1126 }
1127
1128 pub fn get_trigger_hits(&self) -> Vec<(u8, u8, (u8, u8), LTBThreshold)> {
1141 let mut hits = Vec::<(u8,u8,(u8,u8),LTBThreshold)>::with_capacity(5);
1142 let physical_channels = [(1u8, 2u8), (3u8,4u8), (5u8, 6u8), (7u8, 8u8),
1143 (9u8, 10u8), (11u8,12u8), (13u8, 14u8), (15u8, 16u8)];
1144 let n_masks_needed = self.dsi_j_mask.count_ones();
1146 if self.channel_mask.len() < n_masks_needed as usize {
1147 error!("We need {} hit masks, but only have {}! This is bad!", n_masks_needed, self.channel_mask.len());
1148 return hits;
1149 }
1150 let mut n_mask = 0;
1151 trace!("Expecting {} hit masks", n_masks_needed);
1152 trace!("ltb channels {:?}", self.dsi_j_mask);
1153 trace!("hit masks {:?}", self.channel_mask);
1154 for k in 0..32 {
1158 if (self.dsi_j_mask >> k) as u32 & 0x1 == 1 {
1159 let mut dsi = 0u8;
1160 let mut j = 0u8;
1161 if k < 5 {
1162 dsi = 1;
1163 j = k as u8 + 1;
1164 } else if k < 10 {
1165 dsi = 2;
1166 j = k as u8 - 5 + 1;
1167 } else if k < 15 {
1168 dsi = 3;
1169 j = k as u8- 10 + 1;
1170 } else if k < 20 {
1171 dsi = 4;
1172 j = k as u8- 15 + 1;
1173 } else if k < 25 {
1174 dsi = 5;
1175 j = k as u8 - 20 + 1;
1176 }
1177 let channels = self.channel_mask[n_mask];
1181 for (i,ch) in LTB_CHANNELS.iter().enumerate() {
1182 let ph_chn = physical_channels[i];
1184 let thresh_bits = ((channels & ch) >> (i*2)) as u8;
1187 if thresh_bits > 0 { hits.push((dsi, j, ph_chn, LTBThreshold::from(thresh_bits)));
1190 }
1191 }
1192 n_mask += 1;
1193 } }
1195 hits
1196 }
1197
1198 pub fn get_trigger_sources(&self) -> Vec<TriggerType> {
1200 transcode_trigger_sources(self.trigger_sources)
1201 }
1202
1203 pub fn get_timestamp48(&self) -> u64 {
1204 ((self.timestamp16 as u64) << 32) | self.timestamp32 as u64
1205 }
1206
1207 pub fn get_edep_umbrella(&self) -> f32 {
1212 let mut tot_edep = 0.0f32;
1213 for h in &self.hits {
1214 if h.paddle_id < 61 || h.paddle_id > 108 {
1215 continue;
1216 }
1217 tot_edep += h.get_edep();
1218 }
1219 tot_edep
1220 }
1221
1222 pub fn get_edep_cube(&self) -> f32 {
1227 let mut tot_edep = 0.0f32;
1228 for h in &self.hits {
1229 if h.paddle_id > 60 {
1230 continue;
1231 }
1232 tot_edep += h.get_edep();
1233 }
1234 tot_edep
1235 }
1236
1237 pub fn get_edep_cortina(&self) -> f32 {
1242 let mut tot_edep = 0.0f32;
1243 for h in &self.hits {
1244 if h.paddle_id < 109 {
1245 continue;
1246 }
1247 tot_edep += h.get_edep();
1248 }
1249 tot_edep
1250 }
1251
1252 pub fn get_edep(&self) -> f32 {
1257 let mut tot_edep = 0.0f32;
1258 for h in &self.hits {
1259 tot_edep += h.get_edep();
1260 }
1261 tot_edep
1262 }
1263
1264 pub fn get_nhits_umb(&self) -> usize {
1265 let mut nhit = 0;
1266 for h in &self.hits {
1267 if h.paddle_id > 60 && h.paddle_id < 109 {
1268 nhit += 1;
1269 }
1270 }
1271 nhit
1272 }
1273
1274 pub fn get_nhits_cbe(&self) -> usize {
1275 let mut nhit = 0;
1276 for h in &self.hits {
1277 if h.paddle_id < 61 {
1278 nhit += 1;
1279 }
1280 }
1281 nhit
1282 }
1283
1284 pub fn get_nhits_cor(&self) -> usize {
1285 let mut nhit = 0;
1286 for h in &self.hits {
1287 if h.paddle_id > 108 {
1288 nhit += 1;
1289 }
1290 }
1291 nhit
1292 }
1293
1294 pub fn get_nhits(&self) -> usize {
1295 self.hits.len()
1296 }
1297
1298 pub fn from_tofeventpacket(pack : &TofPacket)
1302 -> Result<Self, SerializationError> {
1303 if pack.packet_type != PacketType::TofEvent {
1304 return Err(SerializationError::IncorrectPacketType);
1305 }
1306 let mut pos = 0usize;
1307 let stream = &pack.payload;
1308 let head = parse_u16(stream, &mut pos);
1309 if head != TofEvent::HEAD {
1310 return Err(SerializationError::HeadInvalid);
1311 }
1312 let mut te = TofEvent::new();
1313 te.compression_level = CompressionLevel::try_from(parse_u8(stream, &mut pos)).unwrap();
1314 te.quality = EventQuality::try_from(parse_u8(stream, &mut pos)).unwrap();
1315 te.header = TofEventHeader::from_bytestream(stream, &mut pos)?;
1316 te.mt_event = MasterTriggerEvent::from_bytestream(stream, &mut pos)?;
1317
1318 let v_sizes = TofEvent::decode_size_header(&parse_u32(stream, &mut pos));
1319 for k in 0..v_sizes.0 {
1320 match RBEvent::from_bytestream_nowaveforms(stream, &mut pos) {
1321 Err(err) => error!("Expected RBEvent {} of {}, but got serialization error {}!", k, v_sizes.0, err),
1322 Ok(ev) => {
1323 te.rb_events.push(ev);
1324 }
1325 }
1326 }
1327 let tail = parse_u16(stream, &mut pos);
1328 if tail != Self::TAIL {
1329 error!("Decoding of TAIL failed! Got {} instead!", tail);
1330 return Err(SerializationError::TailInvalid);
1331 }
1332 let summary = te.get_summary();
1333 return Ok(summary);
1334 }
1335}
1336
1337impl Packable for TofEventSummary {
1338 const PACKET_TYPE : PacketType = PacketType::TofEventSummary;
1339}
1340
1341impl Serialization for TofEventSummary {
1342
1343 const HEAD : u16 = 43690; const TAIL : u16 = 21845; fn to_bytestream(&self) -> Vec<u8> {
1347 let mut stream = Vec::<u8>::new();
1348 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
1349 let status_version = self.status.to_u8() | self.version.to_u8();
1350 stream.push(status_version);
1351 stream.extend_from_slice(&self.trigger_sources.to_le_bytes());
1352 stream.extend_from_slice(&self.n_trigger_paddles.to_le_bytes());
1353 stream.extend_from_slice(&self.event_id.to_le_bytes());
1354 if self.version == ProtocolVersion::V1 {
1356 stream.extend_from_slice(&self.n_hits_umb .to_le_bytes());
1357 stream.extend_from_slice(&self.n_hits_cbe .to_le_bytes());
1358 stream.extend_from_slice(&self.n_hits_cor .to_le_bytes());
1359 stream.extend_from_slice(&self.tot_edep_umb.to_le_bytes());
1360 stream.extend_from_slice(&self.tot_edep_cbe.to_le_bytes());
1361 stream.extend_from_slice(&self.tot_edep_cor.to_le_bytes());
1362 }
1363 stream.extend_from_slice(&self.quality.to_le_bytes());
1364 stream.extend_from_slice(&self.timestamp32.to_le_bytes());
1365 stream.extend_from_slice(&self.timestamp16.to_le_bytes());
1366 stream.extend_from_slice(&self.run_id.to_le_bytes());
1368 stream.extend_from_slice(&self.drs_dead_lost_hits.to_le_bytes());
1369 stream.extend_from_slice(&self.dsi_j_mask.to_le_bytes());
1371 let n_channel_masks = self.channel_mask.len();
1372 stream.push(n_channel_masks as u8);
1373 for k in 0..n_channel_masks {
1374 stream.extend_from_slice(&self.channel_mask[k].to_le_bytes());
1375 }
1376 stream.extend_from_slice(&self.mtb_link_mask.to_le_bytes());
1377 let nhits = self.hits.len() as u16;
1378 stream.extend_from_slice(&nhits.to_le_bytes());
1379 for k in 0..self.hits.len() {
1380 stream.extend_from_slice(&self.hits[k].to_bytestream());
1381 }
1382 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
1383 stream
1384 }
1385
1386 fn from_bytestream(stream : &Vec<u8>,
1387 pos : &mut usize)
1388 -> Result<Self, SerializationError>{
1389 let mut summary = Self::new();
1390 let head = parse_u16(stream, pos);
1391 if head != Self::HEAD {
1392 error!("Decoding of HEAD failed! Got {} instead!", head);
1393 return Err(SerializationError::HeadInvalid);
1394 }
1395 let status_version_u8 = parse_u8(stream, pos);
1396 let status = EventStatus::from(status_version_u8 & 0x3f);
1397 let version = ProtocolVersion::from(status_version_u8 & 0xc0);
1398 summary.status = status;
1399 summary.version = version;
1400 summary.trigger_sources = parse_u16(stream, pos);
1401 summary.n_trigger_paddles = parse_u8(stream, pos);
1402 summary.event_id = parse_u32(stream, pos);
1403 if summary.version == ProtocolVersion::V1 {
1404 summary.n_hits_umb = parse_u8(stream, pos);
1405 summary.n_hits_cbe = parse_u8(stream, pos);
1406 summary.n_hits_cor = parse_u8(stream, pos);
1407 summary.tot_edep_umb = parse_f32(stream, pos);
1408 summary.tot_edep_cbe = parse_f32(stream, pos);
1409 summary.tot_edep_cor = parse_f32(stream, pos);
1410 }
1411 summary.quality = parse_u8(stream, pos);
1412 summary.timestamp32 = parse_u32(stream, pos);
1413 summary.timestamp16 = parse_u16(stream, pos);
1414 summary.run_id = parse_u16(stream, pos);
1415 summary.drs_dead_lost_hits = parse_u16(stream, pos);
1416 summary.dsi_j_mask = parse_u32(stream, pos);
1417 let n_channel_masks = parse_u8(stream, pos);
1418 for _ in 0..n_channel_masks {
1419 summary.channel_mask.push(parse_u16(stream, pos));
1420 }
1421 summary.mtb_link_mask = parse_u64(stream, pos);
1422 let nhits = parse_u16(stream, pos);
1423 for _ in 0..nhits {
1424 summary.hits.push(TofHit::from_bytestream(stream, pos)?);
1425 }
1426 let tail = parse_u16(stream, pos);
1427 if tail != Self::TAIL {
1428 error!("Decoding of TAIL failed for version {}! Got {} instead!", version, tail);
1429 return Err(SerializationError::TailInvalid);
1430 }
1431 Ok(summary)
1432 }
1433}
1434
1435impl Default for TofEventSummary {
1436 fn default() -> Self {
1437 Self::new()
1438 }
1439}
1440
1441impl fmt::Display for TofEventSummary {
1442 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1443 let mut repr = format!("<TofEventSummary (version {})", self.version);
1444 repr += &(format!("\n EventID : {}", self.event_id));
1445 repr += &(format!("\n RunID : {}", self.run_id));
1446 repr += &(format!("\n EventStatus : {}", self.status));
1447 repr += &(format!("\n TriggerSources : {:?}", self.get_trigger_sources()));
1448 repr += &(format!("\n NTrigPaddles : {}", self.n_trigger_paddles));
1449 repr += &(format!("\n DRS dead hits : {}", self.drs_dead_lost_hits));
1450 repr += &(format!("\n timestamp32 : {}", self.timestamp32));
1451 repr += &(format!("\n timestamp16 : {}", self.timestamp16));
1452 repr += &(format!("\n |-> timestamp48 : {}", self.get_timestamp48()));
1453 repr += &(format!("\n ** ** TRIGGER HITS (DSI/J/CH) [{} LTBS] ** **", self.dsi_j_mask.count_ones()));
1456 for k in self.get_trigger_hits() {
1457 repr += &(format!("\n => {}/{}/({},{}) ({}) ", k.0, k.1, k.2.0, k.2.1, k.3));
1458 }
1459 repr += "\n ** ** MTB LINK IDs ** **";
1460 let mut mtblink_str = String::from("\n => ");
1461 for k in self.get_rb_link_ids() {
1462 mtblink_str += &(format!("{} ", k))
1463 }
1464 repr += &mtblink_str;
1465 repr += &(format!("\n == Trigger hits {}, expected RBEvents {}",
1466 self.get_trigger_hits().len(),
1467 self.get_rb_link_ids().len()));
1468 repr += &String::from("\n ** ** ** HITS ** ** **");
1469 for h in &self.hits {
1470 repr += &(format!("\n {}", h));
1471 }
1472 write!(f, "{}", repr)
1473 }
1474}
1475
1476#[cfg(feature="random")]
1477impl FromRandom for TofEventSummary {
1478
1479 fn from_random() -> Self {
1480 let mut summary = Self::new();
1481 let mut rng = rand::thread_rng();
1482 let status = EventStatus::from_random();
1483 let version = ProtocolVersion::from_random();
1484 if version == ProtocolVersion::V1 {
1485 summary.n_hits_umb = rng.gen::<u8>();
1486 summary.n_hits_cbe = rng.gen::<u8>();
1487 summary.n_hits_cor = rng.gen::<u8>();
1488 summary.tot_edep_umb = rng.gen::<f32>();
1489 summary.tot_edep_cbe = rng.gen::<f32>();
1490 summary.tot_edep_cor = rng.gen::<f32>();
1491 summary.quality = rng.gen::<u8>();
1492 }
1493 summary.status = status;
1494 summary.version = version;
1495 summary.trigger_sources = rng.gen::<u16>();
1497 summary.n_trigger_paddles = rng.gen::<u8>();
1498 summary.event_id = rng.gen::<u32>();
1499 summary.timestamp32 = rng.gen::<u32>();
1500 summary.timestamp16 = rng.gen::<u16>();
1501 summary.drs_dead_lost_hits = rng.gen::<u16>();
1502 summary.dsi_j_mask = rng.gen::<u32>();
1503 let n_channel_masks = rng.gen::<u8>();
1504 for _ in 0..n_channel_masks {
1505 summary.channel_mask.push(rng.gen::<u16>());
1506 }
1507 summary.mtb_link_mask = rng.gen::<u64>();
1508 let nhits = 1;
1510 for _ in 0..nhits {
1511 summary.hits.push(TofHit::from_random());
1512 }
1513 summary
1514 }
1515}
1516
1517#[test]
1523fn packable_tofeventsummary() {
1524 for _ in 0..100 {
1525 let data = TofEventSummary::from_random();
1526 let mut test : TofEventSummary = data.pack().unpack().unwrap();
1527 for h in &mut test.hits {
1532 h.paddle_len = 0.0;
1533 h.cable_len = 0.0;
1534 h.coax_cable_time = 0.0;
1535 h.hart_cable_time = 0.0;
1536 h.x = 0.0;
1537 h.y = 0.0;
1538 h.z = 0.0;
1539 h.event_t0 = 0.0;
1540 }
1541 assert_eq!(data, test);
1542 }
1543}
1544
1545#[test]
1546fn emit_tofeventsummary() {
1547 for _ in 0..100 {
1548 let data = TofEvent::from_random();
1549 let summary = data.get_summary();
1550 let test : TofEventSummary = summary.pack().unpack().unwrap();
1551 assert_eq!(summary, test);
1552 }
1553}
1554
1555#[test]
1556#[cfg(feature = "random")]
1557fn tofevent_sizes_header() {
1558 for _ in 0..100 {
1559 let data = TofEvent::from_random();
1560 let mask = data.construct_sizes_header();
1561 let size = TofEvent::decode_size_header(&mask);
1562 assert_eq!(size.0, data.rb_events.len());
1563 }
1565}
1566
1567#[test]
1568#[cfg(feature = "random")]
1569fn packable_tofevent() {
1570 for _ in 0..5 {
1571 let data = TofEvent::from_random();
1572 let test : TofEvent = data.pack().unpack().unwrap();
1573 assert_eq!(data.header, test.header);
1574 assert_eq!(data.compression_level, test.compression_level);
1575 assert_eq!(data.quality, test.quality);
1576 assert_eq!(data.mt_event, test.mt_event);
1577 assert_eq!(data.rb_events.len(), test.rb_events.len());
1578 assert_eq!(data.rb_events, test.rb_events);
1581 }
1584}
1585
1586#[test]
1587#[cfg(feature = "random")]
1588fn serialize_tofeventheader() {
1589 let data = TofEventHeader::from_random();
1590 let test = TofEventHeader::from_bytestream(&data.to_bytestream(), &mut 0).unwrap();
1591 assert_eq!(data, test);
1592}
1593