One of the features of Emacs Speaks NONMEM is the automatic generation of
certain pieces of code that may be useful for analysis, such as
conditional weighted residuals, splitting up control streams to bypass the 20
(<NONMEM 6.2) or 50 variable PRED
generated output variable limitation of
NONMEM, and automatically generating code secondary parameters. Some of the
code is specific to the NONMEM version that is used. For this reason a
discussion of how Emacs Speaks NONMEM determines the version is included.
Conditional Weighted Residuals
Conditional Weighted Residuals were proposed for NONMEM by Andrew Hooker. Instructions on what to do to generate the appropriate piece of code are found in Xpose's website. Emacs Speaks NONMEM helps with the generation by allowing
- Appropriate Code to be generated depending on the version of NONMEM selected
- Code to be reflective of the estimation method using. Currently, the default
method where conditional weighted residuals are generated is the first order
conditional estimation method. Other methods may be specified through the
menu:
- Automation
- Options
- Automation
If you plan to use Perl Speaks NONMEM, you will need to select
- Automation
- Options
- PsN compatibility — Use ../../ for .est files
- Options
This allows the .est
files required for the calculation of conditional weighted
residuals to reside in the same directory as the rest of the files and the
control stream.
Large Tables
When there are over 20 PRED
generated variables (or 50 in NONMEM VI.2 or
greater), NONMEM can not output the variables using one control stream. One
solution is to output the model specification, and use the same model to output
the missing variables. Last the variables should be merged together. Emacs
Speaks NONMEM can do this automatically when you save, and open as if there were
no limit to the number of variables that can be output. When there are more
variables output than can be interpreted by NONMEM, Emacs Speaks NONMEM modifies
and splits the files as follows:
- The open control stream is stripped of variables over the 20/50
PRED
generated variable limit, and places comments at the end of the control stream that allows NONMEM to know about these variables and open the base control stream as if this translation did not occur. - Change the table names in this file to have a trailing
~0
in the file name. For example a table output ofpatab1
would be changed topatab1~0
- Create the appropriate number of control streams that read in the model
specification file and output variables that are missing from
patab1~0
. For example,- For the first new control stream,
run1.mod
, create a new control streamrun1~1.mod
that outputs tables where the variables are missing from the table specified inrun1.mod
. For a tablepatab1
, this control stream would outputpatab1~1
. - More control stream and table information are created if
necessary. (i.e.
run1~2.mod
,patab1~2
,run1~3.mod
,patab1~3
, etc. - To produce the final table, you will need to:
- Run the first control stream
run1.mod
. Once this has been completed, run all subsequent control streamsrun1~2.mod
,run1~3.mod
, etc. - Merge the output datasets together to the final tables.
- Run the first control stream
- For the first new control stream,
Note that you will have to create a script to paste the tables together line-by-line. An example of this using Xpose and R, is as follows:
xpose.merge <- function(runno,tab.suffix="", table.names=c("sdtab", "mutab", "patab", "catab", "cotab", "mytab", "extra", "xptab", "cwtab"), cwres.name=c("cwtab")) { tab.files <- sapply(paste(table.names, runno, tab.suffix,"~*",sep = ""),Sys.glob); for (i in 1:length(tab.files)){ merged.file <- NULL; out.file.times <- c(); if (length(tab.files[[i]]) >= 1){ for (file in tab.files[[i]]){ out.file.times <- c(out.file.times,file.info(file)$mtime); con <- file(file,"r"); cont <- readLines(con); close(con); if (is.null(merged.file)){ merged.file <- cont; } else { cont[1] <- ""; merged.file <- paste(merged.file,cont); } } write.file <- TRUE; file <- gsub("~[0-9]+$","",tab.files[[i]][1]); if (file.exists(file)){ file.time <- file.info(file)$mtime; if (all(file.time > out.file.times)){ cat("Not writing ",file," since it is newer than the files ",file,"~*.\n",sep=""); write.file <- FALSE; } } if (write.file){ merged.file <- paste(merged.file,collapse="\n"); write(merged.file,file); } } } }
After loading this function, the tables can be merged with xpose.merge(1)
.
This automatic splitting and reassembling can be toggled by:
- NONMEM
- Automatically...
- Generate Code
- Create multiple control streams to output more generated variables than NONMEM can handle
- Generate Code
- Automatically...
Secondary Parameters Output
Another option that Emacs Speaks NONMEM allows is the generation of secondary parameters for specific PK ADVAN/TRANS combinations. This creates a section of code that generates useful secondary parameters such as half-life when Emacs Speaks NONMEM can determine that the parameter calculation applies.
For example, in a one-compartment model, Emacs Speaks NONMEM adds the following parameters:
$PROBLEM test $SUBROUTINES ADVAN1 TRANS2 $PK CL = THETA(1)*DEXP(ETA(1)) V = THETA(2)*DEXP(ETA(2)) ;| Begin Secondary Parameters IF (AMT.GT.0) THEN ;; Fixed Amount Variable DOSE = AMT ;; Time After Dose Calculation TDOS = TIME TAD = 0.0 ENDIF IF(AMT.EQ.0) THEN TAD = TIME - TDOS ENDIF K = CL/V HLK = -DLOG(0.5)/K AUC = DOSE/CL CMAX = DOSE/V AUMB = DOSE/(CL*KA) VSS = CL*MRT ;| End Secondary Parameters
The code between ;| Begin Secondary Parameters
and ;| End Secondary Parameters
will be auto-generated based on the ADVAN/TRANS combination that is used. This
option may be toggled at:
- NONMEM
- Automatically...
- Generate Code
- On save, generate derived paramters like duration, AUC, etc., when known.
- Generate Code
- Automatically...
Determining NONMEM version
Emacs Speaks NONMEM determines the NONMEM version in the following way:
- The version of NONMEM is specified within the header (must be prompted for, and setup appropriately; see Configure header).
- If Emacs Speaks NONMEM cannot determine the version it assumes the version specified in the Use menu.