Skip to content

Commit 2ad2176

Browse files
mhovdSielCopilot
authored
feat: Normalized rows (#205)
* feat: add NormalizedRow API and ResidualErrorModel This commit adds two related features: ## NormalizedRow API (parser/) - New struct for format-agnostic data parsing - Decouples column mapping from event creation logic - Full ADDL/II expansion support (both positive and negative directions) - Refactors pmetrics.rs to use NormalizedRow internally - Enables external tools (like vial) to reuse parsing logic without reimplementing ADDL expansion ## ResidualErrorModel (data/) - New for parametric algorithms (SAEM, FOCE) - Uses prediction-based sigma (vs observation-based in ErrorModel) - Adds and functions - Documentation clarifying ErrorModel vs ResidualErrorModel usage Both features are independent but included together to avoid merge conflicts. Co-authored-by: Julián D. Otálvaro <juliandavid347@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent c36ba09 commit 2ad2176

File tree

28 files changed

+3080
-1118
lines changed

28 files changed

+3080
-1118
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
### Other
1313

14-
- *(Exa)* when installing Vial on MacOs, the environment varaibles are not completly shared to the sandbox in which Vial is running, this changes are meant to provide vial a better way to approach finding the rust binary ([#181](https://github.com/LAPKB/pharmsol/pull/181))
14+
- _(Exa)_ when installing Papir on MacOs, the environment varaibles are not completly shared to the sandbox in which Papir is running, this changes are meant to provide papir a better way to approach finding the rust binary ([#181](https://github.com/LAPKB/pharmsol/pull/181))
1515
- Update diffsol requirement from =0.7.0 to =0.8.0 ([#176](https://github.com/LAPKB/pharmsol/pull/176))
1616
- Update criterion requirement from 0.7.0 to 0.8.0 ([#177](https://github.com/LAPKB/pharmsol/pull/177))
1717
- Update libloading requirement from 0.8.6 to 0.9.0 ([#162](https://github.com/LAPKB/pharmsol/pull/162))
@@ -218,7 +218,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
218218

219219
- Add events to occasions
220220
- Expose functions for number of states and outeqs
221-
- Add support for multiple error models ([#65](https://github.com/LAPKB/pharmsol/pull/65))
221+
- Add support for multiple error models ([#65](https://github.com/LAPKB/pharmsol/pull/65))
222222

223223
## [0.9.1](https://github.com/LAPKB/pharmsol/compare/v0.9.0...v0.9.1) - 2025-05-22
224224

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ let ode = equation::ODE::new(
8787

8888
Analytical solutions provide 20-33× speedups compared to equivalent ODE formulations. See [benchmarks](benches/) for details.
8989

90-
## Documentation
90+
91+
92+
# Links
9193

9294
- [API Documentation](https://lapkb.github.io/pharmsol/pharmsol/)
9395
- [Examples](examples/)

examples/one_compartment.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,23 @@ fn main() -> Result<(), pharmsol::PharmsolError> {
5656
);
5757

5858
// Define the error models for the observations
59-
let ems = ErrorModels::new().
59+
let ems = AssayErrorModels::new().
6060
// For this example, we use a simple additive error model with 5% error
6161
add(
6262
0,
63-
ErrorModel::additive(ErrorPoly::new(0.0, 0.05, 0.0, 0.0), 0.0),
63+
AssayErrorModel::additive(ErrorPoly::new(0.0, 0.05, 0.0, 0.0), 0.0),
6464
)?;
6565

6666
// Define the parameter values for the simulations
6767
let ke = 1.022; // Elimination rate constant
6868
let v = 194.0; // Volume of distribution
6969

7070
// Compute likelihoods and predictions for both models
71-
let analytical_likelihoods = an.estimate_likelihood(&subject, &vec![ke, v], &ems, false)?;
71+
let analytical_likelihoods = an.estimate_log_likelihood(&subject, &vec![ke, v], &ems, false)?;
7272

7373
let analytical_predictions = an.estimate_predictions(&subject, &vec![ke, v])?;
7474

75-
let ode_likelihoods = ode.estimate_likelihood(&subject, &vec![ke, v], &ems, false)?;
75+
let ode_likelihoods = ode.estimate_log_likelihood(&subject, &vec![ke, v], &ems, false)?;
7676

7777
let ode_predictions = ode.estimate_predictions(&subject, &vec![ke, v])?;
7878

@@ -81,7 +81,7 @@ fn main() -> Result<(), pharmsol::PharmsolError> {
8181
println!("│ │ Analytical │ ODE │ Difference │");
8282
println!("├───────────┼─────────────────┼─────────────────┼─────────────────────┤");
8383
println!(
84-
"│ Likelihood│ {:>15.6} │ {:>15.6} │ {:>19.2e} │",
84+
"│ Log-Likeli│ {:>15.6} │ {:>15.6} │ {:>19.2e} │",
8585
analytical_likelihoods,
8686
ode_likelihoods,
8787
analytical_likelihoods - ode_likelihoods

src/data/builder.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ impl SubjectBuilder {
6666
///
6767
/// * `time` - Time of the bolus dose
6868
/// * `amount` - Amount of drug administered
69-
/// * `input` - The compartment number (zero-indexed) receiving the dose
69+
/// * `input` - The compartment number receiving the dose
7070
pub fn bolus(self, time: f64, amount: f64, input: usize) -> Self {
7171
let bolus = Bolus::new(time, amount, input, self.current_occasion.index());
7272
let event = Event::Bolus(bolus);
@@ -79,7 +79,7 @@ impl SubjectBuilder {
7979
///
8080
/// * `time` - Start time of the infusion
8181
/// * `amount` - Total amount of drug to be administered
82-
/// * `input` - The compartment number (zero-indexed) receiving the dose
82+
/// * `input` - The compartment number receiving the dose
8383
/// * `duration` - Duration of the infusion in time units
8484
pub fn infusion(self, time: f64, amount: f64, input: usize, duration: f64) -> Self {
8585
let infusion = Infusion::new(time, amount, input, duration, self.current_occasion.index());
@@ -93,8 +93,7 @@ impl SubjectBuilder {
9393
///
9494
/// * `time` - Time of the observation
9595
/// * `value` - Observed value (e.g., drug concentration)
96-
/// * `outeq` - Output equation number (zero-indexed) corresponding to this observation
97-
/// * `errorpoly` - Error polynomial coefficients (c0, c1, c2, c3)
96+
/// * `outeq` - Output equation number corresponding to this observation
9897
pub fn observation(self, time: f64, value: f64, outeq: usize) -> Self {
9998
let observation = Observation::new(
10099
time,

0 commit comments

Comments
 (0)