Nothing
#' Run an APSIM-X Simulation
#'
#' A valid apsimx file can be run from within R. The main goal is to make running APSIM-X
#' simple, especially for large scale simulations or parameter optimization
#'
#' @title Run an APSIM-X simulation
#' @name apsimx
#' @description Run apsimx from R. It uses \sQuote{system} (unix) or \sQuote{shell} (windows) and it attempts to be platform independent.
#' @param file file name to be run (the extension .apsimx is optional)
#' @param src.dir directory containing the .apsimx file to be run (defaults to the current directory)
#' @param silent whether to print messages from apsim simulation
#' @param value how much output to return: \cr
#' option \sQuote{report} returns only the \sQuote{main} report component; \cr
#' option \sQuote{all} returns all components of the simulation; \cr
#' option \sQuote{none} does not create a data.frame but it generates the databases
#' option \sQuote{user-defined} should be the name of a specific table
#' @param cleanup logical. Whether to delete the .db file generated by APSIM-X. Default is FALSE
#' @param simplify whether to return a single data frame when multiple reports are present. If FALSE it will return a list.
#' @param xargs extra arguments to be passed to the APSIM-X run. Use function xargs_apsimx.
#' @return a data frame with the \sQuote{Report} from the APSIM-X simulation. The return value depends on the argument \sQuote{value} above.
#' @export
#' @examples
#' \donttest{
#' ## See function 'apsimx_example' and vignette 'apsimx'
#' }
#'
apsimx <- function(file = "", src.dir = ".",
silent = FALSE,
value = "report",
cleanup = FALSE,
simplify = TRUE,
xargs){
if(file == "") stop("need to specify file name")
.check_apsim_name(file)
.check_apsim_name(normalizePath(src.dir))
## The might offer suggestions in case there is a typo in 'file'
file.names <- dir(path = src.dir, pattern=".apsimx$", ignore.case=TRUE)
if(length(file.names) == 0){
stop("There are no .apsimx files in the specified directory to run.")
}
file <- match.arg(file, file.names)
file.name.path <- file.path(src.dir, file)
ada <- auto_detect_apsimx()
## Grabs the global variables
dotnet.flag <- apsimx::apsimx.options$dotnet
mono.flag <- apsimx::apsimx.options$mono
if(!missing(xargs)){
dotnet.flag <- xargs$dotnet
mono.flag <- xargs$mono
if(!is.na(xargs$exe.path))
ada <- xargs$exe.path
}
if(.Platform$OS.type == "unix"){
if(dotnet.flag){
run.strng <- paste("dotnet", ada, file.name.path)
}
if(mono.flag){
mono <- system("which mono", intern = TRUE)
run.strng <- paste(mono, ada, file.name.path)
}
if(isFALSE(dotnet.flag) && isFALSE(mono.flag)){
run.strng <- paste(ada, file.name.path)
}
## Run APSIM-X on the command line
if(!missing(xargs)) run.strng <- paste(run.strng, xargs$xargs.string)
res <- system(command = run.strng, ignore.stdout = silent, intern = TRUE)
}
if(.Platform$OS.type == "windows"){
## Should probably delete the line below
## As of 2020-07-04, this seems to be working fine
## I will leave the line below until I'm sure it is not needed
## if(src.dir != ".") stop("In Windows you can only run a file from the current directory.")
run.strng <- paste0(ada, " ", file.name.path)
if(!missing(xargs)) run.strng <- paste(run.strng, xargs$xargs.string)
shell(cmd = run.strng, translate = TRUE, intern = TRUE)
}
if(value != "none"){
ans <- read_apsimx(file = sub("apsimx","db",file), src.dir = src.dir, value = value, simplify = simplify)
}else{
if(value == "none" && !silent){
cat("APSIM created .db files, but nothing is returned \n")
}
}
if(cleanup){
## Default is not to cleanup
if(value == "none") stop("do not clean up if you choose value = 'none' ")
## Delete the apsim-generated sql database
file.remove(paste0(src.dir, "/", sub("apsimx", "db", file)))
}
if(value != "none")
return(ans)
}
#' Extra arguments for running APSIM-X
#' @title Provide extra arguments for APSIM-X
#' @name xargs_apsimx
#' @description This provides additinoal command line arguments when running the model
#' @param verbose Write detailed messages to stdout when a simulation starts/finishes.
#' @param csv Export all reports to .csv files.
#' @param merge.db.files Merge multiple .db files into a single .db file.
#' @param list.simulations List simulation names without running them.
#' @param list.referenced.filenames List all files that are referenced by an .apsimx file(s).
#' @param single.threaded Run all simulations sequentially on a single thread.
#' @param cpu.count (Default: -1) Maximum number of threads/processes to spawn for running simulations.
#' @param simulation.names Only run simulations if their names match this regular expression.
#' @param dotnet Logical. There is a global option for this argument, but this will override it. This
#' can be useful if the goal is to compare an old version of Next Gen (before Sept 2021) with a more
#' recent version in the same script. This might be needed if you have your own compiled version of APSIM Next Gen.
#' @param mono Logical. Should be set to TRUE if running a version of APSIM Next Gen from Aug 2021 or older on Mac or Linux.
#' @param exe.path executable path. This can be useful for having both a global option through \sQuote{apsimx.options} and
#' a local option that will override that. This option will take precedence.
#' @return it returns a character vector with the extra arguments.
#' @export
xargs_apsimx <- function(verbose = FALSE, csv = FALSE, merge.db.files = FALSE, list.simulations = FALSE,
list.referenced.filenames = FALSE, single.threaded = FALSE, cpu.count = -1L,
simulation.names = FALSE, dotnet = FALSE, mono = FALSE,
exe.path = NA){
if(dotnet && mono)
stop("either dotnet or mono should be TRUE, but not both", call. = TRUE)
verbose <- ifelse(verbose, " --verbose", "")
csv <- ifelse(csv, " --csv", "")
merge.db.files <- ifelse(merge.db.files, " --merge-db-files", "")
list.simulations <- ifelse(list.simulations, " --list-simulations", "")
list.referenced.filenames <- ifelse(list.referenced.filenames, " --list-referenced-filenames", "")
single.threaded <- ifelse(single.threaded, " --single-threaded", "")
if(cpu.count == 0L) stop("cpu.count cannot be zero")
if(!is.integer(cpu.count)) stop("cpu.count should be an integer. For example, cpu.count=2L for two cores")
cpu.count <- ifelse(cpu.count > 0, paste0(" --cpu-count=", cpu.count), "")
simulation.names <- ifelse(simulation.names, " --simulation-names", "")
## I'm guessing single threaded is not compatible with cpu.count
xargs.string <- paste0(verbose, csv, merge.db.files, list.simulations, list.referenced.filenames, single.threaded, cpu.count, simulation.names)
## Remove beggining or trailing spaces
xargs.string <- gsub("^\\s+|\\s+$", "", xargs.string)
xargs.string
ans <- list(xargs.string = xargs.string, dotnet = dotnet, mono = mono, exe.path = exe.path)
}
## This is an internal function so I won't export/document it
#' @noRd
auto_detect_apsimx <- function(){
if(.Platform$OS.type == "unix"){
if(grepl("Darwin", Sys.info()[["sysname"]])){
laf <- list.files("/Applications/")
find.apsim <- grep("APSIM", laf)
## This deals with the fact that APSIM-X might not be present but perhaps a
## custom version is available
if(length(find.apsim) == 0){
## I only throw a warning because maybe the user has a custom version of APSIM-X only
if(!is.na(apsimx::apsimx.options$exe.path) && apsimx::apsimx.options$warn.find.apsimx){
warning("APSIM-X not found, but a custom one is present")
}else{
if(is.na(apsimx::apsimx.options$exe.path))
stop("APSIM-X not found and no 'exe.path' exists.")
}
}
## If only one version of APSIM-X is present
## APSIM executable
st1 <- "/Applications/"
st3 <- "/Contents/Resources/bin/Models.exe"
if(apsimx.options$dotnet) st3 <- gsub("exe$", "dll", st3)
if(isFALSE(apsimx.options$mono) && isFALSE(apsimx.options$dotnet))
st3 <- "/Contents/Resources/bin/Models"
if(length(find.apsim) == 1){
apsimx.name <- laf[find.apsim]
apsimx_dir <- paste0(st1, apsimx.name, st3)
## I could use 'file.path' instead, but it this is not a 'file'
## so it could be confusing
}
## If there is more than one version of APSIM-X
if(length(find.apsim) > 1){
## Originally I was sorting by #issue number but this
## does not give you the latest version
len.fa <- length(find.apsim)
## This extracts the date from the APSIM name but I
## only need this for debugging in case there is a problem
fa.dt <- as.numeric(sapply(laf[find.apsim], .favd))
newest.version <- laf[find.apsim][len.fa]
if(apsimx::apsimx.options$warn.versions &&
is.na(apsimx::apsimx.options$exe.path)){
warning(paste("Multiple versions of APSIM-X installed. \n
Choosing the newest one:", newest.version))
}
apsimx.name <- newest.version
apsimx_dir <- paste0(st1, apsimx.name, st3)
}
}
if(grepl("Linux", Sys.info()[["sysname"]])){
apsimx.versions <- NULL
find.apsim <- grep("apsim", list.files("/usr/local/lib"))
## What if length equals zero?
if(length(find.apsim) == 0){
## I only throw a warning because maybe the user has a custom version of APSIM-X only
if(!is.na(apsimx::apsimx.options$exe.path) && apsimx::apsimx.options$warn.find.apsimx){
warning("APSIM-X not found, but a custom one is present")
}else{
if(is.na(apsimx::apsimx.options$exe.path))
stop("APSIM-X not found and no 'exe.path' exists.")
}
}
## APSIM executable
st1 <- "/usr/local/lib/apsim/"
st3 <- "/bin/Models.exe"
if(apsimx.options$dotnet) st3 <- gsub("exe$", "dll", st3)
if(isFALSE(apsimx.options$mono) && isFALSE(apsimx.options$dotnet))
st3 <- "/bin/Models"
if(length(find.apsim) == 1){
apsimx.versions <- list.files("/usr/local/lib/apsim")
apsimx.name <- apsimx.versions
apsimx_dir <- paste0(st1, apsimx.name, st3)
}
## Note: Apparently Debian does not tolerate multiple
## versions of APSIM-X installed, date 2019-12-12
if(length(apsimx.versions) > 1){
len.fa <- length(find.apsim)
newest.version <- apsimx.versions[find.apsim]
if(apsimx::apsimx.options$warn.versions){
warning(paste("Multiple versions of APSIM-X installed. \n
Choosing the newest one:", newest.version))
}
apsimx.name <- newest.version
apsimx_dir <- paste0(st1, apsimx.name, st3)
}
}
}
if(.Platform$OS.type == "windows"){
st1 <- "C:/PROGRA~1/"
laf <- list.files(st1)
find.apsim <- grep("APSIM", laf)
## What if length equals zero?
if(length(find.apsim) == 0 && is.na(apsimx::apsimx.options$exe.path)){
## Try using the registry only if APSIM path has not been set manually
if(apsimx::apsimx.options$warn.find.apsimx) warning("Searching the Windows registry for APSIM-X")
## HCR hive is for HKEY_CLASSES_ROOT, HLM is for HKEY_LOCAL_MACHINE and HCU is for HKEY_CURRENT_USER
regcmd <- try(utils::readRegistry("APSIMXFile\\shell\\open\\command", "HCR")[[1]], silent = TRUE)
if(inherits(regcmd, "try-error")) regcmd <- try(utils::readRegistry("APSIMXFile\\shell\\open\\command", "HCU")[[1]], silent = TRUE)
if(inherits(regcmd, "try-error")) regcmd <- try(utils::readRegistry("APSIMXFile\\shell\\open\\command", "HLM")[[1]], silent = TRUE)
if(inherits(regcmd, "try-error")) stop("Could not find APSIM-X in the Windows Registry")
regcmd2 <- gsub("\\\\", "/", strsplit(regcmd, "\"")[[1]][2])
apsimx_dir <- gsub("ApsimNG", "Models", regcmd2)
if(length(apsimx_dir) == 0) stop("APSIM-X not found and no 'exe.path' exists.")
if(grepl("\\s", apsimx_dir)) stop("Found a space in the path. Please provide the path manually to APSIM-X using exe.path in apsimx_options.")
return(apsimx_dir)
}
st3 <- "/bin/Models.exe"
if(apsimx.options$dotnet) st3 <- gsub("exe$", "dll", st3)
if(length(find.apsim) == 1){
apsimx.versions <- laf[find.apsim]
apsimx.name <- apsimx.versions
apsimx_dir <- paste0(st1, apsimx.name, st3)
}
if(length(find.apsim) > 1){
apsimx.versions <- laf[find.apsim]
newest.version <- apsimx.versions[length(find.apsim)]
if(apsimx::apsimx.options$warn.versions){
warning(paste("Multiple versions of APSIM-X installed. \n
Choosing the newest one:", newest.version))
}
apsimx.name <- newest.version
apsimx_dir <- paste0(st1, apsimx.name, st3)
}
}
if(!is.na(apsimx::apsimx.options$exe.path)){
## Windows paths might contain white spaces which are
## problematic when running them at the command line
if(grepl("\\s", apsimx::apsimx.options$exe.path))
stop("White spaces are not allowed in APSIM-X executable path")
apsimx_dir <- apsimx::apsimx.options$exe.path
}
return(apsimx_dir)
}
#' Auto detect where apsimx examples are located
#'
#' @title Auto detect where apsimx examples are located
#' @name auto_detect_apsimx_examples
#' @description simple function to detect where APSIM-X examples are located
#' @return will create a directory (character string) pointing to APSIM-X distributed examples
#' @export
#' @examples
#' \dontrun{
#' ex.dir <- auto_detect_apsimx_examples()
#' }
#'
auto_detect_apsimx_examples <- function(){
if(.Platform$OS.type == "unix"){
apsim.name <- NULL # Why did I create this NULL variable?
if(grepl("Darwin", Sys.info()[["sysname"]])){
## If APSIM-X is installed it will be in /Applications/
## look into Applications folder
laf <- list.files("/Applications/")
find.apsim <- grep("APSIM",laf)
if(length(find.apsim) == 0) stop("APSIM-X examples not found")
if(length(find.apsim) > 1){
newest.version <- laf[find.apsim][length(find.apsim)]
if(apsimx::apsimx.options$warn.versions && is.na(apsimx::apsimx.options$exe.path)){
warning(paste("Multiple versions of APSIM-X installed. \n
Choosing the newest one:", newest.version))
}
apsimx.name <- newest.version
}else{
apsimx.name <- laf[find.apsim]
}
st1 <- "/Applications/"
st3 <- "/Contents/Resources/Examples"
apsimx_ex_dir <- paste0(st1, apsimx.name, st3)
}
if(grepl("Linux", Sys.info()[["sysname"]])){
st1 <- "/usr/local/lib/apsim/"
apsimx.versions <- list.files(st1)
## In Ubuntu it looks like you can only have one version
## of APSIM-X installed
if(length(apsimx.versions) > 1){
len.fa <- length(find.apsim)
newest.version <- apsimx.versions[find.apsim]
if(apsimx.options$warn.versions && is.na(apsimx::apsimx.options$exe.path)){
warning(paste("Multiple versions of APSIM-X installed. \n
Choosing the newest one:", newest.version))
}
apsimx.name <- newest.version
}else{
apsimx.name <- apsimx.versions
}
apsimx_ex_dir <- paste0(st1, apsimx.name, "/Examples")
}
}
if(.Platform$OS.type == "windows"){
## Need to test this change
adax <- auto_detect_apsimx()
## APSIM path to examples
# st3 <- "/Examples"
# apsimx_ex_dir <- paste0(st1, "/", apsimx.name, st3)
apsimx_ex_dir <- gsub("bin/Models.*", "Examples", adax)
}
if(!is.na(apsimx::apsimx.options$examples.path)){
## I dislike white spaces in paths!
## I'm looking at you Windows!
if(grepl("\\s", apsimx::apsimx.options$examples.path))
stop("White spaces are not allowed in examples.path")
apsimx_ex_dir <- apsimx::apsimx.options$examples.path
}
return(apsimx_ex_dir)
}
#'
#' @title Access Example APSIM-X Simulations
#' @name apsimx_example
#' @description simple function to run some of the built-in APSIM-X examples
#' @param example run an example from built-in APSIM-X. Options are all of the ones included with the APSIM-X distribution, except \sQuote{Graph}.
#' @param silent whether to print standard output from the APSIM-X execution
#' @note This function creates a new column \sQuote{Date} which is in the R \sQuote{Date} format which is convenient for graphics.
#' @details This function creates a temporary copy of the example file distributed with APSIM-X to avoid writing a .db file
#' to the directory where the \sQuote{Examples} are located. It is not a good practice and there is no guarantee that
#' the user has read/write permissions in that directory.
#' @return It returns a data frame
#' @export
#' @examples
#' \dontrun{
#' wheat <- apsimx_example("Wheat")
#' maize <- apsimx_example("Maize")
#' barley <- apsimx_example("Barley")
#' ## The 'Date' column is created by this function, based on apsim output.
#' require(ggplot2)
#' ggplot(data = wheat , aes(x = Date, y = Yield)) +
#' geom_point()
#' }
#'
apsimx_example <- function(example = "Wheat", silent = FALSE){
## Write to a temp directory only
tmp.dir <- tempdir()
## Run a limited set of examples
## Now the only one missing is Graph, which I assume is about
## graphics and not that relevant to apsimx
## Several examples are not supported because they do not use
## relative paths for the weather file
## Examples which do not run: Chicory
ex.ch <- c("Barley", "ControlledEnvironment", "Eucalyptus",
"EucalyptusRotation",
"Maize", "Oats", "Rotation", "Soybean", "Sugarcane", "Wheat")
example <- match.arg(example, choices = ex.ch)
ex.dir <- auto_detect_apsimx_examples()
ex <- file.path(ex.dir, paste0(example, ".apsimx"))
if(!file.exists(ex)) stop(paste0("cannot find example file ", example))
## Make a temporary copy of the file to the current directory
## Do not transfer permissions?
file.copy(from = ex, to = tmp.dir, copy.mode = FALSE)
sim <- apsimx(paste0(example, ".apsimx"), src.dir = tmp.dir,
value = "report", simplify = FALSE)
## OS independent cleanup (risky?)
file.remove(paste0(tmp.dir, "/", example, ".db"))
file.remove(paste0(tmp.dir, "/", example, ".apsimx"))
return(sim)
}
#' Read APSIM-X generated .db files
#'
#' @title Read APSIM-X generated .db files
#' @name read_apsimx
#' @description read SQLite databases created by APSIM-X runs. One file at a time.
#' @param file file name
#' @param src.dir source directory where file is located
#' @param value either \sQuote{report}, \sQuote{all} (list) or user-defined for a specific report
#' @param simplify if TRUE will attempt to simplify multiple reports into a single data.frame.
#' If FALSE it will return a list.
#' @note if there is one single report it will return a data.frame.
#' If there are multiple reports, it will attempt to merge them into a data frame.
#' If not possible it will return a list with names corresponding to the
#' table report names. It is also possible to select a specific report from several
#' available by selecting \sQuote{value = ReportName}, where \sQuote{ReportName} is the name
#' of the specific report that should be returned.
#' If you select \sQuote{all} it will return all the components in the data base also as a list.
#' @return normally it returns a data frame, but it depends on the argument \sQuote{value} above
#' @export
#'
read_apsimx <- function(file = "", src.dir = ".", value = "report", simplify = TRUE){
if(file == "") stop("need to specify file name")
file.names <- dir(path = src.dir, pattern=".db$", ignore.case=TRUE)
if(length(file.names) == 0){
stop("There are no .db files in the specified directory to read.")
}
file.name.path <- file.path(src.dir, file)
con <- DBI::dbConnect(RSQLite::SQLite(), file.name.path)
## create data frame for each table
## Find table names first
table.names <- RSQLite::dbListTables(con)
other.tables <- grep("^_", table.names, value = TRUE)
report.names <- setdiff(table.names, other.tables)
### Are there other potential tables starting with "_"?
## I guess I always expect to find a table, but not always... better to catch it here
if(length(report.names) < 1)
stop("No report tables found")
if(length(report.names) == 1L){
tbl0 <- DBI::dbGetQuery(con, paste("SELECT * FROM ", report.names))
if(nrow(tbl0) == 0)
warning("Report table has no data")
if(any(grepl("Clock.Today", names(tbl0)))){
if(nrow(tbl0) > 0){
tbl0$Date <- try(as.Date(sapply(tbl0$Clock.Today, function(x) strsplit(x, " ")[[1]][1])), silent = TRUE)
}
}
}
if(length(report.names) > 1L && value %in% c("report", "all")){
if(simplify){
lst0 <- NULL
for(i in seq_along(report.names)){
tbl0 <- DBI::dbGetQuery(con, paste("SELECT * FROM ", report.names[i]))
if(nrow(tbl0) == 0)
warning(paste("Report", report.names[i]), "has no data")
if(any(grepl("Clock.Today", names(tbl0)))){
if(nrow(tbl0) > 0){
tbl0$Date <- try(as.Date(sapply(tbl0$Clock.Today, function(x) strsplit(x, " ")[[1]][1])), silent = TRUE)
}
}
dat0 <- data.frame(report = report.names[i], tbl0)
lst0 <- try(rbind(lst0, dat0), silent = TRUE)
if(inherits(lst0, "try-error")){
stop("Could not simplify reports into a single data.frame \n
Choose simplify = FALSE or modify your reports.")
}
}
}else{
lst0 <- vector("list", length = length(report.names))
for(i in seq_along(report.names)){
tbl0 <- DBI::dbGetQuery(con, paste("SELECT * FROM ", report.names[i]))
if(any(grepl("Clock.Today", names(tbl0)))){
tbl0$Date <- try(as.Date(sapply(tbl0$Clock.Today, function(x) strsplit(x, " ")[[1]][1])), silent = TRUE)
}
lst0[[i]] <- tbl0
}
names(lst0) <- report.names ## Name the lists with report names
}
}
if(!value %in% c("report", "all") && length(report.names) > 1L){
if(!value %in% report.names){
cat("Available table names: ", report.names ,"\n")
stop("user defined report name is not in the list of available tables",
call. = FALSE)
}
tbl0 <- DBI::dbGetQuery(con, paste("SELECT * FROM ", value))
if(any(grepl("Clock.Today", names(tbl0)))){
tbl0$Date <- try(as.Date(sapply(tbl0$Clock.Today, function(x) strsplit(x, " ")[[1]][1])), silent = TRUE)
}
}
if(value == "all"){
other.tables.list <- vector("list", length = length(other.tables))
for(i in seq_along(other.tables)){
other.tables.list[[i]] <- DBI::dbGetQuery(con, paste("SELECT * FROM ", other.tables[i]))
}
names(other.tables.list) <- gsub("_", "", other.tables, fixed = TRUE)
}
## Disconnect
DBI::dbDisconnect(con)
## Return a list if there is only one report, whatever the name and value == "all"
if(value == "all" && length(report.names) == 1L){
lst1 <- list(Report = tbl0)
ans <- do.call(c, list(lst1, other.tables.list))
}
if(value == "all" && length(report.names) > 1L){
ans <- do.call(c, list(lst0, other.tables.list))
}
if(value == "report" && length(report.names) > 1L){
ans <- lst0
}
## Return data.frame if report and length 1 or user defined
if((value == "report" && length(report.names) == 1L) || (!value %in% c("report", "all"))){
ans <- tbl0
}
return(ans)
}
#' Read all APSIM-X generated .db files in a directory
#'
#' @title Read all APSIM-X generated .db files in a directory
#' @name read_apsimx_all
#' @description Like \code{\link{read_apsimx}}, but it reads all .db files in a directory.
#' @param src.dir source directory where files are located
#' @param value either \sQuote{report} or \sQuote{all} (only \sQuote{report} implemented at the moment)
#' @note Warning: very simple function at the moment, not optimized for memory or speed.
#' @return it returns a data frame or a list if \sQuote{value} equals \sQuote{all}.
#' @export
#'
read_apsimx_all <- function(src.dir = ".", value = "report"){
## This is super memorey hungry and not efficient at all, but it might work
## for now
file.names <- dir(path = src.dir, pattern=".db$", ignore.case=TRUE)
ans <- NULL
for(i in file.names){
tmp <- read_apsimx(file.names[i], value = value)
tmp.d <- data.frame(file.name = file.names[i], tmp)
ans <- rbind(ans, tmp)
}
return(ans)
}
#' Set apsimx options
#'
#' @title Setting some options for the package
#' @name apsimx_options
#' @description Set the path to the APSIM-X executable, examples and warning suppression.
#' @param exe.path path to apsim executable. White spaces are not allowed.
#' @param dotnet logical indicating if APSIM should be run through the dotnet command
#' @param mono logical indicating if the mono command should be used when running APSIM. This is for versions
#' for Mac/Linux older than Sept 2021.
#' @param examples.path path to apsim examples
#' @param warn.versions logical. warning if multiple versions of APSIM-X are detected.
#' @param warn.find.apsimx logical. By default a warning will be thrown if APSIM-X is not found.
#' If \sQuote{exe.path} is \sQuote{NA} an error will be thrown instead.
#' @note It is possible that APSIM-X is installed in some alternative location other than the
#' defaults ones. Guessing this can be difficult and then the auto_detect functions might
#' fail. Also, if multiple versions of APSIM-X are installed apsimx will choose the newest
#' one but it will issue a warning. Suppress the warning by setting warn.versions = FLASE.
#' @return as a side effect it modifies the \sQuote{apsimx.options} environment.
#' @export
#' @examples
#'\donttest{
#' names(apsimx.options)
#' apsimx_options(exe.path = "some-new-path-to-executable")
#' apsimx.options$exe.path
#' }
apsimx_options <- function(exe.path = NA, dotnet = FALSE, mono = FALSE, examples.path = NA,
warn.versions = TRUE, warn.find.apsimx = TRUE){
if(dotnet && mono)
stop("either dotnet or mono should be TRUE, but not both", call. = TRUE)
assign('exe.path', exe.path, apsimx.options)
assign('dotnet', dotnet, apsimx.options)
assign('mono', mono, apsimx.options)
assign('examples.path', examples.path, apsimx.options)
assign('warn.versions', warn.versions, apsimx.options)
assign('warn.find.apsimx', warn.find.apsimx, apsimx.options)
}
#' Environment which stores APSIM-X options
#'
#' @title Environment which stores APSIM-X options
#' @name apsimx.options
#' @description Environment which can store the path to the executable, warning settings and
#' where examples are located.
#' Creating an environment avoids the use of global variables or other similar practices
#' which would have possible undesriable consequences.
#' @return This is an environment, not a function, so nothing is returned.
#' @export
#' @examples
#' \donttest{
#' names(apsimx.options)
#' apsimx_options(exe.path = "some-new-path-to-executable")
#' apsimx.options$exe.path
#' }
#'
apsimx.options <- new.env(parent = emptyenv())
assign('exe.path', NA, apsimx.options)
assign('dotnet', FALSE, apsimx.options)
assign('mono', FALSE, apsimx.options)
assign('examples.path', NA, apsimx.options)
assign('warn.versions', TRUE, apsimx.options)
assign('warn.find.apsimx', TRUE, apsimx.options)
assign('.run.local.tests', FALSE, apsimx.options)
## I'm planning to use '.run.local.tests' for running tests
## which do not require an APSIM install
## Import packages needed for apsimx to work correctly
#' @import DBI jsonlite knitr RSQLite xml2
#' @importFrom utils read.table write.table packageVersion
#' @importFrom tools file_path_sans_ext
#' @importFrom stats aggregate anova coef cor cov2cor deviance lm optim qt var sd setNames sigma
NULL
utils::globalVariables(".data")
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.