gmt_dos-actors 3.0.0

Giant Magellan Telescope Dynamic Optical Simulation Actor Model
Documentation
use std::{
    collections::VecDeque,
    fs::File,
    io::{BufRead, BufReader},
    num::ParseFloatError,
    path::Path,
    sync::Arc,
};
use thiserror::Error;

use crate::io::Data;

#[derive(Debug, Error)]
pub enum DTAError {
    #[error("Failed to open DTA file")]
    IO(#[from] std::io::Error),
    #[error("Failed to parse DTA data")]
    Parsing(#[from] ParseFloatError),
}

pub type Result<T> = std::result::Result<T, DTAError>;

#[derive(Debug)]
pub struct Load {
    #[allow(dead_code)]
    time_stamp: f64,
    data: Vec<f64>,
}
#[derive(Debug)]
pub struct CfdLoads(VecDeque<Load>);

impl CfdLoads {
    pub fn new<P: AsRef<Path>>(data_path: P) -> Result<Self> {
        let file = File::open(data_path)?;
        let rdr = BufReader::new(file);
        Ok(Self(
            rdr.lines()
                .skip(12)
                .map(|line| {
                    let a_line = line?;
                    let mut chunks = a_line.split(',');
                    let time_stamp = chunks
                        .next()
                        .map(|x| x.parse::<f64>().map_err(|e| DTAError::Parsing(e)))
                        .unwrap()?;
                    let data = chunks
                        .map(|x| x.parse::<f64>().map_err(|e| DTAError::Parsing(e)))
                        .collect::<Result<Vec<f64>>>()?;
                    Ok(Load { time_stamp, data })
                })
                .collect::<Result<VecDeque<Load>>>()?,
        ))
    }
    pub fn len(&self) -> usize {
        self.0.len()
    }
}

impl Iterator for CfdLoads {
    type Item = Vec<f64>;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.pop_front().map(|x| x.data)
    }
}

impl crate::Update for CfdLoads {}
#[cfg(feature = "fem")]
impl crate::io::Write<Vec<f64>, fem::fem_io::OSSDTAWind6F> for CfdLoads {
    fn write(
        &mut self,
    ) -> Option<std::sync::Arc<crate::io::Data<Vec<f64>, fem::fem_io::OSSDTAWind6F>>> {
        self.next().map(|x| Arc::new(Data::new(x)))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn dta_loads() {
        let loads =
            CfdLoads::new("/fsx/DTA/zen30az000_OS7/GMT-DTA-190952_RevB1_WLC00xx.csv").unwrap();
        println!("CFD loads #: {}", loads.len());
        loads.into_iter().take(3).for_each(|l| println!("{l:?}"));
    }
}