# testing functions
test_ENMevaluation <- function(e, alg, parts, tune.args, nparts.occs, nparts.bg, type = "") {
tune.tbl <- expand.grid(tune.args, stringsAsFactors = FALSE)
test_that("ENMevaluation object and slots exist", {
expect_true(!is.null(e))
expect_true(!is.null(e@algorithm))
expect_true(!is.null(e@tune.settings))
expect_true(!is.null(e@partition.method))
expect_true(!is.null(e@results))
expect_true(!is.null(e@results.partitions))
expect_true(!is.null(e@models))
expect_true(!is.null(e@predictions))
expect_true(terra::nlyr(e@predictions) > 0)
expect_true(!is.null(e@occs))
expect_true(!is.null(e@occs.grp))
expect_true(!is.null(e@bg))
expect_true(!is.null(e@bg.grp))
expect_true(!is.null(e@overlap))
expect_equal(length(slotNames(e)), 20)
expect_equal(slotNames(e),
c("algorithm", "tune.settings", "partition.method",
"partition.settings", "other.settings", "doClamp",
"clamp.directions", "results", "results.partitions",
"models", "variable.importance", "predictions", "taxon.name",
"occs", "occs.testing", "occs.grp", "bg", "bg.grp",
"overlap", "rmm"))
})
test_that("Data in ENMevaluation object slots have correct form", {
# algorithm
expect_true(e@algorithm == alg)
# partition method
expect_true(e@partition.method == parts)
# these checks relate to tune.args, which may be NULL
if(!is.null(tune.args)) {
# tune.settings
expect_true(all(as.data.frame(e@tune.settings[,1:ncol(tune.tbl)]) == tune.tbl))
# nrow of results
expect_true(nrow(e@results) == nrow(tune.tbl))
# tune.args column values are concat of tuning parameters columns
# expect_true(all(apply(e@results[names(tune.args.ls[[m]])], 1, paste, collapse = "_") == as.character(e@results$tune.args)))
# number of models
expect_true(length(e@models) == nrow(tune.tbl))
}
# number of rows for occs matches occs.grp
expect_true(nrow(e@occs) == length(e@occs.grp))
# number of rows for bg matches bg.grp
expect_true(nrow(e@bg) == length(e@bg.grp))
# no overlap is calculated for no tuning or BIOCLIM
if(length(e@overlap) > 0) {
# both indices exist for overlap
expect_true(length(e@overlap) == 2)
# number of rows of overlap D matches tune.args
expect_true(nrow(e@overlap$D) == nrow(tune.tbl))
# number of rows of overlap I matches tune.args
expect_true(nrow(e@overlap$I) == nrow(tune.tbl))
}else{
# no overlap matrix
expect_true(length(e@overlap) == 0)
}
})
test_that("Records with missing environmental values were removed", {
expect_true(sum(is.na(e@occs)) == 0)
expect_true(sum(is.na(e@bg)) == 0)
})
test_that("Number of partitions is correct", {
expect_true(length(unique(e@occs.grp)) == nparts.occs)
expect_true(length(unique(e@bg.grp)) == nparts.bg)
})
test_that("Results table for partitions has correct form", {
if(parts == "none") {
expect_true(nrow(e@results.partitions) == 0)
}else{
expect_true(nrow(e@results.partitions) == nparts.occs * nrow(tune.tbl))
if(parts != "testing") {
expect_true(max(e@results.partitions$fold) == nparts.occs)
}else{
expect_true(max(e@results.partitions$fold) == 0)
}
# jackknife has NAs for cbi.val
if(parts == "jackknife" | !requireNamespace("ecospat", quietly = TRUE)) {
expect_true(sum(is.na(e@results.partitions)) == nrow(e@results.partitions))
}else{
expect_true(sum(is.na(e@results.partitions)) == 0)
}
}
})
}
test_clamp <- function(envs, occs.z, bg.z, categoricals) {
# use occurrences as reference environmental values for clamping
# restrict to small subset in Amazon to ensure lots of extrapolation for
# transfers
p.z <- occs.z[8:13,-1:-2]
# remove cats from dataset
if(!is.null(categoricals)) {
envs <- envs[[-which(names(envs) %in% categoricals)]]
p.z <- p.z |> dplyr::select(-categoricals)
}
# for sub clamping
z <- 2:4
# p.z <- dplyr::bind_rows(occs.z, bg.z)[,-1:-2]
none <- envs
all <- clamp.vars(orig.vals = envs, ref.vals = p.z)
left <- clamp.vars(orig.vals = envs, ref.vals = p.z, right = "none",)
right <- clamp.vars(orig.vals = envs, ref.vals = p.z, left = "none",)
subboth <- clamp.vars(orig.vals = envs, ref.vals = p.z, left = names(envs)[z],
right = names(envs)[z])
subleft <- clamp.vars(orig.vals = envs, ref.vals = p.z, right = "none",
left = names(envs)[z])
subright <- clamp.vars(orig.vals = envs, ref.vals = p.z, left = "none",
right = names(envs)[z])
# clamps.envs <- list(none=none, all=all, left=left, right=right, subboth=subboth, subleft=subleft, subright=subright)
# enm <- lookup.enm(e@algorithm)
# m <- e@models[[1]]
# clamp.envs.p <- lapply(clamps.envs, function(x) enm@predict(m, x, list(doClamp = FALSE, pred.type = "cloglog")))
# combs <- expand.grid(x=names(clamp.envs.p), y=names(clamp.envs.p), stringsAsFactors = FALSE) |> dplyr::filter(x != y)
test_that("Clamped rasters are different from each other", {
expect_true(all(terra::minmax(none) != terra::minmax(all)))
expect_true(all(terra::minmax(none)[1,] != terra::minmax(left)[1,]))
expect_true(all(terra::minmax(none)[2,] == terra::minmax(left)[2,]))
expect_true(all(terra::minmax(none)[1,] == terra::minmax(right)[1,]))
expect_true(all(terra::minmax(none)[2,] != terra::minmax(right)[2,]))
expect_true(all(terra::minmax(none)[,z] != terra::minmax(subboth)[,z]))
expect_true(all(terra::minmax(none)[,-z] == terra::minmax(subboth)[,-z]))
expect_true(all(terra::minmax(none)[1,z] != terra::minmax(subleft)[1,z]))
expect_true(all(terra::minmax(none)[2,z] == terra::minmax(subleft)[2,z]))
expect_true(all(terra::minmax(none)[1,-z] == terra::minmax(subleft)[1,-z]))
expect_true(all(terra::minmax(none)[2,-z] == terra::minmax(subleft)[2,-z]))
expect_true(all(terra::minmax(none)[1,z] == terra::minmax(subright)[1,z]))
expect_true(all(terra::minmax(none)[2,z] != terra::minmax(subright)[2,z]))
expect_true(all(terra::minmax(none)[1,-z] == terra::minmax(subright)[1,-z]))
expect_true(all(terra::minmax(none)[2,-z] == terra::minmax(subright)[2,-z]))
# for(i in 1:nrow(combs)) {
# if(canExtrapolate == TRUE) {
# expect_false(all(abs(terra::minmax(clamp.envs.p[[combs[i,1]]] - clamp.envs.p[[combs[i,2]]])) < 1e-7))
# }else{
# expect_true(all(abs(terra::minmax(clamp.envs.p[[combs[i,1]]] - clamp.envs.p[[combs[i,2]]])) < 1e-7))
# }
# }
})
# clamps.df <- lapply(clamps.envs, function(x) terra::values(x))
# clamp.df.p <- lapply(clamps.df, function(x) enm@predict(m, x, list(doClamp = FALSE, pred.type = "cloglog")))
# test_that("Clamped data frames are different from each other", {
# for(i in 1:nrow(combs)) {
# if(canExtrapolate == TRUE) {
# expect_false(isTRUE(all.equal(clamp.df.p[[combs[i,1]]], clamp.df.p[[combs[i,2]]])))
# }else{
# expect_true(isTRUE(all.equal(clamp.df.p[[combs[i,1]]], clamp.df.p[[combs[i,2]]])))
# }
# }
# })
}
test_ENMnulls <- function(e, ns, no.iter, alg, parts, mod.settings, nparts.occs, nparts.bg, n.sims, type = "") {
mod.settings.tbl <- expand.grid(mod.settings)
test_that("ENMnulls object and slots exist", {
expect_true(!is.null(ns))
expect_true(!is.null(ns@null.algorithm))
expect_true(!is.null(ns@null.mod.settings))
expect_true(!is.null(ns@null.partition.method))
expect_true(!is.null(ns@null.partition.settings))
expect_true(!is.null(ns@null.other.settings))
expect_true(!is.null(ns@null.no.iter))
expect_true(!is.null(ns@null.results))
expect_true(!is.null(ns@null.results.partitions))
expect_true(!is.null(ns@null.emp.results))
expect_true(!is.null(ns@emp.occs))
expect_true(!is.null(ns@emp.occs.grp))
expect_true(!is.null(ns@emp.bg))
expect_true(!is.null(ns@emp.bg.grp))
})
test_that("Data in ENMnulls object slots have correct form", {
# algorithm
expect_true(ns@null.algorithm == alg)
# partition method
expect_true(ns@null.partition.method == parts)
# mod.settings
if(ncol(mod.settings.tbl) > 1) {
expect_true(all(ns@null.mod.settings[,1:ncol(mod.settings.tbl)] == mod.settings.tbl))
}else{
expect_true(as.character(ns@null.mod.settings[,1]) == mod.settings.tbl)
}
# no. of iterations
expect_true(ns@null.no.iter == no.iter)
# number of rows in results table
expect_true(nrow(ns@null.results) == no.iter)
# number of rows in results table for partitions
if(ns@null.partition.method == "none") {
expect_true(nrow(ns@null.results.partitions) == 0)
}else{
expect_true(nrow(ns@null.results.partitions) == no.iter * nparts.occs)
}
# number of rows in empirical vs null results table
expect_true(nrow(ns@null.emp.results) == 6)
# check that not all empirical results are NA
expect_true(sum(apply(ns@null.emp.results[,2:ncol(ns@null.emp.results)], 2, function(x) sum(is.na(x)))) !=
nrow(ns@null.emp.results) * (ncol(ns@null.emp.results)-1))
# check that tables match
expect_true(all(ns@emp.occs == e@occs))
expect_true(all(ns@emp.bg == e@bg))
expect_true(all(ns@emp.occs.grp == e@occs.grp))
})
test_that("Data in ENMnulls object slots are not NA (except CBI, which can be NA due to low data)", {
expect_true(all(apply(ns@null.results |> dplyr::select(!starts_with("cbi")), 2, function(x) sum(is.na(x))) == 0))
if(ns@null.partition.method != "none") expect_true(all(apply(ns@null.results |> dplyr::select(!starts_with("cbi")), 2, function(x) sum(is.na(x))) == 0))
})
}
#' @title Unit tests for ENMevaluation plotting functions
#' @description All parameters are self-explanatory except the following.
#' Anything with the prefix ".z" is a data frame with longitude, latitude,
#' and the environmental predictor variable values. Argument "plot.sel" controls
#' whether testing happens for the histogram function, the plotting function, or both
#' (some implementations do not work with one or the other). Argument "bg.sel" controls
#' whether tests should be done with ref.data as "bg" or not (non-spatial implementations
#' cannot be plotted with ref.data as )
test_evalplot.stats <- function(e) {
test_stats <- function(x, stats) {
if(e@partition.method == "testing") {
y <- 2
z <- c("metric", "value")
}else{
y <- 5
z <- c("metric", "avg", "sd", "lower", "upper")
}
test_that("Outputs for evalplot.stats have correct form", {
expect_true(ncol(x) == ncol(e@tune.settings) + y)
expect_true(nrow(x) == nrow(e@tune.settings) * length(stats))
expect_true(all(unique(x$metric) == stats))
n <- (ncol(e@tune.settings)+1):(ncol(x))
expect_true(all(names(x)[n] == z))
})
}
if(e@partition.method == "none") {
stat1 <- "auc.train"
stat2 <- c("auc.train", "cbi.train")
}else{
stat1 <- "auc.val"
stat2 <- c("auc.val", "or.10p")
}
if(e@algorithm == "bioclim") {
x.var <- color.var <- "tails"
}else if(e@algorithm %in% c("maxnet", "maxent.jar")) {
x.var <- "rm"
color.var <- "fc"
}
# defaults
evalplot.stats(e, stats = stat1, x.var = x.var, color.var = color.var, dodge = FALSE, error.bars = FALSE, facet.labels = NULL, metric.levels = NULL, return.tbl = TRUE) |> test_stats(stat1)
# two stats
evalplot.stats(e, stats = stat2, x.var = x.var, color.var = color.var, dodge = FALSE, error.bars = FALSE, facet.labels = NULL, metric.levels = NULL, return.tbl = TRUE) |> test_stats(stat2)
# dodge
evalplot.stats(e, stats = stat1, x.var = x.var, color.var = color.var, dodge = TRUE, error.bars = FALSE, facet.labels = NULL, metric.levels = NULL, return.tbl = TRUE) |> test_stats(stat1)
# error bars
evalplot.stats(e, stats = stat1, x.var = x.var, color.var = color.var, dodge = FALSE, error.bars = TRUE, facet.labels = NULL, metric.levels = NULL, return.tbl = TRUE) |> test_stats(stat1)
# facet labels
evalplot.stats(e, stats = stat1, x.var = x.var, color.var = color.var, dodge = FALSE, error.bars = TRUE, facet.labels = paste0(stat1), metric.levels = NULL, return.tbl = TRUE) |> test_stats(stat1)
evalplot.stats(e, stats = stat2, x.var = x.var, color.var = color.var, dodge = FALSE, error.bars = TRUE, facet.labels = paste0(stat2), metric.levels = NULL, return.tbl = TRUE) |> test_stats(stat2)
# metric levels
evalplot.stats(e, stats = stat1, x.var = x.var, color.var = color.var, dodge = FALSE, error.bars = TRUE, facet.labels = NULL, metric.levels = stat1, return.tbl = TRUE) |> test_stats(stat1)
evalplot.stats(e, stats = stat2, x.var = x.var, color.var = color.var, dodge = FALSE, error.bars = TRUE, facet.labels = NULL, metric.levels = rev(stat2), return.tbl = TRUE) |> test_stats(stat2)
}
test_evalplot.envSim.hist <- function(e, occs.z, bg.z, occs.grp, bg.grp, bg.sel = 1, occs.testing.z = NULL) {
test_hist <- function(i) {
test_that("Outputs for evalplot.envSim.hist have correct form", {
expect_true(ncol(i) == 2)
expect_true(names(i)[1] == "partition")
})
}
# with ENMevaluation object
evalplot.envSim.hist(e = e, ref.data = "occs", return.tbl = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_hist()
if(bg.sel == 1) {
evalplot.envSim.hist(e = e, ref.data = "bg", return.tbl = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_hist()
}
evalplot.envSim.hist(e = e, ref.data = "occs", envs.vars = c("bio1", "bio12"), return.tbl = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_hist()
evalplot.envSim.hist(e = e, ref.data = "occs", hist.bins = 50, return.tbl = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_hist()
# with occs and bg data
evalplot.envSim.hist(occs.z = occs.z, bg.z = bg.z, occs.grp = occs.grp, bg.grp = bg.grp, ref.data = "occs", return.tbl = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_hist()
if(bg.sel == 1) {
evalplot.envSim.hist(occs.z = occs.z, bg.z = bg.z, occs.grp = occs.grp, bg.grp = bg.grp, ref.data = "bg", return.tbl = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_hist()
}
evalplot.envSim.hist(occs.z = occs.z, bg.z = bg.z, occs.grp = occs.grp, bg.grp = bg.grp, ref.data = "occs", envs.vars = c("bio1", "bio12"), return.tbl = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_hist()
evalplot.envSim.hist(occs.z = occs.z, bg.z = bg.z, occs.grp = occs.grp, bg.grp = bg.grp, ref.data = "occs", hist.bins = 50, return.tbl = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_hist()
}
test_evalplot.envSim.map <- function(e, envs, occs.z, bg.z, occs.grp, bg.grp, bg.sel = 1, occs.testing.z = NULL) {
test_map <- function(i) {
test_that("Outputs for evalplot.envSim.map have correct form", {
if(inherits(i, "SpatRaster")) {
if(is.null(occs.testing.z)) {
expect_true(length(unique(e@occs.grp)) == terra::nlyr(i))
}else{
expect_true(2 == terra::nlyr(i))
}
}else{
expect_true(ncol(i) == 4)
expect_true(names(i)[1] == "x")
expect_true(names(i)[2] == "y")
expect_true(names(i)[3] == "ras")
}
})
}
# with ENMevaluation object
evalplot.envSim.map(e = e, envs = envs, ref.data = "occs", return.tbl = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_map()
evalplot.envSim.map(e = e, envs = envs, ref.data = "occs", return.ras = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_map()
evalplot.envSim.map(e = e, envs = envs, ref.data = "occs", envs.vars = c("bio1","bio12"), return.tbl = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_map()
evalplot.envSim.map(e = e, envs = envs, ref.data = "occs", envs.vars = c("bio1","bio12"), return.ras = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_map()
# with buffer
evalplot.envSim.map(e = e, envs = envs, ref.data = "occs", bb.buf = 5, return.tbl = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_map()
evalplot.envSim.map(e = e, envs = envs, ref.data = "occs", bb.buf = 5, return.ras = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_map()
# with occs and bg data
evalplot.envSim.map(occs.z = occs.z, occs.grp = occs.grp, envs = envs, ref.data = "occs", bb.buf = 5, return.ras = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_map()
if(bg.sel == 1) {
evalplot.envSim.map(bg.z = bg.z, bg.grp = bg.grp, envs = envs, ref.data = "bg", bb.buf = 5, return.ras = TRUE, quiet = TRUE, occs.testing.z = occs.testing.z) |> test_map()
}
}
test_evalplot.nulls <- function(ns) {
test_nulls <- function(x, stats) {
test_that("Outputs for evalplot.nulls have correct form", {
expect_true(length(x) == 2)
expect_true(all(names(x) == c("null.avgs", "empirical.results")))
expect_true(ncol(x[[1]]) == 2)
expect_true(ncol(x[[2]]) == 2)
expect_true(all(names(x[[1]]) == c("metric", "avg")))
expect_true(all(names(x[[2]]) == c("metric", "avg")))
expect_true(nrow(x[[1]]) == ns@null.no.iter * length(stats))
expect_true(all(unique(x[[1]]$metric) == stats))
expect_true(all(unique(x[[2]]$metric) == stats))
})
}
if(ns@null.partition.method == "none") {
stat1 <- "auc.train"
if(requireNamespace("ecospat", quietly = TRUE)) stat2 <- c("auc.train", "cbi.train") else stat2 <- "auc.train"
}else{
stat1 <- "auc.val"
stat2 <- c("auc.val", "or.10p")
}
for(i in c("histogram", "violin")) {
# one metric
evalplot.nulls(ns, stat1, plot.type = i, facet.labels = NULL, metric.levels = NULL, return.tbl = TRUE) |> test_nulls(stat1)
# two metrics
evalplot.nulls(ns, stat2, plot.type = i, facet.labels = NULL, metric.levels = NULL, return.tbl = TRUE) |> test_nulls(stat2)
# one metric labels
evalplot.nulls(ns, stat1, plot.type = i, facet.labels = paste0(stat1, "2"), metric.levels = NULL, return.tbl = TRUE) |> test_nulls(stat1)
# two metrics labels
evalplot.nulls(ns, stat2, plot.type = i, facet.labels = paste0(stat2, "2"), metric.levels = NULL, return.tbl = TRUE) |> test_nulls(stat2)
# one metric levels
evalplot.nulls(ns, stat1, plot.type = i, facet.labels = NULL, metric.levels = stat1, return.tbl = TRUE) |> test_nulls(stat1)
# two metrics levels
evalplot.nulls(ns, stat2, plot.type = i, facet.labels = NULL, metric.levels = stat2, return.tbl = TRUE) |> test_nulls(stat2)
}
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.