rxode2 provides a
small event bus: packages that finish a top-level piece of work announce
it with rxode2::rxEventEmit(), and any package can listen
with rxode2::rxEventListen(). The main consumer is
nlmixr2log (in development), which records fits,
simulations and their results, but you can write your own listener. See
?rxode2::rxEventListen for the full API.
Two rules of the bus matter here:
nlmixr2plot checks that the bus exists before using it, so
with an older rxode2 nothing changes.This vignette describes what nlmixr2plot itself
emits.
nlmixr2plot emits a single event,
fitResult, when one of these functions returns
successfully:
| Function | kind |
fit |
data |
|---|---|---|---|
plot() of a fit
(plot.nlmixr2FitData()) |
"plot" |
the fit | NULL |
vpcPlot() |
"vpcPlot" |
the fit (see below) | NULL |
plot() of an augPred() object
(plot.nlmixr2AugPred()) |
"augPredPlot" |
NULL |
the augPred() data |
The fitResult payload fields are:
| Field | Contents |
|---|---|
fit |
The fit the plots belong to, or NULL for
plot(augPred(...)). |
result |
The value the function returns: the ggtibble::gglist of
plots from plot(fit) or plot(augPred(...)), or
the ggplot from vpcPlot() (the vpc database
with vpcdb = TRUE). |
kind |
"plot", "vpcPlot" or
"augPredPlot". |
call |
The call, normalized by rxode2 so its head is the
kind (e.g. plot(fit),
vpcPlot(fit, n = 5) or augPredPlot(ap)) and
large inlined values are replaced by markers. |
data |
For "augPredPlot" only, the augPred() data
that was plotted; otherwise NULL. |
Details:
vpcPlot() and supplied simulations.
When vpcPlot() is given a vpcSim() result
instead of a fit, the fit field is the fit that simulation
came from, not the simulation.plot(augPred(...)) has no fit. An
augPred() object does not carry its fit, so
fit is NULL and the plotted data is sent as
data; a logger such as nlmixr2log uses it to
find the run it belongs to.NULL, no event is emitted.Everything that happens inside these functions is silent:
vpcPlot() runs (through
nlmixr2est::vpcSim() and rxode2::rxSolve())
emits no solveComplete.traceplot() inside
plot(fit), emit no events of their own.rxode2::rxEventScope())
emits nothing; only the outermost operation reports.Other events you may see around plotting come from other packages:
nlmixr2est emits fitComplete when
nlmixr2() finishes a fit and solveComplete
from augPred(), simulate(),
predict() and vpcSim() called at the top
level. Those require an nlmixr2est with event hooks;
nlmixr2plot does not emit them.
A listener is a function function(event, ...); the
payload fields arrive as named arguments. Here is a small listener that
records what it sees. First fit a small model:
library(nlmixr2plot)
library(nlmixr2est)
#> Loading required package: nlmixr2data
one.cmt <- function() {
ini({
tka <- log(1.57); tcl <- log(2.72); tv <- log(31.5)
eta.ka ~ 0.6; eta.cl ~ 0.3; eta.v ~ 0.1
add.sd <- 0.7
})
model({
ka <- exp(tka + eta.ka)
cl <- exp(tcl + eta.cl)
v <- exp(tv + eta.v)
linCmt() ~ add(add.sd)
})
}
fit <- suppressMessages(
nlmixr2(one.cmt, nlmixr2data::theo_sd, est = "posthoc",
control = list(print = 0))
)Then register a listener and make some plots:
seen <- list()
rxode2::rxEventListen("demo", function(event, ...) {
p <- list(...)
seen[[length(seen) + 1L]] <<- data.frame(
event = event,
kind = if (is.null(p$kind)) NA_character_ else p$kind,
hasFit = !is.null(p$fit),
resultClass = class(p$result)[1],
call = paste(deparse(p$call), collapse = " ")
)
})
p <- plot(fit)
v <- suppressMessages(suppressWarnings(vpcPlot(fit, n = 50)))
ap <- suppressMessages(augPred(fit))
a <- plot(ap)
rxode2::rxEventUnlisten("demo")
do.call(rbind, seen)
#> event kind hasFit resultClass call
#> 1 fitResult plot TRUE gglist plot(fit)
#> 2 fitResult vpcPlot TRUE ggplot2::ggplot vpcPlot(fit, n = 50)
#> 3 solveComplete augPred FALSE nlmixr2AugPred augPred(fit)
#> 4 fitResult augPredPlot FALSE gglist augPredPlot(ap)plot(fit) and vpcPlot() each report one
fitResult, and the simulation inside vpcPlot()
stays silent. plot(ap) reports a fitResult
with no fit. With an nlmixr2est that has event hooks, the
top-level augPred() call also reports a
solveComplete (emitted by nlmixr2est).
After rxEventUnlisten(), plotting reports nothing:
For a complete record of fits, simulations, updates and the plots
made from them, use nlmixr2log (in development), which
listens to all of these events (including fitResult from
nlmixr2plot) and stores the plots with the run they belong
to.