use anyhow::Result;
use pmcore::bestdose;
use pmcore::prelude::*;
use pmcore::routines::initialization::parse_prior;
fn main() -> Result<()> {
let eq = ode! {
diffeq: |x, p, _t, dx, b, _rateiv, _cov| {
fetch_params!(p, ke, _v);
dx[0] = -ke * x[0] + b[0];
},
out: |x, p, _t, _cov, y| {
fetch_params!(p, _ke, v);
y[0] = x[0] / v;
},
};
let params = Parameters::new()
.add("ke", 0.001, 3.0)
.add("v", 25.0, 250.0);
let ems = AssayErrorModels::new().add(
0,
AssayErrorModel::additive(ErrorPoly::new(0.0, 0.20, 0.0, 0.0), 0.0),
)?;
let mut settings = Settings::builder()
.set_algorithm(Algorithm::NPAG)
.set_parameters(params)
.set_error_models(ems.clone())
.build();
settings.disable_output();
fn conc(t: f64, dose: f64) -> f64 {
let ke = 0.3406021231412888; let v = 99.99475717544556; (dose * (-ke * t).exp()) / v
}
let subject = Subject::builder("Nikola Tesla")
.bolus(0.0, 150.0, 0)
.observation(2.0, conc(2.0, 150.0), 0)
.observation(4.0, conc(4.0, 150.0), 0)
.observation(6.0, conc(6.0, 150.0), 0)
.bolus(12.0, 75.0, 0)
.observation(14.0, conc(2.0, 75.0) + conc(14.0, 150.0), 0)
.observation(16.0, conc(4.0, 75.0) + conc(16.0, 150.0), 0)
.observation(18.0, conc(6.0, 75.0) + conc(18.0, 150.0), 0)
.build();
let past_data = subject.clone();
let target_data = Subject::builder("Thomas Edison")
.bolus(0.0, 0.0, 0)
.observation(2.0, conc(2.0, 150.0), 0)
.observation(4.0, conc(4.0, 150.0), 0)
.observation(6.0, conc(6.0, 150.0), 0)
.bolus(12.0, 0.0, 0)
.observation(14.0, conc(2.0, 75.0) + conc(14.0, 150.0), 0)
.observation(16.0, conc(4.0, 75.0) + conc(16.0, 150.0), 0)
.observation(18.0, conc(6.0, 75.0) + conc(18.0, 150.0), 0)
.build();
let (theta, prior) = parse_prior(
&"examples/bimodal_ke/output/theta.csv".to_string(),
&settings,
)
.unwrap();
let problem = bestdose::BestDoseProblem::new(
&theta,
&prior.unwrap(),
Some(past_data.clone()), target_data.clone(),
None,
eq.clone(),
bestdose::DoseRange::new(0.0, 300.0),
0.0,
settings.clone(),
bestdose::Target::Concentration, )?;
println!("Optimizing dose...");
let bias_weights = vec![0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0];
let mut results = Vec::new();
for bias_weight in &bias_weights {
println!("Running optimization with bias weight: {}", bias_weight);
let optimal = problem.clone().with_bias_weight(*bias_weight).optimize()?;
results.push((bias_weight, optimal));
}
for (bias_weight, optimal) in &results {
let opt_doses = optimal.doses();
println!(
"Bias weight: {:.2}\t\t Optimal dose: {:?}\t\tCost: {:.6}\t\tln Cost: {:.4}\t\tMethod: {}",
bias_weight,
opt_doses,
optimal.objf(),
optimal.objf().ln(),
optimal.optimization_method()
);
}
let optimal = &results.last().unwrap().1;
println!("\nConcentration-time predictions for optimal dose:");
for pred in optimal.predictions().predictions().into_iter() {
println!(
"Time: {:.2} h, Observed: {:.2}, (Pop Mean: {:.4}, Pop Median: {:.4}, Post Mean: {:.4}, Post Median: {:.4})",
pred.time(), pred.obs().unwrap_or(0.0), pred.pop_mean(), pred.pop_median(), pred.post_mean(), pred.post_median()
);
}
Ok(())
}