Loops: what are they and why use them?

  • fundamental programming units (most languages have them)
  • used to repeat a set of instructions, without “duplicating” code
  • often used in ecology to iterate something over “time”
    • usually, each ‘time-step’ depends on the previous one. Note in the examples below, how we start an age object at 1, and increment it at each step of time, or t. In both cases time and t are the loop counters, but only in the second case is the counter being effectively “used” inside the loop.

Let’s tear it apart and understand each individual part:

  • Setting up (sometimes required), initializing
  • deciding on bounds and intermediates or “step”
    • lower bound = 1 to upper bound = 10
    • here step is 1 (i.e., 1, 2, 3, 4, … 10)
  • content (what is this loop going to do?)

In both cases, we have to: - initialise a storage vector - define time boundaries - define the step, or incremental unit (in this case implicit) - define the content of the for-loop that is going to be iterated

From loops to events

  • In R, we try to avoid loops because:
    • they are slow
    • they make code harder to share amongst users
  • It’s easy to think about “events” in ecology

In SpaDES, events are first defined, then scheduled to happen at a particular point in time:

Loops in R

As you can see, event execution and scheduling in SpaDES have the same fundamental components of a for-loop: initialize, bounds, step, content

Loops (AKA events) in SpaDES

  • This creates a queue – a list of events that need to occur

Why contain the iterated code in a function?

  • iterated code remains isolated from execution and scheduling - cleaner, more organised
  • easier to share
  • easier to change and update - modular!

Exercise 1. Make your first module

Exercise 1.1. Creating a new module, understanding module scripts

  1. Start by opening a new .R script, where you load the necessary libraries and that will serve as your “user-interface” or SpaDES “controller” script - I like to call it global.R
  2. Define the directories
  3. Create a new module in the module path
  • Two template scripts were created: an .R (will contain module code) and .Rmd (will contain module documentation and examples)
  • Folders for data, R code and test code were also created, along with citation, license and README files

/!\ Atention: running newModule twice will overwrite any changes! /!\

  1. Now manually open the .R and .Rmd scripts
  • First part of loop.R contains metadata, the second part contains event execution and scheduling functions, and the third part contains event functions (content).
  • The loop.Rmd file is a template for documenting the module.

Exercise 1.2. Coding a module

We will first built the module “skeleton” and then define its parameters and eventual inputs/outpupts.

  1. Skip to the doEvent function
  • doEvent is the core of any SpaDES module
  • It is where events are executed and scheduled
  • When modules are created with newModule, doEvent is automatically suffixed with the module name (in this case “loop”, so doEvent.loop) - /!\ this is very important /!\
  1. Add event code and remove unnecessary events
  • the template contains event “slots” for 5 different events: init, plot, save, event1 and event2
  • init is mandatory - /!\ never EVER remove it, or change its name /!\

Can you see where initialize, bounds, step, content are?

  1. Define parameters
  • In SpaDES, parameters can be “global” (of type .<param_name.) or module specific

  • Parameters do not participate in the flow of information/data between modules

  • Parameters can be changed by the user at the higher level (i.e. without changing the module code in the .R script)

  • What do you think can be a parameter in our case?

  • Parameters are defined in definedModule, using the defineParameter function

  • This part of the module is the metadata, containing important information about the module

  • It also indicates to other modules what to expect as its inputs and outputs

  • Time boundaries do not need to be defined as parameters - they have their own special objects

  1. Define inputs/outputs
  • Inputs and outputs, unlike parameters, are objects that establish links between modules, and between the user and modules

  • They are always contained in the simList object

  • A good way of thinking about what input and output objects are is: sim$outputs <- sim$inputs

  • do we have any inputs? What about outputs?

  • Input and output objects are also defined in defineModule using the expectsInput and createsOutput functions

  1. Complete metadata, and define the parameter, expectedInputs and createdOutputs
  • Don’t forget to complete the remaining metadata like authorship, essential keywords, time units, etc.
  • /!\ time units need to be correctly defined, as they will affect how modules are linked /!\
  • /!\ remember to declare package dependecies /!\
  • When you are done, don’t forget to save the loop.R file!

Exercise 1.3. Run simulations, check the event queue and module diagrams

Now let’s give our loop.Rmd an example - let’s set up the “simulation” run. 1. Check the event queue before and after running spades 2. Produce module diagrams before running spades 3. Run the “simulation” 4. Compare with outputs produced by the “normal” loop

Note that mySimOut is a pointer to the updated/changed mySim not a true new simList object

Exercise 1.4. Make it even more SpaDESy

Notice that below the doEvent.loop function there are templates for other funcitons that can be used inside the events. Keeping the code inside these functions increases modularity and flexibility, as functions are self-contained.

  1. Make separate functions to be used in the init and the addOneYear events.

NOTE: We present above two different ways of specifying a function. One always passed the sim object to the function and return the sim oject modified. The second returns the results of a function to the sim object as a new object “in” it.

  1. Now you’ll need to adapt the code inside doEvent.loop so that the appropriate functions are called inside their respective events