Mantid
Loading...
Searching...
No Matches
Interpolation.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
11
12#include <algorithm>
13#include <iterator>
14#include <stdexcept>
15
16namespace Mantid::Kernel {
17namespace {
19Logger g_log("Interpolation");
20} // namespace
21
22/* Functor used in std::lower_bound to replicate the original behavior.
23 */
25 bool operator()(const DataXY &lhs, const DataXY &rhs) { return lhs.first <= rhs.first; }
26};
27
31 : m_method("linear"), m_xUnit(UnitFactory::Instance().create("TOF")),
32 m_yUnit(UnitFactory::Instance().create("TOF")) {}
33
38std::vector<DataXY>::const_iterator Interpolation::findIndexOfNextLargerValue(double key) const {
39 return std::lower_bound(m_data.begin(), m_data.end(), DataXY(key, 0), LessOrEqualFunctor());
40}
41
42std::vector<DataXY>::const_iterator Interpolation::cbegin() const { return m_data.cbegin(); }
43
44std::vector<DataXY>::const_iterator Interpolation::cend() const { return m_data.cend(); }
45
46void Interpolation::setXUnit(const std::string &unit) { m_xUnit = UnitFactory::Instance().create(unit); }
47
48void Interpolation::setYUnit(const std::string &unit) { m_yUnit = UnitFactory::Instance().create(unit); }
49
54double Interpolation::value(const double &at) const {
55 size_t N = m_data.size();
56
57 if (N == 0) {
58 g_log.error() << "Need at least one value for interpolation. Return "
59 "interpolation value zero.";
60 return 0.0;
61 }
62
63 if (N == 1) {
64 return m_data[0].second;
65 }
66
67 // check first if at is within the limits of interpolation interval
68
69 if (at < m_data[0].first) {
70 return m_data[0].second -
71 (m_data[0].first - at) * (m_data[1].second - m_data[0].second) / (m_data[1].first - m_data[0].first);
72 }
73
74 if (at > m_data[N - 1].first) {
75 return m_data[N - 1].second + (at - m_data[N - 1].first) * (m_data[N - 1].second - m_data[N - 2].second) /
76 (m_data[N - 1].first - m_data[N - 2].first);
77 }
78
79 try {
80 // otherwise
81 // General case. Find index of next largest value by std::lower_bound.
82 auto pos = findIndexOfNextLargerValue(at);
83
84 auto posBefore = std::prev(pos);
85 if (posBefore->first == at) {
86 return posBefore->second;
87 } else {
88 double interpolatedY = posBefore->second + (at - posBefore->first) * (pos->second - posBefore->second) /
89 (pos->first - posBefore->first);
90 return interpolatedY;
91 }
92 } catch (const std::range_error &) {
93 return 0.0;
94 }
95}
96
102void Interpolation::addPoint(const double &xx, const double &yy) {
103 size_t N = m_data.size();
104 std::vector<DataXY>::const_iterator it;
105
106 if (N == 0) {
107 DataXY newpair(xx, yy);
108 m_data.emplace_back(newpair);
109 return;
110 }
111
112 // check first if xx is within the limits of interpolation interval
113
114 if (xx < m_data[0].first) {
115 it = m_data.begin();
116 it = m_data.insert(it, DataXY(xx, yy));
117 return;
118 }
119
120 if (xx > m_data[N - 1].first) {
121 m_data.emplace_back(xx, yy);
122 return;
123 }
124
125 // otherwise
126
128
129 auto posBefore = std::prev(it);
130 if (posBefore->first != xx) {
131 m_data.insert(it, DataXY(xx, yy));
132 }
133}
134
139void Interpolation::printSelf(std::ostream &os) const {
140 os << m_method << " ; " << m_xUnit->unitID() << " ; " << m_yUnit->unitID();
141
142 for (unsigned int i = 0; i < m_data.size(); i++) {
143 os << " ; " << m_data[i].first << " " << m_data[i].second;
144 }
145}
146
151
158std::ostream &operator<<(std::ostream &os, const Interpolation &f) {
159 f.printSelf(os);
160 return os;
161}
162
169std::istream &operator>>(std::istream &in, Interpolation &f) {
170
172 std::string str;
173 getline(in, str);
174 tokenizer values(str, ";", tokenizer::TOK_TRIM);
175
176 f.setMethod(values[0]);
177 f.setXUnit(values[1]);
178 f.setYUnit(values[2]);
179 f.resetData(); // Reset data, in case the interpolation table is not empty
180
181 for (unsigned int i = 3; i < values.count(); i++) {
182 std::stringstream strstream(values[i]);
183 double x, y;
184 strstream >> x >> y;
185 f.addPoint(x, y);
186 }
187
188 return in;
189}
190
191} // namespace Mantid::Kernel
const std::vector< double > & rhs
BuilderMethod< ArgType > m_method
Provide interpolation over a series of points.
Definition: Interpolation.h:29
void setMethod(const std::string &method)
set interpolation method
Definition: Interpolation.h:60
std::vector< DataXY > m_data
internal storage of x and y values
Definition: Interpolation.h:32
void resetData()
Clear interpolation values.
std::vector< DataXY >::const_iterator cbegin() const
std::vector< DataXY >::const_iterator cend() const
std::string m_method
method used for doing the interpolation
Definition: Interpolation.h:35
void setXUnit(const std::string &unit)
set x-axis unit
double value(const double &at) const
get interpolated value at location at
std::vector< DataXY >::const_iterator findIndexOfNextLargerValue(double key) const
Get iterator of item that is next larger than the supplied x value.
void setYUnit(const std::string &unit)
set y-axis unit
void printSelf(std::ostream &os) const
Prints object to stream.
void addPoint(const double &xx, const double &yy)
add data point
Interpolation()
Constructor default to linear interpolation and x-unit set to TOF.
Unit_sptr m_yUnit
unit of y-axis
Definition: Interpolation.h:41
Unit_sptr m_xUnit
unit of x-axis
Definition: Interpolation.h:38
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
Manage the lifetime of a class intended to be a singleton.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
@ TOK_TRIM
remove leading and trailing whitespace from tokens
std::size_t count() const
Get the total number of tokens.
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
MANTID_KERNEL_DLL std::ostream & operator<<(std::ostream &, CPUTimer &)
Convenience function to provide for easier debug printing.
Definition: CPUTimer.cpp:86
MANTID_KERNEL_DLL std::istream & operator>>(std::istream &, Interpolation &)
Reads in parameter value.
std::pair< double, double > DataXY
Definition: Interpolation.h:22
bool operator()(const DataXY &lhs, const DataXY &rhs)