Skip to content

Commit 1e15432

Browse files
authored
feat: Improve error handling (#58)
* chore: Implement serialie/deserialize for ErrorModel * refactor: Creating predictions from observations Also adding tests to ErrorModel * WIP * WIP * WIP, seems to be working * Update BKE example results print * Update bke.rs * Handle ShapeError * Handle CSV errors * More errors * Fix tests for exa * Handle progress bar errors * Remove unwrap * Do not cache errors * Cache results, impl From instead of Into for Prediction to Observation * Convenience function for variance * Provide more methods for calculating sigma and variance * Handle errors in psi * Error handling for likelihood * Provide to_observation for Prediction * ErrorPoly as a struct
1 parent 2763504 commit 1e15432

26 files changed

+525
-259
lines changed

benches/ode.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ fn one_compartment() {
3232
},
3333
(2, 1),
3434
);
35-
black_box(ode.estimate_predictions(&subject, &vec![0.3, 0.5, 0.1, 70.0]));
35+
black_box(
36+
ode.estimate_predictions(&subject, &vec![0.3, 0.5, 0.1, 70.0])
37+
.unwrap(),
38+
);
3639
}
3740

3841
fn two_compartment() {
@@ -55,7 +58,10 @@ fn two_compartment() {
5558
},
5659
(2, 1),
5760
);
58-
black_box(ode.estimate_predictions(&subject, &vec![0.3, 0.5, 0.1, 0.04, 0.08, 70.0]));
61+
black_box(
62+
ode.estimate_predictions(&subject, &vec![0.3, 0.5, 0.1, 0.04, 0.08, 70.0])
63+
.unwrap(),
64+
);
5965
}
6066

6167
fn criterion_benchmark(c: &mut Criterion) {

benches/performance.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ fn readme(n: usize) {
3939
(2, 1),
4040
);
4141
for _ in 0..n {
42-
let op = ode.estimate_predictions(&subject, &vec![0.3, 0.5, 0.1, 70.0]);
42+
let op = ode
43+
.estimate_predictions(&subject, &vec![0.3, 0.5, 0.1, 70.0])
44+
.unwrap();
4345
black_box(op);
4446
}
4547
}

examples/bke.rs

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,45 @@ fn main() {
4141
(1, 1),
4242
);
4343

44-
let em = ErrorModel::additive((0.0, 0.05, 0.0, 0.0), 0.0);
45-
let ll = an.estimate_likelihood(
46-
&subject,
47-
&vec![1.02282724609375, 194.51904296875],
48-
&em,
49-
false,
50-
);
51-
let op = an.estimate_predictions(&subject, &vec![1.02282724609375, 194.51904296875]);
52-
println!(
53-
"Analytical: \n-2ll:{:#?}\n{:#?}",
54-
-2.0 * ll,
55-
op.flat_predictions()
56-
);
44+
let em = ErrorModel::additive(ErrorPoly::new(0.0, 0.05, 0.0, 0.0), 0.0);
5745

58-
let ll = ode.estimate_likelihood(
59-
&subject,
60-
&vec![1.02282724609375, 194.51904296875],
61-
&em,
62-
false,
63-
);
64-
let op = ode.estimate_predictions(&subject, &vec![1.02282724609375, 194.51904296875]);
65-
println!("ODE: \n-2ll:{:#?}\n{:#?}", -2.0 * ll, op.flat_predictions());
46+
// Compute likelihoods and predictions for both models
47+
let ll_an = an
48+
.estimate_likelihood(
49+
&subject,
50+
&vec![1.02282724609375, 194.51904296875],
51+
&em,
52+
false,
53+
)
54+
.unwrap();
55+
let op_an = an
56+
.estimate_predictions(&subject, &vec![1.02282724609375, 194.51904296875])
57+
.unwrap();
58+
59+
let ll_ode = ode
60+
.estimate_likelihood(
61+
&subject,
62+
&vec![1.02282724609375, 194.51904296875],
63+
&em,
64+
false,
65+
)
66+
.unwrap();
67+
let op_ode = ode
68+
.estimate_predictions(&subject, &vec![1.02282724609375, 194.51904296875])
69+
.unwrap();
70+
71+
// Display likelihoods side by side
72+
println!("Likelihoods:");
73+
println!("Analytical\tODE");
74+
println!("{:.6}\t:{:.6}", -2.0 * ll_an, -2.0 * ll_ode);
75+
println!();
76+
77+
// Display predictions
78+
println!("Predictions:");
79+
println!("Analytical\tODE\tDifference");
80+
op_an
81+
.flat_predictions()
82+
.iter()
83+
.zip(op_ode.flat_predictions())
84+
.for_each(|(a, b)| println!("{:.9}\t{:.9}\t{:.9}", a, b, a - b));
6685
}

examples/error.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ fn main() {
3939
.repeat(120, 0.1)
4040
.build();
4141

42-
let op = ode.estimate_predictions(&subject, &vec![0.1, 0.1, 0.1, 0.1, 70.0]);
42+
let op = ode
43+
.estimate_predictions(&subject, &vec![0.1, 0.1, 0.1, 0.1, 70.0])
44+
.unwrap();
4345
dbg!(op);
4446
}

examples/exa.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ fn main() {
6868
let params = vec![1.02282724609375, 194.51904296875];
6969

7070
// Get predictions from both models
71-
let dyn_predictions = dyn_ode.estimate_predictions(&subject, &params);
72-
let ode_predictions = ode.estimate_predictions(&subject, &params);
71+
let dyn_predictions = dyn_ode.estimate_predictions(&subject, &params).unwrap();
72+
let ode_predictions = ode.estimate_predictions(&subject, &params).unwrap();
7373

7474
// Check that predictions are the same
7575
let dyn_flat = dyn_predictions.flat_predictions();

examples/gendata.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ fn main() {
6262

6363
let mut data = vec![];
6464
for (i, spp) in support_points.iter().enumerate() {
65-
let trajectories = sde.estimate_predictions(&subject, spp);
65+
let trajectories = sde.estimate_predictions(&subject, spp).unwrap();
6666
let trajectory = trajectories.row(0);
6767
// dbg!(&trajectory);
6868
let mut sb = data::Subject::builder(format!("id{}", i)).bolus(0.0, 20.0, 0);
@@ -72,7 +72,8 @@ fn main() {
7272
data.push(sb.build());
7373
}
7474
let data = data::Data::new(data);
75-
data.write_pmetrics(&File::create(Path::new("test.csv")).unwrap());
75+
data.write_pmetrics(&File::create(Path::new("test.csv")).unwrap())
76+
.unwrap();
7677
// let mut theta = Array2::zeros((1, 3));
7778
// theta[[0, 0]] = 0.7;
7879
// theta[[0, 1]] = 0.1;

examples/ode_readme.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ fn main() {
3535
(2, 1),
3636
);
3737

38-
let op = ode.estimate_predictions(&subject, &vec![0.3, 0.5, 0.1, 70.0]);
38+
let op = ode
39+
.estimate_predictions(&subject, &vec![0.3, 0.5, 0.1, 70.0])
40+
.unwrap();
3941
println!("{:#?}", op.flat_predictions());
4042
}

examples/pf.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,14 @@ fn main() {
2828
(2, 1),
2929
10000,
3030
);
31-
let em = ErrorModel::additive((0.0, 0.05, 0.0, 0.0), 0.0);
31+
let em = ErrorModel::additive(ErrorPoly::new(0.0, 0.05, 0.0, 0.0), 0.0);
3232

33-
let ll = sde.estimate_likelihood(&subject, &vec![1.0], &em, false);
33+
let ll = sde
34+
.estimate_likelihood(&subject, &vec![1.0], &em, false)
35+
.unwrap();
3436

35-
dbg!(sde.estimate_likelihood(&subject, &vec![1.0], &em, false));
37+
dbg!(sde
38+
.estimate_likelihood(&subject, &vec![1.0], &em, false)
39+
.unwrap());
3640
println!("{ll:#?}");
3741
}

examples/sde.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ fn main() {
106106
.repeat(5, 0.2)
107107
.build();
108108

109-
let ode_predictions = ode.estimate_predictions(&subject, &vec![1.0]);
110-
let sde_predictions = sde.estimate_predictions(&subject, &vec![1.0, 0.0]);
109+
let ode_predictions = ode.estimate_predictions(&subject, &vec![1.0]).unwrap();
110+
let sde_predictions = sde.estimate_predictions(&subject, &vec![1.0, 0.0]).unwrap();
111111

112112
let mut sde_flat_predictions: Vec<Vec<f64>> = Vec::new();
113113
for trajectory in sde_predictions.rows() {
@@ -141,8 +141,8 @@ fn main() {
141141
0.0,
142142
];
143143

144-
let ode_predictions = ode.estimate_predictions(&subject, &spp_ode);
145-
let sde_predictions = sde.estimate_predictions(&subject, &spp_sde);
144+
let ode_predictions = ode.estimate_predictions(&subject, &spp_ode).unwrap();
145+
let sde_predictions = sde.estimate_predictions(&subject, &spp_sde).unwrap();
146146

147147
let mut sde_flat_predictions: Vec<Vec<f64>> = Vec::new();
148148
for trajectory in sde_predictions.rows() {
@@ -164,8 +164,8 @@ fn main() {
164164
let data = read_pmetrics("../PMcore/examples/vanco_sde/data.csv").unwrap();
165165
let subject = data.get_subject("51").unwrap();
166166

167-
let ode_predictions = ode.estimate_predictions(subject, &spp_ode);
168-
let sde_predictions = sde.estimate_predictions(subject, &spp_sde);
167+
let ode_predictions = ode.estimate_predictions(subject, &spp_ode).unwrap();
168+
let sde_predictions = sde.estimate_predictions(subject, &spp_sde).unwrap();
169169

170170
let mut sde_flat_predictions: Vec<Vec<f64>> = Vec::new();
171171
for trajectory in sde_predictions.rows() {

src/data/builder.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ impl SubjectBuilder {
115115
time: f64,
116116
value: f64,
117117
outeq: usize,
118-
errorpoly: Option<(f64, f64, f64, f64)>,
118+
errorpoly: Option<ErrorPoly>,
119119
ignore: bool,
120120
) -> Self {
121121
let observation = Observation::new(time, value, outeq, errorpoly, ignore);
@@ -299,7 +299,13 @@ mod tests {
299299
.bolus(0.0, 50.0, 0)
300300
.observation(1.0, 45.3, 0)
301301
.observation(2.0, 40.1, 0)
302-
.observation_with_error(3.0, 36.5, 0, Some((0.1, 0.05, 0.0, 0.0)), false)
302+
.observation_with_error(
303+
3.0,
304+
36.5,
305+
0,
306+
Some(ErrorPoly::new(0.1, 0.05, 0.0, 0.0)),
307+
false,
308+
)
303309
.bolus(4.0, 50.0, 0)
304310
.repeat(1, 12.0) // Repeat bolus at 16.0
305311
.reset()

0 commit comments

Comments
 (0)