Requires simPDF 0.1.2. Report generation could stop with “attempt to apply non-function” when a block's height equalled the space left on the page to within floating-point error; that was a defect in simPDF 0.1.1, fixed in 0.1.2, and the report writer now relies on the fix instead of working around it.
The eight diagnostic report functions and nmw_run() gain a
format argument: "pdf" (default), "md", or
c("pdf", "md"). With "md" the report is written as a
Markdown file (the file name with its extension replaced by
‘.md’): headings, text, preformatted dumps and tables become
GitHub-flavoured Markdown, and every figure page or inline plot is saved
as an SVG file (or PNG with fig_format = "png") in a sibling
‘<name>_files’ directory and linked from the Markdown. The
directory is emptied before each run.
Outline() gains Target = "md": the model development
flow diagram is written as a Markdown file (file, default
‘<MDLName>-Model-Flow.md’) with the diagram as an SVG (or PNG,
fig_format) figure followed by the table of runs from
SumOut(). The figure is sized to the tree (about 1.6 in per leaf
column), so folders with dozens of sibling runs stay legible. The
default Target = "PDF" still draws on the graphics device opened
by the caller, as before; when no device is open (e.g. under
Rscript) it now writes a PDF sized to the tree instead of
failing. SumOut() no
longer aborts on a run folder it cannot summarise (e.g. the empty
‘.ext’ of a simulation run, or a corrupt output file): the run is
listed with Reason = "NOESTIMATION" or "UNREADABLE" and
a warning names it, and GetEstMethod() returns NA for an
empty ‘.ext’.
The report functions now describe their content with a small internal block layer (‘R/report_writer.R’) that is rendered to simPDF for the PDF and to Markdown for the ‘.md’. The statistics and the PDF layout are unchanged.
Fixed: headings of blocks that nmw_report_resid() and
nmw_report_ebe() build in loops showed the last loop value in the
PDF, because simPDF::block_para() evaluates its text lazily. In
0.5.x all three residual-count sections of ‘S4-Residuals.PDF’ were
titled "IWRES" and all extreme-value tables "Extreme IWRES values", and
in ‘S5-EBE.PDF’ every matrix in "Estimation vs EBE" was titled
"Ratios of Cor(EBE)/(Cor from OM)" and every ETA section "ETA <last>".
The new block layer evaluates text when the block is built.
Fixed: nmw_report_indipk() drew its "Individual PK
Parameters" heading and the first rows of the table onto the last figure
page, where they were invisible, and only the overflow rows reached a
fresh page. Flowing text that follows figure pages now always starts on
a new page. The report also gained a title page ("Summary C -
Individual PK Parameters"), like ‘S3-Predictions.PDF’.
nmw_report_ebe() drops continuous covariates whose
per-subject values are all equal (for example nominal time, day or
occasion counters that start at the same value for every subject) from
the covariate/EBE correlation matrix, the regressions and the
ETA-vs-covariate panels. They produced all-NA rows and columns
and flat panels.
nmw_report_param() recognises runs without a successful
$COV step (no <nm:thetase> in the XML): SE, LL, UL, ZERO
and ONE are reported as NA with an explanatory note, fixed thetas
are identified from the ‘.ext’ fixed-parameter row, and the Omega
SE/RSE matrices are replaced by a note. Previously such runs showed
SE = 0 for every theta and RSE of about 1e+12 for every omega. With a
$COV step, fixed or structurally zero Omega elements are now shown
as NA in the SE and RSE matrices instead of 1e+10 and Inf.
nmw_report_ebe() shows NA instead of +/-Inf in the
"Ratios of Cov(EBE)/OM" and "Ratios of Cor(EBE)/(Cor from OM)" matrices
where the Omega element is zero, and in the individual RSE column where
an ETA is exactly zero (e.g. an inter-occasion ETA of an absent
occasion).
Robustness fixes found by regenerating the reports for several
hundred real runs: the ETA distribution panels no longer fail when an
ETA has fewer than two non-zero values (e.g. an inter-occasion ETA in a
single-occasion sensitivity run) or is constant; the pairs-plot panels
restore par("usr") correctly (they emitted "argument 1 does not
name a graphical parameter" on every S5 report); TAB characters in
preformatted text (e.g. the summary.lm R-squared line) are
expanded to spaces instead of triggering "font width unknown" warnings;
and large matrices or tables are no longer forced onto one page with
their heading, which overflowed the page for models with many ETAs and
covariates.
Data sets of $PRED models that lack MDV and/or
AMT (for example the bundled theophylline examples) no longer
make S1, S3, S4, S5 and SA fail with "undefined columns selected" or
"subscript out of bounds": the missing items are added with NONMEM's
implicit values (AMT = 0; MDV = 1 for dosing records,
otherwise 0), an sdtab without MDV or CMT takes
them from the record-aligned data set, and SA-Input notes which items
were assumed and skips the
"Individuals with no dosing" check when the data set has no AMT.
ETAs that are zero for every subject are omitted from the covariate/EBE
correlation matrix with a note instead of producing all-NA rows.
The EBE regression no longer fails when there is exactly one covariate
(RemoveNA() now keeps a one-column input as a data frame and
accepts plain vectors).
nmw_report_ebe() writes a short report stating that no
empirical Bayes estimates are available when all ETAs in the ‘.phi’
file are zero (First Order estimation) and ‘patab’ is missing or
also all zero, instead of failing.
Text that is not valid UTF-8, such as control-stream comments in a
legacy code page that NONMEM echoes into ‘PRINT.OUT’, no longer
crashes R when drawn on the PDF device: it is converted from the code
page in getOption("nmw.codepage") (default "CP949") when
that yields valid text, otherwise the offending bytes are shown as
<xx>.
IPRE is optional in ‘sdtab’ (e.g. a PD model without
IPRED in $TABLE): S3-Predictions omits the IPRE panels and
curves with a note, and S4-Residuals plots CWRES and IWRES against PRED.
IPRED, IWRES and CWRESI are accepted for
IPRE, IWRE and CWRES. The influence-diagnostic
panels of S5-EBE skip non-finite values instead of failing on
ylim. A malformed table file (e.g. one containing merge-conflict
markers) is reported by name.
Worked around a simPDF (<= 0.1.1) edge case in which a block whose height equals the remaining page space up to floating-point error made the flow fail with "attempt to apply non-function" after the block had been drawn; the report writer now places blocks one at a time and continues.
Missing run files now give a clear error naming the file, the run directory and the report that needs it (e.g. ‘patab’ for SC-IndiPK, ‘sdtab’ for S3/S4/S5, ‘FDATA.CSV’ for the data-based reports) instead of "cannot open the connection". ‘FDATA.csv’ is accepted as well as ‘FDATA.CSV’ on case-sensitive file systems.
nmw_report_pred() and nmw_report_indipk() no longer
open a graphics device (‘Rplots.pdf’ under Rscript) when
none is open: the caller's par() state is saved and restored only
if a device exists.
Tables of individuals always carry an explicit ID column:
the "Individual Statistics", "Individuals with no dosing" and
"Individuals with no DV" tables of SA-Input (previously the ID was the
row name, which was dropped when the IDs were 1..n), the "Variable
Statistics" table gains a Variable column, and SC-IndiPK takes
the subject IDs from the record-aligned data set when ‘patab’ was
written without ID.
The invisible return value of every report function now also
contains md_file and figures; file and pages
are NA when no PDF was requested.
nmw_report_resid() now omits unavailable residual diagnostics
cleanly when sdtab lacks WRES, CWRES, or
IWRE, or when such a column contains no finite values. Binomial
tests, extreme-value tables, distribution plots, and subject plots are
generated only for usable residuals; missing panels contain an
explanatory placeholder rather than failing on non-finite plot limits.
Diagnostic report functions now document their invisible summary
return values. The model argument documentation for
nmw_report_output() and nmw_report_indipk() now states that
it is accepted only for a uniform report API because those reports read
the fixed files ‘PRINT.OUT’ and ‘patab’.
The minimum simPDF version is now 0.1.1, the first CRAN release, and the minimum R version is aligned with simPDF at 3.6.0.
Regression tests now exercise PDF generation and the missing
IWRE case using the bundled NONMEM example.
The eight diagnostic report functions (nmw_report_ofv,
nmw_report_param, nmw_report_pred, nmw_report_resid,
nmw_report_ebe, nmw_report_input, nmw_report_output,
nmw_report_indipk) are re-implemented on the simPDF report
engine (now in Imports). The statistics/parsing is unchanged; the
former dead-reckoned pdf() + PrinTxt/split.screen
layout is replaced by a measured flowing layout, which eliminates the
text/matrix overlap that appeared in S2-Parameters.PDF for models
with many random effects (validated overlap-free across hundreds of real
runs, up to 14 ETAs). Each report gained file and
model arguments (backward compatible).
nmw_report_pred no longer errors on subjects/compartments with
no observation records (the "zero-length labels" crash); nmw_report_resid
tolerates an sdtab that is missing a residual column (e.g. IWRE).
The low-level layout helpers PrepPDF, PrinTxt,
AddPage, PrinMTxt and ClosePDF are removed (superseded
by simPDF); DxPlotPost is retained.
New function ctl2nmw(): reads a closed-form $PRED NONMEM
control stream and auto-generates the PRED function (with its
deriv() companions) and the initial estimates
(THETAinit, OMinit, SGinit, LB, UB,
METHOD) needed by InitStep(). This removes the main
inconvenience of the package: hand-writing the PRED function. The
generated PRED reproduces the hand-written example PRED
numerically (verified to floating-point tolerance for FO,
FOCE-INTER and Laplace on the bundled THEO control streams).
The generator classifies free symbols over both the structural model
F and the error model Y, so a THETA or data item that
appears only in the residual error (e.g. a combined
additive-plus-proportional W term) is wired into H correctly.
Random-effect subscripts are ordered numerically (so ETA10 follows
ETA9), and $PRED ETA/EPS indices are
cross-checked against $OMEGA/$SIGMA.
Out-of-scope control streams fail with an informative message rather
than generating incorrect code: ODE models
($PK/$DES/$SUBROUTINE/ADVAN),
IF/THEN branching, MU-referencing, mixtures, unsupported
estimation methods, and FIXed parameters. Assigning the same
symbol more than once in $PRED (sequential reassignment) or
referencing a symbol before it is defined is likewise rejected, as is a
$THETA initial estimate on or outside its bounds
(InitStep() scaling needs LB < init < UB). A diagonal
$OMEGA is promoted to a full block, a non-diagonal $SIGMA
is reduced to its diagonal, and an unbounded $THETA with a
non-positive initial estimate gets LB = -1e6 instead of the usual
default 0, each with a note.
The environment e is exported again. It had been exported up
to 0.1.6 via exportPattern() and was inadvertently dropped in
0.2.0's switch to explicit exports. Without it, a user-written
PRED function referencing e$METHOD – the documented
workflow, and also the code that ctl2nmw() generates – stopped
with “object 'e' not found” when EstStep() ran it, and
reading results with get("EBE", envir=e) failed likewise.
Internal refactoring (prepared as an unreleased 0.3.2) is included
in this release. It changes no other public API and no numerical
result of the estimation steps
(FO, FOCE-INTER, Laplace) or of any diagnostic
report; verified by comparing the estimation output and all eight report
PDFs against the pre-refactor sources on the bundled example run.
De-duplication: the covariate-classification block repeated three
times inside report_ebe is now the internal helper
ClassifyCovariates(); the shared record-count extraction is
GetNRecFromXML(); NMVarStat() reuses the
AllNA()/AllSame() helpers.
Bug fix: the “Sigmas” section of nmw_report_param
(S2-Parameters) no longer errors for models with two or more
SIGMA elements (e.g. a combined additive-plus-proportional error
model); a test that mixed && and & produced a condition of
length greater than one.
Bug fix: PanelCor() no longer errors when an explicit
cex.cor value is supplied (an undefined cex was referenced).
InitStep(): the documented LB/UB defaults
(0 and 1e6) are now applied before they are used, so
omitting these arguments works as documented instead of raising an error.
Passing LB/UB explicitly behaves exactly as before.
Loop bounds in the data-handling utilities (AddDoNoTaLD,
ExpandDoseHist, RemoveNA, RmvFixed, RmvZero,
RenCol) and in the shared report helpers now use
seq_len()/seq_along() so they no longer misbehave on
zero-row input.
Housekeeping: removed leftover working files and dead commented code
from R/, replaced T/F literals with
TRUE/FALSE, corrected user-visible typos in report titles
and labels (“Individiual”, “Estitmate”, “Recods”),
and corrected the TrimOut() return-value documentation.
SumOut() bug fix: the line RunFolders <- MatchEnd(Folders, RunExt) previously assigned the logical vector returned by MatchEnd() to RunFolders instead of using it as a mask to subset Folders. This caused strsplit() inside GetModelNames() to fail with "non-character argument" whenever any run folders were present. Now RunFolders <- Folders[MatchEnd(Folders, RunExt)].
SumOut() default RunExt changed from ".R75" to ".R76" to match NONMEM 7.6 (the current production release). Users on NONMEM 7.5 should pass RunExt = ".R75" explicitly.
SumOut() now warns and returns invisible(NULL) when no matching run folders are found, instead of erroring on a zero-length loop.
GetProbVal() bug fix: grep(Tag, PROB) returns integer(0) when the requested tag (e.g. "P:" or "F:") is absent – for example when the $PROB record is longer than 80 characters and NM-TRAN truncates it inside the FCON file, dropping the tag. The previous if (Loc > 0) test raised "argument is of length zero". The test was changed to if (length(Loc) > 0 && Loc[1] > 0), returning an empty string when the tag is absent.
man/SumOut.Rd updated to reflect the new default RunExt and a richer description of the return value.
MatchEnd() bug fix: replaced for (i in 1:n) with for (i in seq_len(n)) so that calling on an empty character vector no longer iterates over c(1, 0) and tries to read NA elements.
Regression tests added in tests/testthat/test-utils_data.R covering the SumOut() empty-folder, GetProbVal() missing-tag, and MatchEnd() empty-input cases.
report_ebe() (S5 “ETA vs Categorical Variables”) bug fix: when the number of ETAs times the number of categorical covariates produced a panel grid too dense for boxplot margins, plot.new() raised “figure margins too large” and the PDF was truncated mid-page. The categorical-covariate panels are now split across multiple PDF pages (cap of ~35 panels per page, configurable through the internal MAX_CELLS_PER_PAGE constant), with page numbers appended to the panel title when more than one page is produced.
General-purpose helpers for NONMEM dataset construction added (build_nm_dataset, build_dose_records, build_obs_records).
Time-varying covariate merge by LOCF/LOCB: locf_value, merge_cov_locf.
Datetime parsers: parse_dtc, dat2_time_to_posix.
Coding helpers: code_sex, code_race.
Cockcroft-Gault CRCL: crcl_cg, add_crcl_cg.
Mass to molar unit conversion: nm_to_molar.
Post-run processing of NONMEM output with PDF diagnostic reports merged from nma package.
8 report types: OFV, Parameters, Predictions, Residuals, EBE, Input, Output, IndiPK.
New utility functions for NONMEM data processing and parsing.
Switched from exportPattern to explicit exports in NAMESPACE.
Typos in documentation corrected.
AddCox function for adding a covariate to existing NONMEM dataset.
CombDmExPc function for combining demographics(DM), dosing(EX), and DV(PC) tables.
TrimOut function to beautify the original NONMEM OUTPUT
Errata in manual corrected.
Errata in manual corrected.
TabStep() is added.
Speed is increased.
References are updated.
Vignette is updated.
This package will be used at the workshop on 2017-10-25 at Kyoto Japan 1st APC satellite workshop.
Bug at calculating objective function value for "LAPL" method is fixed.
Bug at scaling other than zero lower bound transformation fixed.
This package will be used at the workshop within US FDA on 2017-03-21.
For the initialization step, Pred function name should be given by the user. It does not read directly from the file any more.
This package was born and used at the Workshop held by Kyun-Seop Bae MD PhD <[email protected]>.
InitStep used Pred function within a file.