Loading...
Searching...
No Matches
datatable.C
1/*
2 * This file is part of the SPLINTER library.
3 * Copyright (C) 2012 Bjarne Grimstad (bjarne.grimstad@gmail.com).
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8*/
9
10#include "datatable.h"
11#include <string>
12#include <fstream>
13#include <iomanip>
14#include <stdexcept>
15#include <limits>
16#include <serializer.h>
17#include <initializer_list>
18#include "IOstreams.H"
19
20namespace SPLINTER
21{
22
23DataTable::DataTable()
24 : DataTable(false, false)
25{
26}
27
28DataTable::DataTable(bool allowDuplicates)
29 : DataTable(allowDuplicates, false)
30{
31}
32
33DataTable::DataTable(bool allowDuplicates, bool allowIncompleteGrid)
34 : allowDuplicates(allowDuplicates),
35 allowIncompleteGrid(allowIncompleteGrid),
36 numDuplicates(0),
37 numVariables(0)
38{
39}
40
41DataTable::DataTable(const char* fileName)
42 : DataTable(std::string(fileName))
43{
44}
45
46DataTable::DataTable(const std::string& fileName)
47{
48 load(fileName);
49}
50
51void DataTable::addSample(double x, double y)
52{
53 addSample(DataPoint(x, y));
54}
55
56void DataTable::addSample(std::vector<double> x, double y)
57{
58 addSample(DataPoint(x, y));
59}
60
61void DataTable::addSample(DenseVector x, double y)
62{
63 addSample(DataPoint(x, y));
64}
65
66void DataTable::addSample(const DataPoint& sample)
67{
68 if (getNumSamples() == 0)
69 {
70 numVariables = sample.getDimX();
71 initDataStructures();
72 }
73
74 if (sample.getDimX() != numVariables)
75 {
76 throw Exception("Datatable::addSample: Dimension of new sample is inconsistent with previous samples!");
77 }
78
79 // Check if the sample has been added already
80 if (samples.count(sample) > 0)
81 {
82 if (!allowDuplicates)
83 {
84#ifndef NDEBUG
85 Foam::Info << "Discarding duplicate sample because allowDuplicates is false!" <<
86 Foam::endl;
87 Foam::Info << "Initialise with DataTable(true) to set it to true." << Foam::endl;
88#endif // NDEBUG
89 return;
90 }
91
92 numDuplicates++;
93 }
94
95 samples.insert(sample);
96 recordGridPoint(sample);
97}
98
99void DataTable::addSample(std::initializer_list<DataPoint> samples)
100{
101 for (auto & sample : samples)
102 {
103 addSample(sample);
104 }
105}
106
107void DataTable::recordGridPoint(const DataPoint& sample)
108{
109 for (unsigned int i = 0; i < getNumVariables(); i++)
110 {
111 grid.at(i).insert(sample.getX().at(i));
112 }
113}
114
115unsigned int DataTable::getNumSamplesRequired() const
116{
117 unsigned long samplesRequired = 1;
118 unsigned int i = 0;
119
120 for (auto & variable : grid)
121 {
122 samplesRequired *= (unsigned long) variable.size();
123 i++;
124 }
125
126 return (i > 0 ? samplesRequired : (unsigned long) 0);
127}
128
129bool DataTable::isGridComplete() const
130{
131 return samples.size() > 0
132 && samples.size() - numDuplicates == getNumSamplesRequired();
133}
134
135void DataTable::initDataStructures()
136{
137 for (unsigned int i = 0; i < getNumVariables(); i++)
138 {
139 grid.push_back(std::set<double>());
140 }
141}
142
143void DataTable::gridCompleteGuard() const
144{
145 if (!(isGridComplete() || allowIncompleteGrid))
146 {
147 throw Exception("DataTable::gridCompleteGuard: The grid is not complete yet!");
148 }
149}
150
151void DataTable::save(const std::string& fileName) const
152{
153 Serializer s;
154 s.serialize(* this);
155 s.saveToFile(fileName);
156}
157
158void DataTable::load(const std::string& fileName)
159{
160 Serializer s(fileName);
161 s.deserialize(* this);
162}
163
164/*
165 * Getters for iterators
166 */
167std::multiset<DataPoint>::const_iterator DataTable::cbegin() const
168{
169 return samples.cbegin();
170}
171
172std::multiset<DataPoint>::const_iterator DataTable::cend() const
173{
174 return samples.cend();
175}
176
177/*
178 * Get table of samples x-values,
179 * i.e. table[i][j] is the value of variable i at sample j
180 */
181std::vector< std::vector<double >> DataTable::getTableX() const
182{
183 gridCompleteGuard();
184 // Initialize table
185 std::vector<std::vector<double >> table;
186
187 for (unsigned int i = 0; i < numVariables; i++)
188 {
189 std::vector<double> xi(getNumSamples(), 0.0);
190 table.push_back(xi);
191 }
192
193 // Fill table with values
194 int i = 0;
195
196 for (auto & sample : samples)
197 {
198 std::vector<double> x = sample.getX();
199
200 for (unsigned int j = 0; j < numVariables; j++)
201 {
202 table.at(j).at(i) = x.at(j);
203 }
204
205 i++;
206 }
207
208 return table;
209}
210
211// Get vector of y-values
212std::vector<double> DataTable::getVectorY() const
213{
214 std::vector<double> y;
215
216 for (std::multiset<DataPoint>::const_iterator it = cbegin(); it != cend(); ++it)
217 {
218 y.push_back(it->getY());
219 }
220
221 return y;
222}
223
224DataTable operator+(const DataTable& lhs, const DataTable& rhs)
225{
226 if (lhs.getNumVariables() != rhs.getNumVariables())
227 {
228 throw Exception("operator+(DataTable, DataTable): trying to add two DataTable's of different dimensions!");
229 }
230
231 DataTable result;
232
233 for (auto it = lhs.cbegin(); it != lhs.cend(); it++)
234 {
235 result.addSample(* it);
236 }
237
238 for (auto it = rhs.cbegin(); it != rhs.cend(); it++)
239 {
240 result.addSample(* it);
241 }
242
243 return result;
244}
245
246DataTable operator-(const DataTable& lhs, const DataTable& rhs)
247{
248 if (lhs.getNumVariables() != rhs.getNumVariables())
249 {
250 throw Exception("operator-(DataTable, DataTable): trying to subtract two DataTable's of different dimensions!");
251 }
252
253 DataTable result;
254 auto rhsSamples = rhs.getSamples();
255
256 // Add all samples from lhs that are not in rhs
257 for (auto it = lhs.cbegin(); it != lhs.cend(); it++)
258 {
259 if (rhsSamples.count(* it) == 0)
260 {
261 result.addSample(* it);
262 }
263 }
264
265 return result;
266}
267
268} // namespace SPLINTER