SpaDES logo

This package allows implementation a variety of simulation-type models, with a focus on spatially explicit models. The core simulation components are built upon a discrete event simulation framework that facilitates modularity, and easily enables the user to include additional functionality by running user-built simulation modules. Included are numerous tools to visualize various spatial data formats, as well as non-spatial data. Much work has been done to speed up the core of the DES, with current benchmarking as low as 56 microseconds overhead for each event (including scheduling, sorting event queue, spawning event etc.) or 38 microseconds if there is no sorting (i.e., no sorting occurs under simple conditions). Under most event conditions, therefore, the DES itself will contribute very minimally compared to the content of the events, which may often be milliseconds to many seconds each event.

Bug reports: <https://github.com/PredictiveEcology/SpaDES.core/issues>

Module repository: <https://github.com/PredictiveEcology/SpaDES-modules>

Wiki: <https://github.com/PredictiveEcology/SpaDES/wiki>

------------------------------------------------------------------------------------------

1 Spatial discrete event simulation (`SpaDES`)

A collection of top-level functions for doing spatial discrete event simulation.

1.1 Simulations

There are two workhorse functions that initialize and run a simulation, and third function for doing multiple spades runs:

[simInit()]Initialize a new simulation
[spades()]Run a discrete event simulation
`experiment`In `SpaDES.experiment` package. Run multiple [spades()] calls
`experiment2`In `SpaDES.experiment` package. Run multiple [spades()] calls

1.2 Events

Within a module, important simulation functions include:

[scheduleEvent()]Schedule a simulation event
[scheduleConditionalEvent()]Schedule a conditional simulation event
`removeEvent`Remove an event from the simulation queue (not yet implemented)

2 The `simList` object class

The principle exported object class is the `simList`. All `SpaDES` simulations operate on this object class.

[simList()]The 'simList' class

------------------------------------------------------------------------------------------

3 `simList` methods

Collections of commonly used functions to retrieve or set slots (and their elements) of a [simList()] object are summarized further below.

3.1 Simulation parameters

[globals()]List of global simulation parameters.
[params()]Nested list of all simulation parameter.
[P()]Namespaced version of [params()] (i.e., do not have to specify module name).

3.2 loading from disk, saving to disk

[inputs()]List of loaded objects used in simulation. (advanced)
[outputs()]List of objects to save during simulation. (advanced)

3.3 objects in the `simList`

[ls()], [objects()]Names of objects referenced by the simulation environment.
[ls.str()]List the structure of the simList objects.
[objs()]List of objects referenced by the simulation environment.

3.4 Simulation paths

Accessor functions for the `paths` slot and its elements.

[cachePath()]Global simulation cache path.
[modulePath()]Global simulation module path.
[inputPath()]Global simulation input path.
[outputPath()]Global simulation output path.
[rasterPath()]Global simulation temporary raster path.
[paths()]Global simulation paths (cache, modules, inputs, outputs, rasters).

3.5 Simulation times

Accessor functions for the `simtimes` slot and its elements.

[time()]Current simulation time, in units of longest module.
[start()]Simulation start time, in units of longest module.
[end()]Simulation end time, in units of longest module.
[times()]List of all simulation times (current, start, end), in units of longest module..

3.6 Simulation event queues

Accessor functions for the `events` and `completed` slots. By default, the event lists are shown when the `simList` object is printed, thus most users will not require direct use of these methods.

[events()]Scheduled simulation events (the event queue). (advanced)
[current()]Currently executing event. (advanced)
[completed()]Completed simulation events. (advanced)
[elapsedTime()]The amount of clock time that modules & events use

3.7 Modules, dependencies, packages

Accessor functions for the `depends`, `modules`, and `.loadOrder` slots. These are included for advanced users.

[depends()]List of simulation module dependencies. (advanced)
[modules()]List of simulation modules to be loaded. (advanced)
[packages()]Vector of required R libraries of all modules. (advanced)

3.8 `simList` environment

The [simList()] has a slot called `.xData` which is an environment. All objects in the `simList` are actually in this environment, i.e., the `simList` is not a `list`. In R, environments use pass-by-reference semantics, which means that copying a `simList` object using normal R assignment operation (e.g., `sim2 <- sim1`), will not copy the objects contained within the `.xData` slot. The two objects (`sim1` and `sim2`) will share identical objects within that slot. Sometimes, this not desired, and a true copy is required.

