Skip to main content

gondola_core/physics/
tracklet.rs

1// This file is part of gaps-online-software and published 
2// under the GPLv3 license
3
4use crate::prelude::*;
5
6// copy over the G4Process so that we do not need to
7// include G4 here
8/// Types of serializable data structures used
9/// throughout the TOF system. 
10#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy, FromRepr, AsRefStr, EnumIter)]
11#[cfg_attr(feature = "pybindings", pyclass(eq, eq_int))]
12#[repr(u8)]
13pub enum G4ProcessType {
14   NotDefined        = 0u8,
15   Transportation    = 10u8,
16   Electromagnetic   = 20u8,
17   Optical           = 30u8,
18   Hadronic          = 40u8,
19   PhotoLeptonHadron = 50u8,
20   Decay             = 60u8,
21   General           = 70u8,
22   Parametrisation   = 80u8,
23   UserDefined       = 90u8,
24   Parallel          = 100u8,
25   Phonon            = 110u8,
26   Ucn               = 120u8,
27   Unknown           = 255u8, // since 0 is already assigned
28}
29
30// in case we have pybindings for this type, 
31// expand it so that it can be used as keys
32// in dictionaries
33#[cfg(feature = "pybindings")]
34#[pymethods]
35impl G4ProcessType {
36
37  #[getter]
38  fn __hash__(&self) -> usize {
39    (*self as u8) as usize
40  } 
41}
42
43expand_and_test_enum!(G4ProcessType, test_g4processtype_repr);
44
45//------------------------------------------------------------
46
47
48/// A "RecoHit" is truly just an assembly of coordinates, time 
49/// and energy, allowing to carry an error on the position along. 
50#[derive(Debug, Copy, Clone, PartialEq)]
51#[cfg_attr(feature="pybindings", pyclass)] 
52pub struct RecoHit {
53  pub x      : f32,
54  pub x_err  : f32,
55  pub y      : f32,
56  pub y_err  : f32,
57  pub z      : f32,
58  pub z_err  : f32,
59  pub time   : f32,
60  pub energy : f32,
61  pub volume : u32
62}
63
64impl RecoHit {
65  pub fn new() -> Self {
66    Self {
67      x      : 0.0,
68      x_err  : 0.0,
69      y      : 0.0,
70      y_err  : 0.0,
71      z      : 0.0,
72      z_err  : 0.0,
73      time   : 0.0,
74      energy : 0.0,
75      volume : 0
76    }
77  }
78}
79
80impl Serialization for RecoHit {
81  //FIXME - this has fixed size!!
82  fn from_bytestream(stream : &Vec<u8>,
83                     pos    : &mut usize) 
84    -> Result<Self, SerializationError> {
85    let mut hit = Self::new();
86    let head    = parse_u16(stream, pos);
87    if head != Self::HEAD {
88      error!("Decoding of HEAD failed! Got {} instead!", head);
89      return Err(SerializationError::HeadInvalid);
90    }
91    hit.x      = parse_f32(stream, pos);
92    hit.x_err  = parse_f32(stream, pos);
93    hit.y      = parse_f32(stream, pos);
94    hit.y_err  = parse_f32(stream, pos);
95    hit.z      = parse_f32(stream, pos);
96    hit.z_err  = parse_f32(stream, pos);
97    hit.time   = parse_f32(stream, pos);
98    hit.energy = parse_f32(stream, pos);
99    hit.volume = parse_u32(stream, pos);
100    let tail   = parse_u16(stream, pos);
101    if tail != Self::TAIL {
102      //error!("Decoding of TAIL failed for version {}! Got {} instead!", version, tail);
103      error!("Decoding of TAIL failed! Got {} instead!", tail);
104      return Err(SerializationError::TailInvalid);
105    }
106    Ok(hit) 
107  }
108}
109
110impl fmt::Display for RecoHit {
111  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112    let mut repr = String::from("<RecoHit");
113    repr += &(format!("\n  x {:.2} y {:.2} z {:.2}", self.x, self.y, self.z));
114    repr += &(format!("\n  energy {:.2}", self.energy));
115    repr += &(format!("\n  time   {:.2}>", self.time));
116    write!(f,"{}", repr)
117  } 
118}
119
120// --------------------------------------------
121
122/// This is semantics. However, in a vertex the 
123/// energy will return the energy of the particle 
124/// at that actual position, not the energy depositions
125type Vertex = RecoHit;
126
127// --------------------------------------------
128
129/// A representation of a physics track, as a single, 
130/// unbent, stright line
131#[derive(Debug, Copy, Clone, PartialEq)]
132#[cfg_attr(feature="pybindings", pyclass)] 
133pub struct Tracklet {
134  pub start         : Vertex,
135  pub stop          : Vertex,
136  pub is_infinite   : bool,
137  pub vertex_mom_x  : f32,
138  pub vertex_mom_y  : f32,
139  pub vertex_mom_z  : f32,
140  /// particle identifier
141  pub pdg           : i32,
142}
143
144impl Tracklet {
145  pub fn new() -> Self {
146    Self {
147      start         : RecoHit::new(),
148      stop          : RecoHit::new(),
149      is_infinite   : true,
150      vertex_mom_x  : 0.0,
151      vertex_mom_y  : 0.0,
152      vertex_mom_z  : 0.0,
153      pdg           : 0,
154    }
155  }
156
157  pub fn get_vertex_pos(&self) -> (f32,f32,f32) {
158    (self.start.x, self.start.y, self.start.z)
159  }
160  
161  pub fn get_vertex_mom(&self) -> (f32,f32,f32) {
162    (self.vertex_mom_x, self.vertex_mom_y, self.vertex_mom_z)
163  }
164}
165
166impl Serialization for Tracklet {
167  //FIXME - this has fixed size!!
168  fn from_bytestream(stream : &Vec<u8>,
169                     pos    : &mut usize) 
170    -> Result<Self, SerializationError> {
171    let mut tracklet = Self::new();
172    let head    = parse_u16(stream, pos);
173    if head != Self::HEAD {
174      error!("Decoding of HEAD failed! Got {} instead!", head);
175      return Err(SerializationError::HeadInvalid);
176    }
177    tracklet.start         = RecoHit::from_bytestream(stream, pos)?;
178    tracklet.stop          = RecoHit::from_bytestream(stream, pos)?;
179    tracklet.is_infinite   = parse_bool(stream, pos);
180    tracklet.vertex_mom_x  = parse_f32(stream, pos);
181    tracklet.vertex_mom_y  = parse_f32(stream, pos);
182    tracklet.vertex_mom_z  = parse_f32(stream, pos);
183    tracklet.pdg           = parse_i32(stream, pos);
184    let tail   = parse_u16(stream, pos);
185    if tail != Self::TAIL {
186      //error!("Decoding of TAIL failed for version {}! Got {} instead!", version, tail);
187      error!("Decoding of TAIL failed! Got {} instead!", tail);
188      return Err(SerializationError::TailInvalid);
189    }
190    Ok(tracklet) 
191  }
192}
193
194#[cfg(feature="pybindings")]
195#[pymethods]
196impl Tracklet {
197  
198  #[getter]
199  #[pyo3(name="vertex_mom")]
200  fn get_vertex_mom_py(&self) -> (f32,f32,f32) {
201    self.get_vertex_mom() 
202  }
203
204  #[getter] 
205  #[pyo3(name="vertex_energy")]
206  fn get_vertex_energy_py(&self) -> f32 {
207    self.start.energy
208  }
209
210  #[getter]
211  #[pyo3(name="vertex_pos")]
212  fn get_vertex_pos_py(&self) -> (f32,f32,f32) {
213    self.get_vertex_pos()
214  }
215}
216
217impl fmt::Display for Tracklet {
218  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
219    let mut repr = String::from("<Tracklet");
220    repr += &(format!("\n  vertex {:.2} {:.2} {:.2}", self.start.x, self.start.y, self.start.z));
221    repr += &(format!("\n  pdg    {}>", self.pdg));
222    write!(f,"{}", repr)
223  } 
224}
225
226#[cfg(feature="pybindings")]
227pythonize!(Tracklet);
228
229
230pub struct Track {
231  pub tracklets : Vec<Tracklet>
232}
233