/*LINTLIBRARY*/ /* gauss.c This code provides gaussian fitting routines. Copyright (C) 1997 Karl Glazebrook and Alison Offer Real code Note it is not clear to me that this code is fully debugged. The reason I say that is because I tried using the linear eqn solving routines called elsewhere and they were giving erroneous results. So steal from this code with caution! However it does give good fits to reasonable looking gaussians and tests show correct parameters. KGB 29/Oct/2002 */ #include #include #define NPAR 3 #define MAXITER 1000 /* Malloc 2D ptr array e.g. a[nx][ny] */ static double **malloc2D (int nx, int ny) { int i; double **p; p = (double**) malloc( nx*sizeof(double*) ); /* 1D array of ptrs p[i] */ if (p==NULL) return NULL; for (i=0;i1) { for (irow=1; irow<=icol-1; irow++) { sum = x[irow-1][icol-1]; for (isum=1; isum<=irow-1; isum++) sum -= x[irow-1][isum-1]*x[isum-1][irow-1]; x[irow-1][icol-1] = sum; } } /* L - matrix plus diagonal element of U matrix */ xmax = 0; ipivot = icol; for (irow=icol; irow<=n; irow++) { sum = x[irow-1][icol-1]; if (icol>1) { for(isum=1; isum<=icol-1; isum++) sum -= x[irow-1][isum-1] * x[isum-1][icol-1]; } if (fabs(sum)>xmax) { xmax = sum; ipivot = irow; } x[irow-1][icol-1] = sum; } /* if xmax is very small replace by epsilon to avoid dividing by zero */ if (fabs(xmax)j][j] is L-matrix (diagonal elements are unity) iorder is the permutation of the rows b is the input vector, d is the solution vector */ static void lineq (int n, int ndim, double x[NPAR][NPAR], double b[NPAR], double d[NPAR], int iorder[NPAR]) { int i,isum; double sum; /* solving X.b = d ==> (L.U).b = d or L.(U.b) = d first re-order the vector */ for (i=1; i<=n; i++) d[i-1] = b[iorder[i-1]-1]; /* first find (U.b) */ for(i=2; i<=n; i++) { sum = d[i-1]; for (isum=1; isum<=i-1; isum++) sum -= x[i-1][isum-1] * d[isum-1]; d[i-1] = sum; } /* Now fill out d (solution of X.b) by back substitution */ d[n-1] /= x[n-1][n-1]; for (i=n-1; i>=1; i--){ sum = d[i-1]; for (isum=i+1; isum<=n; isum++) sum -= x[i-1][isum-1] * d[isum-1]; d[i-1] = sum / x[i-1][i-1]; } } /* ======================================================================== My C version of Alison's subroutine to fit a non-linear functions using the Levenberg-Marquardt algorithm input: npoints = number of data points npar = number of parameters in fit par = initial estimates of parameters sigma = errors on data (sigma^2) output: par = output parameters r = residuals (y(i) - yfit(i)) a = estimated covariance matrix of std errs in fitted params. */ static int marquardt (int npoints, int npar, double*x, double *y, double* sig, double par[NPAR], double* r, double a[NPAR][NPAR]) { int i,k, done, decrease, niter; int iorder[NPAR]; double *yfit, **d, **d2, tmp; double par2[NPAR], delta[NPAR], b[NPAR], aprime[NPAR][NPAR]; double lambda, chisq, chisq2, eps=0.001, lamfac=2.0; /* Memory allocation */ yfit = (double*) malloc( npoints*sizeof(double)); if (yfit==NULL) return(1); d = malloc2D( npoints, NPAR); if (d==NULL) { free(yfit); return(1); } d2 = malloc2D( npoints, NPAR); if (d2==NULL) { free(yfit); free2D(d,npoints,NPAR); return(1); } /* Not enough points */ if (npoints < npar) { free(yfit); free2D(d,npoints,NPAR); free2D(d2,npoints,NPAR); return(2); } lambda = 0.001; done = 0; decrease = 0; niter = 1; /* Get the value for the initial fit and the value of the derivatives for the current estimate of the parameters */ funct(npoints, npar, x, yfit, d, par); /* Calculate chi^2 */ chisq = 0; for (k=0; kMAXITER) { free(yfit); free2D(d,npoints,NPAR); free2D(d2,npoints,NPAR); return(3); } } /* Success!!! - compute residual and covariance matrix then return first calculating inverse of aprime */ for (i=0; i