gondola_core/io/caraspace/
frame.rs1use 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}
19
20expand_and_test_enum!(CRFrameObjectType, test_crframeobjecttype_repr);
21
22pub const MERGED_EVENT_TYPES : [&'static str;4] = [
28 "TelemetryPacketType.NoGapsTriggerEvent",
29 "TelemetryPacketType.BoringEvent",
30 "TelemetryPacketType.InterestingEvent",
31 "TelemetryPacketType.NoTofDataEvent"];
32
33#[cfg(feature="pybindings")]
37#[pyfunction]
38pub fn get_all_telemetry_event_names() -> [&'static str;4] {
39 MERGED_EVENT_TYPES
40}
41
42#[derive(Debug, Clone)]
52#[cfg_attr(feature="pybindings", pyclass)]
53pub struct CRFrameObject {
54 pub version : u8,
55 pub ftype : CRFrameObjectType,
56 pub payload : Vec<u8>,
59}
60
61impl CRFrameObject {
62 pub fn new() -> Self {
63 Self {
64 version : 0,
65 ftype : CRFrameObjectType::Unknown,
66 payload : Vec::<u8>::new(),
67 }
68 }
69
70 pub fn size(&self) -> usize {
73 let size = self.payload.len() + 2 + 4;
74 size
75 }
76
77 pub fn extract<T>(&self) -> Result<T, SerializationError>
79 where T: Frameable + Serialization {
80 if T::CRFRAMEOBJECT_TYPE != self.ftype {
81 error!("This bytestream is not for a {} packet!", self.ftype);
82 return Err(SerializationError::IncorrectPacketType);
83 }
84 let unpacked : T = T::from_bytestream(&self.payload, &mut 0)?;
85 Ok(unpacked)
86 }
87}
88
89impl Serialization for CRFrameObject {
90
91 fn from_bytestream(stream : &Vec<u8>,
93 pos : &mut usize)
94 -> Result<Self, SerializationError>
95 where Self : Sized {
96 if stream.len() < 2 {
97 return Err(SerializationError::HeadInvalid {});
98 }
99 let head = parse_u16(stream, pos);
100 if Self::HEAD != head {
101 error!("Packet does not start with CRHEAD signature");
102 return Err(SerializationError::HeadInvalid {});
103 }
104 let mut f_obj = CRFrameObject::new();
105 f_obj.version = parse_u8(stream, pos);
106 let ftype = parse_u8(stream, pos);
107 f_obj.ftype = CRFrameObjectType::from(ftype);
108 let payload_size = parse_u32(stream, pos);
109 *pos += payload_size as usize;
110 let tail = parse_u16(stream, pos);
111 if Self::TAIL != tail {
112 error!("Packet does not end with CRTAIL signature");
113 return Err(SerializationError::TailInvalid {});
114 }
115 *pos -= 2; *pos -= payload_size as usize;
117 f_obj.payload.extend_from_slice(&stream[*pos..*pos+payload_size as usize]);
118 Ok(f_obj)
119 }
120
121 fn to_bytestream(&self) -> Vec<u8> {
123 let mut stream = Vec::<u8>::new();
124 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
125 stream.push(self.version);
126 stream.push(self.ftype as u8);
127 let size = self.payload.len() as u32;
128 stream.extend_from_slice(&size.to_le_bytes());
129 stream.extend_from_slice(&self.payload.as_slice());
130 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
131 stream
132 }
133}
134
135impl fmt::Display for CRFrameObject {
136 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137 let p_len = self.payload.len();
138 write!(f, "<CRFrameObject: type {:?}, payload [ {} {} {} {} .. {} {} {} {}] of size {} >",
139 self.ftype,
140 self.payload[0], self.payload[1], self.payload[2], self.payload[3],
141 self.payload[p_len-4], self.payload[p_len-3], self.payload[p_len - 2], self.payload[p_len-1], p_len )
142 }
143}
144
145#[cfg(feature="pybindings")]
148pythonize!(CRFrameObject);
149
150#[derive(Debug, Clone)]
159#[cfg_attr(feature="pybindings", pyclass)]
160pub struct CRFrame {
161 pub index : HashMap<String, (u64, CRFrameObjectType)>,
165 pub bytestorage : Vec<u8>,
166 pub tof_paddles : Arc<HashMap<u8, TofPaddle>>,
167 pub trk_strips : Arc<HashMap<u32, TrackerStrip>>,
168 pub trk_masks : Arc<HashMap<u32, TrackerStripMask>>,
169 pub trk_ped : Arc<HashMap<u32, TrackerStripPedestal>>,
170 pub trk_tf : Arc<HashMap<u32, TrackerStripTransferFunction>>,
171 pub trk_cmn : Arc<HashMap<u32, TrackerStripCmnNoise>>,
172 pub do_trk_calib : bool,
174 pub subtract_trk_cmn : bool,
176}
177
178impl CRFrame {
179
180 pub fn new() -> Self {
181 Self {
182 index : HashMap::<String, (u64, CRFrameObjectType)>::new(),
183 bytestorage : Vec::<u8>::new(),
184 tof_paddles : Arc::new(HashMap::<u8, TofPaddle>::new()),
185 trk_strips : Arc::new(HashMap::<u32, TrackerStrip>::new()),
186 trk_masks : Arc::new(HashMap::<u32, TrackerStripMask>::new()),
187 trk_ped : Arc::new(HashMap::<u32, TrackerStripPedestal>::new()),
188 trk_tf : Arc::new(HashMap::<u32, TrackerStripTransferFunction>::new()),
189 trk_cmn : Arc::new(HashMap::<u32, TrackerStripCmnNoise>::new()),
190 do_trk_calib : false,
191 subtract_trk_cmn : false,
192 }
193 }
194
195 pub fn serialize_index(&self) -> Vec<u8> {
196 let mut s_index = Vec::<u8>::new();
197 let idx_size = self.index.len() as u8;
199 s_index.push(idx_size);
200 for k in &self.index {
201 let mut s_name = Self::string_to_bytes(k.0.clone());
202 let s_pos = k.1.0.to_le_bytes();
203 s_index.append(&mut s_name);
204 s_index.extend_from_slice(&s_pos);
205 s_index.push(k.1.1 as u8);
206 }
207 s_index
208 }
209
210 fn string_to_bytes(value : String) -> Vec<u8> {
217 let mut stream = Vec::<u8>::new();
218 let mut payload = value.into_bytes();
219 let string_size = payload.len() as u16; stream.extend_from_slice(&string_size.to_le_bytes());
221 stream.append(&mut payload);
222 stream
223 }
224
225 pub fn parse_index(stream : &Vec<u8>, pos : &mut usize) -> HashMap<String, (u64, CRFrameObjectType)> {
226 let idx_size = parse_u8(stream, pos);
227 let mut index = HashMap::<String, (u64, CRFrameObjectType)>::new();
229 for _ in 0..idx_size as usize {
230 let name = parse_string(stream, pos);
231 let obj_pos = parse_u64(stream, pos);
232 let obj_t = CRFrameObjectType::from(stream[*pos]);
233 *pos += 1;
234 index.insert(name.to_owned(), (obj_pos, obj_t));
236 }
237 index
238 }
239
240 pub fn delete(&self, name : &str) -> Result<CRFrame, SerializationError> {
252 if !self.has(name) {
253 error!("There is no object with name {} in this frame!", name);
254 return Err(SerializationError::ObjectNotFound);
255 }
256 let mut new_frame = CRFrame::new();
257 for objname in self.index.keys() {
258 if objname == name {
259 continue;
260 }
261 let obj = self.get_fobject(&objname)?;
262 new_frame.put_fobject(obj, objname);
263 }
264 new_frame.tof_paddles = Arc::clone(&self.tof_paddles);
265 new_frame.trk_strips = Arc::clone(&self.trk_strips);
266 Ok(new_frame)
267 }
268
269
270 pub fn put<T: Serialization + Frameable>(&mut self, object : T, name : &str) {
274 let f_object = object.pack();
275 self.put_fobject(f_object, name);
276 }
277
278 fn put_fobject(&mut self, object : CRFrameObject, name : &str) {
279 let pos = self.bytestorage.len() as u64;
280 self.index.insert(name.to_string(), (pos, object.ftype));
281 let mut stream = object.to_bytestream();
282 self.bytestorage.append(&mut stream);
286 }
287
288 pub fn has(&self, name : &str) -> bool {
293 self.index.contains_key(name)
294 }
295
296 pub fn get_telemetry_event_names(&self) -> Vec<&str> {
298 let mut tevents = Vec::<&str>::new();
299 for k in MERGED_EVENT_TYPES {
300 if self.has(k) {
301 tevents.push(k);
302 }
303 }
304 tevents
305 }
306
307 pub fn get_fobject(&self, name : &str) -> Result<CRFrameObject, SerializationError> {
314 let mut pos : usize;
315 match self.index.get(name) {
316 None => {
317 error!("There is no object with name {} in this frame!", name);
318 return Err(SerializationError::ObjectNotFound);
319 }
320 Some(meta) => {
321 pos = meta.0 as usize;
323 }
324 }
325 let cr_object = CRFrameObject::from_bytestream(&self.bytestorage, &mut pos)?;
326 Ok(cr_object)
327 }
328
329 pub fn get<T : Serialization + Frameable>(&self, name : &str) -> Result<T, SerializationError> {
330
331 let mut pos : usize;
333 match self.index.get(name) {
334 None => {
335 return Err(SerializationError::ValueNotFound);
336 }
337 Some(meta) => {
338 pos = meta.0 as usize;
340 }
341 }
342 let cr_object = CRFrameObject::from_bytestream(&self.bytestorage, &mut pos)?;
343 let result = cr_object.extract::<T>()?;
344 Ok(result)
345 }
346
347 pub fn show_frame(&self) -> String {
349 let mut repr = String::from("");
350 for k in &self.index {
351 repr += &(format!("\n -- {}@{}:{} --", k.0, k.1.0, k.1.1));
352 }
360 repr
361 }
362}
363
364impl Default for CRFrame {
365 fn default() -> Self {
366 Self::new()
367 }
368}
369
370impl Serialization for CRFrame {
371 fn from_bytestream(stream : &Vec<u8>,
373 pos : &mut usize)
374 -> Result<Self, SerializationError> {
375 if stream.len() < 2 {
376 return Err(SerializationError::HeadInvalid {});
377 }
378 let head = parse_u16(stream, pos);
379 if Self::HEAD != head {
380 error!("FrameObject does not start with HEAD signature");
381 return Err(SerializationError::HeadInvalid {});
382 }
383 let fr_size = parse_u64(stream, pos) as usize;
384 *pos += fr_size as usize;
385 let tail = parse_u16(stream, pos);
386 if Self::TAIL != tail {
387 error!("FrameObject does not end with TAIL signature");
388 return Err(SerializationError::TailInvalid {});
389 }
390 *pos -= fr_size - 2; let mut frame = CRFrame::new();
392 let size = parse_u64(stream, pos) as usize;
393 frame.index = Self::parse_index(stream, pos);
394 frame.bytestorage = stream[*pos..*pos + size].to_vec();
395 Ok(frame)
396 }
397
398 fn to_bytestream(&self) -> Vec<u8> {
400 let mut stream = Vec::<u8>::new();
401 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
402 let mut s_index = self.serialize_index();
403 let size = self.bytestorage.len() as u64 + s_index.len() as u64;
405 stream.extend_from_slice(&size.to_le_bytes());
407 stream.append(&mut s_index);
408 stream.extend_from_slice(&self.bytestorage.as_slice());
409 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
410 stream
411 }
412}
413
414impl fmt::Display for CRFrame {
415 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
416 let mut repr = String::from("<CRFrame : ");
417 repr += &self.show_frame();
418 repr += "\n>";
419 write!(f, "{}", repr)
420 }
421}
422
423#[cfg(feature="pybindings")]
426#[pymethods]
427impl CRFrame {
428
429 #[pyo3(name="delete")]
441 pub fn delete_py(&self, name : &str) -> PyResult<Self> {
442 if !self.has(name) {
443 let msg = format!("Frame does not contain {}", name);
444 return Err(PyKeyError::new_err(msg));
445 }
446 match self.delete(name) {
447 Ok(new_frame) => {
448 Ok(new_frame)
449 }
450 Err(err) => {
451 return Err(PyValueError::new_err(err.to_string()));
452 }
453 }
454 }
455
456 #[getter]
457 fn telemetry_event_names(&self) -> Vec<&str> {
459 self.get_telemetry_event_names()
460 }
461
462 #[pyo3(signature = (packet, name = None))]
471 fn put_telemetrypacket(&mut self, packet : TelemetryPacket, name : Option<&str>) -> PyResult<()> {
472 if let Some(p_name) = name {
473 if self.has(p_name) {
474 let msg = format!("Frame already contains a TelemetryPacket named {}", p_name);
475 return Err(PyValueError::new_err(msg));
476 }
477 self.put(packet, p_name);
478 Ok(())
479 } else {
480 let name = format!("TelemetryPacketType.{}", packet.header.packet_type.as_ref());
481 let msg = format!("Frame already contains a TelemetryPacket named {}", name);
482 if self.has(&name) {
483 return Err(PyValueError::new_err(msg));
484 }
485 self.put(packet, name.as_str());
486 Ok(())
487 }
488 }
489
490 #[pyo3(signature = (packet, name = None))]
499 fn put_tofpacket(&mut self, packet : TofPacket, name : Option<&str>) -> PyResult<()> {
500 if let Some(p_name) = name {
501 if self.has(p_name) {
502 let msg = format!("Frame already contains a TofPacket named {}", p_name);
503 return Err(PyValueError::new_err(msg));
504 }
505 self.put(packet, p_name);
506 Ok(())
507 } else {
508 let name = format!("TofPacketType.{}", packet.packet_type.as_ref());
509 let msg = format!("Frame already contains a TofPacket named {}", name);
510 if self.has(&name) {
511 return Err(PyValueError::new_err(msg));
512 }
513 self.put(packet, name.as_str());
514 Ok(())
515 }
516 }
517
518 fn get_tofpacket(&mut self, name : &str) -> PyResult<TofPacket> {
524 let packet = self.get::<TofPacket>(name).unwrap();
525 Ok(packet)
526 }
527
528 fn get_telemetrypacket(&mut self, name : &str) -> PyResult<TelemetryPacket> {
535 let packet = self.get::<TelemetryPacket>(name).unwrap();
536 Ok(packet)
537 }
538
539 fn get_tofevent(&mut self, name : &str) -> PyResult<TofEvent> {
541 let packet = self.get::<TofPacket>(name).unwrap();
542 let mut event = packet.unpack::<TofEvent>().unwrap();
543 event.set_paddles(&self.tof_paddles);
544 Ok(event)
547 }
548
549 #[pyo3(signature = (name = None, always_exclude = None))]
569 fn get_telemetryevent(&mut self, name : Option<&str>, always_exclude : Option<Vec<String>>) -> PyResult<Option<TelemetryEvent>> {
570 let name_ : &str;
571 match name {
572 None => {
573 let mut names = self.get_telemetry_event_names();
574 if let Some(to_exclude) = always_exclude {
575 let exclusion_set: HashSet<_> = to_exclude.into_iter().collect();
576 names.retain(|&x| !exclusion_set.contains(x));
577 }
578 if names.len() != 1 {
579 let msg = format!("Frame contains multiple or no TelemetryEvents {:?}. Please specify a name!", names);
580 return Err(PyValueError::new_err(msg));
581 } else {
582 name_ = names[0];
583 }
584 }
585 Some(n_) => {
586 name_ = n_;
587 }
588 }
589 let packet = self.get::<TelemetryPacket>(name_).unwrap();
591 match packet.unpack::<TelemetryEvent>() {
592 Err(err) => {
593 return Err(PyValueError::new_err(err.to_string()));
594 }
595 Ok(mut event) => {
596 event.header = packet.header;
597 event.dehydrate(&self.tof_paddles, &self.trk_strips);
598 if self.do_trk_calib {
599 event.mask_strips(&self.trk_masks);
600 event.calibrate_tracker(self.subtract_trk_cmn,
601 &self.trk_ped,
602 &self.trk_tf,
603 &self.trk_cmn);
604 }
605 Ok(Some(event))
606 }
607 }
608 }
609
610 #[pyo3(name="has")]
615 fn has_py(&self, name : &str) -> bool {
616 self.has(name)
617 }
618
619 #[getter]
620 fn index(&self) -> HashMap<String, (u64, CRFrameObjectType)> {
621 self.index.clone()
622 }
623
624 #[getter]
625 #[pyo3(name="do_trk_calib")]
626 fn do_trk_calib_py(&self) -> bool {
627 self.do_trk_calib
628 }
629}
630
631#[cfg(feature="pybindings")]
632pythonize!(CRFrame);