% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/sg-sim.R
\name{sg_sim}
\alias{sg_sim}
\title{Perform simulations from an rxode2 model}
\usage{
sg_sim(
  model,
  et,
  stimes = NULL,
  outputs = NULL,
  theta = NULL,
  omega = NULL,
  sigma = NULL,
  thetamat = NULL,
  covs = NULL,
  npop = 1,
  nsub = 1,
  aggr = NULL,
  addcov = TRUE,
  keep = NULL,
  scale = NULL,
  covint = "locf",
  inits = NULL,
  byID = NULL,
  byPOP = NULL,
  shared = NULL,
  ncores = 1,
  atol = 1e-08,
  rtol = 1e-06,
  ...
)
}
\arguments{
\item{model}{A model object passed to \code{sg_sim()}.}

\item{et}{An event table passed to \code{sg_sim()}.}

\item{stimes}{A numeric vector of simulation times.}

\item{outputs}{Vector of strings. Names of the model variables to output.
If \code{NULL}, all variables returned. Default is \code{NULL}.}

\item{theta}{A named numeric vector of baseline parameters. Default is \code{NULL}.
Parameters listed in \code{params} are replaced by sampled values.}

\item{omega}{A named matrix or vector.}

\item{sigma}{A named matrix representing a sigma covariance matrix or its
Cholesky decomposition; Default is \code{NULL}.}

\item{thetamat}{A named variance-covariance matrix (for parameters brought to normal distribution).
Default is \code{NULL}.}

\item{covs}{A list of covariate structures. Each element should be a list containing covariate relationship definitions with the following structure:
\itemize{
\item \code{PAR} - string, name of the parameter to which covariate effect is applied
\item \code{COVNAME} - string, name of the covariate column in the dataset
\item \code{FUNC} - string, functional form of the covariate effect
\item \code{TRANS} - string, transformation applied to covariate
\item \code{REF} - numeric, reference value for categorical covariates
\item \code{INIT} - numeric, initial value for the covariate effect parameter
\item \code{EST} - logical, whether to estimate the covariate effect
Can be \code{NULL}, if no covariates are used. Default is \code{NULL}
}}

\item{npop}{Integer. Number of population replicates. Default is 1.}

\item{nsub}{Integer. Number of subjects sampled per population (omega/sigma matrices per ID). Default is 1.}

\item{aggr}{A string that specifies the aggregation type. Set to \code{NULL} for
no aggregation, \code{ID} for aggregation by time, population and ID, \code{NPOP} for
aggregation by population and time, \code{TIME} for aggregation by time.
Default is \code{NULL}.}

\item{addcov}{Logical. If \code{TRUE}, columns with covariate values will be added
to the resulting dataset. Default is \code{TRUE}.}

\item{keep}{Vector of strings. Columns of event table to keep in the output data frame. Default is \code{NULL}.}

\item{scale}{A numeric named vector. Scaling for ODE parameters of the system.
The names must correspond to the parameter identifiers in the ODE specification.
Each of the ODE variables will be divided by the scaling factor. Default is \code{NULL}.}

\item{covint}{String. Specifies the interpolation method for time-varying
covariates. When solving ODEs it often samples times outside the sampling
time specified in event table. When this happens, the time varying
covariates are interpolated. Currently this can be:
\itemize{
\item \code{"linear"} interpolation, which interpolates the covariate by solving the
line between the observed covariates and extrapolating the new covariate value
\item \code{"locf"} last observation carried forward
\item \code{"NOCB"} next observation carried backward.
This is the same method that NONMEM uses
\item \code{"midpoint"} last observation carried forward to midpoint;
next observation carried backward to midpoint
}

Default is \code{"locf"}}

\item{inits}{A named vector specifying initial conditions for model variables; Default is \code{NULL}.}

\item{byID}{logical. If \code{TRUE}, replicate populations/subjects per event-table ID.
Default \code{NULL} is treated as \code{TRUE}.}

\item{byPOP}{logical. When both thetamat and omega are used: if \code{TRUE},
replicate subjects by population. Default \code{NULL} is treated as \code{TRUE}.}

\item{shared}{logical. If \code{TRUE},
one shared population draw for all IDs. Default \code{NULL} is treated as \code{TRUE}.}

\item{ncores}{Integer. Number of cores used for calculations. Default is 1.}

\item{atol}{A numeric absolute tolerance used by the ODE solver to determine
if a good solution has been achieved. This is also used in the solved linear
model to check if prior doses do no add anything to the solution.
Default is 1e-8.}

\item{rtol}{Numeric. A numeric relative tolerance used by the ODE solver to determine
if a good solution has been achieved. This is also used in the solved linear
model to check if prior doses do not add anything to the solution. Default is 1e-6.}

\item{...}{optional arguments passed to \code{rxode2::rxSolve} (e.g. \code{method}, \code{maxsteps}).}
}
\value{
A dataset with simulation results (long format).
}
\description{
Runs simulations using an rxode2 model object with explicit R objects for
parameters (theta), variance-covariance (thetamat), omega, and sigma.
}
\details{
Index columns \code{ID}, \code{POPN}, and \code{sim.id} are included depending on what is used:
\describe{
\item{No uncertainty, no variability}{Only \code{ID} (and \code{TIME}, \code{VAR}, \code{VALUE})}
\item{Only uncertainty (\code{thetamat})}{ \code{POPN} and \code{ID}}
\item{Only variability (\code{omega})}{\code{sim.id} and \code{ID}}
\item{Uncertainty and variability}{\code{POPN}, \code{sim.id}, and \code{ID}}
}
Other columns:
\describe{
\item{TIME}{Timepoint of the simulations}
\item{VAR}{Names of the output variables}
\item{VALUE}{Optional. Simulated value. Returned when no aggregation applied}
\item{mean, median, ...}{Optional. Aggregated statistic of simulated values. Returned when aggregation is applied}
\item{COV1, ...COVn}{Optional. Covariates value. Returned when \code{addcov} is \code{TRUE}}
\item{KEEP1, ...KEEPn}{Optional. Columns that were specified in the \code{keep} argument}
}
Event table can use either \code{id} or \code{ID}. Parameters can be fixed per ID by
including parameter names (e.g. \code{*_pop}, \code{omega_*}) as columns in the event table.
}
\examples{
\donttest{
library(rxode2)
library(dplyr)
library(tibble)
# Base 1-compartment PK model (no covariate)
mod <- rxode2::rxode2({
  ka_pop = 0.1;
  Vd_pop = 10;
  CL_pop = 0.5;

  omega_ka = 0;
  omega_Vd = 0;
  omega_CL = 0;

  Cc_b = 0;
  ka_tv = exp(ka_pop);
  Vd_tv = exp(Vd_pop);
  CL_tv = exp(CL_pop);

  ka = ka_tv * exp(omega_ka);
  Vd = Vd_tv * exp(omega_Vd);
  CL = CL_tv * exp(omega_CL);

  Cc = Ac / Vd;

  Ad(0) = 0;
  Ac(0) = 0;

  d/dt(Ad) = -ka * Ad;
  d/dt(Ac) = ka * Ad - CL * Cc;

  Cc_ResErr = Cc * (1 + Cc_b);
})

# Model with covariate: WTBL on Vd (Vd_tv = exp(Vd_pop) * (WTBL/70)^beta_WTBL_Vd_pop)

mod_cov <- rxode2::rxode2({
  ka_pop = 0.1;
  Vd_pop = 10;
  CL_pop = 0.5;

  beta_WTBL_Vd_pop = 0;

  omega_ka = 0;
  omega_Vd = 0;
  omega_CL = 0;

  Cc_b = 0;

  ka_tv = exp(ka_pop);
  Vd_tv = exp(Vd_pop) * (WTBL/70)^beta_WTBL_Vd_pop;
  CL_tv = exp(CL_pop);

  ka = ka_tv * exp(omega_ka);
  Vd = Vd_tv * exp(omega_Vd);
  CL = CL_tv * exp(omega_CL);

  Cc = Ac / Vd;

  Ad(0) = 0;
  Ac(0) = 0;

  d/dt(Ad) = -ka * Ad;
  d/dt(Ac) = ka * Ad - CL * Cc;

  Cc_ResErr = Cc * (1 + Cc_b);
})

et_test <- tibble::tribble(
  ~ID, ~TIME, ~EVID, ~CMT, ~AMT,
  1, 0, 1, 1, 10,
  2, 0, 1, 1, 50
)

stimes_test <- seq(0, 24, 0.1)
output_test <- c("Ac", "Ad", "Cc", "Cc_ResErr")
theta_test <- c(ka_pop = log(0.1), Vd_pop = log(10), CL_pop = log(0.5))

thetamat_test <- matrix(c(0.05, 0.01, 0, 0.01, 0.05, 0, 0, 0, 0.05), nrow = 3, byrow = TRUE)
rownames(thetamat_test) <- colnames(thetamat_test) <- c("ka_pop", "Vd_pop", "CL_pop")

omega_test <- matrix(c(0.2, 0.05, 0, 0.05, 0.2, 0, 0, 0, 0.2), nrow = 3, byrow = TRUE)
rownames(omega_test) <- colnames(omega_test) <- c("omega_ka", "omega_Vd", "omega_CL")

sigma_test <- matrix(0.1); rownames(sigma_test) <- colnames(sigma_test) <- "Cc_b"

# No variability
sim1 <- sg_sim(model = mod, et = et_test, stimes = stimes_test, theta = theta_test,
               outputs = output_test)

# Population uncertainty, single scenario (ID)
sim2a <- sg_sim(model = mod, et = dplyr::filter(et_test, ID == 1),
                stimes = stimes_test, theta = theta_test, thetamat = thetamat_test,
                npop = 10)

# Population uncertainty, multiple IDs, byID = TRUE (populations are replicated
# for each scenario (ID)),
# shared = TRUE (the same populations are used for each scenario (ID))
sim2b <- sg_sim(model = mod, et = et_test, stimes = stimes_test, theta = theta_test,
               thetamat = thetamat_test, npop = 10, byID = TRUE, shared = TRUE)

# Population uncertainty, multiple IDs, byID = FALSE (one solve over full event table;
# npop must equal n(ID); ID - virtual subject)
sim2c <- sg_sim(model = mod, et = et_test, stimes = stimes_test, theta = theta_test,
               thetamat = thetamat_test, npop = nrow(et_test), byID = FALSE)


# Between-subject variability (BSV), multiple IDs, byID = TRUE (subjects are
# replicated for each scenario (ID)), shared = FALSE (separate subjects per ID)
sim3a <- sg_sim(model = mod, et = et_test, stimes = stimes_test, theta = theta_test,
                omega = omega_test, nsub = 10, byID = TRUE, shared = FALSE)


# Between-subject variability (BSV), byID = FALSE (one solve over full event table;
# nsub must equal n(ID); ID - virtual subject)
sim3b <- sg_sim(model = mod, et = et_test, stimes = stimes_test, theta = theta_test,
                omega = omega_test, nsub = nrow(et_test), byID = FALSE)


# BSV + uncertainty: byID = TRUE (populations/subjects are replicated for each
# scenario (ID)), byPOP = TRUE (subjects are replicated for each population),
# shared = FALSE (separate populations/subjects per ID)
sim4a <- sg_sim(model = mod, et = et_test, stimes = stimes_test, theta = theta_test,
                thetamat = thetamat_test, npop = 10, omega = omega_test, nsub = 5,
                byID = TRUE, byPOP = TRUE, shared = FALSE)

# BSV + uncertainty: byID = TRUE (populations/subjects are replicated for each
# scenario (ID)), byPOP = FALSE (subjects are not replicated between population;
# npop = nsub)
sim4b <- sg_sim(model = mod, et = et_test, stimes = stimes_test, theta = theta_test,
                thetamat = thetamat_test, npop = nrow(et_test), omega = omega_test,
                nsub = nrow(et_test), byID = TRUE, byPOP = FALSE)

# BSV + uncertainty: byID = FALSE (one solve over full event table; nsub and/or
# npop must equal n(ID); ID - virtual subject), byPOP = TRUE (subjects are
# replicated for each population), shared = FALSE (separate populations/subjects
# per ID)
sim4c <- sg_sim(model = mod, et = et_test, stimes = stimes_test, theta = theta_test,
                thetamat = thetamat_test, npop = 10, omega = omega_test, nsub = 5,
                byID = FALSE, byPOP = TRUE, shared = FALSE)

# BSV + uncertainty: byID = FALSE (one solve over full event table; nsub and/or
# npop must equal n(ID); ID - virtual subject), byPOP = FALSE (subjects are not
# replicated between population; npop = nsub)
sim4d <- sg_sim(model = mod, et = et_test, stimes = stimes_test, theta = theta_test,
                thetamat = thetamat_test, npop = nrow(et_test), omega = omega_test,
                nsub = nrow(et_test), byID = FALSE, byPOP = FALSE)

# Parameter override in event table
sim4 <- sg_sim(model = mod, et = dplyr::filter(et_test, ID == 1) \%>\%
                                 dplyr::mutate(Vd_pop = 2),
               stimes = stimes_test, theta = theta_test, thetamat = thetamat_test,
               npop = 1)


# Covariate (WTBL): pass covs and keep so WTBL is used and returned
theta_cov <- c(theta_test, beta_WTBL_Vd_pop = 0.5)
sim5 <- sg_sim(model = mod_cov, et = dplyr::filter(et_test, ID == 1) \%>\%
                                     dplyr::mutate(WTBL = 70),
               stimes = stimes_test, theta = theta_cov, covs = c("WTBL"),
               keep = c("WTBL"),
               thetamat = thetamat_test, npop = 5)
}
}
