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