faunus
table_2d.h
1 #pragma once
2 #include <map>
3 #include <vector>
4 #include <string>
5 #include <average.h>
6 #include <Eigen/Core>
7 #include <fstream>
8 
9 namespace Faunus {
18 template <typename Tx, typename Ty> class Table2D
19 {
20  protected:
21  typedef std::map<Tx, Ty> Tmap;
22 
23  Ty count()
24  {
25  Ty cnt = 0;
26  for (auto& m : map)
27  cnt += m.second;
28  return cnt;
29  }
30 
31  Tx dx;
32  Tmap map;
33  std::string name;
34 
35  private:
36  Tx round(Tx x) { return (x >= 0) ? int(x / dx + 0.5) * dx : int(x / dx - 0.5) * dx; }
37 
38  double get(Tx x) { return operator()(x); }
39 
40  public:
41  enum type
42  {
43  HISTOGRAM,
44  XYDATA
45  };
46 
47  type tabletype;
48 
50  Ty sumy() const
51  {
52  Ty sum = 0;
53  for (auto& m : map)
54  sum += m.second;
55  return sum;
56  }
57 
63  Table2D(Tx resolution = 0.2, type key = XYDATA)
64  {
65  tabletype = key;
66  setResolution(resolution);
67  }
68 
70  std::map<std::string, std::vector<double>> to_map()
71  {
72  std::map<std::string, std::vector<double>> m;
73  m["x"].reserve(map.size());
74  m["y"].reserve(map.size());
75  for (auto& i : map) {
76  m["x"].push_back(i.first);
77  m["y"].push_back(get(i.first));
78  }
79  return m;
80  }
81 
82  void clear() { map.clear(); }
83 
84  void setResolution(Tx resolution)
85  {
86  assert(resolution > 0);
87  dx = resolution;
88  map.clear();
89  }
90 
91  void setResolution(std::vector<Tx>& resolution)
92  {
93  assert(resolution[0] > 0);
94  dx = resolution[0];
95  map.clear();
96  }
97 
99  Ty& operator()(Tx x) { return map[round(x)]; }
100 
102  Ty& operator()(std::vector<Tx>& x) { return map[round(x[0])]; }
103 
105  Ty find(std::vector<Tx>& x)
106  {
107  Ty value = 0;
108  auto it = map.find(round(x[0]));
109  if (it != map.end())
110  value = it->second;
111  return value;
112  }
113 
115  template <class T = double> void save(const std::string& filename, T scale = 1, T translate = 0)
116  {
117  if (tabletype == HISTOGRAM) {
118  if (!map.empty())
119  map.begin()->second *= 2; // compensate for half bin width
120  if (map.size() > 1)
121  (--map.end())->second *= 2; // -//-
122  }
123 
124  if (!map.empty()) {
125  std::ofstream f(filename.c_str());
126  f.precision(10);
127  if (f) {
128  for (auto& m : map)
129  f << m.first << " " << (m.second + translate) * scale << "\n";
130  }
131  }
132 
133  if (tabletype == HISTOGRAM) {
134  if (!map.empty())
135  map.begin()->second /= 2; // restore half bin width
136  if (map.size() > 1)
137  (--map.end())->second /= 2; // -//-
138  }
139  }
140 
142  template <class T = double> void normSave(const std::string& filename)
143  {
144  if (tabletype == HISTOGRAM) {
145  if (!map.empty())
146  map.begin()->second *= 2; // compensate for half bin width
147  if (map.size() > 1)
148  (--map.end())->second *= 2; // -//-
149  }
150 
151  if (!map.empty()) {
152  std::ofstream f(filename.c_str());
153  f.precision(10);
154  Ty cnt = count() * dx;
155  if (f) {
156  for (auto& m : map)
157  f << m.first << " " << m.second / cnt << "\n";
158  }
159  }
160 
161  if (tabletype == HISTOGRAM) {
162  if (!map.empty())
163  map.begin()->second /= 2; // restore half bin width
164  if (map.size() > 1)
165  (--map.end())->second /= 2; // -//-
166  }
167  }
168 
170  template <class T = double> void sumSave(std::string filename, T scale = 1)
171  {
172  if (tabletype == HISTOGRAM) {
173  if (!map.empty())
174  map.begin()->second *= 2; // compensate for half bin width
175  if (map.size() > 1)
176  (--map.end())->second *= 2; // -//-
177  }
178 
179  if (!map.empty()) {
180  std::ofstream f(filename.c_str());
181  f.precision(10);
182  if (f) {
183  Ty sum_t = 0.0;
184  for (auto& m : map) {
185  sum_t += m.second;
186  f << m.first << " " << sum_t * scale << "\n";
187  }
188  }
189  }
190 
191  if (tabletype == HISTOGRAM) {
192  if (!map.empty())
193  map.begin()->second /= 2; // restore half bin width
194  if (map.size() > 1)
195  (--map.end())->second /= 2; // -//-
196  }
197  }
198 
199  const Tmap& getMap() const { return map; }
200 
201  Tmap& getMap() { return map; }
202 
203  Tx getResolution() { return dx; }
204 
206  Tx mean()
207  {
208  assert(!map.empty());
209  Tx avg = 0;
210  for (auto& m : map)
211  avg += m.first * m.second;
212  return avg / count();
213  }
214 
216  Tx std()
217  {
218  assert(!map.empty());
219  Tx std2 = 0;
220  Tx avg = mean();
221  for (auto& m : map)
222  std2 += m.second * (m.first - avg) * (m.first - avg);
223  return sqrt(std2 / count());
224  }
225 
227  typename Tmap::const_iterator min()
228  {
229  assert(!map.empty());
230  Ty min = std::numeric_limits<Ty>::max();
231  typename Tmap::const_iterator it;
232  for (auto m = map.begin(); m != map.end(); ++m)
233  if (m->second < min) {
234  min = m->second;
235  it = m;
236  }
237  return it;
238  }
239 
241  typename Tmap::const_iterator max()
242  {
243  assert(!map.empty());
244  Ty max = std::numeric_limits<Ty>::min();
245  typename Tmap::const_iterator it;
246  for (auto m = map.begin(); m != map.end(); ++m)
247  if (m->second > max) {
248  max = m->second;
249  it = m;
250  }
251  return it;
252  }
253 
255  Tx minx()
256  {
257  assert(!map.empty());
258  Tx x = 0;
259  for (auto& m : map) {
260  x = m.first;
261  break;
262  }
263  return x;
264  }
265 
267  Ty avg(const std::vector<Tx>& limits)
268  {
269  Ty avg = 0;
270  int cnt = 0;
271  assert(!map.empty());
272  for (auto& m : map) {
273  if (m.first >= limits[0] && m.first <= limits[1]) {
274  avg += m.second;
275  ++cnt;
276  }
277  }
278  if (cnt > 0)
279  avg /= cnt;
280  return avg;
281  }
282 
286  std::vector<double> hist2buf(int& size)
287  {
288  std::vector<double> sendBuf;
289  assert(!map.empty());
290  for (auto& m : map) {
291  sendBuf.push_back(m.first);
292  sendBuf.push_back(m.second);
293  }
294  sendBuf.resize(size, -1);
295  return sendBuf;
296  }
297 
301  void buf2hist(std::vector<double>& v)
302  {
303  this->clear();
304  assert(!v.empty());
305  std::map<double, Average<double>> all;
306  for (int i = 0; i < int(v.size()) - 1; i += 2)
307  if (v.at(i + 1) != -1)
308  all[v.at(i)] += v.at(i + 1);
309  for (auto& m : all)
310  this->operator()(m.first) = m.second.avg();
311  }
312 
319  bool load(const std::string& filename)
320  {
321  std::ifstream f(filename.c_str());
322  if (f) {
323  map.clear();
324  while (!f.eof()) {
325  Tx x;
326  double y;
327  f >> x >> y;
328  operator()(x) = y;
329  }
330  if (tabletype == HISTOGRAM) {
331  if (!map.empty())
332  map.begin()->second /= 2; // restore half bin width
333  if (map.size() > 1)
334  (--map.end())->second /= 2; // -//-
335  }
336  return true;
337  }
338  return false;
339  }
340 
344  Eigen::MatrixXd tableToMatrix()
345  {
346  assert(!this->map.empty() && "Map is empty!");
347  Eigen::MatrixXd table(2, map.size());
348  table.setZero();
349  int I = 0;
350  for (auto& m : this->map) {
351  table(0, I) = m.first;
352  table(1, I) = m.second;
353  I++;
354  }
355  return table;
356  }
357 };
358 
362 template <class Tx, class Ty> Table2D<Tx, Ty> operator-(Table2D<Tx, Ty>& a, Table2D<Tx, Ty>& b)
363 {
364  assert(a.tabletype == b.tabletype && "Table a and b needs to be of same type");
365  Table2D<Tx, Ty> c(std::min(a.getResolution(), b.getResolution()), a.tabletype);
366  auto a_map = a.getMap();
367  auto b_map = b.getMap();
368 
369  if (a.tabletype == Table2D<Tx, Ty>::HISTOGRAM) {
370  if (!a_map.empty())
371  a_map.begin()->second *= 2; // compensate for half bin width
372  if (a_map.size() > 1)
373  (--a_map.end())->second *= 2; // -//-
374  if (!b_map.empty())
375  b_map.begin()->second *= 2; // compensate for half bin width
376  if (b_map.size() > 1)
377  (--b_map.end())->second *= 2; // -//-
378  }
379 
380  for (auto& m1 : a_map) {
381  for (auto& m2 : b_map) {
382  c(m1.first) = m1.second - m2.second;
383  break;
384  }
385  }
386 
387  if (a.tabletype == Table2D<Tx, Ty>::HISTOGRAM) {
388  if (!a_map.empty())
389  a_map.begin()->second /= 2; // compensate for half bin width
390  if (a_map.size() > 1)
391  (--a_map.end())->second /= 2; // -//-
392  if (!b_map.empty())
393  b_map.begin()->second /= 2; // compensate for half bin width
394  if (b_map.size() > 1)
395  (--b_map.end())->second /= 2; // -//-
396  }
397  return c;
398 }
399 
403 template <class Tx, class Ty> Table2D<Tx, Ty> operator+(Table2D<Tx, Ty>& a, Table2D<Tx, Ty>& b)
404 {
405  assert(a.tabletype == b.tabletype && "Table a and b needs to be of same type");
406  Table2D<Tx, Ty> c(std::min(a.getResolution(), b.getResolution()), a.tabletype);
407  auto a_map = a.getMap();
408  auto b_map = b.getMap();
409 
410  if (a.tabletype == Table2D<Tx, Ty>::HISTOGRAM) {
411  if (!a_map.empty())
412  a_map.begin()->second *= 2; // compensate for half bin width
413  if (a_map.size() > 1)
414  (--a_map.end())->second *= 2; // -//-
415  if (!b_map.empty())
416  b_map.begin()->second *= 2; // compensate for half bin width
417  if (b_map.size() > 1)
418  (--b_map.end())->second *= 2; // -//-
419  }
420 
421  for (auto& m : a_map) {
422  c(m.first) += m.second;
423  }
424  for (auto& m : b_map) {
425  c(m.first) += m.second;
426  }
427 
428  if (a.tabletype == Table2D<Tx, Ty>::HISTOGRAM) {
429  if (!a_map.empty())
430  a_map.begin()->second /= 2; // compensate for half bin width
431  if (a_map.size() > 1)
432  (--a_map.end())->second /= 2; // -//-
433  if (!b_map.empty())
434  b_map.begin()->second /= 2; // compensate for half bin width
435  if (b_map.size() > 1)
436  (--b_map.end())->second /= 2; // -//-
437  }
438 
439  return c;
440 }
441 
442 } // namespace Faunus
Tmap::const_iterator min()
Definition: table_2d.h:227
Ty & operator()(Tx x)
Access operator - returns reference to y(x)
Definition: table_2d.h:99
Table2D< Tx, Ty > operator-(Table2D< Tx, Ty > &a, Table2D< Tx, Ty > &b)
Subtract two tables.
Definition: table_2d.h:362
double T
floating point size
Definition: units.h:73
General class for handling 2D tables - xy data, for example.
Definition: table_2d.h:18
Tx mean()
Definition: table_2d.h:206
Table2D(Tx resolution=0.2, type key=XYDATA)
Constructor.
Definition: table_2d.h:63
Definition: table.py:1
Ty avg(const std::vector< Tx > &limits)
Definition: table_2d.h:267
Ty sumy() const
Sum of all y values (same as count())
Definition: table_2d.h:50
Ty find(std::vector< Tx > &x)
Find key and return corresponding value otherwise zero.
Definition: table_2d.h:105
std::map< std::string, std::vector< double > > to_map()
Convert to map.
Definition: table_2d.h:70
Tx std()
Definition: table_2d.h:216
Cell list class templates.
Definition: actions.cpp:11
void buf2hist(std::vector< double > &v)
Convert vector of floats to table2D.
Definition: table_2d.h:301
void sumSave(std::string filename, T scale=1)
Sums up all previous elements and saves table to disk.
Definition: table_2d.h:170
std::vector< double > hist2buf(int &size)
Convert table2D to vector of floats.
Definition: table_2d.h:286
Table2D< Tx, Ty > operator+(Table2D< Tx, Ty > &a, Table2D< Tx, Ty > &b)
Addition two tables.
Definition: table_2d.h:403
bool load(const std::string &filename)
Load table from disk.
Definition: table_2d.h:319
Tmap::const_iterator max()
Definition: table_2d.h:241
Ty & operator()(std::vector< Tx > &x)
Access operator - returns reference to y(x)
Definition: table_2d.h:102
void save(const std::string &filename, T scale=1, T translate=0)
Save table to disk.
Definition: table_2d.h:115
Tx minx()
Definition: table_2d.h:255
void normSave(const std::string &filename)
Save normalized table to disk.
Definition: table_2d.h:142
Eigen::MatrixXd tableToMatrix()
Convert table to matrix.
Definition: table_2d.h:344