Code
# create some data
<- rnorm(10)
x <- x + rnorm(10)
y # fit a linear model
<- lm(y ~ x)
model
# plot the fit
plot(model)
Eliot McIntire
September 18, 2024
See Barebones R script for the code shown in this chapter
SpaDES modules are comprised of R code that has metadata and that gets put into functions. With this in mind, we can start with some simple R code.
Looking at this code above, we can imagine that the first 3 lines are conceptually different – fit a dummy model – from the last line – visualize it. Let’s put these into 2 “modules”, and then run them in sequence.
We use the SpaDES.core
function newModule()
to make a new module.
Step 1 – move the code to an “init” event. This “init” event is a convention that SpaDES uses. A module must always have an “init” event. This is the only code that is “definitely run” in a module.
Require::Require(c("reproducible", "SpaDES.core (>= 2.1.5)"),
repos = c("https://predictiveecology.r-universe.dev", getOption("repos")))
# make a module
modulePath <- "~/SpaDES_book/NewModuleIntro/NewModule"
SpaDES.core::newModule(name = "My_linear_model",
path = modulePath,
open = FALSE,
events = list(
init = {
x <- rnorm(10)
y <- x + rnorm(10)
# fit a linear model
model <- lm(y ~ x)
}
))
You may get a warning related with the testthat
R package not being available. This is fine.1
Keeping objects
For now, we just say, if you want to keep an object, assign it to “sim”. We will explain this in much more detail later. Here, we want to keep the model
that we fit. But we don’t care about the x
and y
. So we assign the model
to sim
.
How would we run this “init” event? We use simInit
, which parses the code (like loading a library or sourcing a function) then spades
, which executes it.
We can look at the output:
We can also look at “what ran”… or in other words, what was our workflow. Of course, this will just be one “user-created” event (there are 4 “SpaDES-created” events … we may use them later, ignore for now)
We have our first “simple workflow”! 1 chunk of code :)
simInit()
before spades()
SpaDES.core::simInit()
always has to be called before SpaDES.core::spades()
.
simInit()
will initialise the workflow simList
object that spades()
uses to execute the workflow.
See Chapter 7 for more detail about the simList
Our next step is to divide the pieces into conceptual chunks. Let’s now create a new module for the plot
… a “visualization module”.
And now we run both together. We name them both in the module
argument. We are using simInitAndSpades
which is a shortcut to running the two functions separately.
We can look at the output again:
This time, there is an extra event that happened. We now have a workflow of 2 events.
Make a new module. Make it really simple. Run it with simInitAndSpades
as in the above examples.
sim$
for an object that will be outputted.Make a second new module that uses the sim$
object.
sim$
Make a third new module that uses the sim$
object from the 2nd module.
# create some data
x <- rnorm(10)
y <- x + rnorm(10)
# fit a linear model
model <- lm(y ~ x)
# plot the fit
plot(model)
Require::Require(c("reproducible", "SpaDES.core (>= 2.1.5)"),
repos = c("https://predictiveecology.r-universe.dev", getOption("repos")))
# make a module
modulePath <- "~/SpaDES_book/NewModuleIntro/NewModule"
SpaDES.core::newModule(name = "My_linear_model",
path = modulePath,
open = FALSE,
events = list(
init = {
x <- rnorm(10)
y <- x + rnorm(10)
# fit a linear model
model <- lm(y ~ x)
}
))
# make a module
SpaDES.core::newModule(name = "My_linear_model",
path = modulePath, open = FALSE,
events = list(
init = {
x <- rnorm(10)
y <- x + rnorm(10)
# fit a linear model
sim$model <- lm(y ~ x) # <--------- change to sim$
}
))
out <- simInit(modules = "My_linear_model",
paths = list(modulePath = modulePath))
out <- spades(out)
out$model
completed(out)
SpaDES.core::newModule("visualize", path = modulePath, open = FALSE,
events = list(
init = {
plot(sim$model)
}
)
)
out2 <- simInitAndSpades(module = c("My_linear_model", "visualize"),
paths = list(modulePath = modulePath))
out2$model
completed(out2)
We use the testthat
package to automate module and code testing. By default, newModule()
creates a tests
folder inside the module folder that is designed to be used with testthat
, hence the warning if this package has not been installed.↩︎