Hi all,

I'm new to GSL and numerical methods so please bear with me. I'm using GSL-2.1.

I'm trying to fit a 3-peak gaussian curve onto experiment data that I have (800W5-95kv_ROI.txt). I started from expfit.c and nlfit.c and modified the code to handle gauss curve. For my initial tests I also used code/data from test_gaussian.c. I've played around with the test set and managed to get proper amplitude, sigma and peak location(s), also when extending test set to hold three peaks (copies of first) and code to handle three peaks.

When using the real data of some 240 points, I'm seeing weird behavior. Solver bails out after 1st iteration and I get my initial guessed parameters back, unchanged.

If I fiddle with the data set a bit to make all the points between the peaks near zero I get better results, bat still good enough.

Maybe it is worth noting that I also have some sample Matlab code that manages to find the fit on the presented data set. It is using code from http://www2.imm.dtu.dk/projects/immoptibox/.

I'm attaching the modified GSL code and real data set if someone might be able to help out.

Thanks in advance,
Hinko
646.01843       -41
646.05176       -21
646.08502       0
646.11835       -12
646.15167       -24
646.185 1
646.21826       -22
646.25159       -15
646.28491       -21
646.31818       -10
646.3515        -15
646.38483       -7
646.41809       -12
646.45142       -11
646.48474       -15
646.51801       3
646.55133       -6
646.58459       5
646.61792       -5
646.65118       -17
646.68451       -15
646.71777       -20
646.7511        -21
646.78436       8
646.81769       -5
646.85095       13
646.88428       -1
646.91754       13
646.95081       -2
646.98413       -17
647.0174        -10
647.05066       -4
647.08398       -12
647.11725       -13
647.15051       5
647.18384       -16
647.2171        6
647.25037       10
647.28363       52
647.31696       105
647.35022       149
647.38348       297
647.41675       421
647.45001       589
647.48328       724
647.5166        907
647.54987       902
647.58313       927
647.61639       906
647.64966       768
647.68292       655
647.71619       515
647.74945       367
647.78271       246
647.81598       152
647.84924       125
647.88251       68
647.91577       30
647.94904       36
647.9823        20
648.01556       -4
648.04883       17
648.08203       32
648.1153        23
648.14856       63
648.18182       60
648.21509       78
648.24835       70
648.28156       60
648.31482       45
648.34808       46
648.38135       35
648.41455       59
648.44781       32
648.48108       49
648.51428       39
648.54755       11
648.58081       24
648.61401       28
648.64728       30
648.68048       36
648.71375       18
648.74695       19
648.78021       11
648.81348       23
648.84668       15
648.87994       19
648.91315       21
648.94635       9
648.97961       21
649.01282       -8
649.04608       8
649.07928       -13
649.11255       3
649.14575       30
649.17896       10
649.21222       20
649.24542       -16
649.27863       10
649.31189       15
649.34509       -2
649.3783        17
649.4115        12
649.44476       20
649.47797       5
649.51117       16
649.54437       6
649.57758       5
649.61084       11
649.64404       9
649.67725       46
649.71045       27
649.74365       30
649.77686       57
649.81006       111
649.84326       197
649.87646       433
649.90967       824
649.94287       1459
649.97607       2391
650.00928       3431
650.04248       4442
650.07568       5232
650.10889       5603
650.14209       5522
650.17529       5059
650.2085        4381
650.24164       3440
650.27484       2586
650.30804       1777
650.34125       1141
650.37445       737
650.40765       538
650.4408        407
650.474 404
650.5072        370
650.54034       395
650.57355       368
650.60675       397
650.63995       386
650.6731        372
650.7063        371
650.73944       364
650.77264       324
650.80585       316
650.83899       328
650.87219       307
650.90533       279
650.93854       291
650.97168       277
651.00488       303
651.03802       395
651.07123       602
651.10437       944
651.13757       1439
651.17072       1975
651.20392       2385
651.23706       2657
651.2702        2627
651.30341       2486
651.33655       2193
651.36969       1763
651.40289       1419
651.43604       971
651.46918       668
651.50232       472
651.53552       344
651.56866       330
651.60181       334
651.63495       302
651.66815       297
651.70129       295
651.73444       270
651.76758       277
651.80072       270
651.83386       253
651.867 247
651.90015       236
651.93329       232
651.96643       230
651.99957       200
652.03271       204
652.06586       175
652.099 214
652.13214       184
652.16528       184
652.19843       161
652.23157       195
652.26471       164
652.29785       171
652.33099       161
652.36414       159
652.39728       167
652.43036       140
652.4635        152
652.49664       185
652.52979       169
652.56293       149
652.59601       158
652.62915       173
652.66229       132
652.69537       145
652.72852       165
652.76166       146
652.79474       139
652.82788       132
652.86102       176
652.8941        138
652.92725       148
652.96033       132
652.99347       123
653.02655       153
653.05969       125
653.09277       116
653.12592       106
653.159 130
653.19214       143
653.22522       155
653.25836       148
653.29144       120
653.32458       141
653.35767       163
653.39075       143
653.42389       124
653.45697       145
653.49005       145
653.52319       114
653.55627       110
653.58936       104
653.62244       130
653.65558       123
653.68866       125
653.72174       119
653.75482       141
653.7879        98
653.82098       111
653.85413       141
653.88721       157
653.92029       165
653.95337       191
/* expfit.c -- model functions for exponential + background */

