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,Queryable, Selectable, serde::Serialize, serde::Deserialize)]
21#[diesel(table_name = schema::tof_db_trackerstriptransferfunction)]
22#[diesel(primary_key(data_id))]
23#[allow(non_snake_case)]
24#[cfg_attr(feature="pybindings", pyclass)]
25pub struct TrackerStripTransferFunction {
26 pub data_id : i32,
27 pub strip_id : i32,
28 pub volume_id : i64,
29 pub utc_timestamp_start: i64,
30 pub utc_timestamp_stop : i64,
31 pub name : Option<String>,
32 pub pol_a2_0 : f32,
33 pub pol_a2_1 : f32,
34 pub pol_a2_2 : f32,
35 pub pol_b3_0 : f32,
36 pub pol_b3_1 : f32,
37 pub pol_b3_2 : f32,
38 pub pol_b3_3 : f32,
39 pub pol_c3_0 : f32,
40 pub pol_c3_1 : f32,
41 pub pol_c3_2 : f32,
42 pub pol_c3_3 : f32,
43 pub pol_d3_0 : f32,
44 pub pol_d3_1 : f32,
45 pub pol_d3_2 : f32,
46 pub pol_d3_3 : f32,
47}
48
49impl TrackerStripTransferFunction {
50
51 pub fn new() -> Self {
52 Self {
53 data_id : 0,
54 strip_id : 0,
55 volume_id : 0,
56 utc_timestamp_start : 0,
57 utc_timestamp_stop : 0,
58 name : None,
59 pol_a2_0 : 0.0,
60 pol_a2_1 : 0.0,
61 pol_a2_2 : 0.0,
62 pol_b3_0 : 0.0,
63 pol_b3_1 : 0.0,
64 pol_b3_2 : 0.0,
65 pol_b3_3 : 0.0,
66 pol_c3_0 : 0.0,
67 pol_c3_1 : 0.0,
68 pol_c3_2 : 0.0,
69 pol_c3_3 : 0.0,
70 pol_d3_0 : 0.0,
71 pol_d3_1 : 0.0,
72 pol_d3_2 : 0.0,
73 pol_d3_3 : 0.0,
74 }
75 }
76
77 pub fn parse_from_file<P: AsRef<Path>>(path: P) -> io::Result<Vec<Self>> {
78 let file = File::open(path)?;
79 let reader = BufReader::new(file);
80 let mut transfer_fns = Vec::<Self>::new();
81 let hid_vid_map = get_hid_vid_maps().unwrap().1;
82 for line in reader.lines() {
83 let line = line?;
84 if line.starts_with("#") || line.starts_with("Layer") || line.starts_with("layer") {
85 continue;
86 }
87 let mut trfn = Self::new();
88 let parts: Vec<&str> = line.split(",").collect();
89 if parts.len() == 19 {
90 let layer = parts[0].parse::<u8>()
92 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
93 let row = parts[1].parse::<u8>()
94 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
95 let module = parts[2].parse::<u8>()
96 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
97 let channel = parts[3].parse::<u8>()
98 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
99 trfn.strip_id = TrackerStrip::create_stripid(layer, row, module, channel) as i32;
100 trfn.volume_id = *hid_vid_map.get(&(trfn.strip_id as u32)).unwrap() as i64; trfn.pol_a2_0 = parts[4].parse::<f32>()
102 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
103 trfn.pol_a2_1 = parts[5].parse::<f32>()
104 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
105 trfn.pol_a2_2 = parts[6].parse::<f32>()
106 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
107 trfn.pol_b3_0 = parts[7].parse::<f32>()
108 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
109 trfn.pol_b3_1 = parts[8].parse::<f32>()
110 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
111 trfn.pol_b3_2 = parts[9].parse::<f32>()
112 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
113 trfn.pol_b3_3 = parts[10].parse::<f32>()
114 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
115 trfn.pol_c3_0 = parts[11].parse::<f32>()
116 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
117 trfn.pol_c3_1 = parts[12].parse::<f32>()
118 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
119 trfn.pol_c3_2 = parts[13].parse::<f32>()
120 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
121 trfn.pol_c3_3 = parts[14].parse::<f32>()
122 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
123 trfn.pol_d3_0 = parts[15].parse::<f32>()
124 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
125 trfn.pol_d3_1 = parts[16].parse::<f32>()
126 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
127 trfn.pol_d3_2 = parts[17].parse::<f32>()
128 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
129 trfn.pol_d3_3 = parts[18].parse::<f32>()
130 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
131 transfer_fns.push(trfn);
132 }
133 }
134 Ok(transfer_fns)
135 }
136
137 pub fn as_dict_by_name(fname : &str) -> Result<HashMap<u32,Self>, ConnectionError> {
142 use schema::tof_db_trackerstriptransferfunction::dsl::*;
143 let mut strips = HashMap::<u32, Self>::new();
144 if fname == "" {
145 match Self::all() {
146 None => {
147 error!("Unable to retrive ANY TrackerStripTransferFunction");
148 return Ok(strips);
149 }
150 Some(_strips) => {
151 for k in _strips {
152 strips.insert(k.strip_id as u32, k);
153 }
154 return Ok(strips);
155 }
156 }
157 }
158 let mut conn = connect_to_db()?;
159 match tof_db_trackerstriptransferfunction.filter(
160 schema::tof_db_trackerstriptransferfunction::name.eq(fname)).load::<Self>(&mut conn) {
161 Err(err) => {
162 error!("We can't find any tracker strip transferfunction in the database! {err}");
163 return Ok(strips);
164 }
165 Ok(peds_) => {
166 for s in peds_ {
167 strips.insert(s.strip_id as u32, s );
168 }
169 }
170 }
171 return Ok(strips);
172 }
173
174 pub fn all_names() -> Result<Vec<String>, ConnectionError> {
175 let mut conn = connect_to_db()?;
176 let mut names = Vec::<String>::new();
177 let unique_names =
178 schema::tof_db_trackerstriptransferfunction::table.select(
179 schema::tof_db_trackerstriptransferfunction::name)
180 .distinct()
181 .load::<Option<String>>(&mut conn).expect("Error getting names from db!");
182 for k in unique_names {
183 if let Some(n) = k {
184 names.push(n);
185 }
186 }
187 Ok(names)
188 }
189
190 pub fn all() -> Option<Vec<Self>> {
195 use schema::tof_db_trackerstriptransferfunction::dsl::*;
196 let mut conn = connect_to_db().ok()?;
197 match tof_db_trackerstriptransferfunction.load::<Self>(&mut conn) {
198 Err(err) => {
199 error!("Unable to load tracker transfer functions from db! {err}");
200 return None;
201 }
202 Ok(strips) => {
203 return Some(strips);
204 }
205 }
206 }
207
208 pub fn transfer_fn(&self, adc : f32) -> f32 {
211 if adc < 0.0 {
212 return 0.0;
213 }
214 if adc <= 190.0 {
215 return self.pol_a2_0 + self.pol_a2_1*adc + self.pol_a2_2*(adc.powi(2));
216 }
217 if 190.0 < adc && adc <= 500.0 {
218 return self.pol_b3_0 + self.pol_b3_1*adc + self.pol_b3_2*(adc.powi(2)) + self.pol_b3_3*(adc.powi(3));
219 }
220 if 500.0 < adc && adc <= 900.0 {
221 return self.pol_c3_0 + self.pol_c3_1*adc + self.pol_c3_2*(adc.powi(2)) + self.pol_c3_3*(adc.powi(3));
222 }
223 if 900.0 < adc && adc <= 1600.0 {
225 return self.pol_d3_0 + self.pol_d3_1*adc + self.pol_d3_2*(adc.powi(2)) + self.pol_d3_3*(adc.powi(3));
226 }
227 0.0
228 }
229}
230
231impl fmt::Display for TrackerStripTransferFunction {
232 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
233 let mut repr = format!("<TrackerStripTransferFunction [{}]:", self.strip_id);
234 repr += &(format!("\n vid : {}", self.volume_id));
235 repr += "\n UTC Timestamps (Begin/End):";
236 repr += &(format!("\n {}/{}", self.utc_timestamp_start, self.utc_timestamp_stop));
237 if self.name.is_some() {
238 repr += &(format!("\n name : {}", self.name.clone().unwrap()));
239 }
240 repr += &(format!("\n Poly A {}*adc + {}*adc + {}*(adc**2) for adc < 190", self.pol_a2_0, self.pol_a2_1, self.pol_a2_2));
241 repr += &(format!("\n Poly B :{}*adc + {}*adc + {}*(adc**2) + {}*(adc**3) for 190 < adc <= 500", self.pol_b3_0, self.pol_b3_1, self.pol_b3_2, self.pol_b3_3));
242 repr += &(format!("\n Poly C :{}*adc + {}*adc + {}*(adc**2) + {}*(adc**3) for 500 < adc <= 900", self.pol_c3_0, self.pol_c3_1, self.pol_c3_2, self.pol_c3_3));
243 repr += &(format!("\n Poly D :{}*adc + {}*adc + {}*(adc**2) + {}*(adc**3) for 900 < adc <= 1600>", self.pol_d3_0, self.pol_d3_1, self.pol_d3_2, self.pol_d3_3));
244 write!(f, "{}", repr)
245 }
246}
247
248#[cfg(feature="pybindings")]
249#[pymethods]
250impl TrackerStripTransferFunction {
251
252 #[staticmethod]
253 #[pyo3(name="all")]
254 pub fn all_py() -> Option<Vec<Self>> {
255 Self::all()
256 }
257
258 #[staticmethod]
259 #[pyo3(name="all_names")]
260 pub fn all_names_py() -> Option<Vec<String>> {
264 match Self::all_names() {
265 Err(_) => {
266 return None;
267 }
268 Ok(names) => {
269 return Some(names);
270 }
271 }
272 }
273
274 #[staticmethod]
275 #[pyo3(name="as_dict_by_name")]
276 pub fn all_as_dict_py(name : &str) -> Option<HashMap<u32,Self>> {
277 match Self::as_dict_by_name(name) {
278 Err(err) => {
279 error!("Unable to retrieve tracker strip transfer fn dictionary. {err}. Did you laod the setup-env.sh shell?");
280 return None;
281 }
282 Ok(_data) => {
283 return Some(_data);
284 }
285 }
286 }
287
288 #[getter]
289 fn get_strip_id (&self) -> i32 {
290 self.strip_id
291 }
292
293 #[getter]
294 fn get_volume_id (&self) -> i64 {
295 self.volume_id
296 }
297
298 #[getter]
299 fn get_utc_timestamp_start(&self) -> i64 {
300 self.utc_timestamp_start
301 }
302
303 #[getter]
304 fn get_utc_timestamp_stop(&self) -> i64 {
305 self.utc_timestamp_stop
306 }
307
308 #[setter]
309 fn set_utc_timestamp_start(&mut self, value : i64) {
310 self.utc_timestamp_start = value;
311 }
312
313 #[setter]
314 fn set_utc_timestamp_stop(&mut self, value : i64) {
315 self.utc_timestamp_stop = value;
316 }
317
318 #[getter]
319 fn get_name(&self) -> Option<String> {
320 self.name.clone()
321 }
322
323 #[setter]
324 fn set_name(&mut self, value : String) {
325 self.name = Some(value);
326 }
327
328 #[pyo3(name="transfer_fn")]
329 fn transfer_fn_py(&self, adc : f32) -> f32 {
330 if adc > 1600.0 {
331 warn!("ADC value larger than 1600! {}. Transfer fn not defined beyond 1600.", adc);
332 }
333 return self.transfer_fn(adc);
334 }
335
336 #[staticmethod]
337 #[pyo3(name="parse_from_file")]
338 fn parse_from_file_py(fname : &str) -> Option<Vec<Self>> {
339 let result = Self::parse_from_file(fname);
340 if result.is_ok() {
341 return Some(result.unwrap());
342 } else {
343 error!("An error occured when parsing {} : '{}'", fname, result.unwrap_err());
344 return None;
345 }
346 }
347}
348
349#[cfg(feature="pybindings")]
350pythonize!(TrackerStripTransferFunction);
351
352#[derive(Debug,PartialEq, Clone, Insertable)]
355#[diesel(table_name = schema::tof_db_trackerstriptransferfunction)]
356#[allow(non_snake_case)]
357#[cfg_attr(feature="pybindings", pyclass)]
358struct NewTrackerStripTransferFunction {
359 pub strip_id : i32,
360 pub volume_id : i64,
361 pub utc_timestamp_start: i64,
362 pub utc_timestamp_stop : i64,
363 pub name : Option<String>,
364 pub pol_a2_0 : f32,
365 pub pol_a2_1 : f32,
366 pub pol_a2_2 : f32,
367 pub pol_b3_0 : f32,
368 pub pol_b3_1 : f32,
369 pub pol_b3_2 : f32,
370 pub pol_b3_3 : f32,
371 pub pol_c3_0 : f32,
372 pub pol_c3_1 : f32,
373 pub pol_c3_2 : f32,
374 pub pol_c3_3 : f32,
375 pub pol_d3_0 : f32,
376 pub pol_d3_1 : f32,
377 pub pol_d3_2 : f32,
378 pub pol_d3_3 : f32,
379}
380
381impl NewTrackerStripTransferFunction {
382 pub fn from(tf : &TrackerStripTransferFunction) -> Self {
383 Self {
384 strip_id : tf.strip_id ,
385 volume_id : tf.volume_id ,
386 utc_timestamp_start : tf.utc_timestamp_start ,
387 utc_timestamp_stop : tf.utc_timestamp_stop ,
388 name : tf.name.clone() ,
389 pol_a2_0 : tf.pol_a2_0 ,
390 pol_a2_1 : tf.pol_a2_1 ,
391 pol_a2_2 : tf.pol_a2_2 ,
392 pol_b3_0 : tf.pol_b3_0 ,
393 pol_b3_1 : tf.pol_b3_1 ,
394 pol_b3_2 : tf.pol_b3_2 ,
395 pol_b3_3 : tf.pol_b3_3 ,
396 pol_c3_0 : tf.pol_c3_0 ,
397 pol_c3_1 : tf.pol_c3_1 ,
398 pol_c3_2 : tf.pol_c3_2 ,
399 pol_c3_3 : tf.pol_c3_3 ,
400 pol_d3_0 : tf.pol_d3_0 ,
401 pol_d3_1 : tf.pol_d3_1 ,
402 pol_d3_2 : tf.pol_d3_2 ,
403 pol_d3_3 : tf.pol_d3_3 ,
404 }
405 }
406}
407
408#[cfg_attr(feature="pybindings", pyfunction)]
409pub fn create_trk_transfer_fn_table( db_path: &str, transfer_fns: Vec<TrackerStripTransferFunction>) {
410 use schema::tof_db_trackerstriptransferfunction::dsl::*;
411 let mut conn = SqliteConnection::establish(db_path).ok().unwrap();
412 let mut _query_result = diesel::sql_query("
413 CREATE TABLE IF NOT EXISTS tof_db_trackerstriptransferfunction (
414 data_id INTEGER PRIMARY KEY AUTOINCREMENT,
415 strip_id INTEGER NOT NULL,
416 volume_id BIGINT NOT NULL,
417 utc_timestamp_start BIGINT NOT NULL,
418 utc_timestamp_stop BIGINT NOT NULL,
419 name TEXT,
420 pol_a2_0 FLOAT NOT NULL,
421 pol_a2_1 FLOAT NOT NULL,
422 pol_a2_2 FLOAT NOT NULL,
423 pol_b3_0 FLOAT NOT NULL,
424 pol_b3_1 FLOAT NOT NULL,
425 pol_b3_2 FLOAT NOT NULL,
426 pol_b3_3 FLOAT NOT NULL,
427 pol_c3_0 FLOAT NOT NULL,
428 pol_c3_1 FLOAT NOT NULL,
429 pol_c3_2 FLOAT NOT NULL,
430 pol_c3_3 FLOAT NOT NULL,
431 pol_d3_0 FLOAT NOT NULL,
432 pol_d3_1 FLOAT NOT NULL,
433 pol_d3_2 FLOAT NOT NULL,
434 pol_d3_3 FLOAT NOT NULL
435 )
436 ").execute(&mut conn);
437 let mut new_data = Vec::<NewTrackerStripTransferFunction>::new();
438 for p in transfer_fns {
439 let np = NewTrackerStripTransferFunction::from(&p);
440 new_data.push(np);
441 }
442 println!("Will insert {} tfns!", new_data.len());
443 _query_result = diesel::insert_into(tof_db_trackerstriptransferfunction)
444 .values(&new_data)
445 .execute(&mut conn);
446 println!("Inserted {}", _query_result.unwrap());
447}
448