---
title: "Getting started with admixr2"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Getting started with admixr2}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(
  collapse = TRUE, comment = "#>",
  message = FALSE, warning = FALSE,
  fig.width = 7, fig.height = 5
)
```

## What is aggregate-data modelling?

`admixr2` fits pharmacometric PK/PD models to **summary-level data**. For each
clinical study you supply:

- **E** — observed mean vector (one entry per observation time)
- **V** — observed covariance matrix (or variance vector)
- **n** — sample size
- **times** — observation time points
- **ev** — dosing event table

The estimators match E and V against their model-predicted counterparts and
return a standard nlmixr2 fit object. This lets you apply established nlmixr2
models to aggregate statistics from publications or internal data summaries
where individual records are unavailable.

Three estimators are available:

| Estimator | `est =` | Control function | Approach |
|-----------|---------|-----------------|---------|
| First-Order | `"adfo"` | `adfoControl()` | First-order Taylor expansion at η = 0; one rxSolve per NLL eval; fastest |
| Monte Carlo | `"admc"` | `admControl()` | Sample average over η; asymptotically exact |
| Iterative Reweighting MC | `"adirmc"` | `adirmcControl()` | Proposals fixed per phase; inner loop needs no new rxSolve calls |

`adfo` is the natural starting point for model screening and initial estimates.
`admc` is the workhorse for standard PK models. `adirmc` is preferred for
complex ODE systems with expensive solves, high-dimensional IIV, or poor
starting values. See
`vignette("estimator-comparison", package = "admixr2")` for a detailed comparison.

## The examplomycin dataset

`examplomycin` ships with admixr2: 500 simulated subjects from a two-compartment
PK model with first-order absorption (100 mg oral dose, sampled at 0.1, 0.25,
0.5, 1, 2, 3, 5, 8, and 12 h). True parameters: CL = 5 L/h, V1 = 10 L,
V2 = 30 L, Q = 10 L/h, ka = 1 h⁻¹; IIV = 0.3 (SD on log scale) for all
parameters; proportional error SD = 0.2.

```{r data}
library(admixr2)
library(rxode2)
library(nlmixr2)

data("examplomycin")
head(examplomycin[examplomycin$EVID == 0, c("ID", "TIME", "DV")], 9)
```

## Computing aggregate statistics

Reshape individual records into a subjects × times matrix, then compute E and V:

```{r aggregate}
obs   <- examplomycin[examplomycin$EVID == 0, ]
obs   <- obs[order(obs$ID, obs$TIME), ]
times <- sort(unique(obs$TIME))
ids   <- unique(obs$ID)
n     <- length(ids)                     # 500

dv_mat <- matrix(NA_real_, nrow = n, ncol = length(times))
for (i in seq_along(ids)) {
  sub         <- obs[obs$ID == ids[i], ]
  dv_mat[i, ] <- sub$DV[order(sub$TIME)]
}

E <- colMeans(dv_mat)
V <- cov.wt(dv_mat, method = "ML")$cov

round(E, 2)
```

`V` is the 9×9 sample covariance matrix. Its off-diagonal entries capture
within-subject correlation across time; using the full matrix (`method = "cov"`)
typically tightens parameter estimates compared to the diagonal-only approximation
(`method = "var"`). `admixr2` auto-detects the method from the structure of V.

## Model definition

Models use standard nlmixr2 syntax with mu-referenced log-scale parameters:

```{r model}
pk_model <- function() {
  ini({
    tcl     <- log(5)  ; label("Log clearance (L/hr)")
    tv1     <- log(10) ; label("Log central volume (L)")
    tv2     <- log(30) ; label("Log peripheral volume (L)")
    tq      <- log(10) ; label("Log inter-compartmental CL (L/hr)")
    tka     <- log(1)  ; label("Log absorption rate constant (1/hr)")
    prop.sd <- c(0, 0.2); label("Proportional residual error SD")
    eta.cl ~ 0.09
    eta.v1 ~ 0.09
    eta.v2 ~ 0.09
    eta.q  ~ 0.09
    eta.ka ~ 0.09
  })
  model({
    cl <- exp(tcl + eta.cl)
    v1 <- exp(tv1 + eta.v1)
    v2 <- exp(tv2 + eta.v2)
    q  <- exp(tq  + eta.q)
    ka <- exp(tka + eta.ka)
    d/dt(depot)      <- -ka * depot
    d/dt(central)    <- ka * depot - (cl/v1 + q/v1) * central + (q/v2) * peripheral
    d/dt(peripheral) <- (q/v1) * central - (q/v2) * peripheral
    cp <- central / v1
    cp ~ prop(prop.sd)
  })
}
```

Writing each parameter as `exp(tcl + eta.cl)` is called **mu-referencing**:
the structural fixed effect and its random effect enter additively on the
log scale. `admixr2` exploits this pairing to compute analytical gradients
via sensitivity equations. See the
[Advanced usage](https://leidenpharmacology.github.io/admixr2/articles/advanced.html#mu-referencing-and-sensitivity-equations)
vignette for details, including how parameters without a random effect are
handled.

## Assembling the study specification

Bundle each study's statistics into a named list:

```{r study}
study <- list(
  E     = E,
  V     = V,                       # full 9x9 covariance matrix
  n     = n,
  times = times,
  ev    = rxode2::et(amt = 100)    # single 100 mg oral dose
)
```

## Fitting

Pass one or more named studies to `admControl()`:

```{r fit}
fit <- nlmixr2(
  pk_model, admData(), est = "admc",
  control = admControl(
    studies   = list(examplomycin = study),
    n_sim     = 5000L,
    cov_n_sim = 10000L,
    maxeval   = 300L,
    seed      = 1L
  )
)
```

## Inspecting the fit

```{r print}
print(fit)
```

Key entries in `fit$env$admExtra`:

```{r internals}
fit$objective                    # -2 log-likelihood
fit$env$admExtra$struct          # structural parameters (log scale)
fit$env$admExtra$omega           # estimated Omega matrix
fit$env$admExtra$sigma_var       # residual variance(s)

logLik(fit)
AIC(fit)
```

## Diagnostic plots

`plot()` produces up to four panel types and returns them as a named list of
ggplot2 objects:

```{r plot, fig.cap="Left: observed vs predicted mean with residuals. Right: NLL convergence trace."}
plots <- plot(fit, which = c("mean", "nll"))
```

For a detailed walkthrough of all four panel types and customisation options, see
`vignette("diagnostic-plots", package = "admixr2")`.
