1use crate::prelude::*;
7
8#[cfg_attr(feature = "pybindings", pyclass(eq, eq_int))]
12#[derive(Debug, Copy, Clone, PartialEq,FromRepr, AsRefStr, EnumIter)]
13#[repr(u8)]
14pub enum CRFrameObjectType {
15 Unknown = 0u8,
16 TofPacket = 10u8,
17 TelemetryPacket = 20u8,
18 McTree = 30u8,
19}
20
21expand_and_test_enum!(CRFrameObjectType, test_crframeobjecttype_repr);
22
23pub const MERGED_EVENT_TYPES : [&'static str;4] = [
29 "TelemetryPacketType.NoGapsTriggerEvent",
30 "TelemetryPacketType.BoringEvent",
31 "TelemetryPacketType.InterestingEvent",
32 "TelemetryPacketType.NoTofDataEvent"];
33
34#[cfg(feature="pybindings")]
38#[pyfunction]
39pub fn get_all_telemetry_event_names() -> [&'static str;4] {
40 MERGED_EVENT_TYPES
41}
42
43#[derive(Debug, Clone)]
53#[cfg_attr(feature="pybindings", pyclass)]
54pub struct CRFrameObject {
55 pub version : u8,
56 pub ftype : CRFrameObjectType,
57 pub payload : Vec<u8>,
60}
61
62impl CRFrameObject {
63 pub fn new() -> Self {
64 Self {
65 version : 0,
66 ftype : CRFrameObjectType::Unknown,
67 payload : Vec::<u8>::new(),
68 }
69 }
70
71 pub fn size(&self) -> usize {
74 let size = self.payload.len() + 2 + 4;
75 size
76 }
77
78 pub fn extract<T>(&self) -> Result<T, SerializationError>
80 where T: Frameable + Serialization {
81 if T::CRFRAMEOBJECT_TYPE != self.ftype {
82 error!("This bytestream is not for a {} packet!", self.ftype);
83 return Err(SerializationError::IncorrectPacketType);
84 }
85 let unpacked : T = T::from_bytestream(&self.payload, &mut 0)?;
86 Ok(unpacked)
87 }
88}
89
90impl Serialization for CRFrameObject {
91
92 fn from_bytestream(stream : &Vec<u8>,
94 pos : &mut usize)
95 -> Result<Self, SerializationError>
96 where Self : Sized {
97 if stream.len() < 2 {
98 return Err(SerializationError::HeadInvalid {});
99 }
100 let head = parse_u16(stream, pos);
101 if Self::HEAD != head {
102 error!("Packet does not start with CRHEAD signature");
103 return Err(SerializationError::HeadInvalid {});
104 }
105 let mut f_obj = CRFrameObject::new();
106 f_obj.version = parse_u8(stream, pos);
107 let ftype = parse_u8(stream, pos);
108 f_obj.ftype = CRFrameObjectType::from(ftype);
109 let payload_size = parse_u32(stream, pos);
110 *pos += payload_size as usize;
111 let tail = parse_u16(stream, pos);
112 if Self::TAIL != tail {
113 error!("Packet does not end with CRTAIL signature");
114 return Err(SerializationError::TailInvalid {});
115 }
116 *pos -= 2; *pos -= payload_size as usize;
118 f_obj.payload.extend_from_slice(&stream[*pos..*pos+payload_size as usize]);
119 Ok(f_obj)
120 }
121
122 fn to_bytestream(&self) -> Vec<u8> {
124 let mut stream = Vec::<u8>::new();
125 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
126 stream.push(self.version);
127 stream.push(self.ftype as u8);
128 let size = self.payload.len() as u32;
129 stream.extend_from_slice(&size.to_le_bytes());
130 stream.extend_from_slice(&self.payload.as_slice());
131 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
132 stream
133 }
134}
135
136impl fmt::Display for CRFrameObject {
137 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138 let p_len = self.payload.len();
139 write!(f, "<CRFrameObject: type {:?}, payload [ {} {} {} {} .. {} {} {} {}] of size {} >",
140 self.ftype,
141 self.payload[0], self.payload[1], self.payload[2], self.payload[3],
142 self.payload[p_len-4], self.payload[p_len-3], self.payload[p_len - 2], self.payload[p_len-1], p_len )
143 }
144}
145
146#[cfg(feature="pybindings")]
149pythonize!(CRFrameObject);
150
151#[derive(Debug, Clone)]
160#[cfg_attr(feature="pybindings", pyclass)]
161pub struct CRFrame {
162 pub index : HashMap<String, (u64, CRFrameObjectType)>,
166 pub bytestorage : Vec<u8>,
167 pub tof_paddles : Arc<HashMap<u8, TofPaddle>>,
168 pub trk_strips : Arc<HashMap<u32, TrackerStrip>>,
169 pub trk_masks : Arc<HashMap<u32, TrackerStripMask>>,
170 pub trk_ped : Arc<HashMap<u32, TrackerStripPedestal>>,
171 pub trk_tf : Arc<HashMap<u32, TrackerStripTransferFunction>>,
172 pub trk_cmn : Arc<HashMap<u32, TrackerStripCmnNoise>>,
173 pub do_trk_calib : bool,
175 pub subtract_trk_cmn : bool,
177 pub timestamp : Option<f64>,
181}
182
183impl CRFrame {
184
185 pub fn new() -> Self {
186 Self {
187 index : HashMap::<String, (u64, CRFrameObjectType)>::new(),
188 bytestorage : Vec::<u8>::new(),
189 tof_paddles : Arc::new(HashMap::<u8, TofPaddle>::new()),
190 trk_strips : Arc::new(HashMap::<u32, TrackerStrip>::new()),
191 trk_masks : Arc::new(HashMap::<u32, TrackerStripMask>::new()),
192 trk_ped : Arc::new(HashMap::<u32, TrackerStripPedestal>::new()),
193 trk_tf : Arc::new(HashMap::<u32, TrackerStripTransferFunction>::new()),
194 trk_cmn : Arc::new(HashMap::<u32, TrackerStripCmnNoise>::new()),
195 do_trk_calib : false,
196 subtract_trk_cmn : false,
197 timestamp : None
198 }
199 }
200
201 pub fn get_tracker_hitseries(&self, source : TrackerHitSource, name : Option<String>)
210 -> Result<Vec<TrackerHit>, SerializationError> {
211 let mut hits = Vec::<TrackerHit>::new();
212 let mut tracker_hit_name = String::from("Tracker");
213 if name.is_some() {
214 tracker_hit_name = name.unwrap();
215 }
216 match source {
217 TrackerHitSource::TelemetryEvent |
218 TrackerHitSource::Unknown => {
219 }
220 TrackerHitSource::TrackerPacket => {
221 for k in self.index.keys() {
222 if k.contains(&tracker_hit_name) {
223 let pack = self.get::<TelemetryPacket>(k)?;
224 let trk = TrackerDAQEventPacket::from_telemetrypacket(&pack)?;
225 for ev in trk.events {
226 for h in ev.hits {
227 hits.push(h.clone());
228 }
229 }
230 }
231 }
232 }
233 }
234 Ok(hits)
235 }
236
237 pub fn get_telemetrypacket_gcutime_range(&self) -> Option<(f64,f64,f64)> {
238 let mut times = Vec::<f64>::new();
239 for k in self.index.keys() {
240 let f_obj_idx = self.index.get(k).unwrap();
241 if f_obj_idx.1 == CRFrameObjectType::TelemetryPacket {
242 let ts = TelemetryPacket::get_gcutime_unpacked(&self.bytestorage[f_obj_idx.0 as usize + 8..].to_vec());
244 if ts.is_ok() {
245 times.push(ts.unwrap());
246 }
247 }
248 }
249 if times.len() > 0 {
250 let min_time = times.iter().min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
251 let max_time = times.iter().max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
252 let delta = max_time - min_time;
253 return Some((*min_time,*max_time,delta));
254 }
255 None
256 }
257
258 pub fn serialize_index(&self) -> Vec<u8> {
259 let mut s_index = Vec::<u8>::new();
260 let idx_size = self.index.len() as u8;
262 s_index.push(idx_size);
263 for k in &self.index {
264 let mut s_name = Self::string_to_bytes(k.0.clone());
265 let s_pos = k.1.0.to_le_bytes();
266 s_index.append(&mut s_name);
267 s_index.extend_from_slice(&s_pos);
268 s_index.push(k.1.1 as u8);
269 }
270 s_index
271 }
272
273 pub fn string_to_bytes(value : String) -> Vec<u8> {
280 let mut stream = Vec::<u8>::new();
281 let mut payload = value.into_bytes();
282 let string_size = payload.len() as u16; stream.extend_from_slice(&string_size.to_le_bytes());
284 stream.append(&mut payload);
285 stream
286 }
287
288 pub fn parse_index(stream : &Vec<u8>, pos : &mut usize) -> HashMap<String, (u64, CRFrameObjectType)> {
289 let idx_size = parse_u8(stream, pos);
290 let mut index = HashMap::<String, (u64, CRFrameObjectType)>::new();
292 for _ in 0..idx_size as usize {
293 let name = parse_string(stream, pos);
294 let obj_pos = parse_u64(stream, pos);
295 let obj_t = CRFrameObjectType::from(stream[*pos]);
296 *pos += 1;
297 index.insert(name.to_owned(), (obj_pos, obj_t));
299 }
300 index
301 }
302
303 pub fn delete(&self, name : &str) -> Result<CRFrame, SerializationError> {
315 if !self.has(name) {
316 error!("There is no object with name {} in this frame!", name);
317 return Err(SerializationError::ObjectNotFound);
318 }
319 let mut new_frame = CRFrame::new();
320 for objname in self.index.keys() {
321 if objname == name {
322 continue;
323 }
324 let obj = self.get_fobject(&objname)?;
325 new_frame.put_fobject(obj, objname);
326 }
327 new_frame.tof_paddles = Arc::clone(&self.tof_paddles);
328 new_frame.trk_strips = Arc::clone(&self.trk_strips);
329 Ok(new_frame)
330 }
331
332
333 pub fn put<T: Serialization + Frameable>(&mut self, object : T, name : &str) {
337 let f_object = object.pack();
338 self.put_fobject(f_object, name);
339 }
340
341 fn put_fobject(&mut self, object : CRFrameObject, name : &str) {
342 let pos = self.bytestorage.len() as u64;
343 self.index.insert(name.to_string(), (pos, object.ftype));
344 let mut stream = object.to_bytestream();
345 self.bytestorage.append(&mut stream);
349 }
350
351 pub fn has(&self, name : &str) -> bool {
356 self.index.contains_key(name)
357 }
358
359 pub fn get_telemetry_event_names(&self) -> Vec<&str> {
361 let mut tevents = Vec::<&str>::new();
362 for k in MERGED_EVENT_TYPES {
363 if self.has(k) {
364 tevents.push(k);
365 }
366 }
367 tevents
368 }
369
370 pub fn get_fobject(&self, name : &str) -> Result<CRFrameObject, SerializationError> {
377 let mut pos : usize;
378 match self.index.get(name) {
379 None => {
380 error!("There is no object with name {} in this frame!", name);
381 return Err(SerializationError::ObjectNotFound);
382 }
383 Some(meta) => {
384 pos = meta.0 as usize;
386 }
387 }
388 let cr_object = CRFrameObject::from_bytestream(&self.bytestorage, &mut pos)?;
389 Ok(cr_object)
390 }
391
392 pub fn get_first_gcutime(&self) -> Option<f64> {
396 let times = self.get_telemetrypacket_gcutime_range()?;
397 Some(times.0)
398 }
399
400 pub fn get<T : Serialization + Frameable>(&self, name : &str) -> Result<T, SerializationError> {
401
402 let mut pos : usize;
404 match self.index.get(name) {
405 None => {
406 return Err(SerializationError::ValueNotFound);
407 }
408 Some(meta) => {
409 pos = meta.0 as usize;
411 }
412 }
413 let cr_object = CRFrameObject::from_bytestream(&self.bytestorage, &mut pos)?;
414 let result = cr_object.extract::<T>()?;
415 Ok(result)
416 }
417
418 pub fn show_frame(&self) -> String {
420 let mut repr = String::from("");
421 for k in &self.index {
422 repr += &(format!("\n -- {}@{}:{} --", k.0, k.1.0, k.1.1));
423 }
431 repr
432 }
433}
434
435impl Default for CRFrame {
436 fn default() -> Self {
437 Self::new()
438 }
439}
440
441impl Serialization for CRFrame {
442 fn from_bytestream(stream : &Vec<u8>,
444 pos : &mut usize)
445 -> Result<Self, SerializationError> {
446 if stream.len() < 2 {
447 return Err(SerializationError::HeadInvalid {});
448 }
449 let head = parse_u16(stream, pos);
450 if Self::HEAD != head {
451 error!("FrameObject does not start with HEAD signature");
452 return Err(SerializationError::HeadInvalid {});
453 }
454 let fr_size = parse_u64(stream, pos) as usize;
455 *pos += fr_size as usize;
456 let tail = parse_u16(stream, pos);
457 if Self::TAIL != tail {
458 error!("FrameObject does not end with TAIL signature");
459 return Err(SerializationError::TailInvalid {});
460 }
461 *pos -= fr_size - 2; let mut frame = CRFrame::new();
463 let size = parse_u64(stream, pos) as usize;
464 frame.index = Self::parse_index(stream, pos);
465 frame.bytestorage = stream[*pos..*pos + size].to_vec();
466 Ok(frame)
467 }
468
469 fn to_bytestream(&self) -> Vec<u8> {
471 let mut stream = Vec::<u8>::new();
472 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
473 let mut s_index = self.serialize_index();
474 let size = self.bytestorage.len() as u64 + s_index.len() as u64;
476 stream.extend_from_slice(&size.to_le_bytes());
478 stream.append(&mut s_index);
479 stream.extend_from_slice(&self.bytestorage.as_slice());
480 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
481 stream
482 }
483}
484
485impl fmt::Display for CRFrame {
486 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
487 let mut repr = String::from("<CRFrame : ");
488 repr += &self.show_frame();
489 repr += "\n>";
490 write!(f, "{}", repr)
491 }
492}
493
494#[cfg(feature="pybindings")]
497#[pymethods]
498impl CRFrame {
499
500 #[pyo3(name="delete")]
512 fn delete_py(&self, name : &str) -> PyResult<Self> {
513 if !self.has(name) {
514 let msg = format!("Frame does not contain {}", name);
515 return Err(PyKeyError::new_err(msg));
516 }
517 match self.delete(name) {
518 Ok(new_frame) => {
519 Ok(new_frame)
520 }
521 Err(err) => {
522 return Err(PyValueError::new_err(err.to_string()));
523 }
524 }
525 }
526
527 #[getter]
528 fn telemetry_event_names(&self) -> Vec<&str> {
530 self.get_telemetry_event_names()
531 }
532
533 #[pyo3(name="get_first_gcutime")]
539 fn get_first_gcutime_py(&self) -> Option<f64> {
540 self.get_first_gcutime()
541 }
542
543 #[getter]
544 fn get_n_objects(&self) -> usize {
545 self.index.len()
546 }
547
548 #[pyo3(name="get_telemetrypacket_gcutime_range")]
549 fn get_telemetrypacket_gcutime_range_py(&self) -> Option<(f64,f64,f64)> {
550 self.get_telemetrypacket_gcutime_range()
551 }
552
553
554 #[pyo3(signature = (packet, name = None, record_timestamp = false))]
563 fn put_telemetrypacket(&mut self, packet : TelemetryPacket, name : Option<&str>, record_timestamp : bool) -> PyResult<()> {
564 if record_timestamp {
565 self.timestamp = Some(packet.header.get_gcutime());
566 }
567 if let Some(p_name) = name {
568 if self.has(p_name) {
569 let msg = format!("Frame already contains a TelemetryPacket named {}", p_name);
570 return Err(PyValueError::new_err(msg));
571 }
572 self.put(packet, p_name);
573 Ok(())
574 } else {
575 let name = format!("TelemetryPacketType.{}", packet.header.packet_type.as_ref());
576 let msg = format!("Frame already contains a TelemetryPacket named {}", name);
577 if self.has(&name) {
578 return Err(PyValueError::new_err(msg));
579 }
580 self.put(packet, name.as_str());
581 Ok(())
582 }
583 }
584
585 #[pyo3(signature = (packet, name = None))]
594 fn put_tofpacket(&mut self, packet : TofPacket, name : Option<&str>) -> PyResult<()> {
595 if let Some(p_name) = name {
596 if self.has(p_name) {
597 let msg = format!("Frame already contains a TofPacket named {}", p_name);
598 return Err(PyValueError::new_err(msg));
599 }
600 self.put(packet, p_name);
601 Ok(())
602 } else {
603 let name = format!("TofPacketType.{}", packet.packet_type.as_ref());
604 let msg = format!("Frame already contains a TofPacket named {}", name);
605 if self.has(&name) {
606 return Err(PyValueError::new_err(msg));
607 }
608 self.put(packet, name.as_str());
609 Ok(())
610 }
611 }
612
613 fn get_tofpacket(&mut self, name : &str) -> PyResult<TofPacket> {
619 let packet = self.get::<TofPacket>(name).unwrap();
620 Ok(packet)
621 }
622
623 fn get_telemetrypacket(&mut self, name : &str) -> PyResult<TelemetryPacket> {
630 let packet = self.get::<TelemetryPacket>(name).unwrap();
631 Ok(packet)
632 }
633
634 fn get_mctree(&mut self, name : &str) -> PyResult<McEvent> {
635 let event = self.get::<McEvent>(name).unwrap();
636 Ok(event)
637 }
638
639 fn get_tofevent(&mut self, name : &str) -> PyResult<TofEvent> {
641 let packet = self.get::<TofPacket>(name).unwrap();
642 let mut event = packet.unpack::<TofEvent>().unwrap();
643 event.set_paddles(&self.tof_paddles);
644 Ok(event)
647 }
648
649 #[pyo3(signature = (name = None, always_exclude = None))]
669 fn get_telemetryevent(&mut self, name : Option<&str>, always_exclude : Option<Vec<String>>) -> PyResult<Option<TelemetryEvent>> {
670 let name_ : &str;
671 match name {
672 None => {
673 let mut names = self.get_telemetry_event_names();
674 if let Some(to_exclude) = always_exclude {
675 let exclusion_set: HashSet<_> = to_exclude.into_iter().collect();
676 names.retain(|&x| !exclusion_set.contains(x));
677 }
678 if names.len() != 1 {
679 let msg = format!("Frame contains multiple or no TelemetryEvents {:?}. Please specify a name!", names);
680 return Err(PyValueError::new_err(msg));
681 } else {
682 name_ = names[0];
683 }
684 }
685 Some(n_) => {
686 name_ = n_;
687 }
688 }
689 let packet = self.get::<TelemetryPacket>(name_).unwrap();
691 match packet.unpack::<TelemetryEvent>() {
692 Err(err) => {
693 return Err(PyValueError::new_err(err.to_string()));
694 }
695 Ok(mut event) => {
696 event.header = packet.header;
697 event.hydrate(&self.tof_paddles, &self.trk_strips);
698 if self.do_trk_calib {
699 error!("Tracker calibration not implemented!");
705 }
706 Ok(Some(event))
707 }
708 }
709 }
710
711 #[pyo3(name="has")]
716 fn has_py(&self, name : &str) -> bool {
717 self.has(name)
718 }
719
720 #[getter]
721 fn index(&self) -> HashMap<String, (u64, CRFrameObjectType)> {
722 self.index.clone()
723 }
724
725 #[getter]
726 #[pyo3(name="do_trk_calib")]
727 fn do_trk_calib_py(&self) -> bool {
728 self.do_trk_calib
729 }
730
731 #[pyo3(name="get_tracker_hitseries")]
732 #[pyo3(signature = (name = None))]
733 fn get_tracker_hitseries_py(&self, name : Option<String>) -> Vec<TrackerHit> {
734 self.get_tracker_hitseries(TrackerHitSource::TrackerPacket, name).unwrap()
735 }
736
737}
738
739
740
741#[cfg(feature="pybindings")]
742pythonize!(CRFrame);