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