{"id":50372508,"url":"https://github.com/priyamthakar/openpkflow","last_synced_at":"2026-05-30T08:01:38.637Z","repository":{"id":358523988,"uuid":"1241731779","full_name":"priyamthakar/openpkflow","owner":"priyamthakar","description":"Python-first toolkit for dissolution similarity, NCA, PK/PD simulation, and pharmacometric reporting","archived":false,"fork":false,"pushed_at":"2026-05-25T10:41:40.000Z","size":2429,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-25T12:26:46.237Z","etag":null,"topics":["bioequivalence","dissolution","formulation","nca","pharmacokinetics","pharmacometrics","pkpd","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/priyamthakar.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-17T18:43:41.000Z","updated_at":"2026-05-25T10:41:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/priyamthakar/openpkflow","commit_stats":null,"previous_names":["priyamthakar/openpkflow"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/priyamthakar/openpkflow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/priyamthakar%2Fopenpkflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/priyamthakar%2Fopenpkflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/priyamthakar%2Fopenpkflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/priyamthakar%2Fopenpkflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/priyamthakar","download_url":"https://codeload.github.com/priyamthakar/openpkflow/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/priyamthakar%2Fopenpkflow/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33684413,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bioequivalence","dissolution","formulation","nca","pharmacokinetics","pharmacometrics","pkpd","python"],"created_at":"2026-05-30T08:01:37.739Z","updated_at":"2026-05-30T08:01:38.617Z","avatar_url":"https://github.com/priyamthakar.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OpenPKFlow\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/logo.png\" alt=\"OpenPKFlow\" width=\"420\"/\u003e\n\u003c/p\u003e\n\n**A transparent, reproducible, open-source Python toolkit for dissolution, NCA, PK/PD simulation, and pharmacometric reporting — with full theory derivations, cross-validated formulas, and regulatory-ready documentation.**\n\n[![CI](https://github.com/priyamthakar/openpkflow/actions/workflows/ci.yml/badge.svg)](https://github.com/priyamthakar/openpkflow/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/priyamthakar/openpkflow/branch/main/graph/badge.svg)](https://codecov.io/gh/priyamthakar/openpkflow)\n[![PyPI version](https://img.shields.io/pypi/v/openpkflow)](https://pypi.org/project/openpkflow/)\n[![Python](https://img.shields.io/pypi/pyversions/openpkflow)](https://pypi.org/project/openpkflow/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![Docs](https://img.shields.io/badge/docs-live-brightgreen)](https://priyamthakar.github.io/openpkflow/)\n\n---\n\n## What it does\n\nOpenPKFlow gives formulation scientists, PK/PD researchers, and CRO/CDMO teams a clean Python workflow for:\n\n- **Dissolution similarity:** f1, f2, bootstrap f2, maximum deviation, MSD (Mahalanobis Statistical Distance), model fitting (Weibull, Higuchi, first-order, zero-order, Korsmeyer-Peppas), model-dependent comparison via 90% CI\n- **NCA:** AUClast, AUCinf, Cmax, Tmax, lambda_z, half-life, CL/F, Vz/F; three AUC methods, explicit BLQ handling, %AUCextrap flag, dose-normalised parameters, CDISC PP output; sparse NCA from 3-5 samples\n- **Bayesian PK (v2.0.0):** MAP individual PK estimation (scipy, no extra deps) + full posterior via PyMC (`[bayes]` extra); Bayesian 2x2 crossover BE with P(GMR in 80-125) decision quantity alongside frequentist 90% CI\n- **Bioequivalence:** paired 2x2 TOST (80-125% FDA/EMA limits), GMR + 90% CI, intra-subject CV; research-grade replicate-design screening with CVwR and scaled-limit summaries\n- **Report generation:** Markdown, HTML, PDF, Word\n- **PK simulation:** 1- and 2-compartment models, oral/IV bolus/IV infusion, repeated dosing\n- **Population PK diagnostics:** 4-panel GOF plots (OBS vs PRED, IWRES vs TIME/IPRED), simulation-based VPC with percentile bands, NONMEM-style dataset helpers\n- **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)\n- **Theory guide:** Full LaTeX formula derivations for every module -- NCA, simulation, dissolution, IVIVC, BE, pop PK, Bayesian PK -- for regulatory review support and teaching\n- **ML surrogate (experimental):** torch MLP that approximates 1-cmt oral profiles\n\nIt does not replace expert regulatory judgement or validated commercial platforms.\nIt makes routine analysis faster, cleaner, and more reproducible.\n\n---\n\n## Install\n\n```bash\npip install openpkflow\n```\n\nFor PDF and Word reports:\n\n```bash\npip install openpkflow[reports]\n```\n\nFor full Bayesian PK (PyMC MCMC):\n\n```bash\npip install openpkflow[bayes]\n```\n\n---\n\n## Quick start: dissolution similarity\n\n```python\nfrom openpkflow.dissolution import f1, f2\n\nreference = [20.0, 40.0, 60.0, 80.0, 90.0]\ntest      = [21.0, 39.0, 61.0, 79.0, 88.0]\n\nprint(f\"f1 = {f1(reference, test):.2f}\")\nprint(f\"f2 = {f2(reference, test):.2f}\")\n```\n\n### From a CSV file\n\n```python\nfrom openpkflow.dissolution import DissolutionStudy\n\nstudy = DissolutionStudy.from_csv(\"dissolution.csv\")\n# or load directly from Excel (requires pip install openpkflow[reports]):\n# study = DissolutionStudy.from_excel(\"dissolution.xlsx\", sheet_name=\"Data\")\n\nresult = study.compare(reference=\"reference\", test=\"test\")\nresult.summary()\nresult.report(\"dissolution_report.html\")\nresult.report(\"dissolution_report.pdf\", format=\"pdf\")   # requires [reports]\n```\n\nCSV format: `formulation,batch,time,percent_released`\n\n### CLI\n\n```bash\nopenpkflow version\nopenpkflow similarity --reference \"20,40,60,80\" --test \"21,39,61,79\"\n```\n\n---\n\n## Quick start: NCA\n\n```python\nfrom openpkflow.nca import NCAStudy\n\nstudy = NCAStudy.from_csv(\n    \"pk_data.csv\",\n    auc_method=\"linear_up_log_down\",   # required: \"linear\", \"log\", or \"linear_up_log_down\"\n    blq_method=\"none\",                  # required: \"none\", \"drop\", \"zero\", \"half_lloq\", \"lloq\"\n)\nsummary = study.analyze()\nprint(summary.summary())               # tabular ASCII output\n\n# Per-subject results\nresult = summary.results[0]\nprint(f\"Subject: {result.subject}\")\nprint(f\"AUClast: {result.AUClast:.2f} h*mg/L\")\nprint(f\"Cmax:    {result.Cmax:.2f} mg/L\")\nprint(f\"Tmax:    {result.Tmax:.2f} h\")\nprint(f\"t1/2:    {result.half_life:.2f} h\")\nprint(f\"CL/F:    {result.CL_F:.2f} L/h\")\n\n# Reports\nresult.report(\"nca_subject1.html\")\nsummary.report(\"nca_summary.html\")\n```\n\n### NCA CSV format\n\n```csv\nsubject,time,conc,dose,route\n1,0.0,0.0,320.0,oral\n1,0.5,4.2,320.0,oral\n1,1.0,8.1,320.0,oral\n1,2.0,6.8,320.0,oral\n1,4.0,3.5,320.0,oral\n1,8.0,1.7,320.0,oral\n1,12.0,0.9,320.0,oral\n1,24.0,0.2,320.0,oral\n```\n\nRequired columns: `subject`, `time`, `conc`, `dose`, `route`.\nDose units must match concentration × time (mg when conc is mg/L and time is h).\nRoute values: `\"oral\"`, `\"iv_bolus\"`, `\"iv_infusion\"`.\n\nOral route yields apparent clearance and volume: `CL_F`, `Vz_F`.\nIV routes yield absolute clearance and volume: `CL`, `Vz`.\n\n---\n\n## Quick start: PK simulation\n\n```python\nimport numpy as np\nfrom openpkflow.sim import simulate\nfrom openpkflow.sim.models import OneCompartmentModel\nfrom openpkflow.sim.dosing import DoseRegimen\n\nmodel = OneCompartmentModel(route=\"oral\", CL_F=5.0, Vz_F=50.0, ka=1.2)\nregimen = DoseRegimen.from_repeated(amount=100.0, route=\"oral\", tau=24.0, n_doses=3)\ntimes = np.linspace(0, 72, 500)\n\nresult = simulate(model, regimen, times)\nprint(result.summary())\nresult.report(\"sim_report.html\")\nresult.report(\"sim_report.pdf\", format=\"pdf\")   # requires [reports]\n```\n\n---\n\n## Quick start: Bayesian individual PK (MAP)\n\n```python\nfrom openpkflow.bayes import map_individual_pk, PKPrior\nimport math\n\n# Noiseless 1-cmt oral data (CL_F=5, Vz_F=50, ka=1.2, dose=100)\ntimes = [0.5, 1.0, 2.0, 4.0, 8.0, 12.0]\nconcs = [1.23, 1.85, 1.97, 1.61, 0.89, 0.49]\n\nresult = map_individual_pk(times, concs, dose=100.0, route=\"oral\", subject=\"S01\")\nprint(result.summary())   # MAP estimates, SEs, diagnostics, disclaimer\nresult.report(\"map_pk_report.html\")\n```\n\nFor full posterior sampling (requires `pip install openpkflow[bayes]`):\n\n```python\nfrom openpkflow.bayes.bayes_pk import bayes_individual_pk\n\nresult = bayes_individual_pk(times, concs, dose=100.0, route=\"oral\",\n                              n_samples=1000, tune=1000, chains=2)\nprint(f\"CL_F = {result.cl_mean:.3g}  [95% CrI: {result.cl_95ci[0]:.3g}, {result.cl_95ci[1]:.3g}]\")\nprint(f\"P(shrinkage) = {result.shrinkage_cl:.1%}\")\n```\n\n## Quick start: Bayesian bioequivalence (requires `[bayes]`)\n\n```python\nimport pandas as pd\nfrom openpkflow.bayes.bayes_be import bayes_be\n\n# Long-format 2x2 crossover data\ndata = pd.DataFrame({\n    \"subject\":   [\"S01\",\"S01\",\"S02\",\"S02\",\"S03\",\"S03\",\"S04\",\"S04\"],\n    \"sequence\":  [\"RT\", \"RT\", \"TR\", \"TR\", \"RT\", \"RT\", \"TR\", \"TR\"],\n    \"period\":    [1,    2,    1,    2,    1,    2,    1,    2   ],\n    \"treatment\": [\"R\",  \"T\",  \"T\",  \"R\",  \"R\",  \"T\",  \"T\",  \"R\" ],\n    \"value\":     [98.0, 103.0, 95.0, 91.0, 107.0, 112.0, 99.0, 94.0],\n})\n\nresult = bayes_be(data, metric=\"AUC\", n_samples=2000, tune=1000, chains=2)\nprint(f\"P(BE) = {result.p_be:.3f}\")\nprint(f\"GMR = {result.gmr_mean:.4g}  [95% CrI: {result.gmr_95ci[0]:.4g}, {result.gmr_95ci[1]:.4g}]\")\nprint(f\"Frequentist 90% CI: [{result.freq_90ci[0]:.4g}, {result.freq_90ci[1]:.4g}]\")\nresult.report(\"bayes_be_report.html\")\n```\n\n---\n\n## Quick start: bioequivalence\n\n```python\nimport pandas as pd\nfrom openpkflow.be import BEStudy\n\n# Wide-format DataFrame: one row per subject, reference and test PK parameter values\nbe_df = pd.DataFrame({\n    \"subject\":   [\"S01\", \"S02\", \"S03\", \"S04\", \"S05\", \"S06\"],\n    \"sequence\":  [\"RT\",  \"RT\",  \"RT\",  \"TR\",  \"TR\",  \"TR\"],\n    \"reference\": [100.2, 98.7, 105.1, 97.3, 102.8, 99.5],\n    \"test\":      [95.1,  94.0,  99.8, 92.9,  97.4, 94.8],\n})\n\nstudy = BEStudy(be_df, parameter=\"AUCinf\")\nresult = study.analyze()          # default: 80-125%, alpha=0.05\nprint(result.summary())\nresult.report(\"be_report.html\")\n\n# NTI products: pass narrower limits\nresult_nti = study.analyze(be_lower=0.90, be_upper=1.1111)\n```\n\n### From NCAStudy results (convenience)\n\n```python\nfrom openpkflow.be import BEStudy\n\n# Run NCA separately on each formulation's PK data\n# reference_nca_summary = NCAStudy.from_csv(\"ref_pk.csv\", ...).analyze()\n# test_nca_summary      = NCAStudy.from_csv(\"test_pk.csv\", ...).analyze()\n\nstudy = BEStudy.from_nca_results(\n    reference_nca_summary, test_nca_summary, parameter=\"AUCinf\"\n)\nresult = study.analyze()\n```\n\n### Formal BE with BioEqPy\n\nOpenPKFlow deliberately keeps `openpkflow.be` as a lightweight convenience layer.\nFor regulator-facing BE analysis with long-format crossover data, ANOVA source\ntables, NTI, ABEL/RSABE, and validation fixtures, export a BioEqPy-ready table:\n\n```python\nfrom openpkflow.be import BEStudy\nfrom bioeqpy import analyze\n\nstudy = BEStudy(be_df, parameter=\"AUCinf\")\nbioeqpy_input = study.to_bioeqpy_dataframe()\nformal_results = analyze(bioeqpy_input, parameters=[\"AUCinf\"])\n```\n\n### CLI\n\n```bash\nopenpkflow be compare be_data.csv --parameter AUCinf --report be_report.html\n```\n\nCSV format: `subject, sequence, reference, test`\n\n---\n\n## Quick start: population PK diagnostics\n\n```python\nimport pandas as pd\nfrom openpkflow.pop import GOFResult, simulate_vpc\nfrom openpkflow.sim.models import OneCompartmentModel\nfrom openpkflow.sim.dosing import DoseRegimen\n\n# GOF: supply your own PRED/IPRED from NONMEM or nlmixr2\ngof = GOFResult(\n    dv=[5.2, 8.1, 6.4, 3.2],\n    pred=[4.9, 7.8, 6.0, 3.0],\n    ipred=[5.1, 8.0, 6.3, 3.1],\n    time=[1.0, 2.0, 4.0, 8.0],\n    id=[\"S1\", \"S1\", \"S1\", \"S1\"],\n    sigma=0.15,\n    study_label=\"Phase 1 Study\",\n)\nprint(gof.summary())\ngof.report(\"gof_report.html\")\n\n# Simulation-based VPC\nmodel = OneCompartmentModel(route=\"oral\", CL_F=5.0, Vz_F=50.0, ka=1.2)\nregimen = DoseRegimen.from_repeated(amount=100.0, route=\"oral\", tau=24.0, n_doses=1)\nobserved = pd.DataFrame({\"TIME\": [1, 2, 4, 8, 12], \"DV\": [5.1, 8.2, 6.5, 3.8, 2.1]})\n\nvpc = simulate_vpc(model, regimen, observed, n_replicates=500, seed=42)\nvpc.report(\"vpc_report.html\")\n```\n\n---\n\n## Feature comparison\n\n| Capability | OpenPKFlow | PKNCA (R) | WinNonlin | Pharmpy |\n|---|---|---|---|---|\n| Dissolution f1 / f2 | :white_check_mark: | :x: | :white_check_mark: | :x: |\n| Bootstrap f2 | :white_check_mark: | :x: | :x: | :x: |\n| Dissolution model fitting (5 models + AICc) | :white_check_mark: | :x: | :x: | :x: |\n| MSD / max deviation / model-dependent comparison | :white_check_mark: | :x: | :white_check_mark: | :x: |\n| NCA (AUClast, AUCinf, CL/F, lambda_z), cross-validated vs Phoenix WinNonlin | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |\n| C0 back-extrapolation for IV bolus (matches WinNonlin within 2%) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |\n| %AUCextrap flag, dose-normalised params | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |\n| CDISC PP output (SDTM, PPTESTCD codes) | :white_check_mark: | :x: | :white_check_mark: | :x: |\n| Bioequivalence convenience (paired 2x2 TOST) | :white_check_mark: | :x: | :white_check_mark: | :x: |\n| PK simulation (1/2-cmt, oral/IV) | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: |\n| Population PK diagnostics (GOF, VPC) | :white_check_mark: | :x: | :x: | :white_check_mark: |\n| Multi-format reports (HTML, PDF, DOCX) | :white_check_mark: | :x: | :white_check_mark: | :x: |\n| Open-source \u0026 free | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |\n| Python-native API | :white_check_mark: | :x: | :x: | :white_check_mark: |\n| Regulatory reference validation (citations) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |\n| IVIVC (Level A) | :white_check_mark: (v1.2.0) | :x: | :white_check_mark: | :x: |\n| Multi-media dissolution | :white_check_mark: (v1.4.0) | :x: | :white_check_mark: | :x: |\n| Sparse-sampling NCA | :white_check_mark: (v1.5.0) | :white_check_mark: | :x: | :x: |\n| Steady-state NCA + urinary excretion | :white_check_mark: (v1.3.0) | :white_check_mark: | :white_check_mark: | :x: |\n| MAP individual PK (scipy, no extra deps) | :white_check_mark: (v2.0.0) | :x: | :white_check_mark: | :x: |\n| Full Bayesian PK + Bayesian BE (PyMC) | :white_check_mark: (v2.0.0) | :x: | :x: | :x: |\n| Population PK estimation: FOCE-I + SAEM (1/2-cmt, full Omega) | :white_check_mark: (v2.3.0)\\* | :x: | :x: | :x: |\n| Replicate BE screening (CVwR/scaled-limit summaries) | :white_check_mark: (v2.4.0)\\*\\* | :x: | :white_check_mark: | :x: |\n| Formal BE ANOVA / validated RSABE decision | :x: | :x: | :white_check_mark: | :x: |\n\n\\* 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).\n\\*\\* Research-grade screening only; not a validated FDA/EMA RSABE submission engine.\n\n## Roadmap\n\nPost-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 screening + release credibility sprint (v2.4.0).\nSee [ROADMAP.md](ROADMAP.md) for the full plan.\n\n---\n\n## Current status\n\n| Module | Status |\n|---|---|\n| Dissolution f1 / f2 | Stable |\n| MSD / max deviation / model-dependent comparison | Stable |\n| Bootstrap f2 | Stable |\n| Dissolution CSV loader | Stable |\n| Dissolution model fitting (5 models, AICc) | Stable |\n| IVIVC Level A (Wagner-Nelson, Loo-Riegelman, convolution, Levy plot, %PE) | Stable (v1.2.0) |\n| Multi-media dissolution (f2 across pH, ethanol dose-dumping) | Stable (v1.4.0) |\n| HTML, Markdown, PDF, Word reports | Stable |\n| NCA (AUClast, AUCinf, lambda_z, CL/F, steady-state, urinary excretion) | Stable (v1.3.0) |\n| Sparse NCA (model-informed 1-cmt oral from 3-5 samples) | Stable (v1.5.0) |\n| PK simulation (1/2-comp, oral/IV bolus/IV infusion, repeated dosing) | Stable (v0.9.1) |\n| Population PK diagnostics (GOF, VPC) | Stable (v0.6.0) |\n| FOCE-I pop PK estimation (scipy tier, 1/2-cmt, full Omega)\\* | Stable (v2.3.0) |\n| SAEM pop PK estimation ([bayes] extra, 1/2-cmt, full Omega)\\* | Stable (v2.3.0) |\n| Covariate modeling | Removed (v2.3.0 breaking change) |\n| Validation utilities (pct_bias, rmse, within_pct) | Stable (v0.9.1) |\n| MAP individual PK (scipy, zero extra deps) | Stable (v2.0.0) |\n| Full Bayesian PK posterior (PyMC, [bayes] extra) | Stable (v2.0.0) |\n| Bayesian 2x2 BE with P(GMR in 80-125) (PyMC) | Stable (v2.0.0) |\n| Bioequivalence convenience (paired TOST) | Stable (2x2 crossover TOST, GMR + 90% CI) |\n| ML surrogate (torch MLP, EXPERIMENTAL) | Prototype (v0.9.0) |\n| Stable public release | Done (v2.0.0) |\n\n\\* Research-grade; FOCE-I typical values are sanity-checked against `nlme` Theophylline reference values. See [HANDOFF.md](HANDOFF.md).\n\n---\n\n## By the numbers\n\n| Stat | Value |\n|---|---|\n| Lines of source code (`src/`) | ~19,600 |\n| Lines of tests (`tests/`) | ~15,200 |\n| Total Python files | 141 (69 src + 72 tests) |\n| Tests | 900 |\n| Public functions / methods | 195 |\n| Classes | 34 |\n| HTML report templates | 12 |\n| Bundled example datasets | 4 |\n| Git commits | 100+ |\n\n---\n\n## Validation\n\nAll formula implementations are validated against published FDA/EMA guidance examples.\nEach test case cites its source: paper DOI, FDA guidance ID, or R-package vignette.\n\n**NCA: four-way cross-validation against Phoenix WinNonlin:**\nNCA results are cross-validated against Phoenix WinNonlin (Certara), PKNCA 0.12.1, and NonCompart 0.8.0\non the standard R `nlme::Theoph` (12-subject oral theophylline) and `nlme::Indometh` (6-subject IV bolus\nindomethacin) datasets. Key validated parameters: AUClast, AUCinf, CL/F, Vz/F, lambda_z, half-life.\nC0 back-extrapolation for IV bolus data (WinNonlin's approach: OLS regression on the first 2 points,\nlinear trapezoid area added from t=0 to t_first) is implemented in `c0_back_extrapolated()` and verified\nto match WinNonlin reference values within 2% for all 6 Indometh subjects.\n\nSee [VALIDATION.md](VALIDATION.md) for the full regulatory test traceability matrix.\n\n---\n\n## Disclaimer\n\nThis software is for research and decision-support workflows.\nFinal regulatory interpretation should be reviewed by qualified formulation, pharmacokinetic, and regulatory experts.\n\n---\n\n## Documentation\n\n- **[Theory Guide](https://priyamthakar.github.io/openpkflow/theory/)** -- Full LaTeX formula derivations for every module: NCA, simulation, dissolution, IVIVC, BE, pop PK, Bayesian PK. Designed for regulatory review support and teaching.\n- **[Migration Guide](https://priyamthakar.github.io/openpkflow/migration-cheatsheet/)** -- WinNonlin / NONMEM / R user? Quick-reference mapping for every parameter and function.\n- **[Tutorials](https://priyamthakar.github.io/openpkflow/)** -- Step-by-step worked examples for all 7 modules.\n- **[Validation Matrix](https://priyamthakar.github.io/openpkflow/reference/validation/)** -- Every test mapped to its FDA/EMA/ICH guidance section or published DOI.\n- **[API Reference](https://priyamthakar.github.io/openpkflow/reference/)** -- Full function and class reference for all 9 modules.\n---\n\n## Contributing\n\nIssues and PRs welcome at https://github.com/priyamthakar/openpkflow/issues\n\n---\n\n## Citation\n\nIf you use OpenPKFlow in research, please cite:\n\n```\nThakar, P. (2026). OpenPKFlow: Python-first pharmacometrics and dissolution toolkit.\nhttps://github.com/priyamthakar/openpkflow\n```\n\n## License\n\nMIT · see [LICENSE](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpriyamthakar%2Fopenpkflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpriyamthakar%2Fopenpkflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpriyamthakar%2Fopenpkflow/lists"}