int call_xcorr_fft(Fluxrec *flux[], int size, char *filename, int nbad, FILE *logfp, int doprint) { int i; /* Looping variable */ int no_error=1; /* Flag set to 0 on error */ int corsize; /* Length of correlation curves */ float meanba,meanbc,meanbd; /* Mean values of cross-correlation curves */ float rmsba,rmsbc,rmsbd; /* RMS values of cross-correlation curves */ float norm=1.0; /* Normalization for curves */ float normday; /* Day from which normalization value comes */ Fluxrec best_ba; /* Highest cross-correlation for B-A */ Fluxrec best_bc; /* Highest cross-correlation for B-C */ Fluxrec best_bd; /* Highest cross-correlation for B-D */ Fluxrec *zmean[N08]={NULL}; /* Zero-mean light curves */ Fluxrec *acorrb=NULL; /* B autocorrelation */ Fluxrec *corrbc=NULL; /* B-C cross-correlation */ Fluxrec *corrba=NULL; /* B-A cross-correlation */ Fluxrec *corrbd=NULL; /* B-D cross-correlation */ Fluxrec *cp1,*cp2,*cp3; /* Pointers to navigate cross-corr arrays */ FILE *ofp=NULL; /* Output file */ /* * Initialize the best lag containers to something ridiculous. In this * function the lag will be contained in the day member of the Fluxrec * structure and the cross-correlation coefficient will be contained * in the flux member. */ best_ba.flux = -999.0; best_bc.flux = -999.0; best_bd.flux = -999.0; /* * Normalize the curves since we are looking for correlations in * fractional variations and then subtract 1 to create a zero-mean * light curve. This helps by getting rid of the DC component in * the cross-correlation. */ printf("\nCalculating cross-correlations....\n\n"); for(i=0; i<N08; i++) { if(no_error) if(!(zmean[i] = norm_zero_mean(flux[i],size))) no_error = 0; } /* * First do an autocorrelation on curve B and use the peak * value (at zero lag) to normalize the cross-correlation * curves. */ if(no_error) if(!(acorrb = do_corr(zmean[1],zmean[1],size,&corsize,nbad))) no_error = 0; if(no_error) { norm = -9999.0; for(i=0,cp1=acorrb; i<corsize; i++,cp1++) { if(cp1->flux > norm) { norm = cp1->flux; normday = cp1->day; } } printf("\ncall_xcorr_fft: Normalization = %f from day %5.1f\n\n", norm,normday); } /* * Call the cross-correlation routines for each pair of * zero-mean light curves. */ if(no_error) if(!(corrba = do_corr(zmean[1],zmean[0],size,&corsize,nbad))) no_error = 0; if(no_error) if(!(corrbc = do_corr(zmean[1],zmean[2],size,&corsize,nbad))) no_error = 0; if(no_error) if(!(corrbd = do_corr(zmean[1],zmean[3],size,&corsize,nbad))) no_error = 0; /* * Open output file */ if(doprint && no_error) if((ofp = fopen(filename,"w")) == NULL) { fprintf(stderr,"ERROR: call_xcorr_fft. Cannot open %s\n",filename); no_error = 0; } /* * Print cross-correlation curves to output files and also find * lags with highest cross-correlation values. */ if(no_error) { if(doprint) { fprintf(ofp,"# Lag Corr_ba Corr_bc Corr_bd\n"); fprintf(ofp,"#------- --------- --------- ---------\n"); } for(i=0,cp1=corrba,cp2=corrbc,cp3=corrbd; i<corsize; i++,cp1++,cp2++,cp3++) { cp1->flux /= norm; cp2->flux /= norm; cp3->flux /= norm; if(doprint) fprintf(ofp,"%8.3f %9f %9f %9f\n", -cp1->day,cp1->flux,cp2->flux,cp3->flux); if(cp1->flux > best_ba.flux) best_ba = *cp1; if(cp2->flux > best_bc.flux) best_bc = *cp2; if(cp3->flux > best_bd.flux) best_bd = *cp3; } } /* * Find rms (and mean) of cross-correlation curves. This can be used * to assess the significance of the highest peaks in the curves. */ if(no_error) { calc_mean(corrba,corsize,&meanba,&rmsba); calc_mean(corrbc,corsize,&meanbc,&rmsbc); calc_mean(corrbd,corsize,&meanbd,&rmsbd); #if 0 printf(" call_xcorr_fft: B-A xcorr curve mean = %f, rms = %f\n", meanba,rmsba); printf(" call_xcorr_fft: B-C xcorr curve mean = %f, rms = %f\n", meanbc,rmsbc); printf(" call_xcorr_fft: B-D xcorr curve mean = %f, rms = %f\n\n", meanbd,rmsbd); #endif } /* * Print best lags to logfile, if it exists. Take the negative of * best_b?.day because if B leads the other light curve, the * cross-correlation will return a negative number for the best-fit * lags. Since we know/hope that B leads all other values and we * are looking for the amount that the other curves lag B, just * take the negative of best_b?.day. */ if(logfp && no_error) { fprintf(logfp,"# Cross correlation results\n"); fprintf(logfp,"%7.2f %f %f ",-best_ba.day,best_ba.flux,rmsba); fprintf(logfp,"%7.2f %f %f ",-best_bc.day,best_bc.flux,rmsbc); fprintf(logfp,"%7.2f %f %f\n",-best_bd.day,best_bd.flux,rmsbd); } /* * Also print output to screen */ if(no_error) { printf(" call_xcorr_fff: B-A best lag = %7.2f d (%f = %6.2f sigma)\n", -best_ba.day,best_ba.flux,(best_ba.flux / rmsba)); printf(" call_xcorr_fft: B-C best lag = %7.2f d (%f = %6.2f sigma)\n", -best_bc.day,best_bc.flux,(best_bc.flux / rmsbc)); printf(" call_xcorr_fft: B-D best lag = %7.2f d (%f = %6.2f sigma)\n", -best_bd.day,best_bd.flux,(best_bd.flux / rmsbd)); } /* * Clean up */ for(i=0; i<N08; i++) zmean[i] = del_fluxrec(zmean[i]); corrbc = del_fluxrec(corrbc); corrba = del_fluxrec(corrba); corrbd = del_fluxrec(corrbd); if(ofp) fclose(ofp); if(no_error) return 0; else { fprintf(stderr,"ERROR: call_xcorr_fft\n"); return 1; } }
int gmx_msd(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the mean square displacement (MSD) of atoms from", "a set of initial positions. This provides an easy way to compute", "the diffusion constant using the Einstein relation.", "The time between the reference points for the MSD calculation", "is set with [TT]-trestart[tt].", "The diffusion constant is calculated by least squares fitting a", "straight line (D*t + c) through the MSD(t) from [TT]-beginfit[tt] to", "[TT]-endfit[tt] (note that t is time from the reference positions,", "not simulation time). An error estimate given, which is the difference", "of the diffusion coefficients obtained from fits over the two halves", "of the fit interval.[PAR]", "There are three, mutually exclusive, options to determine different", "types of mean square displacement: [TT]-type[tt], [TT]-lateral[tt]", "and [TT]-ten[tt]. Option [TT]-ten[tt] writes the full MSD tensor for", "each group, the order in the output is: trace xx yy zz yx zx zy.[PAR]", "If [TT]-mol[tt] is set, [THISMODULE] plots the MSD for individual molecules", "(including making molecules whole across periodic boundaries): ", "for each individual molecule a diffusion constant is computed for ", "its center of mass. The chosen index group will be split into ", "molecules.[PAR]", "The default way to calculate a MSD is by using mass-weighted averages.", "This can be turned off with [TT]-nomw[tt].[PAR]", "With the option [TT]-rmcomm[tt], the center of mass motion of a ", "specific group can be removed. For trajectories produced with ", "GROMACS this is usually not necessary, ", "as [gmx-mdrun] usually already removes the center of mass motion.", "When you use this option be sure that the whole system is stored", "in the trajectory file.[PAR]", "The diffusion coefficient is determined by linear regression of the MSD,", "where, unlike for the normal output of D, the times are weighted", "according to the number of reference points, i.e. short times have", "a higher weight. Also when [TT]-beginfit[tt]=-1,fitting starts at 10%", "and when [TT]-endfit[tt]=-1, fitting goes to 90%.", "Using this option one also gets an accurate error estimate", "based on the statistics between individual molecules.", "Note that this diffusion coefficient and error estimate are only", "accurate when the MSD is completely linear between", "[TT]-beginfit[tt] and [TT]-endfit[tt].[PAR]", "Option [TT]-pdb[tt] writes a [REF].pdb[ref] file with the coordinates of the frame", "at time [TT]-tpdb[tt] with in the B-factor field the square root of", "the diffusion coefficient of the molecule.", "This option implies option [TT]-mol[tt]." }; static const char *normtype[] = { NULL, "no", "x", "y", "z", NULL }; static const char *axtitle[] = { NULL, "no", "x", "y", "z", NULL }; static int ngroup = 1; static real dt = 10; static real t_pdb = 0; static real beginfit = -1; static real endfit = -1; static gmx_bool bTen = FALSE; static gmx_bool bMW = TRUE; static gmx_bool bRmCOMM = FALSE; t_pargs pa[] = { { "-type", FALSE, etENUM, {normtype}, "Compute diffusion coefficient in one direction" }, { "-lateral", FALSE, etENUM, {axtitle}, "Calculate the lateral diffusion in a plane perpendicular to" }, { "-ten", FALSE, etBOOL, {&bTen}, "Calculate the full tensor" }, { "-ngroup", FALSE, etINT, {&ngroup}, "Number of groups to calculate MSD for" }, { "-mw", FALSE, etBOOL, {&bMW}, "Mass weighted MSD" }, { "-rmcomm", FALSE, etBOOL, {&bRmCOMM}, "Remove center of mass motion" }, { "-tpdb", FALSE, etTIME, {&t_pdb}, "The frame to use for option [TT]-pdb[tt] (%t)" }, { "-trestart", FALSE, etTIME, {&dt}, "Time between restarting points in trajectory (%t)" }, { "-beginfit", FALSE, etTIME, {&beginfit}, "Start time for fitting the MSD (%t), -1 is 10%" }, { "-endfit", FALSE, etTIME, {&endfit}, "End time for fitting the MSD (%t), -1 is 90%" } }; t_filenm fnm[] = { { efTRX, NULL, NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "msd", ffWRITE }, { efXVG, "-mol", "diff_mol", ffOPTWR }, { efPDB, "-pdb", "diff_mol", ffOPTWR } }; #define NFILE asize(fnm) t_topology top; int ePBC; matrix box; char title[256]; const char *trx_file, *tps_file, *ndx_file, *msd_file, *mol_file, *pdb_file; rvec *xdum; gmx_bool bTop; int axis, type; real dim_factor; output_env_t oenv; if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_TIME_UNIT, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } trx_file = ftp2fn_null(efTRX, NFILE, fnm); tps_file = ftp2fn_null(efTPS, NFILE, fnm); ndx_file = ftp2fn_null(efNDX, NFILE, fnm); msd_file = ftp2fn_null(efXVG, NFILE, fnm); pdb_file = opt2fn_null("-pdb", NFILE, fnm); if (pdb_file) { mol_file = opt2fn("-mol", NFILE, fnm); } else { mol_file = opt2fn_null("-mol", NFILE, fnm); } if (ngroup < 1) { gmx_fatal(FARGS, "Must have at least 1 group (now %d)", ngroup); } if (mol_file && ngroup > 1) { gmx_fatal(FARGS, "With molecular msd can only have 1 group (now %d)", ngroup); } if (mol_file) { bMW = TRUE; fprintf(stderr, "Calculating diffusion coefficients for molecules.\n"); } GMX_RELEASE_ASSERT(normtype[0] != 0, "Options inconsistency; normtype[0] is NULL"); GMX_RELEASE_ASSERT(axtitle[0] != 0, "Options inconsistency; axtitle[0] is NULL"); if (normtype[0][0] != 'n') { type = normtype[0][0] - 'x' + X; /* See defines above */ dim_factor = 2.0; } else { type = NORMAL; dim_factor = 6.0; } if ((type == NORMAL) && (axtitle[0][0] != 'n')) { type = LATERAL; dim_factor = 4.0; axis = (axtitle[0][0] - 'x'); /* See defines above */ } else { axis = 0; } if (bTen && type != NORMAL) { gmx_fatal(FARGS, "Can only calculate the full tensor for 3D msd"); } bTop = read_tps_conf(tps_file, title, &top, &ePBC, &xdum, NULL, box, bMW || bRmCOMM); if (mol_file && !bTop) { gmx_fatal(FARGS, "Could not read a topology from %s. Try a tpr file instead.", tps_file); } do_corr(trx_file, ndx_file, msd_file, mol_file, pdb_file, t_pdb, ngroup, &top, ePBC, bTen, bMW, bRmCOMM, type, dim_factor, axis, dt, beginfit, endfit, oenv); view_all(oenv, NFILE, fnm); return 0; }
int call_acorr(Fluxrec *flux[], int size, char *filename, int nbad) { int i; /* Looping variable */ int no_error=1; /* Flag set to 0 on error */ int corsize; /* Length of correlation curves */ Fluxrec *zmean[N08]={NULL}; /* Zero-mean light curves */ Fluxrec *corra=NULL; /* Auto-correlation for A */ Fluxrec *corrb=NULL; /* Auto-correlation for B */ Fluxrec *corrc=NULL; /* Auto-correlation for C */ Fluxrec *corrd=NULL; /* Auto-correlation for D */ Fluxrec *aptr,*bptr; /* Pointers to navigate auto-corr arrays */ Fluxrec *cptr,*dptr; /* Pointers to navigate auto-corr arrays */ FILE *ofp=NULL; /* Output file */ /* * Normalize the curves since we are looking for correlations in * fractional variations and then subtract 1 to create a zero-mean * light curve. This helps by getting rid of the DC component in * the autocorrelation. */ for(i=0; i<N08; i++) { if(no_error) if(!(zmean[i] = norm_zero_mean(flux[i],size))) no_error = 0; } /* * Do the autocorrelations */ if(!(corra = do_corr(zmean[0],zmean[0],size,&corsize,nbad))) { fprintf(stderr,"ERROR: call_acorr\n"); return 1; } if(!(corrb = do_corr(zmean[1],zmean[1],size,&corsize,nbad))) no_error = 0; if(no_error) if(!(corrc = do_corr(zmean[2],zmean[2],size,&corsize,nbad))) no_error = 0; if(no_error) if(!(corrd = do_corr(zmean[3],zmean[3],size,&corsize,nbad))) no_error = 0; if(no_error) if((ofp = fopen(filename,"w")) == NULL) { fprintf(stderr,"ERROR: call_acorr. Cannot open %s\n",filename); no_error = 0; } if(no_error) { fprintf(ofp,"# Lag Acorr_a Acorr_b Acorr_c Acorr_d\n"); fprintf(ofp,"#------- -------- ------- ------- -------\n"); for(i=0,aptr=corra,bptr=corrb,cptr=corrc,dptr=corrd; i<corsize; i++,aptr++,bptr++,cptr++,dptr++) fprintf(ofp,"%8.3f %8.5f %8.5f %8.5f %8.5f\n", aptr->day,aptr->flux,bptr->flux,cptr->flux,dptr->flux); } /* * Clean up */ for(i=0; i<N08; i++) zmean[i] = del_fluxrec(zmean[i]); corra = del_fluxrec(corra); corrb = del_fluxrec(corrb); corrc = del_fluxrec(corrc); corrd = del_fluxrec(corrd); if(ofp) fclose(ofp); if(no_error) return 0; else { fprintf(stderr,"ERROR: call_acorr\n"); return 1; } }