void fit_noise(struct complex *ncf,int *badlag,struct FitACFBadSample *badsmp, double skynoise,struct FitPrm *prm, struct FitRange *ptr) { int lag_lim; int istat, j; double A, tau, t; lag_lim = prm->mplgs/2; /* require at least 1/2 of lags be OK*/ istat = fit_acf(ncf, 1, badlag, badsmp, lag_lim, prm, 0.0, 0,0.0,ptr); tau = prm->mpinc * 1.0e-6; if (istat ==1 && (ptr->v == 0.0)) ptr->v = 1.0; if (istat == 1 && (fabs(ptr->v_err/ptr->v) < 0.05)) { if (ptr->w_l_err <= ptr->w_s_err) { if (ptr->p_s > skynoise) ptr->p_s = skynoise; A = exp(ptr->p_s); for (j=0; j < prm->mplgs; ++j) { t = (prm->lag[1][j] - prm->lag[0][j])*tau; ncf[j].x = A*exp(-ptr->w_l*t)*cos(ptr->v*t); ncf[j].y = A*exp(-ptr->w_l*t)*sin(ptr->v*t); } } else { if (ptr->p_s > skynoise) ptr->p_s = skynoise; A = exp(ptr->p_s); for (j=0; j < prm->mplgs; ++j) { t = (prm->lag[1][j] - prm->lag[0][j])*tau; ncf[j].x = A*exp(-(ptr->w_s*t)*(ptr->w_s*t))*cos(ptr->v*t); ncf[j].y = A*exp(-(ptr->w_s*t)*(ptr->w_s*t))*sin(ptr->v*t); } } } else for (j=0; j < prm->mplgs; ++j) { ncf[j].x = 0; ncf[j].y = 0; } return; }
int do_fit(struct FitBlock *iptr,int lag_lim,int goose, struct FitRange *ptr,struct FitRange *xptr, struct FitElv *elv, struct FitNoise *nptr) { struct FitACFBadSample badsmp; int badlag[MAX_RANGE][LAG_SIZE]; int i=0,k; double pwrd[MAX_RANGE],pwrt[MAX_RANGE]; double mnpwr, skylog, freq_to_vel, range; double xomega=0.0; double noise_pwr=0.0; int ni; nptr->skynoise=0.0; nptr->lag0=0.0; nptr->vel=0.0; if (iptr->prm.nave <= 1) return 0; freq_to_vel = C/(4*PI)/(iptr->prm.tfreq * 1000.0); if (iptr->prm.channel==0) FitACFBadlags(&iptr->prm,&badsmp); else FitACFBadlagsStereo(&iptr->prm,&badsmp); /* Determine the lag_0 noise level (0 dB reference) and the noise level at which fit_acf is to quit (average power in the fluctuations of the acfs which are pure noise) */ for (i=0; i < iptr->prm.nrang; i++) { pwrd[i] = (double) iptr->prm.pwr0[i]; /* transfer powers into local array */ pwrt[i] = pwrd[i]; } qsort(pwrt, iptr->prm.nrang, sizeof(double), dbl_cmp); /* determine the average lag0 power of the 10 lowest power acfs */ ni = 0; i = 0; mnpwr = 0.0; /* look for the lowest 10 values of lag0 power and average to get the noise level. Ignore values that are exactly 0. If you can't find 10 useable values within the first 1/3 of the sorted power list, then just use whatever you got in that first 1/3. If you didn't get any useable values, then use the NOISE parameter */ while ((ni < 10) && (i < iptr->prm.nrang/3)) { if (pwrt[i]) ++ni; mnpwr += pwrt[i++]; } ni = (ni > 0) ? ni : 1; mnpwr = mnpwr/ni; if (mnpwr < 1.0) mnpwr = iptr->prm.noise; nptr->skynoise = mnpwr; /* Now determine the level which will be used as the cut-off power for fit_acf. This is the average power at all non-zero lags of all acfs which have lag0 power < 1.6*mnpwr + 1 stnd. deviation from that average power level */ noise_pwr = noise_stat(mnpwr,&iptr->prm,&badsmp, iptr->acfd); /* convert the lag0 powers to dB */ if (nptr->skynoise > 0.0) skylog = 10.0 * log10(nptr->skynoise); else skylog = 0.0; for (i=0; i<iptr->prm.nrang; i++) { pwrd[i] = pwrd[i] - nptr->skynoise; if (pwrd[i] <= 0.0) ptr[i].p_0 = -50.0; else ptr[i].p_0 = 10.0*log10(pwrd[i]) - skylog; } /* reset the output arrays */ for (i=0; i<MAX_RANGE; i++) { ptr[i].p_l = -50.0; ptr[i].p_s = -50.0; ptr[i].p_l_err= 0.0; ptr[i].p_s_err= 0.0; ptr[i].w_l = 0.0; ptr[i].w_s = 0.0; ptr[i].w_l_err = 0.0; ptr[i].w_s_err = 0.0; ptr[i].v = 0.0; ptr[i].v_err = 0.0; ptr[i].phi0 = 0.0; ptr[i].phi0_err=0.0; ptr[i].sdev_l = 0.0; ptr[i].sdev_s = 0.0; ptr[i].sdev_phi = 0.0; ptr[i].gsct = 0.0; ptr[i].qflg = 0; ptr[i].nump=0; xptr[i].p_l = -50.0; xptr[i].p_s = -50.0; xptr[i].p_l_err= 0.0; xptr[i].p_s_err= 0.0; xptr[i].w_l = 0.0; xptr[i].w_s = 0.0; xptr[i].w_l_err = 0.0; xptr[i].w_s_err = 0.0; xptr[i].v = 0.0; xptr[i].v_err = 0.0; xptr[i].phi0 = 0.0; xptr[i].phi0_err=0.0; xptr[i].sdev_l = 0.0; xptr[i].sdev_s = 0.0; xptr[i].sdev_phi = 0.0; xptr[i].gsct = 0.0; xptr[i].qflg = 0; xptr[i].nump=0; elv[i].normal= 0.0; elv[i].low = 0.0; elv[i].high = 0.0; } /* ----------------------------------------------------------------------*/ /* Now do the fits for each acf */ for (k=0, i=0; k<iptr->prm.nrang;k++) { ptr[k].qflg = fit_acf(iptr->acfd[k], k+1,badlag[k],&badsmp, lag_lim,&iptr->prm,noise_pwr,0,0.0,&ptr[k]); xomega=ptr[k].v; if (ptr[k].qflg == 1) { /* several changes have been made here to fix an apparent problem in handling HUGE_VAL. If there are too few points in an ACF to allow the error on a parameter to be calculated then the subroutine fit_acf sets the value to HUGE_VAL. However, in this routine the error values are converted to natural units (e.g. velocity instead of frequency). It appears that multiplying HUGE_VAL by something causes a floating point exception that then sets the result of the calculation to 0. Thus the error values that were being stored in the file would be zero instead of HUGE_VAL. The code now checks to see if the value is set to HUGE_VAL before doing the conversion. If it is then instead of a converted version the error value is reset to HUGE_VAL. */ /* convert power from natural log to dB */ ptr[k].p_l = ptr[k].p_l*LN_TO_LOG - skylog; ptr[k].p_s = ptr[k].p_s*LN_TO_LOG - skylog; ptr[k].p_l_err = (ptr[k].p_l_err == HUGE_VAL) ? HUGE_VAL : ptr[k].p_l_err*LN_TO_LOG; ptr[k].p_s_err = (ptr[k].p_s_err == HUGE_VAL) ? HUGE_VAL : ptr[k].p_s_err*LN_TO_LOG; /* convert Doppler frequency to velocity */ ptr[k].v = iptr->prm.vdir*freq_to_vel*ptr[k].v; /* flag absurdly high velocities with qflg of 8 */ if (ptr[k].v > (freq_to_vel* (PI* 1000.0* 1000.0)/ iptr->prm.mpinc)) ptr[k].qflg= 8; ptr[k].v_err = (ptr[k].v_err == HUGE_VAL) ? HUGE_VAL : freq_to_vel*ptr[k].v_err; /* convert decay parameters to spectral widths */ ptr[k].w_l = freq_to_vel*2*ptr[k].w_l; ptr[k].w_l_err = (ptr[k].w_l_err == HUGE_VAL) ? HUGE_VAL : freq_to_vel*2*ptr[k].w_l_err; /* sigma is returned as sigma**2 so check the sign for validity if sigma**2 is negative take sqrt of the abs and transfer the sign */ ptr[k].w_s = (ptr[k].w_s >= 0) ? sqrt(ptr[k].w_s) : -sqrt(-ptr[k].w_s); if ((ptr[k].w_s !=0.0) && (ptr[k].w_s_err != HUGE_VAL)) ptr[k].w_s_err = 0.5*ptr[k].w_s_err/fabs(ptr[k].w_s); else ptr[k].w_s_err=HUGE_VAL; ptr[k].w_s = 3.33*freq_to_vel*ptr[k].w_s; ptr[k].w_s_err = (ptr[k].w_s_err == HUGE_VAL) ? HUGE_VAL : 3.33*freq_to_vel*ptr[k].w_s_err; /* Now check the values of power, velocity and width to see if this should be flagged as ground-scatter */ if (ptr[k].gsct == 0) ptr[k].gsct=ground_scatter(&ptr[k]); } if ((iptr->prm.xcf != 0) && (ptr[k].qflg == 1)) { xptr[k].qflg = fit_acf(iptr->xcfd[k], k+1,badlag[k],&badsmp, lag_lim,&iptr->prm,noise_pwr,1,xomega, &xptr[k]); } if (xptr[k].qflg == 1) { xptr[k].p_l = xptr[k].p_l*LN_TO_LOG - skylog; xptr[k].p_s = xptr[k].p_s*LN_TO_LOG - skylog; xptr[k].p_l_err = (xptr[k].p_l_err == HUGE_VAL) ? HUGE_VAL : xptr[k].p_l_err*LN_TO_LOG; xptr[k].p_s_err = (xptr[k].p_s_err == HUGE_VAL) ? HUGE_VAL : xptr[k].p_s_err*LN_TO_LOG; /* convert Doppler frequency to velocity */ xptr[k].v = iptr->prm.vdir*freq_to_vel*xptr[k].v; xptr[k].v_err = (xptr[k].v_err == HUGE_VAL) ? HUGE_VAL : freq_to_vel*xptr[k].v_err; /* convert decay parameters to spectral widths */ xptr[k].w_l = freq_to_vel*2*xptr[k].w_l; xptr[k].w_l_err = (xptr[k].w_l_err == HUGE_VAL) ? HUGE_VAL : freq_to_vel*2*xptr[k].w_l_err; /* sigma is returned as sigma**2 so check the sign for validity if sigma**2 is negative take sqrt of the abs and transfer the sign */ xptr[k].w_s = (xptr[k].w_s >= 0) ? sqrt(xptr[k].w_s) : -sqrt(-xptr[k].w_s); if ((xptr[k].w_s !=0.0) && (xptr[k].w_s_err != HUGE_VAL)) xptr[k].w_s_err = 0.5*xptr[k].w_s_err/fabs(xptr[k].w_s); else xptr[k].w_s_err=HUGE_VAL; xptr[k].w_s = 3.33*freq_to_vel*xptr[k].w_s; xptr[k].w_s_err = (xptr[k].w_s_err == HUGE_VAL) ? HUGE_VAL : 3.33*freq_to_vel*xptr[k].w_s_err; /* calculate the elevation angle */ if (xptr[k].phi0 > PI) xptr[k].phi0 = xptr[k].phi0 - 2*PI; if (xptr[k].phi0 < -PI) xptr[k].phi0 = xptr[k].phi0 + 2*PI; if (iptr->prm.phidiff != 0) xptr[k].phi0 = xptr[k].phi0*iptr->prm.phidiff; /* changes which array is first */ range = 0.15*(iptr->prm.lagfr + iptr->prm.smsep*(k-1)); if (goose==0) { elv[k].normal = elevation(&iptr->prm,range, xptr[k].phi0); elv[k].low = elevation(&iptr->prm,range, xptr[k].phi0+xptr[k].phi0_err); elv[k].high = elevation(&iptr->prm,range,xptr[k].phi0-xptr[k].phi0_err); } else { elv[k].normal = elev_goose(&iptr->prm,range, xptr[k].phi0); elv[k].low = elev_goose(&iptr->prm,range, xptr[k].phi0+xptr[k].phi0_err); elv[k].high = elev_goose(&iptr->prm,range, xptr[k].phi0-xptr[k].phi0_err); } } if( (ptr[k].qflg == 1)) i++; } return i; }
void low_do_autocorr(const char *fn,const output_env_t oenv,const char *title, int nframes,int nitem,int nout,real **c1, real dt,unsigned long mode,int nrestart, gmx_bool bAver,gmx_bool bNormalize, gmx_bool bVerbose,real tbeginfit,real tendfit, int eFitFn,int nskip) { FILE *fp,*gp=NULL; int i,k,nfour; real *csum; real *ctmp,*fit; real c0,sum,Ct2av,Ctav; gmx_bool bFour = acf.bFour; /* Check flags and parameters */ nout = get_acfnout(); if (nout == -1) nout = acf.nout = (nframes+1)/2; else if (nout > nframes) nout=nframes; if (MODE(eacCos) && MODE(eacVector)) gmx_fatal(FARGS,"Incompatible options bCos && bVector (%s, %d)", __FILE__,__LINE__); if ((MODE(eacP3) || MODE(eacRcross)) && bFour) { fprintf(stderr,"Can't combine mode %lu with FFT, turning off FFT\n",mode); bFour = FALSE; } if (MODE(eacNormal) && MODE(eacVector)) gmx_fatal(FARGS,"Incompatible mode bits: normal and vector (or Legendre)"); /* Print flags and parameters */ if (bVerbose) { printf("Will calculate %s of %d thingies for %d frames\n", title ? title : "autocorrelation",nitem,nframes); printf("bAver = %s, bFour = %s bNormalize= %s\n", bool_names[bAver],bool_names[bFour],bool_names[bNormalize]); printf("mode = %lu, dt = %g, nrestart = %d\n",mode,dt,nrestart); } if (bFour) { c0 = log((double)nframes)/log(2.0); k = c0; if (k < c0) k++; k++; nfour = 1<<k; if (debug) fprintf(debug,"Using FFT to calculate %s, #points for FFT = %d\n", title,nfour); /* Allocate temp arrays */ snew(csum,nfour); snew(ctmp,nfour); } else { nfour = 0; /* To keep the compiler happy */ snew(csum,nframes); snew(ctmp,nframes); } /* Loop over items (e.g. molecules or dihedrals) * In this loop the actual correlation functions are computed, but without * normalizing them. */ k = max(1,pow(10,(int)(log(nitem)/log(100)))); for(i=0; i<nitem; i++) { if (bVerbose && ((i%k==0 || i==nitem-1))) fprintf(stderr,"\rThingie %d",i+1); if (bFour) do_four_core(mode,nfour,nframes,nframes,c1[i],csum,ctmp); else do_ac_core(nframes,nout,ctmp,c1[i],nrestart,mode); } if (bVerbose) fprintf(stderr,"\n"); sfree(ctmp); sfree(csum); if (fn) { snew(fit,nout); fp=xvgropen(fn,title,"Time (ps)","C(t)",oenv); } else { fit = NULL; fp = NULL; } if (bAver) { if (nitem > 1) average_acf(bVerbose,nframes,nitem,c1); if (bNormalize) normalize_acf(nout,c1[0]); if (eFitFn != effnNONE) { fit_acf(nout,eFitFn,oenv,fn!=NULL,tbeginfit,tendfit,dt,c1[0],fit); sum = print_and_integrate(fp,nout,dt,c1[0],fit,1); } else { sum = print_and_integrate(fp,nout,dt,c1[0],NULL,1); if (bVerbose) printf("Correlation time (integral over corrfn): %g (ps)\n",sum); } } else { /* Not averaging. Normalize individual ACFs */ Ctav = Ct2av = 0; if (debug) gp = xvgropen("ct-distr.xvg","Correlation times","item","time (ps)",oenv); for(i=0; i<nitem; i++) { if (bNormalize) normalize_acf(nout,c1[i]); if (eFitFn != effnNONE) { fit_acf(nout,eFitFn,oenv,fn!=NULL,tbeginfit,tendfit,dt,c1[i],fit); sum = print_and_integrate(fp,nout,dt,c1[i],fit,1); } else { sum = print_and_integrate(fp,nout,dt,c1[i],NULL,1); if (debug) fprintf(debug, "CORRelation time (integral over corrfn %d): %g (ps)\n", i,sum); } Ctav += sum; Ct2av += sum*sum; if (debug) fprintf(gp,"%5d %.3f\n",i,sum); } if (debug) ffclose(gp); if (nitem > 1) { Ctav /= nitem; Ct2av /= nitem; printf("Average correlation time %.3f Std. Dev. %.3f Error %.3f (ps)\n", Ctav,sqrt((Ct2av - sqr(Ctav))), sqrt((Ct2av - sqr(Ctav))/(nitem-1))); } } if (fp) ffclose(fp); sfree(fit); }
void low_do_autocorr(const char *fn, const gmx_output_env_t *oenv, const char *title, int nframes, int nitem, int nout, real **c1, real dt, unsigned long mode, int nrestart, gmx_bool bAver, gmx_bool bNormalize, gmx_bool bVerbose, real tbeginfit, real tendfit, int eFitFn) { FILE *fp, *gp = NULL; int i; real *csum; real *ctmp, *fit; real sum, Ct2av, Ctav; gmx_bool bFour = acf.bFour; /* Check flags and parameters */ nout = get_acfnout(); if (nout == -1) { nout = acf.nout = (nframes+1)/2; } else if (nout > nframes) { nout = nframes; } if (MODE(eacCos) && MODE(eacVector)) { gmx_fatal(FARGS, "Incompatible options bCos && bVector (%s, %d)", __FILE__, __LINE__); } if ((MODE(eacP3) || MODE(eacRcross)) && bFour) { if (bVerbose) { fprintf(stderr, "Can't combine mode %lu with FFT, turning off FFT\n", mode); } bFour = FALSE; } if (MODE(eacNormal) && MODE(eacVector)) { gmx_fatal(FARGS, "Incompatible mode bits: normal and vector (or Legendre)"); } /* Print flags and parameters */ if (bVerbose) { printf("Will calculate %s of %d thingies for %d frames\n", title ? title : "autocorrelation", nitem, nframes); printf("bAver = %s, bFour = %s bNormalize= %s\n", gmx::boolToString(bAver), gmx::boolToString(bFour), gmx::boolToString(bNormalize)); printf("mode = %lu, dt = %g, nrestart = %d\n", mode, dt, nrestart); } /* Allocate temp arrays */ snew(csum, nframes); snew(ctmp, nframes); /* Loop over items (e.g. molecules or dihedrals) * In this loop the actual correlation functions are computed, but without * normalizing them. */ for (int i = 0; i < nitem; i++) { if (bVerbose && (((i % 100) == 0) || (i == nitem-1))) { fprintf(stderr, "\rThingie %d", i+1); fflush(stderr); } if (bFour) { do_four_core(mode, nframes, c1[i], csum, ctmp); } else { do_ac_core(nframes, nout, ctmp, c1[i], nrestart, mode); } } if (bVerbose) { fprintf(stderr, "\n"); } sfree(ctmp); sfree(csum); if (fn) { snew(fit, nout); fp = xvgropen(fn, title, "Time (ps)", "C(t)", oenv); } else { fit = NULL; fp = NULL; } if (bAver) { if (nitem > 1) { average_acf(bVerbose, nframes, nitem, c1); } if (bNormalize) { normalize_acf(nout, c1[0]); } if (eFitFn != effnNONE) { fit_acf(nout, eFitFn, oenv, fn != NULL, tbeginfit, tendfit, dt, c1[0], fit); sum = print_and_integrate(fp, nout, dt, c1[0], fit, 1); } else { sum = print_and_integrate(fp, nout, dt, c1[0], NULL, 1); } if (bVerbose) { printf("Correlation time (integral over corrfn): %g (ps)\n", sum); } } else { /* Not averaging. Normalize individual ACFs */ Ctav = Ct2av = 0; if (debug) { gp = xvgropen("ct-distr.xvg", "Correlation times", "item", "time (ps)", oenv); } for (i = 0; i < nitem; i++) { if (bNormalize) { normalize_acf(nout, c1[i]); } if (eFitFn != effnNONE) { fit_acf(nout, eFitFn, oenv, fn != NULL, tbeginfit, tendfit, dt, c1[i], fit); sum = print_and_integrate(fp, nout, dt, c1[i], fit, 1); } else { sum = print_and_integrate(fp, nout, dt, c1[i], NULL, 1); if (debug) { fprintf(debug, "CORRelation time (integral over corrfn %d): %g (ps)\n", i, sum); } } Ctav += sum; Ct2av += sum*sum; if (debug) { fprintf(gp, "%5d %.3f\n", i, sum); } } if (debug) { xvgrclose(gp); } if (nitem > 1) { Ctav /= nitem; Ct2av /= nitem; printf("Average correlation time %.3f Std. Dev. %.3f Error %.3f (ps)\n", Ctav, std::sqrt((Ct2av - gmx::square(Ctav))), std::sqrt((Ct2av - gmx::square(Ctav))/(nitem-1))); } } if (fp) { xvgrclose(fp); } sfree(fit); }