struct data {
  size_t n;
  double * y;
};

int
expb_f (const gsl_vector * x, void *data, gsl_vector * f)
{
  size_t n = ((struct data *)data)->n;
  double *y = ((struct data *)data)->y;

  double A = gsl_vector_get (x, 0);
  double lambda = gsl_vector_get (x, 1);
  double b = gsl_vector_get (x, 2);

  size_t i;

  for (i = 0; i < n; i++)
    {
      /* Model Yi = A * exp(-lambda * i) + b */
      double t = i;
      double Yi = A * exp (-lambda * t) + b;
      gsl_vector_set (f, i, Yi - y[i]);
    }

  return GSL_SUCCESS;
}

int
gaussian_f1peak (const gsl_vector * x, void *data, gsl_vector * f)
{
  size_t n = ((struct data *)data)->n;
  double *y = ((struct data *)data)->y;
  // amplitude
  double x1 = gsl_vector_get(x, 0);
  // sigma
  double x2 = gsl_vector_get(x, 1);
  // peak
  double x3 = gsl_vector_get(x, 2);
  size_t i;

  for (i = 0; i < n; ++i)
    {
//      double ti = (7.0 - i) / 2.0;
      double ti = (x3 - i) / 2.0;
      double yi = y[i];
//      double term = ti - x3;
      double term = ti;
      double fi = x1 * exp(-x2*term*term/2.0) - yi;
      gsl_vector_set(f, i, fi);
    }

  return GSL_SUCCESS;
}

int
gaussian_f2peak (const gsl_vector * x, void *data, gsl_vector * f)
{
  size_t n = ((struct data *)data)->n;
  double *y = ((struct data *)data)->y;
  // amplitude, sigma, peak
  double x11 = gsl_vector_get(x, 0);
  double x12 = gsl_vector_get(x, 1);
  double x13 = gsl_vector_get(x, 2);
  double x21 = gsl_vector_get(x, 3);
  double x22 = gsl_vector_get(x, 4);
  double x23 = gsl_vector_get(x, 5);
  size_t i;

  for (i = 0; i < n; ++i)
    {
      double ti = (x13 - i) / 2.0;
//	  double ti = i;
      double yi = y[i];
//      double term = ti - x3;
      double term = ti;
      double fi = x11 * exp(-x12*term*term/2.0);

      ti = (x23 - i) / 2.0;
      term = ti;
      fi += x21 * exp(-x22*term*term/2.0);

      fi -= yi;
      gsl_vector_set(f, i, fi);
    }

  return GSL_SUCCESS;
}

