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

BilinearInterpolation.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_BILINEARINTERPOLATION_H
00036 #define OPENMS_MATH_MISC_BILINEARINTERPOLATION_H
00037 
00038 #include <OpenMS/DATASTRUCTURES/Matrix.h>
00039 
00040 namespace OpenMS
00041 {
00042 
00043   namespace Math
00044   {
00045 
00072     template <typename Key = double, typename Value = Key>
00073     class BilinearInterpolation
00074     {
00075 
00076 public:
00077 
00079 
00080       typedef Value value_type;
00081 
00082       typedef Key key_type;
00083       typedef Matrix<value_type> container_type;
00084 
00085       typedef value_type ValueType;
00086       typedef key_type KeyType;
00087       typedef container_type ContainerType;
00089 
00090 public:
00091 
00095 
00097       BilinearInterpolation() :
00098         scale_0_(1),
00099         offset_0_(0),
00100         scale_1_(1),
00101         offset_1_(0),
00102         inside_0_(0),
00103         outside_0_(0),
00104         inside_1_(0),
00105         outside_1_(0),
00106         data_()
00107       {}
00108 
00110       BilinearInterpolation(BilinearInterpolation const & arg) :
00111         scale_0_(arg.scale_0_),
00112         offset_0_(arg.offset_0_),
00113         scale_1_(arg.scale_1_),
00114         offset_1_(arg.offset_1_),
00115         inside_0_(arg.inside_0_),
00116         outside_0_(arg.outside_0_),
00117         inside_1_(arg.inside_1_),
00118         outside_1_(arg.outside_1_),
00119         data_(arg.data_)
00120       {}
00121 
00123       BilinearInterpolation & operator=(BilinearInterpolation const & arg)
00124       {
00125         if (&arg == this)
00126           return *this;
00127 
00128         scale_0_ = arg.scale_0_;
00129         offset_0_ = arg.offset_0_;
00130         scale_1_ = arg.scale_1_;
00131         offset_1_ = arg.offset_1_;
00132         inside_0_ = arg.inside_0_;
00133         outside_1_ = arg.outside_1_;
00134         inside_1_ = arg.inside_1_;
00135         outside_0_ = arg.outside_0_;
00136         data_ = arg.data_;
00137         return *this;
00138       }
00139 
00141       ~BilinearInterpolation()
00142       {}
00143 
00145 
00146       // ----------------------------------------------------------------------
00147 
00149 
00150 
00152       ValueType value(KeyType arg_pos_0, KeyType arg_pos_1) const
00153       {
00154         // apply the key transformations
00155         KeyType const pos_0 = key2index_0(arg_pos_0);
00156         KeyType const pos_1 = key2index_1(arg_pos_1);
00157 
00158         // ???? should use modf() here!
00159 
00160         SignedSize const size_0 = data_.rows();
00161         SignedSize const lower_0 = SignedSize(pos_0);           // this rounds towards zero
00162         SignedSize const size_1 = data_.cols();
00163         SignedSize const lower_1 = SignedSize(pos_1);           // this rounds towards zero
00164 
00165         // small pos_0
00166         if (pos_0 <= 0)
00167         {
00168           if (lower_0 != 0)
00169           {
00170             return 0;
00171           }
00172           else        // that is: -1 < pos_0 <= 0
00173           {             // small pos_1
00174             if (pos_1 <= 0)
00175             {
00176               if (lower_1 != 0)
00177               {
00178                 return 0;
00179               }
00180               else            // that is: -1 < pos_1 <= 0
00181               {
00182                 return data_(0, 0) * (1. + pos_0) * (1. + pos_1);
00183               }
00184             }
00185 
00186             // big pos_1
00187             if (lower_1 >= size_1 - 1)
00188             {
00189               if (lower_1 != size_1 - 1)
00190               {
00191                 return 0;
00192               }
00193               else
00194               {
00195                 return data_(0, lower_1) * (1. + pos_0) * (size_1 - pos_1);
00196               }
00197             }
00198 
00199             // mediumm pos_1
00200             KeyType const factor_1 = pos_1 - KeyType(lower_1);
00201             KeyType const factor_1_complement = KeyType(1.) - factor_1;
00202             return (
00203                      data_(0, lower_1 + 1) * factor_1 +
00204                      data_(0, lower_1) * factor_1_complement
00205                      ) * (1. + pos_0);
00206           }
00207         }
00208 
00209         // big pos_0
00210         if (lower_0 >= size_0 - 1)
00211         {
00212           if (lower_0 != size_0 - 1)
00213           {
00214             return 0;
00215           }
00216           else        // that is: size_0 - 1 <= pos_0 < size_0
00217           {             // small pos_1
00218             if (pos_1 <= 0)
00219             {
00220               if (lower_1 != 0)
00221               {
00222                 return 0;
00223               }
00224               else            // that is: -1 < pos_1 <= 0
00225               {
00226                 return data_(lower_0, 0) * (size_0 - pos_0) * (1. + pos_1);
00227               }
00228             }
00229 
00230             // big pos_1
00231             if (lower_1 >= size_1 - 1)
00232             {
00233               if (lower_1 != size_1 - 1)
00234               {
00235                 return 0;
00236               }
00237               else
00238               {
00239                 return data_(lower_0, lower_1) * (size_0 - pos_0) * (size_1 - pos_1);
00240               }
00241             }
00242 
00243             // mediumm pos_1
00244             KeyType const factor_1 = pos_1 - KeyType(lower_1);
00245             KeyType const factor_1_complement = KeyType(1.) - factor_1;
00246             return (
00247                      data_(lower_0, lower_1 + 1) * factor_1 +
00248                      data_(lower_0, lower_1) * factor_1_complement
00249                      )
00250                    * (size_0 - pos_0);
00251           }
00252         }
00253 
00254         // medium pos_0
00255         {
00256           KeyType const factor_0 = pos_0 - KeyType(lower_0);
00257           KeyType const factor_0_complement = KeyType(1.) - factor_0;
00258 
00259           // small pos_1
00260           if (pos_1 <= 0)
00261           {
00262             if (lower_1 != 0)
00263             {
00264               return 0;
00265             }
00266             else          // that is: -1 < pos_1 <= 0
00267             {
00268               return (
00269                        data_(lower_0 + 1, 0) * factor_0
00270                        +
00271                        data_(lower_0, 0) * factor_0_complement
00272                        )
00273                      * (1. + pos_1);
00274             }
00275           }
00276 
00277           // big pos_1
00278           if (lower_1 >= size_1 - 1)
00279           {
00280             if (lower_1 != size_1 - 1)
00281             {
00282               return 0;
00283             }
00284             else
00285             {
00286               return (
00287                        data_(lower_0 + 1, lower_1) * factor_0
00288                        +
00289                        data_(lower_0, lower_1) * factor_0_complement
00290                        )
00291                      * (size_1 - pos_1);
00292             }
00293           }
00294           KeyType const factor_1 = pos_1 - KeyType(lower_1);
00295           KeyType const factor_1_complement = KeyType(1.) - factor_1;
00296 
00297           // medium pos_0 and medium pos_1 --> "within" the matrix
00298           return (
00299                    data_(lower_0 + 1, lower_1 + 1) * factor_0
00300                    +
00301                    data_(lower_0, lower_1 + 1) * factor_0_complement
00302                    )
00303                  * factor_1
00304                  +
00305                  (
00306                    data_(lower_0 + 1, lower_1) * factor_0
00307                    +
00308                    data_(lower_0, lower_1) * factor_0_complement
00309                  )
00310                  * factor_1_complement;
00311         }
00312       }
00313 
00317       void addValue(KeyType arg_pos_0, KeyType arg_pos_1, ValueType arg_value)
00318       {
00319 
00320         typedef typename container_type::difference_type DiffType;
00321 
00322         // apply key transformation _0
00323         KeyType const pos_0 = key2index_0(arg_pos_0);
00324         KeyType lower_0_key;
00325         KeyType const frac_0 = std::modf(pos_0, &lower_0_key);
00326         DiffType const lower_0 = DiffType(lower_0_key);
00327 
00328         // Small pos_0 ?
00329         if (pos_0 < 0)
00330         {
00331           if (lower_0)
00332           {
00333             return;
00334           }
00335           else        // lower_0 == 0
00336           {             // apply key transformation _1
00337             KeyType const pos_1 = key2index_1(arg_pos_1);
00338             KeyType lower_1_key;
00339             KeyType const frac_1 = std::modf(pos_1, &lower_1_key);
00340             DiffType const lower_1 = DiffType(lower_1_key);
00341 
00342             // Small pos_1 ?
00343             if (pos_1 < 0)
00344             {
00345               if (lower_1)
00346               {
00347                 return;
00348               }
00349               else            // lower_1 == 0
00350               {
00351                 data_(0, 0) += arg_value * (1 + frac_0) * (1 + frac_1);
00352                 return;
00353               }
00354             }
00355             else             // pos_1 >= 0
00356             {
00357               DiffType const back_1 = data_.cols() - 1;
00358               // big pos_1
00359               if (lower_1 >= back_1)
00360               {
00361                 if (lower_1 != back_1)
00362                 {
00363                   return;
00364                 }
00365                 else                 // lower_1 == back_1
00366                 {
00367                   data_(0, lower_1) += arg_value * (1 + frac_0) * (1 - frac_1);
00368                   return;
00369                 }
00370               }
00371               else
00372               {
00373                 // medium pos_1
00374                 KeyType const tmp_prod = KeyType(arg_value * (1. + frac_0));
00375                 data_(0, lower_1 + 1) += tmp_prod * frac_1;
00376                 data_(0, lower_1) += tmp_prod * (1. - frac_1);
00377                 return;
00378               }
00379             }
00380           }
00381         }
00382         else         // pos_0 >= 0
00383         {
00384           DiffType const back_0 = data_.rows() - 1;
00385           if (lower_0 >= back_0)
00386           {
00387             if (lower_0 != back_0)
00388             {
00389               return;
00390             }
00391             else             // lower_0 == back_0
00392             {
00393 
00394               KeyType const tmp_prod = KeyType(arg_value * (1. - frac_0));
00395 
00396               // apply key transformation _1
00397               KeyType const pos_1 = key2index_1(arg_pos_1);
00398               KeyType lower_1_key;
00399               KeyType const frac_1 = std::modf(pos_1, &lower_1_key);
00400               DiffType const lower_1 = DiffType(lower_1_key);
00401 
00402               // Small pos_1 ?
00403               if (pos_1 < 0)
00404               {
00405                 if (lower_1)
00406                 {
00407                   return;
00408                 }
00409                 else              // lower_1 == 0
00410                 {
00411                   data_(lower_0, 0) += tmp_prod * (1 + frac_1);
00412                   return;
00413                 }
00414               }
00415               else               // pos_1 >= 0
00416               {
00417                 DiffType const back_1 = data_.cols() - 1;
00418                 // big pos_1
00419                 if (lower_1 >= back_1)
00420                 {
00421                   if (lower_1 != back_1)
00422                   {
00423                     return;
00424                   }
00425                   else                   // lower_1 == back_1
00426                   {
00427                     data_(lower_0, lower_1) += tmp_prod * (1 - frac_1);
00428                     return;
00429                   }
00430                 }
00431                 else
00432                 {
00433                   // medium pos_1
00434                   data_(lower_0, lower_1 + 1) += tmp_prod * frac_1;
00435                   data_(lower_0, lower_1) += tmp_prod * (1 - frac_1);
00436                   return;
00437                 }
00438               }
00439             }
00440           }
00441           else           // lower_0 < back_0
00442           {
00443 
00444             // Medium pos_0 !
00445 
00446             // apply key transformation _1
00447             KeyType const pos_1 = key2index_1(arg_pos_1);
00448             KeyType lower_1_key;
00449             KeyType const frac_1 = std::modf(pos_1, &lower_1_key);
00450             DiffType const lower_1 = DiffType(lower_1_key);
00451 
00452             // Small pos_1 ?
00453             if (pos_1 < 0)
00454             {
00455               if (lower_1)
00456               {
00457                 return;
00458               }
00459               else            // lower_1 == 0
00460               {
00461                 KeyType const tmp_prod = KeyType(arg_value * (1 + frac_1));
00462                 data_(lower_0 + 1, 0) += tmp_prod * frac_0;
00463                 data_(lower_0, 0) += tmp_prod * (1 - frac_0);
00464                 return;
00465               }
00466             }
00467             else             // pos_1 >= 0
00468             {
00469               DiffType const back_1 = data_.cols() - 1;
00470               // big pos_1
00471               if (lower_1 >= back_1)
00472               {
00473                 if (lower_1 != back_1)
00474                 {
00475                   return;
00476                 }
00477                 else                 // lower_1 == back_1
00478                 {
00479                   KeyType const tmp_prod = KeyType(arg_value * (1 - frac_1));
00480                   data_(lower_0 + 1, lower_1) += tmp_prod * frac_0;
00481                   data_(lower_0, lower_1) += tmp_prod * (1 - frac_0);
00482                   return;
00483                 }
00484               }
00485               else
00486               {
00487                 // Medium pos_1 !
00488 
00489                 // medium pos_0 and medium pos_1 --> "within" the matrix
00490                 KeyType tmp_prod = KeyType(arg_value * frac_0);
00491                 data_(lower_0 + 1, lower_1 + 1) += tmp_prod * frac_1;
00492                 data_(lower_0 + 1, lower_1) += tmp_prod * (1 - frac_1);
00493                 tmp_prod = KeyType(arg_value * (1 - frac_0));
00494                 data_(lower_0, lower_1 + 1) += tmp_prod * frac_1;
00495                 data_(lower_0, lower_1) += tmp_prod * (1 - frac_1);
00496                 return;
00497               }
00498             }
00499           }
00500         }
00501       }
00502 
00504 
00505       // ----------------------------------------------------------------------
00506 
00508 
00509 
00511       ContainerType & getData()
00512       {
00513         return data_;
00514       }
00515 
00517       ContainerType const & getData() const
00518       {
00519         return data_;
00520       }
00521 
00527       template <typename SourceContainer>
00528       void setData(SourceContainer const & data)
00529       {
00530         data_ = data;
00531       }
00532 
00534       bool empty() const
00535       {
00536         return data_.empty();
00537       }
00538 
00540 
00541       // ----------------------------------------------------------------------
00542 
00544 
00545 
00547       KeyType key2index_0(KeyType pos) const
00548       {
00549         if (scale_0_)
00550         {
00551           pos -= offset_0_;
00552           pos /= scale_0_;
00553           return pos;
00554         }
00555         else
00556         {
00557           return 0;
00558         }
00559       }
00560 
00562       KeyType index2key_0(KeyType pos) const
00563       {
00564         pos *= scale_0_;
00565         pos += offset_0_;
00566         return pos;
00567       }
00568 
00570       KeyType key2index_1(KeyType pos) const
00571       {
00572         if (scale_1_)
00573         {
00574           pos -= offset_1_;
00575           pos /= scale_1_;
00576           return pos;
00577         }
00578         else
00579         {
00580           return 0;
00581         }
00582       }
00583 
00585       KeyType index2key_1(KeyType pos) const
00586       {
00587         pos *= scale_1_;
00588         pos += offset_1_;
00589         return pos;
00590       }
00591 
00593       KeyType const & getScale_0() const
00594       {
00595         return scale_0_;
00596       }
00597 
00599       KeyType const & getScale_1() const
00600       {
00601         return scale_1_;
00602       }
00603 
00609       void setScale_0(KeyType const & scale)
00610       {
00611         scale_0_ = scale;
00612       }
00613 
00619       void setScale_1(KeyType const & scale)
00620       {
00621         scale_1_ = scale;
00622       }
00623 
00625       KeyType const & getOffset_0() const
00626       {
00627         return offset_0_;
00628       }
00629 
00631       KeyType const & getOffset_1() const
00632       {
00633         return offset_1_;
00634       }
00635 
00642       void setOffset_0(KeyType const & offset)
00643       {
00644         offset_0_ = offset;
00645       }
00646 
00653       void setOffset_1(KeyType const & offset)
00654       {
00655         offset_1_ = offset;
00656       }
00657 
00671       void setMapping_0(KeyType const & scale, KeyType const & inside_low, KeyType const & outside_low)
00672       {
00673         scale_0_ = scale;
00674         inside_0_ = inside_low;
00675         outside_0_ = outside_low;
00676         offset_0_ = outside_low - scale * inside_low;
00677         return;
00678       }
00679 
00686       void setMapping_0(KeyType const & inside_low, KeyType const & outside_low,
00687                         KeyType const & inside_high, KeyType const & outside_high)
00688       {
00689         if (inside_high != inside_low)
00690         {
00691           setMapping_0((outside_high - outside_low) / (inside_high - inside_low),
00692                        inside_low, outside_low);
00693         }
00694         else
00695         {
00696           setMapping_0(0, inside_low, outside_low);
00697         }
00698         return;
00699       }
00700 
00714       void setMapping_1(KeyType const & scale, KeyType const & inside_low, KeyType const & outside_low)
00715       {
00716         scale_1_ = scale;
00717         inside_1_ = inside_low;
00718         outside_1_ = outside_low;
00719         offset_1_ = outside_low - scale * inside_low;
00720         return;
00721       }
00722 
00729       void setMapping_1(KeyType const & inside_low, KeyType const & outside_low,
00730                         KeyType const & inside_high, KeyType const & outside_high)
00731       {
00732         if (inside_high != inside_low)
00733         {
00734           setMapping_1((outside_high - outside_low) / (inside_high - inside_low),
00735                        inside_low, outside_low);
00736         }
00737         else
00738         {
00739           setMapping_1(0, inside_low, outside_low);
00740         }
00741         return;
00742       }
00743 
00745       KeyType const & getInsideReferencePoint_0() const
00746       {
00747         return inside_0_;
00748       }
00749 
00751       KeyType const & getInsideReferencePoint_1() const
00752       {
00753         return inside_1_;
00754       }
00755 
00757       KeyType const & getOutsideReferencePoint_0() const
00758       {
00759         return outside_0_;
00760       }
00761 
00763       KeyType const & getOutsideReferencePoint_1() const
00764       {
00765         return outside_1_;
00766       }
00767 
00769       KeyType supportMin_0() const
00770       {
00771         return index2key_0(empty() ? KeyType(0.) : KeyType(-1.));
00772       }
00773 
00775       KeyType supportMin_1() const
00776       {
00777         return index2key_1(empty() ? KeyType(0.) : KeyType(-1.));
00778       }
00779 
00781       KeyType supportMax_0() const
00782       {
00783         return index2key_0(KeyType(data_.rows()));
00784       }
00785 
00787       KeyType supportMax_1() const
00788       {
00789         return index2key_1(KeyType(data_.cols()));
00790       }
00791 
00793 
00794 protected:
00795 
00798       KeyType scale_0_;
00799       KeyType offset_0_;
00800       KeyType scale_1_;
00801       KeyType offset_1_;
00802       KeyType inside_0_;
00803       KeyType outside_0_;
00804       KeyType inside_1_;
00805       KeyType outside_1_;
00806       ContainerType data_;
00808     };
00809 
00810   }   // namespace Math
00811 
00812 } // namespace OpenMS
00813 
00814 #endif // OPENMS_MATH_MISC_BILINEARINTERPOLATION_H

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