skip_if(!is_slendr_env_present())
init_env(quiet = TRUE)
# basic extension type and sanity checking --------------------------------
test_that("an valid extension snippet must be a string or a file", {
msg <- "Extension can be either a \\(multi-line\\) R string, or a path to a file"
afr <- population("AFR", time = 100, N = 20)
eur <- population("EUR", time = 10, N = 20, parent = afr)
expect_error(compile_model(populations = list(afr, eur), generation_time = 1, extension = 123), msg)
expect_error(compile_model(populations = list(afr, eur), generation_time = 1, extension = TRUE), msg)
})
test_that("an valid extension snippet must be a valid SLiM code or an existing file", {
msg <- "Extension does not appear to be a file path nor a string containing SLiM code"
afr <- population("AFR", time = 100, N = 20)
eur <- population("EUR", time = 10, N = 20, parent = afr)
expect_error(compile_model(populations = list(afr, eur), generation_time = 1, extension = "/tmp/asdfqwe"), msg)
expect_error(compile_model(populations = list(afr, eur), generation_time = 1, extension = r"(
this isn't valid SLiM code
)"), msg)
expect_s3_class(compile_model(populations = list(afr, eur), generation_time = 1, extension = r"(
initialize() { for the purpose of a regex this is valid SLiM code}
)"), "slendr_model")
})
test_that("SLiM extension R string snippet is correctly embedded into the compiled script", {
afr <- population("AFR", time = 100, N = 20)
eur <- population("EUR", time = 10, N = 20, parent = afr)
extension <- "initialize() { catn('Hello from the SLiM side!'); }"
model <- compile_model(populations = list(afr, eur), generation_time = 1, extension = extension)
compiled_script <- readLines(file.path(model$path, "script.slim"))
expect_true(any(grepl("Hello from the SLiM side!", compiled_script)))
log_output <- capture.output(slim(model, sequence_length = 100, recombination_rate = 0, verbose = TRUE, ts = FALSE))
expect_true(any(grepl("Hello from the SLiM side!", log_output)))
})
test_that("SLiM extension file is correctly embedded into the compiled script", {
afr <- population("AFR", time = 100, N = 20)
eur <- population("EUR", time = 10, N = 20, parent = afr)
extension <- normalizePath(tempfile(), winslash = "/", mustWork = FALSE)
writeLines("initialize() { catn('Hello from the SLiM side!'); }", extension)
model <- compile_model(populations = list(afr, eur), generation_time = 1, extension = extension)
compiled_script <- readLines(file.path(model$path, "script.slim"))
expect_true(any(grepl("Hello from the SLiM side!", compiled_script)))
log_output <- capture.output(slim(model, sequence_length = 100, recombination_rate = 0, verbose = TRUE, ts = FALSE))
expect_true(any(grepl("Hello from the SLiM side!", log_output)))
})
# enforce initialization contents -----------------------------------------
test_that("SLiM extension file is correctly embedded into the compiled script", {
msg <- "SLiM extension snippets must either contain no initialize"
pop <- population("pop", time = 100, N = 100) %>% resize(time = 10, N = 10, how = "step")
extension <- r"(initialize() { initializeMutationType("m1", 0.5, "f", 0.0); })"
expect_error(compile_model(populations = pop, generation_time = 1, extension = extension), msg)
extension <- r"(initialize() { initializeMutationRate(1e-8); } )"
expect_error(compile_model(populations = pop, generation_time = 1, extension = extension), msg)
extension <- r"(initialize() { initializeRecombinationRate(1e-8); })"
expect_error(compile_model(populations = pop, generation_time = 1, extension = extension), msg)
extension <- r"(initialize() {
initializeMutationRate(1e-8);
initializeRecombinationRate(1e-8);
})"
expect_error(compile_model(populations = pop, generation_time = 1, extension = extension), msg)
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, SEQUENCE_LENGTH - 1);
initializeMutationRate(0);
initializeRecombinationRate(RECOMBINATION_RATE);
})"
expect_s3_class(compile_model(populations = pop, generation_time = 1, extension = extension), "slendr_model")
})
test_that("if simulation length is not given in a model, slim() requires it (non-custom script)", {
pop <- population("pop", time = 100, N = 100) %>% resize(time = 10, N = 10, how = "step")
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, SEQUENCE_LENGTH - 1);
initializeMutationRate(0);
initializeRecombinationRate(RECOMBINATION_RATE);
})"
model <- compile_model(populations = pop, generation_time = 1, extension = extension)
msg <- "Specifying the `sequence_length =` argument is required"
expect_error(slim(model), msg)
expect_error(slim(model, recombination_rate = 1e-8), msg)
expect_s3_class(slim(model, sequence_length = 100, recombination_rate = 0), "slendr_ts")
})
test_that("if recombination rate is not given in a model, slim() requires it (non-custom script)", {
pop <- population("pop", time = 100, N = 100) %>% resize(time = 10, N = 10, how = "step")
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, SEQUENCE_LENGTH - 1);
initializeMutationRate(0);
initializeRecombinationRate(RECOMBINATION_RATE);
})"
model <- compile_model(populations = pop, generation_time = 1, extension = extension)
msg <- "Specifying the `recombination_rate =` argument is required"
expect_error(slim(model, sequence_length = 1e-8), msg)
expect_s3_class(slim(model, sequence_length = 100, recombination_rate = 0), "slendr_ts")
})
test_that("if simulation length is not given in a model, slim() requires it (customized script)", {
pop <- population("pop", time = 100, N = 100) %>% resize(time = 10, N = 10, how = "step")
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, SEQUENCE_LENGTH - 1);
initializeMutationRate(0);
initializeRecombinationRate(0);
})"
model <- compile_model(populations = pop, generation_time = 1, extension = extension)
msg <- "Specifying the `sequence_length =` argument is required"
expect_error(slim(model), msg)
expect_s3_class(slim(model, sequence_length = 100), "slendr_ts")
})
test_that("if recombination rate is not given in a model, slim() requires it (customized script)", {
pop <- population("pop", time = 100, N = 100) %>% resize(time = 10, N = 10, how = "step")
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, 999);
initializeMutationRate(0);
initializeRecombinationRate(RECOMBINATION_RATE);
})"
model <- compile_model(populations = pop, generation_time = 1, extension = extension)
msg <- "Specifying the `recombination_rate =` argument is required"
expect_error(slim(model), msg)
expect_s3_class(slim(model, recombination_rate = 0), "slendr_ts")
})
test_that("slim() does not require sequence length and recombination rate with custom scripts", {
pop <- population("pop", time = 100, N = 100) %>% resize(time = 10, N = 10, how = "step")
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, 999);
initializeMutationRate(0);
initializeRecombinationRate(1e-8);
})"
model <- compile_model(populations = pop, generation_time = 1, extension = extension)
expect_s3_class(slim(model), "slendr_ts")
})
test_that("slim() does not accept sequence length and recombination rate with custom scripts", {
pop <- population("pop", time = 100, N = 100) %>% resize(time = 10, N = 10, how = "step")
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, 999);
initializeMutationRate(0);
initializeRecombinationRate(1e-8);
})"
model <- compile_model(populations = pop, generation_time = 1, extension = extension)
expect_error(slim(model, sequence_length = 1000),
"Specifying `sequence_length =` is not allowed when it is already given")
expect_error(slim(model, recombination_rate = 1e-8),
"Specifying `recombination_rate =` is not allowed when it is already given")
expect_s3_class(slim(model), "slendr_ts")
})
# output generation -------------------------------------------------------
pop <- population("pop", time = 100, N = 100) %>% resize(time = 10, N = 10, how = "step")
output_file <- normalizePath(tempfile(), winslash = "/", mustWork = FALSE)
extension <- sprintf(r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, 999);
initializeMutationRate(0);
initializeRecombinationRate(1e-8);
}
SIMULATION_LENGTH late() {
writeFile("%s", "asdf");
}
)", output_file)
model <- compile_model(populations = pop, generation_time = 1, extension = extension)
test_that("output file and tree sequence are both there", {
result <- slim(model)
expect_s3_class(result, "slendr_ts")
expect_true(file.exists(output_file))
expect_true(readLines(output_file) == "asdf")
})
test_that("output file is there but tree sequence is not returned", {
result <- slim(model, ts = FALSE)
expect_true(length(dir(result)) == 0)
expect_true(file.exists(output_file))
expect_true(readLines(output_file) == "asdf")
})
test_that("output directory can be set and files and tree sequence are saved there", {
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, 999);
initializeMutationRate(0);
initializeRecombinationRate(1e-8);
}
SIMULATION_LENGTH late() {
path = PATH + "/" + "output_file";
writeFile(path, "asdf");
}
)"
model <- compile_model(populations = pop, generation_time = 1, extension = extension)
output_dir <- normalizePath(file.path(tempdir(), "testing_dir1"), winslash = "/", mustWork = FALSE)
output_file <- file.path(output_dir, "output_file")
result <- slim(model, path = output_dir)
# slim(..., output_dir = ...) returns the directory path
expect_true(result == paste0(output_dir, "/"))
expect_equal(sort(list.files(output_dir)), sort(c("output_file", "slim.trees")))
expect_true(file.exists(output_file))
expect_true(readLines(output_file) == "asdf")
expect_s3_class(ts_read(file.path(output_dir, "slim.trees"), model), "slendr_ts")
})
test_that("output directory can be set and files (but no tree sequence) are saved there", {
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, 999);
initializeMutationRate(0);
initializeRecombinationRate(1e-8);
}
SIMULATION_LENGTH late() {
path = PATH + "/" + "output_file";
writeFile(path, "asdf");
}
)"
model <- compile_model(populations = pop, generation_time = 1, extension = extension)
output_dir <- normalizePath(file.path(tempdir(), "testing_dir2"), winslash = "/", mustWork = FALSE)
output_file <- file.path(output_dir, "output_file")
result <- slim(model, path = output_dir, ts = FALSE)
# slim(..., output_dir = ...) returns the directory path
expect_true(result == paste0(output_dir, "/"))
expect_equal(list.files(output_dir), "output_file")
expect_true(file.exists(output_file))
expect_true(readLines(output_file) == "asdf")
})
test_that("substitute_values() complains about missing parameters", {
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, {{seq_len}});
initializeMutationRate(0);
initializeRecombinationRate({{rec_rate}});
}
)"
expect_error(
substitute_values(extension, seq_len = 123),
"The extension script contains the following unsubstituted patterns: \\{\\{rec_rate\\}\\}"
)
})
test_that("substitute_values() complains about extra parameters (string)", {
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, {{seq_len}});
initializeMutationRate(0);
initializeRecombinationRate({{rec_rate}});
}
)"
expect_error(
substitute_values(extension, seq_len = 123, rec_rate = 1e-8, ahoy = 42),
"Template pattern '\\{\\{ahoy\\}\\}' not found in the extension script"
)
})
test_that("substitute_values() complains about extra parameters (file)", {
extension_file <- normalizePath(tempfile(), winslash = "/", mustWork = FALSE)
r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, {{seq_len}});
initializeMutationRate(0);
initializeRecombinationRate({{rec_rate}});
}
)" %>% { writeLines(text = ., con = extension_file)}
expect_error(
substitute_values(extension_file, seq_len = 123),
"The extension script contains the following unsubstituted patterns: \\{\\{rec_rate\\}\\}"
)
})
test_that("substitute_values() complains about extra parameters (string)", {
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, {{seq_len}});
initializeMutationRate(0);
initializeRecombinationRate({{rec_rate}});
}
)"
expect_error(
substitute_values(extension, seq_len = 123, rec_rate = 1e-8, ahoy = 42),
"Template pattern '\\{\\{ahoy\\}\\}' not found in the extension script"
)
})
test_that("substitute_values() complains about extra parameters (file)", {
extension_file <- normalizePath(tempfile(), winslash = "/", mustWork = FALSE)
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, {{seq_len}});
initializeMutationRate(0);
initializeRecombinationRate({{rec_rate}});
}
)" %>% { writeLines(text = ., con = extension_file)}
expect_error(
substitute_values(extension_file, seq_len = 123, rec_rate = 1e-8, ahoy = 42),
"Template pattern '\\{\\{ahoy\\}\\}' not found in the extension script"
)
})
test_that("substitute_values() correctly instantiates parameters (string)", {
extension <- r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, {{seq_len}});
initializeMutationRate(0);
initializeRecombinationRate({{rec_rate}});
}
)" %>% substitute_values(seq_len = 424242, rec_rate = 0.123456789)
extension_code <- readLines(extension)
expect_true(sum(grepl("424242", extension_code)) == 1)
expect_true(sum(grepl("0.123456789", extension_code)) == 1)
})
test_that("substitute_values() correctly instantiates parameters (file)", {
extension_file <- normalizePath(tempfile(), winslash = "/", mustWork = FALSE)
r"(
initialize() {
initializeMutationType("m1", 0.5, "f", 0.0);
initializeGenomicElementType("g1", m1, 1.0);
initializeGenomicElement(g1, 0, {{seq_len}});
initializeMutationRate(0);
initializeRecombinationRate({{rec_rate}});
}
)" %>% { writeLines(text = ., con = extension_file)}
extension <- substitute_values(extension_file, seq_len = 424242, rec_rate = 0.123456789)
extension_code <- readLines(extension)
expect_true(sum(grepl("424242", extension_code)) == 1)
expect_true(sum(grepl("0.123456789", extension_code)) == 1)
})
# test ts vs custom-files outputs -------------------------------------------------------------
base_model <- population("asdf", time = 100, N = 100) %>%
compile_model(simulation_length = 100, direction = "forward", generation_time = 1)
extended_model <- extension <- r"(
initialize() { catn("HULLO!"); writeFile(PATH + "/" + "test.txt", "ahojek");}
//SIMULATION_END late() { save_ts(PATH + "/" + "slim.trees"); }
)" %>%
compile_model(populations = population("asdf", time = 100, N = 100),
simulation_length = 100, direction = "forward", generation_time = 1, extension = .)
test_that("basic and extended models return a tree-sequence by default", {
expect_s3_class(slim(base_model, sequence_length = 1e6, recombination_rate = 0, ts = TRUE), "slendr_ts")
expect_s3_class(slim(extended_model, sequence_length = 1e6, recombination_rate = 0, ts = TRUE), "slendr_ts")
})
test_that("basic and extended models return a path if no tree sequence is requested", {
expect_type(slim(base_model, sequence_length = 1e6, recombination_rate = 0, ts = FALSE), "character")
expect_type(slim(extended_model, sequence_length = 1e6, recombination_rate = 0, ts = FALSE), "character")
})
test_that("basic models return a specified path if requested", {
path <- normalizePath(paste0(tempdir(), "_basic_hello_there"), winslash = "/", mustWork = FALSE)
basic_res <- slim(base_model, sequence_length = 1e6, recombination_rate = 0, ts = TRUE, path = path)
expect_true(basic_res == paste0(path, "/"))
})
test_that("extended models return a specified path if requested", {
path <- normalizePath(paste0(tempdir(), "_extended_hello_there"), winslash = "/", mustWork = FALSE)
extended_res <- slim(extended_model, sequence_length = 1e6, recombination_rate = 0, ts = TRUE, path = path)
expect_true(extended_res == paste0(path, "/"))
})
test_that("basic and extended models return expected files at a defined location", {
basic_path <- normalizePath(paste0(tempdir(), "basic_path"), winslash = "/", mustWork = FALSE) %>%
{ slim(base_model, sequence_length = 1e6, recombination_rate = 0, ts = TRUE, path = .) } %>%
{ dirname(dir(., full.names = TRUE)[1]) }
expect_equal(list.files(basic_path), "slim.trees")
extended_path <- normalizePath(paste0(tempdir(), "extended_path"), winslash = "/", mustWork = FALSE) %>%
{ slim(extended_model, sequence_length = 1e6, recombination_rate = 0, ts = TRUE, path = .) } %>%
{ dirname(dir(., full.names = TRUE)[1]) }
expect_equal(sort(list.files(extended_path)), c("slim.trees", "test.txt"))
})
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.