Project

General

Profile

Statistics
| Branch: | Revision:

root / src / scave / export.h @ a3be1d55

History | View | Annotate | Download (12.6 KB)

1
//=========================================================================
2
//  EXPORT.H - part of
3
//                  OMNeT++/OMNEST
4
//           Discrete System Simulation in C++
5
//
6
//  Author: Tamas Borbely
7
//
8
//=========================================================================
9

    
10
/*--------------------------------------------------------------*
11
  Copyright (C) 1992-2008 Andras Varga
12
  Copyright (C) 2006-2008 OpenSim Ltd.
13

14
  This file is distributed WITHOUT ANY WARRANTY. See the file
15
  `license' for details on this and other legal matters.
16
*--------------------------------------------------------------*/
17

    
18
#ifndef _EXPORT_H_
19
#define _EXPORT_H_
20

    
21
#include <string>
22
#include <vector>
23
#include <set>
24
#include <fstream>
25
#include <utility>
26
#include "scavedefs.h"
27
#include "bigdecimal.h"
28
#include "xyarray.h"
29
#include "resultfilemanager.h"
30
#include "datasorter.h"
31

    
32
NAMESPACE_BEGIN
33

    
34
typedef std::vector<std::string> StringVector;
35

    
36
/**
37
 * Basic data structure to be exported.
38
 */
39
class SCAVE_API DataTable
40
{
41
    public:
42
        enum ColumnType
43
        {
44
            DOUBLE,
45
            BIGDECIMAL,
46
            STRING
47
        };
48

    
49
        struct Column
50
        {
51
            std::string name;
52
            ColumnType  type;
53
            Column(const std::string name, ColumnType type) : name(name), type(type) {}
54
        };
55

    
56
        class CellPtr {
57
            private:
58
                DataTable* table;
59
                int row;
60
                int column;
61
            public:
62
                CellPtr() :table(NULL), row(-1), column(-1) {}
63
                CellPtr(DataTable *table, int row, int column) : table(table), row(row), column(column) {}
64
                bool isNull() const { return table == NULL || row < 0 || row >= table->getNumRows() || column < 0 || column >= table->getNumColumns(); }
65
                int getRow() const {return row; }
66
                int getColumn() const { return column; }
67
                void resetRow() { row = 0; }
68
                void nextRow() { row++; }
69
                bool operator<(const CellPtr &other) const;
70
        };
71
    public:
72
        const std::string name;
73
        const std::string description;
74
    protected:
75
        std::vector<Column> header;
76
        DataTable(const std::string &name, const std::string &description) : name(name), description(description) {}
77
        void addColumn(const Column &column) { header.push_back(column); }
78
    public:
79
        virtual ~DataTable() {}
80
        int getNumColumns() const { return header.size(); }
81
        Column getColumn(int i) const { return header[i]; }
82
        virtual int getNumRows() const = 0;
83
        virtual bool isNull(int row, int col) const = 0;
84
        virtual double getDoubleValue(int row, int col) const = 0;
85
        virtual BigDecimal getBigDecimalValue(int row, int col) const = 0;
86
        virtual std::string getStringValue(int row, int col) const = 0;
87

    
88
    // rows (may contain NaN and infinity)
89
};
90

    
91

    
92

    
93
/**
94
 * A table containing an output vector or the result of processing output vectors.
95
 * The vector has two column, X and Y.
96
 */
97
class SCAVE_API XYDataTable : public DataTable
98
{
99
    private:
100
        const XYArray *vec;
101
    public:
102
        XYDataTable(const std::string &name, const std::string &description,
103
            const std::string &xColumnName, const std::string &yColumnName, const XYArray *vec);
104
        virtual int getNumRows() const;
105
        virtual bool isNull(int row, int col) const;
106
        virtual double getDoubleValue(int row, int col) const;
107
        virtual BigDecimal getBigDecimalValue(int row, int col) const;
108
        virtual std::string getStringValue(int row, int col) const;
109
};
110

    
111
/**
112
 * Table containing one X column and several Y columns.
113
 */
114
class SCAVE_API ScatterDataTable : public DataTable
115
{
116
    private:
117
        const XYDataset &dataset;
118
    public:
119
        ScatterDataTable(const std::string &name, const std::string &description, const XYDataset &data);
120
        virtual int getNumRows() const;
121
        virtual bool isNull(int row, int col) const;
122
        virtual double getDoubleValue(int row, int col) const;
123
        virtual BigDecimal getBigDecimalValue(int row, int col) const;
124
        virtual std::string getStringValue(int row, int col) const;
125
};
126

    
127
/**
128
 * A table containing scalars grouped by some of its fields.
129
 */
