parse_monitors/
domeseeing.rs1use serde::{Deserialize, Serialize};
2use serde_pickle as pickle;
3use std::{
4 fs::File,
5 ops::{Deref, DerefMut},
6 path::Path,
7};
8
9#[derive(thiserror::Error, Debug)]
10pub enum DomeSeeingError {
11 #[error("Failed to open `domeseeing_PSSN.rs.pkl`")]
12 Io(#[from] std::io::Error),
13 #[error("Failed to read `domeseeing_PSSN.rs.pkl`")]
14 Pickle(#[from] pickle::Error),
15}
16
17pub enum Band {
19 V,
20 H,
21}
22#[derive(Deserialize, Debug, Clone, Default, Serialize)]
24pub struct Data {
25 #[serde(rename = "Time")]
26 pub time: f64,
27 #[serde(rename = "V SE PSSn")]
28 pub v_se_pssn: f64,
29 #[serde(rename = "H SE PSSn")]
30 pub h_se_pssn: f64,
31 #[serde(rename = "WFE RMS")]
32 pub wfe_rms: Vec<f64>,
33 #[serde(rename = "tip-tilt")]
34 pub tip_tilt: Vec<f64>,
35 #[serde(rename = "segment tip-tilt")]
36 pub segment_tip_tilt: Vec<f64>,
37 #[serde(rename = "segment piston")]
38 pub segment_piston: Vec<f64>,
39 #[serde(rename = "V LE PSSn")]
40 pub v_le_pssn: Option<f64>,
41 #[serde(rename = "H LE PSSn")]
42 pub h_le_pssn: Option<f64>,
43 #[serde(rename = "V FRAME")]
44 pub v_frame: Option<Vec<f64>>,
45 #[serde(rename = "H FRAME")]
46 pub h_frame: Option<Vec<f64>>,
47}
48#[derive(Deserialize, Default, Serialize)]
50pub struct DomeSeeing(Vec<Data>);
51impl Deref for DomeSeeing {
52 type Target = Vec<Data>;
53
54 fn deref(&self) -> &Self::Target {
55 &self.0
56 }
57}
58impl DerefMut for DomeSeeing {
59 fn deref_mut(&mut self) -> &mut Self::Target {
60 &mut self.0
61 }
62}
63impl From<Vec<Data>> for DomeSeeing {
64 fn from(value: Vec<Data>) -> Self {
65 Self(value)
66 }
67}
68impl DomeSeeing {
69 pub fn new() -> Self {
71 Default::default()
72 }
73 pub fn load<P>(path: P) -> Result<Self, DomeSeeingError>
75 where
76 P: AsRef<Path>,
77 {
78 let path = path.as_ref().join("domeseeing_PSSN.rs.pkl");
79 log::info!("Logging dome seeing OPD related data from {:?}", path);
80 let mut file = File::open(Path::new(&path))?;
81 Ok(Self(pickle::from_reader(&mut file, Default::default())?))
82 }
83 pub fn push(&mut self, data: Data) {
85 self.0.push(data);
86 }
87 pub fn truncates(&mut self, len: usize) {
89 self.0.truncate(len);
90 }
91 pub fn len(&self) -> usize {
93 self.0.len()
94 }
95 pub fn wfe_rms(&self) -> impl Iterator<Item = f64> + '_ {
97 self.iter().map(|ds| ds.wfe_rms[0])
98 }
99 pub fn wfe_rms_series(&self) -> (Vec<f64>, Vec<f64>) {
101 self.iter().map(|ds| (ds.time, ds.wfe_rms[0])).unzip()
102 }
103 pub fn wfe_rms_iter(&self) -> impl IntoIterator<Item = (f64, Vec<f64>)> + '_ {
104 self.iter()
105 .cloned()
106 .map(|ds| (ds.time, vec![ds.wfe_rms[0]]))
107 }
108 pub fn wfe_rms_iter_10e(
109 &self,
110 exponent: i32,
111 ) -> impl IntoIterator<Item = (f64, Vec<f64>)> + '_ {
112 self.iter()
113 .cloned()
114 .map(move |ds| (ds.time, vec![10f64.powi(-exponent) * ds.wfe_rms[0]]))
115 }
116 pub fn se_pssn(&self, band: Band) -> (Vec<f64>, Vec<f64>) {
118 match band {
119 Band::V => self.iter().map(|ds| (ds.time, ds.v_se_pssn)).unzip(),
120 Band::H => self.iter().map(|ds| (ds.time, ds.h_se_pssn)).unzip(),
121 }
122 }
123 pub fn se_pssn_iter(&self, band: Band) -> Vec<(f64, Vec<f64>)> {
124 match band {
125 Band::V => self
126 .iter()
127 .cloned()
128 .map(|ds| (ds.time, vec![ds.v_se_pssn]))
129 .collect(),
130
131 Band::H => self
132 .iter()
133 .cloned()
134 .map(|ds| (ds.time, vec![ds.h_se_pssn]))
135 .collect(),
136 }
137 }
138 pub fn le_pssn(&self, band: Band) -> (Vec<f64>, Vec<f64>) {
140 match band {
141 Band::V => self
142 .iter()
143 .filter_map(|ds| ds.v_le_pssn.map(|x| (ds.time, x)))
144 .unzip(),
145 Band::H => self
146 .iter()
147 .filter_map(|ds| ds.h_le_pssn.map(|x| (ds.time, x)))
148 .unzip(),
149 }
150 }
151 pub fn le_pssn_iter(&self, band: Band) -> Vec<(f64, Vec<f64>)> {
152 match band {
153 Band::V => self
154 .iter()
155 .cloned()
156 .filter_map(|ds| ds.v_le_pssn.map(|x| (ds.time, vec![x])))
157 .collect(),
158 Band::H => self
159 .iter()
160 .cloned()
161 .filter_map(|ds| ds.h_le_pssn.map(|x| (ds.time, vec![x])))
162 .collect(),
163 }
164 }
165 pub fn pssn(&self, band: Band) -> Option<f64> {
167 match band {
168 Band::V => self.iter().map(|ds| ds.v_se_pssn).last(),
169 Band::H => self.iter().map(|ds| ds.h_se_pssn).last(),
170 }
171 }
172}
173
174#[cfg(test)]
175pub mod tests {
176 use super::*;
177 #[test]
178 fn load_dome_seeing() {
179 let ds = DomeSeeing::load("data").unwrap();
180 println!("Dome Seeing entry #1: {:?}", ds[0]);
181 }
182 #[test]
183 fn dome_seeing_pssn() {
184 let ds = DomeSeeing::load("data").unwrap();
185 println!(
186 "Dome Seeing PSSn V:{:?}, H:{:?}",
187 ds.pssn(Band::V),
188 ds.pssn(Band::H)
189 );
190 }
191}