Skip to content

Commit

Permalink
skpr v1.6.3: Fix augmented designs not matching factor and character …
Browse files Browse the repository at this point in the history
…columns from candidate set

-Add `plot` argument to `plot_correlations()`
-Ensure errors are removed from parallel output
  • Loading branch information
tylermorganwall committed Feb 20, 2024
1 parent 0d9c24d commit 904a5b0
Show file tree
Hide file tree
Showing 11 changed files with 36 additions and 18 deletions.
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: skpr
Title: Design of Experiments Suite: Generate and Evaluate Optimal Designs
Date: 2024-02-06
Version: 1.6.2
Date: 2024-02-20
Version: 1.6.3
Authors@R: c(person("Tyler", "Morgan-Wall", email = "tylermw@gmail.com", role = c("aut", "cre")),
person("George", "Khoury", email = "george.m.khoury@gmail.com", role = c("aut")))
Description: Generates and evaluates D, I, A, Alias, E, T, and G optimal designs. Supports generation and evaluation of blocked and split/split-split/.../N-split plot designs. Includes parametric and Monte Carlo power evaluation functions, and supports calculating power for censored responses. Provides a framework to evaluate power using functions provided in other packages or written by the user. Includes a Shiny graphical user interface that displays the underlying code used to create and evaluate the design to improve ease-of-use and make analyses more reproducible. For details, see Morgan-Wall et al. (2021) <doi:10.18637/jss.v099.i01>.
Expand Down
1 change: 1 addition & 0 deletions R/eval_design_custom_mc.R
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ eval_design_custom_mc = function(design, model = NULL, alpha = 0.05,
run_search = function(iterations) {
prog = progressr::progressor(steps = nsim)
foreach::foreach(i = iterations,
.errorhandling = "remove",
.options.future = list(packages = parallel_pkgs,
globals = c("extractPvalues", "pvalfunction",
"parameter_names", "progress", "progressbarupdates",
Expand Down
1 change: 1 addition & 0 deletions R/eval_design_mc.R
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ eval_design_mc = function(design, model = NULL, alpha = 0.05,
run_search = function(iterations, is_shiny) {
prog = progressr::progressor(steps = nsim)
foreach::foreach (j = seq_along(iterations), .combine = "rbind",
.errorhandling = "remove",
.options.future = list(packages = packagelist,
globals = c("extractPvalues", "effectpowermc", "RunMatrixReduced", "is_shiny", "blocking",
"responses", "contrastslist", "model_formula", "glmfamily", "glmfamilyname", "calceffect",
Expand Down
1 change: 1 addition & 0 deletions R/eval_design_survival_mc.R
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ eval_design_survival_mc = function(design, model = NULL, alpha = 0.05,
run_search = function(iterations, is_shiny, surv_args) {
prog = progressr::progressor(steps = nsim)
foreach::foreach(i = iterations,
.errorhandling = "remove",
.options.future = list(packages = "survival",
globals = c("extractPvalues", "rfunctionsurv", "parameter_names", "progress", "progressbarupdates",
"model", "distribution", "RunMatrixReduced", "ModelMatrix", "anticoef" ,"nc", "prog",
Expand Down
29 changes: 20 additions & 9 deletions R/gen_design.R
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,15 @@ gen_design = function(candidateset, model, trials,
"' don't match candidate set '",paste0(cand_coltype[aug_coltype != cand_coltype],collapse=", "),
"'--attempting to covert columns to that of the candidate set")
for(i in seq_len(ncol(augmentdesign))) {
augmentdesign[,i] = methods::as(augmentdesign[,i],cand_coltype[i])
if(cand_coltype[i] == "factor") {
candsetlevels = levels(candidateset[,i])
augmentlevels = unique(augmentdesign[,i, drop = TRUE])
augmentlevels_unique = augmentlevels[!augmentlevels %in% candsetlevels]
candsetlevels_all = c(candsetlevels,augmentlevels_unique)
augmentdesign[,i] = factor(augmentdesign[,i, drop = TRUE],levels=candsetlevels_all)
} else {
augmentdesign[,i] = methods::as(augmentdesign[,i, drop = TRUE],cand_coltype[i])
}
}
}
if (nrow(augmentdesign) >= trials) {
Expand Down Expand Up @@ -944,6 +952,7 @@ gen_design = function(candidateset, model, trials,
run_search = function(iterations, is_shiny) {
prog = progressr::progressor(steps = repeats)
foreach::foreach(i = iterations,
.errorhandling = "remove",
.options.future = list(globals = c("genOptimalDesign","genBlockedOptimalDesign", "candidatesetmm", "trials",
"initialreplace", "augmentdesign", "augmentedrows", "augmentdesignmm",
"progress", "is_shiny", "progressbarupdates", "repeats", "num_updates",
Expand Down Expand Up @@ -1059,13 +1068,15 @@ gen_design = function(candidateset, model, trials,
nc = future::nbrOfWorkers()
run_search = function(iterations, is_shiny) {
prog = progressr::progressor(steps = repeats)
foreach::foreach(i = iterations, .options.future = list(globals = c("genSplitPlotOptimalDesign", "candidatesetmm", "trials", "candidateset",
"initialreplace", "blockedmm", "interactionlist", "disallowedcomb",
"anydisallowed",
"progress", "is_shiny", "progressbarupdates", "repeats", "num_updates",
"initialdesign", "optimality", "mm", "aliasmm", "blockedmodelmatrix",
"minDopt", "tolerance", "kexchange" ,"V" ,"prog" ,"nc"),
seed = TRUE)) %dofuture% {
foreach::foreach(i = iterations,
.errorhandling = "remove",
.options.future = list(globals = c("genSplitPlotOptimalDesign", "candidatesetmm", "trials", "candidateset",
"initialreplace", "blockedmm", "interactionlist", "disallowedcomb",
"anydisallowed",
"progress", "is_shiny", "progressbarupdates", "repeats", "num_updates",
"initialdesign", "optimality", "mm", "aliasmm", "blockedmodelmatrix",
"minDopt", "tolerance", "kexchange" ,"V" ,"prog" ,"nc"),
seed = TRUE)) %dofuture% {
if(progress || is_shiny) {
if(is_shiny && i %in% progressbarupdates) {
prog(sprintf(" (%i workers) ", nc), amount = repeats/num_updates)
Expand All @@ -1092,7 +1103,7 @@ gen_design = function(candidateset, model, trials,
criteria = list()
designcounter = 1

for (i in seq_len(repeats)) {
for (i in seq_len(length(genOutput))) {
if (!is.na(genOutput[[i]]["criterion"])) {
designs[designcounter] = genOutput[[i]]["modelmatrix"]
rowindicies[designcounter] = genOutput[[i]]["indices"]
Expand Down
6 changes: 5 additions & 1 deletion R/plot_correlations.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#'@param custompar Default NULL. Custom parameters to pass to the `par` function for base R plotting.
#'@param standardize Default `TRUE`. Whether to standardize (scale to -1 and 1 and center) the continuous numeric columns. Not
#'standardizing the numeric columns can increase multi-collinearity (predictors that are correlated with other predictors in the model).
#'@param plot Default `TRUE`. If `FALSE`, this will return the correlation matrix.
#'@return Silently returns the correlation matrix with the proper row and column names.
#'@import graphics grDevices
#'@export
Expand All @@ -34,7 +35,7 @@
#'plot_correlations(cardesign, customcolors = c("blue", "grey", "red"))
#'plot_correlations(cardesign, customcolors = c("blue", "green", "yellow", "orange", "red"))
plot_correlations = function(genoutput, model = NULL, customcolors = NULL, pow = 2, custompar = NULL,
standardize = TRUE) {
standardize = TRUE, plot = TRUE) {
#Remove skpr-generated REML blocking indicators if present
if (!is.null(attr(genoutput, "splitanalyzable"))) {
if (attr(genoutput, "splitanalyzable")) {
Expand Down Expand Up @@ -107,6 +108,9 @@ plot_correlations = function(genoutput, model = NULL, customcolors = NULL, pow =
mm = model.matrix(model, genoutput, contrasts.arg = contrastlist)
#Generate pseudo inverse as it's likely the model matrix will be singular with extra terms
cormat = abs(cov2cor(getPseudoInverse(t(mm) %*% solve(V) %*% mm))[-1, -1])
if(!plot) {
return(cormat)
}

if (is.null(customcolors)) {
imagecolors = viridis::viridis(101)
Expand Down
4 changes: 2 additions & 2 deletions src/genOptimalDesign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ List genOptimalDesign(Eigen::MatrixXd initialdesign, const Eigen::MatrixXd& cand
Eigen::MatrixXd test(initialdesign.cols(), initialdesign.cols());
test.setZero();
if(nTrials < candidatelist.cols()) {
throw std::runtime_error("skpr: Too few runs to generate initial non-singular matrix: increase the number of runs or decrease the number of parameters in the matrix");
Rcpp::stop("skpr: Too few runs to generate initial non-singular matrix: increase the number of runs or decrease the number of parameters in the matrix");
}
//Check for singularity from a column perfectly correlating with the intercept.
for(int j = 1; j < candidatelist.cols(); j++) {
if(candidatelist.col(0).cwiseEqual(candidatelist.col(j)).all()) {
throw std::runtime_error("skpr: Singular model matrix from factor aliased into intercept, revise model");
Rcpp::stop("skpr: Singular model matrix from factor aliased into intercept, revise model");
}
}
Eigen::VectorXi shuffledindices;
Expand Down
4 changes: 2 additions & 2 deletions src/genSplitPlotOptimalDesign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ List genSplitPlotOptimalDesign(Eigen::MatrixXd initialdesign, Eigen::MatrixXd ca
//Checks if the initial matrix is singular. If so, randomly generates a new design nTrials times.
for(int j = 1; j < candidatelist.cols(); j++) {
if(ones.col(0).cwiseEqual(candidatelist.col(j)).all()) {
throw std::runtime_error("skpr: Singular model matrix from factor aliased into intercept, revise model");
Rcpp::stop("skpr: Singular model matrix from factor aliased into intercept, revise model");
}
}
int nTrials = initialdesign.rows();
Expand Down Expand Up @@ -82,7 +82,7 @@ List genSplitPlotOptimalDesign(Eigen::MatrixXd initialdesign, Eigen::MatrixXd ca
Eigen::VectorXi candidateRow = initialRows;
Eigen::VectorXi shuffledindices;
if(nTrials < candidatelist.cols() + blockedCols + numberinteractions) {
throw std::runtime_error("skpr: Too few runs to generate initial non-singular matrix: increase the number of runs or decrease the number of parameters in the matrix");
Rcpp::stop("skpr: Too few runs to generate initial non-singular matrix: increase the number of runs or decrease the number of parameters in the matrix");
}
//Checks if the initial matrix is singular. If so, randomly generates a new design maxSingularityChecks times.
for (int check = 0; check < maxSingularityChecks; check++) {
Expand Down
4 changes: 2 additions & 2 deletions src/getBlockedOptimalDesign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ List genBlockedOptimalDesign(Eigen::MatrixXd initialdesign, const Eigen::MatrixX
const Eigen::MatrixXd vInv = V.colPivHouseholderQr().inverse();

if(nTrials < candidatelist.cols()) {
throw std::runtime_error("skpr: Too few runs to generate initial non-singular matrix: increase the number of runs or decrease the number of parameters in the matrix");
Rcpp::stop("skpr: Too few runs to generate initial non-singular matrix: increase the number of runs or decrease the number of parameters in the matrix");
}
//Check for singularity from a column perfectly correlating with the intercept.
for(int j = 1; j < candidatelist.cols(); j++) {
if(candidatelist.col(0).cwiseEqual(candidatelist.col(j)).all()) {
throw std::runtime_error("skpr: Singular model matrix from factor aliased into intercept, revise model");
Rcpp::stop("skpr: Singular model matrix from factor aliased into intercept, revise model");
}
}
Eigen::VectorXi shuffledindices;
Expand Down
Binary file modified tests/testthat/Rplots.pdf
Binary file not shown.
Binary file removed tests/testthat/testthat-problems.rds
Binary file not shown.

0 comments on commit 904a5b0

Please sign in to comment.