Generate a skeleton for a new SpaDES module, a template for a
documentation file, a citation file, a license file, a README.md
file,
and a folder that contains unit tests information. newModule
is largely a
wrapper around newModuleCode
and newModuleDocumentation
.
newModuleCode
will not generate the module code.
newModuleDocumentation
will create the other files.
newModule(name, path, ..., events = NULL, envir = parent.frame())
# S4 method for class 'character,character'
newModule(name, path, ..., events = NULL, envir = parent.frame())
# S4 method for class 'character,missing'
newModule(name, path, ..., events = NULL, envir = parent.frame())
newModuleCode(name, path, ..., events)
# S4 method for class 'character,character'
newModuleCode(name, path, ..., events)
newModuleDocumentation(name, path, ...)
# S4 method for class 'character,character'
newModuleDocumentation(name, path, ...)
# S4 method for class 'character,missing'
newModuleDocumentation(name, path, ...)
Character string specifying the name of the new module.
Character string. Subdirectory in which to place the new module code file. The default is the current working directory.
Additional arguments. Currently, these can be either named
function definitions (which will be added to the simList
) or one or
more of the following:
children
Required when type = "parent"
. A character vector
specifying the names of child modules.
open
Logical. Should the new module file be opened after creation?
Default TRUE
.
type
Character string specifying one of "child"
(default),
or "parent"
.
For newModule
can also be:
unitTests
Logical. Should the new module include unit test files?
Default TRUE
. Unit testing relies on the testthat package.
useGitHub
Logical. Is module development happening on GitHub?
Default TRUE
.
A list of named expressions, each of which is surrounded by { }
.
A user can specify events here, instead of accepting the default doEvent
function
that comes with the module template. If this is specified, all events must
be specified, i.e., it will not inherit partially from the template doEvent.<moduleName>
.
See example.
An environment where objects being passed to newModule
can be found.
Default parent.frame()
, which should be fine for most cases.
NULL (invisibly). The new module file is created at
path/name.R
, as well as ancillary files for documentation, citation,
LICENSE
, README
, and tests
directory.
newModuleCode
is invoked for its side effect of creating new module code files.
newModuleDocumentation
is nvoked for its side effect of
creating new module documentation files.
All files will be created within a subdirectory named name
within the path
:
<path>/
|_ <name>/
|_ R/ # contains additional module R scripts
|_ data/ # directory for all included data
|_ CHECKSUMS.txt # contains checksums for data files
|_ tests/ # contains unit tests for module code
|_ citation.bib # bibtex citation for the module
|_ LICENSE # describes module's legal usage
|_ README.md # provide overview of key aspects
|_ <name>.R # module code file (incl. metadata)
|_ <name>.Rmd # documentation, usage info, etc.
On Windows there is currently a bug in RStudio that prevents the editor
from opening when file.edit
is called.
Similarly, in RStudio on macOS, there is an issue opening files where they
are opened in an overlaid window rather than a new tab.
file.edit
does work if the user types it at the command prompt.
A message with the correct lines to copy and paste is provided.
Other module creation helpers:
newModuleTests()
Other module creation helpers:
newModuleTests()
Other module creation helpers:
newModuleTests()
# \donttest{
tmpdir <- tempdir2("exampleNewModule")
## create a "myModule" module in the "modules" subdirectory.
newModule("myModule", tmpdir)
#> New module myModule created at /tmp/Rtmp45trFG/reproducible/exampleNewModule
#> * edit module code in myModule.R
#> * write tests for your module code in tests/
#> * describe and document your module in myModule.Rmd
#> * tell others how to cite your module by editing citation.bib
#> * choose a license for your module; see LICENSE.md
#> Main module file is: /tmp/Rtmp45trFG/reproducible/exampleNewModule/myModule/myModule.R
#> Main documentation file is: /tmp/Rtmp45trFG/reproducible/exampleNewModule/myModule/myModule.Rmd
## create a new parent module in the "modules" subdirectory.
newModule("myParentModule", tmpdir, type = "parent", children = c("child1", "child2"))
#> New module myParentModule created at /tmp/Rtmp45trFG/reproducible/exampleNewModule
#> * edit module code in myParentModule.R
#> * write tests for your module code in tests/
#> * describe and document your module in myParentModule.Rmd
#> * tell others how to cite your module by editing citation.bib
#> * choose a license for your module; see LICENSE.md
#> Main module file is: /tmp/Rtmp45trFG/reproducible/exampleNewModule/myParentModule/myParentModule.R
#> Main documentation file is: /tmp/Rtmp45trFG/reproducible/exampleNewModule/myParentModule/myParentModule.Rmd
unlink(tmpdir, recursive = TRUE)
# }
if (requireNamespace("ggplot2")) {
# We can also specify events and functions in `newModule`; it will still get all
# functions that are not specified from the module template (e.g., plotFun below)
nm <- "test"
modulePath <- Require::tempdir2()
newModule(nm, path = modulePath, open = FALSE,
events = list(
init = {
sim <- Init(sim) # finds definition below
sim <- scheduleEvent(sim, start(sim) + 1,
eventType = "plot")
},
plot = {
plotFun(sim) # finds the templated plotFun
sim <- scheduleEvent(sim, time(sim) + 1,
eventType = "plot")
}
,
),
Init = function(sim) { # replaces Init definition from template
sim$a <- 1
return(sim)
}
)
out <- simInitAndSpades(module = nm, paths = list(modulePath = modulePath))
# clean up
unlink(dir(modulePath, pattern = nm, full.names = TRUE), recursive = TRUE)
}
#> New module test created at /tmp/Rtmp45trFG/Require
#> * edit module code in test.R
#> * write tests for your module code in tests/
#> * describe and document your module in test.Rmd
#> * tell others how to cite your module by editing citation.bib
#> * choose a license for your module; see LICENSE.md
#> Main module file is: /tmp/Rtmp45trFG/Require/test/test.R
#> Main documentation file is: /tmp/Rtmp45trFG/Require/test/test.Rmd
#> Setting:
#> options(
#> spades.modulePath = '/tmp/Rtmp45trFG/Require'
#> )
#> Paths set to:
#> options(
#> rasterTmpDir = '/tmp/Rtmp45trFG/SpaDES/scratch/raster'
#> reproducible.cachePath = '/tmp/Rtmp45trFG/reproducible/cache'
#> spades.inputPath = '/tmp/Rtmp45trFG/SpaDES/inputs'
#> spades.outputPath = '/tmp/Rtmp45trFG/SpaDES/outputs'
#> spades.modulePath = '/tmp/Rtmp45trFG/Require'
#> spades.scratchPath = '/tmp/Rtmp45trFG/SpaDES/scratch'
#> )
#> terra::terraOptions(tempdir = '/tmp/Rtmp45trFG/SpaDES/scratch/terra'
#> Nov21 04:22:38 simInit Using setDTthreads(1). To change: 'options(spades.DTthreads = X)'.
#> Nov21 04:22:38 simInit test: outputObjects: a is assigned to sim inside Init, but is not declared in metadata outputObjects
#> Nov21 04:22:38 test :.inputObjects Running .inputObjects for test
#> Nov21 04:22:38 test :.inputObjects test: using dataPath '/tmp/Rtmp45trFG/Require/test/data'.
#> Elpsed time for simInit: 0.07399797 secs
#> Nov21 04:22:38 simInit Using setDTthreads(1). To change: 'options(spades.DTthreads = X)'.
#> Nov21 04:22:38 chckpn:init total elpsd: 0.076 secs | 0 checkpoint init 0
#> Nov21 04:22:38 save :init total elpsd: 0.078 secs | 0 save init 0
#> Nov21 04:22:38 prgrss:init total elpsd: 0.08 secs | 0 progress init 0
#> Nov21 04:22:38 load :init total elpsd: 0.082 secs | 0 load init 0
#> Nov21 04:22:38 test :init total elpsd: 0.085 secs | 0 test init 1
#> Nov21 04:22:38 test :init test
#> Nov21 04:22:38 test :init New objects created:
#> Nov21 04:22:38 test :init <char>
#> Nov21 04:22:38 test :init 1: a
#> Nov21 04:22:38 test :plot total elpsd: 0.095 secs | 1 test plot 5
#> Nov21 04:22:38 test :plot `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> Nov21 04:22:39 test :plot total elpsd: 0.2 secs | 2 test plot 5
#> Nov21 04:22:39 test :plot `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> Nov21 04:22:39 test :plot total elpsd: 0.28 secs | 3 test plot 5
#> Nov21 04:22:39 test :plot `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> Nov21 04:22:39 test :plot total elpsd: 0.35 secs | 4 test plot 5
#> Nov21 04:22:39 test :plot `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> Nov21 04:22:39 test :plot total elpsd: 0.43 secs | 5 test plot 5
#> Nov21 04:22:39 test :plot `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> Nov21 04:22:39 test :plot total elpsd: 0.53 secs | 6 test plot 5
#> Nov21 04:22:39 test :plot `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> Nov21 04:22:39 test :plot total elpsd: 0.61 secs | 7 test plot 5
#> Nov21 04:22:39 test :plot `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> Nov21 04:22:39 test :plot total elpsd: 0.69 secs | 8 test plot 5
#> Nov21 04:22:39 test :plot `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> Nov21 04:22:39 test :plot total elpsd: 0.79 secs | 9 test plot 5
#> Nov21 04:22:39 test :plot `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> Nov21 04:22:39 test :plot total elpsd: 0.87 secs | 10 test plot 5
#> Nov21 04:22:39 test :plot `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
#> simList saved in
#> SpaDES.core:::savedSimEnv()$.sim
#> It will be deleted at next spades() call.