1
// -*- mode: C++; tab-width: 2; -*-
4
// --------------------------------------------------------------------------
5
// OpenMS Mass Spectrometry Framework
6
// --------------------------------------------------------------------------
7
// Copyright (C) 2003-2011 -- Oliver Kohlbacher, Knut Reinert
9
// This library is free software; you can redistribute it and/or
10
// modify it under the terms of the GNU Lesser General Public
11
// License as published by the Free Software Foundation; either
12
// version 2.1 of the License, or (at your option) any later version.
14
// This library is distributed in the hope that it will be useful,
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
// Lesser General Public License for more details.
19
// You should have received a copy of the GNU Lesser General Public
20
// License along with this library; if not, write to the Free Software
21
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
// --------------------------------------------------------------------------
24
// $Maintainer: David Wojnar $
25
// $Authors: David Wojnar $
26
// --------------------------------------------------------------------------
33
#include <gsl/gsl_sf_psi.h>
34
#include <OpenMS/MATH/STATISTICS/GumbelDistributionFitter.h>
38
#define GUMBEL_DISTRIBUTION_FITTER_VERBOSE
39
#undef GUMBEL_DISTRIBUTION_FITTER_VERBOSE
41
#ifdef GUMBEL_DISTRIBUTION_FITTER_VERBOSE
43
#include <gsl/gsl_rng.h>
44
#include <gsl/gsl_randist.h>
45
#include <gsl/gsl_vector.h>
46
#include <gsl/gsl_blas.h>
47
#include <gsl/gsl_multifit_nlin.h>
54
GumbelDistributionFitter::GumbelDistributionFitter()
60
GumbelDistributionFitter::~GumbelDistributionFitter()
64
void GumbelDistributionFitter::setInitialParameters(const GumbelDistributionFitResult& param)
66
init_param_.a = param.a;
67
init_param_.b = param.b;
70
const String& GumbelDistributionFitter::getGnuplotFormula() const
72
return gnuplot_formula_;
75
int GumbelDistributionFitter::gumbelDistributionFitterf_(const gsl_vector* x, void* params, gsl_vector* f)
77
vector<DPosition<2> >* data = static_cast<vector<DPosition<2> >*>(params);
79
double a = gsl_vector_get (x, 0);
80
double b = gsl_vector_get (x, 1);
83
for (vector<DPosition<2> >::iterator it = data->begin(); it != data->end(); ++it)
85
double the_x = it->getX();
86
double z = exp((a - the_x)/b);
87
gsl_vector_set(f, i++, (z*exp(-1* z))/b - it->getY());
93
// compute Jacobian matrix for the different parameters
94
int GumbelDistributionFitter::gumbelDistributionFitterdf_(const gsl_vector* x, void* params, gsl_matrix* J)
96
vector<DPosition<2> >* data = static_cast<vector<DPosition<2> >*>(params);
98
double a = gsl_vector_get (x, 0);
99
double b = gsl_vector_get (x, 1);
101
for (vector<DPosition<2> >::iterator it = data->begin(); it != data->end(); ++it, ++i)
103
double the_x = it->getX();
104
double z = exp((a - the_x)/b);
105
double f = z* exp (-1 * z);
106
double part_dev_a = (f - pow(z,2) * exp(-1*z))/pow(b,2);
107
gsl_matrix_set(J, i, 0,part_dev_a);
108
double dev_z = ((the_x -a)/pow(b,2));
109
double cum = f*dev_z;
110
double part_dev_b = (( cum - z* cum)* b - f)/pow(b,2);
111
gsl_matrix_set(J,i,1,part_dev_b);
120
int GumbelDistributionFitter::gumbelDistributionFitterfdf_(const gsl_vector* x, void* params, gsl_vector* f, gsl_matrix* J)
122
gumbelDistributionFitterf_(x, params, f);
123
gumbelDistributionFitterdf_(x, params, J);
127
#ifdef GUMBEL_DISTRIBUTION_FITTER_VERBOSE
128
void GumbelDistributionFitter::printState_(size_t iter, gsl_multifit_fdfsolver * s)
130
printf ("iter: %3u x = % 15.8f % 15.8f "
133
gsl_vector_get(s->x, 0),
134
gsl_vector_get(s->x, 1),
135
gsl_blas_dnrm2(s->f));
139
GumbelDistributionFitter::GumbelDistributionFitResult GumbelDistributionFitter::fit(vector<DPosition<2> >& input)
141
const gsl_multifit_fdfsolver_type* T = NULL;
142
gsl_multifit_fdfsolver* s = NULL;
149
gsl_multifit_function_fdf f;
150
double x_init[2] = { init_param_.a, init_param_.b };
151
gsl_vector_view x = gsl_vector_view_array (x_init, p);
152
const gsl_rng_type * type = NULL;
157
type = gsl_rng_default;
158
r = gsl_rng_alloc (type);
160
f.f = &gumbelDistributionFitterf_;
161
f.df = &gumbelDistributionFitterdf_;
162
f.fdf = &gumbelDistributionFitterfdf_;
167
T = gsl_multifit_fdfsolver_lmsder;
168
s = gsl_multifit_fdfsolver_alloc (T, input.size(), p);
169
gsl_multifit_fdfsolver_set (s, &f, &x.vector);
171
#ifdef GUMBEL_DISTRIBUTION_FITTER_VERBOSE
172
printState_(iter, s);
178
status = gsl_multifit_fdfsolver_iterate (s);
180
#ifdef GUMBEL_DISTRIBUTION_FITTER_VERBOSE
181
printf ("status = %s\n", gsl_strerror (status));
182
printState_(iter, s);
189
status = gsl_multifit_test_delta (s->dx, s->x, 1e-4, 1e-4);
190
#ifdef GUMBEL_DISTRIBUTION_FITTER_VERBOSE
191
printf("Status = '%s'\n", gsl_strerror(status));
194
while (status == GSL_CONTINUE && iter < 1000);
196
#ifdef GUMBEL_DISTRIBUTION_FITTER_VERBOSE
197
printf("Final status = '%s'\n", gsl_strerror(status));
200
if (status!=GSL_SUCCESS)
203
gsl_multifit_fdfsolver_free(s);
205
throw Exception::UnableToFit(__FILE__,__LINE__,__PRETTY_FUNCTION__,"UnableToFit-GumbelDistributionFitter","Could not fit the gumbel distribution to the data");
208
// write the result in a GumbelDistributionFitResult struct
209
GumbelDistributionFitResult result;
210
result.a = gsl_vector_get(s->x, 0);
211
result.b = gsl_vector_get(s->x, 1);
213
// build a formula with the fitted parameters for gnuplot
214
stringstream formula;
215
formula <<"f(x)=" << "(1/" << result.b <<") * " << "exp(( "<< result.a<< "- x)/"<< result.b <<") * exp(-exp(("<<result.a<<" - x)/"<<result.b<<"))";
216
gnuplot_formula_ = formula.str();
218
#ifdef GUMBEL_DISTRIBUTION_FITTER_VERBOSE
219
cout << gnuplot_formula_ << endl;
223
gsl_multifit_fdfsolver_free (s);
229
} // namespace OpenMS