Skip to main content

parse_monitors/monitors/reports/loader/
y2021_25.rs

1use std::time::Instant;
2use std::{fs::File, io::Read, path::Path};
3
4use regex::Regex;
5
6use crate::{Exertion, Monitors, MonitorsError};
7
8use super::MonitorsLoader;
9
10type Result<T> = std::result::Result<T, MonitorsError>;
11
12impl<const Y: u32> MonitorsLoader<Y> {
13    #[cfg(feature = "bzip2")]
14    fn decompress(&self) -> Result<String> {
15        let mut contents = String::new();
16        let data_path = Path::new(&self.path).with_extension("csv.bz2");
17        let csv_file =
18            File::open(&data_path).map_err(|e| MonitorsError::Io(e, data_path.clone()))?;
19
20        log::info!("Loading {:?}...", csv_file);
21        let buf = std::io::BufReader::new(csv_file);
22        let mut bz2 = bzip2::bufread::BzDecoder::new(buf);
23        bz2.read_to_string(&mut contents)
24            .map_err(|e| MonitorsError::Io(e, data_path))?;
25        Ok(contents)
26    }
27    #[cfg(not(feature = "bzip2"))]
28    fn decompress(&self) -> Result<String> {
29        use flate2::read::GzDecoder;
30
31        use crate::MonitorsError;
32
33        let mut contents = String::new();
34        let data_path = Path::new(&self.path).with_extension("csv.z");
35        log::info!("Loading {:?}...", data_path);
36        let csv_file =
37            File::open(&data_path).map_err(|e| MonitorsError::Io(e, data_path.clone()))?;
38        let mut gz = GzDecoder::new(csv_file);
39        gz.read_to_string(&mut contents)
40            .map_err(|e| MonitorsError::Io(e, data_path))?;
41        Ok(contents)
42    }
43    #[cfg(feature = "object_store")]
44    pub async fn load_from_store(self, store: impl object_store::ObjectStore) -> Result<Monitors> {
45        use object_store::ObjectStoreExt;
46        use std::io::Cursor;
47        use std::path::PathBuf;
48        let data_path = Path::new(&self.path).with_extension("csv.z");
49        let location = object_store::path::Path::from(data_path.to_str().unwrap());
50        let bytes = store.get(&location).await?.bytes().await?;
51        let cursor = Cursor::new(bytes);
52        let mut gz = flate2::bufread::GzDecoder::new(cursor);
53        let mut contents = String::new();
54        gz.read_to_string(&mut contents)
55            .map_err(|e| MonitorsError::Io(e, PathBuf::from(location.to_string())))?;
56        self.load_from_bytes(contents.into_bytes())
57    }
58    pub fn load(self) -> Result<Monitors> {
59        let contents = self.decompress()?;
60        self.load_from_bytes(contents.into_bytes())
61    }
62    pub fn load_from_bytes(self, bytes: Vec<u8>) -> Result<Monitors> {
63        let now = Instant::now();
64        let mut rdr = csv::Reader::from_reader(bytes.as_slice());
65
66        let headers: Vec<_> = {
67            let headers = rdr.headers()?;
68            //headers.iter().take(20).for_each(|h| println!("{}", h));
69            headers.into_iter().map(|h| h.to_string()).collect()
70        };
71        if Y == 2025 {
72            headers
73                .iter()
74                .find(|h| h.contains("M1c_"))
75                .ok_or(MonitorsError::YearMismatch(2021, Y))?;
76        }
77
78        let re_htc = Regex::new(
79            r"(\w+) Monitor: Surface Average of Heat Transfer Coefficient \(W/m\^2-K\)",
80        )?;
81        //Cabs_X Monitor 2: Force (N)
82        let re_force = Regex::new(r"(.+)_([XYZ]) Monitor(?:: Force)? \(N\)")?;
83        let re_moment = Regex::new(r"(.+)Mom_([XYZ]) Monitor(?:: Moment)? \(N-m\)")?;
84
85        let re_header = Regex::new(&self.header_regex)?;
86        let re_x_header = if let Some(re) = self.header_exclude_regex {
87            Some(Regex::new(&re)?)
88        } else {
89            None
90        };
91
92        let mut monitors = Monitors::default();
93
94        for result in rdr.records() {
95            let record = result?;
96            let time = record.iter().next().unwrap().parse::<f64>()?;
97            if time < self.time_range.0 - 1. / 40. || time > self.time_range.1 + 1. / 40. {
98                continue;
99            };
100            monitors.time.push(time);
101            for (data, header) in record.iter().skip(1).zip(headers.iter().skip(1)).filter(
102                |(_, h)| match &re_x_header {
103                    Some(re_x_header) => re_header.is_match(h) && !re_x_header.is_match(h),
104                    None => re_header.is_match(h),
105                },
106            ) {
107                // HTC
108                if let Some(capts) = re_htc.captures(header) {
109                    let key = capts.get(1).unwrap().as_str().to_owned();
110                    let value = data.parse::<f64>()?;
111                    monitors
112                        .heat_transfer_coefficients
113                        .entry(key)
114                        .or_insert_with(Vec::new)
115                        .push(value.abs());
116                }
117                // FORCE
118                if let Some(capts) = re_force.captures(header) {
119                    let key = capts.get(1).unwrap().as_str().to_owned();
120                    let value = data.parse::<f64>()?;
121                    let exertions = monitors
122                        .forces_and_moments
123                        .entry(key)
124                        .or_insert(vec![Exertion::default()]);
125                    let exertion = exertions.last_mut().unwrap();
126                    match capts.get(2).unwrap().as_str() {
127                        "X" => match exertion.force.x {
128                            Some(_) => exertions.push(Exertion::from_force_x(value)),
129                            None => {
130                                exertion.force.x = Some(value);
131                            }
132                        },
133                        "Y" => match exertion.force.y {
134                            Some(_) => exertions.push(Exertion::from_force_y(value)),
135                            None => {
136                                exertion.force.y = Some(value);
137                            }
138                        },
139                        "Z" => match exertion.force.z {
140                            Some(_) => exertions.push(Exertion::from_force_z(value)),
141                            None => {
142                                exertion.force.z = Some(value);
143                            }
144                        },
145                        &_ => (),
146                    };
147                }
148                // MOMENT
149                if let Some(capts) = re_moment.captures(header) {
150                    let key = capts
151                        .get(1)
152                        .unwrap()
153                        .as_str()
154                        .trim_end_matches('_')
155                        .to_owned();
156                    let value = data.parse::<f64>()?;
157                    let exertions = monitors
158                        .forces_and_moments
159                        .entry(key)
160                        .or_insert(vec![Exertion::default()]);
161                    let exertion = exertions.last_mut().unwrap();
162                    match capts.get(2).unwrap().as_str() {
163                        "X" => match exertion.moment.x {
164                            Some(_) => exertions.push(Exertion::from_moment_x(value)),
165                            None => {
166                                exertion.moment.x = Some(value);
167                            }
168                        },
169                        "Y" => match exertion.moment.y {
170                            Some(_) => exertions.push(Exertion::from_moment_y(value)),
171                            None => {
172                                exertion.moment.y = Some(value);
173                            }
174                        },
175                        "Z" => match exertion.moment.z {
176                            Some(_) => exertions.push(Exertion::from_moment_z(value)),
177                            None => {
178                                exertion.moment.z = Some(value);
179                            }
180                        },
181                        &_ => (),
182                    };
183                }
184            }
185        }
186        log::info!("... loaded in {:}s", now.elapsed().as_secs());
187        Ok(monitors)
188    }
189}