BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
VariableBinAxis.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Base/Axis/VariableBinAxis.cpp
6 //! @brief Implements VariableBinAxis class.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
16 #include "Base/Axis/Bin.h"
17 #include "Base/Util/Algorithms.h"
18 #include <algorithm>
19 #include <iomanip>
20 
21 VariableBinAxis::VariableBinAxis(const std::string& name, const std::vector<double>& bin_boundaries)
22  : IAxis(name)
23  , m_nbins(bin_boundaries.size() - 1)
24 {
25  setBinBoundaries(bin_boundaries);
26 }
27 
28 VariableBinAxis::VariableBinAxis(const std::string& name, size_t nbins)
29  : IAxis(name)
30  , m_nbins(nbins)
31 {
32 }
33 
35 {
36  auto* result = new VariableBinAxis(axisName(), m_bin_boundaries);
37  return result;
38 }
39 
40 double VariableBinAxis::operator[](size_t index) const
41 {
42  return bin(index).center();
43 }
44 
45 Bin1D VariableBinAxis::bin(size_t index) const
46 {
47  if (index >= m_nbins)
48  throw std::runtime_error("VariableBinAxis::bin() -> Error. Wrong index.");
49 
50  Bin1D result(m_bin_boundaries[index], m_bin_boundaries[index + 1]);
51  return result;
52 }
53 
54 double VariableBinAxis::min() const
55 {
56  return m_bin_boundaries.front();
57 }
58 
59 double VariableBinAxis::max() const
60 {
61  return m_bin_boundaries.back();
62 }
63 
64 double VariableBinAxis::binCenter(size_t index) const
65 {
66  return bin(index).center();
67 }
68 
69 size_t VariableBinAxis::findClosestIndex(double value) const
70 {
71  if (m_bin_boundaries.size() < 2)
72  throw std::runtime_error("VariableBinAxis::findClosestIndex() -> Error! "
73  "VariableBinAxis not correctly initialized");
74  if (value < min())
75  return 0;
76  if (value >= max())
77  return m_nbins - 1;
78 
79  auto top_limit = std::lower_bound(m_bin_boundaries.begin(), m_bin_boundaries.end(), value);
80  if (*top_limit != value)
81  --top_limit;
82  size_t nbin = top_limit - m_bin_boundaries.begin();
83  return nbin;
84 }
85 
86 std::vector<double> VariableBinAxis::binCenters() const
87 {
88  std::vector<double> result;
89  result.resize(size(), 0.0);
90  for (size_t i = 0; i < size(); ++i)
91  result[i] = bin(i).center();
92  return result;
93 }
94 
95 void VariableBinAxis::clip(double lower, double upper)
96 {
97  if (lower >= upper)
98  throw std::runtime_error("VariableBinAxis::clip() -> Error. "
99  "'lower' should be smaller than 'upper'");
100 
101  if (lower < min())
102  lower = bin(0).center();
103  if (upper >= max())
104  upper = bin(size() - 1).center();
105 
106  const size_t nbin1 = findClosestIndex(lower);
107  const size_t nbin2 = findClosestIndex(upper);
108  const size_t new_nbins = nbin2 - nbin1 + 1;
109 
110  std::vector<double> new_boundaries;
111  for (size_t i = 0; i < new_nbins + 1; ++i)
112  new_boundaries.push_back(m_bin_boundaries[nbin1 + i]);
113 
114  m_nbins = new_nbins;
115  setBinBoundaries(new_boundaries);
116 }
117 
118 void VariableBinAxis::print(std::ostream& ostr) const
119 {
120  ostr << "VariableBinAxis(\"" << axisName() << "\", " << size() << ", [";
121  for (size_t i = 0; i < m_bin_boundaries.size(); ++i) {
122  ostr << std::setprecision(std::numeric_limits<double>::digits10 + 2) << m_bin_boundaries[i];
123  if (i != m_bin_boundaries.size() - 1)
124  ostr << ", ";
125  }
126  ostr << "])";
127 }
128 
129 bool VariableBinAxis::equals(const IAxis& other) const
130 {
131  if (!IAxis::equals(other))
132  return false;
133  if (const auto* p_other_cast = dynamic_cast<const VariableBinAxis*>(&other)) {
134  if (size() != p_other_cast->size())
135  return false;
136  for (size_t i = 0; i < m_bin_boundaries.size(); ++i) {
138  p_other_cast->m_bin_boundaries[i]))
139  return false;
140  }
141  return true;
142  }
143  return false;
144 }
145 
146 void VariableBinAxis::setBinBoundaries(const std::vector<double>& bin_boundaries)
147 {
148  // checking that values are sorted
149  std::vector<double> vec_sorted = bin_boundaries;
150  std::sort(vec_sorted.begin(), vec_sorted.end());
151  for (size_t i = 0; i < bin_boundaries.size(); ++i) {
152  if (vec_sorted[i] != bin_boundaries[i])
153  throw std::runtime_error("VariableBinAxis::setBinBoundaries() -> Error. "
154  "Array with bin edges is not sorted.");
155  }
156 
157  std::vector<double> vec = bin_boundaries;
158  vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
159 
160  if (vec.size() != bin_boundaries.size())
161  throw std::runtime_error("VariableBinAxis::setBinBoundaries() -> Error. "
162  "Array with bin edges contains repeating values.");
163 
164  m_bin_boundaries = bin_boundaries;
165 }
Defines and implements namespace BaseUtils::algo with some algorithms.
Defines structs Bin1D, Bin1DCVector.
Defines class VariableBinAxis.
Definition: Bin.h:20
double center() const
Definition: Bin.h:30
Abstract base class for one-dimensional axes.
Definition: IAxis.h:27
virtual bool equals(const IAxis &other) const
Definition: IAxis.cpp:20
std::string axisName() const
Returns the label of the axis.
Definition: IAxis.h:61
Axis with variable bin size.
double max() const override
Returns value of last point of axis.
bool equals(const IAxis &other) const override
void clip(double lower, double upper) override
Clips this axis to the given values.
std::vector< double > binCenters() const override
void setBinBoundaries(const std::vector< double > &bin_boundaries)
double binCenter(size_t index) const override
double operator[](size_t index) const override
indexed accessor retrieves a sample
Bin1D bin(size_t index) const override
retrieve a 1d bin for the given index
size_t size() const override
Returns the number of bins.
std::vector< double > m_bin_boundaries
vector containing the bin limits
VariableBinAxis * clone() const override
size_t findClosestIndex(double value) const override
find bin index which is best match for given value
double min() const override
Returns value of first point of axis.
VariableBinAxis(const std::string &name, const std::vector< double > &bin_boundaries)
VariableBinAxis constructor.
void print(std::ostream &ostr) const override
bool almostEqual(double a, double b)
Returns true if two doubles agree within machine epsilon.
Definition: Algorithms.h:33