gondola_core/tof/
detector_status.rs

1//! Short notation for TOF detector status
2//! 1 bit per working channel
3//!
4// This file is part of gaps-online-software and published 
5// under the GPLv3 license
6
7use crate::prelude::*;
8
9/// Report dead channels/non-active detectors
10/// for the TOF system
11///
12/// This is a very simple approach
13/// A channels are the paddle_id - 1
14/// while B channels are encoded as paddle_id - 159
15///
16/// Dead channels will be 0, active channels 
17/// will be 1
18#[derive(Debug, Copy, Clone, PartialEq)]
19#[cfg_attr(feature="pybindings", pyclass)]
20pub struct TofDetectorStatus {
21  pub channels000_031 : u32,
22  pub channels032_063 : u32,
23  pub channels064_095 : u32,
24  pub channels096_127 : u32,
25  pub channels128_159 : u32,
26  pub channels160_191 : u32,
27  pub channels192_223 : u32,
28  pub channels224_255 : u32,
29  pub channels256_297 : u32,
30  pub channels298_319 : u32,
31}
32
33impl TofDetectorStatus {
34 
35  pub fn new() -> Self {
36    Self {
37      // full hex notation to remind us what 
38      // these numbers represent
39      channels000_031 : 0x00000000,
40      channels032_063 : 0x00000000,
41      channels064_095 : 0x00000000,
42      channels096_127 : 0x00000000,
43      channels128_159 : 0x00000000,
44      channels160_191 : 0x00000000,
45      channels192_223 : 0x00000000,
46      channels224_255 : 0x00000000,
47      channels256_297 : 0x00000000,
48      channels298_319 : 0x00000000,
49    }
50  }
51
52  /// Update the dead channel list form a HashMap with 
53  /// paddle information as it is created in the 
54  /// RB communication threads of liftof-cc
55  pub fn update_from_map(&mut self, paddles : HashMap<u16,bool>) {
56    for k in 0..320 {
57      if let Some(val) = paddles.get(&(&k + 1)) {
58        if k < 32 && *val {
59          self.channels000_031 = self.channels000_031 | (k as u32) ;
60        } else if k < 64 && *val  {
61          self.channels032_063 = self.channels032_063 | (k as u32) - 32;
62        } else if k < 96 && *val  {
63          self.channels064_095 = self.channels064_095 | (k as u32) - 64;
64        } else if k < 128 && *val {
65          self.channels096_127 = self.channels096_127 | (k as u32) - 96;
66        } else if k < 160 && *val {
67          self.channels128_159 = self.channels128_159 | (k as u32) - 125;
68        } else if k < 192 && *val {
69          self.channels160_191 = self.channels160_191 | (k as u32) - 160;
70        } else if k < 224 && *val {
71          self.channels192_223 = self.channels192_223 | (k as u32) - 192;
72        } else if k < 256 && *val {
73          self.channels224_255 = self.channels224_255 | (k as u32) - 224;
74        } else if k < 298 && *val {
75          self.channels256_297 = self.channels256_297 | (k as u32) - 256;
76        } else if k < 320 && *val {
77          self.channels298_319 = self.channels298_319 | (k as u32) - 298;
78        }
79      } else {
80        error!("No entry in paddle status map for channel {}", k);
81        continue;
82      }
83    }
84  }
85
86  /// Get all paddle ids which have dead 
87  /// channels on the A-side
88  pub fn get_dead_paddles_a(&self) -> Vec<u8> {
89    let mut dead_a = Vec::<u8>::new();
90    let inactive = self.get_inactive_channels_idx();
91    for k in inactive.iter() {
92      if *k < 160 {
93        dead_a.push(*k as u8);
94      }
95    }
96    dead_a
97  }
98
99  /// Get all paddle ids which have dead 
100  /// channels on the B-side
101  pub fn get_dead_paddles_b(&self) -> Vec<u8> {
102    let mut dead_b = Vec::<u8>::new();
103    let inactive = self.get_inactive_channels_idx();
104    for k in inactive.iter() {
105      if *k >= 160 {
106        dead_b.push((*k-159) as u8);
107      }
108    }
109    dead_b
110  }
111
112  /// Index of inactive channels in the range of 
113  /// 0-319. These indizes are MTBChannel numbers
114  fn get_inactive_channels_idx(&self) -> Vec<u16> {
115    let mut channels = Vec::<u16>::new();
116    for k in 0..10 {
117      if (self.channels000_031 >> k & 0x1) == 1 {
118        channels.push(k);
119      }
120    }
121    for k in 0..10 {
122      if (self.channels032_063 >> k & 0x1) == 1 {
123        channels.push(k + 32);
124      }
125    }
126    for k in 0..10 {
127      if (self.channels064_095 >> k & 0x1) == 1 {
128        channels.push(k + 64);
129      }
130    }
131    for k in 0..10 {
132      if (self.channels096_127 >> k & 0x1) == 1 {
133        channels.push(k + 96);
134      }
135    }
136    for k in 0..10 {
137      if (self.channels128_159 >> k & 0x1) == 1 {
138        channels.push(k + 128);
139      }
140    }
141    for k in 0..10 {
142      if (self.channels160_191 >> k & 0x1) == 1 {
143        channels.push(k + 160);
144      }
145    }
146    for k in 0..10 {
147      if (self.channels192_223 >> k & 0x1) == 1 {
148        channels.push(k + 192);
149      }
150    }
151    for k in 0..10 {
152      if (self.channels224_255 >> k & 0x1) == 1 {
153        channels.push(k + 224);
154      }
155    }
156    for k in 0..10 {
157      if (self.channels256_297 >> k & 0x1) == 1 {
158        channels.push(k + 256);
159      }
160    }
161    for k in 0..10 {
162      if (self.channels298_319 >> k & 0x1) == 1 {
163        channels.push(k + 298);
164      }
165    }
166    channels
167  }
168
169  ///// Index of inactive channels in the range of 
170  ///// 0-319. These indizes are MTBChannel numbers
171  //fn get_active_channels_idx(&self) -> Vec<u16> {
172  //  let inactive_channels   = self.get_inactive_channels_idx();
173  //  let mut active_channels = Vec::<u16>::new();
174  //  for ch in 0..329 {
175  //    if !inactive_channels.contains(&ch) {
176  //      active_channels.push(ch);
177  //    }
178  //  }
179  //  active_channels
180  //}
181}
182
183impl Default for TofDetectorStatus {
184  fn default() -> Self {
185    Self::new()
186  }
187}
188
189impl Serialization for TofDetectorStatus {
190  const HEAD : u16   = 0xAAAA;
191  const TAIL : u16   = 0x5555;
192  const SIZE : usize = 44; 
193  
194  fn from_bytestream(stream     : &Vec<u8>,
195                     pos        : &mut usize)
196    -> Result<Self, SerializationError>{
197      Self::verify_fixed(stream, pos)?;
198      let mut status = TofDetectorStatus::new();
199      status.channels000_031 = parse_u32(stream, pos); 
200      status.channels032_063 = parse_u32(stream, pos); 
201      status.channels064_095 = parse_u32(stream, pos); 
202      status.channels096_127 = parse_u32(stream, pos); 
203      status.channels128_159 = parse_u32(stream, pos); 
204      status.channels160_191 = parse_u32(stream, pos); 
205      status.channels192_223 = parse_u32(stream, pos); 
206      status.channels224_255 = parse_u32(stream, pos); 
207      status.channels256_297 = parse_u32(stream, pos); 
208      status.channels298_319 = parse_u32(stream, pos); 
209      *pos += 2;
210      Ok(status)
211  } 
212  
213  fn to_bytestream(&self) -> Vec<u8> {
214    let mut bs = Vec::<u8>::with_capacity(Self::SIZE);
215    bs.extend_from_slice(&Self::HEAD.to_le_bytes());
216    bs.extend_from_slice(&self.channels000_031.to_le_bytes());
217    bs.extend_from_slice(&self.channels032_063.to_le_bytes());
218    bs.extend_from_slice(&self.channels064_095.to_le_bytes());
219    bs.extend_from_slice(&self.channels096_127.to_le_bytes());
220    bs.extend_from_slice(&self.channels128_159.to_le_bytes());
221    bs.extend_from_slice(&self.channels160_191.to_le_bytes());
222    bs.extend_from_slice(&self.channels192_223.to_le_bytes());
223    bs.extend_from_slice(&self.channels224_255.to_le_bytes());
224    bs.extend_from_slice(&self.channels256_297.to_le_bytes());
225    bs.extend_from_slice(&self.channels298_319.to_le_bytes());
226    bs.extend_from_slice(&Self::TAIL.to_le_bytes());
227    bs
228  }
229}
230
231impl TofPackable for TofDetectorStatus {
232  const TOF_PACKET_TYPE : TofPacketType = TofPacketType::TofDetectorStatus;
233}
234
235impl fmt::Display for TofDetectorStatus {
236  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
237    let mut repr : String = String::from("<TofDetectorStatus");
238    repr += &(format!("\n Ch 000 - 031 {:x}", &self.channels000_031));
239    repr += &(format!("\n Ch 032 - 063 {:x}", &self.channels032_063));
240    repr += &(format!("\n Ch 064 - 095 {:x}", &self.channels064_095));
241    repr += &(format!("\n Ch 096 - 127 {:x}", &self.channels096_127));
242    repr += &(format!("\n Ch 128 - 159 {:x}", &self.channels128_159));
243    repr += &(format!("\n Ch 160 - 191 {:x}", &self.channels160_191));
244    repr += &(format!("\n Ch 192 - 223 {:x}", &self.channels192_223));
245    repr += &(format!("\n Ch 224 - 255 {:x}", &self.channels224_255));
246    repr += &(format!("\n Ch 256 - 297 {:x}", &self.channels256_297));
247    repr += &(format!("\n Ch 298 - 319 {:x}>", &self.channels298_319));
248    write!(f, "{}", repr)
249  }
250}
251
252#[cfg(feature="pybindings")]
253#[pymethods]
254impl TofDetectorStatus {
255  
256  #[getter]
257  fn channels000_031(&self) -> u32 {
258    self.channels000_031
259  }
260
261  #[getter]
262  fn channels032_063(&self) -> u32 { 
263    self.channels032_063
264  }
265
266  #[getter]
267  fn channels064_095(&self) -> u32 { 
268    self.channels064_095
269  }
270
271  #[getter]
272  fn channels096_127(&self) -> u32 { 
273    self.channels096_127
274  }  
275
276  #[getter]
277  fn channels128_159(&self) -> u32 { 
278    self.channels128_159
279  }
280
281  #[getter]
282  fn channels160_191(&self) -> u32 { 
283    self.channels160_191
284  }
285
286  #[getter]
287  fn channels192_223(&self) -> u32 { 
288    self.channels192_223
289  }
290
291  #[getter]
292  fn channels224_255(&self) -> u32 { 
293    self.channels224_255
294  }
295  
296  #[getter]
297  fn channels256_297(&self) -> u32 { 
298    self.channels256_297
299  }
300
301  #[getter]
302  fn channels298_319(&self) -> u32 { 
303    self.channels298_319
304  }
305}
306
307#[cfg(feature="pybindings")]
308pythonize_packable!(TofDetectorStatus);
309
310
311#[cfg(feature = "random")]
312impl FromRandom for TofDetectorStatus {
313  fn from_random() -> Self {
314    let mut status  = TofDetectorStatus::new();
315    let mut rng     = rand::rng();
316    status.channels000_031 = rng.random::<u32>();
317    status.channels032_063 = rng.random::<u32>();
318    status.channels064_095 = rng.random::<u32>();
319    status.channels096_127 = rng.random::<u32>();
320    status.channels128_159 = rng.random::<u32>();
321    status.channels160_191 = rng.random::<u32>();
322    status.channels192_223 = rng.random::<u32>();
323    status.channels224_255 = rng.random::<u32>();
324    status.channels256_297 = rng.random::<u32>();
325    status.channels298_319 = rng.random::<u32>();
326    status
327  }
328}
329
330#[cfg(feature = "random")]
331#[test]
332fn pack_tofdetectorstatus() {
333  for _ in 0..100 {
334    let status  = TofDetectorStatus::from_random();
335    let test : TofDetectorStatus = status.pack().unpack().unwrap();
336    assert_eq!(status, test);
337  }
338}
339