Skip to main content

gondola_core/events/
tracker_daq_event_packet.rs

1//! Tracker event as stored seperately in telemetry packet type 80
2//!
3//! This has been used in tracker stand-alone mode and for calibrations.
4//! The event as described here is NOT part of the merged event
5// This file is part of gaps-online-software and published 
6// under the GPLv3 license
7
8use crate::prelude::*;
9
10/// Tracker stand-alone complete event information from up-to multiple
11/// DAQ boxes as used in TelemetryPacketType::Tracker (80) 
12#[derive(Debug, Clone, PartialEq)]
13#[cfg_attr(feature="pybindings", pyclass)]
14pub struct TrackerDAQEventPacket {
15  pub header     : TelemetryPacketHeader,
16  pub daq_header : TrackerHeader,
17  pub events     : Vec<TrackerDAQEvent>,
18  pub run_id     : u16,
19  pub run_id_old : u8,
20  // not serialized 
21  /// internal counter for number of tracker hits in 
22  /// this event 
23  pub n_hits     : u16,
24}
25
26impl TrackerDAQEventPacket {
27
28  pub fn new() -> Self {
29    Self {
30      header     : TelemetryPacketHeader::new(),
31      daq_header : TrackerHeader::new(),
32      events     : Vec::<TrackerDAQEvent>::new(),
33      run_id     : 0,
34      run_id_old : 0,
35      n_hits     : 0,
36    }
37  }
38
39  /// Return an empty shell, that is all 
40  /// information except the actual events
41  ///
42  /// Ben Drowned...
43  pub fn emit_empty(&self) -> Self {
44    Self {
45      header     : self.header.clone(),
46      daq_header : self.daq_header.clone(),
47      events     : Vec::<TrackerDAQEvent>::new(),
48      run_id     : self.run_id,
49      run_id_old : self.run_id_old,
50      n_hits     : self.n_hits,
51    } 
52  }
53
54  /// Adds a TrackerDAQEvent 
55  pub fn add_event(&mut self, ev : TrackerDAQEvent) {
56    self.events.push(ev);
57  }
58
59
60  /// Remove all the TrackerDAQEvents in 
61  /// the event list
62  pub fn clear_events(&mut self) {
63    self.events.clear();
64  }
65
66  /// Create a telemetrypacket 
67  pub fn pack(&self) -> TelemetryPacket {
68    let mut tp = TelemetryPacket::new();
69    tp.header  = self.header.clone();
70    tp.payload = self.to_bytestream();
71    // update the length, since the packet contents 
72    // might have changed
73    tp.header.length = TelemetryPacketHeader::SIZE as u16 + tp.payload.len() as u16;
74    // FIXME - we need to update the checksum
75    tp
76  }
77
78  /// Remove a single TrackerDAQEvent from the 
79  /// associated list of events 
80  ///
81  /// # Arguments:
82  ///   * evid : Event ID of the event in the 
83  ///            list of associated events to 
84  ///            be removed
85  pub fn remove_event(&mut self,evid : u32) {
86    self.events.retain(|x| x.event_id != evid);
87  }
88
89  /// Get all hits from all daq boxes participating 
90  /// in this event 
91  pub fn get_hits(&self) -> Vec<TrackerHit> {
92    let mut hits = Vec::<TrackerHit>::new();
93    for ev in &self.events {
94      hits.extend_from_slice(&ev.hits);
95    }
96    hits
97  }
98
99  /// Get all event ids in the packet
100  /// (these might be different) 
101  pub fn get_event_ids(&self) -> Vec<u32> {
102    let mut evids = Vec::<u32>::new();
103    for ev in &self.events {
104      evids.push(ev.event_id);
105    }
106    evids 
107  }
108
109  /// Get a copy specific TrackerDAQEvent for a given event id
110  pub fn get_event_for_evid(&self, evid : u32) -> Option<TrackerDAQEvent> {
111    for ev in &self.events {
112      if ev.event_id == evid {
113        return Some(ev.clone())
114      }
115    }
116    None 
117  }
118
119  /// Return all tracker hits which belong to a certain event id
120  pub fn get_hits_for_evid(&self, evid : u32) -> Vec<TrackerHit> {
121    let mut hits = Vec::<TrackerHit>::new();
122    for ev in &self.events {
123      if ev.event_id == evid {
124        hits.extend_from_slice(&ev.hits);
125      }
126    }
127    hits
128  }
129  
130  pub fn from_telemetrypacket(packet : &TelemetryPacket) -> Result<Self, SerializationError> {
131    match Self::from_bytestream(&packet.payload, &mut 0) {
132      Ok(mut event) => {
133        event.header  = packet.header.clone();
134        return Ok(event);
135      }
136      Err(err) => {
137        return Err(err);
138      }  
139    }
140  }
141}
142
143impl Serialization for TrackerDAQEventPacket { 
144
145  fn from_bytestream(stream : &Vec<u8>,
146                     pos    : &mut usize)
147    -> Result<Self, SerializationError> {
148    let mut ev    = Self::new();
149    ev.daq_header = TrackerHeader::from_bytestream(stream, pos)?; 
150    if ev.daq_header.version >= 5 {
151      ev.run_id     = parse_u16(stream, pos);
152    } else {
153      ev.run_id_old = parse_u8(stream, pos);
154    }
155    let event_header_size = 12usize;  
156    loop {
157      if ev.events.len() > 170 {
158        error!("There seem to be more than 170 events (!) in the tracker. This is nonsense!");
159        return Err(SerializationError::TooManyTrackerEvents); 
160      }
161      if ev.daq_header.version >= 4 {
162        if *pos + 1 == stream.len() {
163          if stream[*pos] == 0xff {
164            return Ok(ev);
165          }
166        }
167        if *pos == stream.len() {
168          return Ok(ev);
169        }
170      } 
171      if *pos + event_header_size > stream.len() { 
172        error!("Unable to read more TrackerEvents! Stream is too short!");
173        println!("{}", ev); 
174        println!("pos {} , stream {}",pos, stream.len());
175        println!("Unable to read more TrackerEvents! Stream is too short!");
176        return Err(SerializationError::StreamTooShort);
177      }
178      
179      let mut daq_event      = TrackerDAQEvent::new();
180      daq_event.layer        = ev.daq_header.sys_id;
181      let n_hits             = parse_u8(stream, pos);
182      daq_event.flags1       = parse_u8(stream, pos);
183      daq_event.event_id     = parse_u32(stream, pos);
184      daq_event.event_time32 = parse_u32(stream, pos); 
185      daq_event.event_time16 = parse_u16(stream, pos);
186      if n_hits > 192 {
187        error!("We see more than 192 hits in the event! This seems to be an issue.");
188        return Err(SerializationError::TooManyTrackerHits);
189      } 
190      if (*pos + (3*(n_hits as usize))) > stream.len() {
191        error!("Unable to read all {} tracker hits! Stream is too short!", n_hits);
192        println!("Unable to read all {} tracker hits! Stream is too short!", n_hits);
193        return Err(SerializationError::StreamTooShort);
194      }
195      for _ in 0..n_hits {
196        let h0 = parse_u8(stream, pos);
197        let h1 = parse_u8(stream, pos);
198        let h2 = parse_u8(stream, pos);
199        let asic_event_code = h2 >> 6;
200        let channel = h0 & 0b11111;
201        let module = h0 >> 5;
202        let row = h1 & 0b111;
203        let adc : u16 = ((h2 as u16 & 0b00111111) << 5) | (h1 >> 3) as u16;
204        let mut hit = TrackerHit::new();
205        hit.layer   = daq_event.layer - 128;
206        hit.row     = row    ;
207        hit.module  = module ;
208        hit.channel = channel;
209        hit.adc     = adc    ;
210        hit.asic_event_code   = asic_event_code;
211        daq_event.hits.push(hit);
212        ev.n_hits += 1; 
213      }
214      ev.events.push(daq_event);
215    }
216  }
217  
218  fn to_bytestream(&self) -> Vec<u8> {
219    let mut stream = self.daq_header.to_bytestream();
220    stream.extend_from_slice(&self.run_id.to_le_bytes());
221    for ev in &self.events {
222      stream.push(ev.hits.len() as u8);
223      stream.push(ev.flags1);
224      stream.extend_from_slice(&ev.event_id.to_le_bytes());
225      stream.extend_from_slice(&ev.event_time32.to_le_bytes());
226      stream.extend_from_slice(&ev.event_time16.to_le_bytes()); 
227      for h in &ev.hits {
228        let h0 = ((h.module << 5) | (h.channel & 0b11111)) as u8;
229        let h1_adc = h.adc & 0b11111;
230        let h2_adc = h.adc >> 5;
231        let h1 = ((h1_adc << 3) as u8) | (h.row as u8 & 0b111);
232        let h2 = (h.asic_event_code << 6) as u16 | h2_adc;
233        stream.push(h0);
234        stream.push(h1);
235        stream.push(h2 as u8);
236      }
237    }
238    stream
239  }
240  
241}
242
243impl TelemetryPackable for TrackerDAQEventPacket {
244  const TEL_PACKET_TYPE : TelemetryPacketType = TelemetryPacketType::Tracker;
245}
246
247impl fmt::Display for TrackerDAQEventPacket {
248  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
249    let mut repr = String::from("<TrackerDAQEventPacket:");
250    repr += &(format!("\n  TrackerHeader       : {}", self.daq_header));
251    repr += &(format!("\n  Run ID/Run ID (old) : {} {}", self.run_id, self.run_id_old));
252    repr += &(format!("\n  - N DAQ ev., N Hits : {} {}", self.events.len(), self.n_hits));
253    for daq in &self.events {
254      repr += &(format!("\n  {}", daq));
255    }
256    repr += "\n";
257    write!(f, "{}", repr)
258  }
259}
260
261#[cfg(feature="random")]
262impl FromRandom for TrackerDAQEventPacket {
263
264  fn from_random() -> Self {
265    let mut packet    = Self::new();
266    let mut rng       = rand::rng();
267    packet.header     = TelemetryPacketHeader::from_random();
268    packet.daq_header = TrackerHeader::from_random();
269    packet.events     = Vec::<TrackerDAQEvent>::new();
270    packet.run_id     = rng.random::<u16>();
271    //packet.run_id_old = rng.random::<u8>();
272    let n_events : u8 = rng.random_range(0..6);
273    //let n_events : u8 = 1;
274    for _ in 0..n_events {
275      let mut ev = TrackerDAQEvent::from_random();
276      ev.layer   = packet.daq_header.sys_id;
277      for h in &mut ev.hits {
278        //h.adc = h.adc & 0b11111;
279        h.oscillator = 0;
280        h.layer = ev.layer - 128;
281      }
282      packet.events.push(ev);
283    }
284    packet
285  }
286}
287
288#[test]
289#[cfg(feature="random")]
290fn serialize_deserialize_trackerdaqeventpacket() {
291  for _ in 0..100 {
292    let packet = TrackerDAQEventPacket::from_random();  
293    let stream = packet.to_bytestream();
294    let test   = TrackerDAQEventPacket::from_bytestream(&stream, &mut 0).unwrap();
295    assert_eq!(packet.run_id    , test.run_id); 
296    assert_eq!(packet.run_id_old, test.run_id_old); 
297    assert_eq!(packet.events.len(),   test.events.len());
298    assert_eq!(packet.daq_header, test.daq_header);
299    //println!("Have {} events!", packet.events.len());
300    for k in 0..packet.events.len() {
301      assert_eq!(packet.events[k],test.events[k]);
302    }
303    //println!("-- Success! --");
304  }
305} 
306
307#[test]
308#[cfg(feature="random")]
309fn serialize_deserialize_trackerdaqemptyeventpacket() {
310  for _ in 0..100 {
311    let pre_packet = TrackerDAQEventPacket::from_random(); 
312    let packet = pre_packet.emit_empty();
313    let stream = packet.to_bytestream();
314    let test   = TrackerDAQEventPacket::from_bytestream(&stream, &mut 0).unwrap();
315    assert_eq!(packet.run_id    , test.run_id); 
316    assert_eq!(packet.run_id_old, test.run_id_old); 
317    assert_eq!(packet.events.len(),   test.events.len());
318    assert_eq!(packet.daq_header, test.daq_header);
319    //println!("Have {} events!", packet.events.len());
320    for k in 0..packet.events.len() {
321      assert_eq!(packet.events[k],test.events[k]);
322    }
323    //println!("-- Success! --");
324  }
325} 
326
327#[test]
328#[cfg(feature="random")]
329fn serialize_deserialize_trackerdaqmodifyeventpacket() {
330  for _ in 0..100 {
331    let pre_packet = TrackerDAQEventPacket::from_random(); 
332    let mut packet = pre_packet.emit_empty();
333    if pre_packet.events.len() > 0 {
334      packet.add_event(pre_packet.events[0].clone());
335    }
336    let stream = packet.to_bytestream();
337    let test   = TrackerDAQEventPacket::from_bytestream(&stream, &mut 0).unwrap();
338    assert_eq!(packet.run_id    , test.run_id); 
339    assert_eq!(packet.run_id_old, test.run_id_old); 
340    assert_eq!(packet.events.len(),   test.events.len());
341    assert_eq!(packet.daq_header, test.daq_header);
342    //println!("Have {} events!", packet.events.len());
343    for k in 0..packet.events.len() {
344      assert_eq!(packet.events[k],test.events[k]);
345    }
346    //println!("-- Success! --");
347  }
348} 
349
350#[cfg(feature="pybindings")]
351#[pymethods]
352impl TrackerDAQEventPacket {
353 
354  #[staticmethod]
355  #[pyo3(name="from_telemetrypacket")]
356  fn from_telemetrypacket_py(packet : TelemetryPacket) -> PyResult<Self> {
357    match Self::from_bytestream(&packet.payload, &mut 0) {
358      Ok(mut event) => {
359        event.header  = packet.header.clone();
360        return Ok(event);
361      }
362      Err(err) => {
363        return Err(PyValueError::new_err(err.to_string()));
364      }  
365    }
366  }
367  
368
369  #[pyo3(name="to_bytestream")]
370  fn to_bytestream_py(&self) -> Vec<u8> {
371    self.to_bytestream()
372  }
373 
374  #[staticmethod]
375  #[pyo3(name="from_bytestream")]
376  fn from_bytestream_py(stream : Vec<u8>,
377                        pos    : usize) -> PyResult<Self> {
378    let mut position = pos;
379    Ok(Self::from_bytestream(&stream, &mut position).unwrap())
380  }
381
382
383  /// Modify the event and add another TrackerDAQEvent
384  ///
385  /// WARNING: This is an advanced feature. Usually, There
386  /// is no reason to alter events
387  #[pyo3(name="add_event")]
388  fn add_event_py(&mut self, ev : TrackerDAQEvent) {
389    self.add_event(ev);
390  }
391
392  /// Create an empty copy of myself. 
393  ///
394  /// Empty in this context means no events 
395  #[pyo3(name="emit_empty")]
396  fn emit_empty_py(&self) -> Self {
397    self.emit_empty()
398  }
399
400  /// Create a telemetry packet to be send or 
401  /// written to disk
402  #[pyo3(name="pack")]
403  fn pack_py(&self) -> TelemetryPacket {
404    self.pack()
405  }
406
407  /// Remove a single TrackerDAQEvent from the 
408  /// associated list of events 
409  ///
410  /// # Arguments:
411  ///   * evid : Event ID of the event in the 
412  ///            list of associated events to 
413  ///            be removed
414  #[pyo3(name="remove_event")]
415  fn remove_event_py(&mut self, evid : u32) {
416    self.remove_event(evid);
417  }
418
419  #[getter] 
420  fn get_gcutime(&self) -> f64 {
421    self.header.get_gcutime() 
422  }
423
424  #[getter]
425  fn get_nhits(&self) -> u16 {
426    self.n_hits
427  }
428
429  #[getter]
430  #[pyo3(name="event_ids")]
431  fn get_event_ids_py(&self) -> Vec<u32> {
432    self.get_event_ids()
433  }
434  
435  /// Get a copy specific TrackerDAQEvent for a given event id
436  #[pyo3(name="get_event_for_evid")]
437  fn get_event_for_evid_py(&self, evid : u32) -> Option<TrackerDAQEvent> {
438    self.get_event_for_evid(evid)
439  }
440
441  #[getter] 
442  fn get_header(&self) -> TrackerHeader {
443    self.daq_header 
444  }
445
446  #[getter] 
447  fn get_events(&self) -> Vec<TrackerDAQEvent> {
448    self.events.clone()
449  }
450  
451  /// Return all tracker hits which belong to a certain event id
452  #[pyo3(name="get_hits_for_evid")]
453  fn get_hits_for_evid_py(&self, evid : u32) -> Vec<TrackerHit> {
454    self.get_hits_for_evid(evid).clone()
455  }
456
457  #[getter]
458  fn get_run_id(&self) -> u16 {
459    self.run_id 
460  }
461
462  #[getter]
463  fn get_run_id_old(&self) -> u8 {
464    self.run_id_old 
465  }
466}
467
468#[cfg(feature="pybindings")]
469pythonize!(TrackerDAQEventPacket);
470