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; }
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 ? 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] = 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] = 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] = 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 && abs(t/output_env_get_time_factor(oenv)) < 1e-5) { fprintf(dist, "&\n"); if (num) { fprintf(num, "&\n"); } if (atm) { fprintf(atm, "&\n"); } } 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); ffclose(dist); if (num) { ffclose(num); } if (atm) { 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); }
static int strip_dssp(char *dsspfile, int nres, gmx_bool bPhobres[], real t, real *acc, FILE *fTArea, t_matrix *mat, int average_area[], const output_env_t oenv) { static gmx_bool bFirst = TRUE; static char *ssbuf; FILE *tapeout; static int xsize, frame; char buf[STRLEN+1]; char SSTP; int i, nr, iacc, nresidues; int naccf, naccb; /* Count hydrophobic and hydrophilic residues */ real iaccf, iaccb; t_xpmelmt c; tapeout = gmx_ffopen(dsspfile, "r"); /* Skip header */ do { fgets2(buf, STRLEN, tapeout); } while (strstr(buf, "KAPPA") == NULL); if (bFirst) { /* Since we also have empty lines in the dssp output (temp) file, * and some line content is saved to the ssbuf variable, * we need more memory than just nres elements. To be shure, * we allocate 2*nres-1, since for each chain there is a * separating line in the temp file. (At most each residue * could have been defined as a separate chain.) */ snew(ssbuf, 2*nres-1); } iaccb = iaccf = 0; nresidues = 0; naccf = 0; naccb = 0; for (nr = 0; (fgets2(buf, STRLEN, tapeout) != NULL); nr++) { if (buf[13] == '!') /* Chain separator line has '!' at pos. 13 */ { SSTP = '='; /* Chain separator sign '=' */ } else { SSTP = buf[16] == ' ' ? '~' : buf[16]; } ssbuf[nr] = SSTP; buf[39] = '\0'; /* Only calculate solvent accessible area if needed */ if ((NULL != acc) && (buf[13] != '!')) { sscanf(&(buf[34]), "%d", &iacc); acc[nr] = iacc; /* average_area and bPhobres are counted from 0...nres-1 */ average_area[nresidues] += iacc; if (bPhobres[nresidues]) { naccb++; iaccb += iacc; } else { naccf++; iaccf += iacc; } /* Keep track of the residue number (do not count chain separator lines '!') */ nresidues++; } } ssbuf[nr] = '\0'; if (bFirst) { if (0 != acc) { fprintf(stderr, "%d residues were classified as hydrophobic and %d as hydrophilic.\n", naccb, naccf); } sprintf(mat->title, "Secondary structure"); mat->legend[0] = 0; sprintf(mat->label_x, "%s", output_env_get_time_label(oenv)); sprintf(mat->label_y, "Residue"); mat->bDiscrete = TRUE; mat->ny = nr; snew(mat->axis_y, nr); for (i = 0; i < nr; i++) { mat->axis_y[i] = i+1; } mat->axis_x = NULL; mat->matrix = NULL; xsize = 0; frame = 0; bFirst = FALSE; } if (frame >= xsize) { xsize += 10; srenew(mat->axis_x, xsize); srenew(mat->matrix, xsize); } mat->axis_x[frame] = t; snew(mat->matrix[frame], nr); c.c2 = 0; for (i = 0; i < nr; i++) { c.c1 = ssbuf[i]; mat->matrix[frame][i] = max(0, searchcmap(mat->nmap, mat->map, c)); } frame++; mat->nx = frame; if (fTArea) { fprintf(fTArea, "%10g %10g %10g\n", t, 0.01*iaccb, 0.01*iaccf); } gmx_ffclose(tapeout); /* Return the number of lines found in the dssp file (i.e. number * of redidues plus chain separator lines). * This is the number of y elements needed for the area xpm file */ return nr; }
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); }