gondola_core/events/
rb_event.rs

1//! This files provides an event structure to pack 
2//! and bookkeep RB data
3//!
4// This file is part of gaps-online-software and published 
5// under the GPLv3 license
6
7use crate::prelude::*;
8
9
10/// Get the traces for a set of RBEvents
11///
12/// This will return a cube of 
13/// The sice of this cube will be fixed
14/// in two dimensions, but not the third
15///
16/// The rationale of this is to be able 
17/// to quickly calculate means over all
18/// channels.
19///
20/// Shape
21/// \[ch:9\]\[nevents\]\[adc_bin:1024\]
22///
23/// # Args:
24///   events - events to get the traces from
25pub fn unpack_traces<T>(events : &Vec<RBEvent>)
26  -> Vec<Vec<Vec<T>>> 
27  where T: Float + NumAssign + NumCast + Copy {
28  let nevents          = events.len();
29  let mut traces       = Vec::<Vec::<Vec::<T>>>::new();
30  let mut trace        = Vec::<T>::with_capacity(NWORDS);
31  let mut stop_cells   = Vec::<isize>::new();
32  let mut empty_events = Vec::<Vec::<T>>::new();
33  for _ in 0..nevents {
34    empty_events.push(trace.clone());
35  }
36  for ch in 0..NCHN {
37    traces.push(empty_events.clone());
38    for (k,ev) in events.iter().enumerate() {
39      trace.clear();
40      stop_cells.push(ev.header.stop_cell as isize);
41      for k in 0..NWORDS {
42        // the unwrap here can be debated. Technically it does 
43        // only ensure that the cast can be possible
44        trace.push(T::from(ev.adc[ch][k]).unwrap());
45      }
46      traces[ch][k] = trace.clone();
47    }
48  }
49  traces
50}
51
52
53/// Event data for each individual ReadoutBoard (RB)
54#[derive(Debug, Clone, PartialEq)]
55#[cfg_attr(feature="pybindings", pyclass)]
56pub struct RBEvent {
57  pub data_type    : DataType,
58  pub status       : EventStatus,
59  pub header       : RBEventHeader,
60  pub adc          : Vec<Vec<u16>>,
61  pub hits         : Vec<TofHit>,
62}
63
64impl RBEvent {
65
66  pub fn new() -> Self {
67    let mut adc = Vec::<Vec<u16>>::with_capacity(NCHN);
68    for _ in 0..NCHN {
69      adc.push(Vec::<u16>::new());
70    }
71    Self {
72      data_type    : DataType::Unknown,
73      status       : EventStatus::Unknown,
74      header       : RBEventHeader::new(),
75      adc          : adc,
76      hits         : Vec::<TofHit>::new(),
77    }
78  }
79
80  #[deprecated(since="0.11", note="check seems meaningnless")] 
81  pub fn trace_check(&self) -> bool {
82    let mut check  = true;
83    let mut nchan  = 0usize;
84    let mut failed = true;
85    for ch in self.header.get_channels() {
86      if self.adc[ch as usize].len() != NWORDS {
87        check = false;
88      }
89      for k in &self.adc[ch as usize] {
90        if *k != u16::MAX {
91          // just check that not all bins are 
92          // u16::MAX. They get set to that
93          // value in case of an error
94          // also if that happens to any of 
95          // the channels, throw the whole 
96          // event away.
97          failed = false;
98        }
99      }
100      nchan += 1;
101    }
102    // for the calibration we want to have all 
103    // channels!
104    check && nchan == NCHN && !failed
105  }
106
107  pub fn has_any_mangling_flag(&self) -> bool {
108    match self.status {
109      EventStatus::ChnSyncErrors 
110      | EventStatus::CellSyncErrors
111      | EventStatus::CellAndChnSyncErrors => {
112        return true;
113      }
114      _ => {
115        return false;
116      }
117    }
118  }
119
120  /// Check if we have all the channel data even as 
121  /// indicated by the header
122  pub fn self_check(&self) -> Result<(),AnalysisError>  {
123    let mut pass = false;
124    for ch in self.header.get_channels() {
125      if self.adc[ch as usize].len() == 0 {
126        error!("RB {} expects ch {} but it is empty!", self.header.rb_id, ch + 1);
127        println!("{}", self.header);
128        pass = false;
129      }
130    }
131    if !pass {
132      return Err(AnalysisError::MissingChannel);
133    }
134    Ok(())
135  }
136
137  /// Deconstruct the RBEvent to form RBWaveforms
138  pub fn get_rbwaveforms(&self) -> Vec<RBWaveform> {
139    // FIXME - fix it, this drives me crazy
140    let mut waveforms   = Vec::<RBWaveform>::new();
141    // at max, we can have 4 waveform packets
142    let active_channels = self.header.get_channels();
143    let pid             = self.header.get_rbpaddleid();
144    if active_channels.contains(&0) || active_channels.contains(&1) {
145      let paddle_id  = pid.get_paddle_id(1);
146      let mut wf     = RBWaveform::new();
147      wf.rb_id       = self.header.rb_id;
148      wf.event_id    = self.header.event_id;
149      wf.stop_cell   = self.header.stop_cell;
150      wf.paddle_id   = paddle_id.0;
151      if paddle_id.1 {
152        // then b is channel 1 (or 0)
153        wf.adc_b   = self.adc[0].clone();
154        wf.adc_a   = self.adc[1].clone();
155        wf.rb_channel_b = 0;
156        wf.rb_channel_a = 1;
157      } else {
158        wf.adc_a   = self.adc[0].clone();
159        wf.adc_b   = self.adc[1].clone();
160        wf.rb_channel_b = 1;
161        wf.rb_channel_a = 0;
162      }
163      waveforms.push(wf);
164    }
165    if active_channels.contains(&2) || active_channels.contains(&3) {
166      let paddle_id  = pid.get_paddle_id(3);
167      let mut wf     = RBWaveform::new();
168      wf.rb_id       = self.header.rb_id;
169      wf.event_id    = self.header.event_id;
170      wf.stop_cell   = self.header.stop_cell;
171      wf.paddle_id   = paddle_id.0;
172      if paddle_id.1 {
173        // channel order flipped!
174        wf.adc_b   = self.adc[2].clone();
175        wf.adc_a   = self.adc[3].clone();
176        wf.rb_channel_b = 2;
177        wf.rb_channel_a = 3;
178      } else {
179        wf.adc_a   = self.adc[2].clone();
180        wf.adc_b   = self.adc[3].clone();
181        wf.rb_channel_b = 3;
182        wf.rb_channel_a = 2;
183      }
184      waveforms.push(wf);
185    }
186    if active_channels.contains(&4) || active_channels.contains(&5) {
187      let paddle_id  = pid.get_paddle_id(5);
188      let mut wf     = RBWaveform::new();
189      wf.rb_id       = self.header.rb_id;
190      wf.event_id    = self.header.event_id;
191      wf.stop_cell   = self.header.stop_cell;
192      wf.paddle_id   = paddle_id.0;
193      if paddle_id.1 {
194        // then b is channel 1 (or 0)
195        wf.adc_b   = self.adc[4].clone();
196        wf.adc_a   = self.adc[5].clone();
197        wf.rb_channel_b = 4;
198        wf.rb_channel_a = 5;
199      } else {
200        wf.adc_a   = self.adc[4].clone();
201        wf.adc_b   = self.adc[5].clone();
202        wf.rb_channel_b = 5;
203        wf.rb_channel_a = 4;
204      }
205      waveforms.push(wf);
206    }
207    if active_channels.contains(&6) || active_channels.contains(&7) {
208      let paddle_id  = pid.get_paddle_id(7);
209      let mut wf     = RBWaveform::new();
210      wf.rb_id       = self.header.rb_id;
211      wf.event_id    = self.header.event_id;
212      wf.stop_cell   = self.header.stop_cell;
213      wf.paddle_id   = paddle_id.0;
214      if paddle_id.1 {
215        // then b is channel 1 (or 0)
216        wf.adc_b   = self.adc[6].clone();
217        wf.adc_a   = self.adc[7].clone();
218        wf.rb_channel_b = 6;
219        wf.rb_channel_a = 7;
220      } else {
221        wf.adc_a   = self.adc[6].clone();
222        wf.adc_b   = self.adc[7].clone();
223        wf.rb_channel_b = 6;
224        wf.rb_channel_a = 7;
225      }
226      waveforms.push(wf);
227    }
228    waveforms
229  }
230
231  /// Get the datatype from a bytestream when we know
232  /// that it is an RBEvent
233  ///
234  /// The data type is encoded in byte 3
235  pub fn extract_datatype(stream : &Vec<u8>) -> Result<DataType, SerializationError> {
236    if stream.len() < 3 {
237      return Err(SerializationError::StreamTooShort);
238    }
239    // TODO This might panic! Is it ok?
240    Ok(DataType::try_from(stream[2]).unwrap_or(DataType::Unknown))
241  }
242  
243  /// decode the len field in the in memroy represention of 
244  /// RBEventMemoryView
245  pub fn get_channel_packet_len(stream : &Vec<u8>, pos : usize) -> Result<(usize, Vec::<u8>), SerializationError> {
246    // len is at position 4 
247    // roi is at postion 6
248    if stream.len() < 8 {
249      return Err(SerializationError::StreamTooShort);
250    }
251    let mut _pos = pos + 4;
252    let packet_len = parse_u16(stream, &mut _pos) as usize * 2; // len is in 2byte words
253    if packet_len < 44 {
254      // There is only header data 
255      error!("Event fragment - no channel data!");
256      return Ok((packet_len.into(), Vec::<u8>::new()));
257    }
258    let nwords     = parse_u16(stream, &mut _pos) as usize + 1; // roi is max bin (first is 0)
259    debug!("Got packet len of {} bytes, roi of {}", packet_len, nwords);
260    let channel_packet_start = pos + 36;
261    let nchan_data = packet_len - 44;
262    if stream.len() < channel_packet_start + nchan_data {
263      error!("We claim there should be channel data, but the event is too short!");
264      return Err(SerializationError::StreamTooShort)
265    }
266
267    let mut nchan = 0usize;
268    //println!("========================================");
269    //println!("{} {} {}", nchan, nwords, nchan_data);
270    //println!("========================================");
271    while nchan * (2*nwords + 6) < nchan_data {
272      nchan += 1;
273    }
274    if nchan * (2*nwords + 6) != nchan_data {
275      error!("NCHAN consistency check failed! nchan {} , nwords {}, packet_len {}", nchan, nwords, packet_len);
276    }
277    let mut ch_ids = Vec::<u8>::new();
278    _pos = channel_packet_start;
279    for _ in 0..nchan {
280      ch_ids.push(parse_u16(stream, &mut _pos) as u8);
281      _pos += (nwords*2) as usize;
282      _pos += 4; // trailer
283    }
284    debug!("Got channel ids {:?}", ch_ids);
285    Ok((nchan_data.into(), ch_ids))
286  }
287
288  /// Get the event id from a RBEvent represented by bytestream
289  /// without decoding the whole event
290  ///
291  /// This should be faster than decoding the whole event.
292  pub fn extract_eventid(stream : &Vec<u8>) -> Result<u32, SerializationError> {
293    if stream.len() < 30 {
294      return Err(SerializationError::StreamTooShort);
295    }
296    // event header starts at position 7
297    // in the header, it is as positon 3
298    let event_id = parse_u32(stream, &mut 10);
299    Ok(event_id)
300  }
301
302  pub fn get_ndatachan(&self) -> usize {
303    self.adc.len()
304  }
305
306  pub fn get_channel_by_id(&self, ch : usize) -> Result<&Vec::<u16>, UserError> {
307    if ch >= 9 {
308      error!("channel_by_id expects numbers from 0-8!");
309      return Err(UserError::IneligibleChannelLabel)
310    }
311    return Ok(&self.adc[ch]);
312  }
313
314  pub fn get_channel_by_label(&self, ch : u8) -> Result<&Vec::<u16>, UserError>  {
315    if ch == 0 || ch > 9 {
316      error!("channel_by_label expects numbers from 1-9!");
317      return Err(UserError::IneligibleChannelLabel)
318    }
319    Ok(&self.adc[ch as usize -1])
320  }
321
322  /// Similar to the "official" from_bytestream, this will get the 
323  /// event from a bytestream, omitting the waveforms. This will allow
324  /// for a faster readout in case waveforms are not needed.
325  pub fn from_bytestream_nowaveforms(stream : &Vec<u8>, pos : &mut usize)
326    -> Result<Self, SerializationError> {
327    let mut event = Self::new();
328    if parse_u16(stream, pos) != Self::HEAD {
329      error!("The given position {} does not point to a valid header signature of {}", pos, Self::HEAD);
330      return Err(SerializationError::HeadInvalid {});
331    }
332    event.data_type = DataType::try_from(parse_u8(stream, pos)).unwrap_or(DataType::Unknown);
333    event.status    = EventStatus::try_from(parse_u8(stream, pos)).unwrap_or(EventStatus::Unknown);
334    //let nchan_data  = parse_u8(stream, pos);
335    let n_hits      = parse_u8(stream, pos);
336    event.header    = RBEventHeader::from_bytestream(stream, pos)?;
337    //let ch_ids      = event.header.get_active_data_channels();
338    let stream_len  = stream.len();
339    if event.header.is_event_fragment() {
340      debug!("Fragmented event {} found!", event.header.event_id);
341      let tail_pos = seek_marker(stream, Self::TAIL, *pos)?;
342      * pos = tail_pos + 2 as usize;
343      // the event fragment won't have channel data, so 
344      // let's move on to the next TAIL marker:ta
345      return Ok(event);
346    }
347    if event.header.drs_lost_trigger() {
348      debug!("Event {} has lost trigger!", event.header.event_id);
349      let tail_pos = seek_marker(stream, Self::TAIL, *pos)?;
350      * pos = tail_pos + 2 as usize;
351      return Ok(event);
352    }
353    let mut decoded_ch = Vec::<u8>::new();
354    // here is the only change to from_bytestream. 
355    // We are simply skipping the waveforms, but 
356    // still read the hits
357    for ch in event.header.get_channels().iter() {
358      if *pos + 2*NWORDS >= stream_len {
359        error!("The channel data for event {} ch {} seems corrupt! We want to get channels {:?}, but have decoded only {:?}, because the stream ends {} bytes too early!",event.header.event_id, ch, event.header.get_channels(), decoded_ch, *pos + 2*NWORDS - stream_len);
360        let tail_pos = seek_marker(stream, Self::TAIL, *pos)?;
361        * pos = tail_pos + 2 as usize;
362        return Err(SerializationError::WrongByteSize {})
363      }
364      decoded_ch.push(*ch);
365      // 2*NWORDS because stream is Vec::<u8> and it is 16 bit words.
366      *pos += 2*NWORDS;
367    }
368    for _ in 0..n_hits {
369      match TofHit::from_bytestream(stream, pos) {
370        Err(err) => {
371          error!("Can't read TofHit! Err {err}");
372          let mut h = TofHit::new();
373          h.valid = false;
374          event.hits.push(h);
375        },
376        Ok(h) => {
377          event.hits.push(h);
378        }
379      }
380    }
381    let tail = parse_u16(stream, pos);
382    if tail != Self::TAIL {
383      error!("After parsing the event, we found an invalid tail signature {}", tail);
384      return Err(SerializationError::TailInvalid);
385    }
386    Ok(event)
387  }
388}
389
390impl TofPackable for RBEvent {
391  const TOF_PACKET_TYPE : TofPacketType = TofPacketType::RBEvent;
392}
393
394impl Serialization for RBEvent {
395  const HEAD : u16 = 0xAAAA;
396  const TAIL : u16 = 0x5555;
397  
398  fn from_bytestream(stream : &Vec<u8>, pos : &mut usize)
399    -> Result<Self, SerializationError> {
400    let mut event = Self::new();
401    if parse_u16(stream, pos) != Self::HEAD {
402      error!("The given position {} does not point to a valid header signature of {}", pos, Self::HEAD);
403      return Err(SerializationError::HeadInvalid {});
404    }
405    event.data_type = DataType::try_from(parse_u8(stream, pos)).unwrap_or(DataType::Unknown);
406    event.status    = EventStatus::try_from(parse_u8(stream, pos)).unwrap_or(EventStatus::Unknown);
407    //let nchan_data  = parse_u8(stream, pos);
408    let n_hits      = parse_u8(stream, pos);
409    event.header    = RBEventHeader::from_bytestream(stream, pos)?;
410    //let ch_ids      = event.header.get_active_data_channels();
411    let stream_len  = stream.len();
412    if event.header.is_event_fragment() {
413      debug!("Fragmented event {} found!", event.header.event_id);
414      let tail_pos = seek_marker(stream, Self::TAIL, *pos)?;
415      * pos = tail_pos + 2 as usize;
416      // the event fragment won't have channel data, so 
417      // let's move on to the next TAIL marker:ta
418      return Ok(event);
419    }
420    if event.header.drs_lost_trigger() {
421      debug!("Event {} has lost trigger!", event.header.event_id);
422      let tail_pos = seek_marker(stream, Self::TAIL, *pos)?;
423      * pos = tail_pos + 2 as usize;
424      return Ok(event);
425    }
426    let mut decoded_ch = Vec::<u8>::new();
427    for ch in event.header.get_channels().iter() {
428      if *pos + 2*NWORDS >= stream_len {
429        error!("The channel data for event {} ch {} seems corrupt! We want to get channels {:?}, but have decoded only {:?}, because the stream ends {} bytes too early!",event.header.event_id, ch, event.header.get_channels(), decoded_ch, *pos + 2*NWORDS - stream_len);
430        let tail_pos = seek_marker(stream, Self::TAIL, *pos)?;
431        * pos = tail_pos + 2 as usize;
432        return Err(SerializationError::WrongByteSize {})
433      }
434      decoded_ch.push(*ch);
435      // 2*NWORDS because stream is Vec::<u8> and it is 16 bit words.
436      let data = &stream[*pos..*pos+2*NWORDS];
437      //event.adc[k as usize] = u8_to_u16(data);
438      event.adc[*ch as usize] = u8_to_u16(data);
439      *pos += 2*NWORDS;
440    }
441    for _ in 0..n_hits {
442      match TofHit::from_bytestream(stream, pos) {
443        Err(err) => {
444          error!("Can't read TofHit! Err {err}");
445          let mut h = TofHit::new();
446          h.valid = false;
447          event.hits.push(h);
448        },
449        Ok(h) => {
450          event.hits.push(h);
451        }
452      }
453    }
454    let tail = parse_u16(stream, pos);
455    //println!("{:?}", &stream[*pos-10..*pos+2]);
456    //println!("{} {}", pos, stream.len());
457    if tail != Self::TAIL {
458      error!("After parsing the event, we found an invalid tail signature {}", tail);
459      return Err(SerializationError::TailInvalid);
460    }
461    Ok(event)
462  }
463  
464  fn to_bytestream(&self) -> Vec<u8> {
465    let mut stream = Vec::<u8>::with_capacity(18530);
466    //let mut stream = Vec::<u8>::new();
467    stream.extend_from_slice(&Self::HEAD.to_le_bytes());
468    stream.push(self.data_type as u8);
469    stream.push(self.status as u8);
470    //let nchan_data  = self.adc.len() as u8;
471    //stream.push(nchan_data);
472    let n_hits      = self.hits.len() as u8;
473    stream.push(n_hits);
474    stream.extend_from_slice(&self.header.to_bytestream());
475    // for an empty channel, we will add an empty vector
476    let add_channels = !self.header.is_event_fragment() & !self.header.drs_lost_trigger();
477    if add_channels {
478      for n in 0..NCHN {
479        for k in 0..NWORDS {
480          if self.adc[n].len() == 0 {
481            continue;
482          }
483          stream.extend_from_slice(&self.adc[n][k].to_le_bytes());  
484        }
485      }
486      // this is way slower
487      //for channel_adc in self.adc.iter() {
488      //  stream.extend_from_slice(&u16_to_u8(&channel_adc)); 
489      //}
490    }
491    //if self.ch9_adc.len() > 0 {
492    //  stream.extend_from_slice(&u16_to_u8(&self.ch9_adc));
493    //}
494    for h in self.hits.iter() {
495      stream.extend_from_slice(&h.to_bytestream());
496    }
497    stream.extend_from_slice(&Self::TAIL.to_le_bytes());
498    stream
499  }
500}
501
502impl Default for RBEvent {
503
504  fn default () -> Self {
505    Self::new()
506  }
507}
508
509impl fmt::Display for RBEvent {
510  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
511    let mut adc = Vec::<usize>::new();
512    for k in 0..self.adc.len() -1 {
513      adc.push(self.adc[k].len());
514    }
515    let mut ch9_str = String::from("[");
516    for k in self.adc[8].iter().take(5) {
517      ch9_str += &k.to_string();
518      ch9_str += ","
519    }
520    ch9_str += " .. :";
521    ch9_str += &self.adc[8].len().to_string();
522    ch9_str += "]";
523    let mut ch_field = String::from("[\n");
524    for (ch, vals) in self.adc.iter().enumerate() {
525      if ch == 8 {
526        continue;
527      }
528      let label = (ch + 1).to_string();
529      ch_field += "  [ch ";
530      ch_field += &ch.to_string();
531      ch_field += "('";
532      ch_field += &label;
533      ch_field += "') ";
534      for n in vals.iter().take(5) {
535        ch_field += &n.to_string();
536        ch_field += ",";
537      }
538      ch_field += "..:";
539      ch_field += &vals.len().to_string();
540      ch_field += "]\n";
541    }
542    ch_field += "]\n";
543    write!(f, "<RBEvent 
544  data type     : {},
545  event status  : {},
546  {}
547  .. .. 
548  has ch9       : {},
549    -> ch9      : {},
550  data channels : 
551    -> {},
552  n hits        : {},
553.. .. .. .. .. .. .. .. >",
554    self.data_type,
555    self.status,
556    self.header,
557    self.header.has_ch9(),
558    ch9_str,
559    ch_field,
560    self.hits.len())
561  }
562}
563
564#[cfg(feature = "random")]
565impl FromRandom for RBEvent {
566    
567  fn from_random() -> Self {
568    let mut event   = RBEvent::new();
569    let header      = RBEventHeader::from_random();
570    let mut rng     = rand::rng();
571    event.data_type = DataType::from_random(); 
572    event.status    = EventStatus::from_random();
573    event.header    = header;
574    // set a good status byte. RBEvents from 
575    // random will always be good
576    // status_byte is tested in RBEventHeader test
577    // and here we want to make sure channel data 
578    // gets serialized
579    // status byte of 0 means it is good
580    event.header.status_byte = 0;
581    //if !event.header.event_fragment && !event.header.lost_trigger {
582    for ch in event.header.get_channels().iter() {
583      let random_numbers: Vec<u16> = (0..NWORDS).map(|_| rng.random()).collect();
584      event.adc[*ch as usize] = random_numbers;
585    }
586    //}
587    event
588  }
589}
590
591
592//impl From<&TofPacket> for RBEvent {
593//  fn from(pk : &TofPacket) -> Self {
594//    match pk.packet_type {
595//      //PacketType::RBEventMemoryView => {
596//      //  match RBEvent::extract_from_rbeventmemoryview(&pk.payload, &mut 0) {
597//      //    Ok(event) => {
598//      //      return event;
599//      //    }
600//      //    Err(err) => { 
601//      //      error!("Can not get RBEvent from RBEventMemoryView! Error {err}!");
602//      //      error!("Returning empty event!");
603//      //      return RBEvent::new();
604//      //    }
605//      //  }
606//      //},
607//      TofPacketType::RBEvent => {
608//        match RBEvent::from_bytestream(&pk.payload, &mut 0) {
609//          Ok(event) => {
610//            return event;
611//          }
612//          Err(err) => { 
613//            error!("Can not decode RBEvent - will return empty event! {err}");
614//            return RBEvent::new();
615//          }
616//        }
617//      },
618//      TofPacketType::RBEventMemoryView => {
619//        let mut streamer = RBEventMemoryStreamer::new();
620//        streamer.add(&pk.payload, pk.payload.len());
621//        match streamer.get_event_at_pos_unchecked(None) {
622//          None => {
623//            return RBEvent::new();
624//          },
625//          Some(ev) => {
626//            return ev;
627//          }
628//        }
629//      },
630//
631//      _ => {
632//        error!("Can not deal with {}! Returning empty event", pk);
633//        return RBEvent::new();
634//      }
635//    }
636//  }
637//}
638
639//-----------------------------------------------------------
640  
641#[cfg(feature="pybindings")]
642#[pymethods]
643impl RBEvent {
644
645  #[getter]
646  fn get_status(&self) -> EventStatus {
647    self.status
648  }
649
650  // FIXME - use PyReadonlyArray? Needs test
651  /// Get adc values directly from the RBEvent with zero copy
652  ///
653  /// The channel has to go from 1-9
654  fn get_waveform<'_py>(&self, py: Python<'_py>, channel : usize) -> PyResult<Bound<'_py, PyArray1<u16>>> {  
655    if channel < 1 || channel > 9 {
656      return Err(PyValueError::new_err("Channel must be > 0 and < 9"));
657    }
658    let data = &self.adc[channel - 1];
659    let py_array = data.to_pyarray(py);
660    Ok(py_array)
661  }
662  
663  fn get_waveform_slow<'_py>(&self, py: Python<'_py>, channel : usize) -> PyResult<Bound<'_py, PyArray1<u16>>> {  
664    let wf  = self.get_channel_by_id(channel).unwrap().clone();
665    let arr = PyArray1::<u16>::from_vec(py, wf);
666    Ok(arr)
667  }
668  
669  
670  #[getter]
671  fn get_hits(&self) -> Vec<TofHit> {
672    self.hits.clone()
673  }
674 
675  // FIXME - no clear if a new object is created here 
676  #[getter]
677  fn get_header<'_py>(&self, py : Python<'_py>) -> PyResult<Bound<'_py , RBEventHeader>> {
678    Bound::<'_py, RBEventHeader>::new(py, self.header)
679  }
680  
681  #[getter]
682  fn waveforms(&self) -> Vec<RBWaveform> {
683    self.get_rbwaveforms().clone()
684  }
685}
686
687#[cfg(feature="pybindings")]
688pythonize_packable!(RBEvent);
689
690//-----------------------------------------------------------
691
692//FIXME - test needs some review
693#[test]
694fn serialization_rbevent() {
695  for _ in 0..100 {
696    let event  = RBEvent::from_random();
697    let stream = event.to_bytestream();
698    println!("[test rbevent] stream.len()   {:?}", stream.len());
699    let test   = RBEvent::from_bytestream(&stream, &mut 0).unwrap();
700    println!("[test rbevent] event frag   {:?}", event.header.is_event_fragment());
701    println!("[test rbevent] lost trig    {:?}", event.header.drs_lost_trigger());
702    println!("[test rbevent] event frag   {:?}", test.header.is_event_fragment());
703    println!("[test rbevent] lost trig    {:?}", test.header.drs_lost_trigger());
704    assert_eq!(event.header, test.header);
705    assert_eq!(event.header.get_nchan(), test.header.get_nchan());
706    assert_eq!(event.header.get_channels(), test.header.get_channels());
707    assert_eq!(event.data_type, test.data_type);
708    assert_eq!(event.status, test.status);
709    assert_eq!(event.adc.len(), test.adc.len());
710    assert_eq!(event.hits.len(), test.hits.len());
711    println!("[test rbevent] get_channels() {:?}", event.header.get_channels());
712    assert_eq!(event.adc[0].len(), test.adc[0].len());
713    assert_eq!(event.adc[1].len(), test.adc[1].len());
714    assert_eq!(event.adc[2].len(), test.adc[2].len());
715    assert_eq!(event.adc[3].len(), test.adc[3].len());
716    assert_eq!(event.adc[4].len(), test.adc[4].len());
717    assert_eq!(event.adc[5].len(), test.adc[5].len());
718    assert_eq!(event.adc[6].len(), test.adc[6].len());
719    assert_eq!(event.adc[7].len(), test.adc[7].len());
720    assert_eq!(event.adc[8].len(), test.adc[8].len());
721    assert_eq!(event.adc[0], test.adc[0]);
722    assert_eq!(event.adc[1], test.adc[1]);
723    assert_eq!(event.adc[2], test.adc[2]);
724    assert_eq!(event.adc[3], test.adc[3]);
725    assert_eq!(event.adc[4], test.adc[4]);
726    assert_eq!(event.adc[5], test.adc[5]);
727    assert_eq!(event.adc[6], test.adc[6]);
728    assert_eq!(event.adc[7], test.adc[7]);
729    assert_eq!(event.adc[8], test.adc[8]);
730    //for ch in (event.header.get_channels().iter()){
731    //  assert_eq!(event.adc[*ch as usize], test.adc[*ch as usize]);
732    //}
733    //assert_eq!(event, test);
734
735    //if head.header.event_fragment == test.header.event_fragment {
736    //  println!("Event fragment found, no channel data available!");
737    //} else {
738    //  assert_eq!(head, test);
739    //}
740  }
741}
742
743#[test]
744fn pack_rbevent() {
745  for _ in 0..100 {
746    let event  = RBEvent::from_random();
747    let test : RBEvent = event.pack().unpack().unwrap();
748    assert_eq!(event, test);
749  }
750}
751