Skip to main content

gondola_core/database/
tracker_cali_times.rs

1//! In-flight calibration times for the GAPS tracker system
2// This file is part of gaps-online-software and published 
3// under the GPLv3 license
4
5use crate::prelude::*;
6use crate::database::schema;
7
8use diesel::prelude::*;
9use std::io::BufRead;
10//use diesel::SqliteConnection;
11//use diesel::RunQueryDsl;
12//use diesel::Connection;
13//use crate::database::schema::tof_db_trackercalitime::dsl::tof_db_trackercalitime;
14
15
16/// Check if the given (unix) time is within a calibration 
17/// time window for the tracker 
18// FIXME - this should be rewritten to be 2 functions so that 
19// &Vec can be used as argument (Bound in the python version)
20#[cfg_attr(feature="pybindings", pyfunction)]
21pub fn is_in_tracker_cali_window(ts : f64, cali_windows : Vec<TrackerCaliTimeWindow>) -> bool { 
22  for cw in cali_windows {
23    if ts.trunc() as i64 <= cw.utc_timestamp_stop && ts.trunc() as i64 >= cw.utc_timestamp_start {
24      return true;
25    }
26  }
27  false
28}
29  
30#[cfg_attr(feature="pybindings", pyfunction)]
31pub fn create_trk_cali_tw_table( db_path: &str, cali_time_windows: Vec<TrackerCaliTimeWindow>) { 
32  use schema::tof_db_trackercalitime::dsl::*;
33  let mut conn = SqliteConnection::establish(db_path).ok().unwrap();
34  
35  let mut _query_result = diesel::sql_query("
36      CREATE TABLE IF NOT EXISTS tof_db_trackercalitime (
37          data_id INTEGER PRIMARY KEY AUTOINCREMENT,
38          utc_timestamp_start BIGINT NOT NULL,
39          utc_timestamp_stop BIGINT NOT NULL,
40          meta TEXT
41      )
42  ").execute(&mut conn);
43  _query_result = diesel::insert_into(tof_db_trackercalitime)
44    .values(&cali_time_windows)
45    .execute(&mut conn);
46  match _query_result {
47    Ok(_) => {
48      println!("Entered data into db successfully!");
49    }
50    Err(err) => {
51      println!("Error occured when entering data in the db! {err}");
52    }
53  }
54}
55
56/// Tracker calibrations were conducted on several ocasions during 
57/// the flight. This data might be unusuable for physics analysis 
58/// and might be excluded from any processing. 
59#[derive(Debug,PartialEq, Clone, Queryable, Selectable, Insertable, serde::Serialize, serde::Deserialize)]
60#[diesel(table_name = schema::tof_db_trackercalitime)]
61#[diesel(primary_key(data_id))]
62#[allow(non_snake_case)]
63#[cfg_attr(feature="pybindings", pyclass)]
64pub struct TrackerCaliTimeWindow {
65  #[diesel(deserialize_as = i32)]
66  pub data_id             : Option<i32>,
67  pub utc_timestamp_start : i64,
68  pub utc_timestamp_stop  : i64,
69  pub meta                : Option<String>, 
70}
71
72impl TrackerCaliTimeWindow {
73
74  pub fn new() -> Self {
75    Self {
76      data_id             : None,
77      utc_timestamp_start : 0,  
78      utc_timestamp_stop  : 0,
79      meta                : None, 
80    }
81  }
82 
83  /// Get all tracker calibration times from the database 
84  ///
85  /// # Returns:
86  ///   * HashMap<u32 [strip id], TrackeCaliTime> 
87  pub fn all() -> Option<Vec<Self>> {
88    use schema::tof_db_trackercalitime::dsl::*;
89    let mut conn = connect_to_db().ok()?;
90    match tof_db_trackercalitime.load::<Self>(&mut conn) {
91      Err(err) => {
92        error!("Unable to load tracker calibration times from db! {err}");
93        return None;
94      }
95      Ok(cali_times) => {
96        return Some(cali_times);
97      }
98    }
99  }
100
101  pub fn parse_from_file<P: AsRef<Path>>(path: P) -> io::Result<Vec<Self>> {
102    let file = File::open(path)?;
103    let reader = BufReader::new(file);
104    let mut results = Vec::new(); 
105    for line in reader.lines() {
106      let line = line?;
107      let parts: Vec<&str> = line.split_whitespace().collect();
108      if parts.len() == 2 {
109        let start = parts[0].parse::<i64>()
110          .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
111        let stop = parts[1].parse::<i64>()
112          .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
113        results.push((start, stop));
114      }
115    }
116    let mut ctimes = Vec::<Self>::new();
117    for k in results {
118      let mut tctw  = TrackerCaliTimeWindow::new();
119      tctw.utc_timestamp_start = k.0;
120      tctw.utc_timestamp_stop  = k.1;
121      ctimes.push(tctw);
122    }
123    Ok(ctimes)
124  }
125}
126
127impl Default for TrackerCaliTimeWindow {
128  fn default() -> Self {
129    Self::new()
130  }
131}
132
133impl fmt::Display for TrackerCaliTimeWindow {
134  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135    let mut repr = String::from("<TrackerCaliTimeWindow:");
136    repr += "\n   UTC Timestamps (Begin/End):";
137    repr += &(format!("\n   {}/{}", self.utc_timestamp_start, self.utc_timestamp_stop));    
138    if self.meta.is_some() {
139      repr += &(format!("\n   meta info        : {}", self.meta.clone().unwrap())); 
140    }
141    write!(f, "{}", repr)
142  }
143}
144
145#[cfg(feature="pybindings")]
146#[pymethods]
147impl TrackerCaliTimeWindow {
148  
149  #[staticmethod]
150  #[pyo3(name="all")]
151  pub fn all_py() -> Option<Vec<Self>> {
152    Self::all()
153  } 
154  
155  #[staticmethod]
156  #[pyo3(name="parse_from_file")]
157  fn parse_from_file_py(fname : &str) -> Option<Vec<Self>> {
158    let times = Self::parse_from_file(fname);
159    if times.is_ok() {
160      return Some(times.unwrap());
161    } else {
162      error!("An error occured when parsing {}", fname);
163      return None;
164    }
165  }
166
167  
168  #[getter]
169  fn get_utc_timestamp_start(&self) -> i64 {
170    self.utc_timestamp_start
171  }
172  
173  #[getter]
174  fn get_utc_timestamp_stop(&self) -> i64 {
175    self.utc_timestamp_stop
176  }
177  
178  #[setter]
179  fn set_utc_timestamp_start(&mut self, value : i64) {
180    self.utc_timestamp_start = value;
181  }
182  
183  #[setter]
184  fn set_utc_timestamp_stop(&mut self, value : i64) {
185    self.utc_timestamp_stop = value;
186  }
187  
188  #[getter]
189  fn get_meta    (&self) -> Option<String> {
190    self.meta.clone()
191  }  
192
193}
194
195#[cfg(feature="pybindings")]
196pythonize!(TrackerCaliTimeWindow);
197
198
199
200
201