openpkflow 0.1.2__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-0.1.2/.github/workflows/ci.yml +36 -0
- openpkflow-0.1.2/.github/workflows/publish.yml +77 -0
- openpkflow-0.1.2/.gitignore +58 -0
- openpkflow-0.1.2/CHANGELOG.md +50 -0
- openpkflow-0.1.2/CITATION.cff +11 -0
- openpkflow-0.1.2/CLAUDE.md +220 -0
- openpkflow-0.1.2/LICENSE +21 -0
- openpkflow-0.1.2/PKG-INFO +191 -0
- openpkflow-0.1.2/README.md +140 -0
- openpkflow-0.1.2/docs/dissolution.md +207 -0
- openpkflow-0.1.2/examples/dissolution_advanced.py +283 -0
- openpkflow-0.1.2/examples/dissolution_basic.py +99 -0
- openpkflow-0.1.2/examples/output/dissolution_report.html +352 -0
- openpkflow-0.1.2/pyproject.toml +100 -0
- openpkflow-0.1.2/src/openpkflow/__init__.py +10 -0
- openpkflow-0.1.2/src/openpkflow/bayes/__init__.py +1 -0
- openpkflow-0.1.2/src/openpkflow/cli.py +123 -0
- openpkflow-0.1.2/src/openpkflow/datasets/__init__.py +26 -0
- openpkflow-0.1.2/src/openpkflow/datasets/example_dissolution.csv +37 -0
- openpkflow-0.1.2/src/openpkflow/datasets/example_not_similar.csv +37 -0
- openpkflow-0.1.2/src/openpkflow/datasets/example_similar.csv +37 -0
- openpkflow-0.1.2/src/openpkflow/dissolution/__init__.py +18 -0
- openpkflow-0.1.2/src/openpkflow/dissolution/bootstrap.py +161 -0
- openpkflow-0.1.2/src/openpkflow/dissolution/loader.py +159 -0
- openpkflow-0.1.2/src/openpkflow/dissolution/plotting.py +68 -0
- openpkflow-0.1.2/src/openpkflow/dissolution/reporting.py +169 -0
- openpkflow-0.1.2/src/openpkflow/dissolution/similarity.py +163 -0
- openpkflow-0.1.2/src/openpkflow/dissolution/study.py +275 -0
- openpkflow-0.1.2/src/openpkflow/ml/__init__.py +1 -0
- openpkflow-0.1.2/src/openpkflow/nca/__init__.py +1 -0
- openpkflow-0.1.2/src/openpkflow/pop/__init__.py +1 -0
- openpkflow-0.1.2/src/openpkflow/py.typed +0 -0
- openpkflow-0.1.2/src/openpkflow/report/__init__.py +8 -0
- openpkflow-0.1.2/src/openpkflow/report/html.py +107 -0
- openpkflow-0.1.2/src/openpkflow/report/templates/dissolution_report.html +333 -0
- openpkflow-0.1.2/src/openpkflow/sim/__init__.py +1 -0
- openpkflow-0.1.2/src/openpkflow/validation/__init__.py +1 -0
- openpkflow-0.1.2/tests/__init__.py +0 -0
- openpkflow-0.1.2/tests/dissolution/__init__.py +0 -0
- openpkflow-0.1.2/tests/dissolution/test_bootstrap.py +176 -0
- openpkflow-0.1.2/tests/dissolution/test_similarity.py +240 -0
- openpkflow-0.1.2/tests/dissolution/test_study.py +203 -0
- openpkflow-0.1.2/tests/test_cli.py +183 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Python ${{ matrix.python-version }}
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
fail-fast: false
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install package and dev dependencies
|
|
27
|
+
run: |
|
|
28
|
+
python -m pip install --upgrade pip
|
|
29
|
+
pip install -e ".[dev]"
|
|
30
|
+
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: pytest --tb=short -q
|
|
33
|
+
|
|
34
|
+
- name: Check types
|
|
35
|
+
run: mypy src/openpkflow --ignore-missing-imports
|
|
36
|
+
continue-on-error: true
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write # required for Trusted Publishing
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
name: Build distribution
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.12"
|
|
23
|
+
|
|
24
|
+
- name: Install build tools
|
|
25
|
+
run: python -m pip install --upgrade pip build twine
|
|
26
|
+
|
|
27
|
+
- name: Build wheel and sdist
|
|
28
|
+
run: python -m build
|
|
29
|
+
|
|
30
|
+
- name: Check distribution
|
|
31
|
+
run: python -m twine check dist/*
|
|
32
|
+
|
|
33
|
+
- name: Upload build artifacts
|
|
34
|
+
uses: actions/upload-artifact@v4
|
|
35
|
+
with:
|
|
36
|
+
name: dist
|
|
37
|
+
path: dist/
|
|
38
|
+
|
|
39
|
+
publish-testpypi:
|
|
40
|
+
name: Publish to TestPyPI
|
|
41
|
+
needs: build
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
environment: testpypi
|
|
44
|
+
|
|
45
|
+
permissions:
|
|
46
|
+
id-token: write
|
|
47
|
+
|
|
48
|
+
steps:
|
|
49
|
+
- name: Download build artifacts
|
|
50
|
+
uses: actions/download-artifact@v4
|
|
51
|
+
with:
|
|
52
|
+
name: dist
|
|
53
|
+
path: dist/
|
|
54
|
+
|
|
55
|
+
- name: Publish to TestPyPI
|
|
56
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
57
|
+
with:
|
|
58
|
+
repository-url: https://test.pypi.org/legacy/
|
|
59
|
+
|
|
60
|
+
publish-pypi:
|
|
61
|
+
name: Publish to PyPI
|
|
62
|
+
needs: publish-testpypi
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
environment: pypi
|
|
65
|
+
|
|
66
|
+
permissions:
|
|
67
|
+
id-token: write
|
|
68
|
+
|
|
69
|
+
steps:
|
|
70
|
+
- name: Download build artifacts
|
|
71
|
+
uses: actions/download-artifact@v4
|
|
72
|
+
with:
|
|
73
|
+
name: dist
|
|
74
|
+
path: dist/
|
|
75
|
+
|
|
76
|
+
- name: Publish to PyPI
|
|
77
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
.Python
|
|
7
|
+
*.egg-info/
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
.eggs/
|
|
11
|
+
*.egg
|
|
12
|
+
*.whl
|
|
13
|
+
|
|
14
|
+
# Virtual environments
|
|
15
|
+
.venv/
|
|
16
|
+
venv/
|
|
17
|
+
env/
|
|
18
|
+
ENV/
|
|
19
|
+
|
|
20
|
+
# Testing
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
.tox/
|
|
25
|
+
|
|
26
|
+
# Type checking
|
|
27
|
+
.mypy_cache/
|
|
28
|
+
|
|
29
|
+
# IDE
|
|
30
|
+
.vscode/
|
|
31
|
+
.idea/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
|
|
35
|
+
# OS
|
|
36
|
+
.DS_Store
|
|
37
|
+
Thumbs.db
|
|
38
|
+
|
|
39
|
+
# Distribution
|
|
40
|
+
dist/
|
|
41
|
+
*.tar.gz
|
|
42
|
+
|
|
43
|
+
# Jupyter
|
|
44
|
+
.ipynb_checkpoints/
|
|
45
|
+
*.ipynb
|
|
46
|
+
|
|
47
|
+
# Local config/secrets
|
|
48
|
+
.env
|
|
49
|
+
*.local
|
|
50
|
+
|
|
51
|
+
# Reports generated during tests (but allow templates and docs)
|
|
52
|
+
*.pdf
|
|
53
|
+
*.html
|
|
54
|
+
*.docx
|
|
55
|
+
*.xlsx
|
|
56
|
+
!src/**/*.html
|
|
57
|
+
!examples/**/*.html
|
|
58
|
+
!docs/**
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to OpenPKFlow will be documented in this file.
|
|
4
|
+
|
|
5
|
+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
|
+
Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [Unreleased]
|
|
11
|
+
|
|
12
|
+
## [0.1.2] — 2026-05-18
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- PyPI Trusted Publishing via GitHub Actions (`publish.yml`) — triggers on version tags, publishes to TestPyPI then PyPI using OIDC (no stored tokens)
|
|
16
|
+
|
|
17
|
+
## [0.1.1] — 2026-05-18
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- `dissolution.bootstrap_f2()` — bootstrap CI for f2 (Shah 1998, Davit 2013); suitable for small-sample (<12 vessel) similarity assessment
|
|
21
|
+
- `dissolution.plotting.dissolution_profile_plot_b64()` — embedded matplotlib profile plot in HTML reports
|
|
22
|
+
- HTML reports now include a dissolution profile chart (reference vs test, 85% threshold line)
|
|
23
|
+
- `datasets.example_similar_path()` — example dataset with f2 ~80 (clearly similar profiles)
|
|
24
|
+
- `datasets.example_not_similar_path()` — example dataset with f2 ~38 (clearly dissimilar profiles)
|
|
25
|
+
- `py.typed` marker (PEP 561) — enables mypy type checking in downstream projects
|
|
26
|
+
- GitHub Actions CI — matrix build across Python 3.10, 3.11, 3.12
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
- `datasets/__init__.py` — constants replaced with `example_dissolution_path()`, `example_similar_path()`, `example_not_similar_path()` functions using `importlib.resources`
|
|
30
|
+
- CLAUDE.md — added Commands section, data flow diagram, Windows ASCII constraint note
|
|
31
|
+
|
|
32
|
+
## [0.1.0] — 2026-05-17
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
- `dissolution.f1()` — difference factor (FDA/EMA dissolution guidance)
|
|
36
|
+
- `dissolution.f2()` — similarity factor (FDA/EMA dissolution guidance)
|
|
37
|
+
- `dissolution.DissolutionProfile` — validated data container for a single dissolution profile
|
|
38
|
+
- `dissolution.DissolutionStudy` — high-level study object: load CSV, compare, fit, report
|
|
39
|
+
- `dissolution.loader` — CSV ingestion with schema validation
|
|
40
|
+
- `dissolution.reporting` — Markdown and HTML report generation
|
|
41
|
+
- CLI command `openpkflow similarity` for f1/f2 from terminal
|
|
42
|
+
- CLI command `openpkflow version`
|
|
43
|
+
- Example dataset `datasets/example_dissolution.csv`
|
|
44
|
+
- Example script `examples/dissolution_basic.py`
|
|
45
|
+
- Full test suite with reference validation examples
|
|
46
|
+
|
|
47
|
+
### Notes
|
|
48
|
+
- f1/f2 require caller to supply matched, time-aligned percent-release values
|
|
49
|
+
- No external GUI or enterprise platform connectivity in this release
|
|
50
|
+
- Disclaimer: open-source research workflow; final regulatory interpretation requires expert review
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use OpenPKFlow in your research, please cite it as below."
|
|
3
|
+
authors:
|
|
4
|
+
- family-names: Thakar
|
|
5
|
+
given-names: Priyam
|
|
6
|
+
email: priyamthakar1@gmail.com
|
|
7
|
+
title: "OpenPKFlow: Python-first pharmacometrics and dissolution toolkit"
|
|
8
|
+
version: 0.1.0
|
|
9
|
+
date-released: 2026-05-17
|
|
10
|
+
url: "https://github.com/priyamthakar/openpkflow"
|
|
11
|
+
license: MIT
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Identity
|
|
6
|
+
|
|
7
|
+
**Package:** `openpkflow`
|
|
8
|
+
**Author:** Priyam Thakar <priyamthakar1@gmail.com>
|
|
9
|
+
**GitHub:** https://github.com/priyamthakar/openpkflow
|
|
10
|
+
**PyPI target:** `pip install openpkflow`
|
|
11
|
+
**License:** MIT
|
|
12
|
+
**Philosophy:** Transparent, reproducible, open-source Python workflow for dissolution, NCA, PK/PD simulation, and pharmacometric reporting. Does not replace expert regulatory judgement or validated commercial platforms.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Commands
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Install in editable mode with dev tools
|
|
20
|
+
pip install -e ".[dev]"
|
|
21
|
+
|
|
22
|
+
# Run all tests
|
|
23
|
+
pytest
|
|
24
|
+
|
|
25
|
+
# Run tests with coverage
|
|
26
|
+
pytest --cov=src/openpkflow --cov-report=term-missing
|
|
27
|
+
|
|
28
|
+
# Run a single test file
|
|
29
|
+
pytest tests/dissolution/test_similarity.py
|
|
30
|
+
|
|
31
|
+
# Run a single test by name
|
|
32
|
+
pytest tests/dissolution/test_similarity.py::TestF2::test_identical_profiles
|
|
33
|
+
|
|
34
|
+
# Lint and auto-fix
|
|
35
|
+
ruff check src/ tests/ --fix
|
|
36
|
+
ruff format src/ tests/
|
|
37
|
+
|
|
38
|
+
# Type-check
|
|
39
|
+
mypy src/openpkflow
|
|
40
|
+
|
|
41
|
+
# Build wheel/sdist
|
|
42
|
+
python -m build
|
|
43
|
+
|
|
44
|
+
# Verify wheel before upload
|
|
45
|
+
python -m twine check dist/*
|
|
46
|
+
|
|
47
|
+
# CLI
|
|
48
|
+
openpkflow version
|
|
49
|
+
openpkflow similarity --reference "20,40,60,80" --test "21,39,61,79"
|
|
50
|
+
openpkflow dissolution compare data.csv --reference reference --test test --report out.html
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Architecture
|
|
56
|
+
|
|
57
|
+
- **Layout:** `src/` layout (PEP 517/518). Always import from `src/openpkflow/`, never from project root.
|
|
58
|
+
- **Build:** hatchling (`pyproject.toml`)
|
|
59
|
+
- **Python floor:** 3.10+
|
|
60
|
+
- **Core deps:** numpy, pandas, scipy, matplotlib, pydantic, typer, jinja2
|
|
61
|
+
- **Optional deps:** `[reports]` (openpyxl, reportlab, python-docx), `[bayes]` (pymc, arviz, cmdstanpy), `[ml]` (scikit-learn, torch), `[dev]` (pytest, ruff, mypy, build, twine)
|
|
62
|
+
- **Avoid WeasyPrint** — Windows/GTK dependencies are painful. Use ReportLab for PDF.
|
|
63
|
+
|
|
64
|
+
### Module map
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
dissolution/ — f1, f2, bootstrap_f2, model fitting, loader, reporting ← current MVP
|
|
68
|
+
nca/ — AUC, lambda_z, PK parameters, tables, reporting ← v0.4.0
|
|
69
|
+
sim/ — ODE compartment models, dosing, population sim ← v0.5.0
|
|
70
|
+
pop/ — population PK dataset helpers, diagnostics, VPC ← v0.6.0
|
|
71
|
+
bayes/ — PyMC/Stan Bayesian PK models ← v0.8.0
|
|
72
|
+
ml/ — neural ODE, features, predictors ← v0.9.0
|
|
73
|
+
report/ — Markdown, HTML, PDF (ReportLab), Word (python-docx) ← v0.3.0
|
|
74
|
+
datasets/ — example CSV files for tests and examples
|
|
75
|
+
validation/ — reference comparison utilities
|
|
76
|
+
cli.py — Typer CLI entry point
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Dissolution data flow
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
CSV file
|
|
83
|
+
→ load_dissolution_csv() # pydantic-validated DataFrame
|
|
84
|
+
→ DissolutionStudy.from_csv() # groups by formulation label
|
|
85
|
+
→ study.compare(ref, test) # calls get_formulation_means(), then f1/f2
|
|
86
|
+
→ ComparisonResult # dataclass: f1_value, f2_value, means, time_points
|
|
87
|
+
→ result.summary() # text to stdout
|
|
88
|
+
→ result.report("out.html") # → report_dissolution() → render_html_report()
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Report rendering
|
|
92
|
+
|
|
93
|
+
- HTML template lives at `src/openpkflow/report/templates/dissolution_report.html`
|
|
94
|
+
- Jinja2 renderer is `src/openpkflow/report/html.py` — note: `zip` is manually injected into `env.globals` because Jinja2 does not expose Python builtins
|
|
95
|
+
- Markdown renderer is `src/openpkflow/dissolution/reporting.py`
|
|
96
|
+
- Format is inferred from file extension in `report_dissolution()`
|
|
97
|
+
|
|
98
|
+
### Windows console constraint
|
|
99
|
+
|
|
100
|
+
All CLI output and docstrings must use ASCII-only characters. Unicode punctuation (em dashes `—`, right arrows `→`, `>=`, `<=`) causes `UnicodeEncodeError` on Windows cp1252 consoles. Use plain ASCII equivalents (`>=`, `->`, `-`).
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Current focus
|
|
105
|
+
|
|
106
|
+
v0.1.1 is tagged and CI-passing. Immediate priority is PyPI publication (TestPyPI first), then v0.1.2 polish, then v0.2.0 model fitting.
|
|
107
|
+
|
|
108
|
+
**Before any new feature:** run `python -m build && python -m twine check dist/*` to confirm the wheel is clean.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Release Ladder
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
0.1.0 f1, f2, input validation, CSV loader, CLI, Markdown+HTML report stub, tests DONE
|
|
116
|
+
0.1.1 bootstrap_f2, profile plots in HTML reports, CI, example datasets, py.typed DONE
|
|
117
|
+
0.1.2 PyPI publish, README validation claims softened, f2_method="regulatory" option,
|
|
118
|
+
CV% warning in DissolutionStudy.compare(), validation/ notebook stub
|
|
119
|
+
0.2.0 dissolution model fitting (Weibull, Korsmeyer-Peppas, Higuchi, first-order,
|
|
120
|
+
zero-order) — scipy curve_fit, AIC/BIC/R2, fit overlay in HTML report
|
|
121
|
+
0.3.0 full Markdown + HTML + ReportLab PDF report generator
|
|
122
|
+
0.4.0 NCA engine (AUC, Cmax, Tmax, lambda_z, t1/2, CL/F, Vz/F)
|
|
123
|
+
0.5.0 PK simulation (1-comp, 2-comp, oral, IV, infusion, repeated dosing)
|
|
124
|
+
0.6.0 population PK diagnostics, GOF plots, VPC helpers
|
|
125
|
+
0.7.0 Pharmpy bridge
|
|
126
|
+
0.8.0 Bayesian PK (PyMC, CmdStanPy)
|
|
127
|
+
0.9.0 ML / neural ODE prototypes
|
|
128
|
+
1.0.0 stable public release
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Code Conventions
|
|
134
|
+
|
|
135
|
+
- **Type hints required** on all public API functions and methods.
|
|
136
|
+
- **Docstrings required** on all public functions — use NumPy docstring style.
|
|
137
|
+
- **No comments** unless the WHY is non-obvious (hidden constraint, subtle invariant, workaround).
|
|
138
|
+
- **No multi-paragraph docstrings** — one short description line, then Parameters/Returns/Raises sections only.
|
|
139
|
+
- Line length: 100 characters (ruff).
|
|
140
|
+
- Formatting: ruff (`ruff format`), linting: ruff lint, type-checking: mypy strict.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Pharmacometric Correctness Rules
|
|
145
|
+
|
|
146
|
+
These are load-bearing. Do not violate them.
|
|
147
|
+
|
|
148
|
+
1. **f1/f2 require matched time points.** Caller supplies aligned `reference` and `test` arrays. The functions do not silently reindex or interpolate. If arrays differ in length, raise `ValueError`.
|
|
149
|
+
|
|
150
|
+
2. **AUC method must be explicit.** Never silently default. Always require the caller to pass the method name (`"linear"`, `"log"`, `"linear_up_log_down"`).
|
|
151
|
+
|
|
152
|
+
3. **Apparent vs absolute parameters must be distinguished in output names.** Use `CL_F` for oral apparent clearance, `CL` for IV-derived clearance. Never mix them in the same output without labelling.
|
|
153
|
+
|
|
154
|
+
4. **BLQ handling must be explicit.** Never silently drop BLQ values. Require the caller to specify the method.
|
|
155
|
+
|
|
156
|
+
5. **Disclaimer required in all generated reports:**
|
|
157
|
+
> This report was generated using OpenPKFlow (open-source). Final regulatory interpretation should be reviewed by qualified formulation, pharmacokinetic, and regulatory experts.
|
|
158
|
+
|
|
159
|
+
6. **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.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Validation Discipline (mandatory from day one)
|
|
164
|
+
|
|
165
|
+
Every formula function must have at minimum two test cases:
|
|
166
|
+
|
|
167
|
+
1. A **degenerate/sanity case** with a hand-checkable answer (e.g., identical input → f2 = 100).
|
|
168
|
+
2. A **published reference example** with the citation in the test's docstring (paper DOI, FDA guidance ID, or R-package vignette name).
|
|
169
|
+
|
|
170
|
+
Tests must cite the source of the expected value. "I calculated it manually" is not a citation.
|
|
171
|
+
|
|
172
|
+
Known reference values:
|
|
173
|
+
- f2 = 100 when reference == test (by definition)
|
|
174
|
+
- f2 ≈ 50 when profiles differ by ~10 percentage points at each timepoint (FDA 1997 guidance threshold)
|
|
175
|
+
- f1 = 0 when reference == test (by definition)
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Report Format Priority
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
v0.1.x: console summary → Markdown report → HTML report with embedded profile plot
|
|
183
|
+
v0.2.x: dissolution model fitting results in reports
|
|
184
|
+
v0.3.0: ReportLab PDF export, python-docx Word export
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
OpenPKFlow is **report-first**: the product delivers clean, professional, regulatory-style reports. Calculation correctness is necessary but not sufficient — the output must be shareable with supervisors, clients, CROs, and regulatory teams.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Git Conventions
|
|
192
|
+
|
|
193
|
+
- Never force-push. Never `--no-verify`. Never amend published commits.
|
|
194
|
+
- Commit message format: `<type>(<scope>): <short description>` (e.g., `feat(dissolution): add f1 and f2 with validation`)
|
|
195
|
+
- Version bumps: update `pyproject.toml` version and `CHANGELOG.md` together in one commit.
|
|
196
|
+
- Tag releases: `git tag v0.1.1`
|
|
197
|
+
|
|
198
|
+
## PyPI Upload Order
|
|
199
|
+
|
|
200
|
+
1. tests passing locally
|
|
201
|
+
2. `pip install -e .` works
|
|
202
|
+
3. `python -m build` succeeds
|
|
203
|
+
4. `python -m twine check dist/*` clean
|
|
204
|
+
5. Upload to TestPyPI: `twine upload --repository testpypi dist/*`
|
|
205
|
+
6. Fresh venv install: `pip install -i https://test.pypi.org/simple/ openpkflow` — verify `openpkflow version` and `openpkflow similarity` work
|
|
206
|
+
7. Upload to real PyPI: `twine upload dist/*`
|
|
207
|
+
|
|
208
|
+
**Preferred: PyPI Trusted Publishing** — no stored token, scoped to the repo. Set up at pypi.org/manage/account/publishing/ then add a `publish.yml` GitHub Actions workflow that triggers on version tags. Only the repo owner can configure this — it requires a one-time manual step at pypi.org.
|
|
209
|
+
|
|
210
|
+
Do not upload broken or untested wheels.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Positioning Reminder
|
|
215
|
+
|
|
216
|
+
Use:
|
|
217
|
+
> **A transparent, reproducible, open-source Python workflow for dissolution, NCA, PK/PD simulation, and pharmacometric reporting.**
|
|
218
|
+
|
|
219
|
+
Never say:
|
|
220
|
+
> "FDA-approved", "replaces Certara", "AI discovers the perfect formulation."
|
openpkflow-0.1.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Priyam Thakar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openpkflow
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Python-first toolkit for dissolution, NCA, PK/PD simulation, and pharmacometric reporting.
|
|
5
|
+
Project-URL: Homepage, https://github.com/priyamthakar/openpkflow
|
|
6
|
+
Project-URL: Repository, https://github.com/priyamthakar/openpkflow
|
|
7
|
+
Project-URL: Issues, https://github.com/priyamthakar/openpkflow/issues
|
|
8
|
+
Project-URL: Documentation, https://priyamthakar.github.io/openpkflow/
|
|
9
|
+
Author-email: Priyam Thakar <priyamthakar1@gmail.com>
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: NCA,PKPD,bioequivalence,dissolution,formulation,pharmacokinetics,pharmacometrics
|
|
13
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
14
|
+
Classifier: Intended Audience :: Healthcare Industry
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering
|
|
23
|
+
Classifier: Typing :: Typed
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: jinja2>=3.1
|
|
26
|
+
Requires-Dist: matplotlib>=3.7
|
|
27
|
+
Requires-Dist: numpy>=1.24
|
|
28
|
+
Requires-Dist: pandas>=2.0
|
|
29
|
+
Requires-Dist: pydantic>=2.0
|
|
30
|
+
Requires-Dist: scipy>=1.10
|
|
31
|
+
Requires-Dist: typer>=0.12
|
|
32
|
+
Provides-Extra: bayes
|
|
33
|
+
Requires-Dist: arviz>=0.16; extra == 'bayes'
|
|
34
|
+
Requires-Dist: cmdstanpy>=1.2; extra == 'bayes'
|
|
35
|
+
Requires-Dist: pymc>=5.0; extra == 'bayes'
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
38
|
+
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
39
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
40
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
41
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
42
|
+
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
43
|
+
Provides-Extra: ml
|
|
44
|
+
Requires-Dist: scikit-learn>=1.4; extra == 'ml'
|
|
45
|
+
Requires-Dist: torch>=2.0; extra == 'ml'
|
|
46
|
+
Provides-Extra: reports
|
|
47
|
+
Requires-Dist: openpyxl>=3.1; extra == 'reports'
|
|
48
|
+
Requires-Dist: python-docx>=1.1; extra == 'reports'
|
|
49
|
+
Requires-Dist: reportlab>=4.0; extra == 'reports'
|
|
50
|
+
Description-Content-Type: text/markdown
|
|
51
|
+
|
|
52
|
+
# OpenPKFlow
|
|
53
|
+
|
|
54
|
+
**A transparent, reproducible, open-source Python workflow for dissolution, NCA, PK/PD simulation, and pharmacometric reporting.**
|
|
55
|
+
|
|
56
|
+
[](https://github.com/priyamthakar/openpkflow/actions/workflows/ci.yml)
|
|
57
|
+
[](https://pypi.org/project/openpkflow/)
|
|
58
|
+
[](https://pypi.org/project/openpkflow/)
|
|
59
|
+
[](LICENSE)
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## What it does
|
|
64
|
+
|
|
65
|
+
OpenPKFlow gives formulation scientists, PK/PD researchers, and CRO/CDMO teams a clean Python workflow for:
|
|
66
|
+
|
|
67
|
+
- **Dissolution similarity** — f1, f2, bootstrap f2, model fitting
|
|
68
|
+
- **NCA** — AUC, Cmax, Tmax, half-life, CL/F, Vz/F *(planned v0.4.0)*
|
|
69
|
+
- **PK simulation** — 1- and 2-compartment models, oral/IV/infusion *(planned v0.5.0)*
|
|
70
|
+
- **Report generation** — Markdown, HTML, PDF, Word *(planned v0.3.0)*
|
|
71
|
+
|
|
72
|
+
It does not replace expert regulatory judgement or validated commercial platforms.
|
|
73
|
+
It makes routine analysis faster, cleaner, and more reproducible.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Install
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install openpkflow
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
For report generation:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pip install openpkflow[reports]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Quick start
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from openpkflow.dissolution import f1, f2
|
|
95
|
+
|
|
96
|
+
reference = [20.0, 40.0, 60.0, 80.0, 90.0]
|
|
97
|
+
test = [21.0, 39.0, 61.0, 79.0, 88.0]
|
|
98
|
+
|
|
99
|
+
print(f"f1 = {f1(reference, test):.2f}")
|
|
100
|
+
print(f"f2 = {f2(reference, test):.2f}")
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### From a CSV file
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from openpkflow.dissolution import DissolutionStudy
|
|
107
|
+
|
|
108
|
+
study = DissolutionStudy.from_csv("dissolution.csv")
|
|
109
|
+
|
|
110
|
+
result = study.compare(reference="reference", test="test")
|
|
111
|
+
result.summary()
|
|
112
|
+
result.report("dissolution_report.html")
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### CSV format
|
|
116
|
+
|
|
117
|
+
```csv
|
|
118
|
+
formulation,batch,time,percent_released
|
|
119
|
+
reference,R1,5,18.2
|
|
120
|
+
reference,R1,10,31.4
|
|
121
|
+
reference,R1,15,47.9
|
|
122
|
+
test,T1,5,17.5
|
|
123
|
+
test,T1,10,30.1
|
|
124
|
+
test,T1,15,46.2
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### CLI
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
openpkflow version
|
|
131
|
+
openpkflow similarity --reference "20,40,60,80" --test "21,39,61,79"
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Current status (v0.1.0)
|
|
137
|
+
|
|
138
|
+
| Module | Status |
|
|
139
|
+
|---|---|
|
|
140
|
+
| `dissolution.f1` / `dissolution.f2` | Stable |
|
|
141
|
+
| Dissolution CSV loader | Stable |
|
|
142
|
+
| Markdown + HTML report stub | Stable |
|
|
143
|
+
| CLI | Stable |
|
|
144
|
+
| Bootstrap f2 | Planned v0.1.1 |
|
|
145
|
+
| Dissolution model fitting | Planned v0.2.0 |
|
|
146
|
+
| Full report generation | Planned v0.3.0 |
|
|
147
|
+
| NCA | Planned v0.4.0 |
|
|
148
|
+
| PK simulation | Planned v0.5.0 |
|
|
149
|
+
| Population PK | Planned v0.6.0 |
|
|
150
|
+
| Bayesian PK | Planned v0.8.0 |
|
|
151
|
+
| ML / neural ODE | Planned v0.9.0 |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Validation
|
|
156
|
+
|
|
157
|
+
All formula implementations are validated against:
|
|
158
|
+
|
|
159
|
+
- Published FDA/EMA guidance examples
|
|
160
|
+
- R package reference outputs (PKNCA, bootf2)
|
|
161
|
+
- Manual Excel calculations
|
|
162
|
+
|
|
163
|
+
Validation test cases cite their sources. See `tests/` for details.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Disclaimer
|
|
168
|
+
|
|
169
|
+
This software is for research and decision-support workflows.
|
|
170
|
+
Final regulatory interpretation should be reviewed by qualified formulation, pharmacokinetic, and regulatory experts.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Contributing
|
|
175
|
+
|
|
176
|
+
Issues and PRs welcome at https://github.com/priyamthakar/openpkflow/issues
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Citation
|
|
181
|
+
|
|
182
|
+
If you use OpenPKFlow in research, please cite:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
Thakar, P. (2026). OpenPKFlow: Python-first pharmacometrics and dissolution toolkit.
|
|
186
|
+
https://github.com/priyamthakar/openpkflow
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
MIT — see [LICENSE](LICENSE)
|