A toolkit for working with phylogenetic data.
v0.18.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-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 <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\": \"" << newick_writer.to_string( sample.tree() ) << "\",\n";
89 
90  // Write field names.
91  os << in << "\"fields\": [ \"edge_num\", \"likelihood\", \"like_weight_ratio\", "
92  << "\"distal_length\", \"pendant_length\" ],\n";
93 
94  // Write pqueries.
95  os << in << "\"placements\": [\n";
96  for( size_t i = 0; i < sample.size(); ++i ) {
97  auto const& pquery = sample.at(i);
98  os << in << in << "{\n";
99 
100  // Write placements.
101  os << in << in << in << "\"p\": [\n";
102  for( size_t j = 0; j < pquery.placement_size(); ++j ) {
103  auto const& placement = pquery.placement_at(j);
104  os << in << in << in << in << "[ ";
105 
106  os << placement.edge_num() << ", ";
107  os << placement.likelihood << ", ";
108  os << placement.like_weight_ratio << ", ";
109 
110  auto const& edge_data = placement.edge().data<PlacementEdgeData>();
111  os << edge_data.branch_length - placement.proximal_length << ", ";
112  os << placement.pendant_length;
113 
114  os << " ]";
115  if( j < pquery.placement_size() - 1 ) {
116  os << ",";
117  }
118  os << "\n";
119  }
120  os << in << in << in << "],\n";
121 
122  // Find out whether names have multiplicity.
123  bool has_nm = false;
124  for( auto const& pqry_name : pquery.names() ) {
125  has_nm |= ( pqry_name.multiplicity != 1.0 );
126  }
127 
128  // Write names.
129  if( has_nm ) {
130 
131  // With multiplicity.
132  os << in << in << in << "\"nm\": [\n";
133  for( size_t j = 0; j < pquery.name_size(); ++j ) {
134  os << in << in << in << in << "[ \"" << pquery.name_at(j).name << "\", ";
135  os << pquery.name_at(j).multiplicity << " ]";
136 
137  if( j < pquery.name_size() - 1 ) {
138  os << ", ";
139  }
140  os << "\n";
141  }
142  os << in << in << in << "]\n";
143 
144  } else {
145 
146  // Without multiplicity.
147  os << in << in << in << "\"n\": [ ";
148  for( size_t j = 0; j < pquery.name_size(); ++j ) {
149  os << "\"" << pquery.name_at(j).name << "\"";
150 
151  if( j < pquery.name_size() - 1 ) {
152  os << ", ";
153  }
154  }
155  os << " ]\n";
156 
157  }
158 
159  // Write end of placement stuff.
160  os << in << in << "}";
161  if( i < sample.size() - 1 ) {
162  os << ",";
163  }
164  os << "\n";
165  }
166  os << in << "]\n";
167 
168  // Close json document.
169  os << "}\n";
170 }
171 
180 void JplaceWriter::to_file( Sample const& sample, std::string const& filename ) const
181 {
182  std::ofstream ofs;
183  utils::file_output_stream( filename, ofs );
184  to_stream( sample, ofs );
185 }
186 
190 void JplaceWriter::to_string( Sample const& sample, std::string& output ) const
191 {
192  std::ostringstream oss;
193  to_stream( sample, oss );
194  output = oss.str();
195 }
196 
200 std::string JplaceWriter::to_string( Sample const& sample ) const
201 {
202  std::ostringstream oss;
203  to_stream( sample, oss );
204  return oss.str();
205 }
206 
215 {
216  using namespace utils;
217  doc = JsonDocument::object();
218 
219  // set tree
220  auto nwp = PlacementTreeNewickWriter();
221  nwp.enable_names(true);
222  nwp.enable_branch_lengths(true);
223  nwp.branch_length_precision( branch_length_precision_ );
224  doc[ "tree" ] = nwp.to_string( smp.tree() );
225 
226  // set placements
227  auto& placements_arr = doc[ "placements" ];
228  for( auto const& pqry : smp.pqueries() ) {
229  auto jpqry = JsonDocument::object();
230 
231  // set placements
232  auto pqry_p_arr = JsonDocument::array();
233  for( auto const& pqry_place : pqry.placements() ) {
234  auto pqry_fields = JsonDocument::array();
235 
236  pqry_fields.push_back( JsonDocument::number_unsigned( pqry_place.edge_num() ));
237  pqry_fields.push_back( JsonDocument::number_float( pqry_place.likelihood ));
238  pqry_fields.push_back( JsonDocument::number_float( pqry_place.like_weight_ratio ));
239 
240  // convert from proximal to distal length.
241  auto const& edge_data = pqry_place.edge().data<PlacementEdgeData>();
242  pqry_fields.push_back( JsonDocument::number_float(
243  edge_data.branch_length - pqry_place.proximal_length
244  ));
245  pqry_fields.push_back( JsonDocument::number_float( pqry_place.pendant_length ));
246 
247  pqry_p_arr.push_back( pqry_fields );
248  }
249  jpqry[ "p" ] = pqry_p_arr;
250 
251  // find out whether names have multiplicity
252  bool has_nm = false;
253  for( auto const& pqry_name : pqry.names() ) {
254  has_nm |= ( pqry_name.multiplicity != 1.0 );
255  }
256 
257  // set named multiplicity / name
258  if (has_nm) {
259  auto pqry_nm_arr = JsonDocument::array();
260  for( auto const& pqry_name : pqry.names() ) {
261  auto pqry_nm_val = JsonDocument::array();
262  pqry_nm_val.push_back( pqry_name.name );
263  pqry_nm_val.push_back( JsonDocument::number_float( pqry_name.multiplicity ));
264  pqry_nm_arr.push_back( pqry_nm_val );
265  }
266  jpqry[ "nm" ] = pqry_nm_arr;
267  } else {
268  auto pqry_n_arr = JsonDocument::array();
269  for( auto const& pqry_name : pqry.names() ) {
270  pqry_n_arr.push_back( pqry_name.name );
271  }
272  jpqry[ "n" ] = pqry_n_arr;
273  }
274 
275  placements_arr.push_back( jpqry );
276  }
277 
278  // set fields
279  auto jfields = JsonDocument::array();
280  jfields.push_back( "edge_num" );
281  jfields.push_back( "likelihood" );
282  jfields.push_back( "like_weight_ratio" );
283  jfields.push_back( "distal_length" );
284  jfields.push_back( "pendant_length" );
285  doc[ "fields" ] = jfields;
286 
287  // set version
288  doc[ "version" ] = 3;
289 
290  // set metadata
291  auto jmetadata = JsonDocument::object();
292  jmetadata[ "program" ] = "genesis " + genesis_version();
293  jmetadata[ "invocation" ] = utils::Options::get().command_line_string();
294  doc[ "metadata" ] = jmetadata;
295 }
296 
297 } // namespace placement
298 } // 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:164
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:89
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.
Definition: placement.cpp:50
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:59
Some stuff that is totally not imporatant, but nice.
std::string genesis_version()
Return the current genesis version.
Definition: version.hpp:62