A library for working with phylogenetic and population genetic data.
v0.27.0
sample.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2021 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 
36 
37 #include <algorithm>
38 #include <cassert>
39 #include <cmath>
40 #include <iomanip>
41 #include <map>
42 #include <sstream>
43 #include <stdexcept>
44 #include <stdio.h>
45 #include <unordered_map>
46 #include <utility>
47 
48 namespace genesis {
49 namespace placement {
50 
51 // =================================================================================================
52 // Constructor and Rule of Five
53 // =================================================================================================
54 
56  : tree_( tree )
57 {
58  if( ! tree::tree_data_is< PlacementNodeData, PlacementEdgeData >( tree_ ) ) {
59  throw std::runtime_error( "Tree for constructing the Sample is no PlacementTree." );
60  }
61 }
62 
63 Sample::Sample( Sample const& other )
64 {
65  // We need this custom ctor because the placements contain pointers to their edges.
66  // As the whole tree is copied, the pointers need to be adjusted to that new tree.
67 
68  // First, use normal copy assignment for the data structures.
69  pqueries_ = other.pqueries_;
70  tree_ = other.tree_;
71  metadata = other.metadata;
72 
73  // Now adjust all placement to edge pointers.
74  for( auto& pqry : pqueries_ ) {
75  for( auto& place : pqry.placements() ) {
76  // Get the index using the pointer to the (still valid) old edge.
77  // (Remember: the placement is still pointing to the old edge at that point.)
78  auto index = place.edge().index();
79 
80  // Now set the pointer of the placement to the edge of the new tree.
81  place.reset_edge( tree_.edge_at( index ) );
82  }
83  }
84 }
85 
87 {
88  // As we need a custom copy constructor, it is proably safer to also use a custom copy
89  // assignment, just to make sure that it actually does the copying part correctly.
90  // Use copy swap idiom.
91  auto tmp = Sample( other );
92  this->swap( tmp );
93  return *this;
94 }
95 
96 void Sample::swap( Sample& other )
97 {
98  using std::swap;
99  swap( pqueries_, other.pqueries_ );
100  swap( tree_, other.tree_ );
101  swap( metadata, other.metadata );
102 }
103 
104 void swap( Sample& lhs, Sample& rhs )
105 {
106  lhs.swap( rhs );
107 }
108 
109 // =================================================================================================
110 // Modifiers
111 // =================================================================================================
112 
114 {
115  pqueries_.clear();
116  tree_ = PlacementTree();
117  metadata.clear();
118 }
119 
120 // =================================================================================================
121 // Tree Accessors and Modifiers
122 // =================================================================================================
123 
125 {
126  return tree_;
127 }
128 
129 PlacementTree const& Sample::tree() const
130 {
131  return tree_;
132 }
133 
134 // =================================================================================================
135 // Pquery Accessors and Modifiers
136 // =================================================================================================
137 
138 size_t Sample::size() const
139 {
140  return pqueries_.size();
141 }
142 
143 bool Sample::empty() const
144 {
145  return tree_.empty() || pqueries_.empty();
146 }
147 
148 // -------------------------------------------------------------------------
149 // Add
150 // -------------------------------------------------------------------------
151 
153 {
154  pqueries_.push_back( Pquery() );
155  return pqueries_.back();
156 }
157 
158 Pquery& Sample::add( Pquery const& other )
159 {
160  pqueries_.push_back( other );
161 
162  // Adjust the edge pointers of the placements.
163  for( auto& place : pqueries_.back().placements() ) {
164  // Get the edge index of the old edge, then set the edge to the edge of the
165  // correct sample that is at that index.
166  auto const& old_edge_data = place.edge().data<PlacementEdgeData>();
167  auto const edge_index = place.edge().index();
168  auto const old_edge_num = old_edge_data.edge_num();
169  auto const rel_pos = place.proximal_length / old_edge_data.branch_length;
170  place.reset_edge( tree().edge_at( edge_index ));
171 
172  // Now the placement points to the new edge. We can thus check if this one still has the
173  // same edge_num as the old edge.
174  auto const& edge_data = place.edge().data<PlacementEdgeData>();
175  if( old_edge_num != edge_data.edge_num() ) {
176  throw std::runtime_error(
177  "Trees are incompatible for copying Pqueries between Samples."
178  );
179  }
180  place.proximal_length = rel_pos * edge_data.branch_length;
181  }
182 
183  return pqueries_.back();
184 }
185 
186 // -------------------------------------------------------------------------
187 // At
188 // -------------------------------------------------------------------------
189 
190 Pquery& Sample::at( const size_t index )
191 {
192  return pqueries_.at( index );
193 }
194 
195 Pquery const& Sample::at( const size_t index ) const
196 {
197  return pqueries_.at( index );
198 }
199 
200 // -------------------------------------------------------------------------
201 // Remove
202 // -------------------------------------------------------------------------
203 
204 void Sample::remove( size_t index )
205 {
206  pqueries_.erase( pqueries_.begin() + index );
207 }
208 
209 void Sample::remove( size_t first_index, size_t last_index )
210 {
211  if( first_index >= pqueries_.size()
212  || last_index >= pqueries_.size()
213  || first_index >= last_index
214  ) {
215  throw std::out_of_range( "Invalid indices for removing from SequenceSet." );
216  }
217 
218  pqueries_.erase( pqueries_.begin() + first_index, pqueries_.begin() + last_index );
219 }
220 
222 {
223  pqueries_.erase( position );
224 }
225 
227 {
228  pqueries_.erase( first, last );
229 }
230 
231 // -------------------------------------------------------------------------
232 // Clear
233 // -------------------------------------------------------------------------
234 
236 {
237  pqueries_.clear();
238 }
239 
240 // =================================================================================================
241 // Pquery Iterator
242 // =================================================================================================
243 
245 {
246  return pqueries_.begin();
247 }
248 
250 {
251  return pqueries_.begin();
252 }
253 
255 {
256  return pqueries_.end();
257 }
258 
260 {
261  return pqueries_.end();
262 }
263 
265 {
266  return { pqueries_ };
267 }
268 
270 {
271  return { pqueries_ };
272 }
273 
274 } // namespace placement
275 } // namespace genesis
genesis::placement::swap
void swap(Sample &lhs, Sample &rhs)
Definition: sample.cpp:104
genesis::placement::Sample::tree
PlacementTree & tree()
Get the PlacementTree of this Sample.
Definition: sample.cpp:124
genesis::placement::Sample::size
size_t size() const
Return the number of Pqueries that are stored in this Sample.
Definition: sample.cpp:138
genesis::placement::Sample::end
iterator_pqueries end()
Return an iterator to the end of the Pqueries of this Sample.
Definition: sample.cpp:254
genesis::placement::PlacementEdgeData::edge_num
EdgeNumType edge_num() const
Return the edge_num of this edge. This value is defined by the jplace standard.
Definition: placement_tree.hpp:194
genesis::placement::Sample::clear_pqueries
void clear_pqueries()
Clear all Pqueries of this Sample.
Definition: sample.cpp:235
genesis::placement::Sample
Manage a set of Pqueries along with the PlacementTree where the PqueryPlacements are placed on.
Definition: sample.hpp:68
genesis::placement::Sample::const_iterator_pqueries
std::vector< Pquery >::const_iterator const_iterator_pqueries
Definition: sample.hpp:78
genesis::tree::Tree::edge_at
TreeEdge & edge_at(size_t index)
Return the TreeEdge at a certain index.
Definition: tree/tree.hpp:238
genesis::placement::Sample::empty
bool empty() const
Return whether the tree or the set of Pqueries is empty.
Definition: sample.cpp:143
genesis::placement::Sample::add
Pquery & add()
Create an empty Pquery, add it to the Sample and return it.
Definition: sample.cpp:152
genesis::placement::Sample::operator=
Sample & operator=(Sample const &)
Copy assignment.
Definition: sample.cpp:86
std.hpp
Provides some valuable additions to STD.
genesis::placement::PlacementEdgeData
Data class for PlacementTreeEdges. Stores the branch length of the edge, and the edge_num,...
Definition: placement_tree.hpp:139
genesis::tree::Tree
Class for representing phylogenetic trees.
Definition: tree/tree.hpp:97
genesis::placement::Sample::iterator_pqueries
std::vector< Pquery >::iterator iterator_pqueries
Definition: sample.hpp:77
genesis::placement::Sample::begin
iterator_pqueries begin()
Return an iterator to the beginning of the Pqueries of this Sample.
Definition: sample.cpp:244
genesis::placement::Pquery
A pquery holds a set of PqueryPlacements and a set of PqueryNames.
Definition: pquery.hpp:82
genesis::tree::Tree::empty
bool empty() const
Return whether the Tree is empty (i.e., has no nodes, edges and links).
Definition: tree/tree.hpp:194
genesis::placement::Sample::at
Pquery & at(size_t index)
Return the Pquery at a certain index.
Definition: sample.cpp:190
genesis::placement::Sample::Sample
Sample()=default
Default constructor.
genesis::placement::PlacementTree
tree::Tree PlacementTree
Alias for a tree::Tree used for a tree with information needed for storing Pqueries....
Definition: placement/formats/edge_color.hpp:54
genesis::utils::Range
Simple wrapper for typical begin() and end() iterators, to be used in range-based for loops.
Definition: range.hpp:46
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
operators.hpp
Tree operator functions.
genesis::placement::Sample::clear
void clear()
Clears all data of this object.
Definition: sample.cpp:113
genesis::placement::Sample::swap
void swap(Sample &other)
Swap the contents of this Sample with the contents of another Sample.
Definition: sample.cpp:96
genesis::placement::Sample::remove
void remove(size_t index)
Remove the Pquery at a given index from the Sample.
Definition: sample.cpp:204
sample.hpp
genesis::placement::Sample::pqueries
utils::Range< iterator_pqueries > pqueries()
Return a Range iterator to the Pqueries .
Definition: sample.cpp:264
helper.hpp
genesis::placement::Sample::metadata
std::unordered_map< std::string, std::string > metadata
Definition: sample.hpp:296