Skip to main content

gondola_core/events/
mc_event.rs

1// The following file is part of gaps-online-software and published 
2// under the GPLv3 license
3
4use crate::prelude::*;
5
6#[derive(Debug, Clone)]
7#[cfg_attr(feature="pybindings", pyclass)] 
8pub struct McEvent {
9  pub run_id   : u32,
10  pub event_id : u32,
11  pub mctree   : McTree, 
12  pub primary  : Tracklet
13}
14
15impl McEvent {
16
17  pub fn new() -> Self {
18    Self {
19      run_id   : 0,
20      event_id : 0,
21      mctree   : McTree::new(),
22      primary  : Tracklet::new()
23    }
24  }
25
26
27  /// Calculate the difference between the first and the last 
28  /// hit time in the event
29  pub fn get_event_duration(&self) -> f32 {
30    let mut first_hit = f32::MAX;
31    let mut last_hit  = 0.0f32; 
32    if self.mctree.trackmap.len() == 0 {
33      return 0.0;
34    }
35    for k in self.mctree.trackmap.keys() {
36      //println!("glob time {}", h.glob_time);
37      for h in &self.mctree.trackmap[k].hits { 
38        if h.glob_time > last_hit {
39          last_hit = h.glob_time; 
40        }
41        if h.glob_time < first_hit {
42          first_hit = h.glob_time;
43        }
44      }
45    }
46    return last_hit - first_hit;
47  }
48}
49
50impl Serialization for McEvent {
51  fn from_bytestream(stream : &Vec<u8>,
52                     pos    : &mut usize) 
53    -> Result<Self, SerializationError> {
54    let mut event = Self::new();
55    let head      = parse_u16(stream, pos);
56    if head != Self::HEAD {
57      error!("Decoding of HEAD failed! Got {} instead!", head);
58      return Err(SerializationError::HeadInvalid);
59    }
60    event.run_id   = parse_u32(stream, pos);
61    event.event_id = parse_u32(stream, pos);
62    event.primary  = Tracklet::from_bytestream(stream, pos)?;
63    let nhits      = parse_u16(stream, pos);
64    let mut hits   = Vec::<McHit>::new();
65    for _ in 0..nhits {
66      hits.push(McHit::from_bytestream(stream, pos)?);
67    }
68    let tail = parse_u16(stream, pos);
69    if tail != Self::TAIL {
70      //error!("Decoding of TAIL failed for version {}! Got {} instead!", version, tail);
71      error!("Decoding of TAIL failed! Got {} instead!", tail);
72      return Err(SerializationError::TailInvalid);
73    }
74    // assemble and sort the mc tree 
75    // this consumes the hits! 
76    event.mctree.assemble(&mut hits);
77    Ok(event) 
78  }
79}
80
81impl fmt::Display for McEvent {
82  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83    let mut repr = format!("<McEvent ");
84    repr += &(format!("\n run   id : {}",self.run_id));
85    repr += &(format!("\n event id : {}",self.event_id));
86    repr += "\n === PRIMARY ===";
87    repr += &(format!("\n  {}", self.primary));
88    //repr += "\n === HITS ===";
89    //for h in &self.hits {
90    //  repr += &(format!("\n {}", h));
91    //}
92    repr += "\n === MCTREE ===";
93    repr += &(format!("\n {}", self.mctree));
94    repr += ">";
95    write!(f, "{}", repr)
96  }
97}
98
99impl Frameable for McEvent {
100  const CRFRAMEOBJECT_TYPE : CRFrameObjectType = CRFrameObjectType::McTree;
101}
102
103#[cfg(feature="pybindings")] 
104#[pymethods] 
105impl McEvent {
106
107  /// The properties of the injected primary 
108  #[getter] 
109  #[pyo3(name="primary")]
110  fn get_primary_py(&self) -> Tracklet {
111    self.primary.clone() 
112  }
113
114  #[getter] 
115  #[pyo3(name="event_duration")]
116  fn get_event_duration_py(&self) -> f32 {
117    return self.get_event_duration();
118  }
119
120  /// Get McTruth Hits in the format 
121  /// (x,y,z,time,edep,volumeid,hardware_id)
122  #[getter]
123  fn get_mctruth_hits(&self) -> Vec<(f32, f32, f32, f32, f32, u32, u32)> {
124    let mut hits = Vec::<(f32,f32,f32,f32,f32,u32,u32)>::new();
125    for track_id in self.mctree.trackmap.keys() {
126      for h in &self.mctree.trackmap[track_id].hits {
127        let hp = (h.pos_x, h.pos_y, h.pos_z, h.glob_time,h.kin_E,h.hw_id, h.volume_id);
128        hits.push(hp);
129      }
130    }
131    return hits;
132  }
133  
134  /// Combine all energy depositions in a certain volume 
135  #[getter]
136  fn get_volid_edep_map(&self) -> HashMap<u32, f32> {
137    let mut edep_map = HashMap::<u32,f32>::new();
138    for track_id in self.mctree.trackmap.keys() {
139      for h in &self.mctree.trackmap[track_id].hits {
140        if edep_map.contains_key(&h.volume_id) {
141          *edep_map.get_mut(&h.volume_id).unwrap() += h.step_edep; 
142        } else {
143          edep_map.insert(h.volume_id, h.step_edep);
144        }
145      }
146    }
147    return edep_map;
148  }
149  
150  /// Combine all energy depositions in a certain volume 
151  #[getter]
152  fn get_hwid_edep_map(&self) -> HashMap<u32, f32> {
153    let mut edep_map = HashMap::<u32,f32>::new();
154    for track_id in self.mctree.trackmap.keys() {
155      for h in &self.mctree.trackmap[track_id].hits {
156        if edep_map.contains_key(&h.hw_id) {
157          *edep_map.get_mut(&h.hw_id).unwrap() += h.step_edep; 
158        } else {
159          edep_map.insert(h.hw_id, h.step_edep);
160        }
161      }
162    }
163    return edep_map;
164  }
165  
166  #[getter]
167  #[pyo3(name="mctree")]
168  fn get_mctree_py(&self) -> McTree { 
169    self.mctree.clone()
170  }
171
172}
173
174#[cfg(feature="pybindings")]
175pythonize!(McEvent);
176