InVitroInVivoCorrelation.jl

Tools for Level A in vitro–in vivo correlation (IVIVC) pharmacometric modelling.

Experimental

This package is experimental. The API may change without notice in future releases.

Pipeline

The package provides a complete pipeline for Level A IVIVC:

  1. Dissolution profiles — Load in vitro dissolution data for each formulation
  2. UIR fitting — Fit poly-exponential unit impulse response from IV bolus or immediate-release data
  3. Deconvolution — Extract absorption profiles from in vivo concentration data
  4. Correlation fitting — Establish a functional relationship between dissolution and absorption
  5. Prediction & validation — Predict in vivo behavior for held-out or new formulations

Getting started

run_ivivc runs the whole pipeline: DataFrames in, fitted model and prediction outputs out. The example runs on the Simulated Data used throughout this documentation: 20 subjects in a crossover design receive an IV bolus reference and three oral formulations (FormA–FormC), dissolution profiles exist for four formulations (FormA–FormD), sampling times differ per subject, and four profiles are missing.

PK data is one row per observation with subject, formulation, time and concentration columns; dissolution data is one row per time point with formulation, time and fraction dissolved:

first(pk_df, 5)
5×4 DataFrame
Rowidformulationtimeconc
Int64StringFloat64Float64
11FormA0.00.0
21FormA0.4790170.252104
31FormA0.9406820.766301
41FormA1.51661.48553
51FormA2.06182.15264
first(diss_df, 5)
5×3 DataFrame
Rowformulationtimediss
StringFloat64Float64
1FormA0.00.0
2FormA0.5211240.0463696
3FormA1.074570.130579
4FormA1.410230.189439
5FormA1.98150.294384

fast_formulation names the reference formulation the unit impulse responses are fitted to, and validation_formulation keeps one formulation out of the correlation fit so its prediction can be checked against the observed data:

result = run_ivivc(
    pk_df,
    diss_df;
    fast_formulation = "IV",
    validation_formulation = "FormB",
);

Every exclusion a pipeline stage makes is recorded with its stage and reason. Subject 1 has no IV profile: no unit impulse response can be fitted, and the subject's three oral profiles cannot be deconvolved.

DataFrame(result.skipped)
4×3 DataFrame
Rowidstagereason
Int64SymbolString
11uir_fitno profile for fast_formulation=IV
21deconvolutionno fitted UIR available (formulation=FormA)
31deconvolutionno fitted UIR available (formulation=FormB)
41deconvolutionno fitted UIR available (formulation=FormC)

The fitted AffineTimeLinearModel maps in vivo time to in vitro time (time_scale, time_shift) and fraction dissolved to fraction absorbed (abs_scale, abs_intercept). The simulation makes in vivo absorption 1.2 times slower than in vitro dissolution, so the true values are a time scale of 1/1.2 ≈ 0.83, no time shift, unit slope and zero intercept:

coeftable(result.model)
4×3 DataFrame
Rowparameterconstantestimate
SymbolBoolFloat64
1abs_scalefalse0.990322
2abs_interceptfalse0.00106438
3time_scalefalse0.842282
4time_shiftfalse-0.0818941

The held-out formulation is predicted and scored against the observed mean profile. The prediction error follows the FDA convention, %PE = (observed - predicted) / observed × 100 on AUC and Cmax, so a positive value means the model under-predicts. The acceptance criterion applies to absolute values: mean |%PE| ≤ 10% and individual |%PE| ≤ 15%.

result.pe_summary_df
1×7 DataFrame
Rowformulationauc_predictedauc_observedpe_auccmax_predictedcmax_observedpe_cmax
StringFloat64Float64Float64Float64Float64Float64
1FormB50.062450.4560.78022.859122.878570.675749

Plot recipes take the result directly:

ivivc_correlation(result)
Example block output
levy_plot(result)
Example block output
concentration_profiles(result; kind = :validation, formulation = "FormB")
Example block output

The how-to guides adapt this workflow to other study designs and inputs, and the Low-Level API page runs the same analysis one stage at a time.