Skip to content

1.0.0

Choose a tag to compare

@github-actions github-actions released this 15 Sep 14:55
· 34 commits to develop since this release
467eb5a

Release notes for pkpdutils 1.0.0

pkpdutils 1.0.0 is a rewrite of pkdb-analysis as a library for the pharmacokinetic and pharmacodynamic analysis of timecourses and parameters, without any dependency on PK-DB. The package, the repository and the documentation carry the new name: pypi.org/project/pkpdutils, github.com/matthiaskoenig/pkpdutils, matthiaskoenig.github.io/pkpdutils. pkdb-analysis stays available on PyPI at 0.3.1 and receives no further releases.

Breaking changes

  • The package is pkpdutils; pkdb_analysis is gone. Everything PK-DB specific was removed: the client (PKData, PKFilter, queries, the environment variables), the reports (LaTeX, Jekyll, interactive plots, tables, spreadsheets), the Gaussian process kernels, the circos plots and the caffeine utilities. PK-DB access is the job of the PK-DB tooling, not of this library.
  • The pharmacokinetic analysis moved from pkdb_analysis.pk.pharmacokinetics.TimecoursePK to pkpdutils.nca on a new data model (Timecourse, Timecourses, Dose, Route, DosingRegimen), with new parameter names and new default methods; see the migration note below.
  • Python 3.13 or newer is required (3.13 and 3.14 are tested on Linux, macOS and Windows). The dependencies are numpy, scipy, pandas, xarray, pint, pydantic, matplotlib and rich; requests, depinfo, coloredlogs, openpyxl, XlsxWriter, pyyaml, gspread-pandas, altair, seaborn, scikit-learn and IPython are no longer needed.
  • The library does not configure logging and does not print; pkpdutils.log.enable_rich_logging() is the opt-in for scripts.

Features

  • Data model (pkpdutils.timecourse): Timecourse for one curve with units, uncertainties (sd, se, n), a Dose with a Route and metadata; Timecourses as an xarray.Dataset over a time dimension and any sample dimensions, built from timecourses, data frames, arrays or a simulation dataset; DosingRegimen for steady state.
  • Units (pkpdutils.units): one pint registry, quantities at the boundaries, result units derived from the units of the input.
  • Non-compartmental analysis (pkpdutils.nca): exposure, peak, terminal phase, clearance and volume parameters of concentration curves and the descriptive parameters of effect curves, for iv bolus, iv infusion and extravascular dosing, single dose and steady state (with superposition), vectorized over a batch with an optional process pool; the terminal phase by best adjusted R², last n points, all points after tmax or a manual window; linear, linear-up/log-down and log trapezoids; integer flags per sample; results as NCAResult, an xarray.Dataset with attrs["units"] per variable.
  • Uncertainty (pkpdutils.nca.uncertainty): parametric bootstrap and delta method for group timecourses (mean with SD or SE and n), summarize over the individuals with the same variables, partial areas.
  • Curve fitting (pkpdutils.fit): mono-, bi- and tri-exponential, Bateman, Emax, sigmoid Emax, Imax, linear, log-linear, power and allometric models; least squares in a scaled parameter space from Latin hypercube starts, standard errors from the Jacobian, t intervals, delta method for derived parameters, residual bootstrap, AIC/AICc/BIC and Akaike weights (compare_models), the confidence interval criterion of dose proportionality (proportionality_test); fit_timecourse, fit_timecourses and fit_table.
  • Statistics on parameters (pkpdutils.stats): ParameterSample from a result or from published summary statistics; compare (Student, Welch and paired t, Mann-Whitney, Wilcoxon, permutation, effect sizes) and multiple_comparison (Holm, Bonferroni, Benjamini-Hochberg); the geometric mean ratio (ratio); average bioequivalence by the two one-sided tests for parallel, paired and 2x2 crossover designs (bioequivalence, tost); the FDA/EMA classification of drug-drug interactions (ddi_classification, substrate_sensitivity); fixed effect and DerSimonian-Laird random effects meta-analysis with heterogeneity statistics (meta_analysis).
  • Figures (pkpdutils.plot): timecourses, the NCA diagnostic figure and grid, fits with residuals, goodness of fit, Bland-Altman, dose proportionality, parameter distributions, ratio plots against bioequivalence limits or interaction thresholds, forest plots. Functions return the Figure and never show it.
  • Documentation: a user guide per topic with concepts, math, parameter tables, API examples and references, the API reference from the docstrings, runnable examples in examples/, and the llms.txt files for agents.
  • Tooling: uv, hatchling, ruff, ty, tox, pre-commit, bump-my-version, Zensical; pull requests into develop with the checks tests, ruff, ty and docs; releases by tag with trusted publishing to PyPI.