[envir()]Access the environment of the simList directly (advanced)
[copy()]Deep copy of a simList. (advanced)

3.9 Checkpointing

Accessor methodModuleDescription
[checkpointFile()]`checkpoint`Name of the checkpoint file. (advanced)
[checkpointInterval()]`checkpoint`The simulation checkpoint interval. (advanced)

3.10 Progress Bar

[progressType()]`.progress`Type of graphical progress bar used. (advanced)
[progressInterval()]`.progress`Interval for the progress bar. (advanced)

------------------------------------------------------------------------------------------

4 Module operations

4.1 Creating, distributing, and downloading modules

Modules are the basic unit of `SpaDES`. These are generally created and stored locally, or are downloaded from remote repositories, including our [SpaDES-modules](https://github.com/PredictiveEcology/SpaDES-modules) repository on GitHub.

[checksums()]Verify (and optionally write) checksums for a module's data files.
[downloadModule()]Open all modules nested within a base directory.
[getModuleVersion()]Get the latest module version # from module repository.
[newModule()]Create new module from template.
[newModuleDocumentation()]Create empty documentation for a new module.
[openModules()]Open all modules nested within a base directory.
[moduleMetadata()]Shows the module metadata.
[zipModule()]Zip a module and its associated files.

4.2 Module metadata

Each module requires several items to be defined. These comprise the metadata for that module (including default parameter specifications, inputs and outputs), and are currently written at the top of the module's `.R` file.

[defineModule()]Define the module metadata
[defineParameter()]Specify a parameter's name, value and set a default
[expectsInput()]Specify an input object's name, class, description, `sourceURL` and other specifications
[createsOutput()]Specify an output object's name, class, description and other specifications

There are also accessors for many of the metadata entries:

[timeunit()]Accesses metadata of same name
[citation()]Accesses metadata of same name
[documentation()]Accesses metadata of same name
[reqdPkgs()]Accesses metadata of same name
[inputObjects()]Accesses metadata of same name
[outputObjects()]Accesses metadata of same name

4.3 Module dependencies

Once a set of modules have been chosen, the dependency information is automatically calculated once simInit is run. There are several functions to assist with dependency information:

[depsEdgeList()]Build edge list for module dependency graph
[depsGraph()]Build a module dependency graph using `igraph`

------------------------------------------------------------------------------------------

5 Module functions

*A collection of functions that help with making modules can be found in the suggested `SpaDES.tools` package, and are summarized below.*

5.1 Spatial spreading/distances methods

Spatial contagion is a key phenomenon for spatially explicit simulation models. Contagion can be modelled using discrete approaches or continuous approaches. Several `SpaDES.tools` functions assist with these:

[SpaDES.tools::adj()]An optimized (i.e., faster) version of [raster::adjacent()]
[SpaDES.tools::cir()]Identify pixels in a circle around a [`SpatialPoints*()`][sp::SpatialPoints-class] object
[`directionFromEachPoint()`][SpaDES.tools::distanceFromEachPoint]Fast calculation of direction and distance surfaces
[SpaDES.tools::distanceFromEachPoint()]Fast calculation of distance surfaces
[SpaDES.tools::rings()]Identify rings around focal cells (e.g., buffers and donuts)
[SpaDES.tools::spokes()]Identify outward radiating spokes from initial points
[SpaDES.tools::spread()]Contagious cellular automata
[SpaDES.tools::spread2()]Contagious cellular automata, different algorithm, more robust
[SpaDES.tools::wrap()]Create a torus from a grid

5.2 Spatial agent methods

Agents have several methods and functions specific to them:

[SpaDES.tools::crw()]Simple correlated random walk function
[SpaDES.tools::heading()]Determines the heading between `SpatialPoints*`
[quickPlot::makeLines()]Makes `SpatialLines` object for, e.g., drawing arrows
[`move()`][SpaDES.tools::crw]A meta function that can currently only take "crw"
[`specificNumPerPatch()`][SpaDES.tools::specnumperpatch-probs]Initiate a specific number of agents per patch

5.3 GIS operations

In addition to the vast amount of GIS operations available in R (mostly from contributed packages such as `sp`, `raster`, `maps`, `maptools` and many others), we provide the following GIS-related functions:

[equalExtent()]Assess whether a list of extents are all equal

5.4 'Map-reduce'--type operations

These functions convert between reduced and mapped representations of the same data. This allows compact representation of, e.g., rasters that have many individual pixels that share identical information.

[SpaDES.tools::rasterizeReduced()]Convert reduced representation to full raster.

5.5 Colors in `Raster*` objects

We likely will not want the default colours for every map. Here are several helper functions to add to, set and get colors of `Raster*` objects:

[`setColors()`][quickPlot::getSetColors]Set colours for plotting `Raster*` objects
[getColors()]Get colours in a `Raster*` objects
[divergentColors()]Create a colour palette with diverging colours around a middle

5.6 Random Map Generation

It is often useful to build dummy maps with which to build simulation models before all data are available. These dummy maps can later be replaced with actual data maps.

[SpaDES.tools::gaussMap()]Creates a random map using Gaussian random fields
[SpaDES.tools::randomPolygons()]Creates a random polygon with specified number of classes

5.7 Checking for the existence of objects

`SpaDES` modules will often require the existence of objects in the `simList`. These are helpers for assessing this:

[checkObject()]Check for a existence of an object within a `simList`
[Require::checkPath()]Checks the specified filepath for formatting consistencies

5.8 SELES-type approach to simulation

These functions are essentially skeletons and are not fully implemented. They are intended to make translations from SELES (https://www.gowlland.ca/). You must know how to use SELES for these to be useful:

[`agentLocation()`][SpaDES.tools::SELESagentLocation]Agent location
[SpaDES.tools::initiateAgents()]Initiate agents into a `SpatialPointsDataFrame`
[`numAgents()`][SpaDES.tools::SELESnumAgents]Number of agents
[`probInit()`][SpaDES.tools::SELESprobInit]Probability of initiating an agent or event
[`transitions()`][SpaDES.tools::SELEStransitions]Transition probability

5.9 Miscellaneous

Functions that may be useful within a `SpaDES` context:

[SpaDES.tools::inRange()]Test whether a number lies within range [a,b]
[layerNames()]Get layer names for numerous object classes
[numLayers()]Return number of layers
[paddedFloatToChar()]Wrapper for padding (e.g., zeros) floating numbers to character

------------------------------------------------------------------------------------------

6 Caching simulations and simulation components

*Simulation caching uses the `reproducible` package.*

Caching can be done in a variety of ways, most of which are up to the module developer. However, the one most common usage would be to cache a simulation run. This might be useful if a simulation is very long, has been run once, and the goal is just to retrieve final results. This would be an alternative to manually saving the outputs.

See example in [spades()], achieved by using `cache = TRUE` argument.

[reproducible::Cache()]Caches a function, but often accessed as arg in [spades()]
[`showCache()`][reproducible::cache-tools]Shows information about the objects in the cache
[`clearCache()`][reproducible::cache-tools]Removes objects from the cache
[`keepCache()`][reproducible::cache-tools]Keeps only the objects described

A module developer can build caching into their module by creating cached versions of their functions.

------------------------------------------------------------------------------------------

7 Plotting

Much of the underlying plotting functionality is provided by quickPlot.

There are several user-accessible plotting functions that are optimized for modularity and speed of plotting:

Commonly used:

[Plot()]The workhorse plotting function

Simulation diagrams:

[eventDiagram()]Gantt chart representing the events in a completed simulation.
[moduleDiagram()]Network diagram of simplified module (object) dependencies.
[objectDiagram()]Sequence diagram of detailed object dependencies.

Other useful plotting functions:

[clearPlot()]Helpful for resolving many errors
[clickValues()]Extract values from a raster object at the mouse click location(s)
[clickExtent()]Zoom into a raster or polygon map that was plotted with [Plot()]
[clickCoordinates()]Get the coordinates, in map units, under mouse click
[dev()]Specify which device to plot on, making a non-RStudio one as default
[newPlot()]Open a new default plotting device
[rePlot()]Replots all elements of device for refreshing or moving plot

------------------------------------------------------------------------------------------

8 File operations

In addition to R's file operations, we have added several here to aid in bulk loading and saving of files for simulation purposes:

[loadFiles()]Load simulation objects according to a filelist
[rasterToMemory()]Read a raster from file to RAM
[saveFiles()]Save simulation objects according to outputs and params

------------------------------------------------------------------------------------------

9 Sample modules included in package

Several dummy modules are included for testing of functionality. These can be found with `file.path(find.package("SpaDES.core"), "sampleModules")`.

`randomLandscapes`Imports, updates, and plots several raster map layers
`caribouMovement`A simple agent-based (a.k.a., individual-based) model
`fireSpread`A simple model of a spatial spread process

------------------------------------------------------------------------------------------

10 Package options

`SpaDES` packages use the following [options()] to configure behaviour:

  • `spades.browserOnError`: If `TRUE`, the default, then any error rerun the same event with `debugonce` called on it to allow editing to be done. When that browser is continued (e.g., with 'c'), then it will save it reparse it into the simList and rerun the edited version. This may allow a spades call to be recovered on error, though in many cases that may not be the correct behaviour. For example, if the simList gets updated inside that event in an iterative manner, then each run through the event will cause that iteration to occur. When this option is `TRUE`, then the event will be run at least 3 times: the first time makes the error, the second time has `debugonce` and the third time is after the error is addressed. `TRUE` is likely somewhat slower.

  • `reproducible.cachePath`: The default local directory in which to cache simulation outputs. Default is a temporary directory (typically `/tmp/RtmpXXX/SpaDES/cache`).

  • `spades.inputPath`: The default local directory in which to look for simulation inputs. Default is a temporary directory (typically `/tmp/RtmpXXX/SpaDES/inputs`).

  • `spades.debug`: The default debugging value `debug` argument in `spades()`. Default is `TRUE`.

  • `spades.lowMemory`: If true, some functions will use more memory efficient (but slower) algorithms. Default `FALSE`.

  • `spades.moduleCodeChecks`: Should the various code checks be run during `simInit`. These are passed to codetools::checkUsage. Default is given by the function, plus these :`list(suppressParamUnused = FALSE, suppressUndefined = TRUE, suppressPartialMatchArgs = FALSE, suppressNoLocalFun = TRUE, skipWith = TRUE)`.

  • `spades.modulePath`: The default local directory where modules and data will be downloaded and stored. Default is a temporary directory (typically `/tmp/RtmpXXX/SpaDES/modules`).

  • `spades.moduleRepo`: The default GitHub repository to use when downloading modules via `downloadModule`. Default `"PredictiveEcology/SpaDES-modules"`.

  • `spades.nCompleted`: The maximum number of completed events to retain in the `completed` event queue. Default `1000L`.

  • `spades.outputPath`: The default local directory in which to save simulation outputs. Default is a temporary directory (typically `/tmp/RtmpXXX/SpaDES/outputs`).

  • `spades.recoveryMode`: If this a numeric > 0 or TRUE, then the discrete event simulator will take a snapshot of the objects in the simList that might change (based on metadata `outputObjects` for that module), prior to initiating every event. This will allow the user to be able to recover in case of an error or manual interruption (e.g., `Esc`). If this is numeric, a copy of that number of "most recent events" will be maintained so that the user can recover and restart > 1 event in the past, i.e., redo some of the "completed" events. Default is `TRUE`, i.e., it will keep the state of the `simList` at the start of the current event. This can be recovered with `restartSpades` and the differences can be seen in a hidden object in the stashed `simList.` There is a message which describes how to find that.

  • `spades.switchPkgNamespaces`: Should the search path be modified to ensure a module's required packages are listed first? Default `FALSE` to keep computational overhead down. If `TRUE`, there should be no name conflicts among package objects, but it is much slower, especially if the events are themselves fast.

  • `spades.tolerance`: The default tolerance value used for floating point number comparisons. Default `.Machine$double.eps^0.5`.

  • `spades.useragent`: The default user agent to use for downloading modules from GitHub.com. Default `"https://github.com/PredictiveEcology/SpaDES"`.

See also

[spadesOptions()]

Author

Maintainer: Alex M Chubaty achubaty@for-cast.ca (ORCID)

Authors:

Other contributors: