/* Steven Andrews, 9/98; updated 3/02 */ /* Basis functions for spectral fitting */ /* See documentation called BasisFn doc */ /* Copyright 2003 by Steven Andrews. Permission is granted for non-commercial use of and modifications to the code. */ #include #include #include #include #include #include "string2.h" #include "math2.h" #include "Set.h" #include "Spectra.h" #include "BasisFn.h" #include "BasisFns.h" #include "Rn.h" #include "Plot.h" #include "random.h" #include "RnLU.h" #include "RnSort.h" #include "Utility.h" #include "SpectFit.h" #include "DiskIO.h" #include "VoidComp.h" #define CHECK(A) {if(!(A)) goto failure;} set basisfns=NULL; basisptr BasisAlloc(int n) { basisptr b; int i; if(n<1) return NULL; CHECK(b=(basisptr) malloc(sizeof(struct basisfn))); b->name[0]='\0'; b->proc[0]='\0'; b->color[0]='g'; b->color[1]='\0'; b->desc[0]='\0'; b->addr=NULL; b->model=NULL; b->n=n; b->param=b->pold=b->paramlo=b->paramhi=b->scratch=NULL; b->eqn=b->pname=NULL; b->freeze=NULL; b->isspec=0; b->spec=NULL; CHECK(b->param=allocV(n)); CHECK(b->pold=allocV(n)); CHECK(b->paramlo=allocV(n)); CHECK(b->paramhi=allocV(n)); CHECK(b->eqn=(char **) calloc(n,sizeof(char *))); for(i=0;ieqn[i]=NULL; CHECK(b->pname=(char **) calloc(n,sizeof(char *))); for(i=0;ipname[i]=NULL; CHECK(b->freeze=(int *) calloc(n,sizeof(int))); CHECK(b->scratch=allocV(n)); for(i=0;iparam[i]=b->pold[i]=0; b->paramlo[i]=-FLT_MAX; b->paramhi[i]=FLT_MAX; CHECK(b->eqn[i]=EmptyString()); CHECK(b->pname[i]=EmptyString()); b->freeze[i]=0; b->scratch[i]=0; } return b; failure: BasisFree(b); return NULL; } void BasisFree(basisptr b) { int i; if(!b) return; if(b->param) freeV(b->param); if(b->pold) freeV(b->pold); if(b->paramlo) freeV(b->paramlo); if(b->paramhi) freeV(b->paramhi); if(b->eqn) { for(i=0;in;i++) if(b->eqn[i]) free(b->eqn[i]); free(b->eqn); } if(b->pname) { for(i=0;in;i++) if(b->pname[i]) free(b->pname[i]); free(b->pname); } if(b->freeze) free(b->freeze); return; } modelptr ModelAlloc(sptr s) { modelptr m; m=(modelptr) malloc(sizeof(struct modeltype)); if(!m) return NULL; m->name[0]='\0'; m->file[0]='\0'; m->color[0]='r'; m->color[1]='\0'; m->spec=s; m->uncert=NULL; m->basis=NULL; m->np=0; m->sigma=0; if(s) { m->xmin=minV(s->x,s->n); m->xmax=maxV(s->x,s->n); m->dx=(m->xmax-m->xmin)/(s->n>20?s->n-1:20); } else { m->xmin=0; m->xmax=10; m->dx=0.5; } m->covar=NULL; m->basis=SetAlloc(&StringCmp,NULL); if(!m->basis) {ModelFree(m);return NULL;} return m; } void ModelFree(modelptr m) { void *x,*k; struct scell *trace; if(!m) return; if(m->basis) for(trace=SetNext(NULL,&k,&x,m->basis);trace;trace=SetNext(trace,&k,&x,m->basis)) BasisFree((basisptr)x); SetFree(m->basis,0,0); if(m->covar) freeM(m->covar); free(m); return; } int CheckBasis(basisptr b,modelptr m) { void *x,*k; struct scell *trace; int i,er; er=0; if(b) { if(!b->isspec) er=0; else if(b->isspec==1&&b->spec&&!b->spec->cmplx) er=0; else if(!b->spec) er=16; else if(b->isspec==1&&b->spec->cmplx) er=8; else if(b->isspec==2&&!b->spec->cmplx) er=12; for(i=0;in&&!er;i++) er=(b->paramlo[i]<=b->paramhi[i])?0:45; } if(m) for(trace=SetNext(NULL,&k,&x,m->basis);trace&&!er;trace=SetNext(trace,&k,&x,m->basis)) { b=(basisptr)x; if(!b->isspec) er=0; else if(b->isspec==1&&b->spec&&!b->spec->cmplx) er=0; else if(!b->spec) er=16; else if(b->isspec==1&&b->spec->cmplx) er=8; else if(b->isspec==2&&!b->spec->cmplx) er=12; for(i=0;in&&!er;i++) er=(b->paramlo[i]<=b->paramhi[i])?0:45; } return er; } int CheckMSpec(modelptr m) { if(!m||!m->spec) return 0; if(m->spec->cmplx) return 8; return 0; } int CheckUncert(modelptr m) { if(!m||!m->uncert) return 0; if(!m->spec) return 16; if(m->spec->n!=m->uncert->n) return 11; if(!equalV(m->spec->x,m->uncert->x,m->spec->n)) return 11; if(m->spec->cmplx) return 8; if(minV(m->uncert->y,m->uncert->n)<=0) return 14; return 0; } int setupbasis() { set bset; bset=basisfns=SetAlloc(&StringCmp,NULL); if(!bset) return 1; return getbasis(bset); } void PlotBasis(basisptr b) { float xa,xb,ya,yb,x,dx; if(!b->model) return; if(CheckBasis(b,NULL)) return; GetScales(&xa,&xb,&ya,&yb); if(b->model->xmin>xa) xa=b->model->xmin; if(b->model->xmaxmodel->xmax; dx=b->model->dx; SetColor(b->color[0]); PlotPt(xa,(b->addr)(xa,b->param,b->spec,NULL)); for(x=xa;xaddr)(x,b->param,b->spec,NULL)); PlotLine(xb,(b->addr)(xb,b->param,b->spec,NULL)); SetColor('0'); return; } void PlotModel(modelptr m) { float xa,xb,ya,yb,x,dx; if(CheckBasis(NULL,m)) return; GetScales(&xa,&xb,&ya,&yb); if(m->xmin>xa) xa=m->xmin; if(m->xmaxxmax; dx=m->dx; SetColor(m->color[0]); PlotPt(xa,ModelValue(xa,m)); for(x=xa;xmodel) return; if(CheckBasis(b,NULL)) return; xlo=b->model->xmin; if(!fn||fn<0&&*xa0&&*xa>xlo) *xa=xlo; xhi=b->model->xmax; if(!fn||fn<0&&*xb>xhi||fn>0&&*xb*xb) xhi=*xb; ylo=yhi=(b->addr)(xlo,b->param,b->spec,NULL); for(x=xlo;xmodel->dx) { y=(b->addr)(x,b->param,b->spec,NULL); if(yyhi) yhi=y; } if(!fn||fn<0&&*ya0&&*ya>ylo) *ya=ylo; if(!fn||fn<0&&*yb>yhi||fn>0&&*ybxmin; if(!fn||fn<0&&*xa0&&*xa>xlo) *xa=xlo; xhi=m->xmax; if(!fn||fn<0&&*xb>xhi||fn>0&&*xb*xb) xhi=*xb; ylo=yhi=ModelValue(xlo,m); for(x=xlo;xdx) { y=ModelValue(x,m); if(yyhi) yhi=y; } if(!fn||fn<0&&*ya0&&*ya>ylo) *ya=ylo; if(!fn||fn<0&&*yb>yhi||fn>0&&*ybbasis);trace;trace=SetNext(trace,&k,&item,m->basis)) { b=(basisptr)item; for(i=0;in;i++) if(!b->freeze[i]) nfre++; } if(frzptr) { *frzptr=(int *)calloc(m->np,sizeof(int)); if(!*frzptr) return -1; j=0; for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis)) { b=(basisptr)item; for(i=0;in;i++) (*frzptr)[j++]=b->freeze[i]; }} return nfre; } int FindBasisParam(basisptr *bptr,modelptr m,char* str) { int i; basisptr b; void *k,*item; struct scell *trace; b=*bptr; if(b) { for(i=0;in;i++) if(!strcmp(b->pname[i],str)) return i; return -1; } if(!m) return -1; for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis)) { b=*bptr=(basisptr)item; for(i=0;in;i++) if(!strcmp(b->pname[i],str)) return i; } *bptr=NULL; return -1; } int FindBasisParam2(basisptr *bptr,modelptr m,float* fltptr) { int i; basisptr b; void *k,*item; struct scell *trace; if(!m) return -1; for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis)) { b=*bptr=(basisptr)item; for(i=0;in;i++) if(&(b->param[i])==fltptr) return i; } *bptr=NULL; return -1; } float ModelValue(float x,modelptr m) { float y=0; void *k,*item; struct scell *trace; basisptr b; for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis)) { b=(basisptr)item; y+=(b->addr)(x,b->param,b->spec,NULL); } return y; } float ModelValueD(float x,modelptr m,float *d) { float y=0; int i,j; void *k,*item; struct scell *trace; basisptr b; j=0; for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis)) { b=(basisptr)item; y+=(b->addr)(x,b->param,b->spec,b->scratch); for(i=0;in;i++) if(!b->freeze[i]) d[j++]=b->scratch[i]; } return y; } void TypeBasis(basisptr b) { int i; if(!b) { printf("NULL basis function.\n"); return; } if(b->model) printf("%s is a basis function in model %s\n",b->name,b->model->name); else printf("%s is a basis function without a model\n",b->name); printf(" procedure: %s, color: %s, %i parameters\n",b->proc,b->color,b->n); printf(" description: %s\n",b->desc); for(i=0;in;i++) { printf("\t%s=%f\t%s\n",b->pname[i],b->param[i],b->freeze[i]?"fix":"free"); if(strlen(b->eqn[i])) printf("\t\teqn %sactive: %s\n",b->freeze[i]?"":"in",b->eqn[i]); if(b->paramlo[i]>-FLT_MAX&&b->paramhi[i]paramlo[i],b->pname[i],b->paramhi[i]); else if(b->paramlo[i]>-FLT_MAX) printf("\t\t%f ² %s\n",b->paramlo[i],b->pname[i]); else if(b->paramhi[i]pname[i],b->paramhi[i]); } if(b->isspec&&!b->spec) printf(" spectrum required, none assigned.\n"); else if(b->isspec==1&&!b->spec->cmplx) printf(" spectrum: %s\n",b->spec); else if(b->isspec==1&&b->spec->cmplx) printf(" complex spectrum should be real: %s\n",b->spec); else if(b->isspec==2&&b->spec->cmplx) printf(" complex spectrum: %s\n",b->spec); else if(b->isspec==2&&!b->spec->cmplx) printf(" real spectrum should be complex: %s\n",b->spec); else if(b->isspec) printf(" spectrum: %s\n",b->spec); printf("\n"); } void TypeAllBasis() { struct scell *trace; void *k,*x; if(!basisfns) { printf("Set of basis functions not loaded in.\n"); return; } printf("%i basis functions loaded.\n",SetCard(basisfns)); for(trace=SetNext(NULL,&k,&x,basisfns);trace;trace=SetNext(trace,&k,&x,basisfns)) printf(" %s\t%s\n",(char *) k,((basisptr)x)->desc); return; } void TypeModel(modelptr m) { struct scell *trace; void *k,*x; int n,nfre,i,j,npts; basisptr b; sptr s; if(!m) { printf("No model.\n"); return; } if(m->spec) printf("Model: %s for spectrum %s\n",m->name,m->spec->name); else printf("Model: %s, no spectrum\n",m->name); if(strlen(m->file)) printf(" model file: %s\n",m->file); printf(" domain: %f to %f, color: %s\n",m->xmin,m->xmax,m->color); if(CheckUncert(m)) printf(" invalid uncertainties\n"); else if(m->sigma>0&&m->uncert) printf(" sigma: %f, uncertainties in: %s\n",m->sigma,m->uncert->name); else if(m->sigma>0) printf(" sigma: %f\n",m->sigma); else if(m->uncert) printf(" uncertainties in: %s\n",m->uncert->name); if(m->spec) { s=m->spec; if(s->x[0]>=m->xmin) i=0; else { i=locateV(s->x,m->xmin,s->n); if(i<0) i=0; else if(s->x[i]xmin) i++; } if(s->x[s->n-1]<=m->xmax) j=s->n-1; else j=locateV(s->x,m->xmax,s->n); npts=j-i+1; printf(" points: %i, params: %i with %i free\n",npts,m->np,CountFreParam(m,NULL)); if(CheckBasis(NULL,m)) printf(" a basis set is missing numerical data.\n"); else if(m->uncert||m->sigma>0) printf(" chi^2: %e, rms error: %e\n",chisq(m,-1),rmserror(m)); else printf(" rms error: %e\n",rmserror(m)); } else { npts=0; printf(" no spectrum\n",m->name); } n=m->np; j=0; for(trace=SetNext(NULL,&k,&x,m->basis);trace;trace=SetNext(trace,&k,&x,m->basis)) { b=(basisptr)x; printf(" %s\n",b->name); for(i=0;in;i++) { if(m->covar&&!b->freeze[i]) printf(" %s= %f ± %f\tfree\n",b->pname[i],b->param[i],sqrt(m->covar[n*j+j])); else printf(" %s= %f\t\t\t%s\n",b->pname[i],b->param[i],b->freeze[i]?"fix":"free"); if(b->eqn[i]&&strlen(b->eqn[i])) printf("\t\t%sactive eqn:%s\n",b->freeze[i]?"":"in",b->eqn[i]); if(b->paramlo[i]>-FLT_MAX&&b->paramhi[i]paramlo[i],b->pname[i],b->paramhi[i]); else if(b->paramlo[i]>-FLT_MAX) printf(" %f ² %s\n",b->paramlo[i],b->pname[i]); else if(b->paramhi[i]pname[i],b->paramhi[i]); j++; }} printf("\n"); return; } basisptr BasisCopy(basisptr b) { basisptr a; int i; if(!b) return NULL; a=BasisAlloc(b->n); // ***************** if(!a) return NULL; strcpy(a->name,b->name); strcpy(a->proc,b->proc); strcpy(a->color,b->color); strcpy(a->desc,b->desc); a->model=b->model; a->addr=b->addr; for(i=0;in;i++) { a->param[i]=b->param[i]; a->pold[i]=b->pold[i]; a->paramlo[i]=b->paramlo[i]; a->paramhi[i]=b->paramhi[i]; strcpy(a->pname[i],b->pname[i]); strcpy(a->eqn[i],b->eqn[i]); a->freeze[i]=b->freeze[i]; a->scratch[i]=b->scratch[i]; } a->isspec=b->isspec; a->spec=b->spec; return a; } modelptr ModelCopy(modelptr m) { modelptr a; basisptr b; struct scell *trace; void *key,*item; int ok; if(!m) return NULL; a=ModelAlloc(m->spec); if(!a) return NULL; a->uncert=m->uncert; strcpy(a->name,m->name); strcpy(a->file,m->file); strcpy(a->color,m->color); a->sigma=m->sigma; a->np=m->np; a->xmin=m->xmin; a->xmax=m->xmax; a->dx=m->dx; if(m->covar) { a->covar=allocM(a->np,a->np); if(!a->covar) {ModelFree(a);return NULL;} copyM(m->covar,a->covar,m->np,m->np); } for(trace=SetNext(NULL,&key,&item,m->basis);trace;trace=SetNext(trace,&key,&item,m->basis)) { b=BasisCopy((basisptr)item); if(b) { b->model=a; ok=SetInsert((void *)b->name,(void *)b,a->basis); if(!ok) {ModelFree(a);return NULL;}}} return a; } basisptr AddBasis(basisptr b,char *bproc,sptr s,modelptr m) { void *x; basisptr b2; int i,ok; if(b) b=BasisCopy(b); else if(bproc) b=BasisCopy((basisptr)SetItem((void *)bproc,basisfns)); if(!b) return NULL; if(!strchr(b->name,':')) sprintf(b->name+strlen(b->name),":"); i=0; sprintf(strchr(b->name,':')+1,"%i",i++); for(x=SetItem((void *)b->name,m->basis);x;x=SetItem((void *)b->name,m->basis)) sprintf(strchr(b->name,':')+1,"%i",i++); b->model=m; b->spec=s; if(!b->addr) { b2=SetItem((void *)b->proc,basisfns); if(b2) b->addr=b2->addr; else {BasisFree(b);return NULL;}} ok=SetInsert((void *)b->name,(void *)b,m->basis); if(!ok) {BasisFree(b);return NULL;} m->np+=b->n; if(m->covar) { freeM(m->covar); m->covar=NULL; } return b; } void RemoveBasis(basisptr b) { modelptr m; if(!b) return; m=b->model; if(!m) return; if(SetDelete((void*)b->name,(void*)b,b->model->basis,0,0)) { m->np-=b->n; if(m->covar) { freeM(m->covar); m->covar=NULL; }} b->model=NULL; return; } int SaveModel(modelptr m) { FILE *fptr; char *name; int nmfre,er,i,j; char str[STRCHAR]; struct scell *trace; void *k,*x; basisptr b; name=m->file; er=GetName(&name,&nmfre); if(er) {m->file[0]='\0';return er;} if(!strcmp(name,"stdout")) fptr=stdout; else { fptr=fopen(name,"r"); if(fptr) { fclose(fptr); fprintf(stderr,"File exists. Do you want to overwrite it? "); scanf("%s",str); if(str[0]!='y'&&str[0]!='Y') { if(nmfre) free(name); m->file[0]='\0'; return 2; }} fptr=fopen(name,"w"); } if(nmfre) free(name); if(!fptr) return 3; er=0; er=er||fprintf(fptr,"# Model saved by SpectFit 2.0.\n\n")<0; er=er||fprintf(fptr,"name: %s\n",m->name)<0; er=er||fprintf(fptr,"file: %s\n",m->file)<0; er=er||fprintf(fptr,"color: %s\n",m->color)<0; er=er||fprintf(fptr,"# data modeled: %s\n",m->spec?m->spec->name:"none")<0; er=er||fprintf(fptr,"# uncertainties: %s\n",m->uncert?m->uncert->name:"none")<0; er=er||fprintf(fptr,"sigma: %f\n",m->sigma)<0; er=er||fprintf(fptr,"xmin: %f\n",m->xmin)<0; er=er||fprintf(fptr,"xmax: %f\n",m->xmax)<0; er=er||fprintf(fptr,"dx: %f\n",m->dx)<0; if(CheckBasis(NULL,m)) er=er||fprintf(fptr,"# a basis set is missing numerical data.\n")<0; else if(m->uncert||m->sigma>0) er=er||fprintf(fptr,"# chi^2: %e, rms error: %e\n",chisq(m,-1),rmserror(m))<0; else er=er||fprintf(fptr,"# rms error: %e\n",rmserror(m))<0; j=0; for(trace=SetNext(NULL,&k,&x,m->basis);trace;trace=SetNext(trace,&k,&x,m->basis)) { b=(basisptr)x; er=er||fprintf(fptr,"basis: %s\n",b->proc)<0; er=er||fprintf(fptr," name: %s\n",b->name)<0; er=er||fprintf(fptr," color: %s\n",b->color)<0; er=er||fprintf(fptr," desc: %s\n",b->desc)<0; if(b->spec) er=er||fprintf(fptr," spec: %s\n",b->spec->name)<0; for(i=0;in;i++) { er=er||fprintf(fptr," param: %s\n",b->pname[i])<0; if(m->covar&&!b->freeze[i]) er=er||fprintf(fptr," value: %f ± %f\n",b->param[i],sqrt(m->covar[m->np*j+j]))<0; else er=er||fprintf(fptr," value: %f\n",b->param[i])<0; j++; if(b->freeze[i]) er=er||fprintf(fptr," fix\n")<0; if(strlen(b->eqn[i])) er=er||fprintf(fptr," eqn: %s\n",b->eqn[i])<0; if(b->paramlo[i]>-FLT_MAX) er=er||fprintf(fptr," min: %f\n",b->paramlo[i])<0; if(b->paramhi[i]paramhi[i])<0; } er=er||fprintf(fptr," endbasis\n")<0; } if(er) er=3; fclose(fptr); return er; } int LoadModel(modelptr *mptr,char *name,sptr s) { FILE *fptr; modelptr m; basisptr b; char line[STRCHAR],word[STRCHAR],word2[STRCHAR],*line2; int i,er,nmfre,itct,endflag; if(!mptr) return 6; m=*mptr=NULL; er=GetName(&name,&nmfre); if(er) return er; if(!strcmp(name,"stdin")) fptr=stdin; else fptr=fopen(name,"r"); if(nmfre) free(name); if(!fptr) return 5; m=ModelAlloc(s); if(!m) {er=1;goto failure;} endflag=0; er=1000; while(!endflag&&fgets(line,STRCHAR,fptr)) { er++; if(strlen(line)name,word2,STRCHAR); else if(!strcmp(word,"file:")) strncpy(m->file,word2,STRCHAR); else if(!strcmp(word,"color:")) strncpy(m->color,word2,STRCHAR); else if(!strcmp(word,"sigma:")) { CHECK(sscanf(line2,"%f",&m->sigma)==1); } else if(!strcmp(word,"xmin:")) { CHECK(sscanf(line2,"%f",&m->xmin)==1); } else if(!strcmp(word,"xmax:")) { CHECK(sscanf(line2,"%f",&m->xmax)==1); } else if(!strcmp(word,"dx:")) { CHECK(sscanf(line2,"%f",&m->dx)==1); } else if(!strcmp(word,"basis:")) { CHECK(b=AddBasis(NULL,word2,NULL,m)); i=-1; while(!endflag&&fgets(line,STRCHAR,fptr)) { er++; if(strlen(line)n;i++) { CHECK(b->paramlo[i]<=b->paramhi[i]); } CHECK(!b->isspec||b->spec); endflag=1; } else if(!strcmp(word,"fix")&&i>-1) b->freeze[i]=1; else if(!strcmp(word,"free")&&i>-1) b->freeze[i]=0; else if(!line2) goto failure; else if(!strcmp(word,"name:")) { if(!SetItem((void *)word2,m->basis)) strncpy(b->name,word2,STRCHAR); } else if(!strcmp(word,"color:")) strncpy(b->color,word2,STRCHAR); else if(!strcmp(word,"desc:")) strncpy(b->desc,line2,STRCHAR); else if(!strcmp(word,"spec:")) { CHECK(b->spec=Name2Spec(word2)); } else if(!strcmp(word,"param:")) { for(i=0;in&&strcmp(b->pname[i],word2);i++) CHECK(in); } else if(!strcmp(word,"value:")&&i>-1) { CHECK(sscanf(line2,"%f",&b->param[i])==1); } else if(!strcmp(word,"min:")&&i>-1) { CHECK(sscanf(line2,"%f",&b->paramlo[i])==1); } else if(!strcmp(word,"max:")&&i>-1) { CHECK(sscanf(line2,"%f",&b->paramhi[i])==1); } else if(!strcmp(word,"eqn:")&&i>-1) strncpy(b->eqn[i],line2,STRCHAR); else goto failure; } endflag=0; } else goto failure; } if(fptr!=stdin) fclose(fptr); fptr=NULL; CHECK(m->xminxmax&&m->dx>0); *mptr=m; return 0; failure: if(fptr&&fptr!=stdin) fclose(fptr); ModelFree(m); *mptr=NULL; return er; } int BasisMath(basisptr b,void *v,sptr *ansptr,float k,char *fn) { float dx,y,xlo,*param,*s3x,*s3y; int i,j,n,er; sptr s,s3,bspec; basisptr b2; if(!b||!ansptr||!fn||!b->model||!b->model->spec) return 6; if((er=CheckBasis(b,NULL))) return er; if(*ansptr) SpectFree(*ansptr); *ansptr=NULL; s3=SpectAlloc(b->name,NULL,fn,b->model->spec->xunit,b->model->spec->yunit); if(!s3) return 1; strncat(s3->name,"s",STRCHAR-strlen(s3->name)); strncat(s3->desc,b->name,STRCHAR-strlen(s3->desc)); strncat(s3->desc," ",STRCHAR-strlen(s3->desc)); strncat(s3->desc,fn,STRCHAR-strlen(s3->desc)); dx=b->model->dx; xlo=b->model->xmin; n=s3->n=(b->model->xmax-xlo)/dx+1; s3x=s3->x=allocV(n); s3y=s3->y=allocV(n); if(!s3->x||!s3->y) {SpectFree(s3);return 1;} for(i=0;ix[i]=xlo+i*dx; param=b->param; bspec=b->spec; if(!strcmp(fn,"exp b")) for(i=0;iaddr)(s3x[i],param,bspec,NULL)); s3y[i]=y<=FLT_MAX?y:0; } else if(!strcmp(fn,"ln b")) for(i=0;iaddr)(s3x[i],param,bspec,NULL); s3y[i]=y>0?log(y):0; } else if(!strcmp(fn,"10^b")) for(i=0;iaddr)(s3x[i],param,bspec,NULL)); s3y[i]=y<=FLT_MAX?y:0; } else if(!strcmp(fn,"log b")) for(i=0;iaddr)(s3x[i],param,bspec,NULL); s3y[i]=y>0?log10(y):0; } else if(!strcmp(fn,"sqrt b")) for(i=0;iaddr)(s3x[i],param,bspec,NULL); s3y[i]=y>0?sqrt(y):0; } else if(!strcmp(fn,"b+s")||!strcmp(fn,"s+b")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;iy[i]=interpolate1(s->x,s->y,s->n,&j,s3x[i])+(b->addr)(s3x[i],param,bspec,NULL); } else if(!strcmp(fn,"b-s")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;iaddr)(s3x[i],param,bspec,NULL)-interpolate1(s->x,s->y,s->n,&j,s3x[i]); } else if(!strcmp(fn,"b*s")||!strcmp(fn,"s*b")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;ix,s->y,s->n,&j,s3x[i])*(b->addr)(s3x[i],param,bspec,NULL); } else if(!strcmp(fn,"b/s")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;ix,s->y,s->n,&j,s3x[i]); s3y[i]=(y<0||y>0)?(b->addr)(s3x[i],param,bspec,NULL)/y:0; }} else if(!strcmp(fn,"s-b")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;ix,s->y,s->n,&j,s3x[i])-(b->addr)(s3x[i],param,bspec,NULL); } else if(!strcmp(fn,"s/b")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;iaddr)(s3x[i],param,bspec,NULL); s3y[i]=(y<0||y>0)?interpolate1(s->x,s->y,s->n,&j,s3x[i])/y:0; }} else if(!strcmp(fn,"b+b")) { b2=(basisptr) v; if(!b2) {SpectFree(s3);return 6;} for(i=0;iaddr)(s3x[i],param,bspec,NULL)+(b2->addr)(s3x[i],b2->param,b2->spec,NULL); } else if(!strcmp(fn,"b-b")) { b2=(basisptr) v; if(!b2) {SpectFree(s3);return 6;} for(i=0;iaddr)(s3x[i],param,bspec,NULL)-(b2->addr)(s3x[i],b2->param,b2->spec,NULL); } else if(!strcmp(fn,"b*b")) { b2=(basisptr) v; if(!b2) {SpectFree(s3);return 6;} for(i=0;iaddr)(s3x[i],param,bspec,NULL)*(b2->addr)(s3x[i],b2->param,b2->spec,NULL); } else if(!strcmp(fn,"b/b")) { b2=(basisptr) v; if(!b2) {SpectFree(s3);return 6;} for(i=0;iaddr)(s3x[i],b2->param,b2->spec,NULL); s3y[i]=(y<0||y>0)?(b->addr)(s3x[i],b->param,b->spec,NULL)/y:0; }} else if(!strcmp(fn,"b+k")||!strcmp(fn,"k+b")) for(i=0;iaddr)(s3x[i],param,bspec,NULL)+k; else if(!strcmp(fn,"b*k")||!strcmp(fn,"k*b")) for(i=0;iaddr)(s3x[i],param,bspec,NULL)*k; else if(!strcmp(fn,"k-b")) for(i=0;iaddr)(s3x[i],param,bspec,NULL); else if(!strcmp(fn,"k/b")) for(i=0;iaddr)(s3x[i],param,bspec,NULL); s3y[i]=(y<0||y>0)?k/y:0; } else if(!strcmp(fn,"b-k")) for(i=0;iaddr)(s3x[i],param,bspec,NULL)-k; else if(!strcmp(fn,"b/k")) { if(!(k<0||k>0)) {SpectFree(s3);return 9;} for(i=0;iaddr)(s3x[i],param,bspec,NULL)/k; } else if(!strcmp(fn,"b^k")) if(k>0) for(i=0;iaddr)(s3x[i],param,bspec,NULL),k); else if(k==floor(k)) for(i=0;iaddr)(s3x[i],param,bspec,NULL); s3y[i]=(y<0||y>0)?pow(y,k):0; } else for(i=0;iaddr)(s3x[i],param,bspec,NULL); s3y[i]=y>0?pow(y,k):0; } else { SpectFree(s3); return 7; } *ansptr=s3; return 0; } int ModelMath(modelptr m,void *v,sptr *ansptr,float k,char *fn) { float dx,y,*s3x,*s3y; int i,j,n,er; basisptr b2; modelptr m2; sptr s3,s; if(!m||!ansptr||!fn) return 6; if((er=CheckBasis(NULL,m))) return er; if(*ansptr) SpectFree(*ansptr); *ansptr=NULL; if(m->spec) s3=SpectAlloc(m->name,NULL,fn,m->spec->xunit,m->spec->yunit); else s3=SpectAlloc(m->name,NULL,fn,"x","y"); if(!s3) return 1; strncat(s3->name,"s",STRCHAR-strlen(s3->name)); strncat(s3->desc,m->name,STRCHAR-strlen(s3->desc)); strncat(s3->desc," ",STRCHAR-strlen(s3->desc)); strncat(s3->desc,fn,STRCHAR-strlen(s3->desc)); dx=m->dx; n=s3->n=(m->xmax-m->xmin)/dx+1; s3x=s3->x=allocV(n); s3y=s3->y=allocV(n); if(!s3x||!s3y) {SpectFree(s3);return 1;} for(i=0;ixmin+i*dx; if(!strcmp(fn,"exp m")) for(i=0;i0?log(y):0; } else if(!strcmp(fn,"10^m")) for(i=0;i0?log10(y):0; } else if(!strcmp(fn,"sqrt m")) for(i=0;i0?sqrt(y):0; } else if(!strcmp(fn,"m+s")||!strcmp(fn,"s+m")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;ix,s->y,s->n,&j,s3x[i])+ModelValue(s3x[i],m); } else if(!strcmp(fn,"m-s")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;ix,s->y,s->n,&j,s3x[i]); } else if(!strcmp(fn,"m*s")||!strcmp(fn,"s*m")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;ix,s->y,s->n,&j,s3x[i])*ModelValue(s3x[i],m); } else if(!strcmp(fn,"m/s")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;ix,s->y,s->n,&j,s3x[i]); s3y[i]=(y<0||y>0)?ModelValue(s3x[i],m)/y:0; }} else if(!strcmp(fn,"s-m")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;ix,s->y,s->n,&j,s3x[i])-ModelValue(s3x[i],m); } else if(!strcmp(fn,"s/m")) { s=(sptr) v; if(!s) {SpectFree(s3);return 6;} if(s->cmplx) {SpectFree(s3);return 8;} j=-2; for(i=0;i0)?interpolate1(s->x,s->y,s->n,&j,s3x[i])/y:0; }} else if(!strcmp(fn,"m+b")||!strcmp(fn,"b+m")) { b2=(basisptr) v; if(!b2) {SpectFree(s3);return 6;} for(i=0;iaddr)(s3x[i],b2->param,b2->spec,NULL); } else if(!strcmp(fn,"m-b")) { b2=(basisptr) v; if(!b2) {SpectFree(s3);return 6;} for(i=0;iaddr)(s3x[i],b2->param,b2->spec,NULL); } else if(!strcmp(fn,"m*b")||!strcmp(fn,"b*m")) { b2=(basisptr) v; if(!b2) {SpectFree(s3);return 6;} for(i=0;iaddr)(s3x[i],b2->param,b2->spec,NULL); } else if(!strcmp(fn,"m/b")) { b2=(basisptr) v; if(!b2) {SpectFree(s3);return 6;} for(i=0;iaddr)(s3x[i],b2->param,b2->spec,NULL); s3y[i]=(y<0||y>0)?ModelValue(s3x[i],m)/y:0; }} else if(!strcmp(fn,"b-m")) { b2=(basisptr) v; if(!b2) {SpectFree(s3);return 6;} for(i=0;iaddr)(s3x[i],b2->param,b2->spec,NULL)-ModelValue(s3x[i],m); } else if(!strcmp(fn,"b/m")) { b2=(basisptr) v; if(!b2) {SpectFree(s3);return 6;} for(i=0;i0)?(b2->addr)(s3x[i],b2->param,b2->spec,NULL)/y:0; }} else if(!strcmp(fn,"m+m")) { m2=(modelptr) v; if(!m2) {SpectFree(s3);return 6;} for(i=0;i0)?ModelValue(s3x[i],m)/y:0; }} else if(!strcmp(fn,"m+k")||!strcmp(fn,"k+m")) for(i=0;i0)?k/y:0; } else if(!strcmp(fn,"m-k")) for(i=0;i0)) {SpectFree(s3);return 9;} for(i=0;i0) for(i=0;i0)?pow(y,k):0; } else for(i=0;i0?pow(y,k):0; } else { SpectFree(s3); return 7; } *ansptr=s3; return 0; } void endbasis() { struct scell *trace,*trace2; void *k,*x; for(trace=SetNext(NULL,&k,&x,basisfns);trace;trace=trace2) { trace2=SetNext(trace,&k,&x,basisfns); BasisFree((basisptr) x); } SetFree(basisfns,0,0); basisfns=NULL; return; } float rmserror(modelptr m) { float diff,ch2,siginv,*sx,*sy,*uy; int lo,hi,er; int i; sptr s; if(!m) return -6; if(!m->spec) return -16; if(m->spec->cmplx) return -8; if((er=CheckBasis(NULL,m))) return -er; s=m->spec; sx=s->x; sy=s->y; if(sx[0]>=m->xmin) lo=0; else { lo=locateV(sx,m->xmin,s->n); if(lo<0) lo=0; else if(sx[lo]xmin) lo++; } if(sx[s->n-1]<=m->xmax) hi=s->n-1; else hi=locateV(sx,m->xmax,s->n); ch2=0; for(i=lo;i<=hi;i++) { diff=(sy[i]-ModelValue(sx[i],m)); ch2+=diff*diff; } return sqrt(ch2/(hi-lo+1)); } float chisq(modelptr m,float ch2max) { float diff,ch2,siginv,*sx,*sy,*uy; int lo,hi; int i; sptr s; if(ch2max<0) ch2max=FLT_MAX; s=m->spec; if(m->sigma>0) siginv=1.0/m->sigma; else siginv=1; sx=s->x; sy=s->y; if(m->uncert) uy=m->uncert->y; if(sx[0]>=m->xmin) lo=0; else { lo=locateV(sx,m->xmin,s->n); if(lo<0) lo=0; else if(sx[lo]xmin) lo++; } if(sx[s->n-1]<=m->xmax) hi=s->n-1; else hi=locateV(sx,m->xmax,s->n); ch2=0; if(!m->uncert) for(i=lo;i<=hi&&ch2spec; if(m->sigma>0) siginv=1.0/m->sigma; else siginv=1; sx=s->x; sy=s->y; if(m->uncert) uy=m->uncert->y; deriv=allocV(np); if(!deriv) return -1; if(sx[0]>=m->xmin) lo=0; else { lo=locateV(sx,m->xmin,s->n); if(lo<0) lo=0; else if(sx[lo]xmin) lo++; } if(sx[s->n-1]<=m->xmax) hi=s->n-1; else hi=locateV(sx,m->xmax,s->n); setstdV(beta,np,0); setstdM(alpha,np,np,0); ch2=0; if(!m->uncert) for(i=lo;i<=hi&&ch2uncert) for(i=lo;i<=hi&&ch2-FLT_MAX)) beta[k]=0; for(k2=0;k2-FLT_MAX)) alpha[np*k+k2]=0; } return ch2spec) return -16; if(m->spec->cmplx) return -8; if((er=CheckBasis(NULL,m))) return -er; if((er=CheckUncert(m))) return -er; p=*pptr=NULL; *ploptr=NULL; *phiptr=NULL; nfre=CountFreParam(m,NULL); if(!nfre) return 0; ntot=m->np; p=(float **) calloc(nfre,sizeof(float *)); /* pointers to parameters */ *ploptr=allocV(nfre); *phiptr=allocV(nfre); if(!p||!*ploptr||!*phiptr) { if(p) free(p); if(*ploptr) freeV(*ploptr); if(*phiptr) freeV(*phiptr); return -1; } jfre=0; for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis)) { b=(basisptr)item; for(i=0;in;i++) { b->pold[i]=b->param[i]; if(!b->freeze[i]) { if(b->param[i]paramlo[i]) b->param[i]=b->paramlo[i]; else if(b->param[i]>b->paramhi[i]) b->param[i]=b->paramhi[i]; p[jfre]=&b->param[i]; (*ploptr)[jfre]=b->paramlo[i]; (*phiptr)[jfre]=b->paramhi[i]; jfre++; }}} *pptr=p; return nfre; } int ModelCovar(modelptr m) { int rmssig,er,jfre,nfre,itot,jtot,ntot,*frz,*luindx; float det,*alpha,*alphalu,*covar,*ident,*beta; if(!m) return 6; if(!m->spec) return 16; if(m->spec->cmplx) return 8; if((er=CheckBasis(NULL,m))) return er; if((er=CheckUncert(m))) return er; nfre=CountFreParam(m,&frz); if(nfre<0) return -nfre; else if(!nfre) return 0; er=0; rmssig=0; alpha=allocM(nfre,nfre); alphalu=allocM(nfre,nfre); covar=allocM(nfre,nfre); ident=allocM(nfre,nfre); beta=allocV(nfre); luindx=NULL; if(!alpha||!alphalu||!covar||!ident||!beta) {er=1;goto endfunction;} if(m->sigma<=0&&!m->uncert) { rmssig=1; m->sigma=rmserror(m); } ChiSqD(m,-1,alpha,beta,nfre); copyM(alpha,alphalu,nfre,nfre); det=LUdecomp(alphalu,nfre,&luindx); if(det==0) {er=9;goto endfunction;} setstdM(covar,nfre,nfre,1); LUsolveM(alphalu,luindx,covar,nfre,nfre); setstdM(ident,nfre,nfre,1); LUimprM(alpha,alphalu,luindx,covar,ident,nfre,nfre); ntot=m->np; if(!m->covar) m->covar=allocM(ntot,ntot); if(!m->covar) {er=1;goto endfunction;} setstdM(m->covar,ntot,ntot,0); jfre=0; for(itot=0;itotcovar[ntot*itot+jtot]=covar[jfre++]; endfunction: if(rmssig) m->sigma=0; if(frz) free(frz); if(alpha) freeM(alpha); if(alphalu) freeM(alphalu); if(covar) freeM(covar); if(ident) freeM(ident); if(beta) freeV(beta); if(luindx) free(luindx); if(er&&m->covar) { freeM(m->covar); m->covar=NULL; } return er; } void unfit(modelptr m) { int i; float f1; void *k,*item; struct scell *trace; basisptr b; for(trace=SetNext(NULL,&k,&item,m->basis);trace;trace=SetNext(trace,&k,&item,m->basis)) { b=(basisptr)item; for(i=0;in;i++) { f1=b->param[i]; b->param[i]=b->pold[i]; b->pold[i]=f1; }} if(m->covar) { freeM(m->covar); m->covar=NULL; } return; } int RandomFit(modelptr m) { float ch2,f,f2; float **p,*plo,*phi,*step; int i,j,np,er; np=prefit(m,&p,&plo,&phi); if(np<0) return -np; else if(!np) return 0; step=allocV(np); if(!step) {free(p);freeV(plo);freeV(phi);return 1;} for(j=0;jphi[j]) *p[j]=phi[j]; UpdateModel(m); if((f2=chisq(m,ch2))spec; if(m->sigma>0) siginv=1.0/m->sigma; else siginv=1; if(m->uncert) uy=m->uncert->y; if(s->x[0]>=m->xmin) lo=0; else { lo=locateV(s->x,m->xmin,s->n); if(lo<0) lo=0; else if(s->x[lo]xmin) lo++; } if(s->x[s->n-1]<=m->xmax) hi=s->n-1; else hi=locateV(s->x,m->xmax,s->n); n=hi-lo+1; A=allocM(n,np); Atrans=allocM(np,n); alpha=allocM(np,np); alphalu=allocM(np,np); beta=allocV(np); ans=allocV(np); b=allocV(n); luindx=NULL; if(!A||!Atrans||!alpha||!beta||!alphalu||!ans||!b) {er=1;goto endfunction; } ch2=chisq(m,-1); if(!m->uncert) for(i=lo;i<=hi;i++) { b[i-lo]=(s->y[i]-ModelValueD(s->x[i],m,ans))*siginv; for(j=0;jy[i]-ModelValueD(s->x[i],m,ans))*siginv/uy[i]; for(j=0;jphi[i]) *p[i]=phi[i]; else *p[i]=ans[i]; } UpdateModel(m); if(!(chisq(m,ch2)-FLT_MAX) { *p[j]+=betab[j]; if(*p[j]phi[j]) *p[j]=phi[j]; }} UpdateModel(m); if((ch2b=ChiSqD(m,ch2,alphab,betab,np))>=0&&ch2bnp; } if(!ntotal) return 0; p=(float **) calloc(ntotal,sizeof(float *)); plo=allocV(ntotal); phi=allocV(ntotal); step=allocV(ntotal); if(!p||!plo||!phi||!step) { if(p) free(p); if(plo) freeV(plo); if(phi) freeV(phi); if(step) freeV(step); return 1; } np=0; for(trace=SetNext(NULL,&key,&item,s);trace;trace=SetNext(trace,&key,&item,s)) { m=(modelptr)item; npm=prefit(m,&pm,&plom,&phim); if(npm<0) {free(p);freeV(step);freeV(plo);freeV(phi);return -npm;} if(npm>0) { for(i=0;icovar) { freeM(m->covar); m->covar=NULL; }} ch2=0; for(trace=SetNext(NULL,&key,&item,s);trace;trace=SetNext(trace,&key,&item,s)) ch2+=chisq((modelptr)item,-1); if(np) for(it=0;itphi[j]) *p[j]=phi[j]; for(trace=SetNext(NULL,&key,&item,s);trace;trace=SetNext(trace,&key,&item,s)) UpdateModel((modelptr)item); f2=0; for(trace=SetNext(NULL,&key,&item,s);trace&&ch2>f2;trace=SetNext(trace,&key,&item,s)) f2+=chisq((modelptr)item,ch2-f2); if(f2