1use crate::prelude::*;
9
10use crate::database::schema;
11use diesel::prelude::*;
12
13use std::io::{
14 self,
15 BufRead,
16 BufReader
17};
18
19#[derive(Debug,PartialEq, Clone, Insertable)]
21#[diesel(table_name = schema::tof_db_trackerstrippulse)]
22#[allow(non_snake_case)]
23#[cfg_attr(feature="pybindings", pyclass)]
24struct NewTrackerStripPulse {
25 pub strip_id : i32,
26 pub volume_id : i64,
27 pub utc_timestamp_start : i64,
28 pub utc_timestamp_stop : i64,
29 pub name : Option<String>,
30 pub pulse_chn : i32,
31 pub pulse_avg : f32,
32 pub pulse_is_mean : bool,
33}
34
35impl NewTrackerStripPulse {
36 pub fn from(gain : &TrackerStripPulse) -> Self {
37 Self {
38 strip_id : gain.strip_id ,
39 volume_id : gain.volume_id ,
40 utc_timestamp_start : gain.utc_timestamp_start ,
41 utc_timestamp_stop : gain.utc_timestamp_stop ,
42 name : gain.name.clone() ,
43 pulse_chn : gain.pulse_chn ,
44 pulse_avg : gain.pulse_avg ,
45 pulse_is_mean : gain.pulse_is_mean ,
46 }
47 }
48}
49
50#[derive(Debug,PartialEq, Clone,Queryable, Selectable, serde::Serialize, serde::Deserialize)]
53#[diesel(table_name = schema::tof_db_trackerstrippulse)]
54#[diesel(primary_key(data_id))]
55#[allow(non_snake_case)]
56#[cfg_attr(feature="pybindings", pyclass)]
57pub struct TrackerStripPulse {
58 pub data_id : i32,
59 pub strip_id : i32,
60 pub volume_id : i64,
61 pub utc_timestamp_start : i64,
62 pub utc_timestamp_stop : i64,
63 pub name : Option<String>,
64 pub pulse_chn : i32,
65 pub pulse_avg : f32,
66 pub pulse_is_mean : bool,
67}
68
69impl TrackerStripPulse {
70
71 pub fn new() -> Self {
72 Self {
73 data_id : 0,
74 strip_id : 0,
75 volume_id : 0,
76 utc_timestamp_start : 0,
77 utc_timestamp_stop : 0,
78 name : None,
79 pulse_chn : 0,
80 pulse_avg : 0.0,
81 pulse_is_mean : false,
82 }
83 }
84
85 pub fn parse_from_file<P: AsRef<Path>>(path: P) -> io::Result<Vec<Self>> {
86 let file = File::open(path)?;
87 let reader = BufReader::new(file);
88 let mut pulses = Vec::<Self>::new();
89 let hid_vid_map = get_hid_vid_maps().unwrap().1;
90 let mut n_entries = 0u64;
91 let mut mean_pulse = 0.0f64;
92 let mut all_strip_ids : Vec<_> = hid_vid_map.keys().collect();
94 for line in reader.lines() {
95 let line = line?;
96 if line.starts_with("#") || line.starts_with("Layer") || line.starts_with("layer") {
97 continue;
98 }
99 let mut pulse = Self::new();
100 let parts: Vec<&str> = line.split_whitespace().collect();
101 if parts.len() == 6 {
102 let layer = parts[0].parse::<u8>()
104 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
105 let row = parts[1].parse::<u8>()
106 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
107 let module = parts[2].parse::<u8>()
108 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
109 let channel = parts[3].parse::<u8>()
110 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
111 pulse.strip_id = TrackerStrip::create_stripid(layer, row, module, channel) as i32;
112 pulse.volume_id = *hid_vid_map.get(&(pulse.strip_id as u32)).unwrap() as i64; pulse.pulse_chn = parts[4].parse::<i32>()
114 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
115 pulse.pulse_avg = parts[5].parse::<f32>()
116 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
117 mean_pulse += pulse.pulse_chn as f64;
118 all_strip_ids.retain(|x| *x != &(pulse.strip_id as u32));
120 pulses.push(pulse);
121 n_entries += 1;
122 }
123 }
124 mean_pulse /= n_entries as f64;
125 Ok(pulses)
138 }
139
140 pub fn all_names() -> Result<Vec<String>, ConnectionError> {
141 let mut conn = connect_to_db()?;
142 let mut names = Vec::<String>::new();
143 let unique_names =
144 schema::tof_db_trackerstrippulse::table.select(
145 schema::tof_db_trackerstrippulse::name)
146 .distinct()
147 .load::<Option<String>>(&mut conn).expect("Error getting names from db!");
148 for k in unique_names {
149 if let Some(n) = k {
150 names.push(n);
151 }
152 }
153 Ok(names)
154 }
155
156 pub fn as_dict_by_name(fname : &str) -> Result<HashMap<u32,Self>, ConnectionError> {
161 use schema::tof_db_trackerstrippulse::dsl::*;
162 let mut strips = HashMap::<u32, Self>::new();
163 if fname == "" {
164 match Self::all() {
165 None => {
166 error!("Unable to retrive ANY TrackerStripCMNNoise Data (pulser)");
167 return Ok(strips);
168 }
169 Some(_strips) => {
170 for k in _strips {
171 strips.insert(k.strip_id as u32, k);
172 }
173 return Ok(strips);
174 }
175 }
176 }
177 let mut conn = connect_to_db()?;
178 match tof_db_trackerstrippulse.filter(
179 schema::tof_db_trackerstrippulse::name.eq(fname)).load::<Self>(&mut conn) {
180 Err(err) => {
181 error!("We can't find any tracker strip common noise information with that name in the database! {err}");
182 return Ok(strips);
183 }
184 Ok(peds_) => {
185 for s in peds_ {
186 strips.insert(s.strip_id as u32, s );
187 }
188 }
189 }
190 return Ok(strips);
191 }
192
193 pub fn all() -> Option<Vec<Self>> {
198 use schema::tof_db_trackerstrippulse::dsl::*;
199 let mut conn = connect_to_db().ok()?;
200 match tof_db_trackerstrippulse.load::<Self>(&mut conn) {
201 Err(err) => {
202 error!("Unable to load tracker transfer functions from db! {err}");
203 return None;
204 }
205 Ok(strips) => {
206 return Some(strips);
207 }
208 }
209 }
210}
211
212impl fmt::Display for TrackerStripPulse {
213 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
214 let mut repr = format!("<TrackerStripPulse [{}]:", self.strip_id);
215 repr += &(format!("\n vid : {}", self.volume_id));
216 repr += "\n UTC Timestamps (Begin/End):";
217 repr += &(format!("\n {}/{}", self.utc_timestamp_start, self.utc_timestamp_stop));
218 if self.name.is_some() {
219 repr += &(format!("\n name : {}", self.name.clone().unwrap()));
220 }
221 if self.pulse_is_mean {
222 repr += &(String::from("\n -- Pulse is mean value!"));
223 }
224 repr += &(format!("\n pulse ch : {} pulse avg : {}>", self.pulse_chn, self.pulse_avg));
225 write!(f, "{}", repr)
226 }
227}
228
229#[cfg(feature="pybindings")]
230#[pymethods]
231impl TrackerStripPulse {
232
233 #[staticmethod]
234 #[pyo3(name="all")]
235 pub fn all_py() -> Option<Vec<Self>> {
236 Self::all()
237 }
238
239 #[staticmethod]
240 #[pyo3(name="all_names")]
241 pub fn all_names_py() -> Option<Vec<String>> {
245 match Self::all_names() {
246 Err(_) => {
247 return None;
248 }
249 Ok(names) => {
250 return Some(names);
251 }
252 }
253 }
254
255 #[staticmethod]
256 #[pyo3(name="as_dict_by_name")]
257 pub fn all_as_dict_py(name : &str) -> Option<HashMap<u32,Self>> {
258 match Self::as_dict_by_name(name) {
259 Err(err) => {
260 error!("Unable to retrieve tracker strip gain dictionary. {err}. Did you laod the setup-env.sh shell?");
261 return None;
262 }
263 Ok(_data) => {
264 return Some(_data);
265 }
266 }
267 }
268
269 #[getter]
270 fn get_strip_id (&self) -> i32 {
271 self.strip_id
272 }
273
274 #[getter]
275 fn get_volume_id (&self) -> i64 {
276 self.volume_id
277 }
278
279 #[getter]
280 fn get_utc_timestamp_start(&self) -> i64 {
281 self.utc_timestamp_start
282 }
283
284 #[getter]
285 fn get_utc_timestamp_stop(&self) -> i64 {
286 self.utc_timestamp_stop
287 }
288
289 #[setter]
290 fn set_utc_timestamp_start(&mut self, value : i64) {
291 self.utc_timestamp_start = value;
292 }
293
294 #[setter]
295 fn set_utc_timestamp_stop(&mut self, value : i64) {
296 self.utc_timestamp_stop = value;
297 }
298
299 #[getter]
300 fn get_name(&self) -> Option<String> {
301 self.name.clone()
302 }
303
304 #[setter]
305 fn set_name(&mut self, value : String) {
306 self.name = Some(value);
307 }
308
309 #[getter]
310 fn get_pulse_chn(&self) -> i32 {
311 self.pulse_chn
312 }
313
314 #[getter]
315 fn get_pulse_avg(&self) -> f32 {
316 self.pulse_avg
317 }
318
319 #[getter]
320 fn get_pulse_is_mean(&self) -> bool {
321 self.pulse_is_mean
322 }
323
324 #[staticmethod]
325 #[pyo3(name="parse_from_file")]
326 fn parse_from_file_py(fname : &str) -> Option<Vec<Self>> {
327 let result = Self::parse_from_file(fname);
328 if result.is_ok() {
329 return Some(result.unwrap());
330 } else {
331 error!("An error occured when parsing {} : '{}'", fname, result.unwrap_err());
332 return None;
333 }
334 }
335}
336
337#[cfg(feature="pybindings")]
338pythonize!(TrackerStripPulse);
339
340#[cfg_attr(feature="pybindings", pyfunction)]
341pub fn create_trk_pulse_table( db_path: &str, pulses: Vec<TrackerStripPulse>) {
342 use schema::tof_db_trackerstrippulse::dsl::*;
343 let mut conn = SqliteConnection::establish(db_path).ok().unwrap();
344 let mut _query_result = diesel::sql_query("
345 CREATE TABLE IF NOT EXISTS tof_db_trackerstrippulse (
346 data_id INTEGER PRIMARY KEY AUTOINCREMENT,
347 strip_id INTEGER NOT NULL,
348 volume_id BIGINT NOT NULL,
349 utc_timestamp_start BIGINT NOT NULL,
350 utc_timestamp_stop BIGINT NOT NULL,
351 name TEXT,
352 pulse_chn INTEGER,
353 pulse_avg FLOAT,
354 pulse_is_mean BOOL
355 )
356 ").execute(&mut conn);
357 let mut new_pulses = Vec::<NewTrackerStripPulse>::new();
358 for p in pulses {
359 let np = NewTrackerStripPulse::from(&p);
360 new_pulses.push(np);
361 }
362 _query_result = diesel::insert_into(tof_db_trackerstrippulse)
363 .values(&new_pulses)
364 .execute(&mut conn);
365}
366
367