void xvgr_new_dataset(FILE *out, int nr_first, int nsets, const char **setname, const output_env_t oenv) { int i; char buf[STRLEN]; if (output_env_get_print_xvgr_codes(oenv)) { fprintf(out, "@\n"); for (i = 0; (i < nsets); i++) { if (setname[i]) { if (output_env_get_xvg_format(oenv) == exvgXMGR) { fprintf(out, "@ legend string %d \"%s\"\n", i+nr_first, xvgrstr(setname[i], oenv, buf, STRLEN)); } else { fprintf(out, "@ s%d legend \"%s\"\n", i+nr_first, xvgrstr(setname[i], oenv, buf, STRLEN)); } } } } else { fprintf(out, "\n"); } }
void xvgr_legend(FILE *out, int nsets, const char** setname, const output_env_t oenv) { int i; char buf[STRLEN]; if (output_env_get_print_xvgr_codes(oenv)) { xvgr_view(out, 0.15, 0.15, 0.75, 0.85, oenv); fprintf(out, "@ legend on\n"); fprintf(out, "@ legend box on\n"); fprintf(out, "@ legend loctype view\n"); fprintf(out, "@ legend %g, %g\n", 0.78, 0.8); fprintf(out, "@ legend length %d\n", 2); for (i = 0; (i < nsets); i++) { if (setname[i]) { if (output_env_get_xvg_format(oenv) == exvgXMGR) { fprintf(out, "@ legend string %d \"%s\"\n", i, xvgrstr(setname[i], oenv, buf, STRLEN)); } else { fprintf(out, "@ s%d legend \"%s\"\n", i, xvgrstr(setname[i], oenv, buf, STRLEN)); } } } } }
void histogram(const char *distfile, real binwidth, int n, int nset, real **val, const gmx_output_env_t *oenv) { FILE *fp; int i, s; double minval, maxval; int nbin; gmx_int64_t *histo; minval = val[0][0]; maxval = val[0][0]; for (s = 0; s < nset; s++) { for (i = 0; i < n; i++) { if (val[s][i] < minval) { minval = val[s][i]; } else if (val[s][i] > maxval) { maxval = val[s][i]; } } } minval = binwidth*std::floor(minval/binwidth); maxval = binwidth*std::ceil(maxval/binwidth); if (minval != 0) { minval -= binwidth; } maxval += binwidth; nbin = static_cast<int>(((maxval - minval)/binwidth + 0.5) + 1); fprintf(stderr, "Making distributions with %d bins\n", nbin); snew(histo, nbin); fp = xvgropen(distfile, "Distribution", "", "", oenv); for (s = 0; s < nset; s++) { for (i = 0; i < nbin; i++) { histo[i] = 0; } for (i = 0; i < n; i++) { histo[static_cast<int>((val[s][i] - minval)/binwidth + 0.5)]++; } for (i = 0; i < nbin; i++) { fprintf(fp, " %g %g\n", minval+i*binwidth, static_cast<double>(histo[i])/(n*binwidth)); } if (s < nset-1) { fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } } xvgrclose(fp); }
void histogram(const char *distfile, real binwidth, int n, int nset, real **val, const output_env_t oenv) { FILE *fp; int i, s; double min, max; int nbin; gmx_int64_t *histo; min = val[0][0]; max = val[0][0]; for (s = 0; s < nset; s++) { for (i = 0; i < n; i++) { if (val[s][i] < min) { min = val[s][i]; } else if (val[s][i] > max) { max = val[s][i]; } } } min = binwidth*floor(min/binwidth); max = binwidth*ceil(max/binwidth); if (min != 0) { min -= binwidth; } max += binwidth; nbin = (int)((max - min)/binwidth + 0.5) + 1; fprintf(stderr, "Making distributions with %d bins\n", nbin); snew(histo, nbin); fp = xvgropen(distfile, "Distribution", "", "", oenv); for (s = 0; s < nset; s++) { for (i = 0; i < nbin; i++) { histo[i] = 0; } for (i = 0; i < n; i++) { histo[(int)((val[s][i] - min)/binwidth + 0.5)]++; } for (i = 0; i < nbin; i++) { fprintf(fp, " %g %g\n", min+i*binwidth, (double)histo[i]/(n*binwidth)); } if (s < nset-1) { fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } } gmx_ffclose(fp); }
void xvgr_view(FILE *out, real xmin, real ymin, real xmax, real ymax, const output_env_t oenv) { if (output_env_get_print_xvgr_codes(oenv)) { fprintf(out, "@ view %g, %g, %g, %g\n", xmin, ymin, xmax, ymax); } }
void xvgr_subtitle(FILE *out, const char *subtitle, const output_env_t oenv) { char buf[STRLEN]; if (output_env_get_print_xvgr_codes(oenv)) { fprintf(out, "@ subtitle \"%s\"\n", xvgrstr(subtitle, oenv, buf, STRLEN)); } }
void xvgr_line_props(FILE *out, int NrSet, int LineStyle, int LineColor, const output_env_t oenv) { if (output_env_get_print_xvgr_codes(oenv)) { fprintf(out, "@ with g0\n"); fprintf(out, "@ s%d linestyle %d\n", NrSet, LineStyle); fprintf(out, "@ s%d color %d\n", NrSet, LineColor); } }
void xvgr_world(FILE *out, real xmin, real ymin, real xmax, real ymax, const output_env_t oenv) { if (output_env_get_print_xvgr_codes(oenv)) { fprintf(out, "@ world xmin %g\n" "@ world ymin %g\n" "@ world xmax %g\n" "@ world ymax %g\n", xmin, ymin, xmax, ymax); } }
void AbstractPlotModule::dataStarted(AbstractAnalysisData * /* data */) { if (!impl_->filename_.empty()) { if (impl_->bPlain_) { impl_->fp_ = gmx_fio_fopen(impl_->filename_.c_str(), "w"); } else { time_unit_t time_unit = static_cast<time_unit_t>(impl_->settings_.timeUnit() + 1); xvg_format_t xvg_format = (impl_->settings_.plotFormat() > 0 ? static_cast<xvg_format_t>(impl_->settings_.plotFormat()) : exvgNONE); output_env_t oenv; output_env_init(&oenv, getProgramContext(), time_unit, FALSE, xvg_format, 0); boost::shared_ptr<output_env> oenvGuard(oenv, &output_env_done); impl_->fp_ = xvgropen(impl_->filename_.c_str(), impl_->title_.c_str(), impl_->xlabel_.c_str(), impl_->ylabel_.c_str(), oenv); const SelectionCollection *selections = impl_->settings_.selectionCollection(); if (selections != NULL) { selections->printXvgrInfo(impl_->fp_, oenv); } if (!impl_->subtitle_.empty()) { xvgr_subtitle(impl_->fp_, impl_->subtitle_.c_str(), oenv); } if (output_env_get_print_xvgr_codes(oenv) && !impl_->legend_.empty()) { std::vector<const char *> legend; legend.reserve(impl_->legend_.size()); for (size_t i = 0; i < impl_->legend_.size(); ++i) { legend.push_back(impl_->legend_[i].c_str()); } xvgr_legend(impl_->fp_, legend.size(), &legend[0], oenv); } } } }
void xvgr_header(FILE *fp, const char *title, const char *xaxis, const char *yaxis, int exvg_graph_type, const output_env_t oenv) { char pukestr[100], buf[STRLEN]; time_t t; if (output_env_get_print_xvgr_codes(oenv)) { time(&t); gmx_ctime_r(&t, buf, STRLEN); fprintf(fp, "# This file was created %s", buf); fprintf(fp, "# by the following command:\n# %s\n#\n", command_line()); fprintf(fp, "# %s is part of G R O M A C S:\n#\n", ShortProgram()); bromacs(pukestr, 99); fprintf(fp, "# %s\n#\n", pukestr); fprintf(fp, "@ title \"%s\"\n", xvgrstr(title, oenv, buf, STRLEN)); fprintf(fp, "@ xaxis label \"%s\"\n", xvgrstr(xaxis, oenv, buf, STRLEN)); fprintf(fp, "@ yaxis label \"%s\"\n", xvgrstr(yaxis, oenv, buf, STRLEN)); switch (exvg_graph_type) { case exvggtXNY: if (output_env_get_xvg_format(oenv) == exvgXMGR) { fprintf(fp, "@TYPE nxy\n"); } else { fprintf(fp, "@TYPE xy\n"); } break; case exvggtXYDY: fprintf(fp, "@TYPE xydy\n"); break; case exvggtXYDYDY: fprintf(fp, "@TYPE xydydy\n"); break; } } }
void xvgr_box(FILE *out, int LocType, real xmin, real ymin, real xmax, real ymax, int LineStyle, int LineWidth, int LineColor, int BoxFill, int BoxColor, int BoxPattern, const output_env_t oenv) { if (output_env_get_print_xvgr_codes(oenv)) { fprintf(out, "@with box\n"); fprintf(out, "@ box on\n"); fprintf(out, "@ box loctype %s\n", LocTypeStr[LocType]); fprintf(out, "@ box %g, %g, %g, %g\n", xmin, ymin, xmax, ymax); fprintf(out, "@ box linestyle %d\n", LineStyle); fprintf(out, "@ box linewidth %d\n", LineWidth); fprintf(out, "@ box color %d\n", LineColor); fprintf(out, "@ box fill %s\n", BoxFillStr[BoxFill]); fprintf(out, "@ box fill color %d\n", BoxColor); fprintf(out, "@ box fill pattern %d\n", BoxPattern); fprintf(out, "@box def\n"); } }
int gmx_g_angle(int argc, char *argv[]) { static const char *desc[] = { "[TT]g_angle[tt] computes the angle distribution for a number of angles", "or dihedrals.[PAR]", "With option [TT]-ov[tt], you can plot the average angle of", "a group of angles as a function of time. With the [TT]-all[tt] option,", "the first graph is the average and the rest are the individual angles.[PAR]", "With the [TT]-of[tt] option, [TT]g_angle[tt] also calculates the fraction of trans", "dihedrals (only for dihedrals) as function of time, but this is", "probably only fun for a select few.[PAR]", "With option [TT]-oc[tt], a dihedral correlation function is calculated.[PAR]", "It should be noted that the index file must contain", "atom triplets for angles or atom quadruplets for dihedrals.", "If this is not the case, the program will crash.[PAR]", "With option [TT]-or[tt], a trajectory file is dumped containing cos and", "sin of selected dihedral angles, which subsequently can be used as", "input for a principal components analysis using [TT]g_covar[tt].[PAR]", "Option [TT]-ot[tt] plots when transitions occur between", "dihedral rotamers of multiplicity 3 and [TT]-oh[tt]", "records a histogram of the times between such transitions,", "assuming the input trajectory frames are equally spaced in time." }; static const char *opt[] = { NULL, "angle", "dihedral", "improper", "ryckaert-bellemans", NULL }; static gmx_bool bALL = FALSE, bChandler = FALSE, bAverCorr = FALSE, bPBC = TRUE; static real binwidth = 1; t_pargs pa[] = { { "-type", FALSE, etENUM, {opt}, "Type of angle to analyse" }, { "-all", FALSE, etBOOL, {&bALL}, "Plot all angles separately in the averages file, in the order of appearance in the index file." }, { "-binwidth", FALSE, etREAL, {&binwidth}, "binwidth (degrees) for calculating the distribution" }, { "-periodic", FALSE, etBOOL, {&bPBC}, "Print dihedral angles modulo 360 degrees" }, { "-chandler", FALSE, etBOOL, {&bChandler}, "Use Chandler correlation function (N[trans] = 1, N[gauche] = 0) rather than cosine correlation function. Trans is defined as phi < -60 or phi > 60." }, { "-avercorr", FALSE, etBOOL, {&bAverCorr}, "Average the correlation functions for the individual angles/dihedrals" } }; static const char *bugs[] = { "Counting transitions only works for dihedrals with multiplicity 3" }; FILE *out; real tmp, dt; int status, isize; atom_id *index; char *grpname; real maxang, Jc, S2, norm_fac, maxstat; unsigned long mode; int nframes, maxangstat, mult, *angstat; int i, j, total, nangles, natoms, nat2, first, last, angind; gmx_bool bAver, bRb, bPeriodic, bFrac, /* calculate fraction too? */ bTrans, /* worry about transtions too? */ bCorr; /* correlation function ? */ real t, aa, aver, aver2, aversig, fraction; /* fraction trans dihedrals */ double tfrac = 0; char title[256]; real **dih = NULL; /* mega array with all dih. angles at all times*/ char buf[80]; real *time, *trans_frac, *aver_angle; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efNDX, NULL, "angle", ffREAD }, { efXVG, "-od", "angdist", ffWRITE }, { efXVG, "-ov", "angaver", ffOPTWR }, { efXVG, "-of", "dihfrac", ffOPTWR }, { efXVG, "-ot", "dihtrans", ffOPTWR }, { efXVG, "-oh", "trhisto", ffOPTWR }, { efXVG, "-oc", "dihcorr", ffOPTWR }, { efTRR, "-or", NULL, ffOPTWR } }; #define NFILE asize(fnm) int npargs; t_pargs *ppa; output_env_t oenv; npargs = asize(pa); ppa = add_acf_pargs(&npargs, pa); parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE, fnm, npargs, ppa, asize(desc), desc, asize(bugs), bugs, &oenv); mult = 4; maxang = 360.0; bRb = FALSE; switch (opt[0][0]) { case 'a': mult = 3; maxang = 180.0; break; case 'd': break; case 'i': break; case 'r': bRb = TRUE; break; } if (opt2bSet("-or", NFILE, fnm)) { if (mult != 4) { gmx_fatal(FARGS, "Can not combine angles with trn dump"); } else { please_cite(stdout, "Mu2005a"); } } /* Calculate bin size */ maxangstat = (int)(maxang/binwidth+0.5); binwidth = maxang/maxangstat; rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname); nangles = isize/mult; if ((isize % mult) != 0) { gmx_fatal(FARGS, "number of index elements not multiple of %d, " "these can not be %s\n", mult, (mult == 3) ? "angle triplets" : "dihedral quadruplets"); } /* Check whether specific analysis has to be performed */ bCorr = opt2bSet("-oc", NFILE, fnm); bAver = opt2bSet("-ov", NFILE, fnm); bTrans = opt2bSet("-ot", NFILE, fnm); bFrac = opt2bSet("-of", NFILE, fnm); if (bTrans && opt[0][0] != 'd') { fprintf(stderr, "Option -ot should only accompany -type dihedral. Disabling -ot.\n"); bTrans = FALSE; } if (bChandler && !bCorr) { bCorr = TRUE; } if (bFrac && !bRb) { fprintf(stderr, "Warning:" " calculating fractions as defined in this program\n" "makes sense for Ryckaert Bellemans dihs. only. Ignoring -of\n\n"); bFrac = FALSE; } if ( (bTrans || bFrac || bCorr) && mult == 3) { gmx_fatal(FARGS, "Can only do transition, fraction or correlation\n" "on dihedrals. Select -d\n"); } /* * We need to know the nr of frames so we can allocate memory for an array * with all dihedral angles at all timesteps. Works for me. */ if (bTrans || bCorr || bALL || opt2bSet("-or", NFILE, fnm)) { snew(dih, nangles); } snew(angstat, maxangstat); read_ang_dih(ftp2fn(efTRX, NFILE, fnm), (mult == 3), bALL || bCorr || bTrans || opt2bSet("-or", NFILE, fnm), bRb, bPBC, maxangstat, angstat, &nframes, &time, isize, index, &trans_frac, &aver_angle, dih, oenv); dt = (time[nframes-1]-time[0])/(nframes-1); if (bAver) { sprintf(title, "Average Angle: %s", grpname); out = xvgropen(opt2fn("-ov", NFILE, fnm), title, "Time (ps)", "Angle (degrees)", oenv); for (i = 0; (i < nframes); i++) { fprintf(out, "%10.5f %8.3f", time[i], aver_angle[i]*RAD2DEG); if (bALL) { for (j = 0; (j < nangles); j++) { if (bPBC) { real dd = dih[j][i]; fprintf(out, " %8.3f", atan2(sin(dd), cos(dd))*RAD2DEG); } else { fprintf(out, " %8.3f", dih[j][i]*RAD2DEG); } } } fprintf(out, "\n"); } ffclose(out); } if (opt2bSet("-or", NFILE, fnm)) { dump_dih_trn(nframes, nangles, dih, opt2fn("-or", NFILE, fnm), time); } if (bFrac) { sprintf(title, "Trans fraction: %s", grpname); out = xvgropen(opt2fn("-of", NFILE, fnm), title, "Time (ps)", "Fraction", oenv); tfrac = 0.0; for (i = 0; (i < nframes); i++) { fprintf(out, "%10.5f %10.3f\n", time[i], trans_frac[i]); tfrac += trans_frac[i]; } ffclose(out); tfrac /= nframes; fprintf(stderr, "Average trans fraction: %g\n", tfrac); } sfree(trans_frac); if (bTrans) { ana_dih_trans(opt2fn("-ot", NFILE, fnm), opt2fn("-oh", NFILE, fnm), dih, nframes, nangles, grpname, time, bRb, oenv); } if (bCorr) { /* Autocorrelation function */ if (nframes < 2) { fprintf(stderr, "Not enough frames for correlation function\n"); } else { if (bChandler) { real dval, sixty = DEG2RAD*60; gmx_bool bTest; for (i = 0; (i < nangles); i++) { for (j = 0; (j < nframes); j++) { dval = dih[i][j]; if (bRb) { bTest = (dval > -sixty) && (dval < sixty); } else { bTest = (dval < -sixty) || (dval > sixty); } if (bTest) { dih[i][j] = dval-tfrac; } else { dih[i][j] = -tfrac; } } } } if (bChandler) { mode = eacNormal; } else { mode = eacCos; } do_autocorr(opt2fn("-oc", NFILE, fnm), oenv, "Dihedral Autocorrelation Function", nframes, nangles, dih, dt, mode, bAverCorr); } } /* Determine the non-zero part of the distribution */ for (first = 0; (first < maxangstat-1) && (angstat[first+1] == 0); first++) { ; } for (last = maxangstat-1; (last > 0) && (angstat[last-1] == 0); last--) { ; } aver = aver2 = 0; for (i = 0; (i < nframes); i++) { aver += RAD2DEG*aver_angle[i]; aver2 += sqr(RAD2DEG*aver_angle[i]); } aver /= (real) nframes; aver2 /= (real) nframes; aversig = sqrt(aver2-sqr(aver)); printf("Found points in the range from %d to %d (max %d)\n", first, last, maxangstat); printf(" < angle > = %g\n", aver); printf("< angle^2 > = %g\n", aver2); printf("Std. Dev. = %g\n", aversig); if (mult == 3) { sprintf(title, "Angle Distribution: %s", grpname); } else { sprintf(title, "Dihedral Distribution: %s", grpname); calc_distribution_props(maxangstat, angstat, -180.0, 0, NULL, &S2); fprintf(stderr, "Order parameter S^2 = %g\n", S2); } bPeriodic = (mult == 4) && (first == 0) && (last == maxangstat-1); out = xvgropen(opt2fn("-od", NFILE, fnm), title, "Degrees", "", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(out, "@ subtitle \"average angle: %g\\So\\N\"\n", aver); } norm_fac = 1.0/(nangles*nframes*binwidth); if (bPeriodic) { maxstat = 0; for (i = first; (i <= last); i++) { maxstat = max(maxstat, angstat[i]*norm_fac); } fprintf(out, "@with g0\n"); fprintf(out, "@ world xmin -180\n"); fprintf(out, "@ world xmax 180\n"); fprintf(out, "@ world ymin 0\n"); fprintf(out, "@ world ymax %g\n", maxstat*1.05); fprintf(out, "@ xaxis tick major 60\n"); fprintf(out, "@ xaxis tick minor 30\n"); fprintf(out, "@ yaxis tick major 0.005\n"); fprintf(out, "@ yaxis tick minor 0.0025\n"); } for (i = first; (i <= last); i++) { fprintf(out, "%10g %10f\n", i*binwidth+180.0-maxang, angstat[i]*norm_fac); } if (bPeriodic) { /* print first bin again as last one */ fprintf(out, "%10g %10f\n", 180.0, angstat[0]*norm_fac); } ffclose(out); do_view(oenv, opt2fn("-od", NFILE, fnm), "-nxy"); if (bAver) { do_view(oenv, opt2fn("-ov", NFILE, fnm), "-nxy"); } thanx(stderr); return 0; }
int gmx_nmeig(int argc, char *argv[]) { const char *desc[] = { "[TT]g_nmeig[tt] calculates the eigenvectors/values of a (Hessian) matrix,", "which can be calculated with [TT]mdrun[tt].", "The eigenvectors are written to a trajectory file ([TT]-v[tt]).", "The structure is written first with t=0. The eigenvectors", "are written as frames with the eigenvector number as timestamp.", "The eigenvectors can be analyzed with [TT]g_anaeig[tt].", "An ensemble of structures can be generated from the eigenvectors with", "[TT]g_nmens[tt]. When mass weighting is used, the generated eigenvectors", "will be scaled back to plain Cartesian coordinates before generating the", "output. In this case, they will no longer be exactly orthogonal in the", "standard Cartesian norm, but in the mass-weighted norm they would be.[PAR]", "This program can be optionally used to compute quantum corrections to heat capacity", "and enthalpy by providing an extra file argument [TT]-qcorr[tt]. See the GROMACS", "manual, Chapter 1, for details. The result includes subtracting a harmonic", "degree of freedom at the given temperature.", "The total correction is printed on the terminal screen.", "The recommended way of getting the corrections out is:[PAR]", "[TT]g_nmeig -s topol.tpr -f nm.mtx -first 7 -last 10000 -T 300 -qc [-constr][tt][PAR]", "The [TT]-constr[tt] option should be used when bond constraints were used during the", "simulation [BB]for all the covalent bonds[bb]. If this is not the case, ", "you need to analyze the [TT]quant_corr.xvg[tt] file yourself.[PAR]", "To make things more flexible, the program can also take virtual sites into account", "when computing quantum corrections. When selecting [TT]-constr[tt] and", "[TT]-qc[tt], the [TT]-begin[tt] and [TT]-end[tt] options will be set automatically as well.", "Again, if you think you know it better, please check the [TT]eigenfreq.xvg[tt]", "output." }; static gmx_bool bM = TRUE, bCons = FALSE; static int begin = 1, end = 50, maxspec = 4000; static real T = 298.15, width = 1; t_pargs pa[] = { { "-m", FALSE, etBOOL, {&bM}, "Divide elements of Hessian by product of sqrt(mass) of involved " "atoms prior to diagonalization. This should be used for 'Normal Modes' " "analysis" }, { "-first", FALSE, etINT, {&begin}, "First eigenvector to write away" }, { "-last", FALSE, etINT, {&end}, "Last eigenvector to write away" }, { "-maxspec", FALSE, etINT, {&maxspec}, "Highest frequency (1/cm) to consider in the spectrum" }, { "-T", FALSE, etREAL, {&T}, "Temperature for computing quantum heat capacity and enthalpy when using normal mode calculations to correct classical simulations" }, { "-constr", FALSE, etBOOL, {&bCons}, "If constraints were used in the simulation but not in the normal mode analysis (this is the recommended way of doing it) you will need to set this for computing the quantum corrections." }, { "-width", FALSE, etREAL, {&width}, "Width (sigma) of the gaussian peaks (1/cm) when generating a spectrum" } }; FILE *out, *qc, *spec; int status, trjout; t_topology top; gmx_mtop_t mtop; int ePBC; rvec *top_x; matrix box; real *eigenvalues; real *eigenvectors; real rdum, mass_fac, qcvtot, qutot, qcv, qu; int natoms, ndim, nrow, ncol, count, nharm, nvsite; char *grpname; int i, j, k, l, d, gnx; gmx_bool bSuck; atom_id *index; t_tpxheader tpx; int version, generation; real value, omega, nu; real factor_gmx_to_omega2; real factor_omega_to_wavenumber; real *spectrum = NULL; real wfac; output_env_t oenv; const char *qcleg[] = { "Heat Capacity cV (J/mol K)", "Enthalpy H (kJ/mol)" }; real * full_hessian = NULL; gmx_sparsematrix_t * sparse_hessian = NULL; t_filenm fnm[] = { { efMTX, "-f", "hessian", ffREAD }, { efTPX, NULL, NULL, ffREAD }, { efXVG, "-of", "eigenfreq", ffWRITE }, { efXVG, "-ol", "eigenval", ffWRITE }, { efXVG, "-os", "spectrum", ffOPTWR }, { efXVG, "-qc", "quant_corr", ffOPTWR }, { efTRN, "-v", "eigenvec", ffWRITE } }; #define NFILE asize(fnm) parse_common_args(&argc, argv, PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv); /* Read tpr file for volume and number of harmonic terms */ read_tpxheader(ftp2fn(efTPX, NFILE, fnm), &tpx, TRUE, &version, &generation); snew(top_x, tpx.natoms); read_tpx(ftp2fn(efTPX, NFILE, fnm), NULL, box, &natoms, top_x, NULL, NULL, &mtop); if (bCons) { nharm = get_nharm(&mtop, &nvsite); } else { nharm = 0; nvsite = 0; } top = gmx_mtop_t_to_t_topology(&mtop); bM = TRUE; ndim = DIM*natoms; if (opt2bSet("-qc", NFILE, fnm)) { begin = 7+DIM*nvsite; end = DIM*natoms; } if (begin < 1) { begin = 1; } if (end > ndim) { end = ndim; } printf("Using begin = %d and end = %d\n", begin, end); /*open Hessian matrix */ gmx_mtxio_read(ftp2fn(efMTX, NFILE, fnm), &nrow, &ncol, &full_hessian, &sparse_hessian); /* Memory for eigenvalues and eigenvectors (begin..end) */ snew(eigenvalues, nrow); snew(eigenvectors, nrow*(end-begin+1)); /* If the Hessian is in sparse format we can calculate max (ndim-1) eigenvectors, * and they must start at the first one. If this is not valid we convert to full matrix * storage, but warn the user that we might run out of memory... */ if ((sparse_hessian != NULL) && (begin != 1 || end == ndim)) { if (begin != 1) { fprintf(stderr, "Cannot use sparse Hessian with first eigenvector != 1.\n"); } else if (end == ndim) { fprintf(stderr, "Cannot use sparse Hessian to calculate all eigenvectors.\n"); } fprintf(stderr, "Will try to allocate memory and convert to full matrix representation...\n"); snew(full_hessian, nrow*ncol); for (i = 0; i < nrow*ncol; i++) { full_hessian[i] = 0; } for (i = 0; i < sparse_hessian->nrow; i++) { for (j = 0; j < sparse_hessian->ndata[i]; j++) { k = sparse_hessian->data[i][j].col; value = sparse_hessian->data[i][j].value; full_hessian[i*ndim+k] = value; full_hessian[k*ndim+i] = value; } } gmx_sparsematrix_destroy(sparse_hessian); sparse_hessian = NULL; fprintf(stderr, "Converted sparse to full matrix storage.\n"); } if (full_hessian != NULL) { /* Using full matrix storage */ nma_full_hessian(full_hessian, nrow, bM, &top, begin, end, eigenvalues, eigenvectors); } else { /* Sparse memory storage, allocate memory for eigenvectors */ snew(eigenvectors, ncol*end); nma_sparse_hessian(sparse_hessian, bM, &top, end, eigenvalues, eigenvectors); } /* check the output, first 6 eigenvalues should be reasonably small */ bSuck = FALSE; for (i = begin-1; (i < 6); i++) { if (fabs(eigenvalues[i]) > 1.0e-3) { bSuck = TRUE; } } if (bSuck) { fprintf(stderr, "\nOne of the lowest 6 eigenvalues has a non-zero value.\n"); fprintf(stderr, "This could mean that the reference structure was not\n"); fprintf(stderr, "properly energy minimized.\n"); } /* now write the output */ fprintf (stderr, "Writing eigenvalues...\n"); out = xvgropen(opt2fn("-ol", NFILE, fnm), "Eigenvalues", "Eigenvalue index", "Eigenvalue [Gromacs units]", oenv); if (output_env_get_print_xvgr_codes(oenv)) { if (bM) { fprintf(out, "@ subtitle \"mass weighted\"\n"); } else { fprintf(out, "@ subtitle \"not mass weighted\"\n"); } } for (i = 0; i <= (end-begin); i++) { fprintf (out, "%6d %15g\n", begin+i, eigenvalues[i]); } ffclose(out); if (opt2bSet("-qc", NFILE, fnm)) { qc = xvgropen(opt2fn("-qc", NFILE, fnm), "Quantum Corrections", "Eigenvector index", "", oenv); xvgr_legend(qc, asize(qcleg), qcleg, oenv); qcvtot = qutot = 0; } else { qc = NULL; } printf("Writing eigenfrequencies - negative eigenvalues will be set to zero.\n"); out = xvgropen(opt2fn("-of", NFILE, fnm), "Eigenfrequencies", "Eigenvector index", "Wavenumber [cm\\S-1\\N]", oenv); if (output_env_get_print_xvgr_codes(oenv)) { if (bM) { fprintf(out, "@ subtitle \"mass weighted\"\n"); } else { fprintf(out, "@ subtitle \"not mass weighted\"\n"); } } /* Spectrum ? */ spec = NULL; if (opt2bSet("-os", NFILE, fnm) && (maxspec > 0)) { snew(spectrum, maxspec); spec = xvgropen(opt2fn("-os", NFILE, fnm), "Vibrational spectrum based on harmonic approximation", "\\f{12}w\\f{4} (cm\\S-1\\N)", "Intensity [Gromacs units]", oenv); for (i = 0; (i < maxspec); i++) { spectrum[i] = 0; } } /* Gromacs units are kJ/(mol*nm*nm*amu), * where amu is the atomic mass unit. * * For the eigenfrequencies we want to convert this to spectroscopic absorption * wavenumbers given in cm^(-1), which is the frequency divided by the speed of * light. Do this by first converting to omega^2 (units 1/s), take the square * root, and finally divide by the speed of light (nm/ps in gromacs). */ factor_gmx_to_omega2 = 1.0E21/(AVOGADRO*AMU); factor_omega_to_wavenumber = 1.0E-5/(2.0*M_PI*SPEED_OF_LIGHT); for (i = begin; (i <= end); i++) { value = eigenvalues[i-begin]; if (value < 0) { value = 0; } omega = sqrt(value*factor_gmx_to_omega2); nu = 1e-12*omega/(2*M_PI); value = omega*factor_omega_to_wavenumber; fprintf (out, "%6d %15g\n", i, value); if (NULL != spec) { wfac = eigenvalues[i-begin]/(width*sqrt(2*M_PI)); for (j = 0; (j < maxspec); j++) { spectrum[j] += wfac*exp(-sqr(j-value)/(2*sqr(width))); } } if (NULL != qc) { qcv = cv_corr(nu, T); qu = u_corr(nu, T); if (i > end-nharm) { qcv += BOLTZ*KILO; qu += BOLTZ*T; } fprintf (qc, "%6d %15g %15g\n", i, qcv, qu); qcvtot += qcv; qutot += qu; } } ffclose(out); if (NULL != spec) { for (j = 0; (j < maxspec); j++) { fprintf(spec, "%10g %10g\n", 1.0*j, spectrum[j]); } ffclose(spec); } if (NULL != qc) { printf("Quantum corrections for harmonic degrees of freedom\n"); printf("Use appropriate -first and -last options to get reliable results.\n"); printf("There were %d constraints and %d vsites in the simulation\n", nharm, nvsite); printf("Total correction to cV = %g J/mol K\n", qcvtot); printf("Total correction to H = %g kJ/mol\n", qutot); ffclose(qc); please_cite(stdout, "Caleman2011b"); } /* Writing eigenvectors. Note that if mass scaling was used, the eigenvectors * were scaled back from mass weighted cartesian to plain cartesian in the * nma_full_hessian() or nma_sparse_hessian() routines. Mass scaled vectors * will not be strictly orthogonal in plain cartesian scalar products. */ write_eigenvectors(opt2fn("-v", NFILE, fnm), natoms, eigenvectors, FALSE, begin, end, eWXR_NO, NULL, FALSE, top_x, bM, eigenvalues); thanx(stderr); return 0; }
int gmx_gyrate(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the radius of gyration of a molecule", "and the radii of gyration about the [IT]x[it]-, [IT]y[it]- and [IT]z[it]-axes,", "as a function of time. The atoms are explicitly mass weighted.[PAR]", "The axis components corresponds to the mass-weighted root-mean-square", "of the radii components orthogonal to each axis, for example:[PAR]", "Rg(x) = sqrt((sum_i m_i (R_i(y)^2 + R_i(z)^2))/(sum_i m_i)).[PAR]", "With the [TT]-nmol[tt] option the radius of gyration will be calculated", "for multiple molecules by splitting the analysis group in equally", "sized parts.[PAR]", "With the option [TT]-nz[tt] 2D radii of gyration in the [IT]x-y[it] plane", "of slices along the [IT]z[it]-axis are calculated." }; static int nmol = 1, nz = 0; static gmx_bool bQ = FALSE, bRot = FALSE, bMOI = FALSE; t_pargs pa[] = { { "-nmol", FALSE, etINT, {&nmol}, "The number of molecules to analyze" }, { "-q", FALSE, etBOOL, {&bQ}, "Use absolute value of the charge of an atom as weighting factor instead of mass" }, { "-p", FALSE, etBOOL, {&bRot}, "Calculate the radii of gyration about the principal axes." }, { "-moi", FALSE, etBOOL, {&bMOI}, "Calculate the moments of inertia (defined by the principal axes)." }, { "-nz", FALSE, etINT, {&nz}, "Calculate the 2D radii of gyration of this number of slices along the z-axis" }, }; FILE *out; t_trxstatus *status; t_topology top; int ePBC; rvec *x, *x_s; rvec xcm, gvec, gvec1; matrix box, trans; gmx_bool bACF; real **moi_trans = NULL; int max_moi = 0, delta_moi = 100; rvec d, d1; /* eigenvalues of inertia tensor */ real t, t0, tm, gyro; int natoms; char *grpname; int j, m, gnx, nam, mol; atom_id *index; gmx_output_env_t *oenv; gmx_rmpbc_t gpbc = NULL; const char *leg[] = { "Rg", "Rg\\sX\\N", "Rg\\sY\\N", "Rg\\sZ\\N" }; const char *legI[] = { "Itot", "I1", "I2", "I3" }; #define NLEG asize(leg) t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "gyrate", ffWRITE }, { efXVG, "-acf", "moi-acf", ffOPTWR }, }; #define NFILE asize(fnm) int npargs; t_pargs *ppa; npargs = asize(pa); ppa = add_acf_pargs(&npargs, pa); if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW, NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } bACF = opt2bSet("-acf", NFILE, fnm); if (bACF && nmol != 1) { gmx_fatal(FARGS, "Can only do acf with nmol=1"); } bRot = bRot || bMOI || bACF; /* if (nz > 0) bMOI = TRUE; */ if (bRot) { printf("Will rotate system along principal axes\n"); snew(moi_trans, DIM); } if (bMOI) { printf("Will print moments of inertia\n"); bQ = FALSE; } if (bQ) { printf("Will print radius normalised by charge\n"); } read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, NULL, box, TRUE); get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname); if (nmol > gnx || gnx % nmol != 0) { gmx_fatal(FARGS, "The number of atoms in the group (%d) is not a multiple of nmol (%d)", gnx, nmol); } nam = gnx/nmol; natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); snew(x_s, natoms); j = 0; t0 = t; if (bQ) { out = xvgropen(ftp2fn(efXVG, NFILE, fnm), "Radius of Charge (total and around axes)", "Time (ps)", "Rg (nm)", oenv); } else if (bMOI) { out = xvgropen(ftp2fn(efXVG, NFILE, fnm), "Moments of inertia (total and around axes)", "Time (ps)", "I (a.m.u. nm\\S2\\N)", oenv); } else { out = xvgropen(ftp2fn(efXVG, NFILE, fnm), "Radius of gyration (total and around axes)", "Time (ps)", "Rg (nm)", oenv); } if (bMOI) { xvgr_legend(out, NLEG, legI, oenv); } else { if (bRot) { if (output_env_get_print_xvgr_codes(oenv)) { fprintf(out, "@ subtitle \"Axes are principal component axes\"\n"); } } xvgr_legend(out, NLEG, leg, oenv); } if (nz == 0) { gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms); } do { if (nz == 0) { gmx_rmpbc_copy(gpbc, natoms, box, x, x_s); } gyro = 0; clear_rvec(gvec); clear_rvec(gvec1); clear_rvec(d); clear_rvec(d1); for (mol = 0; mol < nmol; mol++) { tm = sub_xcm(nz == 0 ? x_s : x, nam, index+mol*nam, top.atoms.atom, xcm, bQ); if (nz == 0) { gyro += calc_gyro(x_s, nam, index+mol*nam, top.atoms.atom, tm, gvec1, d1, bQ, bRot, bMOI, trans); } else { calc_gyro_z(x, box, nam, index+mol*nam, top.atoms.atom, nz, t, out); } rvec_inc(gvec, gvec1); rvec_inc(d, d1); } if (nmol > 0) { gyro /= nmol; svmul(1.0/nmol, gvec, gvec); svmul(1.0/nmol, d, d); } if (nz == 0) { if (bRot) { if (j >= max_moi) { max_moi += delta_moi; for (m = 0; (m < DIM); m++) { srenew(moi_trans[m], max_moi*DIM); } } for (m = 0; (m < DIM); m++) { copy_rvec(trans[m], moi_trans[m]+DIM*j); } fprintf(out, "%10g %10g %10g %10g %10g\n", t, gyro, d[XX], d[YY], d[ZZ]); } else { fprintf(out, "%10g %10g %10g %10g %10g\n", t, gyro, gvec[XX], gvec[YY], gvec[ZZ]); } } j++; } while (read_next_x(oenv, status, &t, x, box)); close_trj(status); if (nz == 0) { gmx_rmpbc_done(gpbc); } xvgrclose(out); if (bACF) { int mode = eacVector; do_autocorr(opt2fn("-acf", NFILE, fnm), oenv, "Moment of inertia vector ACF", j, 3, moi_trans, (t-t0)/j, mode, FALSE); do_view(oenv, opt2fn("-acf", NFILE, fnm), "-nxy"); } do_view(oenv, ftp2fn(efXVG, NFILE, fnm), "-nxy"); return 0; }
int gmx_analyze(int argc, char *argv[]) { static const char *desc[] = { "[THISMODULE] reads an ASCII file and analyzes data sets.", "A line in the input file may start with a time", "(see option [TT]-time[tt]) and any number of [IT]y[it]-values may follow.", "Multiple sets can also be", "read when they are separated by & (option [TT]-n[tt]);", "in this case only one [IT]y[it]-value is read from each line.", "All lines starting with # and @ are skipped.", "All analyses can also be done for the derivative of a set", "(option [TT]-d[tt]).[PAR]", "All options, except for [TT]-av[tt] and [TT]-power[tt], assume that the", "points are equidistant in time.[PAR]", "[THISMODULE] always shows the average and standard deviation of each", "set, as well as the relative deviation of the third", "and fourth cumulant from those of a Gaussian distribution with the same", "standard deviation.[PAR]", "Option [TT]-ac[tt] produces the autocorrelation function(s).", "Be sure that the time interval between data points is", "much shorter than the time scale of the autocorrelation.[PAR]", "Option [TT]-cc[tt] plots the resemblance of set i with a cosine of", "i/2 periods. The formula is::", "", " [MATH]2 ([INT][FROM]0[from][TO]T[to][int] y(t) [COS]i [GRK]pi[grk] t[cos] dt)^2 / [INT][FROM]0[from][TO]T[to][int] y^2(t) dt[math]", "", "This is useful for principal components obtained from covariance", "analysis, since the principal components of random diffusion are", "pure cosines.[PAR]", "Option [TT]-msd[tt] produces the mean square displacement(s).[PAR]", "Option [TT]-dist[tt] produces distribution plot(s).[PAR]", "Option [TT]-av[tt] produces the average over the sets.", "Error bars can be added with the option [TT]-errbar[tt].", "The errorbars can represent the standard deviation, the error", "(assuming the points are independent) or the interval containing", "90% of the points, by discarding 5% of the points at the top and", "the bottom.[PAR]", "Option [TT]-ee[tt] produces error estimates using block averaging.", "A set is divided in a number of blocks and averages are calculated for", "each block. The error for the total average is calculated from", "the variance between averages of the m blocks B[SUB]i[sub] as follows:", "error^2 = [SUM][sum] (B[SUB]i[sub] - [CHEVRON]B[chevron])^2 / (m*(m-1)).", "These errors are plotted as a function of the block size.", "Also an analytical block average curve is plotted, assuming", "that the autocorrelation is a sum of two exponentials.", "The analytical curve for the block average is::", "", " [MATH]f(t) = [GRK]sigma[grk][TT]*[tt][SQRT]2/T ( [GRK]alpha[grk] ([GRK]tau[grk][SUB]1[sub] (([EXP]-t/[GRK]tau[grk][SUB]1[sub][exp] - 1) [GRK]tau[grk][SUB]1[sub]/t + 1)) +", " (1-[GRK]alpha[grk]) ([GRK]tau[grk][SUB]2[sub] (([EXP]-t/[GRK]tau[grk][SUB]2[sub][exp] - 1) [GRK]tau[grk][SUB]2[sub]/t + 1)))[sqrt][math],", "", "where T is the total time.", "[GRK]alpha[grk], [GRK]tau[grk][SUB]1[sub] and [GRK]tau[grk][SUB]2[sub] are obtained by fitting f^2(t) to error^2.", "When the actual block average is very close to the analytical curve,", "the error is [MATH][GRK]sigma[grk][TT]*[tt][SQRT]2/T (a [GRK]tau[grk][SUB]1[sub] + (1-a) [GRK]tau[grk][SUB]2[sub])[sqrt][math].", "The complete derivation is given in", "B. Hess, J. Chem. Phys. 116:209-217, 2002.[PAR]", "Option [TT]-filter[tt] prints the RMS high-frequency fluctuation", "of each set and over all sets with respect to a filtered average.", "The filter is proportional to cos([GRK]pi[grk] t/len) where t goes from -len/2", "to len/2. len is supplied with the option [TT]-filter[tt].", "This filter reduces oscillations with period len/2 and len by a factor", "of 0.79 and 0.33 respectively.[PAR]", "Option [TT]-g[tt] fits the data to the function given with option", "[TT]-fitfn[tt].[PAR]", "Option [TT]-power[tt] fits the data to [MATH]b t^a[math], which is accomplished", "by fitting to [MATH]a t + b[math] on log-log scale. All points after the first", "zero or with a negative value are ignored.[PAR]" "Option [TT]-luzar[tt] performs a Luzar & Chandler kinetics analysis", "on output from [gmx-hbond]. The input file can be taken directly", "from [TT]gmx hbond -ac[tt], and then the same result should be produced.[PAR]", "Option [TT]-fitfn[tt] performs curve fitting to a number of different", "curves that make sense in the context of molecular dynamics, mainly", "exponential curves. More information is in the manual. To check the output", "of the fitting procedure the option [TT]-fitted[tt] will print both the", "original data and the fitted function to a new data file. The fitting", "parameters are stored as comment in the output file." }; static real tb = -1, te = -1, frac = 0.5, filtlen = 0, binwidth = 0.1, aver_start = 0; static gmx_bool bHaveT = TRUE, bDer = FALSE, bSubAv = TRUE, bAverCorr = FALSE, bXYdy = FALSE; static gmx_bool bEESEF = FALSE, bEENLC = FALSE, bEeFitAc = FALSE, bPower = FALSE; static gmx_bool bIntegrate = FALSE, bRegression = FALSE, bLuzar = FALSE; static int nsets_in = 1, d = 1, nb_min = 4, resol = 10; static real temp = 298.15, fit_start = 1, fit_end = 60; /* must correspond to enum avbar* declared at beginning of file */ static const char *avbar_opt[avbarNR+1] = { NULL, "none", "stddev", "error", "90", NULL }; t_pargs pa[] = { { "-time", FALSE, etBOOL, {&bHaveT}, "Expect a time in the input" }, { "-b", FALSE, etREAL, {&tb}, "First time to read from set" }, { "-e", FALSE, etREAL, {&te}, "Last time to read from set" }, { "-n", FALSE, etINT, {&nsets_in}, "Read this number of sets separated by &" }, { "-d", FALSE, etBOOL, {&bDer}, "Use the derivative" }, { "-dp", FALSE, etINT, {&d}, "HIDDENThe derivative is the difference over this number of points" }, { "-bw", FALSE, etREAL, {&binwidth}, "Binwidth for the distribution" }, { "-errbar", FALSE, etENUM, {avbar_opt}, "Error bars for [TT]-av[tt]" }, { "-integrate", FALSE, etBOOL, {&bIntegrate}, "Integrate data function(s) numerically using trapezium rule" }, { "-aver_start", FALSE, etREAL, {&aver_start}, "Start averaging the integral from here" }, { "-xydy", FALSE, etBOOL, {&bXYdy}, "Interpret second data set as error in the y values for integrating" }, { "-regression", FALSE, etBOOL, {&bRegression}, "Perform a linear regression analysis on the data. If [TT]-xydy[tt] is set a second set will be interpreted as the error bar in the Y value. Otherwise, if multiple data sets are present a multilinear regression will be performed yielding the constant A that minimize [MATH][GRK]chi[grk]^2 = (y - A[SUB]0[sub] x[SUB]0[sub] - A[SUB]1[sub] x[SUB]1[sub] - ... - A[SUB]N[sub] x[SUB]N[sub])^2[math] where now Y is the first data set in the input file and x[SUB]i[sub] the others. Do read the information at the option [TT]-time[tt]." }, { "-luzar", FALSE, etBOOL, {&bLuzar}, "Do a Luzar and Chandler analysis on a correlation function and " "related as produced by [gmx-hbond]. When in addition the " "[TT]-xydy[tt] flag is given the second and fourth column will be " "interpreted as errors in c(t) and n(t)." }, { "-temp", FALSE, etREAL, {&temp}, "Temperature for the Luzar hydrogen bonding kinetics analysis (K)" }, { "-fitstart", FALSE, etREAL, {&fit_start}, "Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation" }, { "-fitend", FALSE, etREAL, {&fit_end}, "Time (ps) where to stop fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation. Only with [TT]-gem[tt]" }, { "-nbmin", FALSE, etINT, {&nb_min}, "HIDDENMinimum number of blocks for block averaging" }, { "-resol", FALSE, etINT, {&resol}, "HIDDENResolution for the block averaging, block size increases with" " a factor 2^(1/resol)" }, { "-eeexpfit", FALSE, etBOOL, {&bEESEF}, "HIDDENAlways use a single exponential fit for the error estimate" }, { "-eenlc", FALSE, etBOOL, {&bEENLC}, "HIDDENAllow a negative long-time correlation" }, { "-eefitac", FALSE, etBOOL, {&bEeFitAc}, "HIDDENAlso plot analytical block average using a autocorrelation fit" }, { "-filter", FALSE, etREAL, {&filtlen}, "Print the high-frequency fluctuation after filtering with a cosine filter of this length" }, { "-power", FALSE, etBOOL, {&bPower}, "Fit data to: b t^a" }, { "-subav", FALSE, etBOOL, {&bSubAv}, "Subtract the average before autocorrelating" }, { "-oneacf", FALSE, etBOOL, {&bAverCorr}, "Calculate one ACF over all sets" }, }; #define NPA asize(pa) FILE *out; int n, nlast, s, nset, i, j = 0; real **val, *t, dt, tot, error; double *av, *sig, cum1, cum2, cum3, cum4, db; const char *acfile, *msdfile, *ccfile, *distfile, *avfile, *eefile, *fitfile; gmx_output_env_t *oenv; t_filenm fnm[] = { { efXVG, "-f", "graph", ffREAD }, { efXVG, "-ac", "autocorr", ffOPTWR }, { efXVG, "-msd", "msd", ffOPTWR }, { efXVG, "-cc", "coscont", ffOPTWR }, { efXVG, "-dist", "distr", ffOPTWR }, { efXVG, "-av", "average", ffOPTWR }, { efXVG, "-ee", "errest", ffOPTWR }, { efXVG, "-fitted", "fitted", ffOPTWR }, { efLOG, "-g", "fitlog", ffOPTWR } }; #define NFILE asize(fnm) int npargs; t_pargs *ppa; npargs = asize(pa); ppa = add_acf_pargs(&npargs, pa); if (!parse_common_args(&argc, argv, PCA_CAN_VIEW, NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } acfile = opt2fn_null("-ac", NFILE, fnm); msdfile = opt2fn_null("-msd", NFILE, fnm); ccfile = opt2fn_null("-cc", NFILE, fnm); distfile = opt2fn_null("-dist", NFILE, fnm); avfile = opt2fn_null("-av", NFILE, fnm); eefile = opt2fn_null("-ee", NFILE, fnm); if (opt2parg_bSet("-fitfn", npargs, ppa) && acfile == NULL) { fitfile = opt2fn("-g", NFILE, fnm); } else { fitfile = opt2fn_null("-g", NFILE, fnm); } val = read_xvg_time(opt2fn("-f", NFILE, fnm), bHaveT, opt2parg_bSet("-b", npargs, ppa), tb, opt2parg_bSet("-e", npargs, ppa), te, nsets_in, &nset, &n, &dt, &t); printf("Read %d sets of %d points, dt = %g\n\n", nset, n, dt); if (bDer) { printf("Calculating the derivative as (f[i+%d]-f[i])/(%d*dt)\n\n", d, d); n -= d; for (s = 0; s < nset; s++) { for (i = 0; (i < n); i++) { val[s][i] = (val[s][i+d]-val[s][i])/(d*dt); } } } if (bIntegrate) { real sum, stddev; printf("Calculating the integral using the trapezium rule\n"); if (bXYdy) { sum = evaluate_integral(n, t, val[0], val[1], aver_start, &stddev); printf("Integral %10.3f +/- %10.5f\n", sum, stddev); } else { for (s = 0; s < nset; s++) { sum = evaluate_integral(n, t, val[s], NULL, aver_start, &stddev); printf("Integral %d %10.5f +/- %10.5f\n", s+1, sum, stddev); } } } if (fitfile != NULL) { print_fitted_function(fitfile, opt2fn_null("-fitted", NFILE, fnm), bXYdy, nset, n, t, val, npargs, ppa, oenv); } printf(" std. dev. relative deviation of\n"); printf(" standard --------- cumulants from those of\n"); printf("set average deviation sqrt(n-1) a Gaussian distribition\n"); printf(" cum. 3 cum. 4\n"); snew(av, nset); snew(sig, nset); for (s = 0; (s < nset); s++) { cum1 = 0; cum2 = 0; cum3 = 0; cum4 = 0; for (i = 0; (i < n); i++) { cum1 += val[s][i]; } cum1 /= n; for (i = 0; (i < n); i++) { db = val[s][i]-cum1; cum2 += db*db; cum3 += db*db*db; cum4 += db*db*db*db; } cum2 /= n; cum3 /= n; cum4 /= n; av[s] = cum1; sig[s] = std::sqrt(cum2); if (n > 1) { error = std::sqrt(cum2/(n-1)); } else { error = 0; } printf("SS%d %13.6e %12.6e %12.6e %6.3f %6.3f\n", s+1, av[s], sig[s], error, sig[s] ? cum3/(sig[s]*sig[s]*sig[s]*std::sqrt(8/M_PI)) : 0, sig[s] ? cum4/(sig[s]*sig[s]*sig[s]*sig[s]*3)-1 : 0); } printf("\n"); if (filtlen) { filter(filtlen, n, nset, val, dt); } if (msdfile) { out = xvgropen(msdfile, "Mean square displacement", "time", "MSD (nm\\S2\\N)", oenv); nlast = static_cast<int>(n*frac); for (s = 0; s < nset; s++) { for (j = 0; j <= nlast; j++) { if (j % 100 == 0) { fprintf(stderr, "\r%d", j); } tot = 0; for (i = 0; i < n-j; i++) { tot += sqr(val[s][i]-val[s][i+j]); } tot /= (n-j); fprintf(out, " %g %8g\n", dt*j, tot); } if (s < nset-1) { fprintf(out, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } } xvgrclose(out); fprintf(stderr, "\r%d, time=%g\n", j-1, (j-1)*dt); } if (ccfile) { plot_coscont(ccfile, n, nset, val, oenv); } if (distfile) { histogram(distfile, binwidth, n, nset, val, oenv); } if (avfile) { average(avfile, nenum(avbar_opt), n, nset, val, t); } if (eefile) { estimate_error(eefile, nb_min, resol, n, nset, av, sig, val, dt, bEeFitAc, bEESEF, bEENLC, oenv); } if (bPower) { power_fit(n, nset, val, t); } if (acfile != NULL) { if (bSubAv) { for (s = 0; s < nset; s++) { for (i = 0; i < n; i++) { val[s][i] -= av[s]; } } } do_autocorr(acfile, oenv, "Autocorrelation", n, nset, val, dt, eacNormal, bAverCorr); } if (bRegression) { regression_analysis(n, bXYdy, t, nset, val); } if (bLuzar) { luzar_correl(n, t, nset, val, temp, bXYdy, fit_start); } view_all(oenv, NFILE, fnm); return 0; }
static void periodic_mindist_plot(const char *trxfn, const char *outfn, t_topology *top, int ePBC, int n, atom_id index[], gmx_bool bSplit, const output_env_t oenv) { FILE *out; const char *leg[5] = { "min per.", "max int.", "box1", "box2", "box3" }; t_trxstatus *status; real t; rvec *x; matrix box; int natoms, ind_min[2] = {0, 0}, ind_mini = 0, ind_minj = 0; real r, rmin, rmax, rmint, tmint; gmx_bool bFirst; gmx_rmpbc_t gpbc = NULL; natoms = read_first_x(oenv, &status, trxfn, &t, &x, box); check_index(NULL, n, index, NULL, natoms); out = xvgropen(outfn, "Minimum distance to periodic image", output_env_get_time_label(oenv), "Distance (nm)", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(out, "@ subtitle \"and maximum internal distance\"\n"); } xvgr_legend(out, 5, leg, oenv); rmint = box[XX][XX]; tmint = 0; if (NULL != top) { gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms); } bFirst = TRUE; do { if (NULL != top) { gmx_rmpbc(gpbc, natoms, box, x); } periodic_dist(box, x, n, index, &rmin, &rmax, ind_min); if (rmin < rmint) { rmint = rmin; tmint = t; ind_mini = ind_min[0]; ind_minj = ind_min[1]; } if (bSplit && !bFirst && abs(t/output_env_get_time_factor(oenv)) < 1e-5) { fprintf(out, "&\n"); } fprintf(out, "\t%g\t%6.3f %6.3f %6.3f %6.3f %6.3f\n", output_env_conv_time(oenv, t), rmin, rmax, norm(box[0]), norm(box[1]), norm(box[2])); bFirst = FALSE; } while (read_next_x(oenv, status, &t, x, box)); if (NULL != top) { gmx_rmpbc_done(gpbc); } ffclose(out); fprintf(stdout, "\nThe shortest periodic distance is %g (nm) at time %g (%s),\n" "between atoms %d and %d\n", rmint, output_env_conv_time(oenv, tmint), output_env_get_time_unit(oenv), index[ind_mini]+1, index[ind_minj]+1); }
void analyse_ss(const char *outfile, t_matrix *mat, const char *ss_string, const output_env_t oenv) { FILE *fp; t_mapping *map; int f, r, *count, *total, ss_count, total_count; size_t s; const char** leg; map = mat->map; snew(count, mat->nmap); snew(total, mat->nmap); snew(leg, mat->nmap+1); leg[0] = "Structure"; for (s = 0; s < (size_t)mat->nmap; s++) { leg[s+1] = gmx_strdup(map[s].desc); } fp = xvgropen(outfile, "Secondary Structure", output_env_get_xvgr_tlabel(oenv), "Number of Residues", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"Structure = "); } for (s = 0; s < strlen(ss_string); s++) { if (s > 0) { fprintf(fp, " + "); } for (f = 0; f < mat->nmap; f++) { if (ss_string[s] == map[f].code.c1) { fprintf(fp, "%s", map[f].desc); } } } fprintf(fp, "\"\n"); xvgr_legend(fp, mat->nmap+1, leg, oenv); total_count = 0; for (s = 0; s < (size_t)mat->nmap; s++) { total[s] = 0; } for (f = 0; f < mat->nx; f++) { ss_count = 0; for (s = 0; s < (size_t)mat->nmap; s++) { count[s] = 0; } for (r = 0; r < mat->ny; r++) { count[mat->matrix[f][r]]++; total[mat->matrix[f][r]]++; } for (s = 0; s < (size_t)mat->nmap; s++) { if (strchr(ss_string, map[s].code.c1)) { ss_count += count[s]; total_count += count[s]; } } fprintf(fp, "%8g %5d", mat->axis_x[f], ss_count); for (s = 0; s < (size_t)mat->nmap; s++) { fprintf(fp, " %5d", count[s]); } fprintf(fp, "\n"); } /* now print column totals */ fprintf(fp, "%-8s %5d", "# Totals", total_count); for (s = 0; s < (size_t)mat->nmap; s++) { fprintf(fp, " %5d", total[s]); } fprintf(fp, "\n"); /* now print percentages */ fprintf(fp, "%-8s %5.2f", "# SS %", total_count / (real) (mat->nx * mat->ny)); for (s = 0; s < (size_t)mat->nmap; s++) { fprintf(fp, " %5.2f", total[s] / (real) (mat->nx * mat->ny)); } fprintf(fp, "\n"); xvgrclose(fp); sfree(leg); sfree(count); }
void get_chi_product_traj (real **dih, int nframes, int nlist, int maxchi, t_dlist dlist[], real time[], int **lookup, int *multiplicity, gmx_bool bRb, gmx_bool bNormalize, real core_frac, gmx_bool bAll, const char *fnall, const gmx_output_env_t *oenv) { gmx_bool bRotZero, bHaveChi = FALSE; int accum = 0, index, i, j, k, Xi, n, b; real *chi_prtrj; int *chi_prhist; int nbin; FILE *fp, *fpall; char hisfile[256], histitle[256], *namept; int (*calc_bin)(real, int, real); /* Analysis of dihedral transitions */ fprintf(stderr, "Now calculating Chi product trajectories...\n"); if (bRb) { calc_bin = calc_RBbin; } else { calc_bin = calc_Nbin; } snew(chi_prtrj, nframes); /* file for info on all residues */ if (bNormalize) { fpall = xvgropen(fnall, "Cumulative Rotamers", "Residue", "Probability", oenv); } else { fpall = xvgropen(fnall, "Cumulative Rotamers", "Residue", "# Counts", oenv); } for (i = 0; (i < nlist); i++) { /* get nbin, the nr. of cumulative rotamers that need to be considered */ nbin = 1; for (Xi = 0; Xi < maxchi; Xi++) { index = lookup[i][Xi]; /* chi_(Xi+1) of res i (-1 if off end) */ if (index >= 0) { n = multiplicity[index]; nbin = n*nbin; } } nbin += 1; /* for the "zero rotamer", outside the core region */ for (j = 0; (j < nframes); j++) { bRotZero = FALSE; bHaveChi = TRUE; index = lookup[i][0]; /* index into dih of chi1 of res i */ if (index == -1) { bRotZero = TRUE; bHaveChi = FALSE; } else { b = calc_bin(dih[index][j], multiplicity[index], core_frac); accum = b - 1; if (b == 0) { bRotZero = TRUE; } for (Xi = 1; Xi < maxchi; Xi++) { index = lookup[i][Xi]; /* chi_(Xi+1) of res i (-1 if off end) */ if (index >= 0) { n = multiplicity[index]; b = calc_bin(dih[index][j], n, core_frac); accum = n * accum + b - 1; if (b == 0) { bRotZero = TRUE; } } } accum++; } if (bRotZero) { chi_prtrj[j] = 0.0; } else { chi_prtrj[j] = accum; if (accum+1 > nbin) { nbin = accum+1; } } } if (bHaveChi) { if (bAll) { /* print cuml rotamer vs time */ print_one(oenv, "chiproduct", dlist[i].name, "chi product for", "cumulative rotamer", nframes, time, chi_prtrj); } /* make a histogram pf culm. rotamer occupancy too */ snew(chi_prhist, nbin); make_histo(nullptr, nframes, chi_prtrj, nbin, chi_prhist, 0, nbin); if (bAll) { sprintf(hisfile, "histo-chiprod%s.xvg", dlist[i].name); sprintf(histitle, "cumulative rotamer distribution for %s", dlist[i].name); fprintf(stderr, " and %s ", hisfile); fp = xvgropen(hisfile, histitle, "number", "", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ xaxis tick on\n"); fprintf(fp, "@ xaxis tick major 1\n"); fprintf(fp, "@ type xy\n"); } for (k = 0; (k < nbin); k++) { if (bNormalize) { fprintf(fp, "%5d %10g\n", k, (1.0*chi_prhist[k])/nframes); } else { fprintf(fp, "%5d %10d\n", k, chi_prhist[k]); } } fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); xvgrclose(fp); } /* and finally print out occupancies to a single file */ /* get the gmx from-1 res nr by setting a ptr to the number part * of dlist[i].name - potential bug for 4-letter res names... */ namept = dlist[i].name + 3; fprintf(fpall, "%5s ", namept); for (k = 0; (k < nbin); k++) { if (bNormalize) { fprintf(fpall, " %10g", (1.0*chi_prhist[k])/nframes); } else { fprintf(fpall, " %10d", chi_prhist[k]); } } fprintf(fpall, "\n"); sfree(chi_prhist); /* histogram done */ } } sfree(chi_prtrj); xvgrclose(fpall); fprintf(stderr, "\n"); }
int gmx_nmeig(int argc,char *argv[]) { const char *desc[] = { "g_nmeig calculates the eigenvectors/values of a (Hessian) matrix,", "which can be calculated with [TT]mdrun[tt].", "The eigenvectors are written to a trajectory file ([TT]-v[tt]).", "The structure is written first with t=0. The eigenvectors", "are written as frames with the eigenvector number as timestamp.", "The eigenvectors can be analyzed with [TT]g_anaeig[tt].", "An ensemble of structures can be generated from the eigenvectors with", "[TT]g_nmens[tt]. When mass weighting is used, the generated eigenvectors", "will be scaled back to plain cartesian coordinates before generating the", "output - in this case they will no longer be exactly orthogonal in the", "standard cartesian norm (But in the mass weighted norm they would be)." }; static gmx_bool bM=TRUE; static int begin=1,end=50; t_pargs pa[] = { { "-m", FALSE, etBOOL, {&bM}, "Divide elements of Hessian by product of sqrt(mass) of involved " "atoms prior to diagonalization. This should be used for 'Normal Modes' " "analysis" }, { "-first", FALSE, etINT, {&begin}, "First eigenvector to write away" }, { "-last", FALSE, etINT, {&end}, "Last eigenvector to write away" } }; FILE *out; int status,trjout; t_topology top; int ePBC; rvec *top_x; matrix box; real *eigenvalues; real *eigenvectors; real rdum,mass_fac; int natoms,ndim,nrow,ncol,count; char *grpname,title[256]; int i,j,k,l,d,gnx; gmx_bool bSuck; atom_id *index; real value; real factor_gmx_to_omega2; real factor_omega_to_wavenumber; t_commrec *cr; output_env_t oenv; real * full_hessian = NULL; gmx_sparsematrix_t * sparse_hessian = NULL; t_filenm fnm[] = { { efMTX, "-f", "hessian", ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efXVG, "-of", "eigenfreq", ffWRITE }, { efXVG, "-ol", "eigenval", ffWRITE }, { efTRN, "-v", "eigenvec", ffWRITE } }; #define NFILE asize(fnm) cr = init_par(&argc,&argv); if(MASTER(cr)) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_BE_NICE | (MASTER(cr) ? 0 : PCA_QUIET), NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv); read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&top_x,NULL,box,bM); natoms = top.atoms.nr; ndim = DIM*natoms; if(begin<1) begin = 1; if(end>ndim) end = ndim; /*open Hessian matrix */ gmx_mtxio_read(ftp2fn(efMTX,NFILE,fnm),&nrow,&ncol,&full_hessian,&sparse_hessian); /* Memory for eigenvalues and eigenvectors (begin..end) */ snew(eigenvalues,nrow); snew(eigenvectors,nrow*(end-begin+1)); /* If the Hessian is in sparse format we can calculate max (ndim-1) eigenvectors, * and they must start at the first one. If this is not valid we convert to full matrix * storage, but warn the user that we might run out of memory... */ if((sparse_hessian != NULL) && (begin!=1 || end==ndim)) { if(begin!=1) { fprintf(stderr,"Cannot use sparse Hessian with first eigenvector != 1.\n"); } else if(end==ndim) { fprintf(stderr,"Cannot use sparse Hessian to calculate all eigenvectors.\n"); } fprintf(stderr,"Will try to allocate memory and convert to full matrix representation...\n"); snew(full_hessian,nrow*ncol); for(i=0;i<nrow*ncol;i++) full_hessian[i] = 0; for(i=0;i<sparse_hessian->nrow;i++) { for(j=0;j<sparse_hessian->ndata[i];j++) { k = sparse_hessian->data[i][j].col; value = sparse_hessian->data[i][j].value; full_hessian[i*ndim+k] = value; full_hessian[k*ndim+i] = value; } } gmx_sparsematrix_destroy(sparse_hessian); sparse_hessian = NULL; fprintf(stderr,"Converted sparse to full matrix storage.\n"); } if(full_hessian != NULL) { /* Using full matrix storage */ nma_full_hessian(full_hessian,nrow,bM,&top,begin,end,eigenvalues,eigenvectors); } else { /* Sparse memory storage, allocate memory for eigenvectors */ snew(eigenvectors,ncol*end); nma_sparse_hessian(sparse_hessian,bM,&top,end,eigenvalues,eigenvectors); } /* check the output, first 6 eigenvalues should be reasonably small */ bSuck=FALSE; for (i=begin-1; (i<6); i++) { if (fabs(eigenvalues[i]) > 1.0e-3) bSuck=TRUE; } if (bSuck) { fprintf(stderr,"\nOne of the lowest 6 eigenvalues has a non-zero value.\n"); fprintf(stderr,"This could mean that the reference structure was not\n"); fprintf(stderr,"properly energy minimized.\n"); } /* now write the output */ fprintf (stderr,"Writing eigenvalues...\n"); out=xvgropen(opt2fn("-ol",NFILE,fnm), "Eigenvalues","Eigenvalue index","Eigenvalue [Gromacs units]", oenv); if (output_env_get_print_xvgr_codes(oenv)) { if (bM) fprintf(out,"@ subtitle \"mass weighted\"\n"); else fprintf(out,"@ subtitle \"not mass weighted\"\n"); } for (i=0; i<=(end-begin); i++) fprintf (out,"%6d %15g\n",begin+i,eigenvalues[i]); ffclose(out); fprintf(stderr,"Writing eigenfrequencies - negative eigenvalues will be set to zero.\n"); out=xvgropen(opt2fn("-of",NFILE,fnm), "Eigenfrequencies","Eigenvector index","Wavenumber [cm\\S-1\\N]", oenv); if (output_env_get_print_xvgr_codes(oenv)) { if (bM) fprintf(out,"@ subtitle \"mass weighted\"\n"); else fprintf(out,"@ subtitle \"not mass weighted\"\n"); } /* Gromacs units are kJ/(mol*nm*nm*amu), * where amu is the atomic mass unit. * * For the eigenfrequencies we want to convert this to spectroscopic absorption * wavenumbers given in cm^(-1), which is the frequency divided by the speed of * light. Do this by first converting to omega^2 (units 1/s), take the square * root, and finally divide by the speed of light (nm/ps in gromacs). */ factor_gmx_to_omega2 = 1.0E21/(AVOGADRO*AMU); factor_omega_to_wavenumber = 1.0E-5/(2.0*M_PI*SPEED_OF_LIGHT); for (i=0; i<=(end-begin); i++) { value = eigenvalues[i]; if(value < 0) value = 0; value=sqrt(value*factor_gmx_to_omega2)*factor_omega_to_wavenumber; fprintf (out,"%6d %15g\n",begin+i,value); } ffclose(out); /* Writing eigenvectors. Note that if mass scaling was used, the eigenvectors * were scaled back from mass weighted cartesian to plain cartesian in the * nma_full_hessian() or nma_sparse_hessian() routines. Mass scaled vectors * will not be strictly orthogonal in plain cartesian scalar products. */ write_eigenvectors(opt2fn("-v",NFILE,fnm),natoms,eigenvectors,FALSE,begin,end, eWXR_NO,NULL,FALSE,top_x,bM,eigenvalues); thanx(stderr); return 0; }
int gmx_rmsdist(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the root mean square deviation of atom distances,", "which has the advantage that no fit is needed like in standard RMS", "deviation as computed by [gmx-rms].", "The reference structure is taken from the structure file.", "The RMSD at time t is calculated as the RMS", "of the differences in distance between atom-pairs in the reference", "structure and the structure at time t.[PAR]", "[THISMODULE] can also produce matrices of the rms distances, rms distances", "scaled with the mean distance and the mean distances and matrices with", "NMR averaged distances (1/r^3 and 1/r^6 averaging). Finally, lists", "of atom pairs with 1/r^3 and 1/r^6 averaged distance below the", "maximum distance ([TT]-max[tt], which will default to 0.6 in this case)", "can be generated, by default averaging over equivalent hydrogens", "(all triplets of hydrogens named \\*[123]). Additionally a list of", "equivalent atoms can be supplied ([TT]-equiv[tt]), each line containing", "a set of equivalent atoms specified as residue number and name and", "atom name; e.g.:[PAR]", "[TT]HB* 3 SER HB1 3 SER HB2[tt][PAR]", "Residue and atom names must exactly match those in the structure", "file, including case. Specifying non-sequential atoms is undefined." }; int i, teller; real t; t_topology top; int ePBC; t_atoms *atoms; matrix box; rvec *x; FILE *fp; t_trxstatus *status; int isize, gnr = 0; atom_id *index, *noe_index; char *grpname; real **d_r, **d, **dtot, **dtot2, **mean, **rms, **rmsc, *resnr; real **dtot1_3 = NULL, **dtot1_6 = NULL; real rmsnow, meanmax, rmsmax, rmscmax; real max1_3, max1_6; t_noe_gr *noe_gr = NULL; t_noe **noe = NULL; t_rgb rlo, rhi; gmx_bool bRMS, bScale, bMean, bNOE, bNMR3, bNMR6, bNMR; static int nlevels = 40; static real scalemax = -1.0; static gmx_bool bSumH = TRUE; static gmx_bool bPBC = TRUE; output_env_t oenv; t_pargs pa[] = { { "-nlevels", FALSE, etINT, {&nlevels}, "Discretize RMS in this number of levels" }, { "-max", FALSE, etREAL, {&scalemax}, "Maximum level in matrices" }, { "-sumh", FALSE, etBOOL, {&bSumH}, "Average distance over equivalent hydrogens" }, { "-pbc", FALSE, etBOOL, {&bPBC}, "Use periodic boundary conditions when computing distances" } }; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efDAT, "-equiv", "equiv", ffOPTRD }, { efXVG, NULL, "distrmsd", ffWRITE }, { efXPM, "-rms", "rmsdist", ffOPTWR }, { efXPM, "-scl", "rmsscale", ffOPTWR }, { efXPM, "-mean", "rmsmean", ffOPTWR }, { efXPM, "-nmr3", "nmr3", ffOPTWR }, { efXPM, "-nmr6", "nmr6", ffOPTWR }, { efDAT, "-noe", "noe", ffOPTWR }, }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } bRMS = opt2bSet("-rms", NFILE, fnm); bScale = opt2bSet("-scl", NFILE, fnm); bMean = opt2bSet("-mean", NFILE, fnm); bNOE = opt2bSet("-noe", NFILE, fnm); bNMR3 = opt2bSet("-nmr3", NFILE, fnm); bNMR6 = opt2bSet("-nmr6", NFILE, fnm); bNMR = bNMR3 || bNMR6 || bNOE; max1_3 = 0; max1_6 = 0; /* check input */ if (bNOE && scalemax < 0) { scalemax = 0.6; fprintf(stderr, "WARNING: using -noe without -max " "makes no sense, setting -max to %g\n\n", scalemax); } /* get topology and index */ read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, NULL, box, FALSE); if (!bPBC) { ePBC = epbcNONE; } atoms = &(top.atoms); get_index(atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname); /* initialize arrays */ snew(d, isize); snew(dtot, isize); snew(dtot2, isize); if (bNMR) { snew(dtot1_3, isize); snew(dtot1_6, isize); } snew(mean, isize); snew(rms, isize); snew(rmsc, isize); snew(d_r, isize); snew(resnr, isize); for (i = 0; (i < isize); i++) { snew(d[i], isize); snew(dtot[i], isize); snew(dtot2[i], isize); if (bNMR) { snew(dtot1_3[i], isize); snew(dtot1_6[i], isize); } snew(mean[i], isize); snew(rms[i], isize); snew(rmsc[i], isize); snew(d_r[i], isize); resnr[i] = i+1; } /*set box type*/ calc_dist(isize, index, x, ePBC, box, d_r); sfree(x); /*open output files*/ fp = xvgropen(ftp2fn(efXVG, NFILE, fnm), "RMS Deviation", "Time (ps)", "RMSD (nm)", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"of distances between %s atoms\"\n", grpname); } /*do a first step*/ read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); teller = 0; do { calc_dist_tot(isize, index, x, ePBC, box, d, dtot, dtot2, bNMR, dtot1_3, dtot1_6); rmsnow = rms_diff(isize, d, d_r); fprintf(fp, "%g %g\n", t, rmsnow); teller++; } while (read_next_x(oenv, status, &t, x, box)); fprintf(stderr, "\n"); xvgrclose(fp); close_trj(status); calc_rms(isize, teller, dtot, dtot2, rms, &rmsmax, rmsc, &rmscmax, mean, &meanmax); fprintf(stderr, "rmsmax = %g, rmscmax = %g\n", rmsmax, rmscmax); if (bNMR) { calc_nmr(isize, teller, dtot1_3, dtot1_6, &max1_3, &max1_6); } if (scalemax > -1.0) { rmsmax = scalemax; rmscmax = scalemax; meanmax = scalemax; max1_3 = scalemax; max1_6 = scalemax; } if (bNOE) { /* make list of noe atom groups */ snew(noe_index, isize+1); snew(noe_gr, isize); gnr = analyze_noe_equivalent(opt2fn_null("-equiv", NFILE, fnm), atoms, isize, index, bSumH, noe_index, noe_gr); fprintf(stdout, "Found %d non-equivalent atom-groups in %d atoms\n", gnr, isize); /* make half matrix of of noe-group distances from atom distances */ snew(noe, gnr); for (i = 0; i < gnr; i++) { snew(noe[i], gnr); } calc_noe(isize, noe_index, dtot1_3, dtot1_6, gnr, noe); } rlo.r = 1.0, rlo.g = 1.0, rlo.b = 1.0; rhi.r = 0.0, rhi.g = 0.0, rhi.b = 0.0; if (bRMS) { write_xpm(opt2FILE("-rms", NFILE, fnm, "w"), 0, "RMS of distance", "RMS (nm)", "Atom Index", "Atom Index", isize, isize, resnr, resnr, rms, 0.0, rmsmax, rlo, rhi, &nlevels); } if (bScale) { write_xpm(opt2FILE("-scl", NFILE, fnm, "w"), 0, "Relative RMS", "RMS", "Atom Index", "Atom Index", isize, isize, resnr, resnr, rmsc, 0.0, rmscmax, rlo, rhi, &nlevels); } if (bMean) { write_xpm(opt2FILE("-mean", NFILE, fnm, "w"), 0, "Mean Distance", "Distance (nm)", "Atom Index", "Atom Index", isize, isize, resnr, resnr, mean, 0.0, meanmax, rlo, rhi, &nlevels); } if (bNMR3) { write_xpm(opt2FILE("-nmr3", NFILE, fnm, "w"), 0, "1/r^3 averaged distances", "Distance (nm)", "Atom Index", "Atom Index", isize, isize, resnr, resnr, dtot1_3, 0.0, max1_3, rlo, rhi, &nlevels); } if (bNMR6) { write_xpm(opt2FILE("-nmr6", NFILE, fnm, "w"), 0, "1/r^6 averaged distances", "Distance (nm)", "Atom Index", "Atom Index", isize, isize, resnr, resnr, dtot1_6, 0.0, max1_6, rlo, rhi, &nlevels); } if (bNOE) { write_noe(opt2FILE("-noe", NFILE, fnm, "w"), gnr, noe, noe_gr, scalemax); } do_view(oenv, ftp2fn(efXVG, NFILE, fnm), NULL); return 0; }
int gmx_polystat(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] plots static properties of polymers as a function of time", "and prints the average.[PAR]", "By default it determines the average end-to-end distance and radii", "of gyration of polymers. It asks for an index group and split this", "into molecules. The end-to-end distance is then determined using", "the first and the last atom in the index group for each molecules.", "For the radius of gyration the total and the three principal components", "for the average gyration tensor are written.", "With option [TT]-v[tt] the eigenvectors are written.", "With option [TT]-pc[tt] also the average eigenvalues of the individual", "gyration tensors are written.", "With option [TT]-i[tt] the mean square internal distances are", "written.[PAR]", "With option [TT]-p[tt] the persistence length is determined.", "The chosen index group should consist of atoms that are", "consecutively bonded in the polymer mainchains.", "The persistence length is then determined from the cosine of", "the angles between bonds with an index difference that is even,", "the odd pairs are not used, because straight polymer backbones", "are usually all trans and therefore only every second bond aligns.", "The persistence length is defined as number of bonds where", "the average cos reaches a value of 1/e. This point is determined", "by a linear interpolation of [LOG]<cos>[log]." }; static gmx_bool bMW = TRUE, bPC = FALSE; t_pargs pa[] = { { "-mw", FALSE, etBOOL, {&bMW}, "Use the mass weighting for radii of gyration" }, { "-pc", FALSE, etBOOL, {&bPC}, "Plot average eigenvalues" } }; t_filenm fnm[] = { { efTPR, nullptr, nullptr, ffREAD }, { efTRX, "-f", nullptr, ffREAD }, { efNDX, nullptr, nullptr, ffOPTRD }, { efXVG, "-o", "polystat", ffWRITE }, { efXVG, "-v", "polyvec", ffOPTWR }, { efXVG, "-p", "persist", ffOPTWR }, { efXVG, "-i", "intdist", ffOPTWR } }; #define NFILE asize(fnm) t_topology *top; gmx_output_env_t *oenv; int ePBC; int isize, *index, nmol, *molind, mol, nat_min = 0, nat_max = 0; char *grpname; t_trxstatus *status; real t; rvec *x, *bond = nullptr; matrix box; int natoms, i, j, frame, ind0, ind1, a, d, d2, ord[DIM] = {0}; dvec cm, sum_eig = {0, 0, 0}; double **gyr, **gyr_all, eig[DIM], **eigv; double sum_eed2, sum_eed2_tot, sum_gyro, sum_gyro_tot, sum_pers_tot; int *ninp = nullptr; double *sum_inp = nullptr, pers; double *intd, ymax, ymin; double mmol, m; char title[STRLEN]; FILE *out, *outv, *outp, *outi; const char *leg[8] = { "end to end", "<R\\sg\\N>", "<R\\sg\\N> eig1", "<R\\sg\\N> eig2", "<R\\sg\\N> eig3", "<R\\sg\\N eig1>", "<R\\sg\\N eig2>", "<R\\sg\\N eig3>" }; char **legp, buf[STRLEN]; gmx_rmpbc_t gpbc = nullptr; if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_TIME_UNIT, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, nullptr, &oenv)) { return 0; } snew(top, 1); ePBC = read_tpx_top(ftp2fn(efTPR, NFILE, fnm), nullptr, box, &natoms, nullptr, nullptr, top); fprintf(stderr, "Select a group of polymer mainchain atoms:\n"); get_index(&top->atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname); snew(molind, top->mols.nr+1); nmol = 0; mol = -1; for (i = 0; i < isize; i++) { if (i == 0 || index[i] >= top->mols.index[mol+1]) { molind[nmol++] = i; do { mol++; } while (index[i] >= top->mols.index[mol+1]); } } molind[nmol] = i; nat_min = top->atoms.nr; nat_max = 0; for (mol = 0; mol < nmol; mol++) { nat_min = std::min(nat_min, molind[mol+1]-molind[mol]); nat_max = std::max(nat_max, molind[mol+1]-molind[mol]); } fprintf(stderr, "Group %s consists of %d molecules\n", grpname, nmol); fprintf(stderr, "Group size per molecule, min: %d atoms, max %d atoms\n", nat_min, nat_max); sprintf(title, "Size of %d polymers", nmol); out = xvgropen(opt2fn("-o", NFILE, fnm), title, output_env_get_xvgr_tlabel(oenv), "(nm)", oenv); xvgr_legend(out, bPC ? 8 : 5, leg, oenv); if (opt2bSet("-v", NFILE, fnm)) { outv = xvgropen(opt2fn("-v", NFILE, fnm), "Principal components", output_env_get_xvgr_tlabel(oenv), "(nm)", oenv); snew(legp, DIM*DIM); for (d = 0; d < DIM; d++) { for (d2 = 0; d2 < DIM; d2++) { sprintf(buf, "eig%d %c", d+1, 'x'+d2); legp[d*DIM+d2] = gmx_strdup(buf); } } xvgr_legend(outv, DIM*DIM, (const char**)legp, oenv); } else { outv = nullptr; } if (opt2bSet("-p", NFILE, fnm)) { outp = xvgropen(opt2fn("-p", NFILE, fnm), "Persistence length", output_env_get_xvgr_tlabel(oenv), "bonds", oenv); snew(bond, nat_max-1); snew(sum_inp, nat_min/2); snew(ninp, nat_min/2); } else { outp = nullptr; } if (opt2bSet("-i", NFILE, fnm)) { outi = xvgropen(opt2fn("-i", NFILE, fnm), "Internal distances", "n", "<R\\S2\\N(n)>/n (nm\\S2\\N)", oenv); i = index[molind[1]-1] - index[molind[0]]; /* Length of polymer -1 */ snew(intd, i); } else { intd = nullptr; outi = nullptr; } natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); snew(gyr, DIM); snew(gyr_all, DIM); snew(eigv, DIM); for (d = 0; d < DIM; d++) { snew(gyr[d], DIM); snew(gyr_all[d], DIM); snew(eigv[d], DIM); } frame = 0; sum_eed2_tot = 0; sum_gyro_tot = 0; sum_pers_tot = 0; gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms); do { gmx_rmpbc(gpbc, natoms, box, x); sum_eed2 = 0; for (d = 0; d < DIM; d++) { clear_dvec(gyr_all[d]); } if (bPC) { clear_dvec(sum_eig); } if (outp) { for (i = 0; i < nat_min/2; i++) { sum_inp[i] = 0; ninp[i] = 0; } } for (mol = 0; mol < nmol; mol++) { ind0 = molind[mol]; ind1 = molind[mol+1]; /* Determine end to end distance */ sum_eed2 += distance2(x[index[ind0]], x[index[ind1-1]]); /* Determine internal distances */ if (outi) { calc_int_dist(intd, x, index[ind0], index[ind1-1]); } /* Determine the radius of gyration */ clear_dvec(cm); for (d = 0; d < DIM; d++) { clear_dvec(gyr[d]); } mmol = 0; for (i = ind0; i < ind1; i++) { a = index[i]; if (bMW) { m = top->atoms.atom[a].m; } else { m = 1; } mmol += m; for (d = 0; d < DIM; d++) { cm[d] += m*x[a][d]; for (d2 = 0; d2 < DIM; d2++) { gyr[d][d2] += m*x[a][d]*x[a][d2]; } } } dsvmul(1/mmol, cm, cm); for (d = 0; d < DIM; d++) { for (d2 = 0; d2 < DIM; d2++) { gyr[d][d2] = gyr[d][d2]/mmol - cm[d]*cm[d2]; gyr_all[d][d2] += gyr[d][d2]; } } if (bPC) { gyro_eigen(gyr, eig, eigv, ord); for (d = 0; d < DIM; d++) { sum_eig[d] += eig[ord[d]]; } } if (outp) { for (i = ind0; i < ind1-1; i++) { rvec_sub(x[index[i+1]], x[index[i]], bond[i-ind0]); unitv(bond[i-ind0], bond[i-ind0]); } for (i = ind0; i < ind1-1; i++) { for (j = 0; (i+j < ind1-1 && j < nat_min/2); j += 2) { sum_inp[j] += iprod(bond[i-ind0], bond[i-ind0+j]); ninp[j]++; } } } } sum_eed2 /= nmol; sum_gyro = 0; for (d = 0; d < DIM; d++) { for (d2 = 0; d2 < DIM; d2++) { gyr_all[d][d2] /= nmol; } sum_gyro += gyr_all[d][d]; } gyro_eigen(gyr_all, eig, eigv, ord); fprintf(out, "%10.3f %8.4f %8.4f %8.4f %8.4f %8.4f", t*output_env_get_time_factor(oenv), std::sqrt(sum_eed2), sqrt(sum_gyro), std::sqrt(eig[ord[0]]), std::sqrt(eig[ord[1]]), std::sqrt(eig[ord[2]])); if (bPC) { for (d = 0; d < DIM; d++) { fprintf(out, " %8.4f", std::sqrt(sum_eig[d]/nmol)); } } fprintf(out, "\n"); if (outv) { fprintf(outv, "%10.3f", t*output_env_get_time_factor(oenv)); for (d = 0; d < DIM; d++) { for (d2 = 0; d2 < DIM; d2++) { fprintf(outv, " %6.3f", eigv[ord[d]][d2]); } } fprintf(outv, "\n"); } sum_eed2_tot += sum_eed2; sum_gyro_tot += sum_gyro; if (outp) { i = -1; for (j = 0; j < nat_min/2; j += 2) { sum_inp[j] /= ninp[j]; if (i == -1 && sum_inp[j] <= std::exp(-1.0)) { i = j; } } if (i == -1) { pers = j; } else { /* Do linear interpolation on a log scale */ pers = i - 2.0 + 2.0*(std::log(sum_inp[i-2]) + 1.0)/(std::log(sum_inp[i-2]) - std::log(sum_inp[i])); } fprintf(outp, "%10.3f %8.4f\n", t*output_env_get_time_factor(oenv), pers); sum_pers_tot += pers; } frame++; } while (read_next_x(oenv, status, &t, x, box)); gmx_rmpbc_done(gpbc); close_trx(status); xvgrclose(out); if (outv) { xvgrclose(outv); } if (outp) { xvgrclose(outp); } sum_eed2_tot /= frame; sum_gyro_tot /= frame; sum_pers_tot /= frame; fprintf(stdout, "\nAverage end to end distance: %.3f (nm)\n", std::sqrt(sum_eed2_tot)); fprintf(stdout, "\nAverage radius of gyration: %.3f (nm)\n", std::sqrt(sum_gyro_tot)); if (opt2bSet("-p", NFILE, fnm)) { fprintf(stdout, "\nAverage persistence length: %.2f bonds\n", sum_pers_tot); } /* Handle printing of internal distances. */ if (outi) { if (output_env_get_print_xvgr_codes(oenv)) { fprintf(outi, "@ xaxes scale Logarithmic\n"); } ymax = -1; ymin = 1e300; j = index[molind[1]-1] - index[molind[0]]; /* Polymer length -1. */ for (i = 0; i < j; i++) { intd[i] /= (i + 1) * frame * nmol; if (intd[i] > ymax) { ymax = intd[i]; } if (intd[i] < ymin) { ymin = intd[i]; } } xvgr_world(outi, 1, ymin, j, ymax, oenv); for (i = 0; i < j; i++) { fprintf(outi, "%d %8.4f\n", i+1, intd[i]); } xvgrclose(outi); } do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy"); if (opt2bSet("-v", NFILE, fnm)) { do_view(oenv, opt2fn("-v", NFILE, fnm), "-nxy"); } if (opt2bSet("-p", NFILE, fnm)) { do_view(oenv, opt2fn("-p", NFILE, fnm), "-nxy"); } return 0; }
static void estimate_error(const char *eefile, int nb_min, int resol, int n, int nset, double *av, double *sig, real **val, real dt, gmx_bool bFitAc, gmx_bool bSingleExpFit, gmx_bool bAllowNegLTCorr, const output_env_t oenv) { FILE *fp; int bs, prev_bs, nbs, nb; real spacing, nbr; int s, i, j; double blav, var; char **leg; real *tbs, *ybs, rtmp, dens, *fitsig, twooe, tau1_est, tau_sig; real fitparm[4]; real ee, a, tau1, tau2; if (n < 4) { fprintf(stdout, "The number of points is smaller than 4, can not make an error estimate\n"); return; } fp = xvgropen(eefile, "Error estimates", "Block size (time)", "Error estimate", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"using block averaging, total time %g (%d points)\"\n", (n-1)*dt, n); } snew(leg, 2*nset); xvgr_legend(fp, 2*nset, (const char**)leg, oenv); sfree(leg); spacing = pow(2, 1.0/resol); snew(tbs, n); snew(ybs, n); snew(fitsig, n); for (s = 0; s < nset; s++) { nbs = 0; prev_bs = 0; nbr = nb_min; while (nbr <= n) { bs = n/(int)nbr; if (bs != prev_bs) { nb = n/bs; var = 0; for (i = 0; i < nb; i++) { blav = 0; for (j = 0; j < bs; j++) { blav += val[s][bs*i+j]; } var += sqr(av[s] - blav/bs); } tbs[nbs] = bs*dt; if (sig[s] == 0) { ybs[nbs] = 0; } else { ybs[nbs] = var/(nb*(nb-1.0))*(n*dt)/(sig[s]*sig[s]); } nbs++; } nbr *= spacing; nb = (int)(nbr+0.5); prev_bs = bs; } if (sig[s] == 0) { ee = 0; a = 1; tau1 = 0; tau2 = 0; } else { for (i = 0; i < nbs/2; i++) { rtmp = tbs[i]; tbs[i] = tbs[nbs-1-i]; tbs[nbs-1-i] = rtmp; rtmp = ybs[i]; ybs[i] = ybs[nbs-1-i]; ybs[nbs-1-i] = rtmp; } /* The initial slope of the normalized ybs^2 is 1. * For a single exponential autocorrelation: ybs(tau1) = 2/e tau1 * From this we take our initial guess for tau1. */ twooe = 2/exp(1); i = -1; do { i++; tau1_est = tbs[i]; } while (i < nbs - 1 && (ybs[i] > ybs[i+1] || ybs[i] > twooe*tau1_est)); if (ybs[0] > ybs[1]) { fprintf(stdout, "Data set %d has strange time correlations:\n" "the std. error using single points is larger than that of blocks of 2 points\n" "The error estimate might be inaccurate, check the fit\n", s+1); /* Use the total time as tau for the fitting weights */ tau_sig = (n - 1)*dt; } else { tau_sig = tau1_est; } if (debug) { fprintf(debug, "set %d tau1 estimate %f\n", s+1, tau1_est); } /* Generate more or less appropriate sigma's, * also taking the density of points into account. */ for (i = 0; i < nbs; i++) { if (i == 0) { dens = tbs[1]/tbs[0] - 1; } else if (i == nbs-1) { dens = tbs[nbs-1]/tbs[nbs-2] - 1; } else { dens = 0.5*(tbs[i+1]/tbs[i-1] - 1); } fitsig[i] = sqrt((tau_sig + tbs[i])/dens); } if (!bSingleExpFit) { fitparm[0] = tau1_est; fitparm[1] = 0.95; /* We set the initial guess for tau2 * to halfway between tau1_est and the total time (on log scale). */ fitparm[2] = sqrt(tau1_est*(n-1)*dt); do_lmfit(nbs, ybs, fitsig, 0, tbs, 0, dt*n, oenv, bDebugMode(), effnERREST, fitparm, 0); fitparm[3] = 1-fitparm[1]; } if (bSingleExpFit || fitparm[0] < 0 || fitparm[2] < 0 || fitparm[1] < 0 || (fitparm[1] > 1 && !bAllowNegLTCorr) || fitparm[2] > (n-1)*dt) { if (!bSingleExpFit) { if (fitparm[2] > (n-1)*dt) { fprintf(stdout, "Warning: tau2 is longer than the length of the data (%g)\n" " the statistics might be bad\n", (n-1)*dt); } else { fprintf(stdout, "a fitted parameter is negative\n"); } fprintf(stdout, "invalid fit: e.e. %g a %g tau1 %g tau2 %g\n", sig[s]*anal_ee_inf(fitparm, n*dt), fitparm[1], fitparm[0], fitparm[2]); /* Do a fit with tau2 fixed at the total time. * One could also choose any other large value for tau2. */ fitparm[0] = tau1_est; fitparm[1] = 0.95; fitparm[2] = (n-1)*dt; fprintf(stderr, "Will fix tau2 at the total time: %g\n", fitparm[2]); do_lmfit(nbs, ybs, fitsig, 0, tbs, 0, dt*n, oenv, bDebugMode(), effnERREST, fitparm, 4); fitparm[3] = 1-fitparm[1]; } if (bSingleExpFit || fitparm[0] < 0 || fitparm[1] < 0 || (fitparm[1] > 1 && !bAllowNegLTCorr)) { if (!bSingleExpFit) { fprintf(stdout, "a fitted parameter is negative\n"); fprintf(stdout, "invalid fit: e.e. %g a %g tau1 %g tau2 %g\n", sig[s]*anal_ee_inf(fitparm, n*dt), fitparm[1], fitparm[0], fitparm[2]); } /* Do a single exponential fit */ fprintf(stderr, "Will use a single exponential fit for set %d\n", s+1); fitparm[0] = tau1_est; fitparm[1] = 1.0; fitparm[2] = 0.0; do_lmfit(nbs, ybs, fitsig, 0, tbs, 0, dt*n, oenv, bDebugMode(), effnERREST, fitparm, 6); fitparm[3] = 1-fitparm[1]; } } ee = sig[s]*anal_ee_inf(fitparm, n*dt); a = fitparm[1]; tau1 = fitparm[0]; tau2 = fitparm[2]; } fprintf(stdout, "Set %3d: err.est. %g a %g tau1 %g tau2 %g\n", s+1, ee, a, tau1, tau2); fprintf(fp, "@ legend string %d \"av %f\"\n", 2*s, av[s]); fprintf(fp, "@ legend string %d \"ee %6g\"\n", 2*s+1, sig[s]*anal_ee_inf(fitparm, n*dt)); for (i = 0; i < nbs; i++) { fprintf(fp, "%g %g %g\n", tbs[i], sig[s]*sqrt(ybs[i]/(n*dt)), sig[s]*sqrt(fit_function(effnERREST, fitparm, tbs[i])/(n*dt))); } if (bFitAc) { int fitlen; real *ac, acint, ac_fit[4]; snew(ac, n); for (i = 0; i < n; i++) { ac[i] = val[s][i] - av[s]; if (i > 0) { fitsig[i] = sqrt(i); } else { fitsig[i] = 1; } } low_do_autocorr(NULL, oenv, NULL, n, 1, -1, &ac, dt, eacNormal, 1, FALSE, TRUE, FALSE, 0, 0, effnNONE); fitlen = n/nb_min; /* Integrate ACF only up to fitlen/2 to avoid integrating noise */ acint = 0.5*ac[0]; for (i = 1; i <= fitlen/2; i++) { acint += ac[i]; } acint *= dt; /* Generate more or less appropriate sigma's */ for (i = 0; i <= fitlen; i++) { fitsig[i] = sqrt(acint + dt*i); } ac_fit[0] = 0.5*acint; ac_fit[1] = 0.95; ac_fit[2] = 10*acint; do_lmfit(n/nb_min, ac, fitsig, dt, 0, 0, fitlen*dt, oenv, bDebugMode(), effnEXP3, ac_fit, 0); ac_fit[3] = 1 - ac_fit[1]; fprintf(stdout, "Set %3d: ac erest %g a %g tau1 %g tau2 %g\n", s+1, sig[s]*anal_ee_inf(ac_fit, n*dt), ac_fit[1], ac_fit[0], ac_fit[2]); fprintf(fp, "&\n"); for (i = 0; i < nbs; i++) { fprintf(fp, "%g %g\n", tbs[i], sig[s]*sqrt(fit_function(effnERREST, ac_fit, tbs[i]))/(n*dt)); } sfree(ac); } if (s < nset-1) { fprintf(fp, "&\n"); } } sfree(fitsig); sfree(ybs); sfree(tbs); ffclose(fp); }
int gmx_rms(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] compares two structures by computing the root mean square", "deviation (RMSD), the size-independent [GRK]rho[grk] similarity parameter", "([TT]rho[tt]) or the scaled [GRK]rho[grk] ([TT]rhosc[tt]), ", "see Maiorov & Crippen, Proteins [BB]22[bb], 273 (1995).", "This is selected by [TT]-what[tt].[PAR]" "Each structure from a trajectory ([TT]-f[tt]) is compared to a", "reference structure. The reference structure", "is taken from the structure file ([TT]-s[tt]).[PAR]", "With option [TT]-mir[tt] also a comparison with the mirror image of", "the reference structure is calculated.", "This is useful as a reference for 'significant' values, see", "Maiorov & Crippen, Proteins [BB]22[bb], 273 (1995).[PAR]", "Option [TT]-prev[tt] produces the comparison with a previous frame", "the specified number of frames ago.[PAR]", "Option [TT]-m[tt] produces a matrix in [TT].xpm[tt] format of", "comparison values of each structure in the trajectory with respect to", "each other structure. This file can be visualized with for instance", "[TT]xv[tt] and can be converted to postscript with [gmx-xpm2ps].[PAR]", "Option [TT]-fit[tt] controls the least-squares fitting of", "the structures on top of each other: complete fit (rotation and", "translation), translation only, or no fitting at all.[PAR]", "Option [TT]-mw[tt] controls whether mass weighting is done or not.", "If you select the option (default) and ", "supply a valid [TT].tpr[tt] file masses will be taken from there, ", "otherwise the masses will be deduced from the [TT]atommass.dat[tt] file in", "[TT]GMXLIB[tt]. This is fine for proteins, but not", "necessarily for other molecules. A default mass of 12.011 amu (carbon)", "is assigned to unknown atoms. You can check whether this happend by", "turning on the [TT]-debug[tt] flag and inspecting the log file.[PAR]", "With [TT]-f2[tt], the 'other structures' are taken from a second", "trajectory, this generates a comparison matrix of one trajectory", "versus the other.[PAR]", "Option [TT]-bin[tt] does a binary dump of the comparison matrix.[PAR]", "Option [TT]-bm[tt] produces a matrix of average bond angle deviations", "analogously to the [TT]-m[tt] option. Only bonds between atoms in the", "comparison group are considered." }; static gmx_bool bPBC = TRUE, bFitAll = TRUE, bSplit = FALSE; static gmx_bool bDeltaLog = FALSE; static int prev = 0, freq = 1, freq2 = 1, nlevels = 80, avl = 0; static real rmsd_user_max = -1, rmsd_user_min = -1, bond_user_max = -1, bond_user_min = -1, delta_maxy = 0.0; /* strings and things for selecting difference method */ enum { ewSel, ewRMSD, ewRho, ewRhoSc, ewNR }; int ewhat; const char *what[ewNR + 1] = { NULL, "rmsd", "rho", "rhosc", NULL }; const char *whatname[ewNR] = { NULL, "RMSD", "Rho", "Rho sc" }; const char *whatlabel[ewNR] = { NULL, "RMSD (nm)", "Rho", "Rho sc" }; const char *whatxvgname[ewNR] = { NULL, "RMSD", "\\8r\\4", "\\8r\\4\\ssc\\N" }; const char *whatxvglabel[ewNR] = { NULL, "RMSD (nm)", "\\8r\\4", "\\8r\\4\\ssc\\N" }; /* strings and things for fitting methods */ enum { efSel, efFit, efReset, efNone, efNR }; int efit; const char *fit[efNR + 1] = { NULL, "rot+trans", "translation", "none", NULL }; const char *fitgraphlabel[efNR + 1] = { NULL, "lsq fit", "translational fit", "no fit" }; static int nrms = 1; static gmx_bool bMassWeighted = TRUE; t_pargs pa[] = { { "-what", FALSE, etENUM, { what }, "Structural difference measure" }, { "-pbc", FALSE, etBOOL, { &bPBC }, "PBC check" }, { "-fit", FALSE, etENUM, { fit }, "Fit to reference structure" }, { "-prev", FALSE, etINT, { &prev }, "Compare with previous frame" }, { "-split", FALSE, etBOOL, { &bSplit }, "Split graph where time is zero" }, { "-fitall", FALSE, etBOOL, { &bFitAll }, "HIDDENFit all pairs of structures in matrix" }, { "-skip", FALSE, etINT, { &freq }, "Only write every nr-th frame to matrix" }, { "-skip2", FALSE, etINT, { &freq2 }, "Only write every nr-th frame to matrix" }, { "-max", FALSE, etREAL, { &rmsd_user_max }, "Maximum level in comparison matrix" }, { "-min", FALSE, etREAL, { &rmsd_user_min }, "Minimum level in comparison matrix" }, { "-bmax", FALSE, etREAL, { &bond_user_max }, "Maximum level in bond angle matrix" }, { "-bmin", FALSE, etREAL, { &bond_user_min }, "Minimum level in bond angle matrix" }, { "-mw", FALSE, etBOOL, { &bMassWeighted }, "Use mass weighting for superposition" }, { "-nlevels", FALSE, etINT, { &nlevels }, "Number of levels in the matrices" }, { "-ng", FALSE, etINT, { &nrms }, "Number of groups to compute RMS between" }, { "-dlog", FALSE, etBOOL, { &bDeltaLog }, "HIDDENUse a log x-axis in the delta t matrix" }, { "-dmax", FALSE, etREAL, { &delta_maxy }, "HIDDENMaximum level in delta matrix" }, { "-aver", FALSE, etINT, { &avl }, "HIDDENAverage over this distance in the RMSD matrix" } }; int natoms_trx, natoms_trx2, natoms; int i, j, k, m, teller, teller2, tel_mat, tel_mat2; #define NFRAME 5000 int maxframe = NFRAME, maxframe2 = NFRAME; real t, *w_rls, *w_rms, *w_rls_m = NULL, *w_rms_m = NULL; gmx_bool bNorm, bAv, bFreq2, bFile2, bMat, bBond, bDelta, bMirror, bMass; gmx_bool bFit, bReset; t_topology top; int ePBC; t_iatom *iatom = NULL; matrix box; rvec *x, *xp, *xm = NULL, **mat_x = NULL, **mat_x2, *mat_x2_j = NULL, vec1, vec2; t_trxstatus *status; char buf[256], buf2[256]; int ncons = 0; FILE *fp; real rlstot = 0, **rls, **rlsm = NULL, *time, *time2, *rlsnorm = NULL, **rmsd_mat = NULL, **bond_mat = NULL, *axis, *axis2, *del_xaxis, *del_yaxis, rmsd_max, rmsd_min, rmsd_avg, bond_max, bond_min, ang; real **rmsdav_mat = NULL, av_tot, weight, weight_tot; real **delta = NULL, delta_max, delta_scalex = 0, delta_scaley = 0, *delta_tot; int delta_xsize = 0, del_lev = 100, mx, my, abs_my; gmx_bool bA1, bA2, bPrev, bTop, *bInMat = NULL; int ifit, *irms, ibond = 0, *ind_bond1 = NULL, *ind_bond2 = NULL, n_ind_m = 0; atom_id *ind_fit, **ind_rms, *ind_m = NULL, *rev_ind_m = NULL, *ind_rms_m = NULL; char *gn_fit, **gn_rms; t_rgb rlo, rhi; output_env_t oenv; gmx_rmpbc_t gpbc = NULL; t_filenm fnm[] = { { efTPS, NULL, NULL, ffREAD }, { efTRX, "-f", NULL, ffREAD }, { efTRX, "-f2", NULL, ffOPTRD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "rmsd", ffWRITE }, { efXVG, "-mir", "rmsdmir", ffOPTWR }, { efXVG, "-a", "avgrp", ffOPTWR }, { efXVG, "-dist", "rmsd-dist", ffOPTWR }, { efXPM, "-m", "rmsd", ffOPTWR }, { efDAT, "-bin", "rmsd", ffOPTWR }, { efXPM, "-bm", "bond", ffOPTWR } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_TIME_UNIT | PCA_CAN_VIEW | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } /* parse enumerated options: */ ewhat = nenum(what); if (ewhat == ewRho || ewhat == ewRhoSc) { please_cite(stdout, "Maiorov95"); } efit = nenum(fit); bFit = efit == efFit; bReset = efit == efReset; if (bFit) { bReset = TRUE; /* for fit, reset *must* be set */ } else { bFitAll = FALSE; } /* mark active cmdline options */ bMirror = opt2bSet("-mir", NFILE, fnm); /* calc RMSD vs mirror of ref. */ bFile2 = opt2bSet("-f2", NFILE, fnm); bMat = opt2bSet("-m", NFILE, fnm); bBond = opt2bSet("-bm", NFILE, fnm); bDelta = (delta_maxy > 0); /* calculate rmsd vs delta t matrix from * * your RMSD matrix (hidden option */ bNorm = opt2bSet("-a", NFILE, fnm); bFreq2 = opt2parg_bSet("-skip2", asize(pa), pa); if (freq <= 0) { fprintf(stderr, "The number of frames to skip is <= 0. " "Writing out all frames.\n\n"); freq = 1; } if (!bFreq2) { freq2 = freq; } else if (bFile2 && freq2 <= 0) { fprintf(stderr, "The number of frames to skip in second trajectory is <= 0.\n" " Writing out all frames.\n\n"); freq2 = 1; } bPrev = (prev > 0); if (bPrev) { prev = abs(prev); if (freq != 1) { fprintf(stderr, "WARNING: option -skip also applies to -prev\n"); } } if (bFile2 && !bMat && !bBond) { fprintf( stderr, "WARNING: second trajectory (-f2) useless when not calculating matrix (-m/-bm),\n" " will not read from %s\n", opt2fn("-f2", NFILE, fnm)); bFile2 = FALSE; } if (bDelta) { bMat = TRUE; if (bFile2) { fprintf(stderr, "WARNING: second trajectory (-f2) useless when making delta matrix,\n" " will not read from %s\n", opt2fn("-f2", NFILE, fnm)); bFile2 = FALSE; } } bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), buf, &top, &ePBC, &xp, NULL, box, TRUE); snew(w_rls, top.atoms.nr); snew(w_rms, top.atoms.nr); if (!bTop && bBond) { fprintf(stderr, "WARNING: Need a run input file for bond angle matrix,\n" " will not calculate bond angle matrix.\n"); bBond = FALSE; } if (bReset) { fprintf(stderr, "Select group for %s fit\n", bFit ? "least squares" : "translational"); get_index(&(top.atoms), ftp2fn_null(efNDX, NFILE, fnm), 1, &ifit, &ind_fit, &gn_fit); } else { ifit = 0; } if (bReset) { if (bFit && ifit < 3) { gmx_fatal(FARGS, "Need >= 3 points to fit!\n" ); } bMass = FALSE; for (i = 0; i < ifit; i++) { if (bMassWeighted) { w_rls[ind_fit[i]] = top.atoms.atom[ind_fit[i]].m; } else { w_rls[ind_fit[i]] = 1; } bMass = bMass || (top.atoms.atom[ind_fit[i]].m != 0); } if (!bMass) { fprintf(stderr, "All masses in the fit group are 0, using masses of 1\n"); for (i = 0; i < ifit; i++) { w_rls[ind_fit[i]] = 1; } } } if (bMat || bBond) { nrms = 1; } snew(gn_rms, nrms); snew(ind_rms, nrms); snew(irms, nrms); fprintf(stderr, "Select group%s for %s calculation\n", (nrms > 1) ? "s" : "", whatname[ewhat]); get_index(&(top.atoms), ftp2fn_null(efNDX, NFILE, fnm), nrms, irms, ind_rms, gn_rms); if (bNorm) { snew(rlsnorm, irms[0]); } snew(rls, nrms); for (j = 0; j < nrms; j++) { snew(rls[j], maxframe); } if (bMirror) { snew(rlsm, nrms); for (j = 0; j < nrms; j++) { snew(rlsm[j], maxframe); } } snew(time, maxframe); for (j = 0; j < nrms; j++) { bMass = FALSE; for (i = 0; i < irms[j]; i++) { if (bMassWeighted) { w_rms[ind_rms[j][i]] = top.atoms.atom[ind_rms[j][i]].m; } else { w_rms[ind_rms[j][i]] = 1.0; } bMass = bMass || (top.atoms.atom[ind_rms[j][i]].m != 0); } if (!bMass) { fprintf(stderr, "All masses in group %d are 0, using masses of 1\n", j); for (i = 0; i < irms[j]; i++) { w_rms[ind_rms[j][i]] = 1; } } } /* Prepare reference frame */ if (bPBC) { gpbc = gmx_rmpbc_init(&top.idef, ePBC, top.atoms.nr); gmx_rmpbc(gpbc, top.atoms.nr, box, xp); } if (bReset) { reset_x(ifit, ind_fit, top.atoms.nr, NULL, xp, w_rls); } if (bMirror) { /* generate reference structure mirror image: */ snew(xm, top.atoms.nr); for (i = 0; i < top.atoms.nr; i++) { copy_rvec(xp[i], xm[i]); xm[i][XX] = -xm[i][XX]; } } if (ewhat == ewRhoSc) { norm_princ(&top.atoms, ifit, ind_fit, top.atoms.nr, xp); } /* read first frame */ natoms_trx = read_first_x(oenv, &status, opt2fn("-f", NFILE, fnm), &t, &x, box); if (natoms_trx != top.atoms.nr) { fprintf(stderr, "\nWARNING: topology has %d atoms, whereas trajectory has %d\n", top.atoms.nr, natoms_trx); } natoms = min(top.atoms.nr, natoms_trx); if (bMat || bBond || bPrev) { snew(mat_x, NFRAME); if (bPrev) { /* With -prev we use all atoms for simplicity */ n_ind_m = natoms; } else { /* Check which atoms we need (fit/rms) */ snew(bInMat, natoms); for (i = 0; i < ifit; i++) { bInMat[ind_fit[i]] = TRUE; } n_ind_m = ifit; for (i = 0; i < irms[0]; i++) { if (!bInMat[ind_rms[0][i]]) { bInMat[ind_rms[0][i]] = TRUE; n_ind_m++; } } } /* Make an index of needed atoms */ snew(ind_m, n_ind_m); snew(rev_ind_m, natoms); j = 0; for (i = 0; i < natoms; i++) { if (bPrev || bInMat[i]) { ind_m[j] = i; rev_ind_m[i] = j; j++; } } snew(w_rls_m, n_ind_m); snew(ind_rms_m, irms[0]); snew(w_rms_m, n_ind_m); for (i = 0; i < ifit; i++) { w_rls_m[rev_ind_m[ind_fit[i]]] = w_rls[ind_fit[i]]; } for (i = 0; i < irms[0]; i++) { ind_rms_m[i] = rev_ind_m[ind_rms[0][i]]; w_rms_m[ind_rms_m[i]] = w_rms[ind_rms[0][i]]; } sfree(bInMat); } if (bBond) { ncons = 0; for (k = 0; k < F_NRE; k++) { if (IS_CHEMBOND(k)) { iatom = top.idef.il[k].iatoms; ncons += top.idef.il[k].nr/3; } } fprintf(stderr, "Found %d bonds in topology\n", ncons); snew(ind_bond1, ncons); snew(ind_bond2, ncons); ibond = 0; for (k = 0; k < F_NRE; k++) { if (IS_CHEMBOND(k)) { iatom = top.idef.il[k].iatoms; ncons = top.idef.il[k].nr/3; for (i = 0; i < ncons; i++) { bA1 = FALSE; bA2 = FALSE; for (j = 0; j < irms[0]; j++) { if (iatom[3*i+1] == ind_rms[0][j]) { bA1 = TRUE; } if (iatom[3*i+2] == ind_rms[0][j]) { bA2 = TRUE; } } if (bA1 && bA2) { ind_bond1[ibond] = rev_ind_m[iatom[3*i+1]]; ind_bond2[ibond] = rev_ind_m[iatom[3*i+2]]; ibond++; } } } } fprintf(stderr, "Using %d bonds for bond angle matrix\n", ibond); if (ibond == 0) { gmx_fatal(FARGS, "0 bonds found"); } } /* start looping over frames: */ tel_mat = 0; teller = 0; do { if (bPBC) { gmx_rmpbc(gpbc, natoms, box, x); } if (bReset) { reset_x(ifit, ind_fit, natoms, NULL, x, w_rls); } if (ewhat == ewRhoSc) { norm_princ(&top.atoms, ifit, ind_fit, natoms, x); } if (bFit) { /*do the least squares fit to original structure*/ do_fit(natoms, w_rls, xp, x); } if (teller % freq == 0) { /* keep frame for matrix calculation */ if (bMat || bBond || bPrev) { if (tel_mat >= NFRAME) { srenew(mat_x, tel_mat+1); } snew(mat_x[tel_mat], n_ind_m); for (i = 0; i < n_ind_m; i++) { copy_rvec(x[ind_m[i]], mat_x[tel_mat][i]); } } tel_mat++; } /*calculate energy of root_least_squares*/ if (bPrev) { j = tel_mat-prev-1; if (j < 0) { j = 0; } for (i = 0; i < n_ind_m; i++) { copy_rvec(mat_x[j][i], xp[ind_m[i]]); } if (bReset) { reset_x(ifit, ind_fit, natoms, NULL, xp, w_rls); } if (bFit) { do_fit(natoms, w_rls, x, xp); } } for (j = 0; (j < nrms); j++) { rls[j][teller] = calc_similar_ind(ewhat != ewRMSD, irms[j], ind_rms[j], w_rms, x, xp); } if (bNorm) { for (j = 0; (j < irms[0]); j++) { rlsnorm[j] += calc_similar_ind(ewhat != ewRMSD, 1, &(ind_rms[0][j]), w_rms, x, xp); } } if (bMirror) { if (bFit) { /*do the least squares fit to mirror of original structure*/ do_fit(natoms, w_rls, xm, x); } for (j = 0; j < nrms; j++) { rlsm[j][teller] = calc_similar_ind(ewhat != ewRMSD, irms[j], ind_rms[j], w_rms, x, xm); } } time[teller] = output_env_conv_time(oenv, t); teller++; if (teller >= maxframe) { maxframe += NFRAME; srenew(time, maxframe); for (j = 0; (j < nrms); j++) { srenew(rls[j], maxframe); } if (bMirror) { for (j = 0; (j < nrms); j++) { srenew(rlsm[j], maxframe); } } } } while (read_next_x(oenv, status, &t, x, box)); close_trj(status); if (bFile2) { snew(time2, maxframe2); fprintf(stderr, "\nWill read second trajectory file\n"); snew(mat_x2, NFRAME); natoms_trx2 = read_first_x(oenv, &status, opt2fn("-f2", NFILE, fnm), &t, &x, box); if (natoms_trx2 != natoms_trx) { gmx_fatal(FARGS, "Second trajectory (%d atoms) does not match the first one" " (%d atoms)", natoms_trx2, natoms_trx); } tel_mat2 = 0; teller2 = 0; do { if (bPBC) { gmx_rmpbc(gpbc, natoms, box, x); } if (bReset) { reset_x(ifit, ind_fit, natoms, NULL, x, w_rls); } if (ewhat == ewRhoSc) { norm_princ(&top.atoms, ifit, ind_fit, natoms, x); } if (bFit) { /*do the least squares fit to original structure*/ do_fit(natoms, w_rls, xp, x); } if (teller2 % freq2 == 0) { /* keep frame for matrix calculation */ if (bMat) { if (tel_mat2 >= NFRAME) { srenew(mat_x2, tel_mat2+1); } snew(mat_x2[tel_mat2], n_ind_m); for (i = 0; i < n_ind_m; i++) { copy_rvec(x[ind_m[i]], mat_x2[tel_mat2][i]); } } tel_mat2++; } time2[teller2] = output_env_conv_time(oenv, t); teller2++; if (teller2 >= maxframe2) { maxframe2 += NFRAME; srenew(time2, maxframe2); } } while (read_next_x(oenv, status, &t, x, box)); close_trj(status); } else { mat_x2 = mat_x; time2 = time; tel_mat2 = tel_mat; freq2 = freq; } gmx_rmpbc_done(gpbc); if (bMat || bBond) { /* calculate RMS matrix */ fprintf(stderr, "\n"); if (bMat) { fprintf(stderr, "Building %s matrix, %dx%d elements\n", whatname[ewhat], tel_mat, tel_mat2); snew(rmsd_mat, tel_mat); } if (bBond) { fprintf(stderr, "Building bond angle matrix, %dx%d elements\n", tel_mat, tel_mat2); snew(bond_mat, tel_mat); } snew(axis, tel_mat); snew(axis2, tel_mat2); rmsd_max = 0; if (bFile2) { rmsd_min = 1e10; } else { rmsd_min = 0; } rmsd_avg = 0; bond_max = 0; bond_min = 1e10; for (j = 0; j < tel_mat2; j++) { axis2[j] = time2[freq2*j]; } if (bDelta) { if (bDeltaLog) { delta_scalex = 8.0/log(2.0); delta_xsize = (int)(log(tel_mat/2)*delta_scalex+0.5)+1; } else { delta_xsize = tel_mat/2; } delta_scaley = 1.0/delta_maxy; snew(delta, delta_xsize); for (j = 0; j < delta_xsize; j++) { snew(delta[j], del_lev+1); } if (avl > 0) { snew(rmsdav_mat, tel_mat); for (j = 0; j < tel_mat; j++) { snew(rmsdav_mat[j], tel_mat); } } } if (bFitAll) { snew(mat_x2_j, natoms); } for (i = 0; i < tel_mat; i++) { axis[i] = time[freq*i]; fprintf(stderr, "\r element %5d; time %5.2f ", i, axis[i]); if (bMat) { snew(rmsd_mat[i], tel_mat2); } if (bBond) { snew(bond_mat[i], tel_mat2); } for (j = 0; j < tel_mat2; j++) { if (bFitAll) { for (k = 0; k < n_ind_m; k++) { copy_rvec(mat_x2[j][k], mat_x2_j[k]); } do_fit(n_ind_m, w_rls_m, mat_x[i], mat_x2_j); } else { mat_x2_j = mat_x2[j]; } if (bMat) { if (bFile2 || (i < j)) { rmsd_mat[i][j] = calc_similar_ind(ewhat != ewRMSD, irms[0], ind_rms_m, w_rms_m, mat_x[i], mat_x2_j); if (rmsd_mat[i][j] > rmsd_max) { rmsd_max = rmsd_mat[i][j]; } if (rmsd_mat[i][j] < rmsd_min) { rmsd_min = rmsd_mat[i][j]; } rmsd_avg += rmsd_mat[i][j]; } else { rmsd_mat[i][j] = rmsd_mat[j][i]; } } if (bBond) { if (bFile2 || (i <= j)) { ang = 0.0; for (m = 0; m < ibond; m++) { rvec_sub(mat_x[i][ind_bond1[m]], mat_x[i][ind_bond2[m]], vec1); rvec_sub(mat_x2_j[ind_bond1[m]], mat_x2_j[ind_bond2[m]], vec2); ang += acos(cos_angle(vec1, vec2)); } bond_mat[i][j] = ang*180.0/(M_PI*ibond); if (bond_mat[i][j] > bond_max) { bond_max = bond_mat[i][j]; } if (bond_mat[i][j] < bond_min) { bond_min = bond_mat[i][j]; } } else { bond_mat[i][j] = bond_mat[j][i]; } } } } if (bFile2) { rmsd_avg /= tel_mat*tel_mat2; } else { rmsd_avg /= tel_mat*(tel_mat - 1)/2; } if (bMat && (avl > 0)) { rmsd_max = 0.0; rmsd_min = 0.0; rmsd_avg = 0.0; for (j = 0; j < tel_mat-1; j++) { for (i = j+1; i < tel_mat; i++) { av_tot = 0; weight_tot = 0; for (my = -avl; my <= avl; my++) { if ((j+my >= 0) && (j+my < tel_mat)) { abs_my = abs(my); for (mx = -avl; mx <= avl; mx++) { if ((i+mx >= 0) && (i+mx < tel_mat)) { weight = (real)(avl+1-max(abs(mx), abs_my)); av_tot += weight*rmsd_mat[i+mx][j+my]; weight_tot += weight; } } } } rmsdav_mat[i][j] = av_tot/weight_tot; rmsdav_mat[j][i] = rmsdav_mat[i][j]; if (rmsdav_mat[i][j] > rmsd_max) { rmsd_max = rmsdav_mat[i][j]; } } } rmsd_mat = rmsdav_mat; } if (bMat) { fprintf(stderr, "\n%s: Min %f, Max %f, Avg %f\n", whatname[ewhat], rmsd_min, rmsd_max, rmsd_avg); rlo.r = 1; rlo.g = 1; rlo.b = 1; rhi.r = 0; rhi.g = 0; rhi.b = 0; if (rmsd_user_max != -1) { rmsd_max = rmsd_user_max; } if (rmsd_user_min != -1) { rmsd_min = rmsd_user_min; } if ((rmsd_user_max != -1) || (rmsd_user_min != -1)) { fprintf(stderr, "Min and Max value set to resp. %f and %f\n", rmsd_min, rmsd_max); } sprintf(buf, "%s %s matrix", gn_rms[0], whatname[ewhat]); write_xpm(opt2FILE("-m", NFILE, fnm, "w"), 0, buf, whatlabel[ewhat], output_env_get_time_label(oenv), output_env_get_time_label(oenv), tel_mat, tel_mat2, axis, axis2, rmsd_mat, rmsd_min, rmsd_max, rlo, rhi, &nlevels); /* Print the distribution of RMSD values */ if (opt2bSet("-dist", NFILE, fnm)) { low_rmsd_dist(opt2fn("-dist", NFILE, fnm), rmsd_max, tel_mat, rmsd_mat, oenv); } if (bDelta) { snew(delta_tot, delta_xsize); for (j = 0; j < tel_mat-1; j++) { for (i = j+1; i < tel_mat; i++) { mx = i-j; if (mx < tel_mat/2) { if (bDeltaLog) { mx = (int)(log(mx)*delta_scalex+0.5); } my = (int)(rmsd_mat[i][j]*delta_scaley*del_lev+0.5); delta_tot[mx] += 1.0; if ((rmsd_mat[i][j] >= 0) && (rmsd_mat[i][j] <= delta_maxy)) { delta[mx][my] += 1.0; } } } } delta_max = 0; for (i = 0; i < delta_xsize; i++) { if (delta_tot[i] > 0.0) { delta_tot[i] = 1.0/delta_tot[i]; for (j = 0; j <= del_lev; j++) { delta[i][j] *= delta_tot[i]; if (delta[i][j] > delta_max) { delta_max = delta[i][j]; } } } } fprintf(stderr, "Maximum in delta matrix: %f\n", delta_max); snew(del_xaxis, delta_xsize); snew(del_yaxis, del_lev+1); for (i = 0; i < delta_xsize; i++) { del_xaxis[i] = axis[i]-axis[0]; } for (i = 0; i < del_lev+1; i++) { del_yaxis[i] = delta_maxy*i/del_lev; } sprintf(buf, "%s %s vs. delta t", gn_rms[0], whatname[ewhat]); fp = gmx_ffopen("delta.xpm", "w"); write_xpm(fp, 0, buf, "density", output_env_get_time_label(oenv), whatlabel[ewhat], delta_xsize, del_lev+1, del_xaxis, del_yaxis, delta, 0.0, delta_max, rlo, rhi, &nlevels); gmx_ffclose(fp); } if (opt2bSet("-bin", NFILE, fnm)) { /* NB: File must be binary if we use fwrite */ fp = ftp2FILE(efDAT, NFILE, fnm, "wb"); for (i = 0; i < tel_mat; i++) { if (fwrite(rmsd_mat[i], sizeof(**rmsd_mat), tel_mat2, fp) != tel_mat2) { gmx_fatal(FARGS, "Error writing to output file"); } } gmx_ffclose(fp); } } if (bBond) { fprintf(stderr, "\nMin. angle: %f, Max. angle: %f\n", bond_min, bond_max); if (bond_user_max != -1) { bond_max = bond_user_max; } if (bond_user_min != -1) { bond_min = bond_user_min; } if ((bond_user_max != -1) || (bond_user_min != -1)) { fprintf(stderr, "Bond angle Min and Max set to:\n" "Min. angle: %f, Max. angle: %f\n", bond_min, bond_max); } rlo.r = 1; rlo.g = 1; rlo.b = 1; rhi.r = 0; rhi.g = 0; rhi.b = 0; sprintf(buf, "%s av. bond angle deviation", gn_rms[0]); write_xpm(opt2FILE("-bm", NFILE, fnm, "w"), 0, buf, "degrees", output_env_get_time_label(oenv), output_env_get_time_label(oenv), tel_mat, tel_mat2, axis, axis2, bond_mat, bond_min, bond_max, rlo, rhi, &nlevels); } } bAv = opt2bSet("-a", NFILE, fnm); /* Write the RMSD's to file */ if (!bPrev) { sprintf(buf, "%s", whatxvgname[ewhat]); } else { sprintf(buf, "%s with frame %g %s ago", whatxvgname[ewhat], time[prev*freq]-time[0], output_env_get_time_label(oenv)); } fp = xvgropen(opt2fn("-o", NFILE, fnm), buf, output_env_get_xvgr_tlabel(oenv), whatxvglabel[ewhat], oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"%s%s after %s%s%s\"\n", (nrms == 1) ? "" : "of ", gn_rms[0], fitgraphlabel[efit], bFit ? " to " : "", bFit ? gn_fit : ""); } if (nrms != 1) { xvgr_legend(fp, nrms, (const char**)gn_rms, oenv); } for (i = 0; (i < teller); i++) { if (bSplit && i > 0 && abs(time[bPrev ? freq*i : i]/output_env_get_time_factor(oenv)) < 1e-5) { fprintf(fp, "&\n"); } fprintf(fp, "%12.7f", time[bPrev ? freq*i : i]); for (j = 0; (j < nrms); j++) { fprintf(fp, " %12.7f", rls[j][i]); if (bAv) { rlstot += rls[j][i]; } } fprintf(fp, "\n"); } gmx_ffclose(fp); if (bMirror) { /* Write the mirror RMSD's to file */ sprintf(buf, "%s with Mirror", whatxvgname[ewhat]); sprintf(buf2, "Mirror %s", whatxvglabel[ewhat]); fp = xvgropen(opt2fn("-mir", NFILE, fnm), buf, output_env_get_xvgr_tlabel(oenv), buf2, oenv); if (nrms == 1) { if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"of %s after lsq fit to mirror of %s\"\n", gn_rms[0], gn_fit); } } else { if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"after lsq fit to mirror %s\"\n", gn_fit); } xvgr_legend(fp, nrms, (const char**)gn_rms, oenv); } for (i = 0; (i < teller); i++) { if (bSplit && i > 0 && abs(time[i]) < 1e-5) { fprintf(fp, "&\n"); } fprintf(fp, "%12.7f", time[i]); for (j = 0; (j < nrms); j++) { fprintf(fp, " %12.7f", rlsm[j][i]); } fprintf(fp, "\n"); } gmx_ffclose(fp); } if (bAv) { sprintf(buf, "Average %s", whatxvgname[ewhat]); sprintf(buf2, "Average %s", whatxvglabel[ewhat]); fp = xvgropen(opt2fn("-a", NFILE, fnm), buf, "Residue", buf2, oenv); for (j = 0; (j < nrms); j++) { fprintf(fp, "%10d %10g\n", j, rlstot/teller); } gmx_ffclose(fp); } if (bNorm) { fp = xvgropen("aver.xvg", gn_rms[0], "Residue", whatxvglabel[ewhat], oenv); for (j = 0; (j < irms[0]); j++) { fprintf(fp, "%10d %10g\n", j, rlsnorm[j]/teller); } gmx_ffclose(fp); } do_view(oenv, opt2fn_null("-a", NFILE, fnm), "-graphtype bar"); do_view(oenv, opt2fn("-o", NFILE, fnm), NULL); do_view(oenv, opt2fn_null("-mir", NFILE, fnm), NULL); do_view(oenv, opt2fn_null("-m", NFILE, fnm), NULL); do_view(oenv, opt2fn_null("-bm", NFILE, fnm), NULL); do_view(oenv, opt2fn_null("-dist", NFILE, fnm), NULL); return 0; }
int gmx_sorient(int argc, char *argv[]) { t_topology top; int ePBC = -1; t_trxstatus *status; int natoms; real t; rvec *xtop, *x; matrix box; FILE *fp; int i, p, sa0, sa1, sa2, n, ntot, nf, m, *hist1, *hist2, *histn, nbin1, nbin2, nrbin; real *histi1, *histi2, invbw, invrbw; double sum1, sum2; int *isize, nrefgrp, nrefat; int **index; char **grpname; real inp, outp, nav, normfac, rmin2, rmax2, rcut, rcut2, r2, r; real c1, c2; char str[STRLEN]; gmx_bool bTPS; rvec xref, dx, dxh1, dxh2, outer; gmx_rmpbc_t gpbc = NULL; t_pbc pbc; const char *legr[] = { "<cos(\\8q\\4\\s1\\N)>", "<3cos\\S2\\N(\\8q\\4\\s2\\N)-1>" }; const char *legc[] = { "cos(\\8q\\4\\s1\\N)", "3cos\\S2\\N(\\8q\\4\\s2\\N)-1" }; const char *desc[] = { "[THISMODULE] analyzes solvent orientation around solutes.", "It calculates two angles between the vector from one or more", "reference positions to the first atom of each solvent molecule:", "", " * [GRK]theta[grk][SUB]1[sub]: the angle with the vector from the first atom of the solvent", " molecule to the midpoint between atoms 2 and 3.", " * [GRK]theta[grk][SUB]2[sub]: the angle with the normal of the solvent plane, defined by the", " same three atoms, or, when the option [TT]-v23[tt] is set, ", " the angle with the vector between atoms 2 and 3.", "", "The reference can be a set of atoms or", "the center of mass of a set of atoms. The group of solvent atoms should", "consist of 3 atoms per solvent molecule.", "Only solvent molecules between [TT]-rmin[tt] and [TT]-rmax[tt] are", "considered for [TT]-o[tt] and [TT]-no[tt] each frame.[PAR]", "[TT]-o[tt]: distribtion of [MATH][COS][GRK]theta[grk][SUB]1[sub][cos][math] for rmin<=r<=rmax.[PAR]", "[TT]-no[tt]: distribution of [MATH][COS][GRK]theta[grk][SUB]2[sub][cos][math] for rmin<=r<=rmax.[PAR]", "[TT]-ro[tt]: [MATH][CHEVRON][COS][GRK]theta[grk][SUB]1[sub][cos][chevron][math] and [MATH][CHEVRON]3[COS]^2[GRK]theta[grk][SUB]2[sub][cos]-1[chevron][math] as a function of the", "distance.[PAR]", "[TT]-co[tt]: the sum over all solvent molecules within distance r", "of [MATH][COS][GRK]theta[grk][SUB]1[sub][cos][math] and [MATH]3[COS]^2([GRK]theta[grk][SUB]2[sub])-1[cos][math] as a function of r.[PAR]", "[TT]-rc[tt]: the distribution of the solvent molecules as a function of r" }; gmx_output_env_t *oenv; static gmx_bool bCom = FALSE, bVec23 = FALSE, bPBC = FALSE; static real rmin = 0.0, rmax = 0.5, binwidth = 0.02, rbinw = 0.02; t_pargs pa[] = { { "-com", FALSE, etBOOL, {&bCom}, "Use the center of mass as the reference postion" }, { "-v23", FALSE, etBOOL, {&bVec23}, "Use the vector between atoms 2 and 3" }, { "-rmin", FALSE, etREAL, {&rmin}, "Minimum distance (nm)" }, { "-rmax", FALSE, etREAL, {&rmax}, "Maximum distance (nm)" }, { "-cbin", FALSE, etREAL, {&binwidth}, "Binwidth for the cosine" }, { "-rbin", FALSE, etREAL, {&rbinw}, "Binwidth for r (nm)" }, { "-pbc", FALSE, etBOOL, {&bPBC}, "Check PBC for the center of mass calculation. Only necessary when your reference group consists of several molecules." } }; t_filenm fnm[] = { { efTRX, NULL, NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "sori", ffWRITE }, { efXVG, "-no", "snor", ffWRITE }, { efXVG, "-ro", "sord", ffWRITE }, { efXVG, "-co", "scum", ffWRITE }, { efXVG, "-rc", "scount", ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } bTPS = (opt2bSet("-s", NFILE, fnm) || !opt2bSet("-n", NFILE, fnm) || bCom); if (bTPS) { read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, NULL, box, bCom); } /* get index groups */ printf("Select a group of reference particles and a solvent group:\n"); snew(grpname, 2); snew(index, 2); snew(isize, 2); if (bTPS) { get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 2, isize, index, grpname); } else { get_index(NULL, ftp2fn(efNDX, NFILE, fnm), 2, isize, index, grpname); } if (bCom) { nrefgrp = 1; nrefat = isize[0]; } else { nrefgrp = isize[0]; nrefat = 1; } if (isize[1] % 3) { gmx_fatal(FARGS, "The number of solvent atoms (%d) is not a multiple of 3", isize[1]); } /* initialize reading trajectory: */ natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); rmin2 = sqr(rmin); rmax2 = sqr(rmax); rcut = 0.99*std::sqrt(max_cutoff2(guess_ePBC(box), box)); if (rcut == 0) { rcut = 10*rmax; } rcut2 = sqr(rcut); invbw = 1/binwidth; nbin1 = 1+static_cast<int>(2*invbw + 0.5); nbin2 = 1+static_cast<int>(invbw + 0.5); invrbw = 1/rbinw; snew(hist1, nbin1); snew(hist2, nbin2); nrbin = 1+static_cast<int>(rcut/rbinw); if (nrbin == 0) { nrbin = 1; } snew(histi1, nrbin); snew(histi2, nrbin); snew(histn, nrbin); ntot = 0; nf = 0; sum1 = 0; sum2 = 0; if (bTPS) { /* make molecules whole again */ gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms); } /* start analysis of trajectory */ do { if (bTPS) { /* make molecules whole again */ gmx_rmpbc(gpbc, natoms, box, x); } set_pbc(&pbc, ePBC, box); n = 0; inp = 0; for (p = 0; (p < nrefgrp); p++) { if (bCom) { calc_com_pbc(nrefat, &top, x, &pbc, index[0], xref, bPBC); } else { copy_rvec(x[index[0][p]], xref); } for (m = 0; m < isize[1]; m += 3) { sa0 = index[1][m]; sa1 = index[1][m+1]; sa2 = index[1][m+2]; range_check(sa0, 0, natoms); range_check(sa1, 0, natoms); range_check(sa2, 0, natoms); pbc_dx(&pbc, x[sa0], xref, dx); r2 = norm2(dx); if (r2 < rcut2) { r = std::sqrt(r2); if (!bVec23) { /* Determine the normal to the plain */ rvec_sub(x[sa1], x[sa0], dxh1); rvec_sub(x[sa2], x[sa0], dxh2); rvec_inc(dxh1, dxh2); svmul(1/r, dx, dx); unitv(dxh1, dxh1); inp = iprod(dx, dxh1); cprod(dxh1, dxh2, outer); unitv(outer, outer); outp = iprod(dx, outer); } else { /* Use the vector between the 2nd and 3rd atom */ rvec_sub(x[sa2], x[sa1], dxh2); unitv(dxh2, dxh2); outp = iprod(dx, dxh2)/r; } { int ii = static_cast<int>(invrbw*r); range_check(ii, 0, nrbin); histi1[ii] += inp; histi2[ii] += 3*sqr(outp) - 1; histn[ii]++; } if ((r2 >= rmin2) && (r2 < rmax2)) { int ii1 = static_cast<int>(invbw*(inp + 1)); int ii2 = static_cast<int>(invbw*std::abs(outp)); range_check(ii1, 0, nbin1); range_check(ii2, 0, nbin2); hist1[ii1]++; hist2[ii2]++; sum1 += inp; sum2 += outp; n++; } } } } ntot += n; nf++; } while (read_next_x(oenv, status, &t, x, box)); /* clean up */ sfree(x); close_trj(status); gmx_rmpbc_done(gpbc); /* Add the bin for the exact maximum to the previous bin */ hist1[nbin1-1] += hist1[nbin1]; hist2[nbin2-1] += hist2[nbin2]; nav = static_cast<real>(ntot)/(nrefgrp*nf); normfac = invbw/ntot; fprintf(stderr, "Average nr of molecules between %g and %g nm: %.1f\n", rmin, rmax, nav); if (ntot > 0) { sum1 /= ntot; sum2 /= ntot; fprintf(stderr, "Average cos(theta1) between %g and %g nm: %6.3f\n", rmin, rmax, sum1); fprintf(stderr, "Average 3cos2(theta2)-1 between %g and %g nm: %6.3f\n", rmin, rmax, sum2); } sprintf(str, "Solvent orientation between %g and %g nm", rmin, rmax); fp = xvgropen(opt2fn("-o", NFILE, fnm), str, "cos(\\8q\\4\\s1\\N)", "", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"average shell size %.1f molecules\"\n", nav); } for (i = 0; i < nbin1; i++) { fprintf(fp, "%g %g\n", (i+0.5)*binwidth-1, 2*normfac*hist1[i]); } xvgrclose(fp); sprintf(str, "Solvent normal orientation between %g and %g nm", rmin, rmax); fp = xvgropen(opt2fn("-no", NFILE, fnm), str, "cos(\\8q\\4\\s2\\N)", "", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"average shell size %.1f molecules\"\n", nav); } for (i = 0; i < nbin2; i++) { fprintf(fp, "%g %g\n", (i+0.5)*binwidth, normfac*hist2[i]); } xvgrclose(fp); sprintf(str, "Solvent orientation"); fp = xvgropen(opt2fn("-ro", NFILE, fnm), str, "r (nm)", "", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"as a function of distance\"\n"); } xvgr_legend(fp, 2, legr, oenv); for (i = 0; i < nrbin; i++) { fprintf(fp, "%g %g %g\n", (i+0.5)*rbinw, histn[i] ? histi1[i]/histn[i] : 0, histn[i] ? histi2[i]/histn[i] : 0); } xvgrclose(fp); sprintf(str, "Cumulative solvent orientation"); fp = xvgropen(opt2fn("-co", NFILE, fnm), str, "r (nm)", "", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"as a function of distance\"\n"); } xvgr_legend(fp, 2, legc, oenv); normfac = 1.0/(nrefgrp*nf); c1 = 0; c2 = 0; fprintf(fp, "%g %g %g\n", 0.0, c1, c2); for (i = 0; i < nrbin; i++) { c1 += histi1[i]*normfac; c2 += histi2[i]*normfac; fprintf(fp, "%g %g %g\n", (i+1)*rbinw, c1, c2); } xvgrclose(fp); sprintf(str, "Solvent distribution"); fp = xvgropen(opt2fn("-rc", NFILE, fnm), str, "r (nm)", "molecules/nm", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"as a function of distance\"\n"); } normfac = 1.0/(rbinw*nf); for (i = 0; i < nrbin; i++) { fprintf(fp, "%g %g\n", (i+0.5)*rbinw, histn[i]*normfac); } xvgrclose(fp); do_view(oenv, opt2fn("-o", NFILE, fnm), NULL); do_view(oenv, opt2fn("-no", NFILE, fnm), NULL); do_view(oenv, opt2fn("-ro", NFILE, fnm), "-nxy"); do_view(oenv, opt2fn("-co", NFILE, fnm), "-nxy"); return 0; }
int gmx_bundle(int argc,char *argv[]) { const char *desc[] = { "g_bundle analyzes bundles of axes. The axes can be for instance", "helix axes. The program reads two index groups and divides both", "of them in [TT]-na[tt] parts. The centers of mass of these parts", "define the tops and bottoms of the axes.", "Several quantities are written to file:", "the axis length, the distance and the z-shift of the axis mid-points", "with respect to the average center of all axes, the total tilt,", "the radial tilt and the lateral tilt with respect to the average axis.", "[PAR]", "With options [TT]-ok[tt], [TT]-okr[tt] and [TT]-okl[tt] the total,", "radial and lateral kinks of the axes are plotted. An extra index", "group of kink atoms is required, which is also divided into [TT]-na[tt]", "parts. The kink angle is defined as the angle between the kink-top and", "the bottom-kink vectors.", "[PAR]", "With option [TT]-oa[tt] the top, mid (or kink when [TT]-ok[tt] is set)", "and bottom points of each axis", "are written to a pdb file each frame. The residue numbers correspond", "to the axis numbers. When viewing this file with [TT]rasmol[tt], use the", "command line option [TT]-nmrpdb[tt], and type [TT]set axis true[tt] to", "display the reference axis." }; static int n=0; static gmx_bool bZ=FALSE; t_pargs pa[] = { { "-na", FALSE, etINT, {&n}, "Number of axes" }, { "-z", FALSE, etBOOL, {&bZ}, "Use the Z-axis as reference iso the average axis" } }; FILE *out,*flen,*fdist,*fz,*ftilt,*ftiltr,*ftiltl; FILE *fkink=NULL,*fkinkr=NULL,*fkinkl=NULL; t_trxstatus *status; t_trxstatus *fpdb; t_topology top; int ePBC; rvec *xtop; matrix box; t_trxframe fr; t_atoms outatoms; real t,comp; int natoms; char *grpname[MAX_ENDS],title[256]; /* FIXME: The constness should not be cast away */ char *anm=(char *)"CA",*rnm=(char *)"GLY"; int i,j,gnx[MAX_ENDS]; atom_id *index[MAX_ENDS]; t_bundle bun; gmx_bool bKink; rvec va,vb,vc,vr,vl; output_env_t oenv; gmx_rmpbc_t gpbc=NULL; #define NLEG asize(leg) t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, "-ol", "bun_len", ffWRITE }, { efXVG, "-od", "bun_dist", ffWRITE }, { efXVG, "-oz", "bun_z", ffWRITE }, { efXVG, "-ot", "bun_tilt", ffWRITE }, { efXVG, "-otr", "bun_tiltr", ffWRITE }, { efXVG, "-otl", "bun_tiltl", ffWRITE }, { efXVG, "-ok", "bun_kink", ffOPTWR }, { efXVG, "-okr", "bun_kinkr", ffOPTWR }, { efXVG, "-okl", "bun_kinkl", ffOPTWR }, { efPDB, "-oa", "axes", ffOPTWR } }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_TIME_UNIT | PCA_BE_NICE, NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv); read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&xtop,NULL,box,TRUE); bKink = opt2bSet("-ok",NFILE,fnm) || opt2bSet("-okr",NFILE,fnm) || opt2bSet("-okl",NFILE,fnm); if (bKink) bun.nend = 3; else bun.nend = 2; fprintf(stderr,"Select a group of top and a group of bottom "); if (bKink) fprintf(stderr,"and a group of kink "); fprintf(stderr,"atoms\n"); get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),bun.nend, gnx,index,grpname); if (n<=0 || gnx[0] % n || gnx[1] % n || (bKink && gnx[2] % n)) gmx_fatal(FARGS, "The size of one of your index groups is not a multiple of n"); bun.n = n; snew(bun.end[0],n); snew(bun.end[1],n); if (bKink) snew(bun.end[2],n); snew(bun.mid,n); snew(bun.dir,n); snew(bun.len,n); flen = xvgropen(opt2fn("-ol",NFILE,fnm),"Axis lengths", output_env_get_xvgr_tlabel(oenv),"(nm)",oenv); fdist = xvgropen(opt2fn("-od",NFILE,fnm),"Distance of axis centers", output_env_get_xvgr_tlabel(oenv),"(nm)",oenv); fz = xvgropen(opt2fn("-oz",NFILE,fnm),"Z-shift of axis centers", output_env_get_xvgr_tlabel(oenv),"(nm)",oenv); ftilt = xvgropen(opt2fn("-ot",NFILE,fnm),"Axis tilts", output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv); ftiltr = xvgropen(opt2fn("-otr",NFILE,fnm),"Radial axis tilts", output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv); ftiltl = xvgropen(opt2fn("-otl",NFILE,fnm),"Lateral axis tilts", output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv); if (bKink) { fkink = xvgropen(opt2fn("-ok",NFILE,fnm),"Kink angles", output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv); fkinkr = xvgropen(opt2fn("-okr",NFILE,fnm),"Radial kink angles", output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv); if (output_env_get_print_xvgr_codes(oenv)) fprintf(fkinkr,"@ subtitle \"+ = ) ( - = ( )\"\n"); fkinkl = xvgropen(opt2fn("-okl",NFILE,fnm),"Lateral kink angles", output_env_get_xvgr_tlabel(oenv),"(degrees)",oenv); } if (opt2bSet("-oa",NFILE,fnm)) { init_t_atoms(&outatoms,3*n,FALSE); outatoms.nr = 3*n; for(i=0; i<3*n; i++) { outatoms.atomname[i] = &anm; outatoms.atom[i].resind = i/3; outatoms.resinfo[i/3].name = &rnm; outatoms.resinfo[i/3].nr = i/3 + 1; outatoms.resinfo[i/3].ic = ' '; } fpdb = open_trx(opt2fn("-oa",NFILE,fnm),"w"); } else fpdb = NULL; read_first_frame(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&fr,TRX_NEED_X); gpbc = gmx_rmpbc_init(&top.idef,ePBC,fr.natoms,fr.box); do { gmx_rmpbc_trxfr(gpbc,&fr); calc_axes(fr.x,top.atoms.atom,gnx,index,!bZ,&bun); t = output_env_conv_time(oenv,fr.time); fprintf(flen," %10g",t); fprintf(fdist," %10g",t); fprintf(fz," %10g",t); fprintf(ftilt," %10g",t); fprintf(ftiltr," %10g",t); fprintf(ftiltl," %10g",t); if (bKink) { fprintf(fkink," %10g",t); fprintf(fkinkr," %10g",t); fprintf(fkinkl," %10g",t); } for(i=0; i<bun.n; i++) { fprintf(flen," %6g",bun.len[i]); fprintf(fdist," %6g",norm(bun.mid[i])); fprintf(fz," %6g",bun.mid[i][ZZ]); fprintf(ftilt," %6g",RAD2DEG*acos(bun.dir[i][ZZ])); comp = bun.mid[i][XX]*bun.dir[i][XX]+bun.mid[i][YY]*bun.dir[i][YY]; fprintf(ftiltr," %6g",RAD2DEG* asin(comp/sqrt(sqr(comp)+sqr(bun.dir[i][ZZ])))); comp = bun.mid[i][YY]*bun.dir[i][XX]-bun.mid[i][XX]*bun.dir[i][YY]; fprintf(ftiltl," %6g",RAD2DEG* asin(comp/sqrt(sqr(comp)+sqr(bun.dir[i][ZZ])))); if (bKink) { rvec_sub(bun.end[0][i],bun.end[2][i],va); rvec_sub(bun.end[2][i],bun.end[1][i],vb); unitv_no_table(va,va); unitv_no_table(vb,vb); fprintf(fkink," %6g",RAD2DEG*acos(iprod(va,vb))); cprod(va,vb,vc); copy_rvec(bun.mid[i],vr); vr[ZZ] = 0; unitv_no_table(vr,vr); fprintf(fkinkr," %6g",RAD2DEG*asin(iprod(vc,vr))); vl[XX] = vr[YY]; vl[YY] = -vr[XX]; vl[ZZ] = 0; fprintf(fkinkl," %6g",RAD2DEG*asin(iprod(vc,vl))); } } fprintf(flen,"\n"); fprintf(fdist,"\n"); fprintf(fz,"\n"); fprintf(ftilt,"\n"); fprintf(ftiltr,"\n"); fprintf(ftiltl,"\n"); if (bKink) { fprintf(fkink,"\n"); fprintf(fkinkr,"\n"); fprintf(fkinkl,"\n"); } if (fpdb ) dump_axes(fpdb,&fr,&outatoms,&bun); } while(read_next_frame(oenv,status,&fr)); gmx_rmpbc_done(gpbc); close_trx(status); if (fpdb ) close_trx(fpdb); ffclose(flen); ffclose(fdist); ffclose(fz); ffclose(ftilt); ffclose(ftiltr); ffclose(ftiltl); if (bKink) { ffclose(fkink); ffclose(fkinkr); ffclose(fkinkl); } thanx(stderr); return 0; }
int gmx_vanhove(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the Van Hove correlation function.", "The Van Hove G(r,t) is the probability that a particle that is at r[SUB]0[sub]", "at time zero can be found at position r[SUB]0[sub]+r at time t.", "[THISMODULE] determines G not for a vector r, but for the length of r.", "Thus it gives the probability that a particle moves a distance of r", "in time t.", "Jumps across the periodic boundaries are removed.", "Corrections are made for scaling due to isotropic", "or anisotropic pressure coupling.", "[PAR]", "With option [TT]-om[tt] the whole matrix can be written as a function", "of t and r or as a function of [SQRT]t[sqrt] and r (option [TT]-sqrt[tt]).", "[PAR]", "With option [TT]-or[tt] the Van Hove function is plotted for one", "or more values of t. Option [TT]-nr[tt] sets the number of times,", "option [TT]-fr[tt] the number spacing between the times.", "The binwidth is set with option [TT]-rbin[tt]. The number of bins", "is determined automatically.", "[PAR]", "With option [TT]-ot[tt] the integral up to a certain distance", "(option [TT]-rt[tt]) is plotted as a function of time.", "[PAR]", "For all frames that are read the coordinates of the selected particles", "are stored in memory. Therefore the program may use a lot of memory.", "For options [TT]-om[tt] and [TT]-ot[tt] the program may be slow.", "This is because the calculation scales as the number of frames times", "[TT]-fm[tt] or [TT]-ft[tt].", "Note that with the [TT]-dt[tt] option the memory usage and calculation", "time can be reduced." }; static int fmmax = 0, ftmax = 0, nlev = 81, nr = 1, fshift = 0; static real sbin = 0, rmax = 2, rbin = 0.01, mmax = 0, rint = 0; t_pargs pa[] = { { "-sqrt", FALSE, etREAL, {&sbin}, "Use [SQRT]t[sqrt] on the matrix axis which binspacing # in [SQRT]ps[sqrt]" }, { "-fm", FALSE, etINT, {&fmmax}, "Number of frames in the matrix, 0 is plot all" }, { "-rmax", FALSE, etREAL, {&rmax}, "Maximum r in the matrix (nm)" }, { "-rbin", FALSE, etREAL, {&rbin}, "Binwidth in the matrix and for [TT]-or[tt] (nm)" }, { "-mmax", FALSE, etREAL, {&mmax}, "Maximum density in the matrix, 0 is calculate (1/nm)" }, { "-nlevels", FALSE, etINT, {&nlev}, "Number of levels in the matrix" }, { "-nr", FALSE, etINT, {&nr}, "Number of curves for the [TT]-or[tt] output" }, { "-fr", FALSE, etINT, {&fshift}, "Frame spacing for the [TT]-or[tt] output" }, { "-rt", FALSE, etREAL, {&rint}, "Integration limit for the [TT]-ot[tt] output (nm)" }, { "-ft", FALSE, etINT, {&ftmax}, "Number of frames in the [TT]-ot[tt] output, 0 is plot all" } }; #define NPA asize(pa) t_filenm fnm[] = { { efTRX, NULL, NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXPM, "-om", "vanhove", ffOPTWR }, { efXVG, "-or", "vanhove_r", ffOPTWR }, { efXVG, "-ot", "vanhove_t", ffOPTWR } }; #define NFILE asize(fnm) output_env_t oenv; const char *matfile, *otfile, *orfile; char title[256]; t_topology top; int ePBC; matrix boxtop, box, *sbox, avbox, corr; rvec *xtop, *x, **sx; int isize, nalloc, nallocn, natom; t_trxstatus *status; atom_id *index; char *grpname; int nfr, f, ff, i, m, mat_nx = 0, nbin = 0, bin, mbin, fbin; real *time, t, invbin = 0, rmax2 = 0, rint2 = 0, d2; real invsbin = 0, matmax, normfac, dt, *tickx, *ticky; char buf[STRLEN], **legend; real **mat = NULL; int *pt = NULL, **pr = NULL, *mcount = NULL, *tcount = NULL, *rcount = NULL; FILE *fp; t_rgb rlo = {1, 1, 1}, rhi = {0, 0, 0}; if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } matfile = opt2fn_null("-om", NFILE, fnm); if (opt2parg_bSet("-fr", NPA, pa)) { orfile = opt2fn("-or", NFILE, fnm); } else { orfile = opt2fn_null("-or", NFILE, fnm); } if (opt2parg_bSet("-rt", NPA, pa)) { otfile = opt2fn("-ot", NFILE, fnm); } else { otfile = opt2fn_null("-ot", NFILE, fnm); } if (!matfile && !otfile && !orfile) { fprintf(stderr, "For output set one (or more) of the output file options\n"); exit(0); } read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &xtop, NULL, boxtop, FALSE); get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname); nalloc = 0; time = NULL; sbox = NULL; sx = NULL; clear_mat(avbox); natom = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); nfr = 0; do { if (nfr >= nalloc) { nalloc += 100; srenew(time, nalloc); srenew(sbox, nalloc); srenew(sx, nalloc); } time[nfr] = t; copy_mat(box, sbox[nfr]); /* This assumes that the off-diagonal box elements * are not affected by jumps across the periodic boundaries. */ m_add(avbox, box, avbox); snew(sx[nfr], isize); for (i = 0; i < isize; i++) { copy_rvec(x[index[i]], sx[nfr][i]); } nfr++; } while (read_next_x(oenv, status, &t, x, box)); /* clean up */ sfree(x); close_trj(status); fprintf(stderr, "Read %d frames\n", nfr); dt = (time[nfr-1] - time[0])/(nfr - 1); /* Some ugly rounding to get nice nice times in the output */ dt = (int)(10000.0*dt + 0.5)/10000.0; invbin = 1.0/rbin; if (matfile) { if (fmmax <= 0 || fmmax >= nfr) { fmmax = nfr - 1; } snew(mcount, fmmax); nbin = (int)(rmax*invbin + 0.5); if (sbin == 0) { mat_nx = fmmax + 1; } else { invsbin = 1.0/sbin; mat_nx = sqrt(fmmax*dt)*invsbin + 1; } snew(mat, mat_nx); for (f = 0; f < mat_nx; f++) { snew(mat[f], nbin); } rmax2 = sqr(nbin*rbin); /* Initialize time zero */ mat[0][0] = nfr*isize; mcount[0] += nfr; } else { fmmax = 0; } if (orfile) { snew(pr, nr); nalloc = 0; snew(rcount, nr); } if (otfile) { if (ftmax <= 0) { ftmax = nfr - 1; } snew(tcount, ftmax); snew(pt, nfr); rint2 = rint*rint; /* Initialize time zero */ pt[0] = nfr*isize; tcount[0] += nfr; } else { ftmax = 0; } msmul(avbox, 1.0/nfr, avbox); for (f = 0; f < nfr; f++) { if (f % 100 == 0) { fprintf(stderr, "\rProcessing frame %d", f); } /* Scale all the configuration to the average box */ m_inv_ur0(sbox[f], corr); mmul_ur0(avbox, corr, corr); for (i = 0; i < isize; i++) { mvmul_ur0(corr, sx[f][i], sx[f][i]); if (f > 0) { /* Correct for periodic jumps */ for (m = DIM-1; m >= 0; m--) { while (sx[f][i][m] - sx[f-1][i][m] > 0.5*avbox[m][m]) { rvec_dec(sx[f][i], avbox[m]); } while (sx[f][i][m] - sx[f-1][i][m] <= -0.5*avbox[m][m]) { rvec_inc(sx[f][i], avbox[m]); } } } } for (ff = 0; ff < f; ff++) { fbin = f - ff; if (fbin <= fmmax || fbin <= ftmax) { if (sbin == 0) { mbin = fbin; } else { mbin = (int)(sqrt(fbin*dt)*invsbin + 0.5); } for (i = 0; i < isize; i++) { d2 = distance2(sx[f][i], sx[ff][i]); if (mbin < mat_nx && d2 < rmax2) { bin = (int)(sqrt(d2)*invbin + 0.5); if (bin < nbin) { mat[mbin][bin] += 1; } } if (fbin <= ftmax && d2 <= rint2) { pt[fbin]++; } } if (matfile) { mcount[mbin]++; } if (otfile) { tcount[fbin]++; } } } if (orfile) { for (fbin = 0; fbin < nr; fbin++) { ff = f - (fbin + 1)*fshift; if (ff >= 0) { for (i = 0; i < isize; i++) { d2 = distance2(sx[f][i], sx[ff][i]); bin = (int)(sqrt(d2)*invbin + 0.5); if (bin >= nalloc) { nallocn = 10*(bin/10) + 11; for (m = 0; m < nr; m++) { srenew(pr[m], nallocn); for (i = nalloc; i < nallocn; i++) { pr[m][i] = 0; } } nalloc = nallocn; } pr[fbin][bin]++; } rcount[fbin]++; } } } } fprintf(stderr, "\n"); if (matfile) { matmax = 0; for (f = 0; f < mat_nx; f++) { normfac = 1.0/(mcount[f]*isize*rbin); for (i = 0; i < nbin; i++) { mat[f][i] *= normfac; if (mat[f][i] > matmax && (f != 0 || i != 0)) { matmax = mat[f][i]; } } } fprintf(stdout, "Value at (0,0): %.3f, maximum of the rest %.3f\n", mat[0][0], matmax); if (mmax > 0) { matmax = mmax; } snew(tickx, mat_nx); for (f = 0; f < mat_nx; f++) { if (sbin == 0) { tickx[f] = f*dt; } else { tickx[f] = f*sbin; } } snew(ticky, nbin+1); for (i = 0; i <= nbin; i++) { ticky[i] = i*rbin; } fp = gmx_ffopen(matfile, "w"); write_xpm(fp, MAT_SPATIAL_Y, "Van Hove function", "G (1/nm)", sbin == 0 ? "time (ps)" : "sqrt(time) (ps^1/2)", "r (nm)", mat_nx, nbin, tickx, ticky, mat, 0, matmax, rlo, rhi, &nlev); gmx_ffclose(fp); } if (orfile) { fp = xvgropen(orfile, "Van Hove function", "r (nm)", "G (nm\\S-1\\N)", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"for particles in group %s\"\n", grpname); } snew(legend, nr); for (fbin = 0; fbin < nr; fbin++) { sprintf(buf, "%g ps", (fbin + 1)*fshift*dt); legend[fbin] = strdup(buf); } xvgr_legend(fp, nr, (const char**)legend, oenv); for (i = 0; i < nalloc; i++) { fprintf(fp, "%g", i*rbin); for (fbin = 0; fbin < nr; fbin++) { fprintf(fp, " %g", (real)pr[fbin][i]/(rcount[fbin]*isize*rbin*(i == 0 ? 0.5 : 1))); } fprintf(fp, "\n"); } gmx_ffclose(fp); } if (otfile) { sprintf(buf, "Probability of moving less than %g nm", rint); fp = xvgropen(otfile, buf, "t (ps)", "", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp, "@ subtitle \"for particles in group %s\"\n", grpname); } for (f = 0; f <= ftmax; f++) { fprintf(fp, "%g %g\n", f*dt, (real)pt[f]/(tcount[f]*isize)); } gmx_ffclose(fp); } do_view(oenv, matfile, NULL); do_view(oenv, orfile, NULL); do_view(oenv, otfile, NULL); return 0; }
static void write_xvgr_graphs(const char *file, int ngraphs, int nsetspergraph, const char *title, const char *subtitle, const char *xlabel, const char **ylabel, int n, real *x, real **y, real ***sy, real scale_x, gmx_bool bZero, gmx_bool bSplit, const output_env_t oenv) { FILE *out; int g,s,i; real min,max,xsp,ysp; out=ffopen(file,"w"); if (output_env_get_xvg_format(oenv) == exvgXMGRACE) { fprintf(out,"@ autoscale onread none\n"); } for(g=0; g<ngraphs; g++) { if (y) { min=y[g][0]; max=y[g][0]; for(i=0; i<n; i++) { if (y[g][i]<min) min=y[g][i]; if (y[g][i]>max) max=y[g][i]; } } else { min=sy[g][0][0]; max=sy[g][0][0]; for(s=0; s<nsetspergraph; s++) for(i=0; i<n; i++) { if (sy[g][s][i]<min) min=sy[g][s][i]; if (sy[g][s][i]>max) max=sy[g][s][i]; } } if (bZero) min=0; else min=min-0.1*(max-min); max=max+0.1*(max-min); xsp=tick_spacing((x[n-1]-x[0])*scale_x,4); ysp=tick_spacing(max-min,3); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(out,"@ with g%d\n@ g%d on\n",g,g); if (g==0) { fprintf(out,"@ title \"%s\"\n",title); if (subtitle) fprintf(out,"@ subtitle \"%s\"\n",subtitle); } if (g==ngraphs-1) fprintf(out,"@ xaxis label \"%s\"\n",xlabel); else fprintf(out,"@ xaxis ticklabel off\n"); if (n > 1) { fprintf(out,"@ world xmin %g\n",x[0]*scale_x); fprintf(out,"@ world xmax %g\n",x[n-1]*scale_x); fprintf(out,"@ world ymin %g\n",min); fprintf(out,"@ world ymax %g\n",max); } fprintf(out,"@ view xmin 0.15\n"); fprintf(out,"@ view xmax 0.85\n"); fprintf(out,"@ view ymin %g\n",0.15+(ngraphs-1-g)*0.7/ngraphs); fprintf(out,"@ view ymax %g\n",0.15+(ngraphs-g)*0.7/ngraphs); fprintf(out,"@ yaxis label \"%s\"\n",ylabel[g]); fprintf(out,"@ xaxis tick major %g\n",xsp); fprintf(out,"@ xaxis tick minor %g\n",xsp/2); fprintf(out,"@ xaxis ticklabel start type spec\n"); fprintf(out,"@ xaxis ticklabel start %g\n",ceil(min/xsp)*xsp); fprintf(out,"@ yaxis tick major %g\n",ysp); fprintf(out,"@ yaxis tick minor %g\n",ysp/2); fprintf(out,"@ yaxis ticklabel start type spec\n"); fprintf(out,"@ yaxis ticklabel start %g\n",ceil(min/ysp)*ysp); if ((min<0) && (max>0)) { fprintf(out,"@ zeroxaxis bar on\n"); fprintf(out,"@ zeroxaxis bar linestyle 3\n"); } } for(s=0; s<nsetspergraph; s++) { for(i=0; i<n; i++) { if ( bSplit && i>0 && abs(x[i])<1e-5 ) { if (output_env_get_print_xvgr_codes(oenv)) fprintf(out,"&\n"); } fprintf(out,"%10.4f %10.5f\n", x[i]*scale_x,y ? y[g][i] : sy[g][s][i]); } if (output_env_get_print_xvgr_codes(oenv)) fprintf(out,"&\n"); } } ffclose(out); }
int gmx_enemat(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] extracts an energy matrix from the energy file ([TT]-f[tt]).", "With [TT]-groups[tt] a file must be supplied with on each", "line a group of atoms to be used. For these groups matrix of", "interaction energies will be extracted from the energy file", "by looking for energy groups with names corresponding to pairs", "of groups of atoms, e.g. if your [TT]-groups[tt] file contains::", "", " 2", " Protein", " SOL", "", "then energy groups with names like 'Coul-SR:Protein-SOL' and ", "'LJ:Protein-SOL' are expected in the energy file (although", "[THISMODULE] is most useful if many groups are analyzed", "simultaneously). Matrices for different energy types are written", "out separately, as controlled by the", "[TT]-[no]coul[tt], [TT]-[no]coulr[tt], [TT]-[no]coul14[tt], ", "[TT]-[no]lj[tt], [TT]-[no]lj14[tt], ", "[TT]-[no]bham[tt] and [TT]-[no]free[tt] options.", "Finally, the total interaction energy energy per group can be ", "calculated ([TT]-etot[tt]).[PAR]", "An approximation of the free energy can be calculated using:", "[MATH]E[SUB]free[sub] = E[SUB]0[sub] + kT [LOG][CHEVRON][EXP](E-E[SUB]0[sub])/kT[exp][chevron][log][math], where '[MATH][CHEVRON][chevron][math]'", "stands for time-average. A file with reference free energies", "can be supplied to calculate the free energy difference", "with some reference state. Group names (e.g. residue names)", "in the reference file should correspond to the group names", "as used in the [TT]-groups[tt] file, but a appended number", "(e.g. residue number) in the [TT]-groups[tt] will be ignored", "in the comparison." }; static gmx_bool bSum = FALSE; static gmx_bool bMeanEmtx = TRUE; static int skip = 0, nlevels = 20; static real cutmax = 1e20, cutmin = -1e20, reftemp = 300.0; static gmx_bool bCoulSR = TRUE, bCoul14 = FALSE; static gmx_bool bLJSR = TRUE, bLJ14 = FALSE, bBhamSR = FALSE, bFree = TRUE; t_pargs pa[] = { { "-sum", FALSE, etBOOL, {&bSum}, "Sum the energy terms selected rather than display them all" }, { "-skip", FALSE, etINT, {&skip}, "Skip number of frames between data points" }, { "-mean", FALSE, etBOOL, {&bMeanEmtx}, "with [TT]-groups[tt] extracts matrix of mean energies instead of " "matrix for each timestep" }, { "-nlevels", FALSE, etINT, {&nlevels}, "number of levels for matrix colors"}, { "-max", FALSE, etREAL, {&cutmax}, "max value for energies"}, { "-min", FALSE, etREAL, {&cutmin}, "min value for energies"}, { "-coulsr", FALSE, etBOOL, {&bCoulSR}, "extract Coulomb SR energies"}, { "-coul14", FALSE, etBOOL, {&bCoul14}, "extract Coulomb 1-4 energies"}, { "-ljsr", FALSE, etBOOL, {&bLJSR}, "extract Lennard-Jones SR energies"}, { "-lj14", FALSE, etBOOL, {&bLJ14}, "extract Lennard-Jones 1-4 energies"}, { "-bhamsr", FALSE, etBOOL, {&bBhamSR}, "extract Buckingham SR energies"}, { "-free", FALSE, etBOOL, {&bFree}, "calculate free energy"}, { "-temp", FALSE, etREAL, {&reftemp}, "reference temperature for free energy calculation"} }; /* We will define egSP more energy-groups: egTotal (total energy) */ #define egTotal egNR #define egSP 1 gmx_bool egrp_use[egNR+egSP]; ener_file_t in; FILE *out; int timecheck = 0; gmx_enxnm_t *enm = NULL; t_enxframe *fr; int teller = 0; real sum; gmx_bool bCont, bRef; gmx_bool bCutmax, bCutmin; real **eneset, *time = NULL; int *set, i, j, k, prevk, m = 0, n, nre, nset, nenergy; char **groups = NULL; char groupname[255], fn[255]; int ngroups; t_rgb rlo, rhi, rmid; real emax, emid, emin; real ***emat, **etot, *groupnr; double beta, expE, **e, *eaver, *efree = NULL, edum; char label[234]; char **ereflines, **erefres = NULL; real *eref = NULL, *edif = NULL; int neref = 0; gmx_output_env_t *oenv; t_filenm fnm[] = { { efEDR, "-f", NULL, ffOPTRD }, { efDAT, "-groups", "groups", ffREAD }, { efDAT, "-eref", "eref", ffOPTRD }, { efXPM, "-emat", "emat", ffWRITE }, { efXVG, "-etot", "energy", ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } for (i = 0; (i < egNR+egSP); i++) { egrp_use[i] = FALSE; } egrp_use[egCOULSR] = bCoulSR; egrp_use[egLJSR] = bLJSR; egrp_use[egBHAMSR] = bBhamSR; egrp_use[egCOUL14] = bCoul14; egrp_use[egLJ14] = bLJ14; egrp_use[egTotal] = TRUE; bRef = opt2bSet("-eref", NFILE, fnm); in = open_enx(ftp2fn(efEDR, NFILE, fnm), "r"); do_enxnms(in, &nre, &enm); if (nre == 0) { gmx_fatal(FARGS, "No energies!\n"); } bCutmax = opt2parg_bSet("-max", asize(pa), pa); bCutmin = opt2parg_bSet("-min", asize(pa), pa); nenergy = 0; /* Read groupnames from input file and construct selection of energy groups from it*/ fprintf(stderr, "Will read groupnames from inputfile\n"); ngroups = get_lines(opt2fn("-groups", NFILE, fnm), &groups); fprintf(stderr, "Read %d groups\n", ngroups); snew(set, static_cast<size_t>(gmx::square(ngroups)*egNR/2)); n = 0; prevk = 0; for (i = 0; (i < ngroups); i++) { fprintf(stderr, "\rgroup %d", i); for (j = i; (j < ngroups); j++) { for (m = 0; (m < egNR); m++) { if (egrp_use[m]) { sprintf(groupname, "%s:%s-%s", egrp_nm[m], groups[i], groups[j]); #ifdef DEBUG fprintf(stderr, "\r%-15s %5d", groupname, n); #endif for (k = prevk; (k < prevk+nre); k++) { if (std::strcmp(enm[k%nre].name, groupname) == 0) { set[n++] = k; break; } } if (k == prevk+nre) { fprintf(stderr, "WARNING! could not find group %s (%d,%d)" "in energy file\n", groupname, i, j); } else { prevk = k; } } } } } fprintf(stderr, "\n"); nset = n; snew(eneset, nset+1); fprintf(stderr, "Will select half-matrix of energies with %d elements\n", n); /* Start reading energy frames */ snew(fr, 1); do { do { bCont = do_enx(in, fr); if (bCont) { timecheck = check_times(fr->t); } } while (bCont && (timecheck < 0)); if (timecheck == 0) { #define DONTSKIP(cnt) (skip) ? ((cnt % skip) == 0) : TRUE if (bCont) { fprintf(stderr, "\rRead frame: %d, Time: %.3f", teller, fr->t); if ((nenergy % 1000) == 0) { srenew(time, nenergy+1000); for (i = 0; (i <= nset); i++) { srenew(eneset[i], nenergy+1000); } } time[nenergy] = fr->t; sum = 0; for (i = 0; (i < nset); i++) { eneset[i][nenergy] = fr->ener[set[i]].e; sum += fr->ener[set[i]].e; } if (bSum) { eneset[nset][nenergy] = sum; } nenergy++; } teller++; } } while (bCont && (timecheck == 0)); fprintf(stderr, "\n"); fprintf(stderr, "Will build energy half-matrix of %d groups, %d elements, " "over %d frames\n", ngroups, nset, nenergy); snew(emat, egNR+egSP); for (j = 0; (j < egNR+egSP); j++) { if (egrp_use[m]) { snew(emat[j], ngroups); for (i = 0; (i < ngroups); i++) { snew(emat[j][i], ngroups); } } } snew(groupnr, ngroups); for (i = 0; (i < ngroups); i++) { groupnr[i] = i+1; } rlo.r = 1.0, rlo.g = 0.0, rlo.b = 0.0; rmid.r = 1.0, rmid.g = 1.0, rmid.b = 1.0; rhi.r = 0.0, rhi.g = 0.0, rhi.b = 1.0; if (bMeanEmtx) { snew(e, ngroups); for (i = 0; (i < ngroups); i++) { snew(e[i], nenergy); } n = 0; for (i = 0; (i < ngroups); i++) { for (j = i; (j < ngroups); j++) { for (m = 0; (m < egNR); m++) { if (egrp_use[m]) { for (k = 0; (k < nenergy); k++) { emat[m][i][j] += eneset[n][k]; e[i][k] += eneset[n][k]; /* *0.5; */ e[j][k] += eneset[n][k]; /* *0.5; */ } n++; emat[egTotal][i][j] += emat[m][i][j]; emat[m][i][j] /= nenergy; emat[m][j][i] = emat[m][i][j]; } } emat[egTotal][i][j] /= nenergy; emat[egTotal][j][i] = emat[egTotal][i][j]; } } if (bFree) { if (bRef) { fprintf(stderr, "Will read reference energies from inputfile\n"); neref = get_lines(opt2fn("-eref", NFILE, fnm), &ereflines); fprintf(stderr, "Read %d reference energies\n", neref); snew(eref, neref); snew(erefres, neref); for (i = 0; (i < neref); i++) { snew(erefres[i], 5); sscanf(ereflines[i], "%s %lf", erefres[i], &edum); eref[i] = edum; } } snew(eaver, ngroups); for (i = 0; (i < ngroups); i++) { for (k = 0; (k < nenergy); k++) { eaver[i] += e[i][k]; } eaver[i] /= nenergy; } beta = 1.0/(BOLTZ*reftemp); snew(efree, ngroups); snew(edif, ngroups); for (i = 0; (i < ngroups); i++) { expE = 0; for (k = 0; (k < nenergy); k++) { expE += std::exp(beta*(e[i][k]-eaver[i])); } efree[i] = std::log(expE/nenergy)/beta + eaver[i]; if (bRef) { n = search_str2(neref, erefres, groups[i]); if (n != -1) { edif[i] = efree[i]-eref[n]; } else { edif[i] = efree[i]; fprintf(stderr, "WARNING: group %s not found " "in reference energies.\n", groups[i]); } } else { edif[i] = 0; } } } emid = 0.0; /*(emin+emax)*0.5;*/ egrp_nm[egTotal] = "total"; for (m = 0; (m < egNR+egSP); m++) { if (egrp_use[m]) { emin = 1e10; emax = -1e10; for (i = 0; (i < ngroups); i++) { for (j = i; (j < ngroups); j++) { if (emat[m][i][j] > emax) { emax = emat[m][i][j]; } else if (emat[m][i][j] < emin) { emin = emat[m][i][j]; } } } if (emax == emin) { fprintf(stderr, "Matrix of %s energy is uniform at %f " "(will not produce output).\n", egrp_nm[m], emax); } else { fprintf(stderr, "Matrix of %s energy ranges from %f to %f\n", egrp_nm[m], emin, emax); if ((bCutmax) || (emax > cutmax)) { emax = cutmax; } if ((bCutmin) || (emin < cutmin)) { emin = cutmin; } if ((emax == cutmax) || (emin == cutmin)) { fprintf(stderr, "Energy range adjusted: %f to %f\n", emin, emax); } sprintf(fn, "%s%s", egrp_nm[m], ftp2fn(efXPM, NFILE, fnm)); sprintf(label, "%s Interaction Energies", egrp_nm[m]); out = gmx_ffopen(fn, "w"); if (emin >= emid) { write_xpm(out, 0, label, "Energy (kJ/mol)", "Residue Index", "Residue Index", ngroups, ngroups, groupnr, groupnr, emat[m], emid, emax, rmid, rhi, &nlevels); } else if (emax <= emid) { write_xpm(out, 0, label, "Energy (kJ/mol)", "Residue Index", "Residue Index", ngroups, ngroups, groupnr, groupnr, emat[m], emin, emid, rlo, rmid, &nlevels); } else { write_xpm3(out, 0, label, "Energy (kJ/mol)", "Residue Index", "Residue Index", ngroups, ngroups, groupnr, groupnr, emat[m], emin, emid, emax, rlo, rmid, rhi, &nlevels); } gmx_ffclose(out); } } } snew(etot, egNR+egSP); for (m = 0; (m < egNR+egSP); m++) { snew(etot[m], ngroups); for (i = 0; (i < ngroups); i++) { for (j = 0; (j < ngroups); j++) { etot[m][i] += emat[m][i][j]; } } } out = xvgropen(ftp2fn(efXVG, NFILE, fnm), "Mean Energy", "Residue", "kJ/mol", oenv); xvgr_legend(out, 0, NULL, oenv); j = 0; if (output_env_get_print_xvgr_codes(oenv)) { char str1[STRLEN], str2[STRLEN]; if (output_env_get_xvg_format(oenv) == exvgXMGR) { sprintf(str1, "@ legend string "); sprintf(str2, " "); } else { sprintf(str1, "@ s"); sprintf(str2, " legend "); } for (m = 0; (m < egNR+egSP); m++) { if (egrp_use[m]) { fprintf(out, "%s%d%s \"%s\"\n", str1, j++, str2, egrp_nm[m]); } } if (bFree) { fprintf(out, "%s%d%s \"%s\"\n", str1, j++, str2, "Free"); } if (bFree) { fprintf(out, "%s%d%s \"%s\"\n", str1, j++, str2, "Diff"); } fprintf(out, "@TYPE xy\n"); fprintf(out, "#%3s", "grp"); for (m = 0; (m < egNR+egSP); m++) { if (egrp_use[m]) { fprintf(out, " %9s", egrp_nm[m]); } } if (bFree) { fprintf(out, " %9s", "Free"); } if (bFree) { fprintf(out, " %9s", "Diff"); } fprintf(out, "\n"); } for (i = 0; (i < ngroups); i++) { fprintf(out, "%3.0f", groupnr[i]); for (m = 0; (m < egNR+egSP); m++) { if (egrp_use[m]) { fprintf(out, " %9.5g", etot[m][i]); } } if (bFree) { fprintf(out, " %9.5g", efree[i]); } if (bRef) { fprintf(out, " %9.5g", edif[i]); } fprintf(out, "\n"); } xvgrclose(out); } else { fprintf(stderr, "While typing at your keyboard, suddenly...\n" "...nothing happens.\nWARNING: Not Implemented Yet\n"); /* out=ftp2FILE(efMAT,NFILE,fnm,"w"); n=0; emin=emax=0.0; for (k=0; (k<nenergy); k++) { for (i=0; (i<ngroups); i++) for (j=i+1; (j<ngroups); j++) emat[i][j]=eneset[n][k]; sprintf(label,"t=%.0f ps",time[k]); write_matrix(out,ngroups,1,ngroups,groupnr,emat,label,emin,emax,nlevels); n++; } gmx_ffclose(out); */ } close_enx(in); return 0; }
static void process_tcaf(int nframes, real dt, int nkc, real **tc, rvec *kfac, real rho, real wt, const char *fn_trans, const char *fn_tca, const char *fn_tc, const char *fn_tcf, const char *fn_cub, const char *fn_vk, const gmx_output_env_t *oenv) { FILE *fp, *fp_vk, *fp_cub = NULL; int nk, ntc; real **tcaf, **tcafc = NULL, eta, *sig; int i, j, k, kc; int ncorr; double fitparms[3]; nk = kset_c[nkc]; ntc = nk*NPK; if (fn_trans) { fp = xvgropen(fn_trans, "Transverse Current", "Time (ps)", "TC (nm/ps)", oenv); for (i = 0; i < nframes; i++) { fprintf(fp, "%g", i*dt); for (j = 0; j < ntc; j++) { fprintf(fp, " %g", tc[j][i]); } fprintf(fp, "\n"); } xvgrclose(fp); do_view(oenv, fn_trans, "-nxy"); } ncorr = (nframes+1)/2; if (ncorr > static_cast<int>(5*wt/dt+0.5)) { ncorr = static_cast<int>(5*wt/dt+0.5)+1; } snew(tcaf, nk); for (k = 0; k < nk; k++) { snew(tcaf[k], ncorr); } if (fn_cub) { snew(tcafc, nkc); for (k = 0; k < nkc; k++) { snew(tcafc[k], ncorr); } } snew(sig, ncorr); for (i = 0; i < ncorr; i++) { sig[i] = std::exp(0.5*i*dt/wt); } low_do_autocorr(fn_tca, oenv, "Transverse Current Autocorrelation Functions", nframes, ntc, ncorr, tc, dt, eacNormal, 1, FALSE, FALSE, FALSE, 0, 0, 0); do_view(oenv, fn_tca, "-nxy"); fp = xvgropen(fn_tc, "Transverse Current Autocorrelation Functions", "Time (ps)", "TCAF", oenv); for (i = 0; i < ncorr; i++) { kc = 0; fprintf(fp, "%g", i*dt); for (k = 0; k < nk; k++) { for (j = 0; j < NPK; j++) { tcaf[k][i] += tc[NPK*k+j][i]; } if (fn_cub) { for (j = 0; j < NPK; j++) { tcafc[kc][i] += tc[NPK*k+j][i]; } } if (i == 0) { fprintf(fp, " %g", 1.0); } else { tcaf[k][i] /= tcaf[k][0]; fprintf(fp, " %g", tcaf[k][i]); } if (k+1 == kset_c[kc+1]) { kc++; } } fprintf(fp, "\n"); } xvgrclose(fp); do_view(oenv, fn_tc, "-nxy"); if (fn_cub) { fp_cub = xvgropen(fn_cub, "TCAFs and fits", "Time (ps)", "TCAF", oenv); for (kc = 0; kc < nkc; kc++) { fprintf(fp_cub, "%g %g\n", 0.0, 1.0); for (i = 1; i < ncorr; i++) { tcafc[kc][i] /= tcafc[kc][0]; fprintf(fp_cub, "%g %g\n", i*dt, tcafc[kc][i]); } fprintf(fp_cub, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); tcafc[kc][0] = 1.0; } } fp_vk = xvgropen(fn_vk, "Fits", "k (nm\\S-1\\N)", "\\8h\\4 (10\\S-3\\N kg m\\S-1\\N s\\S-1\\N)", oenv); if (output_env_get_print_xvgr_codes(oenv)) { fprintf(fp_vk, "@ s0 symbol 2\n"); fprintf(fp_vk, "@ s0 symbol color 1\n"); fprintf(fp_vk, "@ s0 linestyle 0\n"); if (fn_cub) { fprintf(fp_vk, "@ s1 symbol 3\n"); fprintf(fp_vk, "@ s1 symbol color 2\n"); } } fp = xvgropen(fn_tcf, "TCAF Fits", "Time (ps)", "", oenv); for (k = 0; k < nk; k++) { tcaf[k][0] = 1.0; fitparms[0] = 1; fitparms[1] = 1; do_lmfit(ncorr, tcaf[k], sig, dt, 0, 0, ncorr*dt, oenv, bDebugMode(), effnVAC, fitparms, 0, NULL); eta = 1000*fitparms[1]*rho/ (4*fitparms[0]*PICO*norm2(kfac[k])/(NANO*NANO)); fprintf(stdout, "k %6.3f tau %6.3f eta %8.5f 10^-3 kg/(m s)\n", norm(kfac[k]), fitparms[0], eta); fprintf(fp_vk, "%6.3f %g\n", norm(kfac[k]), eta); for (i = 0; i < ncorr; i++) { fprintf(fp, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt)); } fprintf(fp, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } xvgrclose(fp); do_view(oenv, fn_tcf, "-nxy"); if (fn_cub) { fprintf(stdout, "Averaged over k-vectors:\n"); fprintf(fp_vk, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); for (k = 0; k < nkc; k++) { tcafc[k][0] = 1.0; fitparms[0] = 1; fitparms[1] = 1; do_lmfit(ncorr, tcafc[k], sig, dt, 0, 0, ncorr*dt, oenv, bDebugMode(), effnVAC, fitparms, 0, NULL); eta = 1000*fitparms[1]*rho/ (4*fitparms[0]*PICO*norm2(kfac[kset_c[k]])/(NANO*NANO)); fprintf(stdout, "k %6.3f tau %6.3f Omega %6.3f eta %8.5f 10^-3 kg/(m s)\n", norm(kfac[kset_c[k]]), fitparms[0], fitparms[1], eta); fprintf(fp_vk, "%6.3f %g\n", norm(kfac[kset_c[k]]), eta); for (i = 0; i < ncorr; i++) { fprintf(fp_cub, "%g %g\n", i*dt, fit_function(effnVAC, fitparms, i*dt)); } fprintf(fp_cub, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } fprintf(fp_vk, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); xvgrclose(fp_cub); do_view(oenv, fn_cub, "-nxy"); } xvgrclose(fp_vk); do_view(oenv, fn_vk, "-nxy"); }
void dist_plot(const char *fn, const char *afile, const char *dfile, const char *nfile, const char *rfile, const char *xfile, real rcut, gmx_bool bMat, t_atoms *atoms, int ng, atom_id *index[], int gnx[], char *grpn[], gmx_bool bSplit, gmx_bool bMin, int nres, atom_id *residue, gmx_bool bPBC, int ePBC, gmx_bool bGroup, gmx_bool bEachResEachTime, gmx_bool bPrintResName, const output_env_t oenv) { FILE *atm, *dist, *num; t_trxstatus *trxout; char buf[256]; char **leg; real t, dmin, dmax, **mindres = NULL, **maxdres = NULL; int nmin, nmax; t_trxstatus *status; int i = -1, j, k, natoms; int min1, min2, max1, max2, min1r, min2r, max1r, max2r; atom_id oindex[2]; rvec *x0; matrix box; t_trxframe frout; gmx_bool bFirst; FILE *respertime = NULL; if ((natoms = read_first_x(oenv, &status, fn, &t, &x0, box)) == 0) { gmx_fatal(FARGS, "Could not read coordinates from statusfile\n"); } sprintf(buf, "%simum Distance", bMin ? "Min" : "Max"); dist = xvgropen(dfile, buf, output_env_get_time_label(oenv), "Distance (nm)", oenv); sprintf(buf, "Number of Contacts %s %g nm", bMin ? "<" : ">", rcut); num = nfile ? xvgropen(nfile, buf, output_env_get_time_label(oenv), "Number", oenv) : NULL; atm = afile ? gmx_ffopen(afile, "w") : NULL; trxout = xfile ? open_trx(xfile, "w") : NULL; if (bMat) { if (ng == 1) { snew(leg, 1); sprintf(buf, "Internal in %s", grpn[0]); leg[0] = gmx_strdup(buf); xvgr_legend(dist, 0, (const char**)leg, oenv); if (num) { xvgr_legend(num, 0, (const char**)leg, oenv); } } else { snew(leg, (ng*(ng-1))/2); for (i = j = 0; (i < ng-1); i++) { for (k = i+1; (k < ng); k++, j++) { sprintf(buf, "%s-%s", grpn[i], grpn[k]); leg[j] = gmx_strdup(buf); } } xvgr_legend(dist, j, (const char**)leg, oenv); if (num) { xvgr_legend(num, j, (const char**)leg, oenv); } } } else { snew(leg, ng-1); for (i = 0; (i < ng-1); i++) { sprintf(buf, "%s-%s", grpn[0], grpn[i+1]); leg[i] = gmx_strdup(buf); } xvgr_legend(dist, ng-1, (const char**)leg, oenv); if (num) { xvgr_legend(num, ng-1, (const char**)leg, oenv); } } if (bEachResEachTime) { sprintf(buf, "%simum Distance", bMin ? "Min" : "Max"); respertime = xvgropen(rfile, buf, output_env_get_time_label(oenv), "Distance (nm)", oenv); xvgr_legend(respertime, ng-1, (const char**)leg, oenv); if (bPrintResName) { fprintf(respertime, "# "); } for (j = 0; j < nres; j++) { fprintf(respertime, "%s%d ", *(atoms->resinfo[atoms->atom[index[0][residue[j]]].resind].name), atoms->atom[index[0][residue[j]]].resind); } fprintf(respertime, "\n"); } j = 0; if (nres) { snew(mindres, ng-1); snew(maxdres, ng-1); for (i = 1; i < ng; i++) { snew(mindres[i-1], nres); snew(maxdres[i-1], nres); for (j = 0; j < nres; j++) { mindres[i-1][j] = 1e6; } /* maxdres[*][*] is already 0 */ } } bFirst = TRUE; do { if (bSplit && !bFirst && fabs(t/output_env_get_time_factor(oenv)) < 1e-5) { fprintf(dist, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); if (num) { fprintf(num, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } if (atm) { fprintf(atm, "%s\n", output_env_get_print_xvgr_codes(oenv) ? "&" : ""); } } fprintf(dist, "%12e", output_env_conv_time(oenv, t)); if (num) { fprintf(num, "%12e", output_env_conv_time(oenv, t)); } if (bMat) { if (ng == 1) { calc_dist(rcut, bPBC, ePBC, box, x0, gnx[0], gnx[0], index[0], index[0], bGroup, &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2); fprintf(dist, " %12e", bMin ? dmin : dmax); if (num) { fprintf(num, " %8d", bMin ? nmin : nmax); } } else { for (i = 0; (i < ng-1); i++) { for (k = i+1; (k < ng); k++) { calc_dist(rcut, bPBC, ePBC, box, x0, gnx[i], gnx[k], index[i], index[k], bGroup, &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2); fprintf(dist, " %12e", bMin ? dmin : dmax); if (num) { fprintf(num, " %8d", bMin ? nmin : nmax); } } } } } else { for (i = 1; (i < ng); i++) { calc_dist(rcut, bPBC, ePBC, box, x0, gnx[0], gnx[i], index[0], index[i], bGroup, &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2); fprintf(dist, " %12e", bMin ? dmin : dmax); if (num) { fprintf(num, " %8d", bMin ? nmin : nmax); } if (nres) { for (j = 0; j < nres; j++) { calc_dist(rcut, bPBC, ePBC, box, x0, residue[j+1]-residue[j], gnx[i], &(index[0][residue[j]]), index[i], bGroup, &dmin, &dmax, &nmin, &nmax, &min1r, &min2r, &max1r, &max2r); mindres[i-1][j] = min(mindres[i-1][j], dmin); maxdres[i-1][j] = max(maxdres[i-1][j], dmax); } } } } fprintf(dist, "\n"); if (num) { fprintf(num, "\n"); } if ( (bMin ? min1 : max1) != -1) { if (atm) { fprintf(atm, "%12e %12d %12d\n", output_env_conv_time(oenv, t), 1+(bMin ? min1 : max1), 1+(bMin ? min2 : max2)); } } if (trxout) { oindex[0] = bMin ? min1 : max1; oindex[1] = bMin ? min2 : max2; write_trx(trxout, 2, oindex, atoms, i, t, box, x0, NULL, NULL); } bFirst = FALSE; /*dmin should be minimum distance for residue and group*/ if (bEachResEachTime) { fprintf(respertime, "%12e", t); for (i = 1; i < ng; i++) { for (j = 0; j < nres; j++) { fprintf(respertime, " %7g", bMin ? mindres[i-1][j] : maxdres[i-1][j]); /*reset distances for next time point*/ mindres[i-1][j] = 1e6; maxdres[i-1][j] = 0; } } fprintf(respertime, "\n"); } } while (read_next_x(oenv, status, &t, x0, box)); close_trj(status); gmx_ffclose(dist); if (num) { gmx_ffclose(num); } if (atm) { gmx_ffclose(atm); } if (trxout) { close_trx(trxout); } if (nres && !bEachResEachTime) { FILE *res; sprintf(buf, "%simum Distance", bMin ? "Min" : "Max"); res = xvgropen(rfile, buf, "Residue (#)", "Distance (nm)", oenv); xvgr_legend(res, ng-1, (const char**)leg, oenv); for (j = 0; j < nres; j++) { fprintf(res, "%4d", j+1); for (i = 1; i < ng; i++) { fprintf(res, " %7g", bMin ? mindres[i-1][j] : maxdres[i-1][j]); } fprintf(res, "\n"); } } sfree(x0); }