use std::fs::File;
use crate::prelude::data::Data;
use crate::prelude::simulator::Equation;
use anyhow::{bail, Context, Result};
use ndarray::{Array1, Array2};
use pharmsol::prelude::EstimateTheta;
use crate::prelude::settings::Settings;
pub mod latin;
pub mod sobol;
pub fn sample_space(settings: &Settings, data: &Data, eqn: &impl Equation) -> Result<Array2<f64>> {
let ranges = settings.random.ranges();
if settings.prior.file.is_some() {
let prior = parse_prior(
settings.prior.file.as_ref().unwrap(),
&settings.random.names(),
)?;
return Ok(prior);
}
let prior = match settings.prior.sampler.as_str() {
"sobol" => sobol::generate(settings.prior.points, &ranges, settings.prior.seed)?,
"latin" => latin::generate(settings.prior.points, &ranges, settings.prior.seed)?,
"osat" => {
let mut point = vec![];
for range in ranges {
point.push((range.1 - range.0) / 2.0);
}
data.estimate_theta(eqn, &Array1::from_vec(point))
}
_ => {
bail!(
"Unknown sampler specified in settings: {}",
settings.prior.sampler
);
}
};
Ok(prior)
}
pub fn parse_prior(path: &String, names: &Vec<String>) -> Result<Array2<f64>> {
tracing::info!("Reading prior from {}", path);
let file = File::open(path).context(format!("Unable to open the prior file '{}'", path))?;
let mut reader = csv::ReaderBuilder::new()
.has_headers(true)
.from_reader(file);
let mut parameter_names: Vec<String> = reader
.headers()?
.clone()
.into_iter()
.map(|s| s.trim().to_owned())
.collect();
if let Some(index) = parameter_names.iter().position(|name| name == "prob") {
parameter_names.remove(index);
}
let random_names: Vec<String> = names.clone();
let mut reordered_indices: Vec<usize> = Vec::new();
for random_name in &random_names {
match parameter_names.iter().position(|name| name == random_name) {
Some(index) => {
reordered_indices.push(index);
}
None => {
bail!("Parameter {} is not present in the CSV file.", random_name);
}
}
}
if parameter_names.len() > random_names.len() {
let extra_parameters: Vec<&String> = parameter_names.iter().collect();
bail!(
"Found parameters in the prior not present in configuration: {:?}",
extra_parameters
);
}
let mut theta_values = Vec::new();
for result in reader.records() {
let record = result.unwrap();
let values: Vec<f64> = reordered_indices
.iter()
.map(|&i| record[i].parse::<f64>().unwrap())
.collect();
theta_values.push(values);
}
let n_points = theta_values.len();
let n_params = random_names.len();
let theta_values: Vec<f64> = theta_values.into_iter().flatten().collect();
Ok(Array2::from_shape_vec((n_points, n_params), theta_values)?)
}