Code
<- 1
a <- SpaDES.core::simInit(objects = list(a = a))
sim $a sim
[1] 1
Eliot McIntire
November 20, 2024
See Barebones R script for the code shown in this chapter
We have seen functions called .inputObjects
and reproducible::prepInputs
that help deal with module inputs (Inputs Tip 6.1). We will show these used within a SpaDES module.
The inputs of a SpaDES module can be any R object, and should be specified in the inputObjects
section of the metadata if it is needed for the module to run. All inputs should be used in the sim
using e.g., sim$
somewhere in the module.
There are several ways to get objects into the simList
:
User passes during simInit
:
using the objects
argument (if it is an object);
using the inputs
argument (if it is from disk);
using the params
argument;
Developer creates defaults and specifies them in defineParameter()
and .inputObjects
;
A different module creates them prior to the running of this module.
Ultimately, it is the last of these that is the power of SpaDES. i.e., modularity.
simInit
A user can directly pass objects into the simInit
and these will be put into the simList
or do pass them via an .rds
file
[1] 1
Because parameters are usually module-specific, and need to be passed to with reference to a module. “Global” parameters are the exception to this rule:
[1] 1
To pass parameters to a module, we go back to out simple module and make a minor change:
Now we open My_linear_model.R
and add the following
… to the module metadata section for parameters. Remember to save the file after you’re done.
Now run the the module:
.inputObjects
For every Input that is specified in the metadata, the module developer has the option of specifying a default. In R, functions can be given defaults when they are defined like this:
[1] 6.893804
This works for only the simplest cases. In the case of a module, objects can be arbitrarily complicated and so this approach will not be suitable.
Instead, there is a function that is called every time a module is initialized (i.e. by simInit()
) where a developer can put anything they want to specify as defaults. It is generally most useful to use if (!SpaDES.core::suppliedElsewhere("obj", sim))
i.e., if the object isn’t in sim
, then give it a value.
.inputObjects
exampleIn the Biomass_core module (this is an implementation of the LANDIS-II Biomass Succession Extension v3.2), there are many Inputs as defined in the metadata. The module needs each one of these to work.
The developers have created a .inputObjects
function that will fill in these Inputs with defaults if the user hasn’t supplied them (using !SpaDES.core::suppliedElsewhere()
).
We will look at a few examples in this module: Biomass_core::.inputObjects.
some GIS tests that evaluate whether 2 objects are in the same CRS (i.e., they need to be the same projection, etc., for this module to work)
if an object is missing, it may make sense to fill in the details with parameters from the Internet.
an object called studyArea
. The developer tests whether it exists and creates an error if it does not exist.
.inputObjects
, why don’t we just write if (!is.null(sim$y))
? See ?SpaDES.core::suppliedElsewhere
Using the My_linear_model shown above, try running simulations where you pass different values to the length
parameter
Tip: have a look at the params
argument of SpaDES.core::simInitAndSpades()
a <- 1
sim <- SpaDES.core::simInit(objects = list(a = a))
sim$a
b <- 1
tf <- tempfile(fileext = ".rds")
saveRDS(b, file = tf)
sim <- SpaDES.core::simInit(inputs = data.frame(object = "b", file = tf))
sim$b
c <- 1
sim <- SpaDES.core::simInit(params = list(.globals = list(c = c)))
SpaDES.core::params(sim)$.globals$c
modulePath <- "~/SpaDES_book/NewModuleIntro/NewModule"
SpaDES.core::newModule(name = "My_linear_model", path = modulePath, open = FALSE,
events = list(
init = {
x <- rnorm(P(sim)$length)
y <- x + rnorm(P(sim)$length)
# fit a linear model
model <- lm(y ~ x)
}
))
out2 <- SpaDES.core::simInitAndSpades(modules = "My_linear_model",
paths = list(modulePath = modulePath))
params(out2) # can you find the length parameter?
rnormMean5 <- function(n = 1) { # the n = 1 is the default value
rnorm(n = n, mean = 5)
}
rnormMean5() # can be run without any arguments