use crate::util::{get_ka, get_sample, linspace};
use bitcode::{Encode, Decode};
#[derive(Clone, Encode, Decode)]
pub struct Drug {
pub name: String,
pub half_life: f64,
pub t_max: f64,
pub rep: usize,
pub doses: Vec<Dose>,
}
#[derive(Clone, Copy, Encode, Decode)]
pub struct Dose {
pub amount: f64,
pub offset: f64,
}
impl Drug {
fn s_dose_samples(&self, t_arr: Vec<f64>) -> Vec<f64> {
let ke = 2f64.ln() / self.half_life;
let ka = get_ka(ke, self.t_max);
let p = ka / (ka - ke);
t_arr.iter().map(|t| get_sample(p, ke, ka, *t)).collect()
}
pub fn drug_samples(&self, sph: usize, hrs: usize) -> Vec<f64> {
let t_arr = linspace(hrs, sph * hrs);
let curve = self.s_dose_samples(t_arr.clone());
let mut doses = vec![0f64; sph * hrs];
for dose in self.doses.clone() {
let off_s = (dose.offset * sph as f64) as usize;
let slice = curve[0..(sph * hrs) - off_s].to_vec();
let mul: Vec<f64> = slice.iter().map(|s| s * dose.amount).collect();
(&mut doses[off_s..]).iter_mut().zip(&mul).for_each(|(a, b)| *a += b);
}
let r_count = (hrs as f64 / self.rep as f64) as usize + 1;
let mut out = vec![0f64; sph * hrs];
for rep_c in 0..r_count {
let off_s = (self.rep * rep_c * sph) as usize;
let slice = doses[0..(sph * hrs) - off_s].to_vec();
(&mut out[off_s..]).iter_mut().zip(&slice).for_each(|(a, b)| *a += b);
}
out
}
}