use super::*;
use crate::config::*;
use std::collections::VecDeque;
#[derive(Default, Debug, Clone)]
pub struct TimeBuffer {
data: Vec<VecDeque<Flt>>,
}
impl TimeBuffer {
pub fn new() -> TimeBuffer {
TimeBuffer { data: Vec::new() }
}
pub fn reset(&mut self) {
*self = Self::new();
}
pub fn push<'a, T>(&mut self, new_data: T)
where
T: AsArray<'a, Flt, Ix2>,
{
let new_data = new_data.into();
let nch = new_data.shape()[1];
if self.data.is_empty() {
self.data = vec![VecDeque::new(); nch];
}
if self.data.len() != nch {
panic!("BUG: Number of channels does not match with time buffer");
}
for (new_dat, buf) in new_data.columns().into_iter().zip(self.data.iter_mut()) {
let slice = new_dat.as_slice().unwrap();
buf.extend(slice);
}
}
pub fn nsamples(&self) -> usize {
if let Some(q) = self.data.first() {
return q.len();
};
0
}
pub fn pop(&mut self, nsamples_requested: usize, nsamples_keep: usize) -> Option<Dmat> {
if self.data.is_empty() {
return None;
}
if nsamples_keep > nsamples_requested {
panic!("BUG: Cannot keep more samples than requested to return");
}
debug_assert!(!self.data.is_empty());
let c1 = unsafe { self.data.get_unchecked(0) };
let nsamples_available = c1.len();
debug_assert!(nsamples_available == self.nsamples());
if nsamples_available < nsamples_requested {
return None;
}
let nchannels = self.data.len();
let mut res = Dmat::zeros((nsamples_requested, nchannels).f());
{
for (mut col, dat) in res.columns_mut().into_iter().zip(&mut self.data) {
let col_slice = col
.as_slice_mut()
.expect("Data is not contiguous on the sample axis!");
let (dat_slice1, dat_slice2) = dat.as_slices();
if dat_slice1.len() >= nsamples_requested {
col_slice.copy_from_slice(&dat_slice1[..nsamples_requested]);
} else {
let slice1len = dat_slice1.len();
col_slice[..slice1len].copy_from_slice(dat_slice1);
col_slice[slice1len..nsamples_requested]
.copy_from_slice(&dat_slice2[..nsamples_requested - slice1len]);
}
dat.drain(0..nsamples_requested - nsamples_keep);
}
}
let c1 = unsafe { self.data.get_unchecked(0) };
let nsamples_available = c1.len();
debug_assert!(self
.data
.iter()
.map(|ch| ch.len()) .all(|v| v == nsamples_available));
Some(res)
}
}
#[cfg(test)]
mod test {
use crate::{Dcol, Dmat};
use ndarray::s;
use super::TimeBuffer;
#[test]
fn test_timebuffer1() {
let mut t1 = Dmat::zeros((10, 1));
t1[[9, 0]] = 1.0;
let mut tb = TimeBuffer::new();
tb.push(&t1);
let out = tb.pop(10, 2).unwrap();
assert_eq!(out.len(), 10);
let out = tb.pop(3, 0);
assert!(out.is_none());
let out = tb.pop(2, 0).unwrap();
assert_eq!(out.len(), 2);
assert_eq!(tb.nsamples(), 0);
assert_eq!(out[[1, 0]], 1.0);
tb.reset();
assert_eq!(tb.nsamples(), 0);
}
#[test]
fn test_timebuffer2() {
let mut tb = TimeBuffer::new();
let tlin = Dcol::linspace(0., 100., 101);
let mut t2 = Dmat::zeros((101, 0));
t2.push_column(tlin.view()).unwrap();
t2.push_column(tlin.view()).unwrap();
tb.push(&t2);
assert_eq!(tb.nsamples(), 101);
let tres = tb.pop(50, 49).unwrap();
assert_eq!(tres.shape(), [50, 2]);
assert_eq!(t2.slice(s![..50, ..2]), tres);
}
#[test]
fn test_timebuffer3() {
let mut tb = TimeBuffer::new();
let t1 = Dmat::zeros((10,1));
tb.push(&t1);
tb.push(&t1);
assert_eq!(tb.nsamples(), 20);
let tres = tb.pop(10, 5).unwrap();
assert_eq!(tres.shape(), [10, 1]);
assert_eq!(tb.nsamples(), 15);
let _ = tb.pop(10, 0).unwrap();
assert_eq!(tb.nsamples(), 5);
let tres = tb.pop(5, 5).unwrap();
assert_eq!(tres.shape(), [5, 1]);
assert_eq!(tb.nsamples(), 5);
}
}