#' Combine multiple arg-trees by merging matching sub-trees.
#'
#' @param ... arbitrary number of lists.
#' @return single merged list
#' @export
merge_trees <- function(...) {
args_in <- list(...)
args_out <- args_in[[1]]
args_remaining <- args_in[2:length(args_in)]
for (arg in args_remaining) {
for (name in names(arg)) {
if (!(name %in% names(args_out))) {
args_out[[name]] <- arg[[name]]
} else {
if (is.list(args_out[[name]]) && is.list(arg[[name]])) {
args_out[[name]] <- merge_trees(args_out[[name]], arg[[name]])
} else if (!is.list(args_out[[name]]) && !is.list(arg[[name]])) {
args_out[[name]] <- arg[[name]]
} else {
stop("Mismatched argument types in list merge.")
}
}
}
}
return(args_out)
}
#' Prepare a single input tree by combining paths.
#'
#' @param args an arg-tree
#' @return an arg-tree
#' @export
prepare_inputs = function(args) {
# Prepare model
args[['model_path']] <- find_model(args)
# Prepare data
data_dir <- args[['data_dir']]
if (!is.null(data_dir) && !is.null(args[['data']][['file']])) {
args[['data']][['file']] <- file.path(data_dir, args[['data']][['file']])
}
# Prepare inits
init_exists <- !is.null(args[['init']]) && !is.na(args[['init']])
is_init_file <- init_exists && is.na(as.numeric(args[['init']]))
init_dir <- args[['init_dir']]
if (!is.null(init_dir) && init_exists && is_init_file) {
args[['init']] <- file.path(init_dir, args[['init']])
}
if (is_init_file && !file.exists(args[['init']])) {
msg <- paste0("Initial values file missing at: ", args[['init']])
stop(msg)
}
args[['hash']] <- create_hash(args)
return(args)
}
#' Load a Stannis run control list of arg-trees from
#' a .yaml file
#'
#' Format description: the two top-level items are
#' 'defaults', and 'runs'. The each item under those
#' is a Stannis arg-tree with CmdStan arguments.
#'
#' Arg-trees are loaded, each run arg-tree is merged with the
#' defaults, and a hash is added to each.
#'
#' @param file a .yaml file with arg-tree structure
#' and defaults.
#' @return list of arg-trees with hashes, not finalized.
#' @export
load_args <- function(file) {
control <- yaml::yaml.load_file(file)
defaults <- control[['defaults']]
all_args <- list()
for (i in 1:length(control[['runs']])) {
args <- merge_trees(defaults, control[['runs']][[i]])
args[['binary']] <- compile_model(args)
args <- replicate_args(args)
for (j in seq_along(args)) {
args[[j]] <- prepare_inputs(args[[j]])
}
all_args <- c(all_args, args)
}
return(all_args)
}
#' Finalize an argument tree object by merging components
#' that are not fully specified and creating output directories
#' as necessary.
#'
#' @param args arg-tree object (list).
#' @return same tree, ready to pass to 'construct_cmdline'
#' and 'run_model_cmd'
#' @export
finalize_args <- function(args) {
if (is.null(args[['output']]))
args[['output']] <- list()
args[['output']][['terminal']] = 'terminal.txt'
args[['output']][['error']] = 'error.txt'
args[['output']][['file']] = 'output.csv'
args[['output']][['diagnostic_file']] = 'diagnostics.csv'
args[['output']][['control']] = 'control.yaml'
output_files <- c('terminal', 'error', 'file', 'diagnostic_file', 'control')
if (is.null(args[['target_dir']]))
args[['target_dir']] <- getwd()
args[['fit_path']] <- file.path(args[['target_dir']], args[['hash']])
if (!dir.exists(args[['fit_path']])) {
dir.create(args[['fit_path']], recursive = TRUE)
args[['run']] = TRUE
} else {
args[['run']] = FALSE
}
if (!dir.exists(file.path(args[['fit_path']], 'data')))
dir.create(file.path(args[['fit_path']], 'data'), recursive=TRUE)
if (!dir.exists(file.path(args[['fit_path']], 'init')))
dir.create(file.path(args[['fit_path']], 'init'), recursive=TRUE)
for (output in output_files) {
args[['output']][[output]] <- file.path(args[['fit_path']], args[['output']][[output]])
}
if (!is.null(args[['data']]) && !is.null(args[['data']][['file']])) {
if (file.exists(args[['data']][['file']])) {
file.copy(from = args[['data']][['file']],
to = file.path(args[['fit_path']], basename(args[['data']][['file']])))
} else {
msg <- paste0("Data file missing at: ", args[['data']][['file']])
stop(msg)
}
}
init_exists <- !is.null(args[['init']]) && !is.na(args[['init']])
is_init_file <- init_exists && is.na(as.numeric(args[['init']]))
init_dir <- args[['init_dir']]
if (is_init_file && !file.exists(args[['init']])) {
msg <- paste0("Initial values file missing at: ", args[['init']])
stop(msg)
} else if (is_init_file && file.exists(args[['init']])) {
file.copy(from = args[['init']],
to = file.path(args[['fit_path']], basename(args[['init']])))
}
args[['command']] <- do.call(what = construct_cmdline, args = args)
yaml::write_yaml(args, file = file.path(args[['fit_path']], "finalized.yaml"))
return(args)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.