tests/testthat/test-future.R

# This script tests that models with times going "into the future" give the same result when
# run through both SLiM and msprime. This has been prompted by strange errors like
# "negative times not valid" from msprime when running models like this. This was caused
# by convert_to_forward() missing the following clause (ignoring special treatment of
# "forward" direction models entirely):
#     else if (direction == "forward")
#        times[times != -1] <- times[times != -1] - start_time + generation_time
# The reason why this wasn't discovered earlier is that the change only manifests in more
# complicated forward models (and only when run through msprime).
#
# These kinds of unit tests are also done elsewhere but those clearly have not been
# exhaustive enough -- it's better to put new tests in a separate script so that it's
# cleare why have these been introduced.

skip_if(!is_slendr_env_present())
init_env(quiet = TRUE)

# resizes with default sampling ---------------------------------------------------------------

test_that("forward models not starting from 1 given the same outcome (resizes, all samples)", {
  pop1 <- population("pop1", time = 1500, N = 100) %>%
    resize(time = 1800, N = 10, how = "step") %>%
    resize(time = 2024, N = 30, how = "step") %>%
    resize(time = 2200, N = 30, how = "step")
  pop2 <- population("pop2", time = 1700, N = 100, parent = pop1) %>%
    resize(time = 1800, N = 10, how = "step")

  model <- compile_model(list(pop1, pop2), generation_time = 20, simulation_length = 1000)

  tss <- slim(model, sequence_length = 1e6, recombination_rate = 1e-8)
  tsm <- msprime(model, sequence_length = 1e6, recombination_rate = 1e-8)

  expect_equal(ts_samples(tss), ts_samples(tsm))
})

test_that("forward models starting from 1 give the same outcome (resizes, all samples)", {
  pop1 <- population("pop1", time = 1, N = 100) %>%
    resize(time = 1800, N = 10, how = "step") %>%
    resize(time = 2024, N = 30, how = "step") %>%
    resize(time = 2200, N = 30, how = "step")
  pop2 <- population("pop2", time = 1700, N = 100, parent = pop1) %>%
    resize(time = 1800, N = 10, how = "step")

  model <- compile_model(list(pop1, pop2), generation_time = 20, simulation_length = 3000)

  tss <- slim(model, sequence_length = 1e6, recombination_rate = 1e-8)
  tsm <- msprime(model, sequence_length = 1e6, recombination_rate = 1e-8)

  expect_equal(ts_samples(tss), ts_samples(tsm))
})

test_that("(truncated) forward models starting from 1 give the same outcome (resizes, all samples)", {
  pop1 <- population("pop1", time = 1, N = 100) %>%
    resize(time = 1800, N = 10, how = "step") %>%
    resize(time = 2024, N = 30, how = "step") %>%
    resize(time = 2200, N = 30, how = "step")
  pop2 <- population("pop2", time = 1700, N = 100, parent = pop1) %>%
    resize(time = 1800, N = 10, how = "step")

  model <- compile_model(list(pop1, pop2), generation_time = 20, simulation_length = 1000)

  tss <- slim(model, sequence_length = 1e6, recombination_rate = 1e-8)
  tsm <- msprime(model, sequence_length = 1e6, recombination_rate = 1e-8)

  expect_equal(ts_samples(tss), ts_samples(tsm))
})

# resizes with defined sampling ---------------------------------------------------------------

test_that("forward models not starting from 1 give the same outcome (resizes, defined samples)", {
  pop1 <- population("pop1", time = 1500, N = 100) %>%
    resize(time = 1800, N = 10, how = "step") %>%
    resize(time = 2024, N = 30, how = "step") %>%
    resize(time = 2200, N = 30, how = "step")
  pop2 <- population("pop2", time = 1700, N = 100, parent = pop1) %>%
    resize(time = 1800, N = 10, how = "step")

  model <- compile_model(list(pop1, pop2), generation_time = 20, simulation_length = 1000)

  samples <- schedule_sampling(model, times = c(1, 500, 1900, 2200, 2500), list(pop1, 2), list(pop2, 2))

  tss <- slim(model, sequence_length = 1e6, recombination_rate = 1e-8, samples = samples)
  tsm <- msprime(model, sequence_length = 1e6, recombination_rate = 1e-8, samples = samples)

  expect_equal(ts_samples(tss), ts_samples(tsm))
})

