#' @name get_env_bg
#' @title Extract background data for SDM fitting.
#' @description This function extracts background data around known presence records.
#' @param coords Coordinates (long,lat) to extract values for
#' @param env Environmental SpatRaster(s) in any projection
#' @param method Methods for getting bg points. Current option is buffer
#' @param width Numeric or NULL. Width (meters or map units) of buffer. If NULL, uses max dist between nearest occurrences.
#' @param constraint_regions An optional spatialpolygons* object that can be used to limit the selection of background points.
#' @param standardize Logical. If TRUE, the variables will be scaled and centered
#' @returns A list containing 1) the background data (env), 2) the cell indices for which the background was taken (buffer_cells), 3) the environmental means (env_mean; NA if standardization not done), and 4) the environmental standard deviations (env_sds; NA if standardization not done).
#' @note If supplying constraint_regions, any polygons in which the occurrences fall are considered fair game for background selection.
#' This background selection is, however, still limited by the buffer as well.
#' @importFrom terra buffer vect extract
#' @importFrom stats complete.cases sd
#' @export
#' @examples {
#'
#'# load in sample data
#'
#' library(S4DM)
#' library(terra)
#'
#' # occurrence points
#' data("sample_points")
#' occurrences <- sample_points
#'
#' # environmental data
#' env <- rast(system.file('ex/sample_env.tif', package="S4DM"))
#'
#' # rescale the environmental data
#'
#' env <- scale(env)
#'
#' bg_data <- get_env_bg(coords = occurrences,
#' env = env,
#' method = "buffer",
#' width = 100000)
#'
#'
#' }
get_env_bg <- function(coords,
env,
method = "buffer",
width = NULL,
constraint_regions = NULL,
standardize = TRUE) {
#check for bad coords
if(max(coords[,1]) > 180 | min(coords[,1]) < -180){
message("Problematic coords")
}
if(max(coords[,2]) > 90 | min(coords[,2]) < -90){
message("Problematic coords")
}
#Convert to sf
coords <- st_as_sf(x = coords,
coords = c(1,2))
st_crs(coords) <- st_crs("WGS84")
#convert to env raster projection
coords <-
coords %>%
st_transform(crs = st_crs(env))
#set buffer size based on coordinate distances if distance null
if(is.null(width)){
dists <- st_distance(coords)
#width <- max(dists[which(dists > 0)]) #commenting this out because I don't remember why I had that > 0 in there...
width <- max(dists) %>% as.numeric()
rm(dists)
}
#make buffer
#this is faster than st_buffer, so using this
buff <- buffer(x = vect(coords),
width = width)
#Optionally, limit by polygons supplied
if(!is.null(constraint_regions)){
#convert to env raster projection
constraint_regions <-
constraint_regions %>%
st_transform(crs = st_crs(env)) %>%
st_make_valid()
suppressWarnings(
buff <- st_intersection(x = buff %>%
st_as_sf(),
y = constraint_regions[coords,]) %>% vect()
)
} # end constraint region bit
env_vals <- extract(x = env,
y = buff,
cells=TRUE,
ID=FALSE)
# toss and cells that have NA values
env_vals <- env_vals[complete.cases(env_vals),,drop=FALSE]
# output should be a (1) the environmental variables returned and (2) a vector of cell IDS in the buffers.
buffer_cells <- env_vals$cell
# remove the cell column now that it isn't needed
env_vals$cell <- NULL
#scale and center if needed
if(standardize){
env_mean <- colMeans(env_vals)
env_sd <- apply(X = env_vals,MARGIN = 2,FUN = sd)
env_vals <- rescale_w_objects(data = env_vals,
mean_vector = env_mean,
sd_vector = env_sd)
}else{
# set as NA if scaling not done
env_mean <- NA
env_sd <- NA
}
return(test <- list(env = env_vals,
bg_cells = buffer_cells,
env_mean = env_mean,
env_sd = env_sd))
}# end fx
#' @name rescale_w_objects
#' @title Rescale a dataset using vectors of means and SDs
#' @author Brian Maitner
#' @param data dataframe or matrix for rescaling
#' @param mean_vector vector of means to use for rescaling. Should be one value for each column in the data
#' @param sd_vector vector of sds to use for rescaling. Should be one value for each column in the data
#' @description
#' A little function to rescale data using vectors of means and sds
#' @keywords internal
rescale_w_objects <- function(data, mean_vector, sd_vector){
#?sweep #option
# out <- sweep(data, 2L,mean_vector , "-") |>
# sweep(2L,sd_vector , "/")
out <- t((t(data) - mean_vector)/sd_vector)
return(out)
}
#' @name descale_w_objects
#' @title Return scaled variables to the original scale using means and SDs
#' @author Brian Maitner
#' @param data dataframe or matrix for rescaling
#' @param mean_vector vector of means to use for rescaling. Should be one value for each column in the data
#' @param sd_vector vector of sds to use for rescaling. Should be one value for each column in the data
#' @description
#' A little function to rescale data using vectors of means and sds
#' @keywords internal
descale_w_objects <- function(data, mean_vector, sd_vector){
#?sweep #option
# out <- sweep(2L,sd_vector , "*") |>
# sweep(data, 2L,mean_vector , "+")
out <- t((t(data) * sd_vector) + mean_vector)
return(out)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.