BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
PointwiseAxis.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Base/Axis/PointwiseAxis.cpp
6 //! @brief Implements class PointwiseAxis.
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 <algorithm>
18 #include <iomanip>
19 #include <stdexcept>
20 
21 const size_t min_axis_size = 2;
22 
24 
26 {
27  return new PointwiseAxis(axisName(), m_coordinates);
28 }
29 
30 Bin1D PointwiseAxis::bin(size_t index) const
31 {
32  checkIndex(index);
33  return Bin1D(minary(index), maxary(index));
34 }
35 
36 double PointwiseAxis::min() const
37 {
38  return minary(0);
39 }
40 
41 double PointwiseAxis::max() const
42 {
43  return maxary(m_coordinates.size() - 1);
44 }
45 
46 double PointwiseAxis::binCenter(size_t index) const
47 {
48  checkIndex(index);
49  return m_coordinates[index];
50 }
51 
52 size_t PointwiseAxis::findClosestIndex(double value) const
53 {
54  if (value <= m_coordinates.front())
55  return 0;
56  if (value >= m_coordinates.back())
57  return m_coordinates.size() - 1;
58 
59  const auto begin = m_coordinates.begin();
60  auto result = std::lower_bound(begin, m_coordinates.end(), value);
61  auto index = static_cast<size_t>(std::distance(begin, result));
62  return value < minary(index) ? index - 1 : index;
63 }
64 
65 std::vector<double> PointwiseAxis::binBoundaries() const
66 {
67  std::vector<double> result;
68  const size_t v_size = m_coordinates.size();
69  result.reserve(v_size + 1);
70  for (size_t i = 0; i < v_size; ++i)
71  result.push_back(minary(i));
72  result.push_back(maxary(v_size - 1));
73  return result;
74 }
75 
76 void PointwiseAxis::clip(double lower, double upper)
77 {
78  if (lower >= upper)
79  throw std::runtime_error(
80  "PointwiseAxis::clip() -> Error. 'lower' should be smaller than 'upper'");
81 
82  using diff_t = std::vector<double>::iterator::difference_type;
83  const auto begin = m_coordinates.begin() + static_cast<diff_t>(findClosestIndex(lower));
84  const auto end = m_coordinates.begin() + static_cast<diff_t>(findClosestIndex(upper)) + 1;
85 
86  m_coordinates = std::vector<double>(begin, end);
87  sanityCheck();
88 }
89 
90 void PointwiseAxis::print(std::ostream& ostr) const
91 {
92  auto precision = std::setprecision(std::numeric_limits<double>::digits10 + 2);
93  ostr << "PointwiseAxis(\"" << axisName() << "\", "
94  << ", [";
95  for (size_t i = 0, fin = m_coordinates.size() - 1; i < fin; ++i)
96  ostr << precision << m_coordinates[i] << ",";
97  ostr << precision << m_coordinates.back() << "])";
98 }
99 
100 bool PointwiseAxis::equals(const IAxis& other) const
101 {
102  if (!IAxis::equals(other))
103  return false;
104  if (const auto* otherAxis = dynamic_cast<const PointwiseAxis*>(&other))
105  return m_coordinates == otherAxis->binCenters();
106  return false;
107 }
108 
109 double PointwiseAxis::minary(size_t index) const
110 {
111  if (index == 0)
112  return m_coordinates.front();
113  return 0.5 * (m_coordinates[index] + m_coordinates[index - 1]);
114 }
115 
116 double PointwiseAxis::maxary(size_t index) const
117 {
118  if (index + 1 == m_coordinates.size())
119  return m_coordinates.back();
120  return 0.5 * (m_coordinates[index] + m_coordinates[index + 1]);
121 }
122 
123 void PointwiseAxis::checkIndex(size_t index) const
124 {
125  if (m_coordinates.size() > index)
126  return;
127  std::string message = "Error in PointwiseAxis::binCenter: passed index ";
128  message += std::to_string(index) + " exceeds the size ";
129  message += std::to_string(m_coordinates.size()) + " of the axis";
130  throw std::runtime_error(message);
131 }
132 
134 {
135  if (m_coordinates.size() < min_axis_size)
136  throw std::runtime_error(
137  "Error in PointwiseAxis::PointwiseAxis: the size of passed coordinate array is "
138  "less than minimum acceptable value");
139 
140  const auto begin = m_coordinates.begin();
141  const auto end = m_coordinates.end();
142 
143  if (!std::is_sorted(begin, end))
144  throw std::runtime_error("Error in PointwiseAxis::PointwiseAxis: passed coordinates are "
145  "not sorted in ascending order");
146 
147  if (std::adjacent_find(begin, end) != end)
148  throw std::runtime_error("Error in PointwiseAxis::PointwiseAxis: passed coordinate vector "
149  "contains repeating values");
150 }
Defines structs Bin1D, Bin1DCVector.
const size_t min_axis_size
Defines class PointwiseAxis.
Definition: Bin.h:20
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 containing arbitrary (non-equidistant) coordinate values. Lower boundary of the first bin and up...
Definition: PointwiseAxis.h:33
~PointwiseAxis() override
PointwiseAxis(String &&name, Vector &&coordinate_values)
Definition: PointwiseAxis.h:36
PointwiseAxis * clone() const override
clone function
double min() const override
Returns value of first on-axis point.
double binCenter(size_t index) const override
Returns the coordinate corresponding to the given index. For this type of axis ("pointwise") this equ...
Bin1D bin(size_t index) const override
retrieve a 1d bin for the given index
void checkIndex(size_t index) const
std::vector< double > m_coordinates
Definition: PointwiseAxis.h:86
size_t findClosestIndex(double value) const override
find index of the coordinate closest to the given value
std::vector< double > binBoundaries() const override
void clip(double lower, double upper) override
Clips this axis to the given values.
double maxary(size_t index) const
double minary(size_t index) const
bool equals(const IAxis &other) const override
void print(std::ostream &ostr) const override
void sanityCheck() const
double max() const override
Returns value of last on-axis point.