SSAGES  0.1
A MetaDynamics Package
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Groups Pages
Histogram.h
1 
20 #pragma once
21 
22 #include <exception>
23 
24 #include "Drivers/DriverException.h"
25 #include "GridBase.h"
26 #include "schema.h"
27 #include "Validator/ObjectRequirement.h"
28 
29 namespace SSAGES
30 {
31 
33 
63 template<typename T>
64 class Histogram : public GridBase<T>
65 {
66 private:
68 
76  size_t mapTo1d(const std::vector<int> &indices) const override
77  {
78  // Check if an index is out of bounds
79  for (size_t i=0; i < GridBase<T>::GetDimension(); ++i) {
80  int index = indices.at(i);
81  bool periodic = GridBase<T>::GetPeriodic(i);
82  int numpoints = GridBase<T>::GetNumPoints(i);
83  if ( (periodic && (index < 0 || index >= numpoints)) ||
84  (periodic && (index < -1 || index > numpoints)) )
85  {
86  throw std::out_of_range("Bin index out of range.");
87  }
88  }
89 
90  size_t idx = 0;
91  size_t fac = 1;
92  for (size_t i=0; i < GridBase<T>::GetDimension(); ++i) {
93  if (GridBase<T>::GetPeriodic(i)) {
94  idx += indices.at(i) * fac;
95  fac *= GridBase<T>::GetNumPoints(i);
96  } else {
97  idx += (indices.at(i) + 1) * fac;
98  fac *= GridBase<T>::GetNumPoints(i) + 2;
99  }
100  }
101  return idx;
102  }
103 
104 public:
106 
116  Histogram(std::vector<int> numPoints,
117  std::vector<double> lower,
118  std::vector<double> upper,
119  std::vector<bool> isPeriodic)
120  : GridBase<T>(numPoints, lower, upper, isPeriodic)
121  {
122  size_t data_size = 1;
123  for (size_t d = 0; d < GridBase<T>::GetDimension(); ++d) {
124  size_t storage_size = GridBase<T>::GetNumPoints(d);
125  if (!GridBase<T>::GetPeriodic(d)) { storage_size += 2; }
126  data_size *= storage_size;
127  }
128 
129  GridBase<T>::data_.resize(data_size);
130  }
131 
133 
141  static Histogram<T>* BuildHistogram(const Json::Value& json)
142  {
143  return BuildHistogram(json, "#/Histogram");
144  }
145 
147 
156  static Histogram<T>* BuildHistogram(const Json::Value& json, const std::string& path)
157  {
158  Json::ObjectRequirement validator;
159  Json::Value schema;
160  Json::Reader reader;
161 
162  reader.parse(JsonSchema::grid, schema);
163  validator.Parse(schema, path);
164 
165  // Validate inputs.
166  validator.Validate(json, path);
167  if (validator.HasErrors()) {
168  throw BuildException(validator.GetErrors());
169  }
170 
171  // Read in Lower Grid edges.
172  std::vector<double> lower;
173  for (auto &lv : json["lower"]) {
174  lower.push_back(lv.asDouble());
175  }
176 
177  size_t dimension = lower.size();
178 
179  // Read in upper grid edges.
180  std::vector<double> upper;
181  for (auto &uv : json["upper"]) {
182  upper.push_back(uv.asDouble());
183  }
184 
185  if (upper.size() != dimension) {
186  throw BuildException({"Number of upper values does not match "
187  "number of lower values!"});
188  }
189 
190  // Read in number of points.
191  std::vector<int> number_points;
192  for (auto &np : json["number_points"]) {
193  number_points.push_back(np.asInt());
194  }
195 
196  if (number_points.size() != dimension) {
197  throw BuildException({"Arrays \"lower\" and \"number_points\" do "
198  "not have the same size!"});
199  }
200 
201  // Read in periodicity.
202  std::vector<bool> isPeriodic;
203  for (auto &periodic : json["periodic"]) {
204  isPeriodic.push_back(periodic.asBool());
205  }
206 
207  if (isPeriodic.size() == 0) {
208  isPeriodic = std::vector<bool>(dimension, false);
209  } else if (isPeriodic.size() != dimension) {
210  throw BuildException({"Arrays \"lower\" and \"periodic\" do not "
211  "have the same size!"});
212  }
213 
214  // Construct the grid.
215  Histogram<T>* hist = new Histogram(number_points, lower, upper, isPeriodic);
216 
217  return hist;
218  }
219 
221 
255  template<typename R>
256  class HistIterator {
257  public:
260 
262  typedef int difference_type;
263 
265  typedef R value_type;
266 
268  typedef R* pointer;
269 
271  typedef R& reference;
272 
274  typedef std::bidirectional_iterator_tag iterator_category;
275 
277  HistIterator() = default;
278 
280 
285  HistIterator(const std::vector<int> &indices, Histogram<T> *hist)
286  : indices_(indices), hist_(hist)
287  {
288  }
289 
291 
295  : indices_(other.indices_), hist_(other.hist_)
296  {
297  }
298 
300 
303  reference operator*() { return hist_->at(indices_); }
304 
306 
316  {
317  indices_.at(0) += 1;
318  for (size_t i = 0; i < hist_->GetDimension() - 1; ++i) {
319  if (hist_->GetPeriodic(i) &&
320  indices_.at(i) >= hist_->GetNumPoints(i)) {
321 
322  indices_.at(i) = 0;
323  indices_.at(i+1) += 1;
324  } else if (!hist_->GetPeriodic(i) &&
325  indices_.at(i) > hist_->GetNumPoints(i)) {
326 
327  indices_.at(i) = -1;
328  indices_.at(i+1) += 1;
329  }
330  }
331 
332  return *this;
333  }
334 
336 
340  {
341  HistIterator it(*this);
342  ++(*this);
343  return it;
344  }
345 
347  /*
348  * \param shift Vector of shifts in each dimension.
349  * \return Reference to itself.
350  *
351  * This operator shifts the current position of the iterator by the
352  * given amount in each dimension.
353  *
354  * Example:
355  *
356  * if += {1,1,1};
357  *
358  * In this example the current position of the iterator is shifted
359  * diagonally.
360  */
361  self_type &operator+=(std::vector<int> shift)
362  {
363  if (shift.size() != hist_->GetDimension()) {
364  throw std::invalid_argument("Vector to shift iterator does not "
365  "match histogram dimension.");
366  }
367 
368  for (size_t i = 0; i < hist_->GetDimension(); ++i) {
369  indices_.at(i) += shift.at(i);
370  }
371 
372  return *this;
373  }
374 
376 
382  const self_type operator+(std::vector<int> shift)
383  {
384  return HistIterator(*this) += shift;
385  }
386 
388 
395  {
396  indices_.at(0) -= 1;
397  for (size_t i = 0; i < hist_->GetDimension() - 1; ++i) {
398  if (hist_->GetPeriodic(i) && indices_.at(i) < 0) {
399  indices_.at(i) = hist_->GetNumPoints(i)-1;
400  indices_.at(i+1) -= 1;
401  } else if (!hist_->GetPeriodic(i) && indices_.at(i) < -1) {
402  indices_.at(i) = hist_->GetNumPoints(i);
403  indices_.at(i+1) -= 1;
404  }
405  }
406 
407  return *this;
408  }
409 
411 
415  {
416  HistIterator it(*this);
417  --(*this);
418  return it;
419  }
420 
422 
426  self_type &operator-=(std::vector<int> shift)
427  {
428  if (shift.size() != hist_->GetDimension()) {
429  throw std::invalid_argument("Vector to shift iterator does not "
430  "match histogram dimension.");
431  }
432 
433  for (size_t i = 0; i < hist_->GetDimension(); ++i) {
434  indices_.at(i) -= shift.at(i);
435  }
436 
437  return *this;
438  }
439 
441 
445  const self_type operator-(std::vector<int> shift)
446  {
447  return HistIterator(*this) -= shift;
448  }
449 
451 
456  bool operator==(const self_type &rhs) const
457  {
458  return indices_ == rhs.indices_ && hist_ == rhs.hist_;
459  }
460 
462 
467  bool operator!=(const self_type &rhs) const
468  {
469  return !( (*this) == rhs );
470  }
471 
473 
479  std::vector<int> &indices()
480  {
481  return indices_;
482  }
483 
485 
490  int &index(size_t d)
491  {
492  return indices()[d];
493  }
494 
496 
499  bool isUnderOverflowBin() const
500  {
501  for (size_t i = 0; i < indices_.size(); ++i) {
502  if (indices_.at(i) == -1 || indices_.at(i) == hist_->GetNumPoints(i)) {
503  return true;
504  }
505  }
506  return false;
507  }
508 
510 
513  std::vector<double> coordinates() const
514  {
515  return hist_->GetCoordinates(indices_);
516  }
517 
519 
523  double coordinate(size_t d) const
524  {
525  return coordinates()[d];
526  }
527 
528  private:
530  std::vector<int> indices_;
531 
534  };
535 
537  typedef HistIterator<T> iterator;
538 
540  typedef HistIterator<const T> const_iterator;
541 
543 
550  {
551  std::vector<int> indices(GridBase<T>::GetDimension());
552  for (size_t i = 0; i < indices.size(); ++i) {
553  if(GridBase<T>::GetPeriodic(i)) {
554  indices.at(i) = 0;
555  } else {
556  indices.at(i) = -1;
557  }
558  }
559 
560  return iterator(indices, this);
561  }
562 
564 
572  {
573  std::vector<int> indices(GridBase<T>::GetDimension());
574  for (size_t i = 0; i < indices.size(); ++i) {
575  if (GridBase<T>::GetPeriodic(i)) {
576  indices.at(i) = GridBase<T>::GetNumPoints(i) - 1;
577  } else {
578  indices.at(i) = GridBase<T>::GetNumPoints(i);
579  }
580  }
581 
582  iterator it(indices, this);
583  return ++it;
584  }
585 
587 
593  typename std::vector<T>::const_iterator begin() const
594  {
595  std::vector<int> indices(GridBase<T>::GetDimension());
596  for (size_t i = 0; i < indices.size(); ++i) {
597  if(GridBase<T>::GetPeriodic(i)) {
598  indices.at(i) = 0;
599  } else {
600  indices.at(i) = -1;
601  }
602  }
603 
604  return iterator(indices, this);
605  }
606 
608 
615  typename std::vector<T>::const_iterator end() const
616  {
617  std::vector<int> indices(GridBase<T>::GetDimension());
618  for (size_t i = 0; i < indices.size(); ++i) {
619  if (GridBase<T>::GetPeriodic(i)) {
620  indices.at(i) = GridBase<T>::GetNumPoints(i) - 1;
621  } else {
622  indices.at(i) = GridBase<T>::GetNumPoints(i);
623  }
624  }
625 
626  iterator it(indices, this);
627  return ++it;
628  }
629 };
630 
631 } // End namespace SSAGES
R value_type
Either T or const T for iterator and const_iterator, respectively.
Definition: Histogram.h:265
HistIterator self_type
Type name of the iterator.
Definition: Histogram.h:259
bool HasErrors()
Check if errors have occured.
Definition: Requirement.h:86
self_type & operator-=(std::vector< int > shift)
Subtraction assignment operator.
Definition: Histogram.h:426
self_type operator++(int)
Post-increment operator.
Definition: Histogram.h:339
int & index(size_t d)
Access a specific index.
Definition: Histogram.h:490
Histogram< T > * hist_
Pointer to histogram to iterate over.
Definition: Histogram.h:533
Basic Histogram.
Definition: Histogram.h:64
self_type & operator++()
Pre-increment operator.
Definition: Histogram.h:315
HistIterator(const HistIterator &other)
Copy constructor.
Definition: Histogram.h:294
size_t mapTo1d(const std::vector< int > &indices) const override
Map d-dimensional indices to 1-d data vector.
Definition: Histogram.h:76
std::vector< T >::const_iterator end() const
Return const iterator after last valid bin.
Definition: Histogram.h:615
HistIterator< T > iterator
Custom iterator over a histogram.
Definition: Histogram.h:537
HistIterator()=default
Use default constructor.
virtual void Parse(Value json, const std::string &path) override
Parse JSON value to generate Requirement(s).
R & reference
Either T& or T const& for iterator and const_iterator, respectively.
Definition: Histogram.h:271
Exception to be thrown when building the Driver fails.
int difference_type
Difference type is an int.
Definition: Histogram.h:262
self_type & operator--()
Pre-decrement operator.
Definition: Histogram.h:394
std::vector< int > indices_
Indices of current bin.
Definition: Histogram.h:530
std::vector< std::string > GetErrors()
Get list of error messages.
Definition: Requirement.h:92
const std::vector< bool > & GetPeriodic() const
Return the periodicity of the Grid.
Definition: GridBase.h:219
HistIterator(const std::vector< int > &indices, Histogram< T > *hist)
Constructor.
Definition: Histogram.h:285
bool operator==(const self_type &rhs) const
Equality operator.
Definition: Histogram.h:456
iterator end()
Return iterator after last valid bin.
Definition: Histogram.h:571
const self_type operator+(std::vector< int > shift)
Addition operator.
Definition: Histogram.h:382
Requirements on an object.
self_type & operator+=(std::vector< int > shift)
Addition assignment operator.
Definition: Histogram.h:361
bool isUnderOverflowBin() const
Check if current iterator position is under- or overflow bin.
Definition: Histogram.h:499
double coordinate(size_t d) const
Access specific coordinate dimension.
Definition: Histogram.h:523
self_type operator--(int)
Post-decrement operator.
Definition: Histogram.h:414
const std::vector< int > & GetNumPoints() const
Get the number of points for all dimensions.
Definition: GridBase.h:138
R * pointer
Either T* or T const* for iterator and const_iterator, respectively.
Definition: Histogram.h:268
HistIterator< const T > const_iterator
Custom constant iterator over a histogram.
Definition: Histogram.h:540
iterator begin()
Return iterator at first bin of histogram.
Definition: Histogram.h:549
static Histogram< T > * BuildHistogram(const Json::Value &json, const std::string &path)
Set up the histogram.
Definition: Histogram.h:156
reference operator*()
Dereference operator.
Definition: Histogram.h:303
Histogram(std::vector< int > numPoints, std::vector< double > lower, std::vector< double > upper, std::vector< bool > isPeriodic)
Constructor.
Definition: Histogram.h:116
const self_type operator-(std::vector< int > shift)
Subtraction iterator.
Definition: Histogram.h:445
std::vector< double > coordinates() const
Access coordinates.
Definition: Histogram.h:513
static Histogram< T > * BuildHistogram(const Json::Value &json)
Set up the histogram.
Definition: Histogram.h:141
std::bidirectional_iterator_tag iterator_category
HistIterator is a bidirectional iterator.
Definition: Histogram.h:274
std::vector< T >::const_iterator begin() const
Return const iterator at first bin of histogram.
Definition: Histogram.h:593
bool operator!=(const self_type &rhs) const
Non-equality operator.
Definition: Histogram.h:467
virtual void Validate(const Value &json, const std::string &path) override
Validate JSON value.
std::vector< int > & indices()
Access indices.
Definition: Histogram.h:479
Base class for Grids.
Definition: GridBase.h:38