test_that("forward models not starting from 1 give the same outcome (resizes, defined samples)", {
  pop1 <- population("pop1", time = 1, N = 100) %>%
    resize(time = 1800, N = 10, how = "step") %>%
    resize(time = 2024, N = 30, how = "step") %>%
    resize(time = 2200, N = 30, how = "step")
  pop2 <- population("pop2", time = 1700, N = 100, parent = pop1) %>%
    resize(time = 1800, N = 10, how = "step")

  model <- compile_model(list(pop1, pop2), generation_time = 20, simulation_length = 3000)

  samples <- schedule_sampling(model, times = c(1, 500, 1000, 1001, 1900, 2200, 2500), list(pop1, 2), list(pop2, 2))

  tss <- slim(model, sequence_length = 1e6, recombination_rate = 1e-8, samples = samples)
  tsm <- msprime(model, sequence_length = 1e6, recombination_rate = 1e-8, samples = samples)

  expect_equal(ts_samples(tss), ts_samples(tsm))
})

# gene-flow events ---------------------------------------------------------------

test_that("forward models not starting from 1 given the same outcome (gene flows)", {
  pop1 <- population("pop1", time = 1500, N = 100) %>%
    resize(time = 1800, N = 10, how = "step") %>%
    resize(time = 2024, N = 30, how = "step") %>%
    resize(time = 2200, N = 30, how = "step")
  pop2 <- population("pop2", time = 1700, N = 100, parent = pop1) %>%
    resize(time = 1800, N = 10, how = "step")

  gf <- gene_flow(pop1, pop2, rate = 0.1, start = 1800, end = 1900)

  model <- compile_model(list(pop1, pop2), gene_flow = gf, generation_time = 20, simulation_length = 1000)

  samples <- schedule_sampling(model, times = c(1, 500, 1900, 2200, 2500), list(pop1, 2), list(pop2, 2))

  tss <- slim(model, sequence_length = 1e6, recombination_rate = 1e-8, samples = samples)
  tsm <- msprime(model, sequence_length = 1e6, recombination_rate = 1e-8, samples = samples)

  expect_equal(ts_samples(tss), ts_samples(tsm))
})

test_that("forward models starting from 1 given the same outcome (gene flows)", {
  pop1 <- population("pop1", time = 1, N = 100) %>%
    resize(time = 1800, N = 10, how = "step") %>%
    resize(time = 2024, N = 30, how = "step") %>%
    resize(time = 2200, N = 30, how = "step")
  pop2 <- population("pop2", time = 1700, N = 100, parent = pop1) %>%
    resize(time = 1800, N = 10, how = "step")

  gf <- gene_flow(pop1, pop2, rate = 0.1, start = 1800, end = 1900)

  model <- compile_model(list(pop1, pop2), gene_flow = gf, generation_time = 20, simulation_length = 1000)

  samples <- schedule_sampling(model, times = c(1, 500, 1900, 2200, 2500), list(pop1, 2), list(pop2, 2))

  tss <- slim(model, sequence_length = 1e6, recombination_rate = 1e-8, samples = samples)
  tsm <- msprime(model, sequence_length = 1e6, recombination_rate = 1e-8, samples = samples)

  expect_equal(ts_samples(tss), ts_samples(tsm))
})


# backwards models ----------------------------------------------------------------------------

# This is out of the scope of this unit-test script but given the changes introduced for
# the bugfixes described above, let's make sure everything still works as it used to
# (namely that truncated backwards-time models correctly schedule default sampling times).

test_that("backward models correctly sample by default 'at present' (non-truncated)", {
  pop1 <- population("pop1", time = 10000, N = 100) %>%
    resize(time = 7800, N = 10, how = "step") %>%
    resize(time = 4024, N = 30, how = "step")
  pop2 <- population("pop2", time = 1700, N = 50, parent = pop1) %>%
    resize(time = 800, N = 10, how = "step")

  model <- compile_model(list(pop1, pop2), generation_time = 100)

  tss <- slim(model, sequence_length = 1e6, recombination_rate = 1e-8)
  tsm <- msprime(model, sequence_length = 1e6, recombination_rate = 1e-8)

  expect_equal(ts_samples(tss), ts_samples(tsm))
})

test_that("backward models correctly sample by default 'at present' (truncated)", {
  pop1 <- population("pop1", time = 10000, N = 100) %>%
    resize(time = 7800, N = 10, how = "step") %>%
    resize(time = 4024, N = 30, how = "step")
  pop2 <- population("pop2", time = 1700, N = 50, parent = pop1) %>%
    resize(time = 800, N = 10, how = "step")

  model <- compile_model(list(pop1, pop2), generation_time = 100, simulation_length = 5000)

  tss <- slim(model, sequence_length = 1e6, recombination_rate = 1e-8)
  tsm <- msprime(model, sequence_length = 1e6, recombination_rate = 1e-8)

  expect_equal(ts_samples(tss), ts_samples(tsm))
})
bodkan/slendr documentation built on Dec. 19, 2024, 11:41 p.m.