A toolkit for working with phylogenetic data.
v0.20.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
jplace_writer.cpp
Go to the documentation of this file.
1 /*
2  Genesis - A toolkit for working with phylogenetic data.
3  Copyright (C) 2014-2018 Lucas Czech and HITS gGmbH
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 <fstream>
34 #include <memory>
35 #include <sstream>
36 #include <stdexcept>
37 #include <string>
38 #include <vector>
39 
44 
46 
55 
56 namespace genesis {
57 namespace placement {
58 
59 // =================================================================================================
60 // Printing
61 // =================================================================================================
62 
66 void JplaceWriter::to_stream( Sample const& sample, std::ostream& os ) const
67 {
68  // Indent. Might be replaced by some setting for the class in the future.
69  std::string in = " ";
70 
71  // Open json document.
72  os << "{\n";
73 
74  // Write version.
75  os << in << "\"version\": 3,\n";
76 
77  // Write metadata.
78  os << in << "\"metadata\": {\n";
79  os << in << in << "\"program\": \"" << "genesis " << genesis_version() << "\",\n";
80  os << in << in << "\"invocation\": \"" << utils::Options::get().command_line_string() << "\"\n";
81  os << in << "},\n";
82 
83  // Write tree.
84  auto newick_writer = PlacementTreeNewickWriter();
85  newick_writer.enable_names(true);
86  newick_writer.enable_branch_lengths(true);
87  newick_writer.branch_length_precision( branch_length_precision_ );
88  os << in << "\"tree\": \"";
89  newick_writer.to_stream( sample.tree(), os );
90  os << "\",\n";
91 
92  // Write field names.
93  os << in << "\"fields\": [ \"edge_num\", \"likelihood\", \"like_weight_ratio\", "
94  << "\"distal_length\", \"pendant_length\" ],\n";
95 
96  // Write pqueries.
97  os << in << "\"placements\": [\n";
98  for( size_t i = 0; i < sample.size(); ++i ) {
99  auto const& pquery = sample.at(i);
100  os << in << in << "{\n";
101 
102  // Write placements.
103  os << in << in << in << "\"p\": [\n";
104  for( size_t j = 0; j < pquery.placement_size(); ++j ) {
105  auto const& placement = pquery.placement_at(j);
106  os << in << in << in << in << "[ ";
107 
108  os << placement.edge_num() << ", ";
109  os << placement.likelihood << ", ";
110  os << placement.like_weight_ratio << ", ";
111 
112  auto const& edge_data = placement.edge().data<PlacementEdgeData>();
113  os << edge_data.branch_length - placement.proximal_length << ", ";
114  os << placement.pendant_length;
115 
116  os << " ]";
117  if( j < pquery.placement_size() - 1 ) {
118  os << ",";
119  }
120  os << "\n";
121  }
122  os << in << in << in << "],\n";
123 
124  // Find out whether names have multiplicity.
125  bool has_nm = false;
126  for( auto const& pqry_name : pquery.names() ) {
127  has_nm |= ( pqry_name.multiplicity != 1.0 );
128  }
129 
130  // Write names.
131  if( has_nm ) {
132 
133  // With multiplicity.
134  os << in << in << in << "\"nm\": [\n";
135  for( size_t j = 0; j < pquery.name_size(); ++j ) {
136  os << in << in << in << in << "[ \"" << pquery.name_at(j).name << "\", ";
137  os << pquery.name_at(j).multiplicity << " ]";
138 
139  if( j < pquery.name_size() - 1 ) {
140  os << ", ";
141  }
142  os << "\n";
143  }
144  os << in << in << in << "]\n";
145 
146  } else {
147 
148  // Without multiplicity.
149  os << in << in << in << "\"n\": [ ";
150  for( size_t j = 0; j < pquery.name_size(); ++j ) {
151  os << "\"" << pquery.name_at(j).name << "\"";
152 
153  if( j < pquery.name_size() - 1 ) {
154  os << ", ";
155  }
156  }
157  os << " ]\n";
158 
159  }
160 
161  // Write end of placement stuff.
162  os << in << in << "}";
163  if( i < sample.size() - 1 ) {
164  os << ",";
165  }
166  os << "\n";
167  }
168  os << in << "]\n";
169 
170  // Close json document.
171  os << "}\n";
172 }
173 
182 void JplaceWriter::to_file( Sample const& sample, std::string const& filename ) const
183 {
184  std::ofstream ofs;
185  utils::file_output_stream( filename, ofs );
186  to_stream( sample, ofs );
187 }
188 
192 void JplaceWriter::to_string( Sample const& sample, std::string& output ) const
193 {
194  std::ostringstream oss;
195  to_stream( sample, oss );
196  output = oss.str();
197 }
198 
202 std::string JplaceWriter::to_string( Sample const& sample ) const
203 {
204  std::ostringstream oss;
205  to_stream( sample, oss );
206  return oss.str();
207 }
208 
217 {
218  using namespace utils;
219  doc = JsonDocument::object();
220 
221  // set tree
222  auto nwp = PlacementTreeNewickWriter();
223  nwp.enable_names(true);
224  nwp.enable_branch_lengths(true);
225  nwp.branch_length_precision( branch_length_precision_ );
226  doc[ "tree" ] = nwp.to_string( smp.tree() );
227 
228  // set placements
229  auto& placements_arr = doc[ "placements" ];
230  for( auto const& pqry : smp.pqueries() ) {
231  auto jpqry = JsonDocument::object();
232 
233  // set placements
234  auto pqry_p_arr = JsonDocument::array();
235  for( auto const& pqry_place : pqry.placements() ) {
236  auto pqry_fields = JsonDocument::array();
237 
238  pqry_fields.push_back( JsonDocument::number_unsigned( pqry_place.edge_num() ));
239  pqry_fields.push_back( JsonDocument::number_float( pqry_place.likelihood ));
240  pqry_fields.push_back( JsonDocument::number_float( pqry_place.like_weight_ratio ));
241 
242  // convert from proximal to distal length.
243  auto const& edge_data = pqry_place.edge().data<PlacementEdgeData>();
244  pqry_fields.push_back( JsonDocument::number_float(
245  edge_data.branch_length - pqry_place.proximal_length
246  ));
247  pqry_fields.push_back( JsonDocument::number_float( pqry_place.pendant_length ));
248 
249  pqry_p_arr.push_back( pqry_fields );
250  }
251  jpqry[ "p" ] = pqry_p_arr;
252 
253  // find out whether names have multiplicity
254  bool has_nm = false;
255  for( auto const& pqry_name : pqry.names() ) {
256  has_nm |= ( pqry_name.multiplicity != 1.0 );
257  }
258 
259  // set named multiplicity / name
260  if (has_nm) {
261  auto pqry_nm_arr = JsonDocument::array();
262  for( auto const& pqry_name : pqry.names() ) {
263  auto pqry_nm_val = JsonDocument::array();
264  pqry_nm_val.push_back( pqry_name.name );
265  pqry_nm_val.push_back( JsonDocument::number_float( pqry_name.multiplicity ));
266  pqry_nm_arr.push_back( pqry_nm_val );
267  }
268  jpqry[ "nm" ] = pqry_nm_arr;
269  } else {
270  auto pqry_n_arr = JsonDocument::array();
271  for( auto const& pqry_name : pqry.names() ) {
272  pqry_n_arr.push_back( pqry_name.name );
273  }
274  jpqry[ "n" ] = pqry_n_arr;
275  }
276 
277  placements_arr.push_back( jpqry );
278  }
279 
280  // set fields
281  auto jfields = JsonDocument::array();
282  jfields.push_back( "edge_num" );
283  jfields.push_back( "likelihood" );
284  jfields.push_back( "like_weight_ratio" );
285  jfields.push_back( "distal_length" );
286  jfields.push_back( "pendant_length" );
287  doc[ "fields" ] = jfields;
288 
289  // set version
290  doc[ "version" ] = 3;
291 
292  // set metadata
293  auto jmetadata = JsonDocument::object();
294  jmetadata[ "program" ] = "genesis " + genesis_version();
295  jmetadata[ "invocation" ] = utils::Options::get().command_line_string();
296  doc[ "metadata" ] = jmetadata;
297 }
298 
299 } // namespace placement
300 } // namespace genesis
void to_document(Sample const &smp, utils::JsonDocument &doc) const
Store the data of a Sample in a JsonDocument object.
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 file_output_stream(std::string const &filename, std::ofstream &out_stream, std::ios_base::openmode mode=std::ios_base::out)
Helper function to obtain an output stream to a file.
void to_file(Sample const &smp, std::string const &filename) const
Write the data of a Sample to a file in Jplace format.
Pquery & at(size_t index)
Return the Pquery at a certain index.
Definition: sample.cpp:185
PqueryPlacement & placement_at(size_t index)
Return the PqueryPlacement at a certain index.
Definition: pquery.cpp:118
Provides some valuable additions to STD.
utils::Range< iterator_pqueries > pqueries()
Return a Range iterator to the Pqueries .
Definition: sample.cpp:259
std::string command_line_string() const
Returns a string containing the program's command line arguments.
Definition: options.cpp:100
void to_string(Sample const &smp, std::string &output) const
Store the data of a Sample in a string in Jplace format.
Provides functions for accessing the file system.
Provides easy and fast logging functionality.
Store a Json value of any kind.
double branch_length
Branch length of the edge.
Manage a set of Pqueries along with the PlacementTree where the PqueryPlacements are placed on...
Definition: sample.hpp:68
int edge_num() const
Get the edge_num where this PqueryPlacement is placed.
void to_stream(Sample const &smp, std::ostream &os) const
Write a Sample to a stream, using the Jplace format.
static Options & get()
Returns a single instance of this class.
Definition: options.hpp:60
Some stuff that is totally not imporatant, but nice.
std::string genesis_version()
Return the current genesis version.
Definition: version.hpp:62