A toolkit for working with phylogenetic data.
v0.18.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
indexed_newick_reader.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 
33 #include <cassert>
34 #include <stdexcept>
35 
36 namespace genesis {
37 namespace tree {
38 
39 // =================================================================================================
40 // Settings
41 // =================================================================================================
42 
44  Source source,
45  size_t index,
46  Target target,
47  std::string const& target_key
48 ) {
49  indexed_attributes_.push_back({ source, index, target, target_key, "", false });
50  return *this;
51 }
52 
54  Source source,
55  size_t index,
56  Target target,
57  std::string const& target_key,
58  std::string const& default_value
59 ) {
60  indexed_attributes_.push_back({ source, index, target, target_key, default_value, true });
61  return *this;
62 }
63 
65  Source source,
66  Target target,
67  std::string const& target_key_prefix
68 ) {
69  catch_all_attributes_.push_back({ source, 0, target, target_key_prefix, "", false });
70  return *this;
71 }
72 
74  Target target
75 ) {
76  add_catch_all( Source::kComment, target, "comment_" );
77  add_catch_all( Source::kTag, target, "tag_" );
78  add_catch_all( Source::kValue, target, "value_" );
79  return *this;
80 }
81 
83 {
84  indexed_attributes_.clear();
85  catch_all_attributes_.clear();
86 }
87 
88 // =================================================================================================
89 // Plugin Functions
90 // =================================================================================================
91 
93  NewickBrokerElement const& element,
94  TreeNode& node
95 ) const {
96  auto& attributes = node.data<AttributeTreeNodeData>().attributes;
97  process_indexed_attributes_( element, attributes, Target::kNode );
98  process_catch_all_attributes_( element, attributes, Target::kNode );
99 }
100 
102  NewickBrokerElement const& element,
103  TreeEdge& edge
104 ) const {
105  auto& attributes = edge.data<AttributeTreeEdgeData>().attributes;
106  process_indexed_attributes_( element, attributes, Target::kEdge );
107  process_catch_all_attributes_( element, attributes, Target::kEdge );
108 }
109 
111 {
112  // Set node data creation function.
113  reader.create_node_data_plugin = []( TreeNode& node ){
114  node.reset_data( AttributeTreeNodeData::create() );
115  };
116 
117  // Set edge data creation function.
118  reader.create_edge_data_plugin = []( TreeEdge& edge ){
119  edge.reset_data( AttributeTreeEdgeData::create() );
120  };
121 
122  // Add node manipulation functions.
123  reader.element_to_node_plugins.push_back(
124  [&]( NewickBrokerElement const& element, TreeNode& node ) {
125  element_to_node( element, node );
126  }
127  );
128 
129  // Add edge manipulation functions.
130  reader.element_to_edge_plugins.push_back(
131  [&]( NewickBrokerElement const& element, TreeEdge& edge ) {
132  element_to_edge( element, edge );
133  }
134  );
135 }
136 
137 // =================================================================================================
138 // Internal Functions
139 // =================================================================================================
140 
141 std::vector<std::string> const& IndexedAttributeTreeNewickReaderPlugin::get_attribute_source_(
142  NewickBrokerElement const& element,
143  Source source
144 ) const {
145  switch( source ) {
146  case Source::kValue: {
147  return element.values;
148  }
149  case Source::kComment: {
150  return element.comments;
151  }
152  case Source::kTag: {
153  return element.tags;
154  }
155  default: {
156  // This can only happen if we misuse the enum.
157  throw std::runtime_error( "Invalid source type for indexed attribute." );
158  }
159  }
160 
161  // Make compiler happy. Need to do something here.
162  throw std::runtime_error( "Invalid source type for indexed attribute." );
163 }
164 
165 void IndexedAttributeTreeNewickReaderPlugin::process_indexed_attributes_(
166  NewickBrokerElement const& element,
167  AttributeTreeMap& attributes,
168  Target target
169 ) const {
170  // Process indexed attributes...
171  for( auto const& attrs : indexed_attributes_ ) {
172 
173  // ... but only if they are for our target.
174  if( attrs.target != target ) {
175  continue;
176  }
177 
178  // Find the correct source element.
179  auto const& src = get_attribute_source_( element, attrs.source );
180 
181  // Add the value at the index to the attribute map, or use default if index invalid.
182  if( attrs.index < src.size() ) {
183  attributes[ attrs.target_key ] = src[ attrs.index ];
184  } else if( attrs.use_default ) {
185  attributes[ attrs.target_key ] = attrs.default_value;
186  }
187  }
188 }
189 
190 void IndexedAttributeTreeNewickReaderPlugin::process_catch_all_attributes_(
191  NewickBrokerElement const& element,
192  AttributeTreeMap& attributes,
193  Target target
194 ) const {
195  // Process catch all attributes...
196  for( auto const& attrs : catch_all_attributes_ ) {
197 
198  // ... but only if they are for our target.
199  if( attrs.target != target ) {
200  continue;
201  }
202 
203  // Find the correct source element.
204  auto const& src = get_attribute_source_( element, attrs.source );
205 
206  // Add all source attributes to the target map.
207  size_t cnt = 0;
208  for( auto const& elem : src ) {
209  attributes[ attrs.target_key + std::to_string( cnt ) ] = elem;
210  ++cnt;
211  }
212  }
213 }
214 
215 } // namespace tree
216 } // namespace genesis
std::vector< std::string > values
Numerical values associated with the node, i.e. branch lengths.
Definition: element.hpp:104
Source
Select which kind of Newick data to take, i.e., either comments, values, or tags. ...
Data class for AttributeTreeNodes.
Data class for AttributeTreeEdges.
static std::unique_ptr< AttributeTreeEdgeData > create()
void clear()
Reset all settings to the default, i.e., delete all attribute settings.
self_type & add_catch_all(Source source, Target target, std::string const &target_key_prefix)
Store all Newick data of a given source in an AttributeTreeMap.
static std::unique_ptr< AttributeTreeNodeData > create()
self_type & add_attribute(Source source, size_t index, Target target, std::string const &target_key)
Store the Newick data at a given index in an AttributeTreeMap.
Provide a set of plugin functions for NewickReader to read ordered attributes of the Nodes and Edges ...
std::string to_string(T const &v)
Return a string representation of a given value.
Definition: string.hpp:300
Store data at the attributes map of an AttributeTreeEdge.
std::vector< std::string > comments
Arbitrary strings that can be attached to a node, e.g. in Newick format via "[]". ...
Definition: element.hpp:114
create_edge_data_function create_edge_data_plugin
std::vector< std::string > tags
Arbitrary strings that can be attached to a node, e.g. in Newick format via "{}". ...
Definition: element.hpp:109
void element_to_edge(NewickBrokerElement const &element, TreeEdge &edge) const
Store data at the attributes map of an AttributeTreeNode.
std::vector< element_to_edge_function > element_to_edge_plugins
Target
Select where to store the data, i.e., at Nodes or Edges of the Tree.
create_node_data_function create_node_data_plugin
Take data from Newick comments, i.e., [something].
NodeDataType & data()
Definition: node.hpp:108
std::map< std::string, std::string > AttributeTreeMap
Alias for the map type used by an AttributeTree.
EdgeDataType & data()
Definition: edge.hpp:118
Store the information for one element of a Newick tree.
Definition: element.hpp:60
void element_to_node(NewickBrokerElement const &element, TreeNode &node) const
std::vector< element_to_node_function > element_to_node_plugins