OpenMS
LinearInterpolation.h
Go to the documentation of this file.
1 // --------------------------------------------------------------------------
2 // OpenMS -- Open-Source Mass Spectrometry
3 // --------------------------------------------------------------------------
4 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
5 // ETH Zurich, and Freie Universitaet Berlin 2002-2023.
6 //
7 // This software is released under a three-clause BSD license:
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of any author or any participating institution
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
16 // For a full list of authors, refer to the file AUTHORS.
17 // --------------------------------------------------------------------------
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
22 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // --------------------------------------------------------------------------
31 // $Maintainer: Timo Sachsenberg $
32 // $Authors: $
33 // --------------------------------------------------------------------------
34 
35 #pragma once
36 
37 #include <OpenMS/CONCEPT/Types.h>
38 
39 #include <cmath> // for modf() (which is an overloaded function in C++)
40 #include <vector>
41 
42 namespace OpenMS
43 {
44 
45  namespace Math
46  {
47 
73  template <typename Key = double, typename Value = Key>
75  {
76 
77 public:
78 
80 
81  typedef Value value_type;
82 
83  typedef Key key_type;
84  typedef std::vector<value_type> container_type;
85 
87  typedef key_type KeyType;
90 
91 public:
92 
100  LinearInterpolation(KeyType scale = 1., KeyType offset = 0.) :
101  scale_(scale),
102  offset_(offset),
103  inside_(),
104  outside_(),
105  data_()
106  {}
107 
110  scale_(arg.scale_),
111  offset_(arg.offset_),
112  inside_(arg.inside_),
113  outside_(arg.outside_),
114  data_(arg.data_)
115  {}
116 
119  {
120  if (&arg == this)
121  return *this;
122 
123  scale_ = arg.scale_;
124  offset_ = arg.offset_;
125  inside_ = arg.inside_;
126  outside_ = arg.outside_;
127  data_ = arg.data_;
128 
129  return *this;
130  }
131 
133  ~LinearInterpolation() = default;
134 
135  // ----------------------------------------------------------------------
136 
138 
139 
141  ValueType value(KeyType arg_pos) const
142  {
143 
144  typedef typename container_type::difference_type DiffType;
145 
146  // apply the key transformation
147  KeyType left_key;
148  KeyType pos = key2index(arg_pos);
149  KeyType frac = std::modf(pos, &left_key);
150  DiffType const left = DiffType(left_key);
151 
152  // At left margin?
153  if (pos < 0)
154  {
155  if (left /* <= -1 */)
156  {
157  return 0;
158  }
159  else // left == 0
160  {
161  return data_[0] * (1 + frac);
162  }
163  }
164  else // pos >= 0
165  {
166  // At right margin?
167  DiffType const back = data_.size() - 1;
168  if (left >= back)
169  {
170  if (left != back)
171  {
172  return 0;
173  }
174  else
175  {
176  return data_[left] * (1 - frac);
177  }
178  }
179  else
180  {
181  // In between!
182  return data_[left + 1] * frac + data_[left] * (1 - frac);
183  }
184  }
185  }
186 
190  void addValue(KeyType arg_pos, ValueType arg_value)
191  {
192 
193  typedef typename container_type::difference_type DiffType;
194 
195  // apply the key transformation
196  KeyType left_key;
197  KeyType const pos = key2index(arg_pos);
198  KeyType const frac = std::modf(pos, &left_key);
199  DiffType const left = DiffType(left_key);
200 
201  // At left margin?
202  if (pos < 0)
203  {
204  if (left /* <= -1 */)
205  {
206  return;
207  }
208  else // left == 0
209  {
210  data_[0] += (1 + frac) * arg_value;
211  return;
212  }
213  }
214  else // pos >= 0
215  {
216  // At right margin?
217  DiffType const back = data_.size() - 1;
218  if (left >= back)
219  {
220  if (left != back)
221  {
222  return;
223  }
224  else // left == back
225  {
226  data_[left] += (1 - frac) * arg_value;
227  return;
228  }
229  }
230  else
231  {
232  // In between!
233  data_[left + 1] += frac * arg_value;
234  data_[left] += (1 - frac) * arg_value;
235  return;
236  }
237  }
238  }
239 
244  ValueType derivative(KeyType arg_pos) const
245  {
246 
247  // apply the key transformation
248  KeyType const pos = key2index(arg_pos);
249 
250  SignedSize const size_ = data_.size();
251  SignedSize const left = int(pos + 0.5); // rounds towards zero
252 
253  if (left < 0) // quite small
254  {
255  return 0;
256  }
257  else
258  {
259  if (left == 0) // at the border
260  {
261  if (pos >= -0.5) // that is: -0.5 <= pos < +0.5
262  {
263  return (data_[1] - data_[0]) * (pos + 0.5) + (data_[0]) * (0.5 - pos);
264  }
265  else // that is: -1.5 <= pos < -0.5
266  {
267  return (data_[0]) * (pos + 1.5);
268  }
269  }
270  }
271  // "else" case: to the right of the left margin
272 
273 
274  KeyType factor = KeyType(left) - pos + KeyType(0.5);
275 
276  if (left > size_) // quite large
277  {
278  return 0;
279  }
280  else
281  {
282  if (left < size_ - 1) // to the left of the right margin
283  {
284  // weighted average of derivatives for adjacent intervals
285  return (data_[left] - data_[left - 1]) * factor + (data_[left + 1] - data_[left]) * (1. - factor);
286  }
287  else // somewhat at the border
288  {
289  // at the border, first case
290  if (left == size_ - 1)
291  {
292  return (data_[left] - data_[left - 1]) * factor + (-data_[left]) * (1. - factor);
293  }
294  }
295  }
296  // else // that is: left == size_
297 
298  // We pull the last remaining case out of the "if" tree to avoid a
299  // compiler warning ...
300 
301  // at the border, second case
302  return (-data_[left - 1]) * factor;
303  }
304 
306 
307  // ----------------------------------------------------------------------
308 
310 
311 
314  {
315  return data_;
316  }
317 
319  ContainerType const & getData() const
320  {
321  return data_;
322  }
323 
329  template <typename SourceContainer>
330  void setData(SourceContainer const & data)
331  {
332  data_ = data;
333  }
334 
336  bool empty() const
337  {
338  return data_.empty();
339  }
340 
342 
343  // ----------------------------------------------------------------------
344 
346 
347 
350  {
351  if (scale_)
352  {
353  pos -= offset_;
354  pos /= scale_;
355  return pos;
356  }
357  else
358  {
359  return 0;
360  }
361  }
362 
365  {
366  pos *= scale_;
367  pos += offset_;
368  return pos;
369  }
370 
372  KeyType const & getScale() const
373  {
374  return scale_;
375  }
376 
382  void setScale(KeyType const & scale)
383  {
384  scale_ = scale;
385  }
386 
388  KeyType const & getOffset() const
389  {
390  return offset_;
391  }
392 
399  void setOffset(KeyType const & offset)
400  {
401  offset_ = offset;
402  }
403 
417  void setMapping(KeyType const & scale, KeyType const & inside, KeyType const & outside)
418  {
419  scale_ = scale;
420  inside_ = inside;
421  outside_ = outside;
422  offset_ = outside - scale * inside;
423  }
424 
431  void setMapping(KeyType const & inside_low, KeyType const & outside_low,
432  KeyType const & inside_high, KeyType const & outside_high)
433  {
434  if (inside_high != inside_low)
435  {
436  setMapping((outside_high - outside_low) / (inside_high - inside_low),
437  inside_low, outside_low);
438  }
439  else
440  {
441  setMapping(0, inside_low, outside_low);
442  }
443  return;
444  }
445 
448  {
449  return inside_;
450  }
451 
454  {
455  return outside_;
456  }
457 
460  {
461  return index2key(KeyType(empty() ? 0 : -1));
462  }
463 
466  {
467  return index2key(KeyType(data_.size()));
468  }
469 
471 
472 protected:
473 
478 
480 
481  };
482 
483  } // namespace Math
484 
485 } // namespace OpenMS
486 
Provides access to linearly interpolated values (and derivatives) from discrete data points....
Definition: LinearInterpolation.h:75
ContainerType const & getData() const
Returns the internal random access container from which interpolated values are being sampled.
Definition: LinearInterpolation.h:319
Value value_type
Definition: LinearInterpolation.h:81
KeyType key2index(KeyType pos) const
The transformation from "outside" to "inside" coordinates.
Definition: LinearInterpolation.h:349
KeyType index2key(KeyType pos) const
The transformation from "inside" to "outside" coordinates.
Definition: LinearInterpolation.h:364
KeyType supportMax() const
Upper boundary of the support, in "outside" coordinates.
Definition: LinearInterpolation.h:465
Key key_type
Definition: LinearInterpolation.h:83
ContainerType data_
Definition: LinearInterpolation.h:479
ValueType derivative(KeyType arg_pos) const
Returns the interpolated derivative.
Definition: LinearInterpolation.h:244
container_type ContainerType
Definition: LinearInterpolation.h:88
void setData(SourceContainer const &data)
Assigns data to the internal random access container from which interpolated values are being sampled...
Definition: LinearInterpolation.h:330
KeyType outside_
Definition: LinearInterpolation.h:477
LinearInterpolation & operator=(LinearInterpolation const &arg)
Assignment operator.
Definition: LinearInterpolation.h:118
bool empty() const
Returns true if getData() is empty.
Definition: LinearInterpolation.h:336
KeyType const & getScale() const
Accessor. "Scale" is the difference (in "outside" units) between consecutive entries in "Data".
Definition: LinearInterpolation.h:372
value_type ValueType
Definition: LinearInterpolation.h:86
KeyType scale_
Definition: LinearInterpolation.h:474
void setScale(KeyType const &scale)
Accessor. "Scale" is the difference (in "outside" units) between consecutive entries in "Data".
Definition: LinearInterpolation.h:382
std::vector< value_type > container_type
Definition: LinearInterpolation.h:84
LinearInterpolation(KeyType scale=1., KeyType offset=0.)
Constructors and destructor.
Definition: LinearInterpolation.h:100
ContainerType & getData()
Returns the internal random access container from which interpolated values are being sampled.
Definition: LinearInterpolation.h:313
KeyType const & getOutsideReferencePoint() const
Accessor. See setMapping().
Definition: LinearInterpolation.h:453
key_type KeyType
Definition: LinearInterpolation.h:87
KeyType offset_
Definition: LinearInterpolation.h:475
LinearInterpolation(LinearInterpolation const &arg)
Copy constructor.
Definition: LinearInterpolation.h:109
KeyType const & getOffset() const
Accessor. "Offset" is the point (in "outside" units) which corresponds to "Data[0]".
Definition: LinearInterpolation.h:388
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:431
KeyType inside_
Definition: LinearInterpolation.h:476
void setOffset(KeyType const &offset)
Accessor. "Offset" is the point (in "outside" units) which corresponds to "Data[0]".
Definition: LinearInterpolation.h:399
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:417
~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:190
ValueType value(KeyType arg_pos) const
Returns the interpolated value.
Definition: LinearInterpolation.h:141
KeyType supportMin() const
Lower boundary of the support, in "outside" coordinates.
Definition: LinearInterpolation.h:459
KeyType const & getInsideReferencePoint() const
Accessor. See setMapping().
Definition: LinearInterpolation.h:447
ptrdiff_t SignedSize
Signed Size type e.g. used as pointer difference.
Definition: Types.h:134
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:48