Linuxpops  3.01.04
Spectral Anaysis Package for Single Dish Data
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gaussfit.c
Go to the documentation of this file.
1 #include "ds_extern.h"
2 #include "ds_proto.h"
3 
4 #define GNPARM 100
5 
6 #define SWAP(a,b) {float temp=(a);(a)=(b);(b)=temp;}
7 
8 
9 int nrerror(error_text)
10 char *error_text;
11 {
12  log_msg(error_text);
13 
14  return(0);
15 }
16 
17 
18 
19 
20 
21 float *vector(nl,nh)
22 int nl,nh;
23 {
24  float *v;
25 
26  v = (float *)malloc((unsigned) (nh-nl+1)*sizeof(float));
27 
28  if(!v)
29  {
30  nrerror("allocation failure in vector()");
31  }
32 
33  return(v-nl);
34 }
35 
36 
37 
38 
39 int *ivector(nl,nh)
40 int nl,nh;
41 {
42  int *v;
43 
44  v= (int *)malloc((unsigned) (nh-nl+1)*sizeof(int));
45 
46  if(!v)
47  {
48  nrerror("allocation failure in ivector()");
49  }
50 
51  return(v-nl);
52 }
53 
54 
55 
56 
57 float **matrix(nrl,nrh,ncl,nch)
58 int nrl,nrh,ncl,nch;
59 {
60  int i;
61  float **m;
62 
63  m= (float **)malloc((unsigned) (nrh-nrl+1)*sizeof(float*));
64  if(!m)
65  nrerror("allocation failure 1 in matrix()");
66  m -= nrl;
67 
68  for(i=nrl;i<=nrh;i++)
69  {
70  m[i]=(float *) malloc((unsigned) (nch-ncl+1)*sizeof(float));
71  if(!m[i])
72  nrerror("allocation failure 2 in matrix()");
73  m[i] -= ncl;
74  }
75 
76  return(m);
77 }
78 
79 
80 int free_vector(v,nl)
81 float *v;
82 int nl;
83 {
84  free((char*) (v+nl));
85 
86  return(0);
87 }
88 
89 
90 int free_ivector(v,nl)
91 int *v,nl;
92 {
93  free((char*) (v+nl));
94 
95  return(0);
96 }
97 
98 
99 
100 int free_matrix(m,nrl,nrh,ncl)
101 float **m;
102 int nrl,nrh,ncl;
103 {
104  int i;
105 
106  for(i=nrh;i>=nrl;i--)
107  free((char*) (m[i]+ncl));
108  free((char*) (m+nrl));
109 
110  return(0);
111 }
112 
113 
114 
115 int gaussj(a,n,b,m)
116 float a[GNPARM+1][GNPARM+1],**b;
117 int n,m;
118 {
119  int *indxc,*indxr,*ipiv;
120  int i,icol,irow,j,k,l,ll;
121  float big,dum,pivinv;
122 
123  indxc=ivector(1,n);
124  indxr=ivector(1,n);
125  ipiv=ivector(1,n);
126  for(j=1;j<=n;j++)
127  ipiv[j]=0;
128  for(i=1;i<=n;i++)
129  {
130  big=0.0;
131  for(j=1;j<=n;j++)
132  if(ipiv[j] != 1)
133  for(k=1;k<=n;k++)
134  {
135  if(ipiv[k] == 0)
136  {
137  if(fabs(a[j][k]) >= big)
138  {
139  big=fabs(a[j][k]);
140  irow=j;
141  icol=k;
142  }
143  }
144  else
145  if(ipiv[k] > 1)
146  nrerror("GAUSSJ: Singular Matrix-1");
147  }
148  ++(ipiv[icol]);
149  if(irow != icol)
150  {
151  for(l=1;l<=n;l++)
152  SWAP(a[irow][l],a[icol][l])
153  for(l=1;l<=m;l++)
154  SWAP(b[irow][l],b[icol][l])
155  }
156  indxr[i]=irow;
157  indxc[i]=icol;
158  if(a[icol][icol] == 0.0)
159  nrerror("GAUSSJ: Singular Matrix-2");
160  pivinv=1.0/a[icol][icol];
161  a[icol][icol]=1.0;
162  for(l=1;l<=n;l++)
163  a[icol][l] *= pivinv;
164  for(l=1;l<=m;l++)
165  b[icol][l] *= pivinv;
166  for(ll=1;ll<=n;ll++)
167  if(ll != icol)
168  {
169  dum=a[ll][icol];
170  a[ll][icol]=0.0;
171  for(l=1;l<=n;l++)
172  a[ll][l] -= a[icol][l]*dum;
173  for(l=1;l<=m;l++)
174  b[ll][l] -= b[icol][l]*dum;
175  }
176  }
177  for(l=n;l>=1;l--)
178  {
179  if(indxr[l] != indxc[l])
180  for(k=1;k<=n;k++)
181  SWAP(a[k][indxr[l]],a[k][indxc[l]]);
182  }
183  free_ivector(ipiv,1);
184  free_ivector(indxr,1);
185  free_ivector(indxc,1);
186 
187  return(0);
188 }
189 
190 #undef SWAP
191 
192 
193 
194 
195 
196 int mrqmin(x,y,sig,ndata,a,ma,lista,mfit,covar,alpha,chisq,funcs,alamda)
197 float x[],y[],sig[],a[],covar[GNPARM+1][GNPARM+1],alpha[GNPARM+1][GNPARM+1],*chisq,*alamda;
198 int ndata,ma,lista[],mfit;
199 void (*funcs)();
200 {
201  int k,kk,j,ihit;
202  static float *da,*atry,**oneda,*beta,ochisq;
203 
204  if(*alamda < 0.0)
205  {
206  oneda=matrix(1,mfit,1,1);
207  atry=vector(1,ma);
208  da=vector(1,ma);
209  beta=vector(1,ma);
210  kk=mfit+1;
211  for(j=1;j<=ma;j++)
212  {
213  ihit=0;
214  for(k=1;k<=mfit;k++)
215  if(lista[k] == j)
216  ihit++;
217  if(ihit == 0)
218  lista[kk++]=j;
219  else
220  if(ihit > 1)
221  nrerror("Bad LISTA permutation in MRQMIN-1");
222  }
223  if(kk != ma+1)
224  nrerror("Bad LISTA permutation in MRQMIN-2");
225  *alamda=0.001;
226  mrqcof(x,y,sig,ndata,a,ma,lista,mfit,alpha,beta,chisq,funcs);
227  ochisq=(*chisq);
228  }
229  for(j=1;j<=mfit;j++)
230  {
231  for(k=1;k<=mfit;k++)
232  covar[j][k]=alpha[j][k];
233  covar[j][j]=alpha[j][j]*(1.0+(*alamda));
234  oneda[j][1]=beta[j];
235  }
236  gaussj(covar,mfit,oneda,1);
237  for(j=1;j<=mfit;j++)
238  da[j]=oneda[j][1];
239  if(*alamda == 0.0)
240  {
241  covsrt(covar,ma,lista,mfit);
242  free_vector(beta,1);
243  free_vector(da,1);
244  free_vector(atry,1);
245  free_matrix(oneda,1,mfit,1);
246 
247  return(0);
248  }
249  for(j=1;j<=ma;j++)
250  atry[j]=a[j];
251  for(j=1;j<=mfit;j++)
252  atry[lista[j]] = a[lista[j]]+da[j];
253  mrqcof(x,y,sig,ndata,atry,ma,lista,mfit,covar,da,chisq,funcs);
254  if(*chisq < ochisq)
255  {
256  *alamda *= 0.1;
257  ochisq=(*chisq);
258  for(j=1;j<=mfit;j++)
259  {
260  for(k=1;k<=mfit;k++)
261  alpha[j][k]=covar[j][k];
262  beta[j]=da[j];
263  a[lista[j]]=atry[lista[j]];
264  }
265  }
266  else
267  {
268  *alamda *= 10.0;
269  *chisq=ochisq;
270  }
271 
272  return(0);
273 }
274 
275 
276 
277 
278 int mrqcof(x,y,sig,ndata,a,ma,lista,mfit,alpha,beta,chisq,funcs)
279 float x[],y[],sig[],a[],alpha[GNPARM+1][GNPARM+1],beta[],*chisq;
280 int ndata,ma,lista[],mfit;
281 void (*funcs)();
282 {
283  int k,j,i;
284  float ymod,wt,sig2i,dy,*dyda;
285 
286  dyda=vector(1,ma);
287  for(j=1;j<=mfit;j++)
288  {
289  for(k=1;k<=j;k++)
290  alpha[j][k]=0.0;
291  beta[j]=0.0;
292  }
293  *chisq=0.0;
294  for(i=1;i<=ndata;i++)
295  {
296 /*
297  funcs(x[i],a,&ymod,dyda,ma);
298  */
299  funcs(x[i],a,&ymod,dyda);
300  sig2i=1.0/(sig[i]*sig[i]);
301  dy=y[i]-ymod;
302  for(j=1;j<=mfit;j++)
303  {
304  wt=dyda[lista[j]]*sig2i;
305  for(k=1;k<=j;k++)
306  alpha[j][k] += wt*dyda[lista[k]];
307  beta[j] += dy*wt;
308  }
309  (*chisq) += dy*dy*sig2i;
310  }
311  for(j=2;j<=mfit;j++)
312  for(k=1;k<=j-1;k++)
313  alpha[k][j]=alpha[j][k];
314  free_vector(dyda,1);
315 
316  return(0);
317 }
318 
319 
320 
321 int covsrt(covar,ma,lista,mfit)
322 float covar[GNPARM+1][GNPARM+1];
323 int ma,lista[],mfit;
324 {
325  int i,j;
326  float swap;
327 
328  for(j=1;j<ma;j++)
329  {
330  for(i=j+1;i<=ma;i++)
331  {
332  covar[i][j]=0.0;
333  }
334  }
335 
336  for(i=1;i<mfit;i++)
337  {
338  for(j=i+1;j<=mfit;j++)
339  {
340  if(lista[j] > lista[i])
341  {
342  covar[lista[j]][lista[i]]=covar[i][j];
343  }
344  else
345  {
346  covar[lista[i]][lista[j]]=covar[i][j];
347  }
348  }
349  }
350 
351  swap=covar[1][1];
352 
353  for(j=1;j<=ma;j++)
354  {
355  covar[1][j]=covar[j][j];
356  covar[j][j]=0.0;
357  }
358 
359  covar[lista[1]][lista[1]]=swap;
360 
361  for(j=2;j<=mfit;j++)
362  {
363  covar[lista[j]][lista[j]]=covar[1][j];
364  }
365 
366  for(j=2;j<=ma;j++)
367  {
368  for(i=1;i<=j-1;i++)
369  {
370  covar[i][j]=covar[j][i];
371  }
372  }
373 
374  return(0);
375 }
376 
377 
378 #ifdef USE_FIT_ROUTINE
379 
380 static float sqrarg;
381 
382 #define SQR(a) (sqrarg=(a),sqrarg*sqrarg)
383 
384 /*
385 int fit(x,y,ndata,sig,mwt,a,b,siga,sigb,chi2,q)
386 float x[],y[],sig[],*a,*b,*siga,*sigb,*chi2,*q;
387 int ndata,mwt;
388 {
389  int i;
390  float wt,t,sxoss,sx=0.0,sy=0.0,
391  st2=0.0,ss,sigdat;
392 
393  *b=0.0;
394  if(mwt)
395  {
396  ss=0.0;
397  for(i=1;i<=ndata;i++)
398  {
399  wt=1.0/SQR(sig[i]);
400  ss += wt;
401  sx += x[i]*wt;
402  sy += y[i]*wt;
403  }
404  }
405  else
406  {
407  for(i=1;i<=ndata;i++)
408  {
409  sx += x[i];
410  sy += y[i];
411  }
412  ss=ndata;
413  }
414  sxoss=sx/ss;
415  if(mwt)
416  {
417  for(i=1;i<=ndata;i++)
418  {
419  t=(x[i]-sxoss)/sig[i];
420  st2 += t*t;
421  *b += t*y[i]/sig[i];
422  }
423  }
424  else
425  {
426  for(i=1;i<=ndata;i++)
427  {
428  t=x[i]-sxoss;
429  st2 += t*t;
430  *b += t*y[i];
431  }
432  }
433  *b /= st2;
434  *a=(sy-sx*(*b))/ss;
435  *siga=sqrt((1.0+sx*sx/(ss*st2))/ss);
436  *sigb=sqrt(1.0/st2);
437  *chi2=0.0;
438  if(mwt == 0)
439  {
440  for(i=1;i<=ndata;i++)
441  *chi2 += SQR(y[i]-(*a)-(*b)*x[i]);
442  *q=1.0;
443  sigdat=sqrt((*chi2)/(ndata-2));
444  *siga *= sigdat;
445  *sigb *= sigdat;
446  }
447  else
448  {
449  for(i=1;i<=ndata;i++)
450  *chi2 += SQR((y[i]-(*a)-(*b)*x[i])/sig[i]);
451  *q=gammq(0.5*(ndata-2),0.5*(*chi2));
452  }
453 
454  return(0);
455 }
456 */
457 
458 #undef SQR
459 
460 #endif
461 
462 
463 float gammq(a,x)
464 float a,x;
465 {
466  float gamser,gammcf,gln;
467 
468  if(x < 0.0 || a <= 0.0)
469  nrerror("Invalid arguments in routine GAMMQ");
470  if(x < (a+1.0))
471  {
472  gser(&gamser,a,x,&gln);
473  return(1.0-gamser);
474  }
475  else
476  {
477  gcf(&gammcf,a,x,&gln);
478  return(gammcf);
479  }
480 
481  return(0.0);
482 }
483 
484 
485 
486 #define ITMAX 100
487 #define EPS 3.0e-7
488 
489 int gser(gamser,a, x,gln)
490 float *gamser, a, x, *gln;
491 {
492  int n;
493  float sum,del,ap;
494 
495  *gln=gammln(a);
496  if(x <= 0.0)
497  {
498  if(x < 0.0)
499  nrerror("x less than 0 in routine GSER");
500  *gamser=0.0;
501  return(0);
502  }
503  else
504  {
505  ap=a;
506  del=sum=1.0/a;
507  for(n=1;n<=ITMAX;n++)
508  {
509  ap += 1.0;
510  del *= x/ap;
511  sum += del;
512  if(fabs(del) < fabs(sum)*EPS)
513  {
514  *gamser=sum*exp(-x+a*log(x)-(*gln));
515  return(0);
516  }
517  }
518  nrerror("a too large, ITMAX too small in routine GSER");
519  return(1);
520  }
521 
522 }
523 
524 int gcf(gammcf,a,x,gln)
525 float *gammcf,a,x,*gln;
526 {
527  int n;
528  float gold=0.0,g,fac=1.0,b1=1.0;
529  float b0=0.0,anf,ana,an,a1,a0=1.0;
530 
531  *gln=gammln(a);
532  a1=x;
533  for(n=1;n<=ITMAX;n++)
534  {
535  an=(float) n;
536  ana=an-a;
537  a0=(a1+a0*ana)*fac;
538  b0=(b1+b0*ana)*fac;
539  anf=an*fac;
540  a1=x*a0+anf*a1;
541  b1=x*b0+anf*b1;
542  if(a1)
543  {
544  fac=1.0/a1;
545  g=b1*fac;
546  if(fabs((g-gold)/g) < EPS)
547  {
548  *gammcf=exp(-x+a*log(x)-(*gln))*g;
549  return(0);
550  }
551  gold=g;
552  }
553  }
554  nrerror("a too large, ITMAX too small in routine GCF");
555 
556  return(1);
557 }
558 
559 #undef ITMAX
560 #undef EPS
561 
562 
563 
564 float gammln(xx)
565 float xx;
566 {
567  double x,tmp,ser;
568  static double cof[6]={76.18009173,-86.50532033,24.01409822,
569  -1.231739516,0.120858003e-2,-0.536382e-5};
570  int j;
571 
572  x=xx-1.0;
573  tmp=x+5.5;
574  tmp -= (x+0.5)*log(tmp);
575  ser=1.0;
576  for(j=0;j<=5;j++)
577  {
578  x += 1.0;
579  ser += cof[j]/x;
580  }
581 
582  return( -tmp+log(2.50662827465*ser) );
583 }
584 
585 
586 
587 /*
588 Tom:
589  What follows is a pitiful attempt at C programming. It has
590 little chance of running, although I hope it demonstrates the
591 logic of the fitting algorithm. You might try to compile it and
592 clean up the gross syntax errors, then I'll help you get it
593 running next Monday. I was particularly unsure about how to pass
594 multiple return parameters out of functions. I know you have to
595 do it with pointers, but that's all Greek to me.
596 
597  To run the function "gauss_fit", you'll need to pass it the x
598 and y data arrays, and a first guess at the peak a[0], the center
599 position a[1], and the FWHM a[GNPARM+1]. The function will (should)
600 return new values of 'a'.
601 
602  It would be good to have a graphical display, at least during
603 the debugging stage, that shows the input data and the fitted
604 Gaussian. You can use the function 'fgauss' to generate the
605 computed gaussian.
606 
607  Good luck. You'll need it.
608 
609  Phil
610 
612 
613 */
614 
615 
616 /*
617  * Evaluate the Gaussian function y and its first partial
618  * derivatives dyda[] at a given x value, with supplied
619  * parameters a[].
620  */
621 void fgauss(x, a, y, dyda)
622 float x, *a, *y, *dyda;
623 {
624  float arg1, arg2, ex, fac;
625 
626  arg1 = -4. * log(2.0);
627  arg2 = (x - a[2]) / a[3];
628  ex = exp(arg1 * arg2 * arg2);
629  fac = a[1] * ex * arg1 * 2.0 * arg2;
630 
631  *y = a[1] * ex;
632 
633  dyda[1] = ex;
634  dyda[2] = -fac / a[3];
635  dyda[3] = -fac * arg2 / a[3];
636 
637  return;
638 }
639 
640 
641 /* Control the iterations of mrqmin. x and y are the input data array,
642  * sig is the array of standard deviations (if any), npts are the number
643  * of data points, and 'a' is the array of fitted parameters. When
644  * gauss_fit is first called, 'a' must contain the initial guesses for the
645  * parameters.
646  */
647 int gauss_fit(x, y,sig,npts, a)
648 float *x, *y, * sig, *a;
649 int npts;
650 {
651  float alamda= -1.0, chisq=0.0, chisq1, g, cvtest, conv_crit=0.001,
652  dyda[GNPARM+1], resid[GNPARM+1], alpha[GNPARM+1][GNPARM+1],
653  covar[GNPARM+1][GNPARM+1];
654  int ma=3, mfit=3, converged =0, i, j=1, niter=50, lista[GNPARM+1];
655 
656  lista[1] = 1;
657  lista[2] = 2;
658  lista[3] = 3;
659 
660  /* Calculate the CHI-SQUARED based on the initial-guess coefficients: */
661  for(i = 1; i <=npts; ++i) {
662  fgauss(x[i], a, &g, dyda);
663  resid[i] = y[i] - g;
664  chisq = chisq + resid[i] * resid[i];
665  }
666  /* Start the main iteration loop: */
667  while((j <= niter) && (converged == 0))
668  {
669 
670 /*
671 
672  log_msg("trying Interation %d",j);
673  log_msg("a[1] = %f, a[2] = %f, a[3] = %f", a[1], a[2] ,a[3]);
674  for(t=1;t<=npts;t++)
675  log_msg("x[%d] = %f, y[%d] = %f, sig[%d] = %f",
676  t,x[t], t, y[t], t, sig[t]);
677  */
678 
679  mrqmin(x,y,sig,npts,a,ma,lista,mfit,covar,alpha, &chisq1, (void (*)(void))fgauss, &alamda);
680  if((chisq1 < chisq) || (chisq1 < 0.001)) {
681  cvtest = fabs( (chisq1 - chisq) / chisq );
682  if(cvtest <= conv_crit)
683  converged = 1;
684  chisq = chisq1;
685  }
686  j++;
687  } /* If converged, call mrqmin with alamda = 0
688  to get covariance and curvature matrices. */
689  if(converged) {
690  alamda = 0.0;
691  mrqmin(x,y,sig,npts,a,ma,lista,mfit,covar,alpha, &chisq1, (void (*)(void))fgauss, &alamda);
692  return(1);
693  }
694 
695  return(0);
696 }
int xx()
Definition: linuxpops.c:605
double sqrarg
Definition: gridmap.c:65
int nrerror()
void fgauss()
int gcf()
int gauss_fit()
int mrqmin()
int gaussj()
int free_vector()
int * ivector(int nl, int nh)
Definition: gaussfit.c:39
double gammln()
int mrqcof()
double sum
Definition: beam.h:5
int log_msg(const char *fmt,...)
#define dy(i)
double * vector()
int free_ivector()
#define SWAP(a, b)
Definition: gaussfit.c:6
int gser()
int covsrt()
int free_matrix()
double ** matrix()
#define ITMAX
Definition: gaussfit.c:486
#define EPS
Definition: gaussfit.c:487
#define GNPARM
Definition: gaussfit.c:4
double gammq()
#define m(i)