BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
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/Utils/Algorithms.h"
17 #include <algorithm>
18 #include <iomanip>
19 
20 VariableBinAxis::VariableBinAxis(const std::string& name, size_t nbins,
21  const std::vector<double>& bin_boundaries)
22  : IAxis(name), m_nbins(nbins)
23 {
24  if (m_nbins != bin_boundaries.size() - 1)
25  throw std::runtime_error("VariableBinAxis::VariableBinAxis() -> Error! "
26  "The size of bin_boundaries should be of size [nbins+1].");
27 
28  setBinBoundaries(bin_boundaries);
29 }
30 
31 VariableBinAxis::VariableBinAxis(const std::string& name, size_t nbins)
32  : IAxis(name), m_nbins(nbins)
33 {
34 }
35 
37 {
39  return result;
40 }
41 
42 double VariableBinAxis::operator[](size_t index) const
43 {
44  return bin(index).center();
45 }
46 
47 Bin1D VariableBinAxis::bin(size_t index) const
48 {
49  if (index >= m_nbins)
50  throw std::runtime_error("VariableBinAxis::bin() -> Error. Wrong index.");
51 
52  Bin1D result(m_bin_boundaries[index], m_bin_boundaries[index + 1]);
53  return result;
54 }
55 
57 {
58  return m_bin_boundaries.front();
59 }
60 
62 {
63  return m_bin_boundaries.back();
64 }
65 
66 double VariableBinAxis::binCenter(size_t index) const
67 {
68  return bin(index).center();
69 }
70 
71 size_t VariableBinAxis::findClosestIndex(double value) const
72 {
73  if (m_bin_boundaries.size() < 2)
74  throw std::runtime_error("VariableBinAxis::findClosestIndex() -> Error! "
75  "VariableBinAxis not correctly initialized");
76  if (value < lowerBound()) {
77  return 0;
78  } else if (value >= upperBound()) {
79  return m_nbins - 1;
80  }
81 
82  std::vector<double>::const_iterator top_limit =
83  std::lower_bound(m_bin_boundaries.begin(), m_bin_boundaries.end(), value);
84  if (*top_limit != value)
85  --top_limit;
86  size_t nbin = top_limit - m_bin_boundaries.begin();
87  return nbin;
88 }
89 
90 std::vector<double> VariableBinAxis::binCenters() const
91 {
92  std::vector<double> result;
93  result.resize(size(), 0.0);
94  for (size_t i = 0; i < size(); ++i) {
95  result[i] = bin(i).center();
96  }
97  return result;
98 }
99 
100 VariableBinAxis* VariableBinAxis::createClippedAxis(double left, double right) const
101 {
102 
103  if (left >= right)
104  throw std::runtime_error("VariableBinAxis::createClippedAxis() -> Error. "
105  "'left'' should be smaller than 'right'");
106 
107  if (left < lowerBound())
108  left = bin(0).center();
109  if (right >= upperBound())
110  right = bin(size() - 1).center();
111 
112  size_t nbin1 = findClosestIndex(left);
113  size_t nbin2 = findClosestIndex(right);
114 
115  size_t new_nbins = nbin2 - nbin1 + 1;
116  std::vector<double> new_boundaries;
117  for (size_t i = 0; i < new_nbins + 1; ++i) {
118  new_boundaries.push_back(m_bin_boundaries[nbin1 + i]);
119  }
120 
121  return new VariableBinAxis(getName(), new_nbins, new_boundaries);
122 }
123 
124 void VariableBinAxis::print(std::ostream& ostr) const
125 {
126  ostr << "VariableBinAxis(\"" << getName() << "\", " << size() << ", [";
127  for (size_t i = 0; i < m_bin_boundaries.size(); ++i) {
128  ostr << std::setprecision(std::numeric_limits<double>::digits10 + 2) << m_bin_boundaries[i];
129  if (i != m_bin_boundaries.size() - 1)
130  ostr << ", ";
131  }
132  ostr << "])";
133 }
134 
135 bool VariableBinAxis::equals(const IAxis& other) const
136 {
137  if (!IAxis::equals(other))
138  return false;
139  if (const VariableBinAxis* p_other_cast = dynamic_cast<const VariableBinAxis*>(&other)) {
140  if (size() != p_other_cast->size())
141  return false;
142  for (size_t i = 0; i < m_bin_boundaries.size(); ++i) {
143  if (!algo::almostEqual(m_bin_boundaries[i], p_other_cast->m_bin_boundaries[i])) {
144  return false;
145  }
146  }
147  return true;
148  }
149  return false;
150 }
151 
152 void VariableBinAxis::setBinBoundaries(const std::vector<double>& bin_boundaries)
153 {
154  // checking that values are sorted
155  std::vector<double> vec_sorted = bin_boundaries;
156  std::sort(vec_sorted.begin(), vec_sorted.end());
157  for (size_t i = 0; i < bin_boundaries.size(); ++i) {
158  if (vec_sorted[i] != bin_boundaries[i])
159  throw std::runtime_error("VariableBinAxis::VariableBinAxis() -> Error. "
160  "Array with bin edges is not sorted.");
161  }
162 
163  std::vector<double> vec = bin_boundaries;
164  vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
165 
166  if (vec.size() != bin_boundaries.size())
167  throw std::runtime_error("VariableBinAxis::VariableBinAxis() -> Error. "
168  "Array with bin edges contains repeating values.");
169 
170  m_bin_boundaries = bin_boundaries;
171 }
Defines and implements namespace algo with some algorithms.
Defines class VariableBinAxis.
Interface for one-dimensional axes.
Definition: IAxis.h:25
virtual bool equals(const IAxis &other) const
Definition: IAxis.cpp:17
std::string getName() const
retrieve the label of the axis
Definition: IAxis.h:40
Axis with variable bin size.
double upperBound() const
Returns value of last point of axis.
size_t size() const
retrieve the number of bins
void setBinBoundaries(const std::vector< double > &bin_boundaries)
double operator[](size_t index) const
indexed accessor retrieves a sample
double binCenter(size_t index) const
virtual bool equals(const IAxis &other) const
VariableBinAxis(const std::string &name, size_t nbins, const std::vector< double > &bin_boundaries)
VariableBinAxis constructor.
std::vector< double > m_bin_boundaries
vector containing the bin limits
Bin1D bin(size_t index) const
retrieve a 1d bin for the given index
double lowerBound() const
Returns value of first point of axis.
virtual VariableBinAxis * createClippedAxis(double left, double right) const
Creates a new clipped axis.
size_t findClosestIndex(double value) const
find bin index which is best match for given value
std::vector< double > binCenters() const
virtual void print(std::ostream &ostr) const
VariableBinAxis * clone() const
clone function
QString const & name(EShape k)
Definition: particles.cpp:21
bool almostEqual(double a, double b)
Returns true if two doubles agree within machine epsilon.
Definition: Algorithms.h:34
Definition: Bin.h:20
double center() const
Definition: Bin.h:25