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)
204 -> Result<Vec<TrackerHit>, SerializationError> {
205 let mut hits = Vec::<TrackerHit>::new();
206 match source {
207 TrackerHitSource::TelemetryEvent |
208 TrackerHitSource::Unknown => {
209 }
210 TrackerHitSource::TrackerPacket => {
211 for k in self.index.keys() {
212 if k.contains("Tracker") {
213 let pack = self.get::<TelemetryPacket>(k)?;
214 let trk = TrackerDAQEventPacket::from_telemetrypacket(&pack)?;
215 for ev in trk.events {
216 for h in ev.hits {
217 hits.push(h.clone());
218 }
219 }
220 }
221 }
222 }
223 }
224 Ok(hits)
225 }
226
227 pub fn get_telemetrypacket_gcutime_range(&self) -> Option<(f64,f64,f64)> {
228 let mut times = Vec::<f64>::new();
229 for k in self.index.keys() {
230 let f_obj_idx = self.index.get(k).unwrap();
231 if f_obj_idx.1 == CRFrameObjectType::TelemetryPacket {
232 let ts = TelemetryPacket::get_gcutime_unpacked(&self.bytestorage[f_obj_idx.0 as usize + 8..].to_vec());
234 if ts.is_ok() {
235 times.push(ts.unwrap());
236 }
237 }
238 }
239 if times.len() > 0 {
240 let min_time = times.iter().min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
241 let max_time = times.iter().max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
242 let delta = max_time - min_time;
243 return Some((*min_time,*max_time,delta));
244 }
245 None
246 }
247
248 pub fn serialize_index(&self) -> Vec<u8> {
249 let mut s_index = Vec::<u8>::new();
250 let idx_size = self.index.len() as u8;
252 s_index.push(idx_size);
253 for k in &self.index {
254 let mut s_name = Self::string_to_bytes(k.0.clone());
255 let s_pos = k.1.0.to_le_bytes();
256 s_index.append(&mut s_name);
257 s_index.extend_from_slice(&s_pos);
258 s_index.push(k.1.1 as u8);
259 }
260 s_index
261 }
262
263 pub fn string_to_bytes(value : String) -> Vec<u8> {
270 let mut stream = Vec::<u8>::new();
271 let mut payload = value.into_bytes();
272 let string_size = payload.len() as u16; stream.extend_from_slice(&string_size.to_le_bytes());
274 stream.append(&mut payload);
275 stream
276 }
277
278 pub fn parse_index(stream : &Vec<u8>, pos : &mut usize) -> HashMap<String, (u64, CRFrameObjectType)> {
279 let idx_size = parse_u8(stream, pos);
280 let mut index = HashMap::<String, (u64, CRFrameObjectType)>::new();
282 for _ in 0..idx_size as usize {
283 let name = parse_string(stream, pos);
284 let obj_pos = parse_u64(stream, pos);
285 let obj_t = CRFrameObjectType::from(stream[*pos]);
286 *pos += 1;
287 index.insert(name.to_owned(), (obj_pos, obj_t));
289 }
290 index
291 }
292
293 pub fn delete(&self, name : &str) -> Result<CRFrame, SerializationError> {
305 if !self.has(name) {
306 error!("There is no object with name {} in this frame!", name);
307 return Err(SerializationError::ObjectNotFound);
308 }
309 let mut new_frame = CRFrame::new();
310 for objname in self.index.keys() {
311 if objname == name {
312 continue;
313 }
314 let obj = self.get_fobject(&objname)?;
315 new_frame.put_fobject(obj, objname);
316 }
317 new_frame.tof_paddles = Arc::clone(&self.tof_paddles);
318 new_frame.trk_strips = Arc::clone(&self.trk_strips);
319 Ok(new_frame)
320 }
321
322
323 pub fn put<T: Serialization + Frameable>(&mut self, object : T, name : &str) {
327 let f_object = object.pack();
328 self.put_fobject(f_object, name);
329 }
330
331 fn put_fobject(&mut self, object : CRFrameObject, name : &str) {
332 let pos = self.bytestorage.len() as u64;
333 self.index.insert(name.to_string(), (pos, object.ftype));
334 let mut stream = object.to_bytestream();
335 self.bytestorage.append(&mut stream);
339 }
340
341 pub fn has(&self, name : &str) -> bool {
346 self.index.contains_key(name)
347 }
348
349 pub fn get_telemetry_event_names(&self) -> Vec<&str> {
351 let mut tevents = Vec::<&str>::new();
352 for k in MERGED_EVENT_TYPES {
353 if self.has(k) {
354 tevents.push(k);
355 }
356 }
357 tevents
358 }
359
360 pub fn get_fobject(&self, name : &str) -> Result<CRFrameObject, SerializationError> {
367 let mut pos : usize;
368 match self.index.get(name) {
369 None => {
370 error!("There is no object with name {} in this frame!", name);
371 return Err(SerializationError::ObjectNotFound);
372 }
373 Some(meta) => {
374 pos = meta.0 as usize;
376 }
377 }
378 let cr_object = CRFrameObject::from_bytestream(&self.bytestorage, &mut pos)?;
379 Ok(cr_object)
380 }
381
382 pub fn get_first_gcutime(&self) -> Option<f64> {
386 let times = self.get_telemetrypacket_gcutime_range()?;
387 Some(times.0)
388 }
389
390 pub fn get<T : Serialization + Frameable>(&self, name : &str) -> Result<T, SerializationError> {
391
392 let mut pos : usize;
394 match self.index.get(name) {
395 None => {
396 return Err(SerializationError::ValueNotFound);
397 }
398 Some(meta) => {
399 pos = meta.0 as usize;
401 }
402 }
403 let cr_object = CRFrameObject::from_bytestream(&self.bytestorage, &mut pos)?;
404 let result = cr_object.extract::<T>()?;
405 Ok(result)
406 }
407
408 pub fn show_frame(&self) -> String {
410 let mut repr = String::from("");
411 for k in &self.index {
412 repr += &(format!("\n -- {}@{}:{} --", k.0, k.1.0, k.1.1));
413 }
421 repr
422 }
423}
424
425impl Default for CRFrame {
426 fn default() -> Self {
427 Self::new()
428 }
429}
430
431impl Serialization for CRFrame {
432 fn from_bytestream(stream : &Vec<u8>,
434 pos : &mut usize)
435 -> Result<Self, SerializationError> {
436 if stream.len() < 2 {
437 return Err(SerializationError::HeadInvalid {});
438 }
439 let head = parse_u16(stream, pos);
440 if Self::HEAD != head {
441 error!("FrameObject does not start with HEAD signature");
442 return Err(SerializationError::HeadInvalid {});
443 }
444 let fr_size = parse_u64(stream, pos) as usize;
445 *pos += fr_size as usize;
446 let tail = parse_u16(stream, pos);
447 if Self::TAIL != tail {
448 error!("FrameObject does not end with TAIL signature");
449 return Err(SerializationError::TailInvalid {});
450 }
451 *pos -= fr_size - 2; let mut frame = CRFrame::new();
453 let size = parse_u64(stream, pos) as usize;
454 frame.index = Self::parse_index(stream, pos);
455 frame.bytestorage = stream[*pos..*pos + size].to_vec();
456 Ok(frame)
457 }
458
459 fn to_bytestream(&self) -> Vec<u8> {
461 let mut stream = Vec::<u8>::new();
462 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
463 let mut s_index = self.serialize_index();
464 let size = self.bytestorage.len() as u64 + s_index.len() as u64;
466 stream.extend_from_slice(&size.to_le_bytes());
468 stream.append(&mut s_index);
469 stream.extend_from_slice(&self.bytestorage.as_slice());
470 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
471 stream
472 }
473}
474
475impl fmt::Display for CRFrame {
476 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
477 let mut repr = String::from("<CRFrame : ");
478 repr += &self.show_frame();
479 repr += "\n>";
480 write!(f, "{}", repr)
481 }
482}
483
484#[cfg(feature="pybindings")]
487#[pymethods]
488impl CRFrame {
489
490 #[pyo3(name="delete")]
502 fn delete_py(&self, name : &str) -> PyResult<Self> {
503 if !self.has(name) {
504 let msg = format!("Frame does not contain {}", name);
505 return Err(PyKeyError::new_err(msg));
506 }
507 match self.delete(name) {
508 Ok(new_frame) => {
509 Ok(new_frame)
510 }
511 Err(err) => {
512 return Err(PyValueError::new_err(err.to_string()));
513 }
514 }
515 }
516
517 #[getter]
518 fn telemetry_event_names(&self) -> Vec<&str> {
520 self.get_telemetry_event_names()
521 }
522
523 #[pyo3(name="get_first_gcutime")]
529 fn get_first_gcutime_py(&self) -> Option<f64> {
530 self.get_first_gcutime()
531 }
532
533 #[getter]
534 fn get_n_objects(&self) -> usize {
535 self.index.len()
536 }
537
538 #[pyo3(name="get_telemetrypacket_gcutime_range")]
539 fn get_telemetrypacket_gcutime_range_py(&self) -> Option<(f64,f64,f64)> {
540 self.get_telemetrypacket_gcutime_range()
541 }
542
543
544 #[pyo3(signature = (packet, name = None, record_timestamp = false))]
553 fn put_telemetrypacket(&mut self, packet : TelemetryPacket, name : Option<&str>, record_timestamp : bool) -> PyResult<()> {
554 if record_timestamp {
555 self.timestamp = Some(packet.header.get_gcutime());
556 }
557 if let Some(p_name) = name {
558 if self.has(p_name) {
559 let msg = format!("Frame already contains a TelemetryPacket named {}", p_name);
560 return Err(PyValueError::new_err(msg));
561 }
562 self.put(packet, p_name);
563 Ok(())
564 } else {
565 let name = format!("TelemetryPacketType.{}", packet.header.packet_type.as_ref());
566 let msg = format!("Frame already contains a TelemetryPacket named {}", name);
567 if self.has(&name) {
568 return Err(PyValueError::new_err(msg));
569 }
570 self.put(packet, name.as_str());
571 Ok(())
572 }
573 }
574
575 #[pyo3(signature = (packet, name = None))]
584 fn put_tofpacket(&mut self, packet : TofPacket, name : Option<&str>) -> PyResult<()> {
585 if let Some(p_name) = name {
586 if self.has(p_name) {
587 let msg = format!("Frame already contains a TofPacket named {}", p_name);
588 return Err(PyValueError::new_err(msg));
589 }
590 self.put(packet, p_name);
591 Ok(())
592 } else {
593 let name = format!("TofPacketType.{}", packet.packet_type.as_ref());
594 let msg = format!("Frame already contains a TofPacket named {}", name);
595 if self.has(&name) {
596 return Err(PyValueError::new_err(msg));
597 }
598 self.put(packet, name.as_str());
599 Ok(())
600 }
601 }
602
603 fn get_tofpacket(&mut self, name : &str) -> PyResult<TofPacket> {
609 let packet = self.get::<TofPacket>(name).unwrap();
610 Ok(packet)
611 }
612
613 fn get_telemetrypacket(&mut self, name : &str) -> PyResult<TelemetryPacket> {
620 let packet = self.get::<TelemetryPacket>(name).unwrap();
621 Ok(packet)
622 }
623
624 fn get_mctree(&mut self, name : &str) -> PyResult<McEvent> {
625 let event = self.get::<McEvent>(name).unwrap();
626 Ok(event)
627 }
628
629 fn get_tofevent(&mut self, name : &str) -> PyResult<TofEvent> {
631 let packet = self.get::<TofPacket>(name).unwrap();
632 let mut event = packet.unpack::<TofEvent>().unwrap();
633 event.set_paddles(&self.tof_paddles);
634 Ok(event)
637 }
638
639 #[pyo3(signature = (name = None, always_exclude = None))]
659 fn get_telemetryevent(&mut self, name : Option<&str>, always_exclude : Option<Vec<String>>) -> PyResult<Option<TelemetryEvent>> {
660 let name_ : &str;
661 match name {
662 None => {
663 let mut names = self.get_telemetry_event_names();
664 if let Some(to_exclude) = always_exclude {
665 let exclusion_set: HashSet<_> = to_exclude.into_iter().collect();
666 names.retain(|&x| !exclusion_set.contains(x));
667 }
668 if names.len() != 1 {
669 let msg = format!("Frame contains multiple or no TelemetryEvents {:?}. Please specify a name!", names);
670 return Err(PyValueError::new_err(msg));
671 } else {
672 name_ = names[0];
673 }
674 }
675 Some(n_) => {
676 name_ = n_;
677 }
678 }
679 let packet = self.get::<TelemetryPacket>(name_).unwrap();
681 match packet.unpack::<TelemetryEvent>() {
682 Err(err) => {
683 return Err(PyValueError::new_err(err.to_string()));
684 }
685 Ok(mut event) => {
686 event.header = packet.header;
687 event.hydrate(&self.tof_paddles, &self.trk_strips);
688 if self.do_trk_calib {
689 error!("Tracker calibration not implemented!");
695 }
696 Ok(Some(event))
697 }
698 }
699 }
700
701 #[pyo3(name="has")]
706 fn has_py(&self, name : &str) -> bool {
707 self.has(name)
708 }
709
710 #[getter]
711 fn index(&self) -> HashMap<String, (u64, CRFrameObjectType)> {
712 self.index.clone()
713 }
714
715 #[getter]
716 #[pyo3(name="do_trk_calib")]
717 fn do_trk_calib_py(&self) -> bool {
718 self.do_trk_calib
719 }
720
721 #[pyo3(name="get_tracker_hitseries")]
722 fn get_tracker_hitseries_py(&self) -> Vec<TrackerHit> {
723 self.get_tracker_hitseries(TrackerHitSource::TrackerPacket).unwrap()
724 }
725
726}
727
728
729
730#[cfg(feature="pybindings")]
731pythonize!(CRFrame);