1use std::fmt;
2use std::f32::consts::PI;
3
4use half::f16;
5
6use crate::errors::SerializationError;
7use crate::serialization::{
8 parse_u8,
9 parse_u16,
10 parse_f16,
11 Serialization
12};
13use crate::ProtocolVersion;
14
15use crate::constants::{
16 C_LIGHT_PADDLE,
17};
18
19#[cfg(feature="random")]
20use rand::Rng;
21
22#[cfg(feature="database")]
23use crate::database::Paddle;
24
25#[derive(Debug,Copy,Clone,PartialEq)]
52pub struct Peak {
53 pub paddle_end_id : u16,
54 pub time : f32,
55 pub charge : f32,
56 pub height : f32
57}
58
59impl Peak {
60 pub fn new() -> Self {
61 Self {
62 paddle_end_id : 40,
63 time : 0.0,
64 charge : 0.0,
65 height : 0.0,
66 }
67 }
68}
69
70impl Default for Peak {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76impl fmt::Display for Peak {
77 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78 write!(f, "<Peak:
79 p_end_id : {}
80 time : {}
81 charge : {}
82 height : {}>",
83 self.paddle_end_id,
84 self.time,
85 self.charge,
86 self.height)
87 }
88}
89
90#[derive(Debug,Copy,Clone,PartialEq)]
97pub struct TofHit {
98
99 pub paddle_id : u8,
102 pub time_a : f16,
103 pub time_b : f16,
104 pub peak_a : f16,
105 pub peak_b : f16,
106 pub charge_a : f16,
107 pub charge_b : f16,
108
109 pub paddle_len : f32,
113 pub cable_len : f32,
118 pub timing_offset : f32,
121 pub x : f32,
125 pub y : f32,
126 pub z : f32,
127 pub coax_cable_time: f32,
129 pub hart_cable_time: f32,
130 pub event_t0 : f32,
133
134 pub timestamp32 : u32,
136 pub timestamp16 : u16,
137 pub ctr_etx : u8,
138 pub charge_min_i : u16,
139
140 pub pos_across : u16,
144 pub t0 : u16,
147
148 pub reserved : u8,
150 pub version : ProtocolVersion,
153 pub baseline_a : f16,
155 pub baseline_a_rms : f16,
156 pub baseline_b : f16,
157 pub baseline_b_rms : f16,
158 pub phase : f16,
160 pub valid : bool,
163 pub ftime_a : f32,
165 pub ftime_b : f32,
166 pub fpeak_a : f32,
167 pub fpeak_b : f32,
168}
169
170impl Default for TofHit {
171 fn default() -> Self {
172 Self::new()
173 }
174}
175
176impl fmt::Display for TofHit {
177 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
178 let mut paddle_info = String::from("");
179 if self.paddle_len == 0.0 {
180 paddle_info = String::from("NOT SET!");
181 }
182 write!(f, "<TofHit (version : {}):
183 Paddle ID {}
184 Peak:
185 LE Time A/B {:.2} {:.2}
186 Height A/B {:.2} {:.2}
187 Charge A/B {:.2} {:.2}
188 ** paddle {} **
189 Length {:.2}
190 Harting cable length {:.2}
191 Timing offset {:.2} (ns)
192 Coax cbl time {:.2}
193 Hart cbl time {:.2}
194 ** reconstructed interaction
195 energy_dep {:.2}
196 pos_across {:.2}
197 t0 {:.2}
198 x, y, z {:.2} {:.2} {:.2}
199 ** V1 variables
200 phase (ch9) {:.4}
201 n phs ro {}
202 baseline A/B {:.2} {:.2}
203 bl. RMS A/B {:.2} {:.2}>",
204 self.version,
205 self.paddle_id,
206 self.get_time_a(),
207 self.get_time_b(),
208 self.get_peak_a(),
209 self.get_peak_b(),
210 self.get_charge_a(),
211 self.get_charge_b(),
212 paddle_info,
213 self.paddle_len,
214 self.cable_len,
215 self.timing_offset,
216 self.coax_cable_time,
217 self.hart_cable_time,
218 self.get_edep(),
219 self.get_pos(),
220 self.get_t0(),
221 self.x,
222 self.y,
223 self.z,
224 self.phase,
225 self.get_phase_rollovers(),
226 self.baseline_a,
227 self.baseline_b,
228 self.baseline_a_rms,
229 self.baseline_b_rms,
230 )
231 }
232}
233
234impl Serialization for TofHit {
235
236 const HEAD : u16 = 61680; const TAIL : u16 = 3855;
238 const SIZE : usize = 30; fn to_bytestream(&self) -> Vec<u8> {
251
252 let mut bytestream = Vec::<u8>::with_capacity(Self::SIZE);
253 bytestream.extend_from_slice(&Self::HEAD.to_le_bytes());
254 bytestream.push(self.paddle_id);
255 bytestream.extend_from_slice(&self.time_a .to_le_bytes());
256 bytestream.extend_from_slice(&self.time_b .to_le_bytes());
257 bytestream.extend_from_slice(&self.peak_a .to_le_bytes());
258 bytestream.extend_from_slice(&self.peak_b .to_le_bytes());
259 bytestream.extend_from_slice(&self.charge_a .to_le_bytes());
260 bytestream.extend_from_slice(&self.charge_b .to_le_bytes());
261 bytestream.extend_from_slice(&self.charge_min_i.to_le_bytes());
262 bytestream.extend_from_slice(&self.baseline_a .to_le_bytes());
265 bytestream.extend_from_slice(&self.baseline_a_rms.to_le_bytes());
266 bytestream.extend_from_slice(&self.phase .to_le_bytes());
268 bytestream.push(self.version.to_u8());
273 bytestream.extend_from_slice(&self.baseline_b.to_le_bytes());
274 bytestream.extend_from_slice(&self.baseline_b_rms.to_le_bytes());
275 bytestream.extend_from_slice(&Self::TAIL .to_le_bytes());
276 bytestream
277 }
278
279
280 fn from_bytestream(stream : &Vec<u8>, pos : &mut usize)
287 -> Result<Self, SerializationError> {
288 let mut pp = Self::new();
289 Self::verify_fixed(stream, pos)?;
290 pp.valid = true;
293 pp.paddle_id = parse_u8(stream, pos);
294 pp.time_a = parse_f16(stream, pos);
295 pp.time_b = parse_f16(stream, pos);
296 pp.peak_a = parse_f16(stream, pos);
297 pp.peak_b = parse_f16(stream, pos);
298 pp.charge_a = parse_f16(stream, pos);
299 pp.charge_b = parse_f16(stream, pos);
300 pp.charge_min_i = parse_u16(stream, pos);
301 pp.baseline_a = parse_f16(stream, pos);
302 pp.baseline_a_rms = parse_f16(stream, pos);
303 let mut phase_vec = Vec::<u8>::new();
313 phase_vec.push(parse_u8(stream, pos));
314 phase_vec.push(parse_u8(stream, pos));
315 pp.phase = parse_f16(&phase_vec, &mut 0);
316 let version = ProtocolVersion::from(parse_u8(stream, pos));
319 pp.version = version;
320 match pp.version {
321 ProtocolVersion::V1 => {
322 }
329 _ => ()
330 }
331 pp.baseline_b = parse_f16(stream, pos);
332 pp.baseline_b_rms = parse_f16(stream, pos);
333
334 *pos += 2; Ok(pp)
338 }
339}
340
341impl TofHit {
342
343 pub fn new() -> Self {
344 Self{
345 paddle_id : 0,
346 time_a : f16::from_f32(0.0),
347 time_b : f16::from_f32(0.0),
348 peak_a : f16::from_f32(0.0),
349 peak_b : f16::from_f32(0.0),
350 charge_a : f16::from_f32(0.0),
351 charge_b : f16::from_f32(0.0),
352 paddle_len : f32::NAN,
353 timing_offset : 0.0,
354 cable_len : f32::NAN,
355 coax_cable_time : f32::NAN,
356 hart_cable_time : f32::NAN,
357 event_t0 : f32::NAN,
358 x : f32::NAN,
359 y : f32::NAN,
360 z : f32::NAN,
361
362 charge_min_i : 0,
363 pos_across : 0,
365 t0 : 0,
366 ctr_etx : 0,
367 timestamp32 : 0,
368 timestamp16 : 0,
369 valid : true,
370 version : ProtocolVersion::V1,
372 reserved : 0,
373 baseline_a : f16::from_f32(0.0),
374 baseline_a_rms : f16::from_f32(0.0),
375 baseline_b : f16::from_f32(0.0),
376 baseline_b_rms : f16::from_f32(0.0),
377 phase : f16::from_f32(0.0),
378 ftime_a : 0.0,
380 ftime_b : 0.0,
381 fpeak_a : 0.0,
382 fpeak_b : 0.0,
383 }
384 }
385
386 pub fn distance(&self, other : &TofHit) -> f32 {
392 ((self.x - other.x).powi(2) + (self.y - other.y).powi(2) + (self.z - other.z).powi(2)).sqrt()
393 }
394
395 #[cfg(feature="database")]
396 pub fn set_paddle(&mut self, paddle : &Paddle) {
397 self.cable_len = paddle.cable_len;
398 self.coax_cable_time = paddle.coax_cable_time;
399 self.hart_cable_time = paddle.harting_cable_time;
400 self.paddle_len = paddle.length * 10.0; let pr = paddle.principal();
402 let rel_pos = self.get_pos();
404 let pos = (paddle.global_pos_x_l0_A*10.0 + pr.0*rel_pos,
405 paddle.global_pos_y_l0_A*10.0 + pr.1*rel_pos,
406 paddle.global_pos_z_l0_A*10.0 + pr.2*rel_pos);
407 self.x = pos.0;
408 self.y = pos.1;
409 self.z = pos.2;
410 }
411
412 pub fn get_pid(paddle_end_id : u16) -> u8 {
422 if paddle_end_id < 1000 {
423 return 0;
424 }
425 if paddle_end_id > 2000 {
426 return (paddle_end_id - 2000) as u8;
427 }
428 if paddle_end_id < 2000 {
429 return (paddle_end_id - 1000) as u8;
430 }
431 return 0;
432 }
433
434 pub fn add_peak(&mut self, peak : &Peak) {
435 if self.paddle_id != TofHit::get_pid(peak.paddle_end_id) {
436 }
438 if peak.paddle_end_id < 1000 {
439 error!("Invalide paddle end id {}", peak.paddle_end_id);
440 }
441 if peak.paddle_end_id > 2000 {
442 self.set_time_b (peak.time);
443 self.set_peak_b (peak.height);
444 self.set_charge_b(peak.charge);
445 } else if peak.paddle_end_id < 2000 {
446 self.set_time_a (peak.time);
447 self.set_peak_a (peak.height);
448 self.set_charge_a(peak.charge);
449 }
450 }
451
452
453 pub fn get_pos(&self) -> f32 {
466 let t0 = self.get_t0_uncorrected();
467 let clean_t_a = self.time_a.to_f32() - t0;
468 return clean_t_a*C_LIGHT_PADDLE*10.0;
469 }
470
471 pub fn obeys_causality(&self) -> bool {
475 (self.paddle_len/(10.0*C_LIGHT_PADDLE)) - f32::abs(self.time_a.to_f32() - self.time_b.to_f32()) > 0.0
476 && self.get_t0_uncorrected() > 0.0
477 }
478
479 pub fn get_cable_delay(&self) -> f32 {
481 self.hart_cable_time - self.coax_cable_time
482 }
483
484 pub fn get_phase_delay(&self) -> f32 {
487 let freq : f32 = 20.0e6;
488 let phase = self.phase.to_f32();
489 (phase/(2.0*PI*freq))*1.0e9f32
500 }
501
502 pub fn get_phase_rollovers(&self) -> i16 {
503 let mut phase = self.phase.to_f32();
504 let mut ro = 0i16;
505 while phase < PI/2.0 {
506 phase += PI/2.0;
507 ro += 1;
508 }
509 while phase > PI/2.0 {
510 phase -= PI/2.0;
511 ro -= 1;
512 }
513 ro
514 }
515
516 pub fn get_t0(&self) -> f32 {
521 self.event_t0 + self.timing_offset
523 }
524
525 pub fn get_t0_uncorrected(&self) -> f32 {
531 0.5*(self.time_a.to_f32() + self.time_b.to_f32() - (self.paddle_len/(10.0*C_LIGHT_PADDLE)))}
533
534 pub fn get_edep(&self) -> f32 {
536 (1.29/34.3)*(self.peak_a.to_f32() + self.peak_b.to_f32()) / 2.0
537 }
538
539 pub fn get_time_a(&self) -> f32 {
540 self.time_a.to_f32()
541 }
542
543 pub fn set_time_a(&mut self, t : f32) {
544 self.time_a = f16::from_f32(t);
545 }
546
547 pub fn get_time_b(&self) -> f32 {
548 self.time_b.to_f32()
549 }
550
551 pub fn set_time_b(&mut self, t : f32) {
552 self.time_b = f16::from_f32(t)
553 }
554
555 pub fn get_peak_a(&self) -> f32 {
556 self.peak_a.to_f32()
557 }
558
559 pub fn set_peak_a(&mut self, p : f32) {
560 self.peak_a = f16::from_f32(p)
561 }
562
563 pub fn get_peak_b(&self) -> f32 {
564 self.peak_b.to_f32()
565 }
566
567 pub fn set_peak_b(&mut self, p : f32) {
568 self.peak_b = f16::from_f32(p)
569 }
570
571 pub fn get_charge_a(&self) -> f32 {
572 self.charge_a.to_f32()
573 }
574
575 pub fn set_charge_a(&mut self, c : f32) {
576 self.charge_a = f16::from_f32(c)
577 }
578
579 pub fn get_charge_b(&self) -> f32 {
580 self.charge_b.to_f32()
581 }
582
583 pub fn set_charge_b(&mut self, c : f32) {
584 self.charge_b = f16::from_f32(c)
585 }
586
587 pub fn get_bl_a(&self) -> f32 {
588 self.baseline_a.to_f32()
589 }
590
591 pub fn get_bl_b(&self) -> f32 {
592 self.baseline_b.to_f32()
593 }
594
595 pub fn get_bl_a_rms(&self) -> f32 {
596 self.baseline_a_rms.to_f32()
597 }
598
599 pub fn get_bl_b_rms(&self) -> f32 {
600 self.baseline_b_rms.to_f32()
601 }
602
603 #[cfg(feature="random")]
604 pub fn from_random() -> TofHit {
605 let mut pp = TofHit::new();
606 let mut rng = rand::thread_rng();
607
608 pp.paddle_id = rng.gen::<u8> ();
609 pp.time_a = f16::from_f32(rng.gen::<f32>());
610 pp.time_b = f16::from_f32(rng.gen::<f32>());
611 pp.peak_a = f16::from_f32(rng.gen::<f32>());
612 pp.peak_b = f16::from_f32(rng.gen::<f32>());
613 pp.charge_a = f16::from_f32(rng.gen::<f32>());
614 pp.charge_b = f16::from_f32(rng.gen::<f32>());
615 pp.version = ProtocolVersion::from(rng.gen::<u8>());
616 pp.baseline_a = f16::from_f32(rng.gen::<f32>());
617 pp.baseline_a_rms = f16::from_f32(rng.gen::<f32>());
618 pp.baseline_b = f16::from_f32(rng.gen::<f32>());
619 pp.baseline_b_rms = f16::from_f32(rng.gen::<f32>());
620 pp.phase = f16::from_f32(rng.gen::<f32>());
621
622 pp.paddle_len = 0.0;
623 pp.cable_len = 0.0;
624 pp.coax_cable_time = 0.0;
625 pp.hart_cable_time = 0.0;
626 pp.x = 0.0;
627 pp.y = 0.0;
628 pp.z = 0.0;
629 pp.event_t0 = 0.0;
630 pp
655 }
656}
657
658#[cfg(feature = "random")]
659#[test]
660fn serialization_tofhit() {
661 for _ in 0..100 {
662 let mut pos = 0;
663 let data = TofHit::from_random();
664 let mut test = TofHit::from_bytestream(&data.to_bytestream(),&mut pos).unwrap();
665 test.paddle_len = 0.0;
668 test.cable_len = 0.0;
669 test.coax_cable_time = 0.0;
670 test.hart_cable_time = 0.0;
671 test.x = 0.0;
672 test.y = 0.0;
673 test.z = 0.0;
674 test.event_t0 = 0.0;
675 assert_eq!(pos, TofHit::SIZE);
676 assert_eq!(data, test);
677 }
678}