Known gaps and decisions

  • The parameter aliases kel and auc_inf of the design document are not provided; the names are lambda_z and auc_inf_obs / auc_inf_pred.
  • cmax_half and tmax_half are computed for extravascular dosing only; exclude_cmax=False leaves the start of the terminal window unrestricted; cmax_ss (the maximum within one dosing interval) drives fluctuation and swing; a bolus with pre-dose samples interpolates the value at the dose time for auc_tau.
  • A Timecourses batch has one route; batches with mixed routes are analysed separately.
  • Fitted parameters are reported in the raw units of the data (no normalization of volumes and clearances); the information criteria count the residual variance as an estimated parameter (K = k + 1); the exponential phases are ordered by decreasing rate; the residual bootstrap centers and inflates the residuals and falls back to the Jacobian intervals with FitFlag.BOOTSTRAP_FALLBACK when fewer than two replicates converge; plot_fit draws no bootstrap band.
  • compare reports ci_low/ci_high and the effect sizes with every test; the rank tests report the difference or ratio of the medians without an interval; samples of one value or without variance give NaN statistics rather than an error.
  • bioequivalence takes two results and a sample dimension; the 2x2 crossover is the period-difference analysis of Chow and Liu, which equals the ANOVA with sequence, period and subject effects, and is verified against an ordinary least squares fit with subject effects rather than against a textbook data set.
  • ddi_classification classifies on the AUC ratio and reports the Cmax ratio; the EMA thresholds equal the FDA ones.
  • The meta-analysis pools Study objects (meta_analysis_by groups them by category); the variance of Hedges' g is J² var(d); the regression reference is the BCG example of the R package metafor.
  • Compartmental and ODE models, population modelling, covariate model building and report generation are out of scope.

Migration from pkdb-analysis

TimecoursePK becomes a Timecourse and a call of nca_single; a batch of curves is a Timecourses and a call of nca:

from pkpdutils import Dose, Route, Timecourse, nca_single
from pkpdutils.plot import plot_nca

tc = Timecourse(
    time=time,
    value=concentration,
    time_unit="hr",
    unit="mg/l",
    dose=Dose(amount=100, unit="mg", route=Route.ORAL, time=0.0),
    substance="caffeine",
)
result = nca_single(tc)
result.to_quantities()["auc_inf_obs"]  # pint quantity
result.to_dataframe()  # one row with every parameter
plot_nca(tc, result)  # the diagnostic figure of TimecoursePK.figure()
TimecoursePK.pk (0.3.1) NCAResult (1.0.0)
auc auc_last
aucinf auc_inf_obs (observed last value) and auc_inf_pred (predicted)
tmax, cmax tmax, cmax
tmaxhalf, cmaxhalf tmax_half, cmax_half (extravascular dosing)
kel lambda_z
thalf thalf
slope, intercept, r_value, std_err lambda_z, lambda_z_intercept, lambda_z_r2, lambda_z_stderr (lambda_z_r2_adj, lambda_z_n_points, lambda_z_t_first are new)
p_value, max_idx dropped
vd vz (iv) or vz_f (extravascular)
vdss vss
cl cl (iv) or cl_f (extravascular)
dose dose_amount of the batch; auc_inf_dn, cmax_dn are the dose normalized values
info() to_dataframe(), to_quantities(), flags()
figure() plot_nca(timecourse, result)

The defaults changed: the terminal phase is chosen by the best adjusted R² of at least three points after cmax, and the area uses the linear-up/log-down trapezoid. The numbers of 0.3.1 are reproduced with

from pkpdutils.nca import AUCMethod, NCAOptions, TerminalMethod, TerminalPhase

options = NCAOptions(
    auc_method=AUCMethod.LINEAR,
    terminal=TerminalPhase(method=TerminalMethod.ALL_AFTER_TMAX),
)
result = nca_single(tc, options)

which is what tests/nca/test_reference.py checks against the frozen results of 0.3.1.

The effect analysis of pkdb_analysis.reports.effect_analysis (OutputPair, fixed_effect, random_effects) is pkpdutils.stats.meta (effect_size, fixed_effect, random_effects, meta_analysis); the pairs are Study(label, control, treatment) objects built from ParameterSample values or summary statistics.

Your pkpdutils team