int
gaussian_f (const gsl_vector * x, void *data, gsl_vector * f)
{
  size_t n = ((struct data *)data)->n;
  double *y = ((struct data *)data)->y;
  // amplitude, sigma, peak
  double x11 = gsl_vector_get(x, 0);
  double x12 = gsl_vector_get(x, 1);
  double x13 = gsl_vector_get(x, 2);
  double x21 = gsl_vector_get(x, 3);
  double x22 = gsl_vector_get(x, 4);
  double x23 = gsl_vector_get(x, 5);
  double x31 = gsl_vector_get(x, 6);
  double x32 = gsl_vector_get(x, 7);
  double x33 = gsl_vector_get(x, 8);
  size_t i;

  for (i = 0; i < n; ++i)
    {
      double ti = (x13 - i) / 2.0;
//	  double ti = i;
      double yi = y[i];
//      double term = ti - x3;
      double term = ti;
      double fi = x11 * exp(-x12*term*term/2.0);

      ti = (x23 - i) / 2.0;
      term = ti;
      fi += x21 * exp(-x22*term*term/2.0);

      ti = (x33 - i) / 2.0;
      term = ti;
      fi += x31 * exp(-x32*term*term/2.0);

      fi -= yi;
      gsl_vector_set(f, i, fi);
    }

  return GSL_SUCCESS;
}

int
expb_df (const gsl_vector * x, void *data, 
         gsl_matrix * J)
{
  size_t n = ((struct data *)data)->n;

  double A = gsl_vector_get (x, 0);
  double lambda = gsl_vector_get (x, 1);

  size_t i;

  for (i = 0; i < n; i++)
    {
      /* Jacobian matrix J(i,j) = dfi / dxj, */
      /* where fi = (Yi - yi)/sigma[i],      */
      /*       Yi = A * exp(-lambda * i) + b  */
      /* and the xj are the parameters (A,lambda,b) */
      double t = i;
      double e = exp(-lambda * t);
      gsl_matrix_set (J, i, 0, e); 
      gsl_matrix_set (J, i, 1, -t * A * e);
      gsl_matrix_set (J, i, 2, 1.0);
    }
  return GSL_SUCCESS;
}
all:
        $(CC) -c -Wall -O0 -ggdb3 -I${HOME}/workspace/gsl-2.1/build/include 
nlfit.c -o nlfit.o
        $(CC) nlfit.o -L${HOME}/workspace/gsl-2.1/build/lib -lgsl -lgslcblas 
-lm -o nlfit

clean:
        rm nlfit *.o
#include <stdlib.h>
#include <stdio.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_multifit_nlin.h>

#include "expfit.c"

/* number of data points to fit */
//#define N 40
#define N 240
#define P 9

//static double gaussian_Y[N] = {
//0.0009, 0.0044, 0.0175, 0.0540, 0.1295, 0.2420, 0.3521, 0.3989,
//0.3521, 0.2420, 0.1295, 0.0540, 0.0175, 0.0044, 0.0009,
//0.0001, 0.0001, 0.0001,
//0.0009, 0.0044, 0.0175, 0.0540, 0.1295, 0.2420, 0.3521, 0.3989,
//0.3521, 0.2420, 0.1295, 0.0540, 0.0175, 0.0044, 0.0009,
//0.0001, 0.0001, 0.0001,
//0.0009, 0.0044, 0.0175, 0.0540, 0.1295, 0.2420, 0.3521, 0.3989,
//0.3521, 0.2420, 0.1295, 0.0540, 0.0175, 0.0044, 0.0009
//};

static double gaussian_Y[N] = {0};
static double gaussian_X[N] = {0};

int load(char *fname, double *x, double *y, int npoints) {
	FILE *fp;
	int i;

	/* Save data for simple plotting with gnuplot */
	fp = fopen(fname, "r");
	if (! fp) {
		perror("fopen(): ");
		return -1;
	}

	i = 0;
	while(!feof(fp)) {
		if (i >= npoints) {
			break;
		}
		fscanf(fp, "%lf\t%lf\n", &x[i], &y[i]);
		i++;
	}
	fclose(fp);

	printf("read %d / %d points\n", i, npoints);
	return 0;
}

