fpmas 1.6
csv_output.h
Go to the documentation of this file.
1#ifndef FPMAS_CSV_OUTPUT_H
2#define FPMAS_CSV_OUTPUT_H
3
4#include <fstream>
5#include <functional>
6#include <vector>
7#include <sstream>
8#include "output.h"
10
16namespace fpmas { namespace io {
17 using api::io::Watcher;
18
19
30 template<typename T>
31 struct CsvSerial {
39 static std::string to_csv(const T& data) {
40 std::ostringstream stream;
41 stream << data;
42 return stream.str();
43 }
44 };
45
60 template<typename... DataField>
61 class CsvOutputBase : public OutputBase {
62 private:
63 std::vector<std::string> _headers;
64 std::tuple<std::function<DataField()>...> watchers;
65
66 /*
67 * Tuple unrolling helper structs.
68 */
69 template<int ...> struct seq {};
70 template<int N, int ...S> struct gens {
71 public:
72 typedef typename gens<N-1, N-1, S...>::type type;
73 }; template<int ...S> struct gens<0, S...>{ typedef seq<S...> type; };
74
75 /*
76 * Unrolls the input tuple to feed internal _headers, that are then
77 * accessible with headers().
78 */
79 template<int ...S>
80 void build_headers(
81 std::tuple<std::pair<std::string, std::function<DataField()>>...> csv_fields,
82 const seq<S...>) {
83 _headers = {std::get<S>(csv_fields).first...};
84 }
85
86 /*
87 * Unrolls the input tuple and calls each watcher.
88 * Data is serialized and returned in a vector.
89 */
90 template<int ...S>
91 std::vector<std::string> _dump_fields(const seq<S...>) {
92 std::tuple<DataField...> data {std::get<S>(watchers)() ...};
93 std::ostringstream output_str;
94 return {CsvSerial<typename std::tuple_element<S, decltype(data)>::type>::to_csv(std::get<S>(data))...};
95 }
96
97 protected:
104 void dump_csv(const std::vector<std::string>& data) {
105 std::ostream& output = output_stream.get();
106 for(std::size_t i = 0; i < data.size()-1; i++)
107 output << data[i] << ",";
108 output << data.back() << std::endl;
109 }
110
116 std::vector<std::string> headers() {
117 return _headers;
118 }
125 std::vector<std::string> dump_fields() {
126 return _dump_fields(typename gens<sizeof...(DataField)>::type());
127 }
128
129
140 std::pair<std::string, std::function<DataField()>>... csv_fields)
141 : OutputBase(output_stream), watchers(csv_fields.second...) {
142 build_headers({csv_fields...}, typename gens<sizeof...(DataField)>::type());
143 }
144 };
145
152 template<typename... DataField>
153 class CsvOutput : public CsvOutputBase<DataField...> {
154 public:
168 std::pair<std::string, std::function<DataField()>>... csv_fields)
169 : CsvOutputBase<DataField...>(output_stream, csv_fields...) {
170 this->dump_csv(this->headers());
171 }
172
179 void dump() override {
180 this->dump_csv(this->dump_fields());
181 };
182 };
183
190 template<typename Operation>
191 struct DistributedCsvField : public std::tuple<
192 std::string,
193 Watcher<typename Operation::Type>,
194 typename Operation::Params>
195 {
199 using std::tuple<
200 std::string,
201 std::function<typename Operation::Type()>,
202 typename Operation::Params>::tuple;
203
210 const std::string& name,
211 std::function<typename Operation::Type()> watcher)
212 : DistributedCsvField(name, watcher, {}) {}
213 };
214
224 template<typename... DataFieldOperation>
225 class DistributedCsvOutput : public CsvOutputBase<typename DataFieldOperation::Type...> {
226 private:
228 int root;
229 bool all_out;
230
231 public:
253 : CsvOutputBase<typename DataFieldOperation::Type...>(
255 {
256 // Field name
257 std::get<0>(csv_fields),
258 // DistributedOperation
259 typename DataFieldOperation::Single(
260 comm, root,
261 // Watcher
262 std::get<1>(csv_fields),
263 // Extra Params
264 std::get<2>(csv_fields))
265 }...),
266 comm(comm), root(root), all_out(false)
267 {
268 if(comm.getRank() == root)
269 this->dump_csv(this->headers());
270 }
271
272
291 : CsvOutputBase<typename DataFieldOperation::Type...>(
293 {
294 // Field name
295 std::get<0>(csv_fields),
296 // DistributedOperation
297 typename DataFieldOperation::All(
298 comm,
299 // Watcher
300 std::get<1>(csv_fields),
301 // Extra Params
302 std::get<2>(csv_fields))
303 }...),
304 comm(comm), all_out(true)
305 {
306 this->dump_csv(this->headers());
307 }
308
320 void dump() override {
321 std::vector<std::string> data_fields = this->dump_fields();
322 if(all_out || comm.getRank() == root)
323 this->dump_csv(data_fields);
324 }
325 };
326
327}}
328#endif
Definition: communication.h:251
Definition: csv_output.h:61
std::vector< std::string > headers()
Definition: csv_output.h:116
CsvOutputBase(api::io::OutputStream &output_stream, std::pair< std::string, std::function< DataField()> >... csv_fields)
Definition: csv_output.h:138
std::vector< std::string > dump_fields()
Definition: csv_output.h:125
void dump_csv(const std::vector< std::string > &data)
Definition: csv_output.h:104
Definition: csv_output.h:153
void dump() override
Definition: csv_output.h:179
CsvOutput(api::io::OutputStream &output_stream, std::pair< std::string, std::function< DataField()> >... csv_fields)
Definition: csv_output.h:166
Definition: csv_output.h:225
void dump() override
Definition: csv_output.h:320
DistributedCsvOutput(api::communication::MpiCommunicator &comm, api::io::OutputStream &output_stream, DistributedCsvField< DataFieldOperation >... csv_fields)
Definition: csv_output.h:287
DistributedCsvOutput(api::communication::MpiCommunicator &comm, int root, api::io::OutputStream &output_stream, DistributedCsvField< DataFieldOperation >... csv_fields)
Definition: csv_output.h:249
Definition: output.h:571
api::io::OutputStream & output_stream
Definition: output.h:580
std::function< T()> Watcher
Definition: output.h:103
Definition: fpmas.cpp:3
Definition: output.h:67
virtual std::ostream & get()=0
Definition: csv_output.h:31
static std::string to_csv(const T &data)
Definition: csv_output.h:39
Definition: csv_output.h:195
DistributedCsvField(const std::string &name, std::function< typename Operation::Type()> watcher)
Definition: csv_output.h:209