use crate::{data::Covariates, simulator::*};
use diffsol::{NalgebraContext, Vector};
use super::three_compartment_models::{three_compartments, three_compartments_with_absorption};
use super::wrap_pmetrics_analytical;
pub fn three_compartments_cl(x: &V, p: &V, t: T, rateiv: &V, cov: &Covariates) -> V {
let cl = p[0];
let q2 = p[1];
let q3 = p[2];
let vc = p[3];
let v2 = p[4];
let v3 = p[5];
let k10 = cl / vc;
let k12 = q2 / vc;
let k13 = q3 / vc;
let k21 = q2 / v2;
let k31 = q3 / v3;
let p_ke = V::from_vec(vec![k10, k12, k13, k21, k31], NalgebraContext);
three_compartments(x, &p_ke, t, rateiv, cov)
}
pub fn pm_three_compartments_cl(x: &V, p: &V, t: T, rateiv: &V, cov: &Covariates) -> V {
wrap_pmetrics_analytical(x, p, t, rateiv, cov, three_compartments_cl)
}
pub fn three_compartments_cl_with_absorption(
x: &V,
p: &V,
t: T,
rateiv: &V,
cov: &Covariates,
) -> V {
let ka = p[0];
let cl = p[1];
let q2 = p[2];
let q3 = p[3];
let vc = p[4];
let v2 = p[5];
let v3 = p[6];
let k10 = cl / vc;
let k12 = q2 / vc;
let k13 = q3 / vc;
let k21 = q2 / v2;
let k31 = q3 / v3;
let p_ke = V::from_vec(vec![ka, k10, k12, k13, k21, k31], NalgebraContext);
three_compartments_with_absorption(x, &p_ke, t, rateiv, cov)
}
pub fn pm_three_compartments_cl_with_absorption(
x: &V,
p: &V,
t: T,
rateiv: &V,
cov: &Covariates,
) -> V {
wrap_pmetrics_analytical(x, p, t, rateiv, cov, three_compartments_cl_with_absorption)
}
#[cfg(test)]
mod tests {
use super::super::tests::SubjectInfo;
use super::{three_compartments_cl, three_compartments_cl_with_absorption};
use crate::*;
use approx::assert_relative_eq;
#[test]
fn test_three_compartments_cl() {
let infusion_dosing = SubjectInfo::InfusionDosing;
let subject = infusion_dosing.get_subject();
let ode = equation::ODE::new(
|x, p, _t, dx, b, rateiv, _cov| {
fetch_params!(p, cl, q2, q3, vc, v2, v3);
let k10 = cl / vc;
let k12 = q2 / vc;
let k13 = q3 / vc;
let k21 = q2 / v2;
let k31 = q3 / v3;
dx[0] = rateiv[0] - (k10 + k12 + k13) * x[0] + k21 * x[1] + k31 * x[2] + b[0];
dx[1] = k12 * x[0] - k21 * x[1] + b[1];
dx[2] = k13 * x[0] - k31 * x[2] + b[2];
},
|_p, _t, _cov| lag! {},
|_p, _t, _cov| fa! {},
|_p, _t, _cov, _x| {},
|x, p, _t, _cov, y| {
fetch_params!(p, _cl, _q2, _q3, vc, _v2, _v3);
y[0] = x[0] / vc;
},
)
.with_nstates(3)
.with_nout(1)
.with_ndrugs(3);
let analytical = equation::Analytical::new(
three_compartments_cl,
|_p, _t, _cov| {},
|_p, _t, _cov| lag! {},
|_p, _t, _cov| fa! {},
|_p, _t, _cov, _x| {},
|x, p, _t, _cov, y| {
fetch_params!(p, _cl, _q2, _q3, vc, _v2, _v3);
y[0] = x[0] / vc;
},
)
.with_nstates(3)
.with_nout(1)
.with_ndrugs(3);
let op_ode = ode
.estimate_predictions(
&subject,
&crate::parameters::dense([0.1, 3.0, 2.0, 1.0, 3.0, 4.0]),
)
.unwrap();
let op_analytical = analytical
.estimate_predictions(
&subject,
&crate::parameters::dense([0.1, 3.0, 2.0, 1.0, 3.0, 4.0]),
)
.unwrap();
let pred_ode = &op_ode.flat_predictions()[..];
let pred_analytical = &op_analytical.flat_predictions()[..];
for (&od, &an) in pred_ode.iter().zip(pred_analytical.iter()) {
assert_relative_eq!(od, an, max_relative = 1e-3, epsilon = 1e-3);
}
}
#[test]
fn test_three_compartments_cl_with_absorption() {
let oral_infusion_dosing = SubjectInfo::OralInfusionDosage;
let subject = oral_infusion_dosing.get_subject();
let ode = equation::ODE::new(
|x, p, _t, dx, b, rateiv, _cov| {
fetch_params!(p, ka, cl, q2, q3, vc, v2, v3);
let k10 = cl / vc;
let k12 = q2 / vc;
let k13 = q3 / vc;
let k21 = q2 / v2;
let k31 = q3 / v3;
dx[0] = -ka * x[0] + b[0];
dx[1] = rateiv[0] - (k10 + k12 + k13) * x[1]
+ ka * x[0]
+ k21 * x[2]
+ k31 * x[3]
+ b[1];
dx[2] = k12 * x[1] - k21 * x[2] + b[2];
dx[3] = k13 * x[1] - k31 * x[3] + b[3];
},
|_p, _t, _cov| lag! {},
|_p, _t, _cov| fa! {},
|_p, _t, _cov, _x| {},
|x, p, _t, _cov, y| {
fetch_params!(p, _ka, _cl, _q2, _q3, vc, _v2, _v3);
y[0] = x[1] / vc;
},
);
let analytical = equation::Analytical::new(
three_compartments_cl_with_absorption,
|_p, _t, _cov| {},
|_p, _t, _cov| lag! {},
|_p, _t, _cov| fa! {},
|_p, _t, _cov, _x| {},
|x, p, _t, _cov, y| {
fetch_params!(p, _ka, _cl, _q2, _q3, vc, _v2, _v3);
y[0] = x[1] / vc;
},
);
let op_ode = ode
.estimate_predictions(
&subject,
&crate::parameters::dense([1.0, 0.1, 3.0, 2.0, 1.0, 3.0, 4.0]),
)
.unwrap();
let op_analytical = analytical
.estimate_predictions(
&subject,
&crate::parameters::dense([1.0, 0.1, 3.0, 2.0, 1.0, 3.0, 4.0]),
)
.unwrap();
let pred_ode = &op_ode.flat_predictions()[..];
let pred_analytical = &op_analytical.flat_predictions()[..];
for (&od, &an) in pred_ode.iter().zip(pred_analytical.iter()) {
assert_relative_eq!(od, an, max_relative = 1e-3, epsilon = 1e-3);
}
}
}