| OpenMS 2.5.0

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-2020.
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>
74 class LinearInterpolation
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
86 typedef value_type ValueType;
87 typedef key_type KeyType;
88 typedef container_type ContainerType;
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
109 LinearInterpolation(LinearInterpolation const & arg) :
110 scale_(arg.scale_),
111 offset_(arg.offset_),
112 inside_(arg.inside_),
113 outside_(arg.outside_),
114 data_(arg.data_)
115 {}
116
118 LinearInterpolation & operator=(LinearInterpolation const & arg)
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() {}
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
313 ContainerType & getData()
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
349 KeyType key2index(KeyType pos) const
350 {
351 if (scale_)
352 {
353 pos -= offset_;
354 pos /= scale_;
355 return pos;
356 }
357 else
358 {
359 return 0;
360 }
361 }
362
364 KeyType index2key(KeyType pos) const
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
447 KeyType const & getInsideReferencePoint() const
448 {
449 return inside_;
450 }
451
453 KeyType const & getOutsideReferencePoint() const
454 {
455 return outside_;
456 }
457
459 KeyType supportMin() const
460 {
461 return index2key(KeyType(empty() ? 0 : -1));
462 }
463
465 KeyType supportMax() const
466 {
467 return index2key(KeyType(data_.size()));
468 }
469
471
472 protected:
473
474 KeyType scale_;
475 KeyType offset_;
476 KeyType inside_;
477 KeyType outside_;
478
479 ContainerType data_;
480
481 };
482
483 } // namespace Math
484
485 } // namespace OpenMS
486
OpenMS::SignedSize
ptrdiff_t SignedSize
Signed Size type e.g. used as pointer difference.
Definition: Types.h:134
OpenMS::Math::LinearInterpolation::KeyType
key_type KeyType
Definition: LinearInterpolation.h:87
OpenMS::Math::LinearInterpolation::getOffset
KeyType const & getOffset() const
Accessor. "Offset" is the point (in "outside" units) which corresponds to "Data[0]".
Definition: LinearInterpolation.h:388
OpenMS::Math::LinearInterpolation::LinearInterpolation
LinearInterpolation(LinearInterpolation const &arg)
Copy constructor.
Definition: LinearInterpolation.h:109
OpenMS::Math::LinearInterpolation::ContainerType
container_type ContainerType
Definition: LinearInterpolation.h:88
OpenMS::Math::LinearInterpolation::scale_
KeyType scale_
Definition: LinearInterpolation.h:474
OpenMS::Math::LinearInterpolation::inside_
KeyType inside_
Definition: LinearInterpolation.h:476
OpenMS::Math::LinearInterpolation::operator=
LinearInterpolation & operator=(LinearInterpolation const &arg)
Assignment operator.
Definition: LinearInterpolation.h:118
OpenMS::Math::LinearInterpolation::setOffset
void setOffset(KeyType const &offset)
Accessor. "Offset" is the point (in "outside" units) which corresponds to "Data[0]".
Definition: LinearInterpolation.h:399
OpenMS::Math::LinearInterpolation
Provides access to linearly interpolated values (and derivatives) from discrete data points...
Definition: LinearInterpolation.h:74
OpenMS::Math::LinearInterpolation::outside_
KeyType outside_
Definition: LinearInterpolation.h:477
OpenMS::Math::LinearInterpolation::value
ValueType value(KeyType arg_pos) const
Returns the interpolated value.
Definition: LinearInterpolation.h:141
Types.h
OpenMS::Math::LinearInterpolation::supportMin
KeyType supportMin() const
Lower boundary of the support, in "outside" coordinates.
Definition: LinearInterpolation.h:459
OpenMS::Math::LinearInterpolation::setMapping
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
OpenMS::Math::LinearInterpolation::setScale
void setScale(KeyType const &scale)
Accessor. "Scale" is the difference (in "outside" units) between consecutive entries in "Data"...
Definition: LinearInterpolation.h:382
OpenMS::Math::LinearInterpolation::ValueType
value_type ValueType
Definition: LinearInterpolation.h:86
OpenMS::Math::LinearInterpolation::getScale
KeyType const & getScale() const
Accessor. "Scale" is the difference (in "outside" units) between consecutive entries in "Data"...
Definition: LinearInterpolation.h:372
OpenMS
Main OpenMS namespace.
Definition: FeatureDeconvolution.h:46
OpenMS::Math::LinearInterpolation::key2index
KeyType key2index(KeyType pos) const
The transformation from "outside" to "inside" coordinates.
Definition: LinearInterpolation.h:349
OpenMS::Math::LinearInterpolation::addValue
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
Math
OpenMS::Math::LinearInterpolation::empty
bool empty() const
Returns true if getData() is empty.
Definition: LinearInterpolation.h:336
OpenMS::Math::LinearInterpolation::key_type
Key key_type
Definition: LinearInterpolation.h:83
OpenMS::Math::LinearInterpolation::getData
ContainerType const & getData() const
Returns the internal random access container from which interpolated values are being sampled...
Definition: LinearInterpolation.h:319
OpenMS::Math::LinearInterpolation::data_
ContainerType data_
Definition: LinearInterpolation.h:479
OpenMS::Math::LinearInterpolation::setMapping
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
OpenMS::Math::LinearInterpolation::getData
ContainerType & getData()
Returns the internal random access container from which interpolated values are being sampled...
Definition: LinearInterpolation.h:313
OpenMS::Math::LinearInterpolation::container_type
std::vector< value_type > container_type
Definition: LinearInterpolation.h:84
double
OpenMS::Math::LinearInterpolation::supportMax
KeyType supportMax() const
Upper boundary of the support, in "outside" coordinates.
Definition: LinearInterpolation.h:465
OpenMS::Math::LinearInterpolation::getOutsideReferencePoint
KeyType const & getOutsideReferencePoint() const
Accessor. See setMapping().
Definition: LinearInterpolation.h:453
OpenMS::Math::LinearInterpolation::index2key
KeyType index2key(KeyType pos) const
The transformation from "inside" to "outside" coordinates.
Definition: LinearInterpolation.h:364
int
Value
OpenMS::Math::LinearInterpolation::offset_
KeyType offset_
Definition: LinearInterpolation.h:475
OpenMS::Math::LinearInterpolation::~LinearInterpolation
~LinearInterpolation()
Destructor.
Definition: LinearInterpolation.h:133
OpenMS::Math::LinearInterpolation::LinearInterpolation
LinearInterpolation(KeyType scale=1., KeyType offset=0.)
Constructors and destructor.
Definition: LinearInterpolation.h:100
OpenMS::Math::LinearInterpolation::value_type
Value value_type
Definition: LinearInterpolation.h:81
OpenMS::Math::LinearInterpolation::setData
void setData(SourceContainer const &data)
Assigns data to the internal random access container from which interpolated values are being sampled...
Definition: LinearInterpolation.h:330
OpenMS::Math::LinearInterpolation::derivative
ValueType derivative(KeyType arg_pos) const
Returns the interpolated derivative.
Definition: LinearInterpolation.h:244
OpenMS::Math::LinearInterpolation::getInsideReferencePoint
KeyType const & getInsideReferencePoint() const
Accessor. See setMapping().
Definition: LinearInterpolation.h:447