OGS
Histogram.h
Go to the documentation of this file.
1 
13 #pragma once
14 
15 #include <algorithm>
16 #include <cmath>
17 #include <fstream>
18 #include <iosfwd>
19 #include <iterator>
20 #include <utility>
21 #include <vector>
22 
23 #include "Logging.h"
24 
25 namespace BaseLib
26 {
31 template <typename T>
32 class Histogram
33 {
34 public:
35  using Data =
36  typename std::vector<double>;
37 
38 public:
49  template <typename InputIterator>
50  Histogram(InputIterator first, InputIterator last, const int nr_bins = 16,
51  const bool computeHistogram = true)
52  : data_(first, last), nr_bins_(nr_bins), dirty_(true)
53  {
54  init(computeHistogram);
55  }
56 
63  explicit Histogram(std::vector<T> data, const unsigned int nr_bins = 16,
64  const bool computeHistogram = true)
65  : data_(std::move(data)), nr_bins_(nr_bins), dirty_(true)
66  {
67  init(computeHistogram);
68  }
69 
80  void update()
81  {
82  if (!dirty_)
83  {
84  return;
85  }
86 
87  bin_width_ = (max_ - min_) / nr_bins_;
88 
89  auto it = data_.begin();
90  for (unsigned int bin = 0; bin < nr_bins_; bin++)
91  {
92  auto itEnd = std::upper_bound(it, data_.end(),
93  min_ + (bin + 1) * bin_width_);
94  histogram_[bin] = std::distance(it, itEnd);
95  it = itEnd;
96  }
97  dirty_ = false;
98  }
99 
100  void setMinimum(const T& minimum)
101  {
102  min_ = minimum;
103  dirty_ = true;
104  }
105  void setMaximum(const T& maximum)
106  {
107  max_ = maximum;
108  dirty_ = true;
109  }
110 
111  const Data& getSortedData() const { return data_; }
112  const std::vector<std::size_t>& getBinCounts() const { return histogram_; }
113  const unsigned int& getNumberOfBins() const { return nr_bins_; }
114  const T& getMinimum() const { return min_; }
115  const T& getMaximum() const { return max_; }
116  const T& getBinWidth() const { return bin_width_; }
117 
118  void prettyPrint(std::ostream& os, const unsigned int line_width = 16) const
119  {
120  const std::size_t count_max =
121  *std::max_element(histogram_.begin(), histogram_.end());
122  for (unsigned int bin = 0; bin < nr_bins_; ++bin)
123  {
124  os << "[" << min_ + bin * bin_width_ << ", "
125  << min_ + (bin + 1) * bin_width_ << ")\t";
126  os << histogram_[bin] << "\t";
127 
128  const int n_stars =
129  std::ceil(line_width * ((double)histogram_[bin] / count_max));
130  for (int star = 0; star < n_stars; star++)
131  {
132  os << "*";
133  }
134  os << "\n";
135  }
136  }
137 
138  int write(std::string const& file_name, std::string const& data_set_name,
139  std::string const& param_name) const
140  {
141  if (file_name.empty())
142  {
143  ERR("No file name specified.");
144  return 1;
145  }
146 
147  std::ofstream out(file_name);
148  if (!out)
149  {
150  ERR("Error writing histogram: Could not open file.");
151  return 1;
152  }
153 
154  out << "# Histogram for parameter " << param_name << " of data set "
155  << data_set_name << "\n";
156  std::size_t const n_bins = this->getNumberOfBins();
157  std::vector<std::size_t> const& bin_cnts(this->getBinCounts());
158  double const min(this->getMinimum());
159  double const bin_width(this->getBinWidth());
160 
161  for (std::size_t k(0); k < n_bins; k++)
162  {
163  out << min + k * bin_width << " " << bin_cnts[k] << "\n";
164  }
165  out.close();
166  return 0;
167  }
168 
169 protected:
172  void init(const bool computeHistogram = true)
173  {
174  std::sort(data_.begin(), data_.end());
175  histogram_.resize(nr_bins_);
176  min_ = data_.front();
177  max_ = data_.back();
178  bin_width_ = (max_ - min_) / nr_bins_;
179 
180  dirty_ = true;
181  if (computeHistogram)
182  {
183  update();
184  }
185  }
186 
188  const unsigned int nr_bins_;
189  std::vector<std::size_t> histogram_;
190  T min_, max_;
192 
193 private:
194  bool dirty_;
195 };
196 
202 template <typename T>
203 std::ostream& operator<<(std::ostream& os, const Histogram<T>& h)
204 {
205  os << h.getNumberOfBins() << " " << h.getMinimum() << " " << h.getMaximum()
206  << " ";
207  std::copy(h.getBinCounts().begin(), h.getBinCounts().end(),
208  std::ostream_iterator<T>(os, " "));
209  return os << std::endl;
210 }
211 } // namespace BaseLib
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
const T & getBinWidth() const
Definition: Histogram.h:116
const unsigned int & getNumberOfBins() const
Definition: Histogram.h:113
bool dirty_
When set update() will recompute histogram.
Definition: Histogram.h:194
const T & getMinimum() const
Definition: Histogram.h:114
void setMaximum(const T &maximum)
Definition: Histogram.h:105
T max_
Minimum and maximum input data values.
Definition: Histogram.h:190
void init(const bool computeHistogram=true)
Definition: Histogram.h:172
void prettyPrint(std::ostream &os, const unsigned int line_width=16) const
Definition: Histogram.h:118
Histogram(std::vector< T > data, const unsigned int nr_bins=16, const bool computeHistogram=true)
Definition: Histogram.h:63
const std::vector< std::size_t > & getBinCounts() const
Definition: Histogram.h:112
const Data & getSortedData() const
Definition: Histogram.h:111
typename std::vector< double > Data
Definition: Histogram.h:36
std::vector< std::size_t > histogram_
Definition: Histogram.h:189
const T & getMaximum() const
Definition: Histogram.h:115
Histogram(InputIterator first, InputIterator last, const int nr_bins=16, const bool computeHistogram=true)
Underlying input data vector type.
Definition: Histogram.h:50
void setMinimum(const T &minimum)
Definition: Histogram.h:100
const unsigned int nr_bins_
Definition: Histogram.h:188
int write(std::string const &file_name, std::string const &data_set_name, std::string const &param_name) const
Definition: Histogram.h:138
std::ostream & operator<<(std::ostream &os, const Histogram< T > &h)
Definition: Histogram.h:203
void copy(PETScVector const &x, PETScVector &y)
Definition: LinAlg.cpp:37