use std::{
error::Error,
fs::File,
iter::Sum,
ops::{AddAssign, DivAssign, MulAssign, SubAssign},
};
use num_traits::Float;
use crate::tSNE;
impl<'data, T, U, const D: usize> tSNE<'data, T, U, D>
where
T: Send + Sync + Float + Sum + DivAssign + MulAssign + AddAssign + SubAssign,
U: Send + Sync,
{
pub fn write_csv(&mut self, path: &str) -> Result<&mut Self, Box<dyn Error>>
where
T: Float + ToString,
{
let mut writer = csv::Writer::from_path(path)?;
let to_write = self
.y
.iter()
.map(|&el| el.to_string())
.collect::<Vec<String>>();
match D {
2 => writer.write_record(["x", "y"])?,
3 => writer.write_record(["x", "y", "z"])?,
_ => (), }
for record in to_write.chunks(D) {
writer.write_record(record)?
}
writer.flush()?;
Ok(self)
}
}
pub fn load_csv<T, F>(
path: &str,
has_headers: bool,
skip: Option<&[usize]>,
f: F,
) -> Result<Vec<T>, Box<dyn Error>>
where
F: Fn(String) -> T,
{
let mut data: Vec<T> = Vec::new();
let file = File::open(path)?;
let mut reader = csv::ReaderBuilder::new()
.has_headers(has_headers)
.from_reader(file);
match skip {
Some(range) => {
for result in reader.records() {
let record = result?;
(0..record.len())
.filter(|column| !range.contains(column))
.for_each(|field| data.push(f(record.get(field).unwrap().to_string())));
}
}
None => {
for result in reader.records() {
let record = result?;
(0..record.len())
.for_each(|field| data.push(f(record.get(field).unwrap().to_string())));
}
}
}
Ok(data)
}