int
main (void)
{
  const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder;
  gsl_multifit_fdfsolver *s;
  int status, info;
  size_t i;
  const size_t n = N;
  const size_t p = P;

  gsl_matrix *J = gsl_matrix_alloc(n, p);
  gsl_matrix *covar = gsl_matrix_alloc (p, p);
  double y[N], weights[N];
  struct data d = { n, y };
  gsl_multifit_function_fdf f;
//  double x_init[3] = { 1.0, 0.0, 0.0 };
// amplitude, sigma, peak
//  double x_init[3] = { 0.4, 1.0, 0.0 };
//  double x_init[P] = { 0.4, 1.0, 7.0, 0.4, 1.0, 22.0 };
//  double x_init[P] = { 0.4, 1.0, 7.0, 0.4, 1.0, 22.0, 0.4, 1.0, 37.0 };
//  double x_init[P] = { 0.8, 1.0, 7.0, 1.2, 1.0, 25.0, 0.4, 1.0, 40.0 };
  double x_init[P] = { 870.0, 5.0, 49.0, 5530.0, 5.0, 125.0, 2554.0, 5.0, 160.0 };
  gsl_vector_view x = gsl_vector_view_array (x_init, p);
  gsl_vector_view w = gsl_vector_view_array(weights, n);
  const gsl_rng_type * type;
  gsl_rng * r;
  gsl_vector *res_f;
  double chi, chi0;

  const double xtol = 1e-20;
  const double gtol = 1e-20;
  const double ftol = 0.0;

  load("./800W5-95kv_ROI.txt", gaussian_X, gaussian_Y, N);

  gsl_rng_env_setup();

  type = gsl_rng_default;
  r = gsl_rng_alloc (type);

//  f.f = &expb_f;
//  f.df = &expb_df;   /* set to NULL for finite-difference Jacobian */
  // for gaussian
  f.f = &gaussian_f;
  f.df = NULL;

  f.n = n;
  f.p = p;
  f.params = &d;

  /* This is the data to be fitted */

  for (i = 0; i < n; i++)
    {
      //double t = i;
      //double yi = 1.0 + 5 * exp (-0.1 * t);
      //double si = 0.1 * yi;
//      double si = 0.1 * gaussian_Y[i];
      //double dy = gsl_ran_gaussian(r, si);

//      weights[i] = 1.0 / (si * si);
      //y[i] = yi + dy;
//      y[i] = gaussian_Y[i];

      double yi = gaussian_Y[i];
//      if (i < 15) {
//    	  yi *= 2;
//      } else if (i < 30) {
//    	  yi *= 3;
//      } else {
//    	  yi *= 1;
//      }
//      if (yi < 500) {
//    	  yi = 0.0009;
//      }
      y[i] = yi;
      double si = 0.1 * yi;
      weights[i] = 1.0 / (si * si);

      printf ("data: %zu %g %g\n", i, y[i], si);
    };

  s = gsl_multifit_fdfsolver_alloc (T, n, p);

  /* initialize solver with starting point and weights */
  gsl_multifit_fdfsolver_wset (s, &f, &x.vector, &w.vector);

  /* compute initial residual norm */
  res_f = gsl_multifit_fdfsolver_residual(s);
  chi0 = gsl_blas_dnrm2(res_f);

  /* solve the system with a maximum of 2000 iterations */
  status = gsl_multifit_fdfsolver_driver(s, 2000, xtol, gtol, ftol, &info);

  gsl_multifit_fdfsolver_jac(s, J);
  gsl_multifit_covar (J, 0.0, covar);

  /* compute final residual norm */
  chi = gsl_blas_dnrm2(res_f);

#define FIT(i) gsl_vector_get(s->x, i)
#define ERR(i) sqrt(gsl_matrix_get(covar,i,i))

  fprintf(stderr, "summary from method '%s'\n",
          gsl_multifit_fdfsolver_name(s));
  fprintf(stderr, "number of iterations: %zu\n",
          gsl_multifit_fdfsolver_niter(s));
  fprintf(stderr, "function evaluations: %zu\n", f.nevalf);
  fprintf(stderr, "Jacobian evaluations: %zu\n", f.nevaldf);
  fprintf(stderr, "reason for stopping: %s\n",
          (info == 1) ? "small step size" : "small gradient");
  fprintf(stderr, "initial |f(x)| = %g\n", chi0);
  fprintf(stderr, "final   |f(x)| = %g\n", chi);

  { 
    double dof = n - p;
    double c = GSL_MAX_DBL(1, chi / sqrt(dof)); 

    fprintf(stderr, "chisq/dof = %g\n",  pow(chi, 2.0) / dof);

    for (i = 0; i < p; i +=3) {
		fprintf (stderr, "Amp      = %.5f +/- %.5f\n", FIT(i), c*ERR(i));
		fprintf (stderr, "sigma    = %.5f +/- %.5f\n", FIT(i+1), c*ERR(i+1));
		fprintf (stderr, "peak     = %.5f +/- %.5f\n", FIT(i+2), c*ERR(i+2));
    }
  }

  fprintf (stderr, "status = %s\n", gsl_strerror (status));

  gsl_multifit_fdfsolver_free (s);
  gsl_matrix_free (covar);
  gsl_matrix_free (J);
  gsl_rng_free (r);
  return 0;
}
~/workspace/gslfit$ ./nlfit 
read 240 / 240 points
data: 0 -41 -4.1
data: 1 -21 -2.1
data: 2 0 0
data: 3 -12 -1.2
data: 4 -24 -2.4
data: 5 1 0.1
data: 6 -22 -2.2
data: 7 -15 -1.5
data: 8 -21 -2.1
data: 9 -10 -1
data: 10 -15 -1.5
data: 11 -7 -0.7
data: 12 -12 -1.2
data: 13 -11 -1.1
data: 14 -15 -1.5
data: 15 3 0.3
data: 16 -6 -0.6
data: 17 5 0.5
data: 18 -5 -0.5
data: 19 -17 -1.7
data: 20 -15 -1.5
data: 21 -20 -2
data: 22 -21 -2.1
data: 23 8 0.8
data: 24 -5 -0.5
data: 25 13 1.3
data: 26 -1 -0.1
data: 27 13 1.3
data: 28 -2 -0.2
data: 29 -17 -1.7
data: 30 -10 -1
data: 31 -4 -0.4
data: 32 -12 -1.2
data: 33 -13 -1.3
data: 34 5 0.5
data: 35 -16 -1.6
data: 36 6 0.6
data: 37 10 1
data: 38 52 5.2
data: 39 105 10.5
data: 40 149 14.9
data: 41 297 29.7
data: 42 421 42.1
data: 43 589 58.9
data: 44 724 72.4
data: 45 907 90.7
data: 46 902 90.2
data: 47 927 92.7
data: 48 906 90.6
data: 49 768 76.8
data: 50 655 65.5
data: 51 515 51.5
data: 52 367 36.7
data: 53 246 24.6
data: 54 152 15.2
data: 55 125 12.5
data: 56 68 6.8
data: 57 30 3
data: 58 36 3.6
data: 59 20 2
data: 60 -4 -0.4
data: 61 17 1.7
data: 62 32 3.2
data: 63 23 2.3
data: 64 63 6.3
data: 65 60 6
data: 66 78 7.8
data: 67 70 7
data: 68 60 6
data: 69 45 4.5
data: 70 46 4.6
data: 71 35 3.5
data: 72 59 5.9
data: 73 32 3.2
data: 74 49 4.9
data: 75 39 3.9
data: 76 11 1.1
data: 77 24 2.4
data: 78 28 2.8
data: 79 30 3
data: 80 36 3.6
data: 81 18 1.8
data: 82 19 1.9
data: 83 11 1.1
data: 84 23 2.3
data: 85 15 1.5
data: 86 19 1.9
data: 87 21 2.1
data: 88 9 0.9
data: 89 21 2.1
data: 90 -8 -0.8
data: 91 8 0.8
data: 92 -13 -1.3
data: 93 3 0.3
data: 94 30 3
data: 95 10 1
data: 96 20 2
data: 97 -16 -1.6
data: 98 10 1
data: 99 15 1.5
data: 100 -2 -0.2
data: 101 17 1.7
data: 102 12 1.2
data: 103 20 2
data: 104 5 0.5
data: 105 16 1.6
data: 106 6 0.6
data: 107 5 0.5
data: 108 11 1.1
data: 109 9 0.9
data: 110 46 4.6
data: 111 27 2.7
data: 112 30 3
data: 113 57 5.7
data: 114 111 11.1
data: 115 197 19.7
data: 116 433 43.3
data: 117 824 82.4
data: 118 1459 145.9
data: 119 2391 239.1
data: 120 3431 343.1
data: 121 4442 444.2
data: 122 5232 523.2
data: 123 5603 560.3
data: 124 5522 552.2
data: 125 5059 505.9
data: 126 4381 438.1
data: 127 3440 344
data: 128 2586 258.6
data: 129 1777 177.7
data: 130 1141 114.1
data: 131 737 73.7
data: 132 538 53.8
data: 133 407 40.7
data: 134 404 40.4
data: 135 370 37
data: 136 395 39.5
data: 137 368 36.8
data: 138 397 39.7
data: 139 386 38.6
data: 140 372 37.2
data: 141 371 37.1
data: 142 364 36.4
data: 143 324 32.4
data: 144 316 31.6
data: 145 328 32.8
data: 146 307 30.7
data: 147 279 27.9
data: 148 291 29.1
data: 149 277 27.7
data: 150 303 30.3
data: 151 395 39.5
data: 152 602 60.2
data: 153 944 94.4
data: 154 1439 143.9
data: 155 1975 197.5
data: 156 2385 238.5
data: 157 2657 265.7
data: 158 2627 262.7
data: 159 2486 248.6
data: 160 2193 219.3
data: 161 1763 176.3
data: 162 1419 141.9
data: 163 971 97.1
data: 164 668 66.8
data: 165 472 47.2
data: 166 344 34.4
data: 167 330 33
data: 168 334 33.4
data: 169 302 30.2
data: 170 297 29.7
data: 171 295 29.5
data: 172 270 27
data: 173 277 27.7
data: 174 270 27
data: 175 253 25.3
data: 176 247 24.7
data: 177 236 23.6
data: 178 232 23.2
data: 179 230 23
data: 180 200 20
data: 181 204 20.4
data: 182 175 17.5
data: 183 214 21.4
data: 184 184 18.4
data: 185 184 18.4
data: 186 161 16.1
data: 187 195 19.5
data: 188 164 16.4
data: 189 171 17.1
data: 190 161 16.1
data: 191 159 15.9
data: 192 167 16.7
data: 193 140 14
data: 194 152 15.2
data: 195 185 18.5
data: 196 169 16.9
data: 197 149 14.9
data: 198 158 15.8
data: 199 173 17.3
data: 200 132 13.2
data: 201 145 14.5
data: 202 165 16.5
data: 203 146 14.6
data: 204 139 13.9
data: 205 132 13.2
data: 206 176 17.6
data: 207 138 13.8
data: 208 148 14.8
data: 209 132 13.2
data: 210 123 12.3
data: 211 153 15.3
data: 212 125 12.5
data: 213 116 11.6
data: 214 106 10.6
data: 215 130 13
data: 216 143 14.3
data: 217 155 15.5
data: 218 148 14.8
data: 219 120 12
data: 220 141 14.1
data: 221 163 16.3
data: 222 143 14.3
data: 223 124 12.4
data: 224 145 14.5
data: 225 145 14.5
data: 226 114 11.4
data: 227 110 11
data: 228 104 10.4
data: 229 130 13
data: 230 123 12.3
data: 231 125 12.5
data: 232 119 11.9
data: 233 141 14.1
data: 234 98 9.8
data: 235 111 11.1
data: 236 141 14.1
data: 237 157 15.7
data: 238 165 16.5
data: 239 191 19.1
summary from method 'lmsder'
number of iterations: 1
function evaluations: 20
Jacobian evaluations: 0
reason for stopping: small gradient
initial |f(x)| = nan
final   |f(x)| = nan
chisq/dof = nan
Amp      = 870.00000 +/- nan
sigma    = 5.00000 +/- nan
peak     = 49.00000 +/- -nan
Amp      = 5530.00000 +/- nan
sigma    = 5.00000 +/- nan
peak     = 125.00000 +/- nan
Amp      = 2554.00000 +/- nan
sigma    = 5.00000 +/- nan
peak     = 160.00000 +/- nan
status = success

Reply via email to