-
Notifications
You must be signed in to change notification settings - Fork 0
Description
#' Creates a terra raster stack of a specified number and size of clumped binary rasters
#' Simulates presence/absence species distributions
#' Useful for generating binary feature layers for testing
#'
#' @param nrows The number of rows in each raster
#' @param ncols The number of columns in each raster
#' @param clump The degree of clumping (0 = random, 1 = max clumping). The returned rasters are very sensitive to this
#' @param numrasters The number of raster layers to create
#' @param layername base name for each raster layer (will be suffixed with 1:numrasters)
#'
#' @return A terra raster stack of a specified number and size of clumped binary rasters
#'
#' @example
#' \dontrun{
#' binary_features <- create_binary_rasters(nrows = 100, ncols = 100, clump = 0.8, numrasters = 10, layername = "spp")
#' plot(binary_features)
#' }
create_binary_rasters <- function(nrows = 100, ncols = 100, clump = 0.8, numrasters = 1, layername = "layer") {
prob <- 0.5 # Probability for binary raster (best results with 0.5)
Helper function to get all factors of a number
factors <- function(x) {
factors <- NULL
for (i in 1:x) {
if ((x %% i) == 0) {
factors <- c(factors, i)
}
}
return(factors)
}
Function to create a single binary raster with clumping
make_one_raster <- function() {
# Generate random binary values
vals <- tibble::tibble(
value = sample(c(0, 1),
size = nrows * ncols,
replace = TRUE,
prob = c(prob, 1 - prob))
)
# Convert to matrix and then to raster
mat <- matrix(vals$value, nrow = nrows, ncol = ncols, byrow = TRUE)
r <- terra::rast(mat)
# Calculate scaling factor for clumping based on factors of min dimension
scaling <- quantile(x = factors(min(nrows, ncols)), probs = clump, type = 3)
# If scaling > 1, aggregate and disaggregate to create clumping
if(scaling > 1){
r <- terra::aggregate(r, fact = scaling, fun = "mean")
r <- terra::disagg(r, fact = scaling, method = "bilinear")
r <- (r > prob) * 1 # Convert back to binary
}
return(r)
}
Create a list of rasters using purrr::map
raster_list <- purrr::map(1:numrasters, ~make_one_raster())
Stack rasters into a single SpatRaster object
raster_stack <- terra::rast(raster_list)
Name each layer using the provided text string and a number
names(raster_stack) <- paste0(layername, seq_len(numrasters))
return(raster_stack)
}