#include #include "../../src/forest.h" #include "../../src/random/constant_generator.h" #include "../../src/random/mersenne_twister.h" #include "../../src/event.h" #include "../../src/summary_statistics/tmrca.h" class TestForest : public CppUnit::TestCase { CPPUNIT_TEST_SUITE( TestForest ); CPPUNIT_TEST( testInitialization ); CPPUNIT_TEST( testGettersAndSetters ); CPPUNIT_TEST( testCreateExampleTree ); CPPUNIT_TEST( testCheckTreeLength ); CPPUNIT_TEST( testGetFirstNode ); CPPUNIT_TEST( testSamplePoint ); CPPUNIT_TEST( testCalcRecombinationRate ); CPPUNIT_TEST( testCalcRate ); CPPUNIT_TEST( testCalcRateWithArachicSamples ); CPPUNIT_TEST( testNodeIsOld ); CPPUNIT_TEST( testPrune ); CPPUNIT_TEST( testSelectFirstTime ); CPPUNIT_TEST( testSampleEventType ); CPPUNIT_TEST( testSampleEvent ); CPPUNIT_TEST( testGetNodeState ); CPPUNIT_TEST( testCut ); CPPUNIT_TEST( testImplementCoalescence ); CPPUNIT_TEST( testBuildInitialTree ); CPPUNIT_TEST( testImplementRecombination ); CPPUNIT_TEST( testImplementFixTimeEvent ); CPPUNIT_TEST( testPrintTree ); CPPUNIT_TEST( testCopyConstructor ); CPPUNIT_TEST( testCheckForNodeAtHeight ); CPPUNIT_TEST( testPrintLocusSumStats ); CPPUNIT_TEST( testSampleNextPosition ); CPPUNIT_TEST( testClear ); CPPUNIT_TEST_SUITE_END(); private: Model *model, *model_2pop; Forest *forest, *forest_2pop; MersenneTwister *rg; public: void setUp() { rg = new MersenneTwister(1234); model = new Model(5); model_2pop = new Model(5); model_2pop->set_population_number(2); forest = new Forest(model, rg); forest->createExampleTree(); forest_2pop = new Forest(model_2pop, rg); forest_2pop->createExampleTree(); } void tearDown() { delete forest; delete model; delete forest_2pop; delete model_2pop; delete rg; } void testInitialization() { Forest test_forest = Forest(new Model(4), rg); CPPUNIT_ASSERT( test_forest.model().sample_size() == 4 ); CPPUNIT_ASSERT( test_forest.random_generator() == rg ); delete test_forest.writable_model(); } void testGettersAndSetters() { CPPUNIT_ASSERT( forest->model().sample_size() == 4 ); } void testGetFirstNode() { CPPUNIT_ASSERT( forest->nodes()->get(0)->height() == 0 ); } void testCreateExampleTree() { CPPUNIT_ASSERT_EQUAL((size_t)2, forest_2pop->model().population_number() ); CPPUNIT_ASSERT_EQUAL((size_t)9, forest->nodes()->size()); CPPUNIT_ASSERT( forest->local_root() == forest->nodes()->get(8) ); CPPUNIT_ASSERT( forest->primary_root() == forest->nodes()->get(8) ); CPPUNIT_ASSERT( forest->getLocalTreeLength() == 24 ); CPPUNIT_ASSERT( forest->checkTree() ); forest->createExampleTree(); CPPUNIT_ASSERT_EQUAL((size_t)9, forest->nodes()->size()); CPPUNIT_ASSERT( forest->local_root() == forest->nodes()->get(8) ); CPPUNIT_ASSERT( forest->primary_root() == forest->nodes()->get(8) ); CPPUNIT_ASSERT( forest->getLocalTreeLength() == 24 ); CPPUNIT_ASSERT( forest->checkTree() ); } void testCheckTreeLength() { CPPUNIT_ASSERT( forest->checkTreeLength() ); } void testCalcRate() { TimeIntervalIterator tii(forest, forest->nodes()->at(0)); double pop_size = 2*forest->model().population_size(0); Node *node1 = new Node(0.1); Node *node2 = new Node(0.2); forest->set_active_node(0, node1); forest->set_active_node(1, node2); forest->states_[0] = 0; forest->states_[1] = 0; CPPUNIT_ASSERT_NO_THROW( forest->calcRates(*tii) ); CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[0] ); CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[1] ); CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[2] ); forest->states_[0] = 1; CPPUNIT_ASSERT_NO_THROW( forest->calcRates(*tii) ); CPPUNIT_ASSERT( areSame(4.0/pop_size, forest->rates_[0]) ); CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[1] ); CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[2] ); forest->states_[1] = 1; CPPUNIT_ASSERT_NO_THROW( forest->calcRates(*tii) ); CPPUNIT_ASSERT( areSame(9.0/pop_size, forest->rates_[0]) ); CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[1] ); CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[2] ); // Coalescence with structure forest_2pop->set_active_node(0, node1); forest_2pop->set_active_node(1, node2); forest_2pop->states_[0] = 1; forest_2pop->states_[1] = 1; node1->set_population(1); forest_2pop->nodes()->at(1)->set_population(1); TimeIntervalIterator tii2(forest_2pop, forest_2pop->nodes()->at(0)); CPPUNIT_ASSERT_NO_THROW( forest_2pop->calcRates(*tii2) ); // Only node2 can coalescence CPPUNIT_ASSERT( areSame(4.0/pop_size, forest_2pop->rates_[0]) ); CPPUNIT_ASSERT_EQUAL( 0.0, forest_2pop->rates_[1] ); CPPUNIT_ASSERT_EQUAL( 0.0, forest_2pop->rates_[2] ); std::vector growth(2, 0.0); growth.at(1) = 1.0; forest_2pop->writable_model()->addGrowthRates(0, growth); growth.at(0) = 2.0; forest_2pop->writable_model()->addGrowthRates(1, growth); TimeIntervalIterator tii3(forest_2pop, forest_2pop->nodes()->at(0)); CPPUNIT_ASSERT_NO_THROW( forest_2pop->calcRates(*tii3) ); CPPUNIT_ASSERT( areSame(3.0/pop_size, forest_2pop->rates_[0]) ); CPPUNIT_ASSERT( areSame(1.0/pop_size, forest_2pop->rates_[1]) ); CPPUNIT_ASSERT( areSame(0.0/pop_size, forest_2pop->rates_[2]) ); CPPUNIT_ASSERT_EQUAL( (size_t)1, forest_2pop->active_nodes_timelines_[0] ); CPPUNIT_ASSERT_EQUAL( (size_t)0, forest_2pop->active_nodes_timelines_[1] ); forest_2pop->writable_model()->increaseTime(); CPPUNIT_ASSERT_NO_THROW( forest_2pop->calcRates(*tii3) ); //CPPUNIT_ASSERT_EQUAL( 0.0/pop_size, forest_2pop->rates_[0] ); //CPPUNIT_ASSERT_EQUAL( 1.0/pop_size, forest_2pop->rates_[1] ); //CPPUNIT_ASSERT_EQUAL( 3.0/pop_size, forest_2pop->rates_[2] ); CPPUNIT_ASSERT_EQUAL( (size_t)1, forest_2pop->active_nodes_timelines_[0] ); CPPUNIT_ASSERT_EQUAL( (size_t)2, forest_2pop->active_nodes_timelines_[1] ); node2->set_population(1); CPPUNIT_ASSERT_NO_THROW( forest_2pop->calcRates(*tii3) ); //CPPUNIT_ASSERT_EQUAL( 0.0/pop_size, forest_2pop->rates_[0] ); //CPPUNIT_ASSERT( areSame(3.0/pop_size, forest_2pop->rates_[1]) ); //CPPUNIT_ASSERT_EQUAL( 0.0/pop_size, forest_2pop->rates_[2] ); CPPUNIT_ASSERT_EQUAL( (size_t)1, forest_2pop->active_nodes_timelines_[0] ); CPPUNIT_ASSERT_EQUAL( (size_t)1, forest_2pop->active_nodes_timelines_[1] ); delete node1; delete node2; } void testCalcRateWithArachicSamples() { Node* node1 = forest->nodes()->createNode(20, 5); forest->nodes()->add(node1); TimeIntervalIterator tii(forest, node1); double pop_size = 2*forest->model().population_size(0); forest->set_active_node(0, node1); forest->set_active_node(1, forest->local_root()); forest->states_[0] = 1; forest->states_[1] = 1; CPPUNIT_ASSERT_NO_THROW( forest->calcRates(*tii) ); CPPUNIT_ASSERT( areSame(1.0/pop_size, forest->rates_[0]) ); CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[1] ); CPPUNIT_ASSERT_EQUAL( 0.0, forest->rates_[2] ); } void testGetNodeState() { CPPUNIT_ASSERT( forest->getNodeState(forest->getNodes()->get(8), 11) == 1 ); CPPUNIT_ASSERT( forest->getNodeState(forest->getNodes()->get(6), 11) == 2 ); CPPUNIT_ASSERT( forest->getNodeState(forest->getNodes()->get(7), 11) == 1 ); } void testPrintTree() { //CPPUNIT_ASSERT_NO_THROW( forest->printTree() ); } void testSelectFirstTime() { double current_time = -1.0; size_t time_line = -1; forest->selectFirstTime(-1, 1, current_time, time_line); CPPUNIT_ASSERT_EQUAL( -1.0, current_time ); forest->selectFirstTime(5.0, 1, current_time, time_line); CPPUNIT_ASSERT_EQUAL( 5.0, current_time ); CPPUNIT_ASSERT_EQUAL( (size_t)1, time_line ); forest->selectFirstTime(7.0, 2, current_time, time_line); CPPUNIT_ASSERT_EQUAL( 5.0, current_time ); CPPUNIT_ASSERT_EQUAL( (size_t)1, time_line ); forest->selectFirstTime(-1, 2, current_time, time_line); CPPUNIT_ASSERT_EQUAL( 5.0, current_time ); CPPUNIT_ASSERT_EQUAL( (size_t)1, time_line ); forest->selectFirstTime(4.0, 2, current_time, time_line); CPPUNIT_ASSERT_EQUAL( 4.0, current_time ); CPPUNIT_ASSERT_EQUAL( (size_t)2, time_line ); } void testSampleEventType() { Event event; Forest *forest2 = forest_2pop; forest2->nodes()->at(0)->set_population(1); forest2->nodes()->at(1)->set_population(1); forest2->writable_model()->addMigrationRates(1, std::vector(4, 5.0), false, true); forest2->writable_model()->addGrowthRates(0.2, std::vector(2, 0.000125)); forest2->writable_model()->addGrowthRates(1, std::vector(2, 0.0)); forest2->writable_model()->addGrowthRates(2, std::vector(2, 2)); forest2->writable_model()->finalize(); forest2->writable_model()->resetTime(); TimeIntervalIterator tii(forest2, forest2->nodes()->at(0)); forest2->set_active_node(0, forest2->nodes()->at(0)); forest2->set_active_node(1, forest2->nodes()->at(2)); forest2->states_[0] = 1; forest2->states_[1] = 0; forest2->calcRates(*tii); forest2->active_nodes_timelines_[0] = 0; forest2->active_nodes_timelines_[1] = 0; forest2->sampleEventType(-1, 0, *tii, event); CPPUNIT_ASSERT( event.isNoEvent() ); forest2->sampleEventType(0.5, 0, *tii, event); CPPUNIT_ASSERT_EQUAL( 0.5, event.time() ); CPPUNIT_ASSERT( event.isCoalescence() ); // Only coalescence possible for (size_t i = 0; i < 1000; ++i) { forest2->sampleEventType(0.5, 0, *tii, event); CPPUNIT_ASSERT( event.isCoalescence() ); CPPUNIT_ASSERT( event.node() == forest2->active_node(0) ); }; // Coalescence of two nodes // active_node 0: Pop 1, 2 Contemporaries // active_node 1: Pop 0, 2 Contemporaries // => 50% each forest2->states_[1] = 1; forest2->calcRates(*tii); size_t count = 0, count2 = 0; for (size_t i = 0; i < 10000; ++i) { forest2->sampleEventType(0.5, 0, *tii, event); CPPUNIT_ASSERT( event.isCoalescence() ); count += (event.node() == forest2->active_node(0)); }; CPPUNIT_ASSERT( 4900 < count && count < 5100 ); // ~5000 // Test with Pw Coalescence // active_node 0: Pop 1, 2 Contemporaries // active_node 1: Pop 1, 2 Contemporaries // 4/5 Prob of Coalescence, 1/5 of Pw coalescence forest2->writable_model()->resetTime(); forest2->set_active_node(1, forest2->nodes()->at(1)); forest2->calcRates(*tii); count = 0; for (size_t i = 0; i < 10000; ++i) { forest2->sampleEventType(0.5, 0, *tii, event); CPPUNIT_ASSERT( event.isCoalescence() || event.isPwCoalescence() ); count += event.isCoalescence(); }; CPPUNIT_ASSERT( 7900 < count && count < 8100 ); // Test with migration // active_node 0: Pop 1, 2 Contemporaries // active_node 1: Pop 1, 2 Contemporaries // => Coal: 4/2Ne, Pw Coal: 1/2Ne // Migration: 2 * 5/4Ne // => 40% Coal, 10% Pw Coal, 50% Mig forest2->writable_model()->increaseTime(); forest2->writable_model()->increaseTime(); forest2->calcRates(*tii); count = 0; for (size_t i = 0; i < 10000; ++i) { forest2->sampleEventType(0.5, 0, *tii, event); CPPUNIT_ASSERT( event.isCoalescence() || event.isPwCoalescence() || event.isMigration() ); count += event.isMigration(); count2 += event.isCoalescence(); }; CPPUNIT_ASSERT( 4900 < count && count < 5100 ); CPPUNIT_ASSERT( 3900 < count2 && count2 < 4100 ); // Coalescence and Recombination // active_node 0: Pop 1, 2 Contemporaries => Coal rate: 2 / 2 * Ne = 1/Ne // active_node 1: Pop 1, Recombination => Rec rate: 10 Bases * 0.4 / 4Ne = 1/Ne // => 50% Recombination, 50% Coalescence forest2->writable_model()->setLocusLength(101); forest2->writable_model()->setRecombinationRate(0.4, false, true); forest2->set_current_base(10); forest2->active_node(1)->make_nonlocal(forest2->current_rec_); forest2->set_next_base(20); forest2->current_rec_++; forest2->states_[0] = 1; forest2->states_[1] = 2; forest2->writable_model()->resetTime(); // set migration to 0 forest2->calcRates(*tii); count = 0; for (size_t i = 0; i < 100000; ++i) { forest2->sampleEventType(0.5, 0, *tii, event); CPPUNIT_ASSERT( event.isCoalescence() || event.isRecombination() ); count += event.isRecombination(); }; CPPUNIT_ASSERT( 49500 < count && count < 50500 ); // Other way round Node* tmp = forest2->active_node(1); forest2->set_active_node(1, forest2->active_node(0)); forest2->set_active_node(0, tmp); forest2->states_[0] = 2; forest2->states_[1] = 1; forest2->calcRates(*tii); count = 0; for (size_t i = 0; i < 100000; ++i) { forest2->sampleEventType(0.5, 0, *tii, event); CPPUNIT_ASSERT( event.isCoalescence() || event.isRecombination() ); count += event.isRecombination(); }; CPPUNIT_ASSERT( 49500 < count && count < 50500 ); // True with >95% // Double recombination // => 1/3 active_node 0 // 2/3 active_node 1 forest2->states_[0] = 2; forest2->states_[1] = 2; forest2->set_current_base(10.0); forest2->set_next_base(15.0); forest2->set_next_base(20.0); forest2->current_rec_ += 2; forest2->active_node(0)->make_nonlocal(forest2->current_rec_ - 1); forest2->active_node(1)->make_nonlocal(forest2->current_rec_ - 2); forest2->calcRates(*tii); count = 0; for (size_t i = 0; i < 15000; ++i) { forest2->sampleEventType(0.5, 0, *tii, event); CPPUNIT_ASSERT( event.isRecombination() ); count += (event.node() == forest2->active_node(0)); }; CPPUNIT_ASSERT( 4880 < count && count < 5120 ); // True with >96% // Recombination with Rate 0 // active_node 1: Up to date = rec rate = 0; // => always coalescence forest2->states_[0] = 1; forest2->active_node(0)->make_local(); forest2->active_node(1)->set_last_update(forest2->current_rec_); forest2->calcRates(*tii); for (size_t i = 0; i < 1000; ++i) { forest2->sampleEventType(0.5, 0, *tii, event); CPPUNIT_ASSERT( event.isCoalescence() ); }; // Combinations With Growth forest2->writable_model()->resetTime(); forest2->writable_model()->increaseTime(); forest2->writable_model()->increaseTime(); forest2->writable_model()->increaseTime(); forest2->states_[0] = 1; forest2->states_[1] = 1; forest2->active_node(0)->set_population(0); forest2->active_node(1)->set_population(1); forest2->calcRates(*tii); for (size_t i = 0; i < 100; ++i) { CPPUNIT_ASSERT_NO_THROW( forest2->sampleEventType(0.5, 0, *tii, event) ); CPPUNIT_ASSERT( event.isMigration() ); CPPUNIT_ASSERT_NO_THROW( forest2->sampleEventType(0.5, 1, *tii, event) ); CPPUNIT_ASSERT( event.isCoalescence() ); CPPUNIT_ASSERT( event.node() == forest2->active_node(0) ); CPPUNIT_ASSERT_NO_THROW( forest2->sampleEventType(0.5, 2, *tii, event) ); CPPUNIT_ASSERT( event.isCoalescence() ); CPPUNIT_ASSERT( event.node() == forest2->active_node(1) ); }; forest2->active_node(0)->set_population(0); forest2->active_node(1)->set_population(0); forest2->calcRates(*tii); for (size_t i = 0; i < 100; ++i) { CPPUNIT_ASSERT_NO_THROW( forest2->sampleEventType(0.5, 0, *tii, event) ); CPPUNIT_ASSERT( event.isMigration() ); CPPUNIT_ASSERT_NO_THROW( forest2->sampleEventType(0.5, 1, *tii, event) ); CPPUNIT_ASSERT( event.isCoalescence() || event.isPwCoalescence() ); }; } void testCalcRecombinationRate() { forest->writable_model()->setRecombinationRate(1, false, false, 0); forest->writable_model()->setRecombinationRate(2, false, false, 10); forest->writable_model()->setRecombinationRate(3, false, false, 15); forest->writable_model()->setRecombinationRate(4, false, false, 20); forest->writable_model()->resetSequencePosition(); Node* node = forest->nodes()->at(6); forest->set_next_base(7.0); forest->current_rec_++; CPPUNIT_ASSERT_EQUAL( 2.0, forest->calcRecombinationRate(node) ); forest->writable_model()->increaseSequencePosition(); forest->set_current_base(12); CPPUNIT_ASSERT_EQUAL( 5.0+2*2, forest->calcRecombinationRate(node) ); forest->writable_model()->increaseSequencePosition(); forest->set_current_base(17); CPPUNIT_ASSERT_EQUAL( 5.0+10.0+6.0, forest->calcRecombinationRate(node) ); forest->writable_model()->increaseSequencePosition(); forest->set_current_base(22); CPPUNIT_ASSERT_EQUAL( 5.0+10.0+15.0+8.0, forest->calcRecombinationRate(node) ); } void testSampleEvent() { Model model = Model(5); Forest forest2 = Forest(&model, rg); forest2.createScaledExampleTree(); forest2.writable_model()->finalize(); forest2.writable_model()->resetTime(); TimeIntervalIterator tii(&forest2, forest2.nodes()->at(0)); forest2.set_active_node(0, forest2.nodes()->at(0)); forest2.set_active_node(1, forest2.nodes()->at(8)); forest2.states_[0] = 1; forest2.states_[1] = 0; forest2.calcRates(*tii); forest2.active_nodes_timelines_[0] = 0; forest2.active_nodes_timelines_[1] = 0; Event event; double tmp_event_time = 0.0; for (size_t i = 0; i < 1000; ++i) { forest2.sampleEvent(*tii, tmp_event_time, event); CPPUNIT_ASSERT( event.isNoEvent() || ( 0 <= event.time() && event.time() < forest2.nodes()->at(4)->height() ) ); CPPUNIT_ASSERT( event.isNoEvent() || event.isCoalescence() ); } ++tii; forest2.calcRates(*tii); for (size_t i = 0; i < 1000; ++i) { forest2.sampleEvent(*tii, tmp_event_time, event); CPPUNIT_ASSERT( event.isNoEvent() || ( forest2.nodes()->at(4)->height() <= event.time() && event.time() < forest2.nodes()->at(5)->height() ) ); CPPUNIT_ASSERT( event.isNoEvent() || event.isCoalescence() ); } } void testNodeIsOld() { forest->set_current_base(5.0); forest->set_next_base(15); forest->current_rec_++; forest->writable_model()->disable_approximation(); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(0)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(5)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(6)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(7)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(8)) ); forest->writable_model()->set_window_length_seq(5); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(0)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(5)) ); CPPUNIT_ASSERT( forest->nodeIsOld(forest->nodes()->at(6)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(7)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(8)) ); forest->writable_model()->set_window_length_seq(9.5); CPPUNIT_ASSERT( forest->nodeIsOld(forest->nodes()->at(6)) ); forest->writable_model()->set_window_length_seq(10.5); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(6)) ); forest->createExampleTree(); forest->writable_model()->set_window_length_rec(2); forest->set_next_base(15); forest->current_rec_++; forest->set_next_base(20); forest->current_rec_++; CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(0)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(5)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(6)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(7)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(8)) ); forest->set_next_base(25); forest->current_rec_++; CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(0)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(5)) ); CPPUNIT_ASSERT( forest->nodeIsOld(forest->nodes()->at(6)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(7)) ); CPPUNIT_ASSERT(! forest->nodeIsOld(forest->nodes()->at(8)) ); } void testPrune() { // Old node forest->set_current_base(5.0); forest->set_next_base(15); forest->current_rec_++; forest->writable_model()->disable_approximation(); forest->writable_model()->set_window_length_seq(5); CPPUNIT_ASSERT( forest->model().has_approximation() ); CPPUNIT_ASSERT( forest->model().has_window_seq() ); CPPUNIT_ASSERT( !forest->model().has_window_rec() ); CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(0)) ); CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(1)) ); CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(2)) ); CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(3)) ); CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(4)) ); CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(5)) ); CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(7)) ); CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(8)) ); CPPUNIT_ASSERT( forest->pruneNodeIfNeeded(forest->nodes()->at(6)) ); CPPUNIT_ASSERT( forest->nodes()->size() == 8); CPPUNIT_ASSERT( forest->checkTree() ); // Orphaned node CPPUNIT_ASSERT( forest->pruneNodeIfNeeded(forest->nodes()->at(6)) ); CPPUNIT_ASSERT( forest->nodes()->size() == 7); CPPUNIT_ASSERT( forest->checkTree() == 1 ); // In-Between Nodes should be pruned, iff they are of same age Node *parent = forest->nodes()->createNode(20), *inbetween1 = forest->nodes()->createNode(19), *inbetween2 = forest->nodes()->createNode(18), *child = forest->nodes()->createNode(17); forest->set_current_base(13); inbetween2->make_nonlocal(forest->current_rec_); child->make_nonlocal(forest->current_rec_); forest->set_next_base(15); forest->current_rec_++; parent->make_nonlocal(forest->current_rec_); inbetween1->make_nonlocal(forest->current_rec_); forest->nodes()->add(parent); forest->nodes()->add(inbetween1); forest->nodes()->add(inbetween2); forest->nodes()->add(child); parent->set_first_child(inbetween1); inbetween1->set_first_child(inbetween2); inbetween2->set_first_child(child); child->set_parent(inbetween2); inbetween2->set_parent(inbetween1); inbetween1->set_parent(parent); CPPUNIT_ASSERT( !forest->nodeIsOld(inbetween2) ); CPPUNIT_ASSERT( forest->pruneNodeIfNeeded(inbetween2) ); CPPUNIT_ASSERT_EQUAL(inbetween1, child->parent()); CPPUNIT_ASSERT( inbetween1->parent() == parent ); CPPUNIT_ASSERT( parent->is_root() ); CPPUNIT_ASSERT( parent->first_child() == inbetween1 ); CPPUNIT_ASSERT( inbetween1->first_child() == child ); CPPUNIT_ASSERT( child->countChildren() == 0 ); forest->nodes()->at(0)->set_parent(NULL); CPPUNIT_ASSERT(! forest->pruneNodeIfNeeded(forest->nodes()->at(0)) ); } void testBuildInitialTree() { Model model = Model(5); for (size_t i = 0; i < 100; ++i) { Forest frst = Forest(&model, rg); frst.buildInitialTree(); CPPUNIT_ASSERT_EQUAL(true, frst.checkTree()); CPPUNIT_ASSERT( frst.current_base() == 0.0 ); CPPUNIT_ASSERT( frst.next_base() > 0.0 ); } model = Model(2); model.set_population_number(2); model.addSampleSizes(0.0, std::vector(2, 1)); model.addSymmetricMigration(0.0, 5.0, true, true); model.finalize(); Forest frst = Forest(&model, rg); CPPUNIT_ASSERT_NO_THROW( frst.buildInitialTree() ); CPPUNIT_ASSERT_EQUAL( true, frst.checkTree() ); size_t i = 0; for (size_t j = 0; j < 4; ++j) { CPPUNIT_ASSERT( frst.nodes()->at(j)->population() == 0 || frst.nodes()->at(j)->population() == 1 ); i += frst.nodes()->at(j)->population(); } CPPUNIT_ASSERT_EQUAL( (size_t)1, i ); model = Model(0); model.set_population_number(2); std::vector sample_size(2, 1); sample_size.at(1) = 0; model.addSampleSizes(0.0, sample_size); sample_size.at(0) = 0; sample_size.at(1) = 1; model.addSampleSizes(1.0, sample_size); model.addSymmetricMigration(0.0, 5.0, true, true); model.finalize(); frst = Forest(&model, rg); CPPUNIT_ASSERT_NO_THROW( frst.buildInitialTree() ); CPPUNIT_ASSERT_EQUAL( true, frst.checkTree() ); CPPUNIT_ASSERT_EQUAL( (size_t)0, frst.nodes()->at(0)->population() ); CPPUNIT_ASSERT_EQUAL( (size_t)1, frst.nodes()->at(1)->population() ); CPPUNIT_ASSERT_EQUAL( 0.0, frst.nodes()->at(0)->height() ); CPPUNIT_ASSERT_EQUAL( 1.0, frst.nodes()->at(1)->height() ); } void testCut() { Node* base_node = forest->nodes()->at(4); Node* new_root = forest->cut(TreePoint(base_node, 3.5, false)); CPPUNIT_ASSERT_EQUAL((size_t)11, forest->nodes()->size()); CPPUNIT_ASSERT( new_root->local() ); CPPUNIT_ASSERT( new_root->is_root() ); CPPUNIT_ASSERT_EQUAL((size_t)1, new_root->countChildren() ); CPPUNIT_ASSERT_EQUAL(3.5, new_root->height() ); CPPUNIT_ASSERT( base_node->parent() == new_root ); CPPUNIT_ASSERT( base_node->local() ); Node* single_branch = forest->local_root()->first_child(); CPPUNIT_ASSERT( !single_branch->local() ); CPPUNIT_ASSERT_EQUAL( forest->segment_count(), single_branch->last_update() ); CPPUNIT_ASSERT_EQUAL( (size_t)0, single_branch->countChildren() ); CPPUNIT_ASSERT_EQUAL( 3.5, single_branch->height() ); } void testImplementRecombination() { Node* new_root = forest->cut(TreePoint(forest->nodes()->at(4), 3.5, false)); TimeIntervalIterator tii(forest, new_root); forest->set_active_node(0, new_root); forest->set_active_node(1, forest->local_root()); forest->states_[0] = 2; forest->states_[1] = 0; Event event = Event(3.7); event.setToCoalescence(new_root, 0); forest->tmp_event_ = event; forest->implementCoalescence(event, tii); ++tii; forest->set_current_base(100); event.set_time(4.5); event.setToRecombination(forest->active_node(0), 0); CPPUNIT_ASSERT_NO_THROW( forest->implementRecombination(event, tii) ); CPPUNIT_ASSERT( forest->nodes()->at(9) == forest->active_node(0) || forest->nodes()->at(10) == forest->active_node(0) ); CPPUNIT_ASSERT( forest->active_node(0)->local() ); CPPUNIT_ASSERT( forest->active_node(0)->is_root() ); CPPUNIT_ASSERT_EQUAL( (size_t)1, forest->active_node(0)->countChildren() ); Node* single_branch = forest->nodes()->at(9); if( forest->nodes()->at(9) == forest->active_node(0) ) single_branch = forest->nodes()->at(10); CPPUNIT_ASSERT( !single_branch->local() ); CPPUNIT_ASSERT_EQUAL( (size_t)0, single_branch->countChildren() ); CPPUNIT_ASSERT_EQUAL( (size_t)1, single_branch->last_update() ); } void testImplementCoalescence() { for (size_t i=0; i<100; ++i) { forest->createExampleTree(); Node* new_root = forest->cut(TreePoint(forest->nodes()->at(1), 1.5, false)); TimeIntervalIterator tii(forest, new_root); CPPUNIT_ASSERT_EQUAL( (size_t)3, forest->contemporaries_.size(0) ); forest->set_active_node(0, new_root); forest->set_active_node(1, forest->local_root()); forest->states_[0] = 1; forest->states_[1] = 0; forest->tmp_event_ = Event(2.0); forest->tmp_event_.setToCoalescence(new_root, 0); forest->implementCoalescence(forest->tmp_event_, tii); CPPUNIT_ASSERT( forest->active_node(0) == new_root ); CPPUNIT_ASSERT( new_root->parent_height() == 3 || new_root->parent_height() == 10 ); if ( !new_root->local() ) { CPPUNIT_ASSERT( new_root->countChildren() == 2 ); CPPUNIT_ASSERT( !(new_root->first_child()->local() && new_root->second_child()->local()) ); Node* child = new_root->first_child(); if (!new_root->second_child()->local()) child = new_root->second_child(); CPPUNIT_ASSERT( child->last_update() == 1 ); CPPUNIT_ASSERT( child->length_below() == 0 ); CPPUNIT_ASSERT( new_root->last_update() == 1 ); } } } void testImplementFixTimeEvent() { Model* model2 = new Model(5); model2->set_population_number(3); model2->addSingleMigrationEvent(0.5, 0, 1, 1.0); Forest* forest2 = new Forest(model2, rg); forest2->createExampleTree(); Node* new_root = forest2->cut(TreePoint(forest2->nodes()->at(1), 0.5, false)); forest2->set_active_node(0, new_root); forest2->set_active_node(1, forest2->local_root()); forest2->states_[0] = 1; forest2->states_[1] = 0; TimeIntervalIterator tii(forest2, new_root); CPPUNIT_ASSERT( new_root->population() == 0 ); forest2->implementFixedTimeEvent(tii); CPPUNIT_ASSERT( new_root->is_root() ); CPPUNIT_ASSERT( new_root->population() == 1 ); // Chained events new_root->set_population(0); model2->addSingleMigrationEvent(0.5, 1, 2, 1.0); forest2->implementFixedTimeEvent(tii); CPPUNIT_ASSERT( new_root->is_root() ); CPPUNIT_ASSERT( new_root->population() == 2 ); // Circes do not cause problems model2->addSingleMigrationEvent(0.5, 2, 0, 1.0); forest2->implementFixedTimeEvent(tii); CPPUNIT_ASSERT( new_root->is_root() ); CPPUNIT_ASSERT( new_root->population() == 0 ); delete forest2; delete model2; } void testSamplePoint() { rg->set_seed(1234); forest->createScaledExampleTree(); TreePoint point; int n0 = 0, n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0; for (int i = 0; i < 240000; ++i) { point = forest->samplePoint(); CPPUNIT_ASSERT( point.base_node() != NULL ); CPPUNIT_ASSERT( point.base_node()->local() ); if (point.base_node() == forest->nodes()->at(0)) ++n0; if (point.base_node() == forest->nodes()->at(1)) ++n1; if (point.base_node() == forest->nodes()->at(2)) ++n2; if (point.base_node() == forest->nodes()->at(3)) ++n3; if (point.base_node() == forest->nodes()->at(4)) ++n4; if (point.base_node() == forest->nodes()->at(5)) ++n5; } //std::cout << n0 << " " << n1 << " " << n2 << " " // << n3 << " " << n4 << " " << n5 << std::endl; CPPUNIT_ASSERT( 29500 <= n0 && n0 <= 30500 ); // expected 30000 CPPUNIT_ASSERT( 29500 <= n1 && n1 <= 30500 ); // expected 30000 CPPUNIT_ASSERT( 9800 <= n2 && n2 <= 10200 ); // expected 10000 CPPUNIT_ASSERT( 9800 <= n3 && n3 <= 10200 ); // expected 10000 CPPUNIT_ASSERT( 89000 <= n4 && n4 <= 91000 ); // expected 90000 CPPUNIT_ASSERT( 69000 <= n5 && n5 <= 71000 ); // expected 70000 } void testCopyConstructor() { forest->createScaledExampleTree(); forest->set_next_base(10.0); CPPUNIT_ASSERT( forest->coalescence_finished_ == true ); Forest forest2(*forest); CPPUNIT_ASSERT_EQUAL(forest->nodes()->size(), forest2.nodes()->size() ); CPPUNIT_ASSERT(forest2.model_ == forest->model_); CPPUNIT_ASSERT(forest2.local_root() != NULL); CPPUNIT_ASSERT(forest2.local_root() != forest->local_root()); CPPUNIT_ASSERT_EQUAL(forest->rec_bases_.size(), forest2.rec_bases_.size()); CPPUNIT_ASSERT_EQUAL(forest->current_base(), forest2.current_base()); for (auto it = forest2.nodes()->iterator(); it.good(); ++it) { CPPUNIT_ASSERT( (*it)->label() <= 4 ); CPPUNIT_ASSERT( (*it)->parent() != NULL || (*it)->first_child() != NULL ); } CPPUNIT_ASSERT( forest2.checkLeafsOnLocalTree() ); CPPUNIT_ASSERT( forest2.checkTree() ); forest2.sampleNextGenealogy(); CPPUNIT_ASSERT( forest2.checkTree() ); } void testCheckForNodeAtHeight() { CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 0.0 ) ); CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 1.0 ) ); CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 3.0 ) ); CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 4.0 ) ); CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 6.0 ) ); CPPUNIT_ASSERT( forest->checkForNodeAtHeight( 10.0 ) ); CPPUNIT_ASSERT( !forest->checkForNodeAtHeight( 0.5 ) ); CPPUNIT_ASSERT( !forest->checkForNodeAtHeight( 1.5 ) ); CPPUNIT_ASSERT( !forest->checkForNodeAtHeight( 2.0 ) ); CPPUNIT_ASSERT( !forest->checkForNodeAtHeight( 9.0 ) ); CPPUNIT_ASSERT( !forest->checkForNodeAtHeight( 20.0 ) ); } void testPrintLocusSumStats() { ostringstream output; forest->writable_model()->addSummaryStatistic(std::make_shared()); forest->set_current_base(0); forest->set_next_base(forest->model().loci_length()); forest->calcSegmentSumStats(); forest->printLocusSumStats(output); CPPUNIT_ASSERT( output.str() != "" ); } void testSampleNextPosition() { forest->createScaledExampleTree(); forest->writable_model()->setRecombinationRate(0.0); forest->writable_model()->setRecombinationRate(1.0, false, false, 3); forest->sampleNextBase(); CPPUNIT_ASSERT_EQUAL(3.0, forest->next_base()); CPPUNIT_ASSERT_EQUAL(1.0, forest->model().recombination_rate()); } void testClear() { forest->createScaledExampleTree(); forest->writable_model()->setRecombinationRate(0.0); forest->writable_model()->setRecombinationRate(1.0, false, false, 3); forest->writable_model()->addSymmetricMigration(1.0, 0.5); forest->writable_model()->increaseSequencePosition(); forest->writable_model()->increaseTime(); CPPUNIT_ASSERT_EQUAL(3.0, forest->model().getCurrentSequencePosition()); CPPUNIT_ASSERT_EQUAL(1.0, forest->model().getCurrentTime()); forest->clear(); CPPUNIT_ASSERT_EQUAL((size_t)0, forest->nodes()->size()); CPPUNIT_ASSERT_EQUAL((size_t)1, forest->rec_bases_.size()); CPPUNIT_ASSERT_EQUAL((size_t)0, forest->segment_count()); CPPUNIT_ASSERT_EQUAL(-1.0, forest->current_base()); CPPUNIT_ASSERT_EQUAL(0.0, forest->model().getCurrentSequencePosition()); CPPUNIT_ASSERT_EQUAL(0.0, forest->model().getCurrentTime()); } }; //Uncomment this to activate the test CPPUNIT_TEST_SUITE_REGISTRATION( TestForest );