This is built with `spread2()`

and is still experimental.
This one differs from other attempts in that it treats the advection and
dispersal as mathematical vectors that are added together.
They are "rounded" to pixel centres.

```
spread3(
start,
rasQuality,
rasAbundance,
advectionDir,
advectionMag,
meanDist,
dispersalKernel = "exponential",
sdDist = 1,
plot.it = 2,
minNumAgents = 50,
verbose = getOption("LandR.verbose", 0),
saveStack = NULL,
skipChecks = FALSE
)
```

- start
Raster indices from which to initiate dispersal

- rasQuality
A raster with habitat quality. Currently, must be scaled from 0 to 1, i.e., a probability of "settling"

- rasAbundance
A raster where each pixel represents the number of "agents" or pseudo-agents contained. This number of agents, will be spread horizontally, and distributed from each pixel that contains a non-zero non NA value.

- advectionDir
A single number or

`RasterLayer`

in degrees from North = 0 (though it will use radians if all values are`abs(advectionDir) > 2 * pi)`

. This indicates the direction of advective forcing (i.e., wind).- advectionMag
A single number or

`RasterLayer`

in distance units of the`rasQuality`

, e.g., meters, indicating the relative forcing that will occur. It is imposed on the total event, i.e., if the`meanDist`

is`10000`

, and`advectionMag`

is`5000`

, then the expected distance (i.e.,`63%`

of agents) will have settled by`15000`

map units.- meanDist
A single number indicating the mean distance parameter in map units (not pixels), for a negative exponential distribution dispersal kernel (e.g.,

`dexp`

). This will mean that`63%`

of agents will have settled at this`meanDist`

(still experimental).- dispersalKernel
One of either

`"exponential"`

or`"weibull"`

.- sdDist
A single number indicating the

`sd`

parameter of a two-parameter`dispersalKernel`

. Defaults to`1`

, which is the same as the`exponential`

distribution.- plot.it
Numeric. With increasing numbers above 0, there will be plots produced during iterations. Currently, only 0, 1, or 2+ are distinct.

- minNumAgents
Single numeric indicating the minimum number of agents to consider all dispersing finished. Default is 50.

- verbose
Numeric. With increasing numbers above 0, there will be more messages produced. Currently, only 0, 1, or 2+ are distinct.

- saveStack
If provided as a character string, it will save each iteration as part of a

`rasterStack`

to disk upon exit.- skipChecks
Logical. If

`TRUE`

, assertions will be skipped (faster, but could miss problems)

A `data.table`

with all information used during the spreading

```
## these tests are fairly heavy, so don't run during automated tests
if (interactive()) {
#########################################################
# Simple case, no variation in rasQuality, numeric advectionDir and advectionMag
#########################################################
library(raster)
library(quickPlot)
maxDim <- 10000
ras <- raster::raster(extent(c(0, maxDim, 0, maxDim)), res = 100, vals = 0)
rasQuality <- raster(ras)
rasQuality[] <- 1
rasAbundance <- raster(rasQuality)
rasAbundance[] <- 0
# startPixel <- middlePixel(rasAbundance)
startPixel <- sample(seq(ncell(rasAbundance)), 30)
rasAbundance[startPixel] <- 1000
advectionDir <- 70
advectionMag <- 4 * res(rasAbundance)[1]
meanDist <- 2600
# Test the dispersal kernel -- create a function
plotDispersalKernel <- function(out, meanAdvectionMag) {
out[, disGroup := round(distance / 100) * 100]
freqs <- out[, .N, by = "disGroup"]
freqs[, `:=`(cumSum = cumsum(N), N = N)]
Plot(freqs$disGroup, freqs$cumSum, addTo = "CumulativeNumberSettled",
title = "Cumulative Number Settled") # can plot the distance X number
abline(v = meanAdvectionMag + meanDist)
newTitle <- "Number Settled By Distance"
Plot(freqs$disGroup, freqs$N, addTo = gsub(" ", "", newTitle),
title = newTitle) # can plot the distance X number
abline(v = meanAdvectionMag + meanDist)
# should be 0.63:
freqs[disGroup == meanAdvectionMag + meanDist, cumSum] / tail(freqs,1)[, cumSum]
mtext(side = 3, paste("Average habitat quality: ",
round(mean(rasQuality[], na.rm = TRUE), 2)),
outer = TRUE, line = -2, cex = 2)
}
dev() # don't use Rstudio windows, which is very slow
clearPlot()
out <- spread3(rasAbundance = rasAbundance,
rasQuality = rasQuality,
advectionDir = advectionDir,
advectionMag = advectionMag,
meanDist = meanDist, verbose = 2,
plot.it = 2)
plotDispersalKernel(out, advectionMag)
#########################################################
### The case of variable quality raster
#########################################################
if (require(sf) && require(fasterize)) {
library(SpaDES.tools)
mask <- fasterize(st_as_sf(a), ras) # faster than raster::rasterize
rasQuality <- raster(system.file("extdata", "rasQuality.tif", package = "SpaDES.tools"))
crs(rasQuality) <- readRDS(system.file("extdata", "targetCRS.rds", package = "SpaDES.tools"))
rasQuality[is.na(mask)] <- NA
# rescale so min is 0.75 and max is 1
rasQuality[] <- rasQuality[] / (maxValue(rasQuality) * 4 ) + 1/4
rasAbundance <- raster(rasQuality)
rasAbundance[] <- 0
startPixel <- sample(seq(ncell(rasAbundance)), 300)
rasAbundance[startPixel] <- 1000
advectionDir <- 75
advectionMag <- 4 * res(rasAbundance)[1]
meanDist <- 2600
clearPlot()
out <- spread3(rasAbundance = rasAbundance,
rasQuality = rasQuality,
advectionDir = advectionDir,
advectionMag = advectionMag,
meanDist = meanDist, verbose = 2,
plot.it = 1)
if (interactive()) {
plotDispersalKernel(out, advectionMag)
}
}
###############################################################################
### The case of variable quality raster, raster for advectionDir & advectionMag
###############################################################################
library(raster)
library(quickPlot)
library(SpaDES.tools)
maxDim <- 10000
ras <- raster(extent(c(0, maxDim, 0, maxDim)), res = 100, vals = 0)
rasQuality <- raster(ras)
rasQuality[] <- 1
rasAbundance <- raster(rasQuality)
rasAbundance[] <- NA
# startPixel <- middlePixel(rasAbundance)
startPixel <- sample(seq(ncell(rasAbundance)), 25)
rasAbundance[startPixel] <- 1000
# raster for advectionDir
advectionDir <- raster(system.file("extdata", "advectionDir.tif", package = "SpaDES.tools"))
crs(advectionDir) <- crs(rasQuality)
# rescale so min is 0.75 and max is 1
advectionDir[] <- advectionDir[] / (maxValue(advectionDir)) * 180
# raster for advectionMag
advectionMag <- raster(system.file("extdata", "advectionMag.tif", package = "SpaDES.tools"))
crs(advectionMag) <- crs(rasQuality)
# rescale so min is 0.75 and max is 1
advectionMag[] <- advectionMag[] / (maxValue(advectionMag)) * 600
out <- spread3(rasAbundance = rasAbundance,
rasQuality = rasQuality,
advectionDir = advectionDir,
advectionMag = advectionMag,
meanDist = meanDist, verbose = 2,
plot.it = 1)
if (interactive()) {
dev() # don't use Rstudio windows, which is very slow
clearPlot()
Plot(advectionDir, title = "Wind direction", cols = "Reds")
Plot(advectionMag, title = "Wind speed", cols = "Blues")
plotDispersalKernel(out, mean(advectionMag[]))
Plot(rasAbundance, addTo = "rasAbundance", cols = "black", title = "")
}
#########################################
# save iterations to a stack to make animated GIF
########################################
tmpStack <- raster::rasterTmpFile("stackToAnimate")
out <- spread3(rasAbundance = rasAbundance,
rasQuality = rasQuality,
advectionDir = advectionDir,
advectionMag = advectionMag,
meanDist = 2600, verbose = 2,
plot.it = 0, saveStack = tmpStack)
## This animates the series of images into an animated GIF
if (require(animation, quietly = TRUE)) {
out2 <- raster::stack(tmpStack)
gifName <- file.path(tempdir(), "animation.gif")
saveGIF(interval = 0.1, movie.name = gifName, expr = {
for (i in seq(numLayers(out2))) plot(out2[[i]])
})
}
}
```