libdrugplotter 0.1.3

Easily compute drug concentration curves
Documentation
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()
    }                              
    
    // returns xs and ys
    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 d_buffer: Vec<Vec<f64>> = Vec::with_capacity(self.doses.len());
        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
    }
}