use burn::prelude::*;
pub struct InputBatch<B: Backend> {
pub signal: Tensor<B, 3>,
pub channel_locations: Tensor<B, 3>,
pub channel_names: Option<Tensor<B, 2, Int>>,
pub n_channels: usize,
pub n_samples: usize,
}
pub struct FifInfo {
pub ch_names: Vec<String>,
pub ch_pos_mm: Vec<[f32; 3]>,
pub sfreq: f32,
pub n_times_raw: usize,
pub duration_s: f32,
pub n_epochs: usize,
pub target_sfreq: f32,
pub epoch_dur_s: f32,
}
pub fn channel_wise_normalize<B: Backend>(x: Tensor<B, 3>) -> Tensor<B, 3> {
let mean = x.clone().mean_dim(2); let diff = x.clone() - mean.clone();
let var = (diff.clone() * diff.clone()).mean_dim(2);
let std = (var + 1e-8).sqrt();
(x - mean) / std
}
pub fn build_batch<B: Backend>(
signal: Vec<f32>, positions: Vec<f32>, channel_indices: Option<Vec<i64>>, n_channels: usize,
n_samples: usize,
device: &B::Device,
) -> InputBatch<B> {
let signal = Tensor::<B, 2>::from_data(
TensorData::new(signal, vec![n_channels, n_samples]), device,
).unsqueeze_dim::<3>(0);
let channel_locations = Tensor::<B, 2>::from_data(
TensorData::new(positions, vec![n_channels, 3]), device,
).unsqueeze_dim::<3>(0);
let channel_names = channel_indices.map(|idx| {
Tensor::<B, 1, Int>::from_data(
TensorData::new(idx, vec![n_channels]), device,
).unsqueeze_dim::<2>(0) });
InputBatch {
signal,
channel_locations,
channel_names,
n_channels,
n_samples,
}
}
pub fn build_batch_named<B: Backend>(
signal: Vec<f32>, channel_names: &[&str], n_samples: usize,
device: &B::Device,
) -> InputBatch<B> {
let n_channels = channel_names.len();
let indices = crate::channel_vocab::channel_indices_unwrap(channel_names);
let positions: Vec<f32> = channel_names.iter()
.flat_map(|name| {
crate::channel_positions::bipolar_channel_xyz(name)
.unwrap_or([0.0, 0.0, 0.0])
.to_vec()
})
.collect();
build_batch(signal, positions, Some(indices), n_channels, n_samples, device)
}