read timeseries into vector

This commit is contained in:
Daniel Bauer
2020-10-25 19:42:33 +01:00
parent d7eea7aa03
commit 07fc8344fe

View File

@@ -115,12 +115,48 @@ fn is_in_time_boundaries(time: f64, cfg: &Config) -> bool {
false false
} }
// parse a time series file into a histogram // Read a multidimensional timeseries
fn read_window_file(window_file: &str, cfg: &Config) -> Result<Histogram> { // The resulting vector contains one vector per dimension
fn read_timeseries(window_file: &str, cfg: &Config) -> Result<Vec<Vec<f64>>> {
let f = File::open(window_file) let f = File::open(window_file)
.chain_err(|| format!("Failed to open sample data file {}.", window_file))?; .chain_err(|| format!("Failed to open sample data file {}.", window_file))?;
let mut buf = BufReader::new(&f); let mut buf = BufReader::new(&f);
let mut timeseries = vec![Vec::new(); cfg.dimens+1];
// read and parse each timeseries line
let mut line = String::new();
let mut linecount = 0;
while buf.read_line(&mut line).chain_err(|| "Failed to read line")? > 0 {
linecount += 1;
// skip comments and empty lines
if line.starts_with('#') || line.starts_with('@') || line.is_empty() {
line.clear();
continue;
}
{
let split: Vec<&str> = line.split_whitespace().collect();
if split.len() < cfg.dimens+1 {
bail!(format!("Wrong number of columns in line {} of window file {}. Empty Line?.", linecount, window_file));
}
for i in 0..cfg.dimens+1 {
timeseries[i].push(split[i].parse::<f64>()
.chain_err(|| format!("Failed to parse line {} of window file {}.", linecount, window_file))?
);
}
}
line.clear();
}
Ok(timeseries)
}
// parse a time series file into a histogram
fn read_window_file(window_file: &str, cfg: &Config) -> Result<Histogram> {
// total number of bins is the product of all dimensions length // total number of bins is the product of all dimensions length
let total_bins = cfg.num_bins.iter().product(); let total_bins = cfg.num_bins.iter().product();
let mut hist = vec![0.0; total_bins]; let mut hist = vec![0.0; total_bins];
@@ -130,28 +166,14 @@ fn read_window_file(window_file: &str, cfg: &Config) -> Result<Histogram> {
(cfg.hist_max[idx] - cfg.hist_min[idx])/(cfg.num_bins[idx] as f64) (cfg.hist_max[idx] - cfg.hist_min[idx])/(cfg.num_bins[idx] as f64)
}).collect(); }).collect();
// read and parse each timeseries line let timeseries: Vec<Vec<f64>> = read_timeseries(window_file, cfg)?;
let mut line = String::new();
let mut linecount = 0;
while buf.read_line(&mut line).chain_err(|| "Failed to read line")? > 0 {
linecount += 1;
// skip comments and empty lines
if line.starts_with('#') || line.starts_with('@') || line.is_empty() {
line.clear();
continue;
}
{ // TODO decorrelate
let split: Vec<&str> = line.split_whitespace().collect();
if split.len() < cfg.dimens+1 {
bail!(format!("Wrong number of columns in line {} of window file {}. Empty Line?.", linecount, window_file));
}
for i in 0..timeseries[0].len() {
let mut values: Vec<f64> = vec![f64::NAN; cfg.dimens+1]; let mut values: Vec<f64> = vec![f64::NAN; cfg.dimens+1];
for i in 0..values.len() { for j in 0..values.len() {
values[i] = split[i].parse::<f64>() values[j] = timeseries[j][i];
.chain_err(|| format!("Failed to parse line {} of window file {}.", linecount, window_file))?;
} }
if is_in_hist_boundaries(&values[1..], cfg) && is_in_time_boundaries(values[0], cfg) { if is_in_hist_boundaries(&values[1..], cfg) && is_in_time_boundaries(values[0], cfg) {
@@ -163,8 +185,6 @@ fn read_window_file(window_file: &str, cfg: &Config) -> Result<Histogram> {
hist[index] += 1.0; hist[index] += 1.0;
} }
} }
line.clear();
}
let num_points: f64 = hist.iter().sum(); let num_points: f64 = hist.iter().sum();
Ok(Histogram::new(num_points as u32, hist)) Ok(Histogram::new(num_points as u32, hist))
@@ -214,7 +234,8 @@ mod tests {
bootstrap: 0, bootstrap: 0,
bootstrap_seed: 1234, bootstrap_seed: 1234,
start: 0.0, start: 0.0,
end: 1e+20 end: 1e+20,
uncorr: false,
} }
} }
@@ -233,6 +254,26 @@ mod tests {
assert_approx_eq!(0.0, h.bins[7]); assert_approx_eq!(0.0, h.bins[7]);
} }
#[test]
fn read_timeseries() {
let f = "example/1d_cyclic/COLVAR+0.0.xvg";
let cfg = cfg();
let ts = super::read_timeseries(&f, &cfg).unwrap();
let expected = [
-0.153_145,
-0.377_860,
0.010_992,
0.123_074,
0.108_291,
0.261_607,
];
assert!(ts.len() == 2);
assert!(ts[0].len() == 5000);
println!("{:?}", ts);
for (actual, expected) in ts[1].iter().zip(expected.iter()) {
assert!((actual-expected).abs() < 0.001, format!("{:?} != {:?}", actual, expected));
}
}
#[test] #[test]
fn read_data() { fn read_data() {