A toolkit for working with phylogenetic data.
v0.18.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
taxonomy.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2017 Lucas Czech
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  Contact:
19  Lucas Czech <lucas.czech@h-its.org>
20  Exelixis Lab, Heidelberg Institute for Theoretical Studies
21  Schloss-Wolfsbrunnenweg 35, D-69118 Heidelberg, Germany
22 */
23 
32 
34 
35 #include <algorithm>
36 #include <stdexcept>
37 
38 namespace genesis {
39 namespace taxonomy {
40 
41 // =================================================================================================
42 // Constructors and Rule of Five
43 // =================================================================================================
44 
52  : children_( other.children_ )
53 {
54  reset_parent_pointers_( nullptr );
55 }
56 
64  : children_( std::move( other.children_ ))
65 {
66  reset_parent_pointers_( nullptr );
67 }
68 
76 {
77  children_ = other.children_;
78  reset_parent_pointers_( nullptr );
79  return *this;
80 }
81 
89 {
90  children_ = std::move( other.children_ );
91  reset_parent_pointers_( nullptr );
92  return *this;
93 }
94 
98 void swap( Taxonomy& lhs, Taxonomy& rhs )
99 {
100  using std::swap;
101  swap( lhs.children_, rhs.children_ );
102 }
103 
104 // =================================================================================================
105 // Accessors
106 // =================================================================================================
107 
113 size_t Taxonomy::size() const
114 {
115  return children_.size();
116 }
117 
121 bool Taxonomy::has_child ( std::string name ) const
122 {
123  return children_.end() != std::find_if(
124  children_.begin(),
125  children_.end(),
126  [ &name ] ( Taxon const& r ) {
127  return r.name() == name;
128  }
129  );
130 }
131 
135 Taxon const& Taxonomy::get_child ( std::string name ) const
136 {
137  for( auto const& c : children_ ) {
138  if( c.name() == name ) {
139  return c;
140  }
141  }
142  throw std::runtime_error( "Taxon has no child named '" + name + "'." );
143 }
144 
148 Taxon& Taxonomy::get_child ( std::string name )
149 {
150  for( auto& c : children_ ) {
151  if( c.name() == name ) {
152  return c;
153  }
154  }
155  throw std::runtime_error( "Taxon has no child named '" + name + "'." );
156 }
157 
161 Taxon const& Taxonomy::operator [] ( std::string name ) const
162 {
163  return get_child( name );
164 }
165 
169 Taxon& Taxonomy::operator [] ( std::string name )
170 {
171  return get_child( name );
172 }
173 
179 Taxon const& Taxonomy::at ( size_t index ) const
180 {
181  return children_.at( index );
182 }
183 
189 Taxon& Taxonomy::at ( size_t index )
190 {
191  return children_.at( index );
192 }
193 
199 Taxon const& Taxonomy::operator [] ( size_t index ) const
200 {
201  return children_[ index ];
202 }
203 
210 {
211  return children_[ index ];
212 }
213 
214 size_t Taxonomy::index_of( std::string const& name ) const
215 {
216  for( size_t i = 0; i < children_.size(); ++i ) {
217  if( children_[i].name() == name ) {
218  return i;
219  }
220  }
221  throw std::runtime_error( "Taxon has no child named '" + name + "'." );
222 }
223 
224 // =================================================================================================
225 // Modifiers
226 // =================================================================================================
227 
234 {
235  return add_child_( child );
236 }
237 
243 Taxon& Taxonomy::add_child( std::string const& name )
244 {
245  return add_child_( Taxon( name ));
246 }
247 
254 void Taxonomy::remove_child( std::string const& name )
255 {
256  auto it = std::find_if(
257  children_.begin(),
258  children_.end(),
259  [ &name ] ( Taxon const& r ) {
260  return r.name() == name;
261  }
262  );
263  if( it == children_.end() ) {
264  throw std::runtime_error( "Taxon has no child named '" + name + "'." );
265  }
266  children_.erase( it );
267 
268  // We probably don't need to call reset_parent_pointers_() here. The removal causes all
269  // following elements in the container to move, so that their particular move constructors
270  // (or assignment operators) are called, causing all their children to be updated. The
271  // elemetns themselves do not need an update, as their parent didn't move!
272  // (Hopefully, that's true... The tests don't fail, so that's a good sign!)
273 }
274 
279 {
280  children_.clear();
281 }
282 
283 // =================================================================================================
284 // Iterators
285 // =================================================================================================
286 
291 {
292  return children_.begin();
293 }
294 
299 {
300  return children_.end();
301 }
302 
307 {
308  return children_.cbegin();
309 }
310 
315 {
316  return children_.cend();
317 }
318 
323 {
324  return children_.cbegin();
325 }
326 
331 {
332  return children_.cend();
333 }
334 
335 // =================================================================================================
336 // Internal Implementation Details
337 // =================================================================================================
338 
353 {
354  // Check if a child taxon with the given name already exists.
355  for( auto& c : children_ ) {
356  if( c.name() == child.name() ) {
357 
358  // If so, add the children of the new child to it (recursively), and return it.
359  for( auto& child_children : child ) {
360  c.add_child_( child_children );
361  }
362  return c;
363  }
364  }
365 
366  // If not, add it as a a new child.
367  children_.push_back( child );
368  // children_.back().parent_ = nullptr;
369 
370  // We added to the container. This might have cause relocation of the contant.
371  // Need to update parent pointers!
372  reset_parent_pointers_( nullptr );
373  return children_.back();
374 }
375 
389 {
390  for( auto& taxon : children_ ) {
391  taxon.parent_ = parent;
392  // Probably don't need recursion here, as this function will be called for the sub-objects
393  // anyway if needed.
394  // The following line is left here in case it turns out we need it after all...
395  // taxon.reset_parent_pointers_( &taxon );
396  }
397 }
398 
399 } // namespace taxonomy
400 } // namespace genesis
Taxon & add_child_(Taxon const &child) override
Virtual implementation function for adding a child taxon.
Definition: taxon.cpp:280
Taxonomy & operator=(Taxonomy const &)
Copy assigment operator.
Definition: taxonomy.cpp:75
iterator begin()
Return an iterator to the beginning of the child taxa.
Definition: taxonomy.cpp:290
std::string const & name() const
Return the name of this taxon.
Definition: taxon.cpp:169
Taxon & add_child(Taxon const &child)
Add a child Taxon as a copy of a given Taxon and return it.
Definition: taxonomy.cpp:233
Taxon const & at(size_t index) const
Return the child Taxon at the given index.
Definition: taxonomy.cpp:179
std::vector< Taxon >::const_iterator const_iterator
bool has_child(std::string name) const
Return whether an immediate child Taxon with the given name exists.
Definition: taxonomy.cpp:121
Taxon const & get_child(std::string name) const
Return the child Taxon with a given name if it exists, or throw otherwise.
Definition: taxonomy.cpp:135
void reset_parent_pointers_(Taxon *parent)
Internal helper function that resets the parent pointer of all stored Taxa.
Definition: taxonomy.cpp:388
Store a Taxonomy, i.e., a nested hierarchy of Taxa.
std::vector< Taxon >::iterator iterator
size_t index_of(std::string const &name) const
Definition: taxonomy.cpp:214
const_iterator cend() const
Return a const iterator to the end of the child taxa.
Definition: taxonomy.cpp:330
Store a Taxon, i.e., an element in a Taxonomy, with its name, rank and sub-taxa.
Definition: taxon.hpp:76
void swap(Taxon &lhs, Taxon &rhs)
Swapperator for Taxon.
Definition: taxon.cpp:147
void remove_child(std::string const &name)
Remove a child Taxon with a certain name.
Definition: taxonomy.cpp:254
size_t size() const
Return the number of immediate child Taxa.
Definition: taxonomy.cpp:113
iterator end()
Return an iterator to the end of the child taxa.
Definition: taxonomy.cpp:298
const_iterator cbegin() const
Return a const iterator to the beginning of the child taxa.
Definition: taxonomy.cpp:322
void swap(Taxonomy &lhs, Taxonomy &rhs)
Swapperator for Taxonomy.
Definition: taxonomy.cpp:98
void clear_children()
Remove all children.
Definition: taxonomy.cpp:278
virtual Taxon & add_child_(Taxon const &child)
Virtual implementation function for adding a child Taxon.
Definition: taxonomy.cpp:352
Taxon const & operator[](std::string name) const
Return the child Taxon with a given name if it exists, or throw otherwise.
Definition: taxonomy.cpp:161