Home  · Classes  · Annotated Classes  · Modules  · Members  · Namespaces  · Related Pages

LinearInterpolation.h

Go to the documentation of this file.
00001 // --------------------------------------------------------------------------
00002 //                   OpenMS -- Open-Source Mass Spectrometry
00003 // --------------------------------------------------------------------------
00004 // Copyright The OpenMS Team -- Eberhard Karls University Tuebingen,
00005 // ETH Zurich, and Freie Universitaet Berlin 2002-2012.
00006 //
00007 // This software is released under a three-clause BSD license:
00008 //  * Redistributions of source code must retain the above copyright
00009 //    notice, this list of conditions and the following disclaimer.
00010 //  * Redistributions in binary form must reproduce the above copyright
00011 //    notice, this list of conditions and the following disclaimer in the
00012 //    documentation and/or other materials provided with the distribution.
00013 //  * Neither the name of any author or any participating institution
00014 //    may be used to endorse or promote products derived from this software
00015 //    without specific prior written permission.
00016 // For a full list of authors, refer to the file AUTHORS.
00017 // --------------------------------------------------------------------------
00018 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 // ARE DISCLAIMED. IN NO EVENT SHALL ANY OF THE AUTHORS OR THE CONTRIBUTING
00022 // INSTITUTIONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00024 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00025 // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00027 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028 // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 //
00030 // --------------------------------------------------------------------------
00031 // $Maintainer: Clemens Groepl $
00032 // $Authors: $
00033 // --------------------------------------------------------------------------
00034 
00035 #ifndef OPENMS_MATH_MISC_LINEARINTERPOLATION_H
00036 #define OPENMS_MATH_MISC_LINEARINTERPOLATION_H
00037 
00038 #include <OpenMS/CONCEPT/Types.h>
00039 
00040 #include <cmath> // for modf() (which is an overloaded function in C++)
00041 #include <vector>
00042 
00043 namespace OpenMS
00044 {
00045 
00046   namespace Math
00047   {
00048 
00074     template <typename Key = DoubleReal, typename Value = Key>
00075     class LinearInterpolation
00076     {
00077 
00078 public:
00079 
00081 
00082       typedef Value value_type;
00083 
00084       typedef Key key_type;
00085       typedef std::vector<value_type> container_type;
00086 
00087       typedef value_type      ValueType;
00088       typedef key_type        KeyType;
00089       typedef container_type  ContainerType;
00091 
00092 public:
00093 
00101       LinearInterpolation(KeyType scale = 1., KeyType offset = 0.) :
00102         scale_(scale),
00103         offset_(offset),
00104         inside_(),
00105         outside_(),
00106         data_()
00107       {}
00108 
00110       LinearInterpolation(LinearInterpolation const & arg) :
00111         scale_(arg.scale_),
00112         offset_(arg.offset_),
00113         inside_(arg.inside_),
00114         outside_(arg.outside_),
00115         data_(arg.data_)
00116       {}
00117 
00119       LinearInterpolation & operator=(LinearInterpolation const & arg)
00120       {
00121         if (&arg == this)
00122           return *this;
00123 
00124         scale_   = arg.scale_;
00125         offset_  = arg.offset_;
00126         inside_  = arg.inside_;
00127         outside_ = arg.outside_;
00128         data_    = arg.data_;
00129 
00130         return *this;
00131       }
00132 
00134       ~LinearInterpolation() {}
00135 
00136       // ----------------------------------------------------------------------
00137 
00139 
00140 
00142       ValueType value(KeyType arg_pos) const
00143       {
00144 
00145         typedef typename container_type::difference_type DiffType;
00146 
00147         // apply the key transformation
00148         KeyType left_key;
00149         KeyType pos = key2index(arg_pos);
00150         KeyType frac = std::modf(pos, &left_key);
00151         DiffType const left = DiffType(left_key);
00152 
00153         // At left margin?
00154         if (pos < 0)
00155         {
00156           if (left /* <= -1 */)
00157           {
00158             return 0;
00159           }
00160           else        // left == 0
00161           {
00162             return data_[0] * (1 + frac);
00163           }
00164         }
00165         else         // pos >= 0
00166         {
00167           // At right margin?
00168           DiffType const back = data_.size() - 1;
00169           if (left >= back)
00170           {
00171             if (left != back)
00172             {
00173               return 0;
00174             }
00175             else
00176             {
00177               return data_[left] * (1 - frac);
00178             }
00179           }
00180           else
00181           {
00182             // In between!
00183             return data_[left + 1] * frac + data_[left] * (1 - frac);
00184           }
00185         }
00186       }
00187 
00191       void addValue(KeyType arg_pos, ValueType arg_value)
00192       {
00193 
00194         typedef typename container_type::difference_type DiffType;
00195 
00196         // apply the key transformation
00197         KeyType left_key;
00198         KeyType const pos = key2index(arg_pos);
00199         KeyType const frac = std::modf(pos, &left_key);
00200         DiffType const left = DiffType(left_key);
00201 
00202         // At left margin?
00203         if (pos < 0)
00204         {
00205           if (left /* <= -1 */)
00206           {
00207             return;
00208           }
00209           else        // left == 0
00210           {
00211             data_[0] += (1 + frac) * arg_value;
00212             return;
00213           }
00214         }
00215         else         // pos >= 0
00216         {
00217           // At right margin?
00218           DiffType const back = data_.size() - 1;
00219           if (left >= back)
00220           {
00221             if (left != back)
00222             {
00223               return;
00224             }
00225             else             // left == back
00226             {
00227               data_[left] += (1 - frac) * arg_value;
00228               return;
00229             }
00230           }
00231           else
00232           {
00233             // In between!
00234             data_[left + 1] += frac * arg_value;
00235             data_[left] += (1 - frac) * arg_value;
00236             return;
00237           }
00238         }
00239       }
00240 
00245       ValueType derivative(KeyType arg_pos) const
00246       {
00247 
00248         // apply the key transformation
00249         KeyType const pos = key2index(arg_pos);
00250 
00251         SignedSize const size_ = data_.size();
00252         SignedSize const left = int(pos + 0.5);       // rounds towards zero
00253 
00254         if (left < 0)           // quite small
00255         {
00256           return 0;
00257         }
00258         else
00259         {
00260           if (left == 0)             // at the border
00261           {
00262             if (pos >= -0.5)               // that is: -0.5 <= pos < +0.5
00263             {
00264               return (data_[1] - data_[0]) * (pos + 0.5) + (data_[0]) * (0.5 - pos);
00265             }
00266             else             // that is: -1.5 <= pos < -0.5
00267             {
00268               return (data_[0]) * (pos + 1.5);
00269             }
00270           }
00271         }
00272         // "else" case: to the right of the left margin
00273 
00274 
00275         KeyType factor = KeyType(left) - pos + KeyType(0.5);
00276 
00277         if (left > size_)           // quite large
00278         {
00279           return 0;
00280         }
00281         else
00282         {
00283           if (left < size_ - 1)             // to the left of the right margin
00284           {
00285             // weighted average of derivatives for adjacent intervals
00286             return (data_[left] - data_[left - 1]) * factor + (data_[left + 1] - data_[left]) * (1. - factor);
00287           }
00288           else           // somewhat at the border
00289           {
00290             // at the border, first case
00291             if (left == size_ - 1)
00292             {
00293               return (data_[left] - data_[left - 1]) * factor + (-data_[left]) * (1. - factor);
00294             }
00295           }
00296         }
00297         // else // that is: left == size_
00298 
00299         // We pull the last remaining case out of the "if" tree to avoid a
00300         // compiler warning ...
00301 
00302         // at the border, second case
00303         return (-data_[left - 1]) * factor;
00304       }
00305 
00307 
00308       // ----------------------------------------------------------------------
00309 
00311 
00312 
00314       ContainerType & getData()
00315       {
00316         return data_;
00317       }
00318 
00320       ContainerType const & getData() const
00321       {
00322         return data_;
00323       }
00324 
00330       template <typename SourceContainer>
00331       void setData(SourceContainer const & data)
00332       {
00333         data_ = data;
00334       }
00335 
00337       bool empty() const
00338       {
00339         return data_.empty();
00340       }
00341 
00343 
00344       // ----------------------------------------------------------------------
00345 
00347 
00348 
00350       KeyType key2index(KeyType pos) const
00351       {
00352         if (scale_)
00353         {
00354           pos -= offset_;
00355           pos /= scale_;
00356           return pos;
00357         }
00358         else
00359         {
00360           return 0;
00361         }
00362       }
00363 
00365       KeyType index2key(KeyType pos) const
00366       {
00367         pos *= scale_;
00368         pos += offset_;
00369         return pos;
00370       }
00371 
00373       KeyType const & getScale() const
00374       {
00375         return scale_;
00376       }
00377 
00383       void setScale(KeyType const & scale)
00384       {
00385         scale_ = scale;
00386       }
00387 
00389       KeyType const & getOffset() const
00390       {
00391         return offset_;
00392       }
00393 
00400       void setOffset(KeyType const & offset)
00401       {
00402         offset_ = offset;
00403       }
00404 
00418       void setMapping(KeyType const & scale, KeyType const & inside, KeyType const & outside)
00419       {
00420         scale_   = scale;
00421         inside_  = inside;
00422         outside_ = outside;
00423         offset_  = outside - scale * inside;
00424       }
00425 
00432       void setMapping(KeyType const & inside_low, KeyType const & outside_low,
00433                       KeyType const & inside_high, KeyType const & outside_high)
00434       {
00435         if (inside_high != inside_low)
00436         {
00437           setMapping((outside_high - outside_low) / (inside_high - inside_low),
00438                      inside_low, outside_low);
00439         }
00440         else
00441         {
00442           setMapping(0, inside_low, outside_low);
00443         }
00444         return;
00445       }
00446 
00448       KeyType const & getInsideReferencePoint() const
00449       {
00450         return inside_;
00451       }
00452 
00454       KeyType const & getOutsideReferencePoint() const
00455       {
00456         return outside_;
00457       }
00458 
00460       KeyType supportMin() const
00461       {
00462         return index2key(KeyType(empty() ? 0 : -1));
00463       }
00464 
00466       KeyType supportMax() const
00467       {
00468         return index2key(KeyType(data_.size()));
00469       }
00470 
00472 
00473 protected:
00474 
00475       KeyType scale_;
00476       KeyType offset_;
00477       KeyType inside_;
00478       KeyType outside_;
00479 
00480       ContainerType data_;
00481 
00482     };
00483 
00484   }   // namespace Math
00485 
00486 } // namespace OpenMS
00487 
00488 #endif // OPENMS_MATH_MISC_LINEARINTERPOLATION_H

OpenMS / TOPP release 1.10.0 Documentation generated on Thu Mar 7 2013 09:42:40 using doxygen 1.7.1