skip_if(!is_slendr_env_present())
init_env(quiet = TRUE)
test_that("forward and backward time model objects are equivalent", {
map <- world(xrange = c(0, 100), yrange = c(0, 100), landscape = "blank")
# forward direction
p1 <- population(name = "p1", time = 1, N = 1, center = c(1, 1), radius = 1, map = map)
p2 <- population(name = "p2", parent = p1, time = 2, N = 1, center = c(1, 1), radius = 1)
p3 <- population(name = "p3", parent = p1, time = 3, N = 1, center = c(1, 1), radius = 1)
p4 <- population(name = "p4", parent = p3, time = 4, N = 1, center = c(1, 1), radius = 1)
p5 <- population(name = "p5", parent = p2, time = 5, N = 1, center = c(1, 1), radius = 1)
geneflows <- gene_flow(p1, p2, start = 3, end = 4, rate = 0.5, overlap = FALSE)
forward <- compile_model(
path = file.path(tempdir(), "tmp-forward"),
populations = list(p1, p2, p3, p4, p5), gene_flow = geneflows,
generation_time = 1, resolution = 1,
overwrite = TRUE, force = TRUE,
competition = 1, mating = 1, dispersal = 1,
simulation_length = 5
)
# backward direction
p1 <- population(name = "p1", time = 5, N = 1, center = c(1, 1), radius = 1, map = map)
p2 <- population(name = "p2", parent = p1, time = 4, N = 1, center = c(1, 1), radius = 1)
p3 <- population(name = "p3", parent = p1, time = 3, N = 1, center = c(1, 1), radius = 1)
p4 <- population(name = "p4", parent = p3, time = 2, N = 1, center = c(1, 1), radius = 1)
p5 <- population(name = "p5", parent = p2, time = 1, N = 1, center = c(1, 1), radius = 1)
geneflows <- gene_flow(p1, p2, start = 3, end = 2, rate = 0.5, overlap = FALSE)
backward <- compile_model(
path = file.path(tempdir(), "tmp-backward"),
populations = list(p1, p2, p3, p4, p5), gene_flow = geneflows,
generation_time = 1, resolution = 1,
overwrite = TRUE, force = TRUE,
competition = 1, mating = 1, dispersal = 1
)
expect_true(all.equal(forward$splits[, grep("_orig", colnames(forward$splits), value = TRUE, invert = TRUE)],
backward$splits[, grep("_orig", colnames(backward$splits), value = TRUE, invert = TRUE)]))
expect_true(all.equal(forward$geneflow[, grep("_orig", colnames(forward$geneflow), value = TRUE, invert = TRUE)],
backward$geneflow[, grep("_orig", colnames(forward$geneflow), value = TRUE, invert = TRUE)]))
expect_true(all.equal(forward$maps[, c("pop", "pop_id", "time_gen")],
backward$maps[, c("pop", "pop_id","time_gen")]))
components <- c("generation_time", "resolution", "world")
expect_true(all(sapply(components, function(i) all.equal(forward[[i]], backward[[i]]))))
})
test_that("forward and backward models yield the same simulation result", {
map <- readRDS("map.rds")
# forward simulation ------------------------------------------------------
p1 <- population(name = "pop1", N = 100, time = 1, radius = 600000, center = c(10, 25), map = map)
p2 <- population(name = "pop2", parent = p1, time = 10, N = 100, center = c(10, 25), radius = 300000) %>%
move(trajectory = list(c(25, 25), c(40, 30), c(40, 40), c(50, 50)), start = 11, end = 200, snapshots = 30)
p3 <- population(name = "pop3", parent = p2, time = 200, N = 100, polygon = list(c(-10, 50), c(10, 50), c(20, 53), c(40, 60), c(40, 70), c(-10, 65)))
p4 <- population(name = "pop4", parent = p2, time = 200, N = 100, polygon = list(c(-10, 35), c(20, 37), c(25, 40), c(30, 45), c(10, 50), c(-10, 45)))
p5 <- population(name = "pop5", parent = p1, time = 300, N = 100, center = c(10, 25), radius = 300000) %>%
move(trajectory = list(c(-5, 33), c(-5, 40)), start = 301, end = 400, snapshots = 20)
geneflow <- list(
gene_flow(from = p5, to = p4, rate = 0.2, start = 310, end = 350, overlap = F),
gene_flow(from = p5, to = p3, rate = 0.3, start = 340, end = 480, overlap = F)
)
forward <- compile_model(
path = file.path(tempdir(), "tmp-forward"),
populations = list(p1, p2, p3, p4, p5),
gene_flow = geneflow,
generation_time = 1,
resolution = 10000,
overwrite = TRUE, force = TRUE,
competition = 100e3, mating = 100e3, dispersal = 100e3,
simulation_length = 480
)
# backward simulation -----------------------------------------------------
p1 <- population(name = "pop1", N = 100, time = 480, radius = 600000, center = c(10, 25), map = map)
p2 <- population(name = "pop2", parent = p1, time = 471, N = 100, center = c(10, 25), radius = 300000) %>%
move(trajectory = list(c(25, 25), c(40, 30), c(40, 40), c(50, 50)), start = 470, end = 281, snapshots = 30)
p3 <- population(name = "pop3", parent = p2, time = 281, N = 100, polygon = list(c(-10, 50), c(10, 50), c(20, 53), c(40, 60), c(40, 70), c(-10, 65)))
p4 <- population(name = "pop4", parent = p2, time = 281, N = 100, polygon = list(c(-10, 35), c(20, 37), c(25, 40), c(30, 45), c(10, 50), c(-10, 45)))
p5 <- population(name = "pop5", parent = p1, time = 181, N = 100, center = c(10, 25), radius = 300000) %>%
move(trajectory = list(c(-5, 33), c(-5, 40)), start = 180, end = 81, snapshots = 20)
geneflow <- list(
gene_flow(from = p5, to = p4, rate = 0.2, start = 171, end = 131, overlap = F),
gene_flow(from = p5, to = p3, rate = 0.3, start = 141, end = 1, overlap = F)
)
backward <- compile_model(
path = file.path(tempdir(), "tmp-backward"),
populations = list(p1, p2, p3, p4, p5),
gene_flow = geneflow,
generation_time = 1,
resolution = 10000,
overwrite = TRUE, force = TRUE,
competition = 100e3, mating = 100e3, dispersal = 100e3
)
expect_true(all.equal(forward$splits[, grep("_orig", colnames(forward$splits), value = TRUE, invert = TRUE)],
backward$splits[, grep("_orig", colnames(backward$splits), value = TRUE, invert = TRUE)]))
expect_true(all.equal(forward$geneflow[, grep("_orig", colnames(forward$geneflow), value = TRUE, invert = TRUE)],
backward$geneflow[, grep("_orig", colnames(forward$geneflow), value = TRUE, invert = TRUE)]))
expect_true(all.equal(forward$maps[, c("pop", "pop_id", "time_gen")],
backward$maps[, c("pop", "pop_id","time_gen")]))
components <- c("generation_time", "resolution", "world")
expect_true(all(sapply(components, function(i) all.equal(forward[[i]], backward[[i]]))))
locations_forward <- normalizePath(tempfile(fileext = ".gz"), winslash = "/", mustWork = FALSE)
locations_backward <- normalizePath(tempfile(fileext = ".gz"), winslash = "/", mustWork = FALSE)
# simulation runs are the same
slim(forward, sequence_length = 1, recombination_rate = 0, locations = locations_forward, method = "batch", random_seed = 123, verbose = FALSE)
slim(backward, sequence_length = 1, recombination_rate = 0, locations = locations_backward, method = "batch", random_seed = 123, verbose = FALSE)
# make sure the scripts are the same
f_script <- file.path(forward$path, "script.slim") %>% readLines
b_script <- file.path(backward$path, "script.slim") %>% readLines
expect_equal(f_script, b_script)
# make sure that the simulated location data is the same
f_loc <- suppressMessages(readr::read_tsv(locations_forward))
b_loc <- suppressMessages(readr::read_tsv(locations_backward))
expect_equal(f_loc, b_loc)
})
test_that("forward and backward models yield the same simulation result (nonspatial)", {
# forward simulation ------------------------------------------------------
p1 <- population(name = "pop1", N = 100, time = 1)
p2 <- population(name = "pop2", parent = p1, time = 10, N = 100)
p3 <- population(name = "pop3", parent = p2, time = 200, N = 100)
p4 <- population(name = "pop4", parent = p2, time = 200, N = 100)
p5 <- population(name = "pop5", parent = p1, time = 300, N = 100)
geneflow <- list(
gene_flow(from = p5, to = p4, rate = 0.2, start = 310, end = 350, overlap = F),
gene_flow(from = p5, to = p3, rate = 0.3, start = 340, end = 480, overlap = F)
)
forward <- compile_model(
path = file.path(tempdir(), "tmp-forward"),
populations = list(p1, p2, p3, p4, p5),
gene_flow = geneflow,
generation_time = 1,
overwrite = TRUE, force = TRUE,
simulation_length = 480
)
# backward simulation -----------------------------------------------------
p1 <- population(name = "pop1", N = 100, time = 480)
p2 <- population(name = "pop2", parent = p1, time = 471, N = 100)
p3 <- population(name = "pop3", parent = p2, time = 281, N = 100)
p4 <- population(name = "pop4", parent = p2, time = 281, N = 100)
p5 <- population(name = "pop5", parent = p1, time = 181, N = 100)
geneflow <- list(
gene_flow(from = p5, to = p4, rate = 0.2, start = 171, end = 131, overlap = F),
gene_flow(from = p5, to = p3, rate = 0.3, start = 141, end = 1, overlap = F)
)
backward <- compile_model(
path = file.path(tempdir(), "tmp-backward"),
populations = list(p1, p2, p3, p4, p5),
gene_flow = geneflow,
generation_time = 1,
overwrite = TRUE, force = TRUE,
)
expect_true(all.equal(forward$splits[, grep("_orig", colnames(forward$splits), value = TRUE, invert = TRUE)],
backward$splits[, grep("_orig", colnames(backward$splits), value = TRUE, invert = TRUE)]))
expect_true(all.equal(forward$geneflow[, grep("_orig", colnames(forward$geneflow), value = TRUE, invert = TRUE)],
backward$geneflow[, grep("_orig", colnames(forward$geneflow), value = TRUE, invert = TRUE)]))
expect_true(all.equal(forward$maps[, c("pop", "pop_id", "time_gen")],
backward$maps[, c("pop", "pop_id","time_gen")]))
components <- c("generation_time", "resolution", "world")
expect_true(all(sapply(components, function(i) all.equal(forward[[i]], backward[[i]]))))
# simulation runs are the same
slim(forward, sequence_length = 1, recombination_rate = 0, method = "batch", random_seed = 123, verbose = FALSE)
slim(backward, sequence_length = 1, recombination_rate = 0, method = "batch", random_seed = 123, verbose = FALSE)
# make sure the scripts are the same
f_script <- file.path(forward$path, "script.slim") %>% readLines
b_script <- file.path(backward$path, "script.slim") %>% readLines
expect_equal(f_script, b_script)
# TODO after some output generation is implemented, test equivalence here
})
test_that("move preceding population split results in an error", {
map <- world(xrange = c(0, 100), yrange = c(0, 100), landscape = "blank")
p1 <- population(name = "p1", time = 1, N = 1, center = c(1, 1), radius = 10, map = map)
p2 <- population(name = "p2", parent = p1, time = 10, N = 1, center = c(20, 50), radius = 20)
expect_error(move(p2, trajectory = c(100, 100), start = 3, end = 20, snapshots = 5),
"The new event (.*) pre-dates the last specified active event")
})
test_that("overlaps in time result in an error (forward time)", {
map <- world(xrange = c(0, 100), yrange = c(0, 100), landscape = "blank")
p1 <- population(name = "p1", time = 1, N = 1, center = c(1, 1), radius = 10, map = map)
p2 <- population(name = "p2", parent = p1, time = 10, N = 1, center = c(20, 50), radius = 20) %>%
move(trajectory = c(100, 100), start = 11, end = 20, snapshots = 5)
msg <- "The new event (.*) pre-dates the last specified active event"
# repeating the same move
expect_error(move(p2, trajectory = c(100, 100), start = 10, end = 20, snapshots = 5), msg)
# overlapping time window of the second move
expect_error(move(p2, trajectory = c(100, 100), start = 5, end = 30, snapshots = 5), msg)
# overlapping time window of the following range expansion
expect_error(expand_range(p2, by = 20, start = 5, end = 30, snapshots = 5), msg)
# overlapping time window of the following range change
expect_error(set_range(p2, time = 8, center = c(50, 10), radius = 8), msg)
})
test_that("overlaps in time result in an error (backward time)", {
map <- world(xrange = c(0, 100), yrange = c(0, 100), landscape = "blank")
p1 <- population(name = "p1", time = 100, N = 1, center = c(1, 1), radius = 10, map = map)
p2 <- population(name = "p2", parent = p1, time = 40, N = 1, center = c(20, 50), radius = 20) %>%
move(trajectory = c(100, 100), start = 30, end = 10, snapshots = 5)
msg <- "The new event (.*) pre-dates the last specified active event"
# repeating the same move
expect_error(move(p2, trajectory = c(100, 100), start = 30, end = 10, snapshots = 5), msg)
# overlapping time window of the second move
expect_error(move(p2, trajectory = c(100, 100), start = 25, end = 5, snapshots = 5), msg)
# overlapping time window of the following range expansion
expect_error(expand_range(p2, by = 20, start = 25, end = 5, snapshots = 5), msg)
# overlapping time window of the following range change
expect_error(set_range(p2, time = 15, center = c(50, 10), radius = 8), msg)
})
test_that("resizing of populations is consistent with established population dynamics (forward time)", {
map <- world(xrange = c(0, 100), yrange = c(0, 100), landscape = "blank")
p1 <- population(name = "pop1", map = map, time = 1, N = 500, center = c(10, 25), radius = 300000)
p2 <- population(name = "pop2", parent = p1, time = 10, N = 500, center = c(10, 25), radius = 300000)
msg <- "The new event (.*) pre-dates the last specified active event"
expect_error(resize(p2, N = 10, how = "step", time = 5), msg)
})
test_that("resizing of populations is consistent with established population dynamics (backward time)", {
map <- world(xrange = c(0, 100), yrange = c(0, 100), landscape = "blank")
p1 <- population(name = "pop1", map = map, time = 30000, N = 500, center = c(10, 25), radius = 300000)
p2 <- population(name = "pop2", parent = p1, time = 25000, N = 500, center = c(10, 25), radius = 300000)
msg <- "The new event (.*) pre-dates the last specified active event"
expect_error(resize(p2, N = 10, how = "step", time = 28000), msg)
})
# New tests for time consistency added after re-factoring of event time checks
map <- readRDS("map.rds")
p1 <- population(name = "p1", map = map, time = 100, N = 1, center = c(20, 50), radius = 20)
# ancestral populations
test_that("Overlapping time-windows for ancestral populations are caught", {
expect_error(expand_range(p1, by = 20, start = 120, end = 20, snapshots = 5),
"The new event (.*) falls both before and after")
})
test_that("Older forward event can't follow ancestral population with a higher 'split time'", {
msg <- "The new event (.*) implies a forward time direction but"
expect_error(move(p1, trajectory = c(10, 10), start = 80, end = 90, snapshots = 5), msg)
expect_error(expand_range(p1, by = 1000, start = 80, end = 90, snapshots = 5), msg)
})
test_that("Older backward event can't follow ancestral population with a lower 'split time'", {
msg <- "The new event (.*) implies a backward time direction but"
expect_error(move(p1, trajectory = c(10, 10), start = 120, end = 110, snapshots = 5), msg)
expect_error(expand_range(p1, by = 1000, start = 120, end = 110, snapshots = 5), msg)
})
# daughter populations
# backward model
test_that("Populations can only be created after their parents (backward model)", {
expect_error(population(name = "p2", parent = p1, time = 100, N = 1, center = c(20, 50), radius = 20),
"Population can be only created after its parent")
expect_silent(population(name = "p2", parent = p1, time = 90, N = 1, center = c(20, 50), radius = 20))
})
p2 <- population(name = "p2", parent = p1, time = 98, N = 1, center = c(20, 50), radius = 20)
test_that("Forward time events not allowed for backward models", {
msg <- "The new forward event (.*) is inconsistent with the backward time"
expect_error(move(p2, trajectory = c(10, 10), start = 50, end = 80, snapshots = 5), msg)
expect_error(expand_range(p2, by = 1000, start = 50, end = 80, snapshots = 5), msg)
})
test_that("Backward time events can't predate previous active event for backward models", {
msg <- "The new event (.*) pre-dates"
expect_error(move(p2, trajectory = c(10, 10), start = 150, end = 140, snapshots = 5), msg)
expect_error(expand_range(p2, by = 1000, start = 150, end = 140, snapshots = 5), msg)
})
# forward model
test_that("Populations can only be created after their parents (forward model)", {
expect_error(population(name = "p2", parent = p1, time = 100, N = 1, center = c(20, 50), radius = 20),
"Population can be only created after its parent")
expect_silent(population(name = "p2", parent = p1, time = 90, N = 1, center = c(20, 50), radius = 20))
})
p2 <- population(name = "p2", parent = p1, time = 120, N = 1, center = c(20, 50), radius = 20)
test_that("Backward time events not allowed for forward models", {
msg <- "The new backward event (.*) is inconsistent with the forward time"
expect_error(move(p2, trajectory = c(10, 10), start = 80, end = 50, snapshots = 5), msg)
expect_error(expand_range(p2, by = 1000, start = 80, end = 50, snapshots = 5), msg)
})
test_that("Forward time events can't predate previous active event for forward models", {
msg <- "The new event (.*) pre-dates"
expect_error(move(p2, trajectory = c(10, 10), start = 40, end = 50, snapshots = 5), msg)
expect_error(expand_range(p2, by = 1000, start = 40, end = 50, snapshots = 5), msg)
})
# Test consistency with scheduled removal times
test_that("Events can't be scheduled after population removal", {
msg <- "The specified event time (.*) is not consistent with the scheduled removal .*"
forward <- population(name = "forward", map = map, time = 1, N = 1, center = c(20, 50), radius = 20, remove = 50)
expect_error(move(forward, trajectory = c(5, 5), start = 5, end = 80, snapshots = 3), paste0(msg, "given the assumed forward time"))
expect_error(move(forward, trajectory = c(5, 5), start = 60, end = 80, snapshots = 3), paste0(msg, "given the assumed forward time"))
expect_error(expand_range(forward, by = 100, start = 5, end = 80, snapshots = 3), paste0(msg, "given the assumed forward time"))
expect_error(expand_range(forward, by = 100, start = 60, end = 80, snapshots = 3), paste0(msg, "given the assumed forward time"))
expect_silent(move(forward, trajectory = c(5, 5), start = 5, end = 40, snapshots = 3))
backward <- population(name = "backward", map = map, time = 100, N = 1, center = c(20, 50), radius = 20, remove = 10)
expect_error(move(backward, trajectory = c(5, 5), start = 80, end = 5, snapshots = 3), paste0(msg, "given the assumed backward time"))
expect_error(move(backward, trajectory = c(5, 5), start = 8, end = 5, snapshots = 3),paste0(msg, "given the assumed backward time"))
expect_error(expand_range(backward, by = 10, start = 80, end = 5, snapshots = 3), paste0(msg, "given the assumed backward time"))
expect_error(expand_range(backward, by = 10, start = 8, end = 5, snapshots = 3),paste0(msg, "given the assumed backward time"))
expect_silent(move(backward, trajectory = c(5, 5), start = 80, end = 50, snapshots = 3))
})
test_that("Explicitly given direction must agree with the implied direction", {
map <- readRDS("map.rds")
msg <- "The direction that was explicitly specified contradicts the direction implied by the model"
pop <- population("pop", time = 500, N = 100, map = map, center = c(20, 50), radius = 500e3) %>%
resize(N = 1000, time = 900, how = "step")
model_dir <- file.path(tempdir(), "direction_conflict")
expect_error(compile_model(populations = list(pop), generation_time = 1,
resolution = 10e3, competition = 130e3, mating = 100e3, dispersal = 70e3, # how far will offspring end up from their parents
path = model_dir, direction = "backward", overwrite = TRUE, force = TRUE), msg)
pop <- population("pop", time = 500, N = 100, map = map, center = c(20, 50), radius = 500e3) %>%
resize(N = 1000, time = 300, how = "step")
model_dir <- file.path(tempdir(), "direction_conflict")
expect_error(compile_model(populations = list(pop), generation_time = 1,
resolution = 10e3, competition = 130e3, mating = 100e3, dispersal = 70e3, # how far will offspring end up from their parents
path = model_dir, direction = "forward", overwrite = TRUE, force = TRUE), msg)
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.