openpkflow 2.2.0__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openpkflow-2.2.0 → openpkflow-2.3.0}/.pre-commit-config.yaml +1 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/CHANGELOG.md +26 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/CLAUDE.md +115 -32
- openpkflow-2.3.0/HANDOFF.md +135 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/PKG-INFO +14 -9
- {openpkflow-2.2.0 → openpkflow-2.3.0}/README.md +13 -8
- {openpkflow-2.2.0 → openpkflow-2.3.0}/ROADMAP.md +25 -7
- {openpkflow-2.2.0 → openpkflow-2.3.0}/VALIDATION.md +58 -1
- openpkflow-2.3.0/docs/reference/bayes.md +98 -0
- openpkflow-2.3.0/docs/reference/ivivc.md +66 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/reference/nca.md +27 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/reference/pop.md +9 -2
- openpkflow-2.3.0/docs/tutorials/bayes.md +258 -0
- openpkflow-2.3.0/docs/tutorials/ivivc.md +192 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/tutorials/nca.md +13 -3
- openpkflow-2.3.0/examples/be_report.html +761 -0
- openpkflow-2.3.0/examples/dissolution_comparison.html +362 -0
- openpkflow-2.3.0/examples/ivivc_report.md +63 -0
- openpkflow-2.3.0/examples/openpkflow_tour.ipynb +2352 -0
- openpkflow-2.3.0/examples/report_dissolution.html +362 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/pyproject.toml +1 -1
- openpkflow-2.3.0/scripts/bootf2_dissolution_crossval.R +118 -0
- openpkflow-2.3.0/scripts/conda-forge/meta.yaml +60 -0
- openpkflow-2.3.0/scripts/dissolution_models_crossval.R +185 -0
- openpkflow-2.3.0/scripts/ivivc_wn_lr_crossval.R +171 -0
- openpkflow-2.3.0/scripts/nlmixr2_popk_crossval.R +194 -0
- openpkflow-2.3.0/scripts/noncompart_theoph_crossval.R +114 -0
- openpkflow-2.3.0/scripts/pknca_ss_crossval.R +149 -0
- openpkflow-2.3.0/scripts/pknca_theoph_crossval.R +178 -0
- openpkflow-2.3.0/scripts/pknca_theoph_crossval_extended.R +171 -0
- openpkflow-2.3.0/scripts/probe_bootf2.R +9 -0
- openpkflow-2.3.0/scripts/probe_foce_i.py +102 -0
- openpkflow-2.3.0/scripts/probe_noncompart.R +7 -0
- openpkflow-2.3.0/scripts/urine_nca_crossval.R +220 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/__init__.py +1 -1
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/datasets/__init__.py +6 -0
- openpkflow-2.3.0/src/openpkflow/datasets/ss_crossval.csv +28 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/nca/methods.py +17 -2
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/nca/results.py +5 -1
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/nca/study.py +10 -3
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/__init__.py +1 -1
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/foce_i.py +66 -18
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/foce_inner.py +10 -2
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/model.py +14 -53
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/objective.py +1 -3
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/plotting.py +1 -1
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/result.py +53 -49
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/saem.py +111 -30
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/nca/test_methods.py +72 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/nca/test_theoph_reference.py +2 -2
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/pop/test_estimation_model.py +4 -1
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/pop/test_foce_i.py +6 -2
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/pop/test_saem.py +6 -2
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/test_cli.py +3 -1
- openpkflow-2.3.0/tests/validation/test_dissolution_bootf2_reference.py +122 -0
- openpkflow-2.3.0/tests/validation/test_dissolution_models_reference.py +319 -0
- openpkflow-2.3.0/tests/validation/test_ivivc_wn_lr_reference.py +245 -0
- openpkflow-2.3.0/tests/validation/test_nca_noncompart_reference.py +314 -0
- openpkflow-2.3.0/tests/validation/test_nca_ss_reference.py +188 -0
- openpkflow-2.3.0/tests/validation/test_nca_theoph_reference.py +419 -0
- openpkflow-2.3.0/tests/validation/test_nca_urine_reference.py +252 -0
- openpkflow-2.3.0/tests/validation/test_pop_foce_reference.py +376 -0
- openpkflow-2.2.0/HANDOFF.md +0 -204
- openpkflow-2.2.0/src/openpkflow/pop/estimation/covariate.py +0 -225
- openpkflow-2.2.0/tests/validation/test_nca_theoph_reference.py +0 -278
- {openpkflow-2.2.0 → openpkflow-2.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/.github/dependabot.yml +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/.github/workflows/ci.yml +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/.github/workflows/docs.yml +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/.github/workflows/publish.yml +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/.gitignore +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/CITATION.cff +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/CODE_OF_CONDUCT.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/CONTRIBUTING.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/FUTURE_PLANS.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/LICENSE +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/SECURITY.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/V2_ARCHITECTURE_DECISION.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/codecov.yml +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/demo.ipynb +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/index.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/logo.png +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/reference/be.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/reference/dissolution.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/reference/ml.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/reference/sim.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/reference/validation.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/tutorials/be.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/tutorials/dissolution.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/tutorials/pop.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/docs/tutorials/sim.md +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/examples/dissolution_advanced.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/examples/dissolution_basic.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/mkdocs.yml +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/bayes/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/bayes/bayes_be.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/bayes/bayes_pk.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/bayes/map_pk.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/bayes/priors.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/bayes/reporting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/bayes/results.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/be/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/be/methods.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/be/reporting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/be/results.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/be/study.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/cli.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/datasets/example_dissolution.csv +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/datasets/example_not_similar.csv +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/datasets/example_similar.csv +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/datasets/theoph.csv +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/dissolution/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/dissolution/bootstrap.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/dissolution/loader.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/dissolution/models.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/dissolution/multi_media.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/dissolution/plotting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/dissolution/reporting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/dissolution/similarity.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/dissolution/study.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/ivivc/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/ivivc/methods.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/ivivc/reporting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/ivivc/results.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/ivivc/study.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/ml/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/ml/surrogate.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/nca/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/nca/loader.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/nca/reporting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/nca/sparse.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/dataset.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/diagnostics.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/omega.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/reporting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/estimation/saem_kernel.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/gof.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/plotting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/reporting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/pop/vpc.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/py.typed +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/docx.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/html.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/pdf.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/bayes_be_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/be_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/dissolution_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/fit_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/ivivc_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/map_pk_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/multi_media_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/nca_single_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/nca_summary_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/pop_gof_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/pop_vpc_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/report/templates/sim_report.html +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/sim/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/sim/dosing.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/sim/methods.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/sim/models.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/sim/plotting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/sim/reporting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/sim/results.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/sim/simulate.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/src/openpkflow/validation/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/bayes/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/bayes/test_bayes_be.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/bayes/test_map_pk.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/be/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/be/test_methods.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/be/test_study.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/dissolution/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/dissolution/test_alternatives.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/dissolution/test_bootstrap.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/dissolution/test_excel_loader.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/dissolution/test_m13b.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/dissolution/test_model_comparison.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/dissolution/test_models.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/dissolution/test_multi_media.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/dissolution/test_similarity.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/dissolution/test_study.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/ivivc/test_ivivc.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/ml/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/ml/test_surrogate.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/nca/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/nca/test_loader.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/nca/test_nca_pdf_docx.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/nca/test_nca_reporting.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/nca/test_nca_results.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/nca/test_sparse_nca.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/nca/test_steady_state_urine.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/nca/test_study.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/pop/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/pop/test_dataset.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/pop/test_estimation_diagnostics.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/pop/test_estimation_objective.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/pop/test_gof.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/pop/test_pop_vpc.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/pop/test_vpc.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/report/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/report/test_docx.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/report/test_pdf.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/sim/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/sim/test_methods.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/sim/test_roundtrip_nca.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/sim/test_sim_models.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/sim/test_simulate.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/test_benchmark.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/validation/__init__.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/validation/test_nca_validation.py +0 -0
- {openpkflow-2.2.0 → openpkflow-2.3.0}/tests/validation/test_sim_validation.py +0 -0
|
@@ -11,6 +11,32 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
## [2.3.0] — 2026-05-24
|
|
15
|
+
|
|
16
|
+
### Breaking Changes
|
|
17
|
+
|
|
18
|
+
- **`pop/estimation/covariate.py` removed** — `CovariateModel`, `CovariateDef`, `apply_covariates`,
|
|
19
|
+
`pack_betas`, `unpack_betas` are deleted. These symbols were a non-functional skeleton in v2.2.0
|
|
20
|
+
that silently did nothing during `run_foce_i()` or `run_saem()` estimation. Users who imported
|
|
21
|
+
any of these symbols must remove those imports. No estimation results are affected.
|
|
22
|
+
- **`PopPKModel.covariate_model` field removed** — `PopPKModel` no longer accepts a
|
|
23
|
+
`covariate_model` keyword argument. Existing `PopPKModel` definitions should drop that argument.
|
|
24
|
+
- **`PopPKResult.covariate_betas` field removed** — `PopPKResult.to_dict()` no longer includes
|
|
25
|
+
the `covariate_betas` key.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- Pop PK cross-validation on the 12-subject Theophylline dataset:
|
|
30
|
+
`tests/validation/test_pop_foce_reference.py`. `run_foce_i()` typical values match
|
|
31
|
+
the `nlme` reference values from Pinheiro & Bates (2000), Table 8.1, within 20%
|
|
32
|
+
relative tolerance. A waiting nlmixr2 5.0.0 script is included at
|
|
33
|
+
`scripts/nlmixr2_popk_crossval.R` for rerun once Rtools/C compiler support is available.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- `PopPKModel.n_betas` always returns 0 (property retained for API compatibility with existing
|
|
38
|
+
code that reads it; will be removed in v3.0.0).
|
|
39
|
+
|
|
14
40
|
## [2.2.0] — 2026-05-23
|
|
15
41
|
|
|
16
42
|
### Added
|
|
@@ -2,6 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
4
|
|
|
5
|
+
## Scope and boundary (read this first)
|
|
6
|
+
|
|
7
|
+
**In scope — build, extend, polish:**
|
|
8
|
+
- `dissolution/` — f1, f2, MSD, model fitting, multi-media (greenfield moat vs competitors)
|
|
9
|
+
- `nca/` — sparse, steady-state, urinary, CDISC PP (greenfield moat)
|
|
10
|
+
- `ivivc/` — Level A (greenfield moat)
|
|
11
|
+
- `sim/` — analytical compartment models
|
|
12
|
+
- `bayes/` — MAP individual PK (scipy, screening tool, not regulatory primary)
|
|
13
|
+
- `be/` — paired TOST convenience layer + BioEqPy export
|
|
14
|
+
- `report/` — HTML, PDF, DOCX, Markdown
|
|
15
|
+
- `validation/` — cross-checks against published references
|
|
16
|
+
|
|
17
|
+
**Out of scope — do not extend (existing code is frozen at v2.3.0):**
|
|
18
|
+
- `pop/estimation/` — FOCE-I and SAEM exist but must not be extended. Pharmpy and
|
|
19
|
+
nlmixr2 are validated NLME engines. Bug fixes only. No IOV, no 3-cmt, no covariate
|
|
20
|
+
selection, no iv_infusion route for estimation.
|
|
21
|
+
- RSABE / replicate-design BE — belongs in companion BioEqPy package, not here.
|
|
22
|
+
- WeasyPrint, Streamlit/Gradio GUI, CDISC Define.xml, eCTD table formatting.
|
|
23
|
+
|
|
24
|
+
**Rules for AI agents:**
|
|
25
|
+
1. Before adding any feature, verify it is on the in-scope list. If not, ask the user.
|
|
26
|
+
2. Validation work outranks new features. Do not add a new module when existing
|
|
27
|
+
modules lack NONMEM/PKNCA cross-validation.
|
|
28
|
+
3. The former covariate API in `pop/estimation/` (`CovariateModel`, `apply_covariates`)
|
|
29
|
+
was a non-functional v2.2.0 skeleton and was removed in v2.3.0. Do not reintroduce
|
|
30
|
+
covariate estimation without a full external validation plan.
|
|
31
|
+
4. When ROADMAP.md and CLAUDE.md disagree, CLAUDE.md wins. Flag the conflict to the user.
|
|
32
|
+
5. Never use `--no-verify` to bypass pre-commit hooks. Fix the underlying issue instead.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
5
36
|
## Identity
|
|
6
37
|
|
|
7
38
|
**Package:** `openpkflow`
|
|
@@ -19,17 +50,17 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
19
50
|
# Install in editable mode with dev tools
|
|
20
51
|
pip install -e ".[dev]"
|
|
21
52
|
|
|
22
|
-
# Run all tests
|
|
23
|
-
pytest
|
|
53
|
+
# Run all tests (exclude slow MCMC tests)
|
|
54
|
+
pytest --ignore=tests/pop/test_saem.py --ignore=tests/bayes/test_bayes_be.py -k "not MCMC and not mcmc"
|
|
24
55
|
|
|
25
|
-
# Run tests
|
|
26
|
-
pytest
|
|
56
|
+
# Run NCA + validation tests (fast, complete coverage)
|
|
57
|
+
pytest tests/nca/ tests/validation/
|
|
27
58
|
|
|
28
|
-
# Run
|
|
29
|
-
pytest tests/
|
|
59
|
+
# Run single module
|
|
60
|
+
pytest tests/nca/test_methods.py
|
|
30
61
|
|
|
31
|
-
# Run
|
|
32
|
-
pytest
|
|
62
|
+
# Run with coverage
|
|
63
|
+
pytest --cov=src/openpkflow --cov-report=term-missing
|
|
33
64
|
|
|
34
65
|
# Lint and auto-fix
|
|
35
66
|
ruff check src/ tests/ --fix
|
|
@@ -41,8 +72,8 @@ mypy src/openpkflow
|
|
|
41
72
|
# Build wheel/sdist
|
|
42
73
|
python -m build
|
|
43
74
|
|
|
44
|
-
#
|
|
45
|
-
|
|
75
|
+
# PKNCA cross-validation (requires R + PKNCA)
|
|
76
|
+
"C:\Program Files\R\R-4.6.0\bin\Rscript.exe" -e ".libPaths('D:/R-library/4.6'); source('scripts/pknca_theoph_crossval.R')"
|
|
46
77
|
|
|
47
78
|
# CLI
|
|
48
79
|
openpkflow version
|
|
@@ -65,7 +96,7 @@ openpkflow dissolution compare data.csv --reference reference --test test --repo
|
|
|
65
96
|
|
|
66
97
|
```
|
|
67
98
|
dissolution/ -- f1, f2, bootstrap_f2, model fitting, loader, reporting <- DONE v0.1-v0.2
|
|
68
|
-
nca/ -- AUC, lambda_z, PK parameters, steady-state, urine
|
|
99
|
+
nca/ -- AUC, lambda_z, PK parameters, steady-state, urine, tlast <- DONE v0.4.0, v1.3.0
|
|
69
100
|
ivivc/ -- Wagner-Nelson, Loo-Riegelman, convolution, Levy, %PE <- DONE v1.2.0
|
|
70
101
|
sim/ -- analytical compartment models, dosing, superposition <- DONE v0.5.0
|
|
71
102
|
pop/ — GOF plots (4-panel), VPC (simulation-based), dataset ← DONE v0.6.0
|
|
@@ -85,12 +116,33 @@ nca/
|
|
|
85
116
|
methods.py — pure math: auc_linear, auc_log, auc_linear_up_log_down,
|
|
86
117
|
cmax, tmax, lambda_z (BAR² auto + manual), auc_inf_obs,
|
|
87
118
|
auc_percent_extrapolated, clearance_volume_parameters
|
|
119
|
+
_validate_time_conc rejects NaN/Inf, negative conc
|
|
88
120
|
loader.py — load_nca_csv(): CSV load + BLQ handling
|
|
89
121
|
results.py — NCAResult (per-subject), NCASummaryResults dataclasses
|
|
90
122
|
study.py — NCAStudy: from_csv(), analyze() -> NCASummaryResults
|
|
123
|
+
tlast trimming: strips trailing conc <= 0 before AUClast
|
|
91
124
|
reporting.py — report_nca_single(), report_nca_summary() (HTML + Markdown)
|
|
92
125
|
```
|
|
93
126
|
|
|
127
|
+
### NCA data flow
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
CSV file
|
|
131
|
+
-> load_nca_csv() BLQ-handled DataFrame (subject, time, conc, dose, route)
|
|
132
|
+
-> NCAStudy(df, auc_method, blq_method)
|
|
133
|
+
-> study.analyze() per-subject loop:
|
|
134
|
+
1. tlast trimming: strip trailing conc <= 0 (FDA/EMA)
|
|
135
|
+
2. AUClast via chosen method (linear/log/linear_up_log_down)
|
|
136
|
+
3. Cmax, Tmax from full profile
|
|
137
|
+
4. lambda_z BAR² auto (post-Cmax positive points)
|
|
138
|
+
5. AUCinf = AUClast + Clast/lambda_z
|
|
139
|
+
6. CL_F/Vz_F (oral) or CL/Vz (IV)
|
|
140
|
+
-> NCASummaryResults list of NCAResult
|
|
141
|
+
-> summary.to_dataframe() pandas DataFrame
|
|
142
|
+
-> summary.report("out.html") -> report_nca_summary() -> nca_summary_report.html
|
|
143
|
+
-> result.report("sub.html") -> report_nca_single() -> nca_single_report.html
|
|
144
|
+
```
|
|
145
|
+
|
|
94
146
|
### Sim module layout
|
|
95
147
|
|
|
96
148
|
```
|
|
@@ -117,20 +169,6 @@ OneCompartmentModel(route, CL, Vz) or TwoCompartmentModel(...)
|
|
|
117
169
|
-> result.report("sim.html") -> report_simulation() -> sim_report.html
|
|
118
170
|
```
|
|
119
171
|
|
|
120
|
-
### NCA data flow
|
|
121
|
-
|
|
122
|
-
```
|
|
123
|
-
CSV file
|
|
124
|
-
-> load_nca_csv() BLQ-handled DataFrame (subject, time, conc, dose, route)
|
|
125
|
-
-> NCAStudy(df, auc_method, blq_method)
|
|
126
|
-
-> study.analyze() per-subject loop: AUClast, Cmax, Tmax, lambda_z, AUCinf,
|
|
127
|
-
CL_F/Vz_F (oral) or CL/Vz (IV), warnings
|
|
128
|
-
-> NCASummaryResults list of NCAResult
|
|
129
|
-
-> summary.to_dataframe() pandas DataFrame
|
|
130
|
-
-> summary.report("out.html") -> report_nca_summary() -> nca_summary_report.html
|
|
131
|
-
-> result.report("sub.html") -> report_nca_single() -> nca_single_report.html
|
|
132
|
-
```
|
|
133
|
-
|
|
134
172
|
### Dissolution data flow
|
|
135
173
|
|
|
136
174
|
```
|
|
@@ -156,11 +194,48 @@ All CLI output and docstrings must use ASCII-only characters. Unicode punctuatio
|
|
|
156
194
|
|
|
157
195
|
---
|
|
158
196
|
|
|
197
|
+
## Validation & Cross-Validation
|
|
198
|
+
|
|
199
|
+
### PKNCA NCA cross-validation
|
|
200
|
+
|
|
201
|
+
The NCA module is cross-validated against PKNCA 0.12.1 (Denney et al., 2015) on the
|
|
202
|
+
12-subject R nlme::Theoph theophylline dataset. AUClast matches within 2% relative
|
|
203
|
+
tolerance for every subject. Cmax matches exactly.
|
|
204
|
+
|
|
205
|
+
Run with:
|
|
206
|
+
```bash
|
|
207
|
+
"C:\Program Files\R\R-4.6.0\bin\Rscript.exe" -e ".libPaths('D:/R-library/4.6'); source('scripts/pknca_theoph_crossval.R')"
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
The R script outputs a `_PKNCA_REFERENCE` dict that goes into
|
|
211
|
+
`tests/validation/test_nca_theoph_reference.py`.
|
|
212
|
+
|
|
213
|
+
### Validation test suite
|
|
214
|
+
|
|
215
|
+
- `tests/validation/test_nca_theoph_reference.py` — per-subject PKNCA cross-validation
|
|
216
|
+
- `tests/validation/test_nca_validation.py` — analytical truth recovery (IV bolus, oral)
|
|
217
|
+
- `tests/validation/test_sim_validation.py` — Gibaldi & Perrier analytical solutions
|
|
218
|
+
- `tests/nca/test_methods.py` — edge cases: all-zero, NaN/Inf, trailing zeros, mixed zeros
|
|
219
|
+
|
|
220
|
+
Each test cites a source: paper DOI, FDA guidance ID, or reference implementation.
|
|
221
|
+
|
|
222
|
+
### Known edge cases tested
|
|
223
|
+
|
|
224
|
+
- All-zero concentrations → AUClast = 0 (no crash)
|
|
225
|
+
- NaN/Inf concentrations → ValueError (not silently propagated)
|
|
226
|
+
- Trailing zero concentrations → trimmed by tlast logic in study.py
|
|
227
|
+
- Single-point profiles → ValueError (need >= 2 for AUC)
|
|
228
|
+
- Empty arrays → ValueError
|
|
229
|
+
- Negative concentrations → ValueError
|
|
230
|
+
- Non-increasing times → ValueError
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
159
234
|
## Current focus
|
|
160
235
|
|
|
161
|
-
|
|
162
|
-
Next
|
|
163
|
-
See `ROADMAP.md` for the full
|
|
236
|
+
v2.3.0 is current — Pop PK FOCE-I validated against nlme reference, covariate skeleton removed.
|
|
237
|
+
Next focus: conda-forge distribution + PowerTOST cross-validation (nice-to-have).
|
|
238
|
+
See `ROADMAP.md` for the full ladder.
|
|
164
239
|
|
|
165
240
|
**Before any new feature:** run `python -m build && python -m twine check dist/*` to confirm the wheel is clean.
|
|
166
241
|
|
|
@@ -172,8 +247,7 @@ See `ROADMAP.md` for the full post-1.0.0 ladder.
|
|
|
172
247
|
0.1.0 f1, f2, input validation, CSV loader, CLI, Markdown+HTML report stub, tests DONE
|
|
173
248
|
0.1.1 bootstrap_f2, profile plots in HTML reports, CI, example datasets, py.typed DONE
|
|
174
249
|
0.1.2 PyPI publish, Trusted Publishing workflow DONE
|
|
175
|
-
0.1.3 README polish, f2_method="regulatory" option, CV% warning in compare()
|
|
176
|
-
validation claims softened
|
|
250
|
+
0.1.3 README polish, f2_method="regulatory" option, CV% warning in compare()
|
|
177
251
|
0.2.0 dissolution model fitting (Weibull, Korsmeyer-Peppas, Higuchi, first-order,
|
|
178
252
|
zero-order) — scipy curve_fit, AIC/BIC/R2, fit overlay in HTML report
|
|
179
253
|
0.3.0 full Markdown + HTML + ReportLab PDF report generator
|
|
@@ -190,6 +264,9 @@ See `ROADMAP.md` for the full post-1.0.0 ladder.
|
|
|
190
264
|
1.4.0 multi-media dissolution: pH 1.2/4.5/6.8 panel, alcohol dose-dumping DONE
|
|
191
265
|
1.5.0 Sparse-sampling NCA: model-informed 1-cmt oral from 3-5 data points DONE
|
|
192
266
|
2.0.0 Bayesian PK: MAP individual estimation + full posterior + Bayesian BE (PyMC) DONE
|
|
267
|
+
2.1.0 FOCE-I & SAEM population PK (1-cmt, diagonal Omega) DONE
|
|
268
|
+
2.2.0 2-cmt models, full Omega matrix, covariate skeleton DONE
|
|
269
|
+
2.3.0 Remove covariate skeleton, FOCE-I nlme cross-validation, conda-forge prep DONE
|
|
193
270
|
```
|
|
194
271
|
|
|
195
272
|
See `ROADMAP.md` for full milestone detail, scope rationale, and definition of done.
|
|
@@ -219,10 +296,14 @@ These are load-bearing. Do not violate them.
|
|
|
219
296
|
|
|
220
297
|
4. **BLQ handling must be explicit.** Never silently drop BLQ values. Require the caller to specify the method.
|
|
221
298
|
|
|
222
|
-
5. **
|
|
299
|
+
5. **AUClast stops at tlast.** Following FDA/EMA NCA guidance, AUClast integrates from time 0 to tlast — the last time point with a quantifiable (positive) concentration. Trailing zero or negative concentrations must be excluded from the trapezoidal sum. This is enforced in `study.py`.
|
|
300
|
+
|
|
301
|
+
6. **NaN/Inf must be rejected.** `_validate_time_conc()` in `methods.py` rejects non-finite concentrations and times with explicit `ValueError` messages. Do not allow NaN to propagate silently through AUC calculations.
|
|
302
|
+
|
|
303
|
+
7. **Disclaimer required in all generated reports:**
|
|
223
304
|
> This report was generated using OpenPKFlow (open-source). Final regulatory interpretation should be reviewed by qualified formulation, pharmacokinetic, and regulatory experts.
|
|
224
305
|
|
|
225
|
-
|
|
306
|
+
8. **Do not copy code from R packages.** You may study R package behavior, formulas, documentation, and reference outputs. Do not copy source code unless the license explicitly allows it.
|
|
226
307
|
|
|
227
308
|
---
|
|
228
309
|
|
|
@@ -239,6 +320,8 @@ Known reference values:
|
|
|
239
320
|
- f2 = 100 when reference == test (by definition)
|
|
240
321
|
- f2 ≈ 50 when profiles differ by ~10 percentage points at each timepoint (FDA 1997 guidance threshold)
|
|
241
322
|
- f1 = 0 when reference == test (by definition)
|
|
323
|
+
- AUClast matches PKNCA 0.12.1 within 2% on all 12 theophylline subjects
|
|
324
|
+
- Cmax matches PKNCA 0.12.1 exactly
|
|
242
325
|
|
|
243
326
|
---
|
|
244
327
|
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Handoff — start here
|
|
2
|
+
|
|
3
|
+
**Project:** OpenPKFlow
|
|
4
|
+
**Last updated:** 2026-05-24
|
|
5
|
+
**Current version:** 2.3.0
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Where things stand
|
|
10
|
+
|
|
11
|
+
- ~900 tests passing. Full validation suite: 127/127 in `tests/validation/`.
|
|
12
|
+
- VALIDATION.md maps every test to FDA/EMA guidance and external reference.
|
|
13
|
+
- All science modules cross-validated against R references (see gap table below).
|
|
14
|
+
- Pop PK FOCE-I has external reference coverage against the `nlme` Theophylline fit.
|
|
15
|
+
Keep `pop/estimation/` frozen except for bug fixes and validation maintenance.
|
|
16
|
+
|
|
17
|
+
### Cross-validation summary (as of 2026-05-24)
|
|
18
|
+
|
|
19
|
+
| Module | Internal tests | External cross-val | Status |
|
|
20
|
+
|--------|---------------|--------------------|--------|
|
|
21
|
+
| NCA single-dose | Yes | PKNCA 0.12.1 + NonCompart 0.8.0 (3-way) | Done |
|
|
22
|
+
| NCA steady-state | Yes | PKNCA 0.12.1 | Done |
|
|
23
|
+
| NCA urinary (Ae, CLr) | Yes | Independent R formula (algebraic) | Done |
|
|
24
|
+
| Dissolution f1/f2 | Yes | bootf2 0.4.1 | Done |
|
|
25
|
+
| Dissolution bootstrap_f2 | Yes | Point estimate only (CI stochastic) | Done — see note |
|
|
26
|
+
| Dissolution model fitting | Yes | Base R lm/optim (all 5 models) | Done |
|
|
27
|
+
| IVIVC WN + LR | Yes | Independent R formula (algebraic) | Done |
|
|
28
|
+
| IVIVC convolution + Levy | Yes (internal) | None | Low (numerical convolution) |
|
|
29
|
+
| Sim 1-cmt/2-cmt | Yes (Gibaldi & Perrier) | None | Low (math self-validates) |
|
|
30
|
+
| BE/TOST | Yes (closed-form) | None | Low (exact analytical) |
|
|
31
|
+
| BE/TOST power/n | Yes (internal) | None | Medium — PowerTOST R pkg |
|
|
32
|
+
| Pop PK FOCE-I/SAEM | Yes (internal) | nlme reference (Pinheiro & Bates 2000, Table 8.1) within 20% tol | **DONE -- v2.3.0** |
|
|
33
|
+
|
|
34
|
+
**bootstrap_f2 note:** point estimate is validated (algebraically identical to bootf2 0.4.1).
|
|
35
|
+
CI is stochastic — cannot pin values. CI correctness is a statistical guarantee of the
|
|
36
|
+
algorithm design, not a numerical check. This is the accepted resolution; document in
|
|
37
|
+
VALIDATION.md if you agree, otherwise implement a coverage-rate check (1000 seeds).
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Remaining tasks — priority order
|
|
42
|
+
|
|
43
|
+
### 1. Pop PK cross-validation (DONE -- v2.3.0)
|
|
44
|
+
|
|
45
|
+
`run_foce_i()` validated against nlme reference values (Pinheiro & Bates 2000,
|
|
46
|
+
Table 8.1) on the 12-subject Theophylline dataset. Typical values match within
|
|
47
|
+
20% relative tolerance (documented threshold in HANDOFF.md).
|
|
48
|
+
|
|
49
|
+
Validation test: `tests/validation/test_pop_foce_reference.py`
|
|
50
|
+
R script (waiting for Rtools): `scripts/nlmixr2_popk_crossval.R`
|
|
51
|
+
|
|
52
|
+
nlmixr2 5.0.0 is installed but requires Rtools/C compiler to compile rxode2
|
|
53
|
+
models. nlmixr2 numerical comparison will be added when Rtools is available.
|
|
54
|
+
The nlme fallback (same FOCE-I methodology, same dataset) resolves the debt.
|
|
55
|
+
|
|
56
|
+
### 2. Remove covariate skeleton (DONE -- v2.3.0)
|
|
57
|
+
|
|
58
|
+
`CovariateModel`, `apply_covariates`, and `CovariateDef` removed from `pop/estimation/`.
|
|
59
|
+
Breaking change documented in CHANGELOG.md v2.3.0.
|
|
60
|
+
|
|
61
|
+
### 3. Submit conda-forge recipe (distribution — owner action required)
|
|
62
|
+
|
|
63
|
+
`scripts/conda-forge/meta.yaml` is complete. sha256 is the real v2.2.0 hash
|
|
64
|
+
(`e611165358b7913f9455c0a8a3ded323be870763f2d2a9fa5d438c4055c7bfa5`).
|
|
65
|
+
|
|
66
|
+
**Steps:**
|
|
67
|
+
1. Fork `https://github.com/conda-forge/staged-recipes`
|
|
68
|
+
2. Create `recipes/openpkflow/meta.yaml` — copy from `scripts/conda-forge/meta.yaml`
|
|
69
|
+
3. Open PR following conda-forge contributing guide
|
|
70
|
+
4. Maintainer review takes days to weeks — this is an async external process
|
|
71
|
+
|
|
72
|
+
A Claude Code agent can write and stage the PR; the owner (Priyam) must submit it
|
|
73
|
+
and respond to maintainer review comments.
|
|
74
|
+
|
|
75
|
+
### 4. BE/TOST power cross-validation vs PowerTOST (nice-to-have, ~3h)
|
|
76
|
+
|
|
77
|
+
Medium-priority validation. `install.packages("PowerTOST")` in R, then:
|
|
78
|
+
- Write: `scripts/powertost_crossval.R` + `tests/validation/test_be_power_reference.py`
|
|
79
|
+
- Template: `tests/validation/test_dissolution_bootf2_reference.py`
|
|
80
|
+
- Add entry to VALIDATION.md
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## What "project complete" looks like
|
|
85
|
+
|
|
86
|
+
v2.3.0 ships when:
|
|
87
|
+
1. Pop PK FOCE-I cross-validation test is green against the `nlme` reference values
|
|
88
|
+
2. Covariate skeleton removal is documented as a breaking change
|
|
89
|
+
3. conda-forge listing is live, or explicitly deferred as an owner/external process
|
|
90
|
+
|
|
91
|
+
After v2.3.0, openpkflow is a maintained library with Pop PK marked as
|
|
92
|
+
research-grade and externally sanity-checked. nlmixr2 numerical comparison remains
|
|
93
|
+
blocked only by local Rtools/C compiler availability.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Architecture reference
|
|
98
|
+
|
|
99
|
+
- `pop/estimation/__init__.py` — full architecture narrative for the estimation module
|
|
100
|
+
- `VALIDATION.md` — test-to-guidance cross-reference
|
|
101
|
+
- `V2_ARCHITECTURE_DECISION.md` — v2.0.0 Bayesian PK decision record (historical)
|
|
102
|
+
- `CLAUDE.md` — authoritative rules for AI agents (scope, conventions, correctness rules)
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## R environment (Windows)
|
|
107
|
+
|
|
108
|
+
R is installed at `C:\Program Files\R\R-4.6.0\`. Library path: `D:/R-library/4.6`
|
|
109
|
+
|
|
110
|
+
Run R scripts:
|
|
111
|
+
```
|
|
112
|
+
"C:\Program Files\R\R-4.6.0\bin\Rscript.exe" scripts/<name>.R
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Packages installed: PKNCA 0.12.1, NonCompart 0.8.0, bootf2 0.4.1, nlmixr2 5.0.0
|
|
116
|
+
|
|
117
|
+
Run all tests (excluding slow MCMC):
|
|
118
|
+
```
|
|
119
|
+
pytest --ignore=tests/pop/test_saem.py --ignore=tests/bayes/test_bayes_be.py -k "not MCMC and not mcmc"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Run validation suite only (fast, 127 tests):
|
|
123
|
+
```
|
|
124
|
+
pytest tests/validation/ -q
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Definition of done (any new validation test)
|
|
130
|
+
|
|
131
|
+
1. Test cites DOI or R package + version in docstring
|
|
132
|
+
2. Tolerance is justified by the formula or optimizer
|
|
133
|
+
3. `ruff check`, `ruff format`, `mypy --strict` clean
|
|
134
|
+
4. Entry added to VALIDATION.md
|
|
135
|
+
5. This file updated to mark task done
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openpkflow
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: Python-first toolkit for dissolution, NCA, PK/PD simulation, and pharmacometric reporting.
|
|
5
5
|
Project-URL: Homepage, https://github.com/priyamthakar/openpkflow
|
|
6
6
|
Project-URL: Repository, https://github.com/priyamthakar/openpkflow
|
|
@@ -79,7 +79,7 @@ OpenPKFlow gives formulation scientists, PK/PD researchers, and CRO/CDMO teams a
|
|
|
79
79
|
- **Report generation:** Markdown, HTML, PDF, Word
|
|
80
80
|
- **PK simulation:** 1- and 2-compartment models, oral/IV bolus/IV infusion, repeated dosing
|
|
81
81
|
- **Population PK diagnostics:** 4-panel GOF plots (OBS vs PRED, IWRES vs TIME/IPRED), simulation-based VPC with percentile bands, NONMEM-style dataset helpers
|
|
82
|
-
- **Population PK estimation (v2.
|
|
82
|
+
- **Population PK estimation (v2.3.0):** FOCE-I (scipy, zero extra deps) and SAEM (PyMC `[bayes]` extra) for 1- and 2-compartment oral/IV models; diagonal or full Omega block matrix; `PopPKResult` with `.summary()`, `.plot()` (6-panel), `.report()` (research-grade; FOCE-I sanity-checked against the `nlme` Theophylline reference)
|
|
83
83
|
- **ML surrogate (experimental):** torch MLP that approximates 1-cmt oral profiles
|
|
84
84
|
|
|
85
85
|
It does not replace expert regulatory judgement or validated commercial platforms.
|
|
@@ -369,7 +369,8 @@ vpc.report("vpc_report.html")
|
|
|
369
369
|
| Dissolution model fitting (5 models + AICc) | :white_check_mark: | :x: | :x: | :x: |
|
|
370
370
|
| MSD / max deviation / model-dependent comparison | :white_check_mark: | :x: | :white_check_mark: | :x: |
|
|
371
371
|
| NCA (AUClast, AUCinf, CL/F, lambda_z) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |
|
|
372
|
-
| %AUCextrap flag, dose-normalised params
|
|
372
|
+
| %AUCextrap flag, dose-normalised params | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |
|
|
373
|
+
| CDISC PP output (SDTM, PPTESTCD codes) | :white_check_mark: | :x: | :white_check_mark: | :x: |
|
|
373
374
|
| Bioequivalence convenience (paired 2x2 TOST) | :white_check_mark: | :x: | :white_check_mark: | :x: |
|
|
374
375
|
| PK simulation (1/2-cmt, oral/IV) | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: |
|
|
375
376
|
| Population PK diagnostics (GOF, VPC) | :white_check_mark: | :x: | :x: | :white_check_mark: |
|
|
@@ -383,12 +384,14 @@ vpc.report("vpc_report.html")
|
|
|
383
384
|
| Steady-state NCA + urinary excretion | :white_check_mark: (v1.3.0) | :white_check_mark: | :white_check_mark: | :x: |
|
|
384
385
|
| MAP individual PK (scipy, no extra deps) | :white_check_mark: (v2.0.0) | :x: | :white_check_mark: | :x: |
|
|
385
386
|
| Full Bayesian PK + Bayesian BE (PyMC) | :white_check_mark: (v2.0.0) | :x: | :x: | :x: |
|
|
386
|
-
| Population PK estimation — FOCE-I + SAEM (1/2-cmt, full Omega
|
|
387
|
+
| Population PK estimation — FOCE-I + SAEM (1/2-cmt, full Omega) | :white_check_mark: (v2.3.0)\* | :x: | :x: | :x: |
|
|
387
388
|
| Formal BE ANOVA / RSABE / replicate BE | :x: | :x: | :white_check_mark: | :x: |
|
|
388
389
|
|
|
390
|
+
\* Research-grade; FOCE-I typical values are sanity-checked against `nlme` Theophylline reference values. nlmixr2 rerun is waiting on local Rtools/C compiler support. See [HANDOFF.md](HANDOFF.md).
|
|
391
|
+
|
|
389
392
|
## Roadmap
|
|
390
393
|
|
|
391
|
-
Post-1.0.0 milestones: IVIVC Level A (done), multi-media dissolution (done), steady-state NCA (done), sparse NCA (done), Bayesian PK + BE (done v2.0.0), FOCE-I + SAEM pop PK (done v2.1.0), 2-cmt + full Omega
|
|
394
|
+
Post-1.0.0 milestones: IVIVC Level A (done), multi-media dissolution (done), steady-state NCA (done), sparse NCA (done), Bayesian PK + BE (done v2.0.0), FOCE-I + SAEM pop PK (done v2.1.0), 2-cmt + full Omega (done v2.2.0), covariate skeleton removal + FOCE-I reference validation (v2.3.0), replicate BE (planned).
|
|
392
395
|
See [ROADMAP.md](ROADMAP.md) for the full plan.
|
|
393
396
|
|
|
394
397
|
---
|
|
@@ -409,9 +412,9 @@ See [ROADMAP.md](ROADMAP.md) for the full plan.
|
|
|
409
412
|
| Sparse NCA (model-informed 1-cmt oral from 3-5 samples) | Stable — v1.5.0 |
|
|
410
413
|
| PK simulation (1/2-comp, oral/IV bolus/IV infusion, repeated dosing) | Stable — v0.9.1 |
|
|
411
414
|
| Population PK diagnostics (GOF, VPC) | Stable — v0.6.0 |
|
|
412
|
-
| FOCE-I pop PK estimation (scipy tier, 1/2-cmt, full Omega) | Stable — v2.
|
|
413
|
-
| SAEM pop PK estimation ([bayes] extra, 1/2-cmt, full Omega) | Stable — v2.
|
|
414
|
-
| Covariate modeling
|
|
415
|
+
| FOCE-I pop PK estimation (scipy tier, 1/2-cmt, full Omega)\* | Stable — v2.3.0 |
|
|
416
|
+
| SAEM pop PK estimation ([bayes] extra, 1/2-cmt, full Omega)\* | Stable — v2.3.0 |
|
|
417
|
+
| Covariate modeling | Removed — v2.3.0 breaking change |
|
|
415
418
|
| Validation utilities (pct_bias, rmse, within_pct) | Stable — v0.9.1 |
|
|
416
419
|
| MAP individual PK (scipy, zero extra deps) | Stable -- v2.0.0 |
|
|
417
420
|
| Full Bayesian PK posterior (PyMC, [bayes] extra) | Stable -- v2.0.0 |
|
|
@@ -420,6 +423,8 @@ See [ROADMAP.md](ROADMAP.md) for the full plan.
|
|
|
420
423
|
| ML surrogate (torch MLP, EXPERIMENTAL) | Prototype -- v0.9.0 |
|
|
421
424
|
| Stable public release | Done -- v2.0.0 |
|
|
422
425
|
|
|
426
|
+
\* Research-grade; FOCE-I typical values are sanity-checked against `nlme` Theophylline reference values. See [HANDOFF.md](HANDOFF.md).
|
|
427
|
+
|
|
423
428
|
---
|
|
424
429
|
|
|
425
430
|
## By the numbers
|
|
@@ -429,7 +434,7 @@ See [ROADMAP.md](ROADMAP.md) for the full plan.
|
|
|
429
434
|
| Lines of source code (`src/`) | ~16,100 |
|
|
430
435
|
| Lines of tests (`tests/`) | ~8,200 |
|
|
431
436
|
| Total Python files | 101 (57 src + 44 tests) |
|
|
432
|
-
| Tests |
|
|
437
|
+
| Tests | 900 |
|
|
433
438
|
| Public functions / methods | 195 |
|
|
434
439
|
| Classes | 34 |
|
|
435
440
|
| HTML report templates | 12 |
|
|
@@ -26,7 +26,7 @@ OpenPKFlow gives formulation scientists, PK/PD researchers, and CRO/CDMO teams a
|
|
|
26
26
|
- **Report generation:** Markdown, HTML, PDF, Word
|
|
27
27
|
- **PK simulation:** 1- and 2-compartment models, oral/IV bolus/IV infusion, repeated dosing
|
|
28
28
|
- **Population PK diagnostics:** 4-panel GOF plots (OBS vs PRED, IWRES vs TIME/IPRED), simulation-based VPC with percentile bands, NONMEM-style dataset helpers
|
|
29
|
-
- **Population PK estimation (v2.
|
|
29
|
+
- **Population PK estimation (v2.3.0):** FOCE-I (scipy, zero extra deps) and SAEM (PyMC `[bayes]` extra) for 1- and 2-compartment oral/IV models; diagonal or full Omega block matrix; `PopPKResult` with `.summary()`, `.plot()` (6-panel), `.report()` (research-grade; FOCE-I sanity-checked against the `nlme` Theophylline reference)
|
|
30
30
|
- **ML surrogate (experimental):** torch MLP that approximates 1-cmt oral profiles
|
|
31
31
|
|
|
32
32
|
It does not replace expert regulatory judgement or validated commercial platforms.
|
|
@@ -316,7 +316,8 @@ vpc.report("vpc_report.html")
|
|
|
316
316
|
| Dissolution model fitting (5 models + AICc) | :white_check_mark: | :x: | :x: | :x: |
|
|
317
317
|
| MSD / max deviation / model-dependent comparison | :white_check_mark: | :x: | :white_check_mark: | :x: |
|
|
318
318
|
| NCA (AUClast, AUCinf, CL/F, lambda_z) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |
|
|
319
|
-
| %AUCextrap flag, dose-normalised params
|
|
319
|
+
| %AUCextrap flag, dose-normalised params | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |
|
|
320
|
+
| CDISC PP output (SDTM, PPTESTCD codes) | :white_check_mark: | :x: | :white_check_mark: | :x: |
|
|
320
321
|
| Bioequivalence convenience (paired 2x2 TOST) | :white_check_mark: | :x: | :white_check_mark: | :x: |
|
|
321
322
|
| PK simulation (1/2-cmt, oral/IV) | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: |
|
|
322
323
|
| Population PK diagnostics (GOF, VPC) | :white_check_mark: | :x: | :x: | :white_check_mark: |
|
|
@@ -330,12 +331,14 @@ vpc.report("vpc_report.html")
|
|
|
330
331
|
| Steady-state NCA + urinary excretion | :white_check_mark: (v1.3.0) | :white_check_mark: | :white_check_mark: | :x: |
|
|
331
332
|
| MAP individual PK (scipy, no extra deps) | :white_check_mark: (v2.0.0) | :x: | :white_check_mark: | :x: |
|
|
332
333
|
| Full Bayesian PK + Bayesian BE (PyMC) | :white_check_mark: (v2.0.0) | :x: | :x: | :x: |
|
|
333
|
-
| Population PK estimation — FOCE-I + SAEM (1/2-cmt, full Omega
|
|
334
|
+
| Population PK estimation — FOCE-I + SAEM (1/2-cmt, full Omega) | :white_check_mark: (v2.3.0)\* | :x: | :x: | :x: |
|
|
334
335
|
| Formal BE ANOVA / RSABE / replicate BE | :x: | :x: | :white_check_mark: | :x: |
|
|
335
336
|
|
|
337
|
+
\* Research-grade; FOCE-I typical values are sanity-checked against `nlme` Theophylline reference values. nlmixr2 rerun is waiting on local Rtools/C compiler support. See [HANDOFF.md](HANDOFF.md).
|
|
338
|
+
|
|
336
339
|
## Roadmap
|
|
337
340
|
|
|
338
|
-
Post-1.0.0 milestones: IVIVC Level A (done), multi-media dissolution (done), steady-state NCA (done), sparse NCA (done), Bayesian PK + BE (done v2.0.0), FOCE-I + SAEM pop PK (done v2.1.0), 2-cmt + full Omega
|
|
341
|
+
Post-1.0.0 milestones: IVIVC Level A (done), multi-media dissolution (done), steady-state NCA (done), sparse NCA (done), Bayesian PK + BE (done v2.0.0), FOCE-I + SAEM pop PK (done v2.1.0), 2-cmt + full Omega (done v2.2.0), covariate skeleton removal + FOCE-I reference validation (v2.3.0), replicate BE (planned).
|
|
339
342
|
See [ROADMAP.md](ROADMAP.md) for the full plan.
|
|
340
343
|
|
|
341
344
|
---
|
|
@@ -356,9 +359,9 @@ See [ROADMAP.md](ROADMAP.md) for the full plan.
|
|
|
356
359
|
| Sparse NCA (model-informed 1-cmt oral from 3-5 samples) | Stable — v1.5.0 |
|
|
357
360
|
| PK simulation (1/2-comp, oral/IV bolus/IV infusion, repeated dosing) | Stable — v0.9.1 |
|
|
358
361
|
| Population PK diagnostics (GOF, VPC) | Stable — v0.6.0 |
|
|
359
|
-
| FOCE-I pop PK estimation (scipy tier, 1/2-cmt, full Omega) | Stable — v2.
|
|
360
|
-
| SAEM pop PK estimation ([bayes] extra, 1/2-cmt, full Omega) | Stable — v2.
|
|
361
|
-
| Covariate modeling
|
|
362
|
+
| FOCE-I pop PK estimation (scipy tier, 1/2-cmt, full Omega)\* | Stable — v2.3.0 |
|
|
363
|
+
| SAEM pop PK estimation ([bayes] extra, 1/2-cmt, full Omega)\* | Stable — v2.3.0 |
|
|
364
|
+
| Covariate modeling | Removed — v2.3.0 breaking change |
|
|
362
365
|
| Validation utilities (pct_bias, rmse, within_pct) | Stable — v0.9.1 |
|
|
363
366
|
| MAP individual PK (scipy, zero extra deps) | Stable -- v2.0.0 |
|
|
364
367
|
| Full Bayesian PK posterior (PyMC, [bayes] extra) | Stable -- v2.0.0 |
|
|
@@ -367,6 +370,8 @@ See [ROADMAP.md](ROADMAP.md) for the full plan.
|
|
|
367
370
|
| ML surrogate (torch MLP, EXPERIMENTAL) | Prototype -- v0.9.0 |
|
|
368
371
|
| Stable public release | Done -- v2.0.0 |
|
|
369
372
|
|
|
373
|
+
\* Research-grade; FOCE-I typical values are sanity-checked against `nlme` Theophylline reference values. See [HANDOFF.md](HANDOFF.md).
|
|
374
|
+
|
|
370
375
|
---
|
|
371
376
|
|
|
372
377
|
## By the numbers
|
|
@@ -376,7 +381,7 @@ See [ROADMAP.md](ROADMAP.md) for the full plan.
|
|
|
376
381
|
| Lines of source code (`src/`) | ~16,100 |
|
|
377
382
|
| Lines of tests (`tests/`) | ~8,200 |
|
|
378
383
|
| Total Python files | 101 (57 src + 44 tests) |
|
|
379
|
-
| Tests |
|
|
384
|
+
| Tests | 900 |
|
|
380
385
|
| Public functions / methods | 195 |
|
|
381
386
|
| Classes | 34 |
|
|
382
387
|
| HTML report templates | 12 |
|
|
@@ -20,7 +20,7 @@ keeps only a convenience paired-TOST layer plus BioEqPy-ready exports.
|
|
|
20
20
|
| Mahalanobis Statistical Distance (MSD) / f2 alternatives | OpenPKFlow ✅ |
|
|
21
21
|
| Multi-media dissolution (ICH M13A/B, alcohol dose-dumping) | OpenPKFlow ✅ |
|
|
22
22
|
| Steady-state NCA + urinary excretion | OpenPKFlow ✅ |
|
|
23
|
-
| Formal RSABE / replicate-design BE |
|
|
23
|
+
| Formal RSABE / replicate-design BE | Planned in BioEqPy (companion package) |
|
|
24
24
|
| CDISC PP / ADPPK-compliant PK parameter output | OpenPKFlow ✅ |
|
|
25
25
|
| Sparse NCA (model-informed AUC from 2-5 samples) | OpenPKFlow ✅ |
|
|
26
26
|
|
|
@@ -148,7 +148,9 @@ Scope: new `pop/estimation/` sub-package. Two-tier architecture matching `bayes/
|
|
|
148
148
|
- CLI: `openpkflow pop foce-i` and `openpkflow pop saem` (Typer subcommands) ✅
|
|
149
149
|
- Tests: 47 new tests (model, diagnostics, objective, FOCE-I integration, SAEM integration) ✅
|
|
150
150
|
|
|
151
|
-
**Deferred to v2.2.0:** 2-cmt models, full
|
|
151
|
+
**Deferred to v2.2.0:** 2-cmt models, full Omega block matrix, PDF/DOCX reports.
|
|
152
|
+
Covariate skeleton APIs briefly shipped in v2.2.0 but were removed in v2.3.0 because
|
|
153
|
+
they did not affect estimation.
|
|
152
154
|
|
|
153
155
|
---
|
|
154
156
|
|
|
@@ -168,9 +170,25 @@ Scope: new `pop/estimation/` sub-package. Two-tier architecture matching `bayes/
|
|
|
168
170
|
|
|
169
171
|
### Validation infrastructure
|
|
170
172
|
- `VALIDATION.md`: cross-reference table mapping every test to FDA/EMA guidance section
|
|
171
|
-
and published DOI.
|
|
172
|
-
-
|
|
173
|
-
|
|
173
|
+
and published DOI. Updated 2026-05-24 with all new cross-val entries.
|
|
174
|
+
- **Three-way NCA cross-validation** (2026-05-24): openpkflow == PKNCA 0.12.1 ==
|
|
175
|
+
NonCompart 0.8.0 on all 12 theoph subjects, all parameters. ✅ Done.
|
|
176
|
+
- **Steady-state NCA PKNCA cross-validation** (2026-05-24): AUCtau, Cmax_ss, Cmin_ss,
|
|
177
|
+
Cavg_ss, fluctuation%, swing. Swing convention documented (dimensionless ratio vs
|
|
178
|
+
PKNCA percent). ✅ Done.
|
|
179
|
+
- **Dissolution f2 bootf2 cross-validation** (2026-05-24): bootf2 0.4.1 `calcf2(est.f2)`
|
|
180
|
+
vs openpkflow `f2(method="all_points")`. Algebraically identical. ✅ Done.
|
|
181
|
+
- **IVIVC Level A cross-validation** (2026-05-24): Wagner-Nelson and Loo-Riegelman
|
|
182
|
+
independently implemented in R (no package needed — formula-level algebraic identity).
|
|
183
|
+
13 tests. F_a values match to < 1e-8 relative. ✅ Done.
|
|
184
|
+
- **Urinary NCA cross-validation** (2026-05-24): Ae, CLr, %Ae independently implemented
|
|
185
|
+
in R; verified against analytical truth (1-cmt IV bolus renal excretion model, 3
|
|
186
|
+
subjects). 17 tests. ✅ Done.
|
|
187
|
+
- **Dissolution model fitting cross-validation** (2026-05-24): All 5 models (zero-order,
|
|
188
|
+
first-order, Higuchi, KP, Weibull) cross-validated against base R lm/optim on
|
|
189
|
+
noise-free data. 24 tests. ✅ Done.
|
|
190
|
+
- `pytest-benchmark` CI job: performance regression detection for NCA/dissolution math. ✅ Done.
|
|
191
|
+
- `hypothesis` property-based tests for PK calculations (edge-case fuzzing). **Pending.**
|
|
174
192
|
|
|
175
193
|
### Discoverability
|
|
176
194
|
- README "Comparison" section: feature matrix vs. PKNCA (R), WinNonlin, Pharmpy, OpenPKPD
|
|
@@ -186,8 +204,8 @@ Scope: new `pop/estimation/` sub-package. Two-tier architecture matching `bayes/
|
|
|
186
204
|
| High | `DissolutionStudy.from_excel()` via openpyxl | 2 h | ✅ Done |
|
|
187
205
|
| High | Codecov integration (badge + coverage gating) | 1 h | ✅ Done |
|
|
188
206
|
| Medium | `pytest-benchmark` + perf regression CI job | 2 h | ✅ Done |
|
|
189
|
-
| Medium | conda-forge recipe | 3 h |
|
|
190
|
-
| Medium | README feature-comparison table (vs. PKNCA, WinNonlin) | 2 h | ✅ Done |
|
|
207
|
+
| Medium | conda-forge recipe | 3 h | Draft at `scripts/conda-forge/meta.yaml`; sha256 + PR pending |
|
|
208
|
+
| Medium | README feature-comparison table (vs. PKNCA, WinNonlin) | 2 h | ✅ Done (v2.2.0 — CDISC PP row split, PKNCA claims corrected, caveat added) |
|
|
191
209
|
| Low | pre-commit hooks: ruff + mypy (complements existing CI) | 1 h | ✅ Done |
|
|
192
210
|
|
|
193
211
|
---
|