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

LevMarqFitter1D.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_TRANSFORMATIONS_FEATUREFINDER_LEVMARQFITTER1D_H
00036 #define OPENMS_TRANSFORMATIONS_FEATUREFINDER_LEVMARQFITTER1D_H
00037 
00038 #include <OpenMS/TRANSFORMATIONS/FEATUREFINDER/Fitter1D.h>
00039 
00040 #include <gsl/gsl_rng.h> // gsl random number generators
00041 #include <gsl/gsl_randist.h> // gsl random number distributions
00042 #include <gsl/gsl_vector.h> // gsl vector and matrix definitions
00043 #include <gsl/gsl_multifit_nlin.h> // gsl multidimensional fitting
00044 #include <gsl/gsl_blas.h> // gsl linear algebra stuff
00045 
00046 namespace OpenMS
00047 {
00048 
00052   class OPENMS_DLLAPI LevMarqFitter1D :
00053     public Fitter1D
00054   {
00055 
00056 public:
00057 
00058     typedef std::vector<double> ContainerType;
00059 
00061     LevMarqFitter1D() :
00062       Fitter1D()
00063     {
00064       this->defaults_.setValue("max_iteration", 500, "Maximum number of iterations using by Levenberg-Marquardt algorithm.", StringList::create("advanced"));
00065       this->defaults_.setValue("deltaAbsError", 0.0001, "Absolute error used by the Levenberg-Marquardt algorithm.", StringList::create("advanced"));
00066       this->defaults_.setValue("deltaRelError", 0.0001, "Relative error used by the Levenberg-Marquardt algorithm.", StringList::create("advanced"));
00067     }
00068 
00070     LevMarqFitter1D(const LevMarqFitter1D & source) :
00071       Fitter1D(source),
00072       max_iteration_(source.max_iteration_),
00073       abs_error_(source.abs_error_),
00074       rel_error_(source.rel_error_)
00075     {
00076     }
00077 
00079     virtual ~LevMarqFitter1D()
00080     {
00081     }
00082 
00084     virtual LevMarqFitter1D & operator=(const LevMarqFitter1D & source)
00085     {
00086       if (&source == this) return *this;
00087 
00088       Fitter1D::operator=(source);
00089       max_iteration_ = source.max_iteration_;
00090       abs_error_ = source.abs_error_;
00091       rel_error_ = source.rel_error_;
00092 
00093       return *this;
00094     }
00095 
00096 protected:
00097 
00099     Int gsl_status_;
00101     bool symmetric_;
00103     Int max_iteration_;
00105 
00106     CoordinateType abs_error_;
00108     CoordinateType rel_error_;
00109 
00113     virtual void printState_(Int iter, gsl_multifit_fdfsolver * s) = 0;
00114 
00116     const String getGslStatus_()
00117     {
00118       return gsl_strerror(gsl_status_);
00119     }
00120 
00126     void optimize_(const RawDataArrayType & set, Int num_params, CoordinateType x_init[],
00127                    Int (* residual)(const gsl_vector * x, void * params, gsl_vector * f),
00128                    Int (* jacobian)(const gsl_vector * x, void * params, gsl_matrix * J),
00129                    Int (* evaluate)(const gsl_vector * x, void * params, gsl_vector * f, gsl_matrix * J),
00130                    void * advanced_params
00131                    )
00132     {
00133 
00134       const gsl_multifit_fdfsolver_type * T;
00135       gsl_multifit_fdfsolver * s;
00136 
00137       Int status;
00138       Int iter = 0;
00139       const UInt n = (UInt)set.size();
00140 
00141       // number of parameters to be optimized
00142       UInt p = num_params;
00143 
00144       // gsl always expects N>=p or default gsl error handler invoked,
00145       // cause Jacobian be rectangular M x N with M>=N
00146       if (n < p) throw Exception::UnableToFit(__FILE__, __LINE__, __PRETTY_FUNCTION__, "UnableToFit-FinalSet", "Skipping feature, gsl always expects N>=p");
00147 
00148       // allocate space for a covariance matrix of size p by p
00149       gsl_matrix * covar = gsl_matrix_alloc(p, p);
00150       gsl_multifit_function_fdf f;
00151 
00152       gsl_vector_view x = gsl_vector_view_array(x_init, p);
00153 
00154       gsl_rng_env_setup();
00155 
00156       // set up the function to be fit
00157       f.f = (residual);     // the function of residuals
00158       f.df = (jacobian);     // the gradient of this function
00159       f.fdf = (evaluate);     // combined function and gradient
00160       f.n = set.size();     // number of points in the data set
00161       f.p = p;     // number of parameters in the fit function
00162       f.params = advanced_params;     // // structure with the data and error bars
00163 
00164       T = gsl_multifit_fdfsolver_lmsder;
00165       s = gsl_multifit_fdfsolver_alloc(T, n, p);
00166       gsl_multifit_fdfsolver_set(s, &f, &x.vector);
00167 
00168 #ifdef DEBUG_FEATUREFINDER
00169       printState_(iter, s);
00170 #endif
00171 
00172       // this is the loop for fitting
00173       do
00174       {
00175         iter++;
00176 
00177         // perform a single iteration of the fitting routine
00178         status = gsl_multifit_fdfsolver_iterate(s);
00179 
00180 #ifdef DEBUG_FEATUREFINDER
00181         // customized routine to print out current parameters
00182         printState_(iter, s);
00183 #endif
00184 
00185         /* check if solver is stuck */
00186         if (status) break;
00187 
00188         // test for convergence with an absolute and relative error
00189         status = gsl_multifit_test_delta(s->dx, s->x, abs_error_, rel_error_);
00190       }
00191       while (status == GSL_CONTINUE && iter < max_iteration_);
00192 
00193       // This function uses Jacobian matrix J to compute the covariance matrix of the best-fit parameters, covar.
00194       // The parameter epsrel (0.0) is used to remove linear-dependent columns when J is rank deficient.
00195       gsl_multifit_covar(s->J, 0.0, covar);
00196 
00197 #ifdef DEBUG_FEATUREFINDER
00198       gsl_matrix_fprintf(stdout, covar, "covar %g");
00199 #endif
00200 
00201 #define FIT(i) gsl_vector_get(s->x, i)
00202 #define ERR(i) sqrt(gsl_matrix_get(covar, i, i))
00203 
00204       // Set GSl status
00205       gsl_status_ = status;
00206 
00207 #ifdef DEBUG_FEATUREFINDER
00208       {
00209         // chi-squared value
00210         DoubleReal chi = gsl_blas_dnrm2(s->f);
00211         DoubleReal dof = n - p;
00212         DoubleReal c = GSL_MAX_DBL(1, chi / sqrt(dof));
00213 
00214         printf("chisq/dof = %g\n", pow(chi, 2.0) / dof);
00215 
00216         for (Size i = 0; i < p; ++i)
00217         {
00218           std::cout << i;
00219           printf(".Parameter = %.5f +/- %.5f\n", FIT(i), c * ERR(i));
00220         }
00221       }
00222 #endif
00223 
00224       // set optimized parameters
00225       for (Size i = 0; i < p; ++i)
00226       {
00227         x_init[i] = FIT(i);
00228       }
00229 
00230       gsl_multifit_fdfsolver_free(s);
00231       gsl_matrix_free(covar);
00232 
00233     }
00234 
00235     void updateMembers_()
00236     {
00237       Fitter1D::updateMembers_();
00238       max_iteration_ = this->param_.getValue("max_iteration");
00239       abs_error_ = this->param_.getValue("deltaAbsError");
00240       rel_error_ = this->param_.getValue("deltaRelError");
00241     }
00242 
00243   };
00244 }
00245 
00246 #endif // OPENMS_TRANSFORMATIONS_FEATUREFINDER_LEVMARQFITTER1D_H

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