1 /*
2  * scrm is an implementation of the Sequential-Coalescent-with-Recombination Model.
3  *
4  * Copyright (C) 2013, 2014 Paul R. Staab, Sha (Joe) Zhu, Dirk Metzler and Gerton Lunter
5  *
6  * This file is part of scrm.
7  *
8  * scrm is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 /*
23  * node.h
24  *
25  * A Node is the most elemental unit of a tree/forest. It represents the
26  * point of coalescence of two branches, as well as the single branch above.
27  *
28  */
29 
30 #ifndef scrm_node
31 #define scrm_node
32 
33 #include "macros.h" // Needs to be before cassert
34 
35 #include <cstddef>
36 #include <cfloat>
37 #include <stdexcept>
38 #include <iostream>
39 #include <cassert>
40 #include <string>
41 
42 
43 class Node
44 {
45  public:
46 #ifdef UNITTEST
47   friend class TestForest;
48   friend class TestNode;
49   friend class TestNodeContainer;
50 #endif
51   friend class NodeContainer;
52 
53   ~Node();
54 
55   //Getters & Setters
56   void extract_bl_and_label ( std::string::iterator in_it );
57   double bl_;
bl()58   double bl() const { return this->bl_; }
set_bl(double bl)59   void set_bl ( double bl ) { this->bl_ = bl; }
60 
height()61   double height() const { return this->height_; }
set_height(const double height)62   void set_height(const double height) { this->height_ = height; }
63 
parent_height()64   double parent_height() const {
65     if ( this->is_root() ) return this->height();
66     return this->parent()->height();
67   }
68 
height_above()69   double height_above() const { return this->parent_height() - this->height(); }
70 
population()71   size_t population() const { return population_; }
set_population(const size_t pop)72   void set_population(const size_t pop) { population_ = pop; }
73 
local()74   bool local() const { return (last_update_ == 0); }
75 
make_local()76   void make_local() {
77     last_update_ = 0;
78   }
make_nonlocal(const size_t current_recombination)79   void make_nonlocal(const size_t current_recombination) {
80     assert( this->local() );
81     set_last_update(current_recombination);
82   }
83 
parent()84 	Node *parent() const {
85     assert( this->parent_ != NULL );
86     return this->parent_;
87   }
set_parent(Node * parent)88   void set_parent(Node *parent) { this->parent_ = parent; }
89 
second_child()90   Node *second_child() const { return this->second_child_; }
set_second_child(Node * second_child)91   void set_second_child(Node *second_child) { this->second_child_ = second_child; }
92 
first_child()93   Node *first_child() const { return this->first_child_; }
set_first_child(Node * first_child)94   void set_first_child(Node *first_child) { this->first_child_ = first_child; }
95 
last_update()96   size_t last_update() const { return last_update_; }
97 
last_change()98   size_t last_change() const { return last_change_; }
set_last_change(const size_t pos)99   void set_last_change(const size_t pos) { last_change_ = pos; }
100 
samples_below()101   size_t samples_below() const { return samples_below_; }
set_samples_below(size_t samples)102   void set_samples_below(size_t samples) { samples_below_ = samples; }
103 
length_below()104   double length_below() const { return length_below_; }
set_length_below(const double length)105   void set_length_below(const double length) { length_below_ = length; }
106 
107   void change_child(Node* from, Node* to);
108   size_t countChildren(const bool only_local = false) const;
109 
set_label(size_t label)110   void set_label(size_t label) { label_ = label; }
label()111   size_t label() const { return label_; }
112 
is_root()113   bool is_root() const { return ( this->parent_ == NULL ); }
in_sample()114   bool in_sample() const {
115     return ( this->label() != 0 );
116   }
117 
118   bool is_migrating() const;
119 
is_first()120   bool is_first() const { return( previous_ == NULL ); }
is_last()121   bool is_last() const { return( next_ == NULL ); }
122 
123   // Uminportant Nodes are nodes that sit at the top of the single
124   // top branch of a tree after it got cut away from the primary tree.
125   // These Nodes can be reused or removed if they are involved in an event.
is_unimportant()126   bool is_unimportant() const {
127     return (this->countChildren() == 1 && !this->is_migrating());
128   }
129 
is_contemporary(const double time)130   bool is_contemporary(const double time) {
131     return ( time <= height() && height() <= parent_height() );
132   }
133 
134   void remove_child(Node* child);
135 
next()136   Node* next() const {
137     if ( next_ == NULL ) throw std::out_of_range("Node has no next node");
138     return next_;
139   }
previous()140   Node* previous() const {
141     if ( previous_ == NULL ) throw std::out_of_range("Node has no previous node");
142     return previous_;
143   }
144 
set_next(Node * next)145   void set_next(Node* next) { next_ = next; }
set_previous(Node * previous)146   void set_previous(Node* previous) { previous_ = previous; }
147 
148   // Navigate on local tree
149   Node *getLocalParent() const;
150   Node *getLocalChild1() const;
151   Node *getLocalChild2() const;
152 
153  private:
154   Node();
155   Node(double height);
156   Node(double height, size_t label);
157 
158   void init(double heigh=-1, size_t label=0);
set_last_update(const size_t recombination)159   void set_last_update(const size_t recombination) { last_update_ = recombination; };
160 
161   size_t label_;
162   double height_;        // The total height of the node
163   size_t last_update_;   // The recombination on which the branch above the node
164                          // was last checked for recombination events or 0 if
165                          // the node is local
166   size_t last_change_;   // The recombination at which the subtree below the node
167                          // changed most recently.
168 
169   size_t population_;    // The number of the population the node belong to.
170 
171   size_t samples_below_; // the number of sampled nodes in the subtree below this node
172   double length_below_;  // the total length of local branches in the subtree below this node
173 
174   Node* next_;
175   Node* previous_;
176 
177   //The tree structure
178   Node *parent_;
179   Node *first_child_;
180   Node *second_child_;
181 };
182 
is_migrating()183 inline bool Node::is_migrating() const {
184   if ( this->countChildren() != 1 ) return false;
185   return ( this->population() != this->first_child()->population() );
186 }
187 
countChildren(const bool only_local)188 inline size_t Node::countChildren(const bool only_local) const {
189   if (first_child() == NULL) return 0;
190   if (!only_local) {
191     if (second_child() == NULL) return 1;
192     else return 2;
193   } else {
194     if (second_child() == NULL) {
195       if (first_child()->local()) return 1;
196       else return 0;
197     } else {
198       return first_child()->local() + second_child()->local();
199     }
200   }
201 }
202 
203 /** Hash nodes based on their height */
204 namespace std {
205   template <>
206   struct hash<Node*> {
207     std::size_t operator()(Node const* node) const {
208       return std::hash<double>()(node->height() - node->label());
209     }
210   };
211 }
212 #endif
213