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

LinearInterpolation.h (Maintainer: Clemens Groepl)

Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 // --------------------------------------------------------------------------
00005 //                   OpenMS Mass Spectrometry Framework
00006 // --------------------------------------------------------------------------
00007 //  Copyright (C) 2003-2008 -- Oliver Kohlbacher, Knut Reinert
00008 //
00009 //  This library is free software; you can redistribute it and/or
00010 //  modify it under the terms of the GNU Lesser General Public
00011 //  License as published by the Free Software Foundation; either
00012 //  version 2.1 of the License, or (at your option) any later version.
00013 //
00014 //  This library is distributed in the hope that it will be useful,
00015 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 //  Lesser General Public License for more details.
00018 //
00019 //  You should have received a copy of the GNU Lesser General Public
00020 //  License along with this library; if not, write to the Free Software
00021 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // --------------------------------------------------------------------------
00024 // $Maintainer: Clemens Groepl $
00025 // --------------------------------------------------------------------------
00026 
00027 #ifndef OPENMS_MATH_MISC_LINEARINTERPOLATION_H
00028 #define OPENMS_MATH_MISC_LINEARINTERPOLATION_H
00029 
00030 #include <cmath> // for modf() (which is an overloaded function in C++)
00031 #include <vector>
00032 
00033 namespace OpenMS
00034 {
00035 
00036   namespace Math
00037   {
00038 
00064     template < typename Key = double, typename Value = Key >
00065     class LinearInterpolation
00066     {
00067 
00068      public:
00069 
00071 
00072       typedef Value value_type;
00073 
00074       typedef Key key_type;
00075       typedef std::vector < value_type > container_type;
00076 
00077       typedef value_type      ValueType;
00078       typedef key_type        KeyType;
00079       typedef container_type  ContainerType;
00081 
00082      public:
00083 
00091       LinearInterpolation ( KeyType scale = 1., KeyType offset = 0. )
00092         : scale_  ( scale ),
00093           offset_ ( offset ),
00094           inside_ (),
00095           outside_(),
00096           data_   ()
00097       {}
00098 
00100       LinearInterpolation ( LinearInterpolation const & arg )
00101         : scale_  ( arg.scale_ ),
00102           offset_ ( arg.offset_ ),
00103           inside_ ( arg.inside_ ),
00104           outside_ (arg.outside_ ),
00105           data_   ( arg.data_ )
00106       {}
00107 
00109       LinearInterpolation & operator= ( LinearInterpolation const & arg )
00110       {
00111          if (&arg == this)
00112       return *this;
00113 
00114           scale_   = arg.scale_;
00115           offset_  = arg.offset_;
00116           inside_  = arg.inside_;
00117           outside_ = arg.outside_;
00118           data_    = arg.data_;
00119 
00120           return *this;
00121       }
00122 
00124       ~LinearInterpolation () {}
00125 
00126       // ----------------------------------------------------------------------
00127 
00129 
00130 
00132       ValueType value ( KeyType arg_pos ) const throw()
00133       {
00134 
00135         typedef typename container_type::difference_type DiffType;
00136 
00137         // apply the key transformation
00138         KeyType left_key;
00139         KeyType pos = key2index(arg_pos);
00140         KeyType frac = std::modf(pos, &left_key);
00141         DiffType const left = DiffType(left_key);
00142 
00143         // At left margin?
00144         if ( pos < 0 )
00145         {
00146           if ( left /* <= -1 */ )
00147           {
00148             return 0;
00149           }
00150           else
00151           { // left == 0
00152             return data_[ 0 ] * ( 1 + frac );
00153           }
00154         }
00155         else // pos >= 0
00156         {
00157           // At right margin?
00158           DiffType const back = data_.size() - 1;
00159           if ( left >= back )
00160           {
00161             if ( left != back )
00162             {
00163               return 0;
00164             }
00165             else
00166             {
00167               return data_[ left ] * ( 1 - frac );
00168             }
00169           }
00170           else
00171           {
00172             // In between!
00173             return data_[ left + 1 ] * frac + data_[ left ] * ( 1 - frac );
00174           }
00175         }
00176       }
00177 
00178 
00182       void addValue ( KeyType arg_pos, ValueType arg_value ) throw()
00183       {
00184 
00185         typedef typename container_type::difference_type DiffType;
00186 
00187         // apply the key transformation
00188         KeyType left_key;
00189         KeyType const pos = key2index(arg_pos);
00190         KeyType const frac = std::modf(pos, &left_key);
00191         DiffType const left = DiffType(left_key);
00192 
00193         // At left margin?
00194         if ( pos < 0 )
00195         {
00196           if ( left /* <= -1 */ )
00197           {
00198             return;
00199           }
00200           else
00201           { // left == 0
00202             data_[ 0 ] += ( 1 + frac ) * arg_value;
00203             return;
00204           }
00205         }
00206         else // pos >= 0
00207         {
00208           // At right margin?
00209           DiffType const back = data_.size() - 1;
00210           if ( left >= back )
00211           {
00212             if ( left != back )
00213             {
00214               return;
00215             }
00216             else // left == back
00217             {
00218               data_[ left ] += ( 1 - frac ) * arg_value;
00219               return;
00220             }
00221           }
00222           else
00223           {
00224             // In between!
00225             data_[ left + 1 ] += frac * arg_value;
00226             data_[ left ] += ( 1 - frac ) * arg_value;
00227             return;
00228           }
00229         }
00230       }
00231 
00236       ValueType derivative ( KeyType arg_pos ) const throw()
00237       {
00238 
00239         // apply the key transformation
00240         KeyType const pos = key2index(arg_pos);
00241 
00242         int const size_ = data_.size();
00243         int const left = int(pos+0.5); // rounds towards zero
00244 
00245         if ( left < 0 ) // quite small
00246           return 0;
00247         else
00248           if ( left == 0 ) // at the border
00249             if ( pos >= -0.5 ) // that is: -0.5 <= pos < +0.5
00250               return
00251                 ( data_[1] - data_[0] ) * ( pos + 0.5 ) +
00252                 ( data_[0] ) * ( 0.5 - pos );
00253             else // that is: -1.5 <= pos < -0.5
00254               return
00255                 ( data_[0] ) * ( pos + 1.5 );
00256 
00257         // "else" case: to the right of the left margin
00258 
00259 
00260         KeyType factor = KeyType(left) - pos + 0.5;
00261 
00262         if ( left > size_ ) // quite large
00263           return 0;
00264         else
00265           if ( left < size_ - 1 ) // to the left of the right margin
00266             return // weighted average of derivatives for adjacent intervals
00267               ( data_[left] - data_[left-1] ) * factor +
00268               ( data_[left+1] - data_[left] ) * ( 1. - factor );
00269           else // somewhat at the border
00270             if ( left == size_ - 1 ) // at the border, first case
00271               return
00272                 ( data_[left] - data_[left-1] ) * factor +
00273                 ( - data_[left] ) * ( 1. - factor );
00274         // else // that is: left == size_
00275 
00276         // We pull the last remaining case out of the "if" tree to avoid a
00277         // compiler warning ...
00278 
00279         return // at the border, second case
00280           ( - data_[left-1] ) * factor;
00281 
00282       }
00283 
00285 
00286       // ----------------------------------------------------------------------
00287 
00289 
00290 
00292       ContainerType & getData () throw()
00293       {
00294         return data_;
00295       }
00296 
00298       ContainerType const & getData () const throw()
00299       {
00300         return data_;
00301       }
00302 
00308       template < typename SourceContainer >
00309       void setData ( SourceContainer const & data ) throw()
00310       {
00311         data_ = data;
00312       }
00313 
00314 
00316       bool empty () const throw()
00317       {
00318         return data_.empty();
00319       }
00320 
00322 
00323       // ----------------------------------------------------------------------
00324 
00326 
00327 
00329       KeyType key2index ( KeyType pos ) const throw()
00330       {
00331         if ( scale_ )
00332         {
00333           pos -= offset_;
00334           pos /= scale_;
00335           return pos;
00336         }
00337         else
00338         {
00339           return 0;
00340         }
00341       }
00342 
00344       KeyType index2key ( KeyType pos ) const throw()
00345       {
00346         pos *= scale_;
00347         pos += offset_;
00348         return pos;
00349       }
00350 
00352       KeyType const & getScale () const throw()
00353       {
00354         return scale_;
00355       }
00356 
00362       void setScale ( KeyType const & scale ) throw()
00363       {
00364         scale_ = scale;
00365       }
00366 
00368       KeyType const & getOffset () const throw()
00369       {
00370         return offset_;
00371       }
00372 
00379       void setOffset ( KeyType const & offset ) throw()
00380       {
00381         offset_ = offset;
00382       }
00383 
00397       void setMapping ( KeyType const & scale, KeyType const & inside, KeyType const & outside )
00398       {
00399         scale_   = scale;
00400         inside_  = inside;
00401         outside_ = outside;
00402         offset_  = outside - scale * inside;
00403       }
00404 
00411       void setMapping ( KeyType const & inside_low, KeyType const & outside_low,
00412                         KeyType const & inside_high, KeyType const & outside_high )
00413       {
00414         if ( inside_high != inside_low )
00415         {
00416           setMapping ( ( outside_high - outside_low ) / ( inside_high - inside_low ),
00417                        inside_low, outside_low );
00418         }
00419         else
00420         {
00421           setMapping ( 0, inside_low, outside_low );
00422         }
00423         return;
00424       }
00425 
00427       KeyType const & getInsideReferencePoint () const throw()
00428       {
00429         return inside_;
00430       }
00431 
00433       KeyType const & getOutsideReferencePoint () const throw()
00434       {
00435         return outside_;
00436       }
00437 
00439       KeyType supportMin() const throw()
00440       {
00441         return index2key ( empty() ? 0 : -1 );
00442       }
00443 
00445       KeyType supportMax() const throw()
00446       {
00447         return index2key ( data_.size() );
00448       }
00449 
00451 
00452      protected:
00453 
00454       KeyType scale_;
00455       KeyType offset_;
00456       KeyType inside_;
00457       KeyType outside_;
00458 
00459       ContainerType data_;
00460 
00461     };
00462 
00463   } // namespace Math
00464 
00465 } // namespace OpenMS
00466 
00467 #endif // OPENMS_MATH_MISC_LINEARINTERPOLATION_H

Generated Tue Apr 1 15:36:35 2008 -- using doxygen 1.5.4 OpenMS / TOPP 1.1