Skip to content

Commit

Permalink
Inject the refactored back end into the Python module
Browse files Browse the repository at this point in the history
* Implement pickling for ForwardDemesGraph Python class.
* ForwardDemesGraph now stores its demes.Graph
* Pull in demes-rs dependencies from GitHub
* remove some tests that rely on the deprecated API
* Remove test decorator invoking DemographyDebugger
* API updates for cpp_neutral_benchmark/cpp_neutral_benchmark.cc
* When rounding leads to a bad model, return DemographyError rather
  than ValueError
* Update examples/plugin/test_plugin.py
* Fix C++ tests that were incorrect.
  These had to be changed b/c of errors we discovered upstream
  in demes-forward.
  • Loading branch information
molpopgen committed Mar 2, 2023
1 parent bb890c0 commit f657af9
Show file tree
Hide file tree
Showing 37 changed files with 915 additions and 990 deletions.
19 changes: 10 additions & 9 deletions cpp_neutral_benchmark/cpp_neutral_benchmark.cc
@@ -1,3 +1,4 @@
#include "core/demes/forward_graph.hpp"
#include <iostream>
#include <vector>
#include <fwdpy11/types/DiploidPopulation.hpp>
Expand All @@ -8,7 +9,6 @@
#include <fwdpy11/regions/RecombinationRegions.hpp>
#include <fwdpy11/regions/GeneticMapUnit.hpp>
#include <fwdpy11/regions/MutationRegions.hpp>
#include <fwdpy11/discrete_demography/DiscreteDemography.hpp>
#include <fwdpy11/evolvets/SampleRecorder.hpp>
#include <fwdpy11/evolvets/recorders.hpp>
#include <fwdpy11/rng.hpp>
Expand Down Expand Up @@ -166,13 +166,14 @@ simulate(const command_line_options& options)

fwdpy11::MutationRegions mmodel({}, {});

fwdpy11::discrete_demography::DiscreteDemography demography(
std::vector<fwdpy11::discrete_demography::MassMigration>{},
std::vector<fwdpy11::discrete_demography::SetExponentialGrowth>{},
std::vector<fwdpy11::discrete_demography::SetDemeSize>{},
std::vector<fwdpy11::discrete_demography::SetSelfingRate>{},
fwdpy11::discrete_demography::MigrationMatrix{},
std::vector<fwdpy11::discrete_demography::SetMigrationRates>{});
std::ostringstream o;
o << "time_units: generations\n";
o << "demes:\n"
<< " - name: A\n"
<< " epochs:\n"
<< " - start_size: " << options.N << '\n';

fwdpy11_core::ForwardDemesGraph forward_demes_graph(o.str(), options.nsteps);

DiploidMultiplicative fitness(1, 2., final_multiplicative_fitness(), nullptr,
nullptr);
Expand All @@ -197,7 +198,7 @@ simulate(const command_line_options& options)
};

