OpenMS
LinearInterpolation.h
Go to the documentation of this file.
1 // Copyright (c) 2002-2023, The OpenMS Team -- EKU Tuebingen, ETH Zurich, and FU Berlin
2 // SPDX-License-Identifier: BSD-3-Clause
3 //
4 // --------------------------------------------------------------------------
5 // $Maintainer: Timo Sachsenberg $
6 // $Authors: $
7 // --------------------------------------------------------------------------
8 
9 #pragma once
10 
11 #include <OpenMS/CONCEPT/Types.h>
12 
13 #include <cmath> // for modf() (which is an overloaded function in C++)
14 #include <vector>
15 
16 namespace OpenMS
17 {
18 
19  namespace Math
20  {
21 
47  template <typename Key = double, typename Value = Key>
49  {
50 
51 public:
52 
54 
55  typedef Value value_type;
56 
57  typedef Key key_type;
58  typedef std::vector<value_type> container_type;
59 
61  typedef key_type KeyType;
64 
65 public:
66 
74  LinearInterpolation(KeyType scale = 1., KeyType offset = 0.) :
75  scale_(scale),
76  offset_(offset),
77  inside_(),
78  outside_(),
79  data_()
80  {}
81 
84  scale_(arg.scale_),
85  offset_(arg.offset_),
86  inside_(arg.inside_),
87  outside_(arg.outside_),
88  data_(arg.data_)
89  {}
90 
93  {
94  if (&arg == this)
95  return *this;
96 
97  scale_ = arg.scale_;
98  offset_ = arg.offset_;
99  inside_ = arg.inside_;
100  outside_ = arg.outside_;
101  data_ = arg.data_;
102 
103  return *this;
104  }
105 
107  ~LinearInterpolation() = default;
108 
109  // ----------------------------------------------------------------------
110 
112 
113 
115  ValueType value(KeyType arg_pos) const
116  {
117 
118  typedef typename container_type::difference_type DiffType;
119 
120  // apply the key transformation
121  KeyType left_key;
122  KeyType pos = key2index(arg_pos);
123  KeyType frac = std::modf(pos, &left_key);
124  DiffType const left = DiffType(left_key);
125 
126  // At left margin?
127  if (pos < 0)
128  {
129  if (left /* <= -1 */)
130  {
131  return 0;
132  }
133  else // left == 0
134  {
135  return data_[0] * (1 + frac);
136  }
137  }
138  else // pos >= 0
139  {
140  // At right margin?
141  DiffType const back = data_.size() - 1;
142  if (left >= back)
143  {
144  if (left != back)
145  {
146  return 0;
147  }
148  else
149  {
150  return data_[left] * (1 - frac);
151  }
152  }
153  else
154  {
155  // In between!
156  return data_[left + 1] * frac + data_[left] * (1 - frac);
157  }
158  }
159  }
160 
164  void addValue(KeyType arg_pos, ValueType arg_value)
165  {
166 
167  typedef typename container_type::difference_type DiffType;
168 
169  // apply the key transformation
170  KeyType left_key;
171  KeyType const pos = key2index(arg_pos);
172  KeyType const frac = std::modf(pos, &left_key);
173  DiffType const left = DiffType(left_key);
174 
175  // At left margin?
176  if (pos < 0)
177  {
178  if (left /* <= -1 */)
179  {
180  return;
181  }
182  else // left == 0
183  {
184  data_[0] += (1 + frac) * arg_value;
185  return;
186  }
187  }
188  else // pos >= 0
189  {
190  // At right margin?
191  DiffType const back = data_.size() - 1;
192  if (left >= back)
193  {
194  if (left != back)
195  {
196  return;
197  }
198  else // left == back
199  {
200  data_[left] += (1 - frac) * arg_value;
201  return;
202  }
203  }
204  else
205  {
206  // In between!
207  data_[left + 1] += frac * arg_value;
208  data_[left] += (1 - frac) * arg_value;
209  return;
210  }
211  }
212  }
213 
218  ValueType derivative(KeyType arg_pos) const
219  {
220 
221  // apply the key transformation
222  KeyType const pos = key2index(arg_pos);
223 
224  SignedSize const size_ = data_.size();
225  SignedSize const left = int(pos + 0.5); // rounds towards zero
226 
227  if (left < 0) // quite small
228  {
229  return 0;
230  }
231  else
232  {
233  if (left == 0) // at the border
234  {
235  if (pos >= -0.5) // that is: -0.5 <= pos < +0.5
236  {
237  return (data_[1] - data_[0]) * (pos + 0.5) + (data_[0]) * (0.5 - pos);
238  }
239  else // that is: -1.5 <= pos < -0.5
240  {
241  return (data_[0]) * (pos + 1.5);
242  }
243  }
244  }
245  // "else" case: to the right of the left margin
246 
247 
248  KeyType factor = KeyType(left) - pos + KeyType(0.5);
249 
250  if (left > size_) // quite large
251  {
252  return 0;
253  }
254  else
255  {
256  if (left < size_ - 1) // to the left of the right margin
257  {
258  // weighted average of derivatives for adjacent intervals
259  return (data_[left] - data_[left - 1]) * factor + (data_[left + 1] - data_[left]) * (1. - factor);
260  }
261  else // somewhat at the border
262  {
263  // at the border, first case
264  if (left == size_ - 1)
265  {
266  return (data_[left] - data_[left - 1]) * factor + (-data_[left]) * (1. - factor);
267  }
268  }
269  }
270  // else // that is: left == size_
271 
272  // We pull the last remaining case out of the "if" tree to avoid a
273  // compiler warning ...
274 
275  // at the border, second case
276  return (-data_[left - 1]) * factor;
277  }
278 
280 
281  // ----------------------------------------------------------------------
282 
284 
285 
288  {
289  return data_;
290  }
291 
293  ContainerType const & getData() const
294  {
295  return data_;
296  }
297 
303  template <typename SourceContainer>
304  void setData(SourceContainer const & data)
305  {
306  data_ = data;
307  }
308 
310  bool empty() const
311  {
312  return data_.empty();
313  }
314 
316 
317  // ----------------------------------------------------------------------
318 
320 
321 
324  {
325  if (scale_)
326  {
327  pos -= offset_;
328  pos /= scale_;
329  return pos;
330  }
331  else
332  {
333  return 0;
334  }
335  }
336 
339  {
340  pos *= scale_;
341  pos += offset_;
342  return pos;
343  }
344 
346  KeyType const & getScale() const
347  {
348  return scale_;
349  }
350 
356  void setScale(KeyType const & scale)
357  {
358  scale_ = scale;
359  }
360 
362  KeyType const & getOffset() const
363  {
364  return offset_;
365  }
366 
373  void setOffset(KeyType const & offset)
374  {
375  offset_ = offset;
376  }
377 
391  void setMapping(KeyType const & scale, KeyType const & inside, KeyType const & outside)
392  {
393  scale_ = scale;
394  inside_ = inside;
395  outside_ = outside;
396  offset_ = outside - scale * inside;
397  }
398 
405  void setMapping(KeyType const & inside_low, KeyType const & outside_low,
406  KeyType const & inside_high, KeyType const & outside_high)
407  {
408  if (inside_high != inside_low)
409  {
410  setMapping((outside_high - outside_low) / (inside_high - inside_low),
411  inside_low, outside_low);
412  }
413  else
414  {
415  setMapping(0, inside_low, outside_low);
416  }
417  return;
418  }
419 
422  {
423  return inside_;
424  }
425 
428  {
429  return outside_;
430  }
431 
434  {
435  return index2key(KeyType(empty() ? 0 : -1));
436  }
437 
440  {
441  return index2key(KeyType(data_.size()));
442  }
443 
445 
446 protected:
447 
452 
454 
455  };
456 
457  } // namespace Math
458 
459 } // namespace OpenMS
460 
Provides access to linearly interpolated values (and derivatives) from discrete data points....
Definition: LinearInterpolation.h:49
ContainerType const & getData() const
Returns the internal random access container from which interpolated values are being sampled.
Definition: LinearInterpolation.h:293
Value value_type
Definition: LinearInterpolation.h:55
KeyType key2index(KeyType pos) const
The transformation from "outside" to "inside" coordinates.
Definition: LinearInterpolation.h:323
KeyType index2key(KeyType pos) const
The transformation from "inside" to "outside" coordinates.
Definition: LinearInterpolation.h:338
KeyType supportMax() const
Upper boundary of the support, in "outside" coordinates.
Definition: LinearInterpolation.h:439
Key key_type
Definition: LinearInterpolation.h:57
ContainerType data_
Definition: LinearInterpolation.h:453
ValueType derivative(KeyType arg_pos) const
Returns the interpolated derivative.
Definition: LinearInterpolation.h:218
container_type ContainerType
Definition: LinearInterpolation.h:62
void setData(SourceContainer const &data)
Assigns data to the internal random access container from which interpolated values are being sampled...
Definition: LinearInterpolation.h:304
KeyType outside_
Definition: LinearInterpolation.h:451
LinearInterpolation & operator=(LinearInterpolation const &arg)
Assignment operator.
Definition: LinearInterpolation.h:92
bool empty() const
Returns true if getData() is empty.
Definition: LinearInterpolation.h:310
KeyType const & getScale() const
Accessor. "Scale" is the difference (in "outside" units) between consecutive entries in "Data".
Definition: LinearInterpolation.h:346
value_type ValueType
Definition: LinearInterpolation.h:60
KeyType scale_
Definition: LinearInterpolation.h:448
void setScale(KeyType const &scale)
Accessor. "Scale" is the difference (in "outside" units) between consecutive entries in "Data".
Definition: LinearInterpolation.h:356
std::vector< value_type > container_type
Definition: LinearInterpolation.h:58
LinearInterpolation(KeyType scale=1., KeyType offset=0.)
Constructors and destructor.
Definition: LinearInterpolation.h:74
ContainerType & getData()
Returns the internal random access container from which interpolated values are being sampled.
Definition: LinearInterpolation.h:287
KeyType const & getOutsideReferencePoint() const
Accessor. See setMapping().
Definition: LinearInterpolation.h:427
key_type KeyType
Definition: LinearInterpolation.h:61
KeyType offset_
Definition: LinearInterpolation.h:449
LinearInterpolation(LinearInterpolation const &arg)
Copy constructor.
Definition: LinearInterpolation.h:83
KeyType const & getOffset() const
Accessor. "Offset" is the point (in "outside" units) which corresponds to "Data[0]".
Definition: LinearInterpolation.h:362
void setMapping(KeyType const &inside_low, KeyType const &outside_low, KeyType const &inside_high, KeyType const &outside_high)
Specifies the mapping from "outside" to "inside" coordinates by the following data:
Definition: LinearInterpolation.h:405
KeyType inside_
Definition: LinearInterpolation.h:450
void setOffset(KeyType const &offset)
Accessor. "Offset" is the point (in "outside" units) which corresponds to "Data[0]".
Definition: LinearInterpolation.h:373
void setMapping(KeyType const &scale, KeyType const &inside, KeyType const &outside)
Specifies the mapping from "outside" to "inside" coordinates by the following data:
Definition: LinearInterpolation.h:391
~LinearInterpolation()=default
Destructor.
void addValue(KeyType arg_pos, ValueType arg_value)
Performs linear resampling. The arg_value is split up and added to the data points around arg_pos.
Definition: LinearInterpolation.h:164
ValueType value(KeyType arg_pos) const
Returns the interpolated value.
Definition: LinearInterpolation.h:115
KeyType supportMin() const
Lower boundary of the support, in "outside" coordinates.
Definition: LinearInterpolation.h:433
KeyType const & getInsideReferencePoint() const
Accessor. See setMapping().
Definition: LinearInterpolation.h:421
ptrdiff_t SignedSize
Signed Size type e.g. used as pointer difference.
Definition: Types.h:108
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:22