Skip to content

Releases: matthiaskoenig/pkpdutils

1.3.0

Choose a tag to compare

@github-actions github-actions released this 25 Sep 11:51
40214d4

Release notes for pkpdutils 1.3.0

Minor release of pkpdutils which compares the non-compartmental analysis against the public benchmark suite of the NonCompart validation report (#103): all eight scenarios (theophylline and indomethacin, intravenous bolus, 0.25 h infusion and extravascular dose, linear and linear-up / log-down trapezoids) against the published Phoenix WinNonlin output and against PKNCA 0.12.1 and NonCompart 0.8.4 run on the same data, plus analytical profiles with an exact answer. Every parameter of every subject agrees with all three tools, to the digits the published tables carry. The comparison found one important difference, now fixed: the area of an extravascular dose whose first sample comes after the dose. The new pkpdutils.crosswalk writes and reads the result tables of the three tools, and every result carries the predicted variants of the extrapolated parameters.

Important fixes

  • The area of an extravascular single dose starts at the dose. A curve whose first sample comes after the dose now gets a zero inserted at the dose time for the areas (never for the terminal regression), as for an infusion and as Phoenix WinNonlin, PKNCA and NonCompart all do. Up to 1.2.0 the area of such a curve started at its first sample, which was deliberately left out of the zero rule in 1.2.0; the benchmark shows that every reference tool applies it, and without it auc_last, auc_all, auc_inf_obs, aumc_*, mrt, cl_f, vz_f and the extrapolated fractions of the extravascular indomethacin profiles were up to 13 % off. A curve with a sample at the dose (the theophylline study) is unchanged. partial_auc and the urine analysis already applied the rule; the documentation of nca_urine described it.
  • The NCA figure shades the area the analysis computed. plot_nca, plot_nca_grid and draw_nca_panel shade AUC(0-tlast) from the dose, with the value the analysis inserts there (the back-extrapolated C0 after a bolus, 0 after an infusion or an extravascular dose) and a dotted segment to the first sample; before, the shading started at the first sample and left out the area the reported number contains.

Breaking changes

  • auc_last, auc_all, auc_inf_obs, auc_inf_pred, aumc_last, aumc_inf, mrt, thalf_eff, cl_f, vz_f, auc_extrap_fraction, the dose normalized areas and everything computed from them (summaries, ratios, bioequivalence, the uncertainty) change for an extravascular single dose curve whose first sample is after the dose; see "Important fixes". A BLQ value at the dose which a rule drops leaves the same gap and is filled with the same zero.
  • Every NCAResult of a single dose analysis carries the new variables below, so to_dataframe, to_pp and the tables have more columns.

Non-compartmental analysis

  • The predicted variants of Phoenix WinNonlin and PKNCA, from the value of the terminal regression at tlast (clast_pred): aumc_inf_pred, mrt_pred, cl_pred / cl_f_pred, vz_pred / vz_f_pred, vss_pred, auc_inf_pred_dn, auc_extrap_fraction_pred and auc_back_extrap_fraction_pred; and aumc_extrap_fraction, aumc_extrap_fraction_pred and mrt_last, the mean residence time to the last measurable value. The mean residence times of an infusion are corrected by half its duration. Their CDISC codes (AUMCIFP, MRTEVIFP / MRTIBIFP / MRTICIFP, CLP, CLFP, VZP, VZFP, VSSP, AUCIFPD, AUCPEP, AUCPBEP, AUMCPEO, AUMCPEP, MRTEVLST / MRTIBLST / MRTICLST) are extracted from the same NCI EVS terminology file as the others, and the fractions are written as percentages in the PP domain.

Data formats

  • pkpdutils.crosswalk, the result tables of other tools: to_winnonlin / write_winnonlin / read_winnonlin (the "Final Parameters Pivoted" table of Phoenix WinNonlin), to_pknca_results / write_pknca_results / read_pknca_results (the long table of as.data.frame(pk.nca(...))) and to_noncompart / write_noncompart / read_noncompart (the table of NonCompart::tblNCA), with the name maps WINNONLIN_NAMES, PKNCA_NAMES, NONCOMPART_NAMES and their route dependent parts. The writers export the percentages of the tools, the readers return the variables of pkpdutils with fractions, so a published result compares column by column.
  • Timecourses.from_dataframe(dose_duration=...) reads the infusion duration from a column, constant per sample or one per dose with dose_time.

Validation

  • docs/benchmark_datasets.md: the eight scenarios with every setting in docs/data/benchmarks/scenarios.csv, the code of the comparison, the largest deviation per parameter and tool, the exported tables and the analytical profiles (the exact monoexponential bolus and the convergence of the trapezoid on a Bateman curve). Every table is the printed output of the code above it, pasted by scripts/benchmark_datasets.py; tests/docs/test_benchmark_datasets.py fails when the page is stale and tests/nca/test_benchmark_datasets.py asserts the agreement within 1e-8.
  • docs/data/benchmarks/ holds the theophylline and indomethacin datasets (moved from tests/data/validation/), the eight WinNonlin tables of the report unchanged and the PKNCA and NonCompart results, which scripts/benchmark_datasets.R recomputes.

Python

  • Python 3.15 is supported and tested on Linux, macOS and Windows (#104).

Documentation

  • The snippets of the documentation may read the directories of docs/data/ as well.
  • The pages whose output depends on the extravascular zero (the quickstart, the workflows, NCA, uncertainty, bioequivalence, data formats, units, urinary excretion) and the example figures are regenerated.

1.2.0

Choose a tag to compare

@github-actions github-actions released this 17 Sep 08:04
ceaaac0

Release notes for pkpdutils 1.2.0

Minor release of pkpdutils which closes the gaps a survey of the other non-compartmental analysis tools found: the parameters and rules the guidances name, acceptance criteria and exclusions, a published validation against Phoenix WinNonlin and PKNCA, the steady state completion, urinary excretion and sparse sampling, analytes and routes per sample with the CDISC parameter map, the replicate designs and reference scaled limits of bioequivalence with power and sample size, the study report, and the figures a reviewer asks for. The console renders the tables of the package, the NCA figure reports every value with its interval, and the drug-drug interaction figure shades the classes.

Breaking changes

  • Timecourses.substance and Timecourses.route raise a ValueError for a batch whose samples differ; the coordinates substance and route carry the values then. Timecourses.from_timecourses builds those coordinates for a mixed list instead of raising.
  • read_adnca reads ADUR (the infusion durations, duration_col) and NRRLT (the nominal times, nominal_time_col); pass None for either to restore the old reading. read_pknca reads a duration column when the dose table has one.
  • A batch carrying an lloq coordinate (every read_adnca batch with ALLOQ) is analysed against that limit under the default options; set NCAOptions.blq explicitly or drop the coordinate for the old numbers.
  • Every NCAResult carries the boolean variables accepted and excluded (and excluded_reason once a sample is excluded), so to_dataframe has more columns; summarize, summary_table, sample, ddi_table and bioequivalence skip excluded samples by default (include_excluded=True keeps them). BEResult.to_dataframe carries a carryover column.
  • An intravenous infusion whose first sample is after the dose starts at 0 at the dose time, and its terminal regression starts after the end of the infusion (the rules of Phoenix WinNonlin); auc_last, aumc_last, auc_inf_obs, mrt, vss, lambda_z and what reads them change for such a curve. The extravascular half of the zero rule is deliberately not applied.
  • tlag is 0 rather than NaN for an extravascular curve whose first sample is already measurable.
  • The last dosing interval of a profile whose last sample falls short of tau by at most NCAOptions.tau_tolerance (10 %) is completed with the terminal regression instead of NaN and INCOMPLETE_INTERVAL; tau_tolerance=0.0 restores the old behaviour.
  • accumulation_ratio(steady_state, single_dose) returns a dataset with accumulation_ratio and stationarity_ratio.
  • The delta method treats auc_tau, cmin_ss, cmax_ss, ctrough and cavg as terminal dependent when the interval can be completed.
  • plot_nca returns a figure of three axes (the parameter table is the third); annotate=False gives the two bare panels. The default colors of every figure follow the Okabe-Ito palette.
  • ParameterSample raises a ValueError for values given together with a summary field (mean, sd, n, geomean, geocv), which were kept but never read, and for labels or coords on summary data (#74).
  • ParameterResult.sample, to_quantities, flags and NCAResult.exclude raise a ValueError naming the indexer for a name which is not a sample dimension, for dim given as an indexer as well and for a label which is not on its dimension, instead of the KeyError of xarray; a coordinate along a sample dimension (period=1) is no indexer of sample any more, select the subset from the batch before the analysis (#70).
  • A sample dimension or a coordinate of a batch named like a dimension the result adds (parameter, parameter_ and point of a fit, interval and candidate of an NCA) raises a ValueError instead of being overwritten, and so does a by coordinate or a sample dimension of summary_table named like a column of the table (#72).
  • The process pool of the fit starts its workers with forkserver (spawn on macOS and Windows) on every python version, pkpdutils.parallel.PROCESS_START_METHOD; on python 3.13 on Linux a pooled fit (n_workers > 1) now needs a model the workers can import, as on python 3.14 (#74).

Non-compartmental analysis

  • New parameters: tlag, auc_all, aumc_all, clast_pred, auc_back_extrap_fraction, aumc_back_extrap_fraction, the dose normalized auc_last_dn, auc_all_dn, auc_tau_dn, cavg_dn, cmax_ss_dn, c0_dn and NCAResult.dose_normalized(parameters), thalf_eff (the effective half-life ln 2 * MRT), fluctuation_tau, swing_tau, ptr, accumulation_ratio_cmax_obs, accumulation_ratio_cmin_obs, accumulation_ratio_ctrough_obs, auc_tau_extrap_fraction, lambda_z_t_last, lambda_z_span.
  • BLQ rules: BLQRules with the positional axis (first, middle, last) or the tmax axis, the actions DROP, KEEP, ZERO, LLOQ, HALF_LLOQ or a number, and the presets BLQRules.ich_m13a(), BLQRules.pkanalix(), BLQRules.pumas(); Timecourse.lloq per sample; C0Method.NONE and the variable c0_method.
  • Acceptance criteria (Acceptance, Acceptance.pkanalix(), the flag NOT_ACCEPTED), exclusions (NCAResult.exclude), named partial areas (NCAOptions.partial_aucs, the flag PARTIAL_EXTRAPOLATED), terminal windows per sample (TerminalPhase.windows, NCAResult.terminal_windows()), the candidate windows (TerminalPhase.keep_candidates).
  • The tables of a regulatory report (pkpdutils.nca.report): M13A_STATISTICS, acceptability_table, methods_line.
  • Time to steady state (pkpdutils.nca.tss) and bioavailability (pkpdutils.nca.bioavailability).
  • Urinary excretion (pkpdutils.nca.urine: Excretion, nca_urine with the renal clearance) and sparse sampling (pkpdutils.nca.sparse: nca_sparse with the Bailer estimator, its standard error and degrees of freedom, sparse_mean).
  • Analytes and routes per sample: parent and metabolite in one batch (analytes= on the readers, metabolite_ratio), an intravenous reference and an oral test in one batch.
  • Validation: the analysis reproduces Phoenix WinNonlin to machine precision on the indomethacin dataset and to the printed digits on the theophylline dataset, and PKNCA to 1e-7 per subject; docs/validation.md, tests/nca/test_validation.py, scripts/validation.py.

Data formats and units

  • pkpdutils.cdisc: the PKPARMCD map parsed from the NCI EVS SDTM terminology, to_pp/write_pp writing the PP domain with PKUNIT spellings.
  • ParameterResult.to_units({...}) and NCAOptions.units convert a result to the reporting units.
  • write_pknca and write_adnca as the inverse of the readers; nominal_time carried by a batch (from_arrays, from_dataframe, ADNCA NRRLT).

Statistics and reporting

  • Bioequivalence: the replicate designs (Design.REPLICATE, EMA Method A), the reference scaled limits (scaling="ema" | "fda" | "fda_nti" | "ema_nti"), the carryover check (carryover_table, bioequivalence(carryover=)), the tmax comparison (hodges_lehmann), power and sample size (pkpdutils.stats.power).
  • The study report (pkpdutils.report: Report, study_report) as a self-contained HTML or markdown.
  • The console renders the tables of the package (pkpdutils.console.print_table, rich_table, a result through the rich protocol); summary_table(unit_style="short") and summary_table(digits={...}).

Figures

  • The NCA figure reports every value on the plot with its interval and a confidence band of the terminal regression, with a third panel listing the parameters; plot_terminal_windows, plot_study_curves, plot_excretion, plot_sparse, the partial area shading of plot_nca; plot_ratio shades the classes of an interaction; save_figure writes PNG, SVG and TIFF from one stem.

Fixes

  • compare(paired=True, test="wilcoxon") takes the medians of the effect from the remaining pairs, not from every finite value of either sample, so a subject with a missing value on one side no longer shifts the effect (#69).
  • plot_parameters with log_y=True draws the box of a group from the same positive values as its points, a group with a non-positive value is marked with its arithmetic mean under its own legend entry, and the legend sits in room made above the data instead of covering an interval (#71).
  • The fit keeps data beyond the range of double precision to its row: no floating-point warning escapes the guess, the search, the covariance, the statistics or the bootstrap, the exceptions of terminal_guess and Bateman.derived are gone, and a row whose sum of squares, covariance or statistics overflow is NaN and flagged with the new FitFlag.OVERFLOW (#73).
  • The process pool of the fit no longer forks next to the threads of the NCA on python 3.13, which could deadlock and warned This process is multi-threaded, use of fork() may lead to deadlocks (#74).
  • The plot functions draw into the axes of a subfigure (fig.subfigures) and return the figure holding it.
  • The glossary gives every row one unit or one unit per name.

Documentation

  • The pages bioequivalence.md, ddi.md, urine.md, sparse.md, validation.md, reporting.md, the further reading of references.md, the survey and the design of the round in docs/superpowers/.
  • The citation of the package (CITATION.cff, .zenodo.json, README.md, docs/index.md) names König as its only author (#98).

Your pkpdutils team

1.1.0

Choose a tag to compare

@github-actions github-actions released this 16 Sep 09:33
45dbb03

Release notes for pkpdutils 1.1.0

Minor release of pkpdutils with dosing protocols, the multiple dose analysis and the exchange formats of pharmacokinetic data, followed by a cleanup and usability round: bug fixes, a faster batch path, consistent signatures, the tables and figures a publication prints, and documentation whose every snippet runs. The release breaks the 1.0.0 API where consistency demanded it; every change is listed below with the call to adapt.

Dosing protocols, multiple dosing and exchange formats

  • Dosing is the dosing protocol of a curve: amounts, times, durations (infusions), one unit and one route, built with Dosing.single(dose), Dosing.from_doses(doses) or Dosing.regimen(dose, interval, n_doses); Timecourse.dosing holds it, Timecourse.dose reads the first dose back, relative_to_dose(which="first" | "last") shifts a curve and its protocol.
  • A batch (Timecourses) carries the protocol of every sample over the dimension dose_index (dose_amount, dose_time, dose_duration, NaN padded); n_doses, first_dose_*, last_dose_* and dosing_of(**indexers) read it back.
  • The non-compartmental analysis of a multiple dose curve computes the parameters of every dosing interval (interval_* variables over the dimension interval, NCAResult.intervals() as a table) and the steady state parameters of the last complete interval (auc_tau, cmax_ss, cmin_ss, ctrough, cavg, fluctuation, swing, accumulation_ratio, cl_ss); the point parameters are computed from the last dose on. Flags INCOMPLETE_INTERVAL (the last interval is not covered by the data) and EXTRAPOLATED_TROUGH (the trough of a bolus interval was regressed). NCAOptions.tau analyses a curve given with its last dose only; superposition and accumulation_ratio predict the steady state from a single dose.
  • pkpdutils.io: read_events/Timecourses.from_events and write_events/Timecourses.to_events (NONMEM and Monolix event records with EVID, AMT, DV, MDV, ADDL/II, SS, RATE/TINF, covariates as coordinates), read_pknca/Timecourses.from_pknca (the two PKNCA tables) and read_adnca/Timecourses.from_adnca (CDISC ADaM ADNCA). Every reader returns one batch with one sample dimension, the protocol of every subject and the covariates as coordinates.
  • Figures: the dose lines of a protocol in plot_timecourse, the shaded AUC(0-tau) of a multiple dose result in the NCA panel, plot_intervals of the interval_* variables against the interval number.

Breaking changes of this part:

  • NCAOptions.regimen is removed. A repeated administration is given as the Dosing protocol of the timecourse (Dosing.regimen(dose, interval, n_doses), DosingRegimen.dosing()), and a curve given with its last dose only is analysed with NCAOptions.tau.
  • superposition(timecourse, dosing) takes a Dosing protocol or a DosingRegimen; the predicted curve carries the protocol and no label.
  • Timecourse.dose is a read-only property, the first dose of Timecourse.dosing; the protocol is replaced with model_copy(update={"dosing": Dosing.single(dose)}), not with update={"dose": ...}.
  • A Timecourses dataset carries the dose dimension dose_index: dose_amount, dose_time and dose_duration are 2-D over (*sample_dims, dose_index); the 1-D view of a single dose batch is first_dose_amount/first_dose_time and last_dose_amount/last_dose_time. A sample dimension named dose_index is rejected.
  • A multiple dose analysis reports cl, cl_f, vz, vz_f, vss, auc_inf_dn and cmax_dn as NaN, since the slice after the last dose carries the exposure of the earlier doses; auc_inf_obs, auc_inf_pred, aumc_inf and mrt describe the decline after the last dose.
  • The clearance at steady state of an extravascular route is cl_ss_f, not cl_ss.
  • read_events and read_pknca require the route keyword: a batch has one route and the two formats carry none.

Breaking changes of the cleanup round

  • nca, nca_single, partial_auc and superposition take options as a keyword, as fit does: nca(batch, options=NCAOptions(...)); t_end of superposition follows options in the signature and is a keyword as well.
  • FitResult reports p_cv as a fraction instead of a percentage; a table or a figure which printed it directly multiplies by 100 (the tables of the package do it themselves).
  • Every plot_* function takes ax/axes and style as keywords, and a logarithmic axis is log_x/log_y instead of log; plot_dose_proportionality takes the ProportionalityResult which proportionality_test now returns instead of its former tuple.
  • read_events, read_pknca and read_adnca name their column keywords *_col (id_col, time_col, dv_col, amt_col, ...); groups of read_pknca is covariates.
  • Timecourses.n_workers and NCAOptions.n_workers: None is automatic (the pool only above the size threshold) and 1 is serial; pass a number to force that many workers.
  • stats.effects_from_arrays uses EffectKind.HEDGES_G by default, like the other entry points; pass kind= for another one.
  • The readers and Timecourses.from_dataframe raise ValueError naming the sample instead of a pydantic ValidationError: a sample with fewer than two time points, a NaN time, duplicate times or a dose which is not a valid protocol is caught by the batch itself, which no longer builds one Timecourse per sample.
  • Timecourses.from_dataframe rejects a value which is neither missing nor a number with a ValueError naming the sample and the column; a non-numeric time column raised a TypeError from pandas before, and a non-numeric dose column with dose_time was read as a missing dose.
  • ParameterResult.summarize no longer reports _sd, _se, _ci_low, _ci_high, _geomean and _geocv for the discrete parameters (tmax, tlast, tau, the counts and the diagnostics of the terminal regression); they keep x, x_median, x_q25, x_q75 and x_n.
  • plot_timecourse no longer takes ax positionally; plot_forest takes exp before ax and style; draw_nca_panel(timecourse, values, flags, *, log_y, title, ax, style) takes its data first, ax as a keyword, and returns the Axes instead of None.
  • plot_goodness_of_fit: log is replaced by log_x and log_y, which scale and mask the two axes on their own. plot_bland_altman: log is renamed log_ratio, since it selects the statistic (the log ratio against the log mean) and not only the scale of an axis.
  • plot_nca, plot_nca_grid and plot_fit take axes, the panels to draw into; the log of plot_nca_grid is log_y, and so is the log of plot_parameters.
  • plot_dose_proportionality and plot_bland_altman take ax.
  • write_events names its column keywords *_col like the readers, so id no longer shadows the builtin.
  • read_adnca and read_pknca gain covariates; the ADNCA column keywords subject, param, value, value_unit, time_first, time_ref, dose, dtype and lloq are subject_col, param_col, value_col, value_unit_col, time_first_col, time_ref_col, dose_col, dtype_col and lloq_col; the PKNCA subject is subject_col.
  • stats.multiple_comparison(p_values, *, method=...) and stats.effects_from_arrays(estimates, variances, *, labels=..., kind=..., ci_level=...) take their options by keyword.
  • stats.substrate_sensitivity(auc_ratio, *, thresholds=None) takes the thresholds as an optional keyword (the FDA ones by default) instead of a required positional argument.
  • compare_models(models, x, y): y defaults to None and x also takes a Timecourse or a Timecourses, in which case y, sd, dims, coords, x_unit and y_unit must not be given.
  • The result of the NCA carries the variables lambda_z_t_last and lambda_z_span and the flag NCAFlag.SPAN_LOW (1024); pkpdutils.nca.terminal.TerminalFit gains the field t_last after t_first, so a positional construction of it has to be adapted.
  • ParameterResult.summarize reports x_min and x_max for every parameter and x_cv for every non-discrete one, and reduces the point variables of summarized_point_variables (the interval_* parameters of a multiple dose analysis, which it dropped before) over the sample dimension, keeping their interval dimension.
  • pkpdutils.result.SUMMARY_SUFFIXES holds _min and _max, so a fit model whose parameter or derived name ends in one of them (e_max, c_min) is rejected by the reserved suffix guard of pkpdutils.fit.engine and has to be spelled emax, cmin.
  • plot_timecourse(by=...) colors the curves by group and writes one legend entry per group, where it used to give every sample its own color and entry with the group value as its label; a figure of more than max_legend (12) entries gets no legend at all. The function gains facet and, with it, axes.
  • plot_nca draws the legend on the linear panel only, plot_nca_grid once for the figure (into the first panel when the caller supplies axes); its panel titles are dose = 50 mg, individual = s1 instead of 50.0|s1, and its ncols is clamped to the number of samples, so a batch of one sample no longer produces a figure of three panels. draw_nca_panel gains legend.
  • plot_ratio and plot_forest annotate the rows with estimate [low, high] (and the weight of a study) by default and widen the x axis to hold the column; annotate=False restores the bare figure. plot_ratio gains labels for the row names.
  • A curve with an infusion is drawn with the window of the infusion (a shaded span from the dose time to the end of the dose) in plot_timecourse and draw_nca_panel; the NCA panel marks the dose it analyses alone, since it starts at that dose.
  • The figures label an axis whose unit is the canonical long form of pint with the short symbols instead (trough [mg/l], not `trough [milligram...
Read more

1.0.0

Choose a tag to compare

@github-actions github-actions released this 15 Sep 14:55
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

0.3.1

Choose a tag to compare

@github-actions github-actions released this 20 Oct 20:51

Release notes for pkdb-analysis 0.3.1

We are pleased to release the next version of sbmlutils including the
following changes:

  • warnings to info on pharmacokinetics calculation
  • support python 3.10, 3.11, 3.12, 3.13
  • updated build system with uv and ruff
  • fixed tests

Your pkdb-analysis team

0.2.2

Choose a tag to compare

@github-actions github-actions released this 15 Sep 09:11

Release notes for pkdb-analysis 0.2.2

New features

Fixes

  • updated dependencies for compatibility with sbmlutils and sbmlsim
  • cleanup code and tests
  • bugfixes

Deprecated features

0.2.1

Choose a tag to compare

@github-actions github-actions released this 15 Sep 08:57

Release notes for pkdb-analysis 0.2.1

New features

Fixes

  • updated dependencies for compatibility with sbmlutils and sbmlsim
  • cleanup code and tests
  • bugfixes

Deprecated features

0.2.0

Choose a tag to compare

@github-actions github-actions released this 08 Mar 23:01

Release notes for pkdb-analysis 0.1.7

New features

  • meta analysis of caffeine

Fixes

  • enabled nan values in concentration for auc_inf and auc_end calculation.
  • fixed tests and continuous integration (#48)
  • support for python3.9 (#55)

Deprecated features

  • removed deprecated tests

0.1.6

Choose a tag to compare

@github-actions github-actions released this 02 Oct 12:28

Release notes for pkdb-analysis 0.1.6

New features

  • python 3.8 support
  • github actions CI-CD
  • isort and black support
  • tox testing support

Fixes

Deprecated features

  • travis CI

pkdb-analysis-v0.1.6a2

Choose a tag to compare

@matthiaskoenig matthiaskoenig released this 24 Aug 15:38
version bump for release