[1] 1
6 Providing Module Inputs
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.
6.1 How to supply Inputs
There are several ways to get objects into the simList:
User passes during
simInit:using the
objectsargument (if it is an object);using the
inputsargument (if it is from disk);using the
paramsargument;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.
6.1.1 During 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
Code
b <- 1
tf <- tempfile(fileext = ".rds")
saveRDS(b, file = tf)
sim <- SpaDES.core::simInit(inputs = data.frame(object = "b", file = tf))
sim$b[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:
Code
[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
Code
defineParameter("length", "integer", 10L, 5L, 100L,
"Number of values to generate")… to the module metadata section for parameters. Remember to save the file after you’re done.
Code
defineModule(
<...>
parameters = bindrows(
# here
<...>
)
<...>
)Now run the the module:
Code
out2 <- SpaDES.core::simInitAndSpades(modules = "My_linear_model",
paths = list(modulePath = modulePath))
params(out2) # can you find the length parameter?
6.1.2 .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:
Code
rnormMean5 <- function(n = 1) { # the n = 1 is the default value
rnorm(n = n, mean = 5)
}
rnormMean5() # can be run without any arguments[1] 2.542349
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.
6.1.2.1 Advanced .inputObjects example
In 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.
6.2 Questions
- In
.inputObjects, why don’t we just writeif (!is.null(sim$y))? See?SpaDES.core::suppliedElsewhere
- It turns out that other modules may create this object “after” this module is run, and this test will fail.
6.3 Try on your own
Using the My_linear_model shown above, try running simulations where you pass different values to the
lengthparameterTip: have a look at the
paramsargument ofSpaDES.core::simInitAndSpades()
6.4 See also
6.5 Barebones R script
Code
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
d <- 1
sim <- SpaDES.core::simInit(params = list(.globals = list(d = d)))
SpaDES.core::params(sim)$.globals$d
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