Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Package Overview

PKPDmap is an R package implementing Maximum A Posteriori (MAP) Bayesian estimation and non-parametric fitting for pharmacokinetic/pharmacodynamic (PK/PD) data. It depends heavily on [PKPDsim](https://github.com/InsightRX/PKPDsim) (also an InsightRX package) for ODE-based PK/PD simulation.

## Common Commands

All development uses standard R/devtools workflows (no Makefile):

```r
# Load package for interactive development
devtools::load_all()

# Run all tests
devtools::test()

# Run a single test file
devtools::test(filter = "get_map_estimates")

# Regenerate documentation from roxygen2 comments
devtools::document()

# Full R CMD check (as done in CI)
devtools::check("--no-manual --as-cran")
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

devtools::check("--no-manual --as-cran") passes both flags as a single argument string; R CMD check expects them as separate args, and this doesn’t match the CI workflow (which passes --no-manual and --as-cran separately). Update the example to pass a character vector of args so local checks behave like CI.

Suggested change
devtools::check("--no-manual --as-cran")
devtools::check(args = c("--no-manual", "--as-cran"))

Copilot uses AI. Check for mistakes.

# Install PKPDsim dependency from GitHub (requires PAT_TOKEN)
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says installing from GitHub “requires PAT_TOKEN”, but remotes::install_github() uses the GITHUB_PAT environment variable (and in CI this is populated from the PAT_TOKEN secret). Reword this to avoid confusion for local dev (e.g., mention GITHUB_PAT for local installs and that CI maps it from secrets.PAT_TOKEN).

Suggested change
# Install PKPDsim dependency from GitHub (requires PAT_TOKEN)
# Install PKPDsim dependency from GitHub (requires GITHUB_PAT locally; in CI this comes from secrets.PAT_TOKEN)

Copilot uses AI. Check for mistakes.
remotes::install_github("InsightRX/PKPDsim")
```

## Architecture

### Estimation Methods

The main entry point is `get_map_estimates()` (`R/get_map_estimates.R`), which supports five estimation methods via the `method` argument:

- `map` — standard MAP Bayesian with empirical Bayes (default)
- `map_flat_prior` — MAP with flattened priors (reduced shrinkage)
- `ls` — Least squares (nearly-flat MAP priors)
- `np` — Non-parametric estimation on a user-supplied parameter matrix
- `np_hybrid` — Hybrid MAP + non-parametric grid search

### Estimation Pipeline

```
get_map_estimates()
├── check_inputs() # validate all inputs upfront
├── parse_*()/ # ~10 parse_ functions normalize inputs
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the pipeline diagram, parse_*()/ includes a trailing /, which reads like a typo and is inconsistent with the other entries. Consider removing the slash to keep the diagram clean.

Suggested change
├── parse_*()/ # ~10 parse_ functions normalize inputs
├── parse_*() # ~10 parse_ functions normalize inputs

Copilot uses AI. Check for mistakes.
│ ├── parse_input_data()
│ ├── parse_omega_matrix()
│ ├── parse_error()
│ └── ...
├── mle_wrapper() # wraps optim() + Hessian calculation
│ └── ll_func_PKPDsim() # likelihood: calls PKPDsim, applies error model + censoring
└── get_np_estimates() # for np/np_hybrid methods
```

### Key Function Roles

| File | Purpose |
|------|---------|
| `R/get_map_estimates.R` | Main user-facing function; orchestrates the full estimation pipeline |
| `R/mle_wrapper.R` | Wraps `optim()`, handles Hessian for variance-covariance |
| `R/ll_func_PKPDsim.R` | Computes log-likelihood by calling PKPDsim and applying residual error + censoring |
| `R/calc_ofv_map.R` | Objective function value for MAP (includes prior penalty) |
| `R/calc_ofv_ls.R` | OFV for least squares |
| `R/get_np_estimates.R` | Non-parametric grid search fitting |
| `R/parse_omega_matrix.R` | Converts various omega input formats to full covariance matrix |
| `R/check_inputs.R` | Comprehensive upfront validation (throws descriptive errors) |
| `R/run_sequential_map.R` | Batch MAP estimation across multiple individuals |

### Parameter Conventions

- **ETA (η)**: Random effects (inter-individual variability), parameterized on log-normal or normal scale
- **Omega (Ω)**: Between-subject variability covariance matrix — can be supplied as full matrix, CV%, or variance vector
- **IOV**: Inter-occasion variability, handled via `create_iov_object()`
- **Fixed parameters**: Listed in `fixed` argument to exclude from optimization

### Test Organization

Tests live in `tests/testthat/`. The most comprehensive test file is `test-get_map_estimates.R`. Snapshot outputs for regression testing are stored in `tests/testthat/output/`. Test setup fixtures (shared model objects) are in `tests/testthat/setup.R`.

## CI

GitHub Actions runs `R CMD check --no-manual --as-cran` on Ubuntu/R-release on push/PR to `master`. macOS and Windows runners are currently disabled in the matrix.
Loading