A toolkit for working with phylogenetic data.
v0.19.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sample.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 
36 
37 #include <algorithm>
38 #include <assert.h>
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 // =================================================================================================
105 // Modifiers
106 // =================================================================================================
107 
109 {
110  pqueries_.clear();
111  tree_ = PlacementTree();
112  metadata.clear();
113 }
114 
115 // =================================================================================================
116 // Tree Accessors and Modifiers
117 // =================================================================================================
118 
120 {
121  return tree_;
122 }
123 
125 {
126  return tree_;
127 }
128 
129 // =================================================================================================
130 // Pquery Accessors and Modifiers
131 // =================================================================================================
132 
133 size_t Sample::size() const
134 {
135  return pqueries_.size();
136 }
137 
138 bool Sample::empty() const
139 {
140  return tree_.empty() || pqueries_.empty();
141 }
142 
143 // -------------------------------------------------------------------------
144 // Add
145 // -------------------------------------------------------------------------
146 
148 {
149  pqueries_.push_back( Pquery() );
150  return pqueries_.back();
151 }
152 
153 Pquery& Sample::add( Pquery const& other )
154 {
155  pqueries_.push_back( other );
156 
157  // Adjust the edge pointers of the placements.
158  for( auto& place : pqueries_.back().placements() ) {
159  // Get the edge index of the old edge, then set the edge to the edge of the
160  // correct sample that is at that index.
161  auto const& old_edge_data = place.edge().data<PlacementEdgeData>();
162  auto const edge_index = place.edge().index();
163  auto const old_edge_num = old_edge_data.edge_num();
164  auto const rel_pos = place.proximal_length / old_edge_data.branch_length;
165  place.reset_edge( tree().edge_at( edge_index ));
166 
167  // Now the placement points to the new edge. We can thus check if this one still has the
168  // same edge_num as the old edge.
169  auto const& edge_data = place.edge().data<PlacementEdgeData>();
170  if( old_edge_num != edge_data.edge_num() ) {
171  throw std::runtime_error(
172  "Trees are incompatible for copying Pqueries between Samples."
173  );
174  }
175  place.proximal_length = rel_pos * edge_data.branch_length;
176  }
177 
178  return pqueries_.back();
179 }
180 
181 // -------------------------------------------------------------------------
182 // At
183 // -------------------------------------------------------------------------
184 
185 Pquery& Sample::at( const size_t index )
186 {
187  return pqueries_.at( index );
188 }
189 
190 Pquery const& Sample::at( const size_t index ) const
191 {
192  return pqueries_.at( index );
193 }
194 
195 // -------------------------------------------------------------------------
196 // Remove
197 // -------------------------------------------------------------------------
198 
199 void Sample::remove( size_t index )
200 {
201  pqueries_.erase( pqueries_.begin() + index );
202 }
203 
204 void Sample::remove( size_t first_index, size_t last_index )
205 {
206  if( first_index >= pqueries_.size()
207  || last_index >= pqueries_.size()
208  || first_index >= last_index
209  ) {
210  throw std::out_of_range( "Invalid indices for removing from SequenceSet." );
211  }
212 
213  pqueries_.erase( pqueries_.begin() + first_index, pqueries_.begin() + last_index );
214 }
215 
217 {
218  pqueries_.erase( position );
219 }
220 
222 {
223  pqueries_.erase( first, last );
224 }
225 
226 // -------------------------------------------------------------------------
227 // Clear
228 // -------------------------------------------------------------------------
229 
231 {
232  pqueries_.clear();
233 }
234 
235 // =================================================================================================
236 // Pquery Iterator
237 // =================================================================================================
238 
240 {
241  return pqueries_.begin();
242 }
243 
245 {
246  return pqueries_.begin();
247 }
248 
250 {
251  return pqueries_.end();
252 }
253 
255 {
256  return pqueries_.end();
257 }
258 
260 {
261  return { pqueries_ };
262 }
263 
265 {
266  return { pqueries_ };
267 }
268 
269 } // namespace placement
270 } // namespace genesis
size_t size() const
Return the number of Pqueries that are stored in this Sample.
Definition: sample.cpp:133
Data class for PlacementTreeEdges. Stores the branch length of the edge, and the edge_num, as defined in the jplace standard.
PlacementTree & tree()
Get the PlacementTree of this Sample.
Definition: sample.cpp:119
void swap(SequenceSet &lhs, SequenceSet &rhs)
A pquery holds a set of PqueryPlacements and a set of PqueryNames.
Definition: pquery.hpp:82
Tree operator functions.
Pquery & at(size_t index)
Return the Pquery at a certain index.
Definition: sample.cpp:185
Provides some valuable additions to STD.
tree::Tree PlacementTree
Alias for a tree::Tree used for a tree with information needed for storing Pqueries. This kind of tree is used by Sample.
utils::Range< iterator_pqueries > pqueries()
Return a Range iterator to the Pqueries .
Definition: sample.cpp:259
Class for representing phylogenetic trees.
Definition: tree/tree.hpp:95
Sample()=default
Default constructor.
std::unordered_map< std::string, std::string > metadata
Definition: sample.hpp:291
bool empty() const
Return whether the Tree is empty (i.e., has no nodes, edges and links).
Definition: tree/tree.cpp:222
std::vector< Pquery >::const_iterator const_iterator_pqueries
Definition: sample.hpp:78
bool empty() const
Return whether the tree or the set of Pqueries is empty.
Definition: sample.cpp:138
std::vector< Pquery >::iterator iterator_pqueries
Definition: sample.hpp:77
iterator_pqueries begin()
Return an iterator to the beginning of the Pqueries of this Sample.
Definition: sample.cpp:239
void clear_pqueries()
Clear all Pqueries of this Sample.
Definition: sample.cpp:230
Manage a set of Pqueries along with the PlacementTree where the PqueryPlacements are placed on...
Definition: sample.hpp:68
TreeEdge & edge_at(size_t index)
Return the TreeEdge at a certain index.
Definition: tree/tree.cpp:324
void swap(Sample &other)
Swap the contents of this Sample with the contents of another Sample.
Definition: sample.cpp:96
void remove(size_t index)
Remove the Pquery at a given index from the Sample.
Definition: sample.cpp:199
Sample & operator=(Sample const &)
Copy assignment.
Definition: sample.cpp:86
iterator_pqueries end()
Return an iterator to the end of the Pqueries of this Sample.
Definition: sample.cpp:249
void clear()
Clears all data of this object.
Definition: sample.cpp:108
Pquery & add()
Create an empty Pquery, add it to the Sample and return it.
Definition: sample.cpp:147
int edge_num() const
Return the edge_num of this edge. This value is defined by the jplace standard.