Faster function for determining the cells of the 4, 8 or bishop
neighbours of the cells. This is a hybrid function that uses
matrix for small numbers of loci (<1e4) and data.table for larger numbers of loci
adj(
x = NULL,
cells,
directions = 8,
sort = FALSE,
pairs = TRUE,
include = FALSE,
target = NULL,
numCol = NULL,
numCell = NULL,
match.adjacent = FALSE,
cutoff.for.data.table = 2000,
torus = FALSE,
id = NULL,
numNeighs = NULL,
returnDT = FALSE
)SpatRaster object for which adjacency will be calculated.
vector of cell numbers for which adjacent cells should be found. Cell numbers start with 1 in the upper-left corner and increase from left to right and from top to bottom.
the number of directions in which cells should be connected:
4 (rook's case), 8 (queen's case), or "bishop" to connect
cells with one-cell diagonal moves.
Or a neighbourhood matrix (see Details).
logical. Whether the outputs should be sorted or not, using cell ids
of the from cells (and to cells, if match.adjacent
is TRUE).
logical. If TRUE, a matrix of pairs of adjacent cells is returned.
If FALSE, a vector of cells adjacent to cells is returned
logical. Should the focal cells be included in the result?
a vector of cells that can be spread to. This is the inverse of a mask.
numeric indicating number of columns in the raster.
Using this with numCell is a bit faster execution time.
numeric indicating number of cells in the raster.
Using this with numCol is a bit faster execution time.
logical. Should the returned object be the same as
raster::adjacent.
Default FALSE, which is faster.
numeric. If the number of cells is above this value,
the function uses data.table internally, which is faster
with large numbers of cells. Default is 2000, which appears
to be the turning point where data.table becomes faster.
This selects the internal strategy only; it does not
affect the class of the returned object (see returnDT).
Logical. Should the spread event wrap around to the other side of the raster?
Default is FALSE.
numeric If not NULL (default), then function will return "id" column.
A numeric scalar, indicating how many neighbours to return. Must be
less than or equal to directions; which neighbours are random
with equal probabilities.
A logical. If TRUE, the result is returned as a data.table,
whichever internal strategy was used to build it. Up to version
2.1.2 this was honoured only when length(cells) was greater
than cutoff.for.data.table; below that the argument was
ignored and a matrix was returned. The first call per session
that lands in that window warns.
If returnDT is TRUE, a data.table; otherwise a matrix, except
for pairs = FALSE combined with match.adjacent = TRUE, which returns a
bare vector of the unique to cells.
The columns will be one or more of id, from, to: to always;
from if pairs is TRUE; id if id was supplied.
The variable output is done to minimize coercion to maintain speed.
Between 4x (large number loci) to 200x (small number loci) speed gains over
adjacent in raster package. There is some extra speed gain if
NumCol and NumCells are passed rather than a raster.
Efficiency gains come from:
use data.table internally
no need to remove NAs because wrapped or outside points are just removed directly with data.table
use data.table to sort and fast select (though not fastest possible)
don't make intermediate objects; just put calculation into return statement
The steps used in the algorithm are:
Calculate indices of neighbouring cells
Remove "to" cells that are
< 1 or > numCells (i.e., they are above or below raster), using a single modulo
calculation
where the modulo of "to" cells is equal to 1 if "from" cells are 0 (wrapped right to left)
or where the modulo of the "to" cells is equal to 0 if "from" cells are 1 (wrapped left to right)
library(terra)
#> terra 1.9.50
#>
#> Attaching package: ‘terra’
#> The following object is masked from ‘package:SpaDES.tools’:
#>
#> wrap
origDTThreads <- data.table::setDTthreads(2L)
origNcpus <- options(Ncpus = 2L)
a <- rast(ext(0, 1000, 0, 1000), resolution = 1)
sam <- sample(1:ncell(a), 1e4)
numCol <- ncol(a)
numCell <- ncell(a)
adj.new <- adj(numCol = numCol, numCell = numCell, cells = sam, directions = 8)
adj.new <- adj(numCol = numCol, numCell = numCell, cells = sam, directions = 8,
include = TRUE)
# clean up
data.table::setDTthreads(origDTThreads)
options(Ncpus = origNcpus)