evolve_with_tree_sequences(
rng, pop, sample_recorder, options.simplification_interval, demography,
rng, pop, sample_recorder, options.simplification_interval, forward_demes_graph,
options.nsteps, 0., 0., mmodel, genetic_map, gvalue_pointers,
[](const fwdpy11::DiploidPopulation& /*pop*/, fwdpy11::SampleRecorder& /*sr*/) {
},
Expand Down
104 changes: 52 additions & 52 deletions cpptests/test_evolvets.cc
Expand Up @@ -273,10 +273,10 @@ BOOST_FIXTURE_TEST_CASE(test_basic_api_coherence, common_setup)

// TODO: if we put long run times in here, we get exceptions
// from the ForwardDemesGraph back end.
evolve_with_tree_sequences_refactor(rng, pop, recorder, 10, forward_demes_graph, 10,
0., 0., mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
evolve_with_tree_sequences(rng, pop, recorder, 10, forward_demes_graph, 10, 0., 0.,
mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
BOOST_REQUIRE_EQUAL(pop.generation, 10);
}

Expand All @@ -291,10 +291,10 @@ BOOST_FIXTURE_TEST_CASE(test_basic_api_coherence_two_deme_perpetual_island_model

// TODO: if we put long run times in here, we get exceptions
// from the ForwardDemesGraph back end.
evolve_with_tree_sequences_refactor(rng, pop, recorder, 10, forward_demes_graph, 10,
0., 0., mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
evolve_with_tree_sequences(rng, pop, recorder, 10, forward_demes_graph, 10, 0., 0.,
mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
BOOST_REQUIRE_EQUAL(pop.generation, 10);
std::vector<unsigned> ndemes{0, 0};
for (const auto& dip : pop.diploid_metadata)
Expand All @@ -311,10 +311,10 @@ BOOST_FIXTURE_TEST_CASE(test_simlen_longer_than_model_length, common_setup)
fwdpy11_core::ForwardDemesGraph forward_demes_graph(model.yaml, 10);

// Here, simlen = 100, but the graph only has 10 generations of births in it.
evolve_with_tree_sequences_refactor(rng, pop, recorder, 10, forward_demes_graph, 100,
0., 0., mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
evolve_with_tree_sequences(rng, pop, recorder, 10, forward_demes_graph, 100, 0., 0.,
mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
BOOST_REQUIRE_EQUAL(pop.generation, 10);
}

Expand All @@ -335,10 +335,10 @@ BOOST_FIXTURE_TEST_CASE(test_invalid_deme_metadata, common_setup)

BOOST_CHECK_THROW(
{
evolve_with_tree_sequences_refactor(
rng, pop, recorder, 10, forward_demes_graph, 10, 0., 0., mregions,
recregions, gvalue_ptrs, sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
evolve_with_tree_sequences(rng, pop, recorder, 10, forward_demes_graph, 10,
0., 0., mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
},
fwdpy11::discrete_demography::DemographyError);
// pop hasn't evolved!
Expand All @@ -363,7 +363,7 @@ BOOST_FIXTURE_TEST_CASE(test_initial_pop_size_invalid, common_setup)

BOOST_CHECK_THROW(
{
evolve_with_tree_sequences_refactor(
evolve_with_tree_sequences(
rng, pop, recorder, 10, forward_demes_graph, 10, 0., 0.,
mregions, recregions, gvalue_ptrs, sample_recorder_callback,
stopping_criterion, post_simplification_recorder, options);
Expand Down Expand Up @@ -394,7 +394,7 @@ BOOST_FIXTURE_TEST_CASE(test_initial_pop_size_invalid_island_model, common_setup

BOOST_CHECK_THROW(
{
evolve_with_tree_sequences_refactor(
evolve_with_tree_sequences(
rng, pop, recorder, 10, forward_demes_graph, 10, 0., 0.,
mregions, recregions, gvalue_ptrs, sample_recorder_callback,
stopping_criterion, post_simplification_recorder, options);
Expand All @@ -417,7 +417,7 @@ BOOST_FIXTURE_TEST_CASE(test_initial_pop_size_invalid_island_model, common_setup
fwdpy11_core::ForwardDemesGraph forward_demes_graph(model.yaml, 10);
BOOST_CHECK_THROW(
{
evolve_with_tree_sequences_refactor(
evolve_with_tree_sequences(
rng, pop, recorder, 10, forward_demes_graph, 10, 0., 0.,
mregions, recregions, gvalue_ptrs, sample_recorder_callback,
stopping_criterion, post_simplification_recorder, options);
Expand All @@ -439,10 +439,10 @@ BOOST_FIXTURE_TEST_CASE(test_generation_time_past_end_of_model, common_setup)
pop.generation = 11;
BOOST_CHECK_THROW(
{
evolve_with_tree_sequences_refactor(
rng, pop, recorder, 10, forward_demes_graph, 10, 0., 0., mregions,
recregions, gvalue_ptrs, sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
evolve_with_tree_sequences(rng, pop, recorder, 10, forward_demes_graph, 10,
0., 0., mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
},
fwdpy11::discrete_demography::DemographyError);
BOOST_REQUIRE_EQUAL(pop.generation, 11);
Expand All @@ -453,10 +453,10 @@ BOOST_FIXTURE_TEST_CASE(test_size_history_single_deme_model_one_size_change,
{
auto model = SingleDemeModelOneSizeChange();
fwdpy11_core::ForwardDemesGraph forward_demes_graph(model.yaml, 10);
evolve_with_tree_sequences_refactor(rng, pop, recorder, 10, forward_demes_graph, 60,
0., 0., mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
evolve_with_tree_sequences(rng, pop, recorder, 10, forward_demes_graph, 60, 0., 0.,
mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
BOOST_REQUIRE_EQUAL(pop.generation, 60);
BOOST_REQUIRE_EQUAL(size_history.size(), 1);
for (auto& x : size_history)
Expand Down Expand Up @@ -484,10 +484,10 @@ BOOST_FIXTURE_TEST_CASE(
auto model = TwoDemePerpetualIslandModelWithSizeChangeAndExtinction();
pop = fwdpy11::DiploidPopulation({100, 100}, 10.);
fwdpy11_core::ForwardDemesGraph forward_demes_graph(model.yaml, 10);
evolve_with_tree_sequences_refactor(rng, pop, recorder, 10, forward_demes_graph, 60,
0., 0., mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
evolve_with_tree_sequences(rng, pop, recorder, 10, forward_demes_graph, 60, 0., 0.,
mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
BOOST_REQUIRE_EQUAL(pop.generation, 60);
BOOST_REQUIRE_EQUAL(size_history.size(), 2);
BOOST_REQUIRE(std::all_of(std::begin(pop.diploid_metadata),
Expand Down Expand Up @@ -515,10 +515,10 @@ BOOST_FIXTURE_TEST_CASE(test_size_history_two_demes_unequal_merge,
auto model = TwoDemesUnequalMerge();
pop = fwdpy11::DiploidPopulation({100, 75}, 10.);
fwdpy11_core::ForwardDemesGraph forward_demes_graph(model.yaml, 10);
evolve_with_tree_sequences_refactor(rng, pop, recorder, 10, forward_demes_graph, 60,
0., 0., mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
evolve_with_tree_sequences(rng, pop, recorder, 10, forward_demes_graph, 60, 0., 0.,
mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
BOOST_REQUIRE_EQUAL(pop.generation, 35);
BOOST_REQUIRE_EQUAL(size_history.size(), 3);

Expand Down Expand Up @@ -548,29 +548,29 @@ BOOST_FIXTURE_TEST_CASE(test_ancestry_proportions_from_pulse_with_burnin,
BOOST_REQUIRE_EQUAL(forward_demes_graph.number_of_demes(), 2);
pop = fwdpy11::DiploidPopulation({50, 50}, 1.);
update_parents(pop);
evolve_with_tree_sequences_refactor(rng, pop, recorder, 10, forward_demes_graph, 60,
0., 0., mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
evolve_with_tree_sequences(rng, pop, recorder, 10, forward_demes_graph, 60, 0., 0.,
mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
BOOST_REQUIRE_EQUAL(pop.generation, 12);

auto condition = [](std::uint32_t a) { return a == 50; };

// pre-pulse
for (std::uint32_t g = 1; g < 11; ++g)
for (std::uint32_t g = 1; g < 10; ++g)
{
auto found = validate_ancestry(this->ancestry, g, 0, 0, condition);
BOOST_REQUIRE(found);
found = validate_ancestry(this->ancestry, g, 1, 1, condition);
BOOST_REQUIRE(found);
}
auto found = validate_ancestry(this->ancestry, 11, 0, 1, condition);
auto found = validate_ancestry(this->ancestry, 10, 0, 1, condition);
BOOST_REQUIRE(found);
found = validate_ancestry(this->ancestry, 11, 1, 0, condition);
found = validate_ancestry(this->ancestry, 10, 1, 0, condition);
BOOST_REQUIRE(found);
found = validate_ancestry(this->ancestry, 12, 0, 0, condition);
found = validate_ancestry(this->ancestry, 11, 0, 0, condition);
BOOST_REQUIRE(found);
found = validate_ancestry(this->ancestry, 12, 1, 1, condition);
found = validate_ancestry(this->ancestry, 11, 1, 1, condition);
BOOST_REQUIRE(found);
}

Expand All @@ -582,10 +582,10 @@ BOOST_FIXTURE_TEST_CASE(test_ancestry_with_extreme_migration_until_one_generatio
BOOST_REQUIRE_EQUAL(forward_demes_graph.number_of_demes(), 2);
pop = fwdpy11::DiploidPopulation({1000, 1000}, 1.);
update_parents(pop);
evolve_with_tree_sequences_refactor(rng, pop, recorder, 10, forward_demes_graph, 60,
0., 0., mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
evolve_with_tree_sequences(rng, pop, recorder, 10, forward_demes_graph, 60, 0., 0.,
mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
BOOST_REQUIRE_EQUAL(pop.generation, 10);

auto validate_complete_ancestry = [](std::uint32_t p) { return p == 1000; };
Expand Down Expand Up @@ -636,10 +636,10 @@ BOOST_FIXTURE_TEST_CASE(
auto last_generation = pop.generation;
for (std::size_t i = 0; i < 10; ++i)
{
evolve_with_tree_sequences_refactor(
rng, pop, recorder, 10, forward_demes_graph, 1, 0., 0., mregions,
recregions, gvalue_ptrs, sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
evolve_with_tree_sequences(rng, pop, recorder, 10, forward_demes_graph, 1,
0., 0., mregions, recregions, gvalue_ptrs,
sample_recorder_callback, stopping_criterion,
post_simplification_recorder, options);
BOOST_REQUIRE_EQUAL(pop.generation, last_generation + 1);
last_generation += 1;
}
Expand Down
14 changes: 13 additions & 1 deletion examples/plugin/test_plugin.py
@@ -1,10 +1,22 @@
import demes
import fwdpy11
import gvalue_recorder

N = 1000

yaml = """
time_units: generations
demes:
- name: pop
epochs:
- start_size: 1000
"""

graph = demes.loads(yaml)
demography = fwdpy11.discrete_demography.from_demes(graph, 1)

pdict = {
"demography": fwdpy11.DiscreteDemography(),
"demography": demography,
"simlen": 100,
"nregions": [],
"sregions": [fwdpy11.GaussianS(0, 1, 1, 0.25)],
Expand Down
29 changes: 13 additions & 16 deletions fwdpy11/_evolvets.py
Expand Up @@ -25,19 +25,19 @@
from ._types import DiploidPopulation, ModelParams


def _validate_event_timings(demography: fwdpy11.DiscreteDemography, generation: int):
too_early = []
for i in demography._timed_events():
if i is not None:
for j in i:
if j.when < generation:
too_early.append(j)
if len(too_early) > 0:
import warnings

msg = "The following demographic events are registered to occur "
msg += f"before the current generation, which is {generation}: {too_early}"
warnings.warn(msg)
# def _validate_event_timings(demography: fwdpy11.DiscreteDemography, generation: int):
# too_early = []
# for i in demography._timed_events():
# if i is not None:
# for j in i:
# if j.when < generation:
# too_early.append(j)
# if len(too_early) > 0:
# import warnings
#
# msg = "The following demographic events are registered to occur "
# msg += f"before the current generation, which is {generation}: {too_early}"
# warnings.warn(msg)


def evolvets(
Expand Down Expand Up @@ -221,9 +221,6 @@ def evolvets(
fwdpy11._validate_regions(params.nregions, pop.tables.genome_length)
fwdpy11._validate_regions(params.recregions, pop.tables.genome_length)

if check_demographic_event_timings:
_validate_event_timings(demographic_model, pop.generation)

pneutral = 0.0
if params.rates.neutral_mutation_rate + params.rates.selected_mutation_rate > 0.0:
pneutral = params.rates.neutral_mutation_rate / (
Expand Down

0 comments on commit f657af9

Please sign in to comment.