|
4 | 4 | [](https://github.com/LAPKB/pharmsol/actions/workflows/docs.yml) |
5 | 5 | [](https://crates.io/crates/pharmsol) |
6 | 6 |
|
7 | | -Simulate PK/PD profiles using ordinary and stochastic differential equations, or analytical models. |
| 7 | +A high-performance Rust library for pharmacokinetic/pharmacodynamic (PK/PD) simulation using analytical solutions, ordinary differential equations (ODEs), or stochastic differential equations (SDEs). |
8 | 8 |
|
9 | | -## Example |
| 9 | +## Installation |
10 | 10 |
|
11 | | -ODE based model. |
| 11 | +Add `pharmsol` to your `Cargo.toml`, either manually or using |
12 | 12 |
|
13 | | -```rust |
14 | | - use pharmsol::*; |
15 | | - |
16 | | - // Subject data can be generated using the builder pattern |
17 | | - let subject = Subject::builder("id1") |
18 | | - .bolus(0.0, 100.0, 0) |
19 | | - .repeat(2, 0.5) |
20 | | - .observation(0.5, 0.1, 0) |
21 | | - .observation(1.0, 0.4, 0) |
22 | | - .observation(2.0, 1.0, 0) |
23 | | - .observation(2.5, 1.1, 0) |
24 | | - .covariate("wt", 0.0, 80.0) |
25 | | - .covariate("wt", 1.0, 83.0) |
26 | | - .covariate("age", 0.0, 25.0) |
27 | | - .build(); |
28 | | - |
29 | | - let ode = equation::ODE::new( |
30 | | - |x, p, t, dx, _rateiv, cov| { |
31 | | - // The following are helper functions to fetch parameters and covariates |
32 | | - fetch_cov!(cov, t, _wt, _age); |
33 | | - fetch_params!(p, ka, ke, _tlag, _v); |
34 | | - |
35 | | - // The ODEs are defined here |
36 | | - dx[0] = -ka * x[0]; |
37 | | - dx[1] = ka * x[0] - ke * x[1]; |
38 | | - }, |
39 | | - |p| { |
40 | | - fetch_params!(p, _ka, _ke, tlag, _v); |
41 | | - lag! {0=>tlag} |
42 | | - }, |
43 | | - |_p, _t, _cov| fa! {}, |
44 | | - |_p, _t, _cov, _x| {}, |
45 | | - |x, p, _t, _cov, y| { |
46 | | - fetch_params!(p, _ka, _ke, _tlag, v); |
47 | | - // This equation specifies the output, e.g. the measured concentrations |
48 | | - y[0] = x[1] / v; |
49 | | - }, |
50 | | - (2, 1), |
51 | | - ); |
52 | | - |
53 | | - let op = ode.estimate_predictions(&subject, &vec![0.3, 0.5, 0.1, 70.0]); |
54 | | - // println!("{op:#?}"); |
55 | | - let _ = op.run(); |
| 13 | +```bash |
| 14 | +cargo add pharmsol |
56 | 15 | ``` |
57 | 16 |
|
58 | | -Analytic based model. |
| 17 | +## Quick Start |
59 | 18 |
|
60 | 19 | ```rust |
61 | 20 | use pharmsol::*; |
| 21 | + |
| 22 | +// Create a subject with an IV infusion and observations |
| 23 | +let subject = Subject::builder("patient_001") |
| 24 | + .infusion(0.0, 500.0, 0, 0.5) // 500 units over 0.5 hours |
| 25 | + .observation(0.5, 1.645, 0) |
| 26 | + .observation(1.0, 1.216, 0) |
| 27 | + .observation(2.0, 0.462, 0) |
| 28 | + .observation(4.0, 0.063, 0) |
| 29 | + .build(); |
| 30 | + |
| 31 | +// Define parameters: ke (elimination rate), v (volume) |
| 32 | +let ke = 1.022; |
| 33 | +let v = 194.0; |
| 34 | + |
| 35 | +// Use the built-in one-compartment analytical solution |
62 | 36 | let analytical = equation::Analytical::new( |
63 | | - one_compartment_with_absorption, |
64 | | - |_p, _cov| {}, |
65 | | - |p| { |
66 | | - fetch_params!(p, _ka, _ke, tlag, _v); |
67 | | - lag! {0=>tlag} |
68 | | - }, |
| 37 | + one_compartment, |
| 38 | + |_p, _t, _cov| {}, |
| 39 | + |_p, _t, _cov| lag! {}, |
69 | 40 | |_p, _t, _cov| fa! {}, |
70 | 41 | |_p, _t, _cov, _x| {}, |
71 | 42 | |x, p, _t, _cov, y| { |
72 | | - fetch_params!(p, _ka, _ke, _tlag, v); |
73 | | - y[0] = x[1] / v; |
| 43 | + fetch_params!(p, _ke, v); |
| 44 | + y[0] = x[0] / v; // Concentration = Amount / Volume |
74 | 45 | }, |
75 | | - (2, 1), |
| 46 | + (1, 1), // (compartments, outputs) |
76 | 47 | ); |
77 | | -let op = analytical.simulate_subject(&subject, &vec![0.3, 0.5, 0.1, 70.0]); |
78 | | -println!("{op:#?}"); |
| 48 | + |
| 49 | +// Get predictions |
| 50 | +let predictions = analytical.estimate_predictions(&subject, &vec![ke, v]).unwrap(); |
79 | 51 | ``` |
80 | 52 |
|
81 | | -## Supported analytical models |
| 53 | +## ODE-Based Models |
| 54 | + |
| 55 | +For custom or complex models, define your own ODEs: |
| 56 | + |
| 57 | +```rust |
| 58 | +use pharmsol::*; |
| 59 | + |
| 60 | +let ode = equation::ODE::new( |
| 61 | + |x, p, _t, dx, _b, rateiv, _cov| { |
| 62 | + fetch_params!(p, ke, _v); |
| 63 | + // One-compartment model with IV infusion support |
| 64 | + dx[0] = -ke * x[0] + rateiv[0]; |
| 65 | + }, |
| 66 | + |_p, _t, _cov| lag! {}, |
| 67 | + |_p, _t, _cov| fa! {}, |
| 68 | + |_p, _t, _cov, _x| {}, |
| 69 | + |x, p, _t, _cov, y| { |
| 70 | + fetch_params!(p, _ke, v); |
| 71 | + y[0] = x[0] / v; |
| 72 | + }, |
| 73 | + (1, 1), |
| 74 | +); |
| 75 | +``` |
82 | 76 |
|
83 | | -We are working to support all the standard analytical models. |
| 77 | +## Supported Analytical Models |
84 | 78 |
|
85 | 79 | - [x] One-compartment with IV infusion |
86 | 80 | - [x] One-compartment with IV infusion and oral absorption |
87 | 81 | - [x] Two-compartment with IV infusion |
88 | 82 | - [x] Two-compartment with IV infusion and oral absorption |
89 | | -- [ ] Three-compartmental models |
| 83 | +- [x] Three-compartment with IV infusion |
| 84 | +- [x] Three-compartment with IV infusion and oral absorption |
| 85 | + |
| 86 | +## Performance |
| 87 | + |
| 88 | +Analytical solutions provide 20-33× speedups compared to equivalent ODE formulations. See [benchmarks](benches/) for details. |
90 | 89 |
|
91 | | -# Links |
| 90 | +## Documentation |
92 | 91 |
|
93 | | -[Documentation](https://lapkb.github.io/pharmsol/pharmsol/) |
94 | | -[Benchmarks](https://lapkb.github.io/pharmsol/dev/bench/) |
| 92 | +- [API Documentation](https://lapkb.github.io/pharmsol/pharmsol/) |
| 93 | +- [Examples](examples/) |
0 commit comments