use std::io::Write as IoWrite;
use std::path::Path;
use anyhow::Context;
pub fn fif_to_csv(
fif_path: &Path,
csv_path: &Path,
keep: Option<&[&str]>,
) -> anyhow::Result<(Vec<String>, f32)> {
use exg::fiff::raw::open_raw;
let raw = open_raw(fif_path)
.with_context(|| format!("opening FIF: {}", fif_path.display()))?;
let sfreq = raw.info.sfreq as f32;
let all_names: Vec<String> = raw.info.chs.iter().map(|ch| ch.name.clone()).collect();
let keep_indices: Vec<usize> = match keep {
None => (0..all_names.len()).collect(),
Some(subset) => {
let lower: Vec<String> = subset.iter().map(|s| s.to_ascii_lowercase()).collect();
all_names.iter().enumerate()
.filter(|(_, n)| lower.contains(&n.to_ascii_lowercase()))
.map(|(i, _)| i)
.collect()
}
};
let written_names: Vec<String> =
keep_indices.iter().map(|&i| all_names[i].clone()).collect();
let data_f64 = raw.read_all_data()
.with_context(|| format!("reading FIF data: {}", fif_path.display()))?;
let n_times = data_f64.ncols();
if let Some(parent) = csv_path.parent() {
std::fs::create_dir_all(parent)
.with_context(|| format!("creating directory: {}", parent.display()))?;
}
let mut file = std::fs::File::create(csv_path)
.with_context(|| format!("creating CSV: {}", csv_path.display()))?;
writeln!(file, "# generated by zuna-rs fif_to_csv")?;
writeln!(file, "# sfreq={sfreq} n_channels={} n_samples={n_times}",
written_names.len())?;
write!(file, "timestamp")?;
for name in &written_names { write!(file, ",{name}")?; }
writeln!(file)?;
let dt = 1.0_f32 / sfreq;
for t in 0..n_times {
let ts = t as f32 * dt;
write!(file, "{ts:.9e}")?;
for &ci in &keep_indices {
let v = data_f64[[ci, t]] as f32;
write!(file, ",{v:.9e}")?;
}
writeln!(file)?;
}
Ok((written_names, sfreq))
}