ʻOhana
Population structure, admixture history, and selection using learning methods.
jade.rerooted_tree.hpp
1 /* -------------------------------------------------------------------------
2  Ohana
3  Copyright (c) 2015-2020 Jade Cheng (\___/)
4  Jade Cheng <info@jade-cheng.com> (='.'=)
5  ------------------------------------------------------------------------- */
6 
7 #ifndef JADE_REROOTED_TREE_HPP__
8 #define JADE_REROOTED_TREE_HPP__
9 
10 #include "jade.tree_path.hpp"
11 
12 namespace jade
13 {
14  ///
15  /// A template for a class that maintains a list of paths from all leaf
16  /// nodes to the rerooted node with the name "0".
17  ///
18  template <typename TValue>
20  {
21  public:
22  /// The value type.
23  typedef TValue value_type;
24 
25  /// The tree path type.
27 
28  /// The Newick node type.
30 
31  /// The Newick node pointer type.
32  typedef std::unique_ptr<node_type> node_ptr_type;
33 
34  /// The tree path vector type.
35  typedef std::vector<path_type> vector_type;
36 
37  ///
38  /// Initialize a new instance of the class.
39  ///
41  : _rk (0)
42  , _node_ptr ()
43  , _vector ()
44  {
45  }
46 
47  ///
48  /// Initialize a new instance of the class.
49  ///
51  const node_type & node) ///< The node to validate and reroot.
52  : _rk (_validate_tree(node))
53  , _node_ptr (node.find_name("0")->reroot())
54  , _vector ()
55  {
56  const auto & tree = *_node_ptr;
57 
58  //
59  // Create a list of tree paths, one for each leaf node.
60  //
61  _vector.reserve(_rk);
62  for (size_t i = 1; i <= _rk; i++)
63  {
64  std::ostringstream name_stream;
65  name_stream << i;
66 
67  const auto name = name_stream.str();
68  const auto node_ptr = tree.find_name(name.c_str());
69  _vector.emplace_back(*node_ptr);
70  }
71  }
72 
73  ///
74  /// \return The rooted K value.
75  ///
76  inline size_t get_rk() const
77  {
78  return _rk;
79  }
80 
81  ///
82  /// \return The overlapping path between two nodes and the root node.
83  ///
85  const size_t node1, ///< The first node.
86  const size_t node2) ///< The second node.
87  const
88  {
89  return _vector[node1] & _vector[node2];
90  }
91 
92  ///
93  /// \return The tree path for the node with the name that corresponds
94  /// to the specified index.
95  ///
96  inline const path_type & get_path(
97  const size_t index) ///< The index of the node.
98  const
99  {
100  assert(index < _vector.size());
101  return _vector[index];
102  }
103 
104  ///
105  /// \return A reference to the rerooted tree.
106  ///
107  inline node_type & get_tree()
108  {
109  return *_node_ptr;
110  }
111 
112  ///
113  /// \return A reference to the rerooted tree.
114  ///
115  inline const node_type & get_tree() const
116  {
117  return *_node_ptr;
118  }
119 
120  ///
121  /// Resets the tree maintained by this instance.
122  ///
123  inline void reset(
124  const node_type & node) ///< The node to validate and reroot.
125  {
126  *this = basic_rerooted_tree(node);
127  }
128 
129  private:
130  // --------------------------------------------------------------------
131  static size_t _validate_tree(const node_type & tree)
132  {
133  //
134  // Gather references to the leaf nodes.
135  //
136  const auto leaf_nodes = tree.find_leafs();
137  const auto k = leaf_nodes.size();
138 
139  //
140  // Ensure there is at least one component.
141  //
142  if (k == 0)
143  throw error()
144  << "invalid Newick tree: there must be at "
145  << "least one node";
146 
147  //
148  // Ensure all leaf nodes are named and named uniquely.
149  //
150  std::set<std::string> names;
151  for (const auto leaf : leaf_nodes)
152  {
153  if (!leaf->has_name())
154  throw error() << "invalid Newick tree: at least one "
155  << "leaf node has no name";
156 
157  const auto & name = leaf->get_name();
158  if (names.find(name) != names.end())
159  throw error() << "invalid Newick tree; duplicate leaf "
160  << "node name '" << name << "'";
161 
162  names.insert(leaf->get_name());
163  }
164 
165  //
166  // Ensure leafs are named numerically based on their
167  // corresponding component; e.g. "0", "1", "2", etc.
168  //
169  for (size_t index = 0; index < k; index++)
170  {
171  std::ostringstream name_stream;
172  name_stream << index;
173 
174  const auto name = name_stream.str();
175  if (names.find(name) == names.end())
176  throw error() << "invalid Newick tree: missing leaf "
177  << "named '" << name << "'";
178  }
179 
180  //
181  // Return the rooted K value.
182  //
183  return k - 1;
184  };
185 
186  size_t _rk;
187  node_ptr_type _node_ptr;
188  vector_type _vector;
189  };
190 }
191 
192 #endif // JADE_REROOTED_TREE_HPP__
jade::basic_rerooted_tree::node_type
basic_newick_node< value_type > node_type
The Newick node type.
Definition: jade.rerooted_tree.hpp:29
jade::basic_rerooted_tree::reset
void reset(const node_type &node)
Resets the tree maintained by this instance.
Definition: jade.rerooted_tree.hpp:123
jade::basic_rerooted_tree::get_rk
size_t get_rk() const
Definition: jade.rerooted_tree.hpp:76
jade::basic_rerooted_tree::get_overlap
path_type get_overlap(const size_t node1, const size_t node2) const
Definition: jade.rerooted_tree.hpp:84
jade::basic_rerooted_tree::vector_type
std::vector< path_type > vector_type
The tree path vector type.
Definition: jade.rerooted_tree.hpp:35
jade::basic_newick_node
A template class representing a node from a Newick tree.
Definition: jade.newick.hpp:19
jade::basic_rerooted_tree::node_ptr_type
std::unique_ptr< node_type > node_ptr_type
The Newick node pointer type.
Definition: jade.rerooted_tree.hpp:32
jade::basic_rerooted_tree::get_tree
const node_type & get_tree() const
Definition: jade.rerooted_tree.hpp:115
jade::basic_tree_path< value_type >
jade::basic_rerooted_tree::basic_rerooted_tree
basic_rerooted_tree(const node_type &node)
Initialize a new instance of the class.
Definition: jade.rerooted_tree.hpp:50
jade::basic_rerooted_tree::path_type
basic_tree_path< value_type > path_type
The tree path type.
Definition: jade.rerooted_tree.hpp:26
jade::basic_rerooted_tree::get_tree
node_type & get_tree()
Definition: jade.rerooted_tree.hpp:107
jade::basic_rerooted_tree::basic_rerooted_tree
basic_rerooted_tree()
Initialize a new instance of the class.
Definition: jade.rerooted_tree.hpp:40
jade::basic_rerooted_tree::get_path
const path_type & get_path(const size_t index) const
Definition: jade.rerooted_tree.hpp:96
jade::basic_rerooted_tree
A template for a class that maintains a list of paths from all leaf nodes to the rerooted node with t...
Definition: jade.rerooted_tree.hpp:20
jade::basic_error
A template for a class representing an exception thrown from this namespace.
Definition: jade.error.hpp:20
jade::basic_rerooted_tree::value_type
TValue value_type
The value type.
Definition: jade.rerooted_tree.hpp:23