130
class SCAVE_API ScalarDataTable : public DataTable
131
{
132
    private:
133
        IDVectorVector scalars;
134
        ResultFileManager &manager;
135
    public:
136
        ScalarDataTable(const std::string name, const std::string description,
137
            const IDList &idlist, ResultItemFields groupBy, ResultFileManager &manager);
138

    
139
        virtual int getNumRows() const;
140
        virtual bool isNull(int row, int col) const;
141
        virtual double getDoubleValue(int row, int col) const;
142
        virtual BigDecimal getBigDecimalValue(int row, int col) const;
143
        virtual std::string getStringValue(int row, int col) const;
144
};
145

    
146
/**
147
 * Computes the outer join of DataTables.
148
 */
149
class SCAVE_API JoinedDataTable : public DataTable
150
{
151
    private:
152
        std::vector<DataTable*> joinedTables;
153
        int tableCount;
154
        int rowCount;
155
        std::vector<std::pair<int,int> > columnMap; // maps column -> (tableIndex,tableColumn)
156
        int* rowMap; // maps (row,tableIndex) -> tableRow
157
                     //   implemented as a two dimensional array (has rowCount*tableCount elements)
158
    public:
159
        JoinedDataTable(const std::string name, const std::string description,
160
            const std::vector<DataTable*> &joinedTables, int joinOnColumn);
161
        virtual ~JoinedDataTable();
162

    
163
        virtual int getNumRows() const;
164
        virtual bool isNull(int row, int col) const;
165
        virtual double getDoubleValue(int row, int col) const;
166
        virtual BigDecimal getBigDecimalValue(int row, int col) const;
167
        virtual std::string getStringValue(int row, int col) const;
168
    private:
169
        void addColumn(const Column &column, int tableIndex, int colIndex);
170
        void mapTableCell(int row, int column, DataTable *&table, int &tableRow, int &tableCol) const;
171
};
172

    
173
inline void JoinedDataTable::addColumn(const Column &column, int tableIndex, int colIndex)
174
{
175
    header.push_back(column); //addColumn(column);
176
    columnMap.push_back(std::make_pair(tableIndex, colIndex));
177
}
178

    
179

    
180

    
181
/**
182
 * Base class for scalar/vector exporters.
183
 */
184
class SCAVE_API ScaveExport
185
{
186
    private:
187
        std::set<std::string> identifiers;
188

    
189
    protected:
190
        std::string baseFileName;
191
        std::string fileName;
192
        std::ofstream out;
193
        int prec;
194

    
195
    protected:
196
        void open();
197
        void close();
198
        virtual std::string makeFileName(const std::string name) = 0;
199

    
200
    public:
201
        ScaveExport() : prec(DEFAULT_PRECISION) {}
202
        virtual ~ScaveExport();
203

    
204
        void setPrecision(int prec) { this->prec = prec; }
205
        void setBaseFileName(const std::string baseFileName) { this->baseFileName = baseFileName; }
206

    
207
        virtual void saveVector(const std::string &name, const std::string &description,
208
                        ID vectorID, bool computed, const XYArray *vec, ResultFileManager &manager,
209
                        int startIndex=0, int endIndex=-1);
210
        virtual void saveVectors(const std::string &name, const std::string &description,
211
                                     const IDList &vectors, const std::vector<XYArray*> xyarrays,
212
                                     const ResultFileManager &manager);
213
        virtual void saveScalars(const std::string &name, const std::string &description,
214
                                    const IDList &scalars, ResultItemFields groupBy, ResultFileManager &manager);
215

    
216
        virtual void saveScalars(const std::string &name, const std::string &description,
217
                                    const IDList &scalars, const std::string &moduleName, const std::string &scalarName,
218
                                    ResultItemFields columnFields,
219
                                    const std::vector<std::string> &isoModuleNames, const StringVector &isoScalarNames,
220
                                    ResultItemFields isoFields, ResultFileManager &manager);
221

    
222
        const std::string &getLastFileName() const { return fileName; }
223
    protected:
224
        std::string makeUniqueIdentifier(const std::string &name);
225
        virtual std::string makeIdentifier(const std::string &name) = 0;
226
        virtual void saveTable(const DataTable &rows, int startIndex, int endIndex) = 0;
227
};
228

    
229
/**
230
 * Common base class for formats that creates a matlab structure when loaded.
231
 */
232
class MatlabStructExport : public ScaveExport
233
{
234
    protected:
235
        void writeDouble(double value);
236
        virtual std::string makeIdentifier(const std::string &name);
237
        static std::string quoteString(const std::string &str);
238
};
239

    
240
/**
241
 * Exports data as a Matlab script.
242
 *
243
 * The script defines a structure containing a description field,
244
 * and a column fields for each column. The column fields are
245
 * equal length vectors.
246
 *
247
 * Note: Although BigDecimal values (e.g. simulation time) are
248
 * written out with the specified precision, Matlab reads them as IEEE
249
 * double (max 15 digit), so their precision gets lost.
250
 *
251
 * FIXME: BigDecimals always written out with maximal precision (19 digit), prec is ignored.
252
 */
253
class SCAVE_API MatlabScriptExport : public MatlabStructExport
254
{
255
    protected:
256
        virtual std::string makeFileName(const std::string name);
257
        virtual void saveTable(const DataTable &table, int startRow, int endRow);
258
    private:
259
        void writeDescriptionField(const DataTable &rows, const std::string tableName);
260
        void writeColumnFields(const DataTable &rows, int startRow, int endRow, const std::string tableName);
261
        void writeDoubleColumn(const DataTable &table, int col, int startRow, int endRow);
262
        void writeBigDecimalColumn(const DataTable &table, int col, int startRow, int endRow);
263
        void writeStringColumn(const DataTable &table, int col, int startRow, int endRow);
264
};
265

    
266
/**
267
 * Exports data in Octave's "save -text" format. This format can be loaded
268
 * into R (r-project.org) as well.
269
 *
270
 * To see the an example, type the following commands in Octave:
271
 * <pre>
272
 *    a = [1 2; 3 4; 5 6]
273
 *    save -text - a
274
 * </pre>
275
 *
276
 * The output:
277
 * <pre>
278
 *  # Created by Octave 2.1.73 ...
279
 *  # name: a
280
 *  # type: matrix
281
 *  # rows: 3
282
 *  # columns: 2
283
 *   1 2
284
 *   3 4
285
 *   5 6
286
 * </pre>
287
 *
288
 * If several variables are saved, the above pattern repeats.
289
 *
290
 * FIXME: BigDecimals always written out with maximal precision (19 digit), prec is ignored.
291
 */
292
class SCAVE_API OctaveTextExport : public MatlabStructExport
293
{
294
    protected:
295
        virtual std::string makeFileName(const std::string name);
296
        virtual void saveTable(const DataTable &table, int startRow, int endRow);
297
    private:
298
        void writeStructHeader(const DataTable &table);
299
        void writeDescriptionField(const DataTable &table);
300
        void writeColumnFields(const DataTable &table, int startRow, int endRow);
301
        void writeDoubleColumn(const DataTable &table, int col, int startRow, int endRow);
302
        void writeBigDecimalColumn(const DataTable &table, int col, int startRow, int endRow);
303
        void writeStringColumn(const DataTable &table, int col, int startRow, int endRow);
304
};
305

    
306
/**
307
 * Export data in various CSV formats.
308
 * With default parameters the format is the same as described in RFC 4180.
309
 */
310
class SCAVE_API CsvExport : public ScaveExport
311
{
312
    public: // options
313
        typedef enum {DOUBLE, ESCAPE} QuoteMethod;
314
        char separator;
315
        char quoteChar;
316
        std::string eol;
317
        QuoteMethod quoteMethod;
318
        bool columnNames;
319
        // state
320
        int fileNameSuffix; // zero = do not add suffix, otherwise incremented when writing a new table
321
    public:
322
        CsvExport() : separator(','), quoteChar('"'), eol("\r\n"), quoteMethod(DOUBLE),
323
                        columnNames(true), fileNameSuffix(0) {}
324
        virtual void saveVector(const std::string name, const std::string description,
325
                        ID vectorID, bool computed, const XYArray *vec, ResultFileManager &manager,
326
                        int startIndex=0, int endIndex=-1);
327
    protected:
328
        virtual std::string makeFileName(const std::string name);
329
        virtual std::string makeIdentifier(const std::string &name);
330
        virtual void saveTable(const DataTable &table, int startRow, int endRow);
331
    private:
332
        void writeHeader(const DataTable &table);
333
        void writeRow(const DataTable &table, int row);
334
        void writeDouble(double value);
335
        void writeBigDecimal(BigDecimal value);
336
        void writeString(const std::string &value);
337
        bool needsQuote(const std::string &value);
338
        void writeChar(char ch);
339
};
340

    
341
class SCAVE_API ExporterFactory
342
{
343
    public:
344
        static ScaveExport *createExporter(const std::string format);
345
};
346

    
347
NAMESPACE_END
348

    
349

    
350
#endif
351

    
352