A library for working with phylogenetic and population genetic data.
v0.27.0
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
genesis::tree::NewickReader::create_node_data_plugin
create_node_data_function create_node_data_plugin
Definition: tree/formats/newick/reader.hpp:313
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::element_to_edge
void element_to_edge(NewickBrokerElement const &element, TreeEdge &edge) const
Definition: indexed_newick_reader.cpp:101
genesis::tree::AttributeTreeMap
std::map< std::string, std::string > AttributeTreeMap
Alias for the map type used by an AttributeTree.
Definition: tree/attribute_tree/tree.hpp:81
genesis::tree::NewickReader
Definition: tree/formats/newick/reader.hpp:67
genesis::tree::NewickBrokerElement::comments
std::vector< std::string > comments
Arbitrary strings that can be attached to a node, e.g. in Newick format via "[]".
Definition: element.hpp:132
genesis::tree::NewickReader::create_edge_data_plugin
create_edge_data_function create_edge_data_plugin
Definition: tree/formats/newick/reader.hpp:314
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::Source
Source
Select which kind of Newick data to take, i.e., either comments, values, or tags.
Definition: indexed_newick_reader.hpp:110
genesis::tree::IndexedAttributeTreeNewickReaderPlugin
Provide a set of plugin functions for NewickReader to read ordered attributes of the Nodes and Edges ...
Definition: indexed_newick_reader.hpp:95
genesis::tree::NewickBrokerElement::values
std::vector< std::string > values
Numerical values associated with the node, i.e. branch lengths.
Definition: element.hpp:122
genesis::population::to_string
std::string to_string(GenomeLocus const &locus)
Definition: functions/genome_locus.hpp:48
genesis::tree::AttributeTreeEdgeData
Data class for AttributeTreeEdges.
Definition: tree/attribute_tree/tree.hpp:151
genesis::tree::NewickReader::element_to_edge_plugins
std::vector< element_to_edge_function > element_to_edge_plugins
Definition: tree/formats/newick/reader.hpp:317
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::Target
Target
Select where to store the data, i.e., at Nodes or Edges of the Tree.
Definition: indexed_newick_reader.hpp:131
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::Source::kValue
@ kValue
Take data from Newick values, i.e., :3.14.
genesis::tree::NewickBrokerElement::tags
std::vector< std::string > tags
Arbitrary strings that can be attached to a node, e.g. in Newick format via "{}".
Definition: element.hpp:127
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::Source::kComment
@ kComment
Take data from Newick comments, i.e., [something].
genesis::tree::AttributeTreeEdgeData::create
static std::unique_ptr< AttributeTreeEdgeData > create()
Definition: tree/attribute_tree/tree.hpp:175
genesis::tree::TreeEdge
Definition: edge.hpp:60
genesis::tree::TreeNode
Definition: tree/tree/node.hpp:58
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
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::Target::kEdge
@ kEdge
Store data at the attributes map of an AttributeTreeEdge.
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::clear
void clear()
Reset all settings to the default, i.e., delete all attribute settings.
Definition: indexed_newick_reader.cpp:82
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::Source::kTag
@ kTag
Take data from Newick tags, i.e., {42}.
genesis::tree::NewickReader::element_to_node_plugins
std::vector< element_to_node_function > element_to_node_plugins
Definition: tree/formats/newick/reader.hpp:316
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::add_attribute
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.
Definition: indexed_newick_reader.cpp:43
genesis::tree::TreeNode::data
NodeDataType & data()
Definition: tree/tree/node.hpp:203
genesis::tree::TreeEdge::data
EdgeDataType & data()
Definition: edge.hpp:217
genesis::tree::NewickBrokerElement
Store the information for one element of a Newick tree.
Definition: element.hpp:60
genesis::tree::AttributeTreeNodeData
Data class for AttributeTreeNodes.
Definition: tree/attribute_tree/tree.hpp:92
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::register_with
void register_with(NewickReader &reader) const
Definition: indexed_newick_reader.cpp:110
indexed_newick_reader.hpp
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::Target::kNode
@ kNode
Store data at the attributes map of an AttributeTreeNode.
genesis::tree::AttributeTreeNodeData::create
static std::unique_ptr< AttributeTreeNodeData > create()
Definition: tree/attribute_tree/tree.hpp:116
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::element_to_node
void element_to_node(NewickBrokerElement const &element, TreeNode &node) const
Definition: indexed_newick_reader.cpp:92
genesis::tree::IndexedAttributeTreeNewickReaderPlugin::add_catch_all
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.
Definition: indexed_newick_reader.cpp:64