A toolkit for working with phylogenetic data.
v0.18.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tree/formats/phyloxml/writer.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 "genesis/tree/tree.hpp"
34 
37 
44 
45 #include <assert.h>
46 #include <stdexcept>
47 #include <vector>
48 
49 namespace genesis {
50 namespace tree {
51 
52 // =================================================================================================
53 // Printing
54 // =================================================================================================
55 
56 void PhyloxmlWriter::to_file (const Tree& tree, const std::string filename) const
57 {
58  std::string ts;
59  to_string(tree, ts);
60  utils::file_write(ts, filename);
61 }
62 
63 void PhyloxmlWriter::to_string (const Tree& tree, std::string& ts) const
64 {
65  ts = to_string(tree);
66 }
67 
68 std::string PhyloxmlWriter::to_string (const Tree& tree) const
69 {
71  to_document(tree, xml);
72  return utils::XmlWriter().to_string(xml);
73 }
74 
75 void PhyloxmlWriter::to_document (const Tree& tree, utils::XmlDocument& xml) const
76 {
77  xml.clear();
78 
79  // Call all preparatory plugins.
80  for( auto const& prepare_plugin : prepare_writing_plugins ) {
81  prepare_plugin( tree, xml );
82  }
83 
84  // Set XML declaration.
85  // xml.xml_tag = "xml";
86  // xml.declarations.emplace("version", "1.0");
87  // xml.declarations.emplace("encoding", "UTF-8");
88 
89  // Set XML root element.
90  xml.tag = "phyloxml";
91  xml.attributes.emplace("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
92  xml.attributes.emplace(
93  "xsi:schemaLocation",
94  "http://www.phyloxml.org http://www.phyloxml.org/1.10/phyloxml.xsd"
95  );
96  xml.attributes.emplace("xmlns", "http://www.phyloxml.org");
97 
98  // Add the (phylogeny) element.
99  auto phylogeny = utils::make_unique< utils::XmlElement >();
100  phylogeny->tag = "phylogeny";
101  phylogeny->attributes.emplace("rooted", "true");
102  //~ phylogeny.attributes.emplace("rerootable", "true");
103 
104  // Create a stack where we will push the tree elements to. Use the phylogeny element as root.
105  std::vector< utils::XmlElement* > stack;
106  stack.push_back(phylogeny.get());
107  xml.content.push_back(std::move(phylogeny));
108  size_t cur_d = 0;
109 
110  // Store the distance from each node to the root. Will be used to determine the position on the
111  // stack that is used for adding clades to the phylogeny.
112  auto depths = node_path_length_vector(tree);
113 
114  for( auto it : preorder(tree) ) {
115  // Depth can never increase more than one between two nodes when doing a preoder traversal.
116  assert(depths[it.node().index()] <= cur_d + 1);
117 
118  // Delete end of stack when moving up the tree, unless we are already at the root.
119  while (cur_d >= depths[it.node().index()] && depths[it.node().index()] > 0) {
120  assert(stack.size() > 0);
121  stack.pop_back();
122  --cur_d;
123  }
124  // Set current depth (explicitly needed in case we are moving further into the tree, which
125  // means that the loop above is not executed).
126  cur_d = depths[it.node().index()];
127 
128  // Create clade element, append it to the stack, so that all sub-elements will use it as
129  // parent.
130  auto clade = utils::make_unique< utils::XmlElement >();
131  clade->tag = "clade";
132 
133  // Call all plugins to translate node and edge data to xml.
134  for( auto const& node_plugin : node_to_element_plugins ) {
135  node_plugin( it.node(), *clade.get() );
136  }
137  for( auto const& edge_plugin : edge_to_element_plugins ) {
138  edge_plugin( it.edge(), *clade.get() );
139  }
140 
141  // Append the clade to the current parent (end of the stack), then use it as the new parent
142  // for the next iteration of the loop.
143  auto clade_ptr = clade.get();
144  stack.back()->content.push_back(std::move(clade));
145  stack.push_back(clade_ptr);
146  }
147 
148  // Call all finalizing plugins.
149  for( auto const& finish_plugin : finish_writing_plugins ) {
150  finish_plugin( tree, xml );
151  }
152 }
153 
154 } // namespace tree
155 } // namespace genesis
std::vector< size_t > node_path_length_vector(Tree const &tree, TreeNode const &node)
Return a vector containing the depth of all nodes with respect to the given start node...
std::vector< node_to_element_function > node_to_element_plugins
Collect all functions to be called for each TreeNode in order to translate it to a Phyloxml represent...
void to_string(const Tree &tree, std::string &ts) const
Gives a Phyloxml string representation of the tree.
void to_string(const XmlDocument &document, std::string &output)
Give the XML string representation of a XmlDocument.
Provides some valuable additions to STD.
utils::Range< IteratorPreorder< TreeLink const, TreeNode const, TreeEdge const > > preorder(ElementType const &element)
std::vector< prepare_writing_function > prepare_writing_plugins
Collect all functions to be called before starting the actual tree writing.
Class for representing phylogenetic trees.
Definition: tree/tree.hpp:95
A collection of classes for working with XML documents. See XmlDocument for more. ...
Provides functions for accessing the file system.
void to_file(const Tree &tree, const std::string filename) const
Writes the tree to a file in Phyloxml format.
Provides easy and fast logging functionality.
std::vector< std::unique_ptr< XmlValue > > content
void to_document(const Tree &tree, utils::XmlDocument &xml) const
Store the information of the tree into an Phyloxml-formatted XmlDocument.
Header of Tree class.
Header of Tree distance methods.
void file_write(std::string const &content, std::string const &filename)
Write the content of a string to a file.
Definition: fs.cpp:106
std::vector< finish_writing_function > finish_writing_plugins
Collect all functions to be called after finishing the actual tree writing.
std::vector< edge_to_element_function > edge_to_element_plugins
Collect all functions to be called for each TreeEdge in order to translate it to a Phyloxml represent...