void TrajectoryAnalysisRunnerCommon::Impl::finishTrajectory() { if (bTrajOpen_) { close_trx(status_); bTrajOpen_ = false; } if (gpbc_ != NULL) { gmx_rmpbc_done(gpbc_); gpbc_ = NULL; } }
static void calc_dihs(t_xrama *xr) { int i, t1, t2, t3; rvec r_ij, r_kj, r_kl, m, n; t_dih *dd; gmx_rmpbc_t gpbc = nullptr; gpbc = gmx_rmpbc_init(xr->idef, xr->ePBC, xr->natoms); gmx_rmpbc(gpbc, xr->natoms, xr->box, xr->x); gmx_rmpbc_done(gpbc); for (i = 0; (i < xr->ndih); i++) { dd = &(xr->dih[i]); dd->ang = dih_angle(xr->x[dd->ai[0]], xr->x[dd->ai[1]], xr->x[dd->ai[2]], xr->x[dd->ai[3]], nullptr, r_ij, r_kj, r_kl, m, n, &t1, &t2, &t3); } }
int gmx_spol(int argc, char *argv[]) { t_topology *top; t_inputrec *ir; t_atom *atom; t_trxstatus *status; int nrefat, natoms, nf, ntot; real t; rvec *x, xref, trial, dx = {0}, dip, dir; matrix box; FILE *fp; int *isize, nrefgrp; atom_id **index, *molindex; char **grpname; real rmin2, rmax2, rcut, rcut2, rdx2 = 0, rtry2, qav, q, dip2, invbw; int nbin, i, m, mol, a0, a1, a, d; double sdip, sdip2, sinp, sdinp, nmol; int *hist; t_pbc pbc; gmx_rmpbc_t gpbc = NULL; const char *desc[] = { "[THISMODULE] analyzes dipoles around a solute; it is especially useful", "for polarizable water. A group of reference atoms, or a center", "of mass reference (option [TT]-com[tt]) and a group of solvent", "atoms is required. The program splits the group of solvent atoms", "into molecules. For each solvent molecule the distance to the", "closest atom in reference group or to the COM is determined.", "A cumulative distribution of these distances is plotted.", "For each distance between [TT]-rmin[tt] and [TT]-rmax[tt]", "the inner product of the distance vector", "and the dipole of the solvent molecule is determined.", "For solvent molecules with net charge (ions), the net charge of the ion", "is subtracted evenly from all atoms in the selection of each ion.", "The average of these dipole components is printed.", "The same is done for the polarization, where the average dipole is", "subtracted from the instantaneous dipole. The magnitude of the average", "dipole is set with the option [TT]-dip[tt], the direction is defined", "by the vector from the first atom in the selected solvent group", "to the midpoint between the second and the third atom." }; output_env_t oenv; static gmx_bool bCom = FALSE; static int srefat = 1; static real rmin = 0.0, rmax = 0.32, refdip = 0, bw = 0.01; t_pargs pa[] = { { "-com", FALSE, etBOOL, {&bCom}, "Use the center of mass as the reference postion" }, { "-refat", FALSE, etINT, {&srefat}, "The reference atom of the solvent molecule" }, { "-rmin", FALSE, etREAL, {&rmin}, "Maximum distance (nm)" }, { "-rmax", FALSE, etREAL, {&rmax}, "Maximum distance (nm)" }, { "-dip", FALSE, etREAL, {&refdip}, "The average dipole (D)" }, { "-bw", FALSE, etREAL, {&bw}, "The bin width" } }; t_filenm fnm[] = { { efTRX, NULL, NULL, ffREAD }, { efTPR, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "scdist", 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; } snew(top, 1); snew(ir, 1); read_tpx_top(ftp2fn(efTPR, NFILE, fnm), ir, box, &natoms, NULL, NULL, NULL, top); /* get index groups */ printf("Select a group of reference particles and a solvent group:\n"); snew(grpname, 2); snew(index, 2); snew(isize, 2); get_index(&top->atoms, ftp2fn_null(efNDX, NFILE, fnm), 2, isize, index, grpname); if (bCom) { nrefgrp = 1; nrefat = isize[0]; } else { nrefgrp = isize[0]; nrefat = 1; } spol_atom2molindex(&(isize[1]), index[1], &(top->mols)); srefat--; /* initialize reading trajectory: */ natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); rcut = 0.99*std::sqrt(max_cutoff2(ir->ePBC, box)); if (rcut == 0) { rcut = 10*rmax; } rcut2 = sqr(rcut); invbw = 1/bw; nbin = static_cast<int>(rcut*invbw)+2; snew(hist, nbin); rmin2 = sqr(rmin); rmax2 = sqr(rmax); nf = 0; ntot = 0; sdip = 0; sdip2 = 0; sinp = 0; sdinp = 0; molindex = top->mols.index; atom = top->atoms.atom; gpbc = gmx_rmpbc_init(&top->idef, ir->ePBC, natoms); /* start analysis of trajectory */ do { /* make molecules whole again */ gmx_rmpbc(gpbc, natoms, box, x); set_pbc(&pbc, ir->ePBC, box); if (bCom) { calc_com_pbc(nrefat, top, x, &pbc, index[0], xref, ir->ePBC); } for (m = 0; m < isize[1]; m++) { mol = index[1][m]; a0 = molindex[mol]; a1 = molindex[mol+1]; for (i = 0; i < nrefgrp; i++) { pbc_dx(&pbc, x[a0+srefat], bCom ? xref : x[index[0][i]], trial); rtry2 = norm2(trial); if (i == 0 || rtry2 < rdx2) { copy_rvec(trial, dx); rdx2 = rtry2; } } if (rdx2 < rcut2) { hist[static_cast<int>(std::sqrt(rdx2)*invbw)+1]++; } if (rdx2 >= rmin2 && rdx2 < rmax2) { unitv(dx, dx); clear_rvec(dip); qav = 0; for (a = a0; a < a1; a++) { qav += atom[a].q; } qav /= (a1 - a0); for (a = a0; a < a1; a++) { q = atom[a].q - qav; for (d = 0; d < DIM; d++) { dip[d] += q*x[a][d]; } } for (d = 0; d < DIM; d++) { dir[d] = -x[a0][d]; } for (a = a0+1; a < a0+3; a++) { for (d = 0; d < DIM; d++) { dir[d] += 0.5*x[a][d]; } } unitv(dir, dir); svmul(ENM2DEBYE, dip, dip); dip2 = norm2(dip); sdip += std::sqrt(dip2); sdip2 += dip2; for (d = 0; d < DIM; d++) { sinp += dx[d]*dip[d]; sdinp += dx[d]*(dip[d] - refdip*dir[d]); } ntot++; } } nf++; } while (read_next_x(oenv, status, &t, x, box)); gmx_rmpbc_done(gpbc); /* clean up */ sfree(x); close_trj(status); fprintf(stderr, "Average number of molecules within %g nm is %.1f\n", rmax, static_cast<real>(ntot)/nf); if (ntot > 0) { sdip /= ntot; sdip2 /= ntot; sinp /= ntot; sdinp /= ntot; fprintf(stderr, "Average dipole: %f (D), std.dev. %f\n", sdip, std::sqrt(sdip2-sqr(sdip))); fprintf(stderr, "Average radial component of the dipole: %f (D)\n", sinp); fprintf(stderr, "Average radial component of the polarization: %f (D)\n", sdinp); } fp = xvgropen(opt2fn("-o", NFILE, fnm), "Cumulative solvent distribution", "r (nm)", "molecules", oenv); nmol = 0; for (i = 0; i <= nbin; i++) { nmol += hist[i]; fprintf(fp, "%g %g\n", i*bw, nmol/nf); } xvgrclose(fp); do_view(oenv, opt2fn("-o", 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; }
int gmx_spatial(int argc,char *argv[]) { const char *desc[] = { "g_spatial calculates the spatial distribution function and ", "outputs it in a form that can be read by VMD as Gaussian98 cube format. ", "This was developed from template.c (gromacs-3.3). ", "For a system of 32K atoms and a 50ns trajectory, the SDF can be generated ", "in about 30 minutes, with most of the time dedicated to the two runs through ", "trjconv that are required to center everything properly. ", "This also takes a whole bunch of space (3 copies of the xtc file). ", "Still, the pictures are pretty and very informative when the fitted selection is properly made. ", "3-4 atoms in a widely mobile group like a free amino acid in solution works ", "well, or select the protein backbone in a stable folded structure to get the SDF ", "of solvent and look at the time-averaged solvation shell. ", "It is also possible using this program to generate the SDF based on some arbitrarty ", "Cartesian coordinate. To do that, simply omit the preliminary trjconv steps. \n", "USAGE: \n", "1. Use make_ndx to create a group containing the atoms around which you want the SDF \n", "2. trjconv -s a.tpr -f a.xtc -o b.xtc -center tric -ur compact -pbc none \n", "3. trjconv -s a.tpr -f b.xtc -o c.xtc -fit rot+trans \n", "4. run g_spatial on the xtc output of step #3. \n", "5. Load grid.cube into VMD and view as an isosurface. \n", "*** Systems such as micelles will require trjconv -pbc cluster between steps 1 and 2\n", "WARNINGS: \n", "The SDF will be generated for a cube that contains all bins that have some non-zero occupancy. ", "However, the preparatory -fit rot+trans option to trjconv implies that your system will be rotating ", "and translating in space (in order that the selected group does not). Therefore the values that are ", "returned will only be valid for some region around your central group/coordinate that has full overlap ", "with system volume throughout the entire translated/rotated system over the course of the trajectory. ", "It is up to the user to ensure that this is the case. \n", "BUGS: \n", "When the allocated memory is not large enough, a segmentation fault may occur. This is usually detected ", "and the program is halted prior to the fault while displaying a warning message suggesting the use of the -nab ", "option. However, the program does not detect all such events. If you encounter a segmentation fault, run it again ", "with an increased -nab value. \n", "RISKY OPTIONS: \n", "To reduce the amount of space and time required, you can output only the coords ", "that are going to be used in the first and subsequent run through trjconv. ", "However, be sure to set the -nab option to a sufficiently high value since ", "memory is allocated for cube bins based on the initial coords and the -nab ", "(Number of Additional Bins) option value. \n" }; static gmx_bool bPBC=FALSE; static gmx_bool bSHIFT=FALSE; static int iIGNOREOUTER=-1; /*Positive values may help if the surface is spikey */ static gmx_bool bCUTDOWN=TRUE; static real rBINWIDTH=0.05; /* nm */ static gmx_bool bCALCDIV=TRUE; static int iNAB=4; t_pargs pa[] = { { "-pbc", FALSE, etBOOL, {&bPBC}, "Use periodic boundary conditions for computing distances" }, { "-div", FALSE, etBOOL, {&bCALCDIV}, "Calculate and apply the divisor for bin occupancies based on atoms/minimal cube size. Set as TRUE for visualization and as FALSE (-nodiv) to get accurate counts per frame" }, { "-ign", FALSE, etINT, {&iIGNOREOUTER}, "Do not display this number of outer cubes (positive values may reduce boundary speckles; -1 ensures outer surface is visible)" }, /* { "-cut", bCUTDOWN, etBOOL, {&bCUTDOWN},*/ /* "Display a total cube that is of minimal size" }, */ { "-bin", FALSE, etREAL, {&rBINWIDTH}, "Width of the bins in nm" }, { "-nab", FALSE, etINT, {&iNAB}, "Number of additional bins to ensure proper memory allocation" } }; double MINBIN[3]; double MAXBIN[3]; t_topology top; int ePBC; char title[STRLEN]; t_trxframe fr; rvec *xtop,*shx[26]; matrix box,box_pbc; t_trxstatus *status; int flags = TRX_READ_X; t_pbc pbc; t_atoms *atoms; int natoms; char *grpnm,*grpnmp; atom_id *index,*indexp; int i,nidx,nidxp; int v; int j,k; long ***bin=(long ***)NULL; long nbin[3]; FILE *flp; long x,y,z,minx,miny,minz,maxx,maxy,maxz; long numfr, numcu; long tot,max,min; double norm; output_env_t oenv; gmx_rmpbc_t gpbc=NULL; t_filenm fnm[] = { { efTPS, NULL, NULL, ffREAD }, /* this is for the topology */ { efTRX, "-f", NULL, ffREAD }, /* and this for the trajectory */ { efNDX, NULL, NULL, ffOPTRD } }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); /* This is the routine responsible for adding default options, * calling the X/motif interface, etc. */ parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW, 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); sfree(xtop); atoms=&(top.atoms); printf("Select group to generate SDF:\n"); get_index(atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&nidx,&index,&grpnm); printf("Select group to output coords (e.g. solute):\n"); get_index(atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&nidxp,&indexp,&grpnmp); /* The first time we read data is a little special */ natoms=read_first_frame(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&fr,flags); /* Memory Allocation */ MINBIN[XX]=MAXBIN[XX]=fr.x[0][XX]; MINBIN[YY]=MAXBIN[YY]=fr.x[0][YY]; MINBIN[ZZ]=MAXBIN[ZZ]=fr.x[0][ZZ]; for(i=1; i<top.atoms.nr; ++i) { if(fr.x[i][XX]<MINBIN[XX])MINBIN[XX]=fr.x[i][XX]; if(fr.x[i][XX]>MAXBIN[XX])MAXBIN[XX]=fr.x[i][XX]; if(fr.x[i][YY]<MINBIN[YY])MINBIN[YY]=fr.x[i][YY]; if(fr.x[i][YY]>MAXBIN[YY])MAXBIN[YY]=fr.x[i][YY]; if(fr.x[i][ZZ]<MINBIN[ZZ])MINBIN[ZZ]=fr.x[i][ZZ]; if(fr.x[i][ZZ]>MAXBIN[ZZ])MAXBIN[ZZ]=fr.x[i][ZZ]; } for (i=ZZ; i>=XX; --i){ MAXBIN[i]=(ceil((MAXBIN[i]-MINBIN[i])/rBINWIDTH)+(double)iNAB)*rBINWIDTH+MINBIN[i]; MINBIN[i]-=(double)iNAB*rBINWIDTH; nbin[i]=(long)ceil((MAXBIN[i]-MINBIN[i])/rBINWIDTH); } bin=(long ***)malloc(nbin[XX]*sizeof(long **)); if(!bin)mequit(); for(i=0; i<nbin[XX]; ++i){ bin[i]=(long **)malloc(nbin[YY]*sizeof(long *)); if(!bin[i])mequit(); for(j=0; j<nbin[YY]; ++j){ bin[i][j]=(long *)calloc(nbin[ZZ],sizeof(long)); if(!bin[i][j])mequit(); } } copy_mat(box,box_pbc); numfr=0; minx=miny=minz=999; maxx=maxy=maxz=0; if (bPBC) gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box); /* This is the main loop over frames */ do { /* Must init pbc every step because of pressure coupling */ copy_mat(box,box_pbc); if (bPBC) { gmx_rmpbc_trxfr(gpbc,&fr); set_pbc(&pbc,ePBC,box_pbc); } for(i=0; i<nidx; i++) { if(fr.x[index[i]][XX]<MINBIN[XX]||fr.x[index[i]][XX]>MAXBIN[XX]|| fr.x[index[i]][YY]<MINBIN[YY]||fr.x[index[i]][YY]>MAXBIN[YY]|| fr.x[index[i]][ZZ]<MINBIN[ZZ]||fr.x[index[i]][ZZ]>MAXBIN[ZZ]) { printf("There was an item outside of the allocated memory. Increase the value given with the -nab option.\n"); printf("Memory was allocated for [%f,%f,%f]\tto\t[%f,%f,%f]\n",MINBIN[XX],MINBIN[YY],MINBIN[ZZ],MAXBIN[XX],MAXBIN[YY],MAXBIN[ZZ]); printf("Memory was required for [%f,%f,%f]\n",fr.x[index[i]][XX],fr.x[index[i]][YY],fr.x[index[i]][ZZ]); exit(1); } x=(long)ceil((fr.x[index[i]][XX]-MINBIN[XX])/rBINWIDTH); y=(long)ceil((fr.x[index[i]][YY]-MINBIN[YY])/rBINWIDTH); z=(long)ceil((fr.x[index[i]][ZZ]-MINBIN[ZZ])/rBINWIDTH); ++bin[x][y][z]; if(x<minx)minx=x; if(x>maxx)maxx=x; if(y<miny)miny=y; if(y>maxy)maxy=y; if(z<minz)minz=z; if(z>maxz)maxz=z; } numfr++; /* printf("%f\t%f\t%f\n",box[XX][XX],box[YY][YY],box[ZZ][ZZ]); */ } while(read_next_frame(oenv,status,&fr)); if (bPBC) gmx_rmpbc_done(gpbc); if(!bCUTDOWN){ minx=miny=minz=0; maxx=nbin[XX]; maxy=nbin[YY]; maxz=nbin[ZZ]; } /* OUTPUT */ flp=ffopen("grid.cube","w"); fprintf(flp,"Spatial Distribution Function\n"); fprintf(flp,"test\n"); fprintf(flp,"%5d%12.6f%12.6f%12.6f\n",nidxp,(MINBIN[XX]+(minx+iIGNOREOUTER)*rBINWIDTH)*10./bohr,(MINBIN[YY]+(miny+iIGNOREOUTER)*rBINWIDTH)*10./bohr,(MINBIN[ZZ]+(minz+iIGNOREOUTER)*rBINWIDTH)*10./bohr); fprintf(flp,"%5ld%12.6f%12.6f%12.6f\n",maxx-minx+1-(2*iIGNOREOUTER),rBINWIDTH*10./bohr,0.,0.); fprintf(flp,"%5ld%12.6f%12.6f%12.6f\n",maxy-miny+1-(2*iIGNOREOUTER),0.,rBINWIDTH*10./bohr,0.); fprintf(flp,"%5ld%12.6f%12.6f%12.6f\n",maxz-minz+1-(2*iIGNOREOUTER),0.,0.,rBINWIDTH*10./bohr); for(i=0; i<nidxp; i++){ v=2; if(*(top.atoms.atomname[indexp[i]][0])=='C')v=6; if(*(top.atoms.atomname[indexp[i]][0])=='N')v=7; if(*(top.atoms.atomname[indexp[i]][0])=='O')v=8; if(*(top.atoms.atomname[indexp[i]][0])=='H')v=1; if(*(top.atoms.atomname[indexp[i]][0])=='S')v=16; fprintf(flp,"%5d%12.6f%12.6f%12.6f%12.6f\n",v,0.,(double)fr.x[indexp[i]][XX]*10./bohr,(double)fr.x[indexp[i]][YY]*10./bohr,(double)fr.x[indexp[i]][ZZ]*10./bohr); } tot=0; for(k=0;k<nbin[XX];k++) { if(!(k<minx||k>maxx))continue; for(j=0;j<nbin[YY];j++) { if(!(j<miny||j>maxy))continue; for(i=0;i<nbin[ZZ];i++) { if(!(i<minz||i>maxz))continue; if(bin[k][j][i]!=0){ printf("A bin was not empty when it should have been empty. Programming error.\n"); printf("bin[%d][%d][%d] was = %ld\n",k,j,i,bin[k][j][i]); exit(1); } } } } min=999; max=0; for(k=0;k<nbin[XX];k++) { if(k<minx+iIGNOREOUTER||k>maxx-iIGNOREOUTER)continue; for(j=0;j<nbin[YY];j++) { if(j<miny+iIGNOREOUTER||j>maxy-iIGNOREOUTER)continue; for(i=0;i<nbin[ZZ];i++) { if(i<minz+iIGNOREOUTER||i>maxz-iIGNOREOUTER)continue; tot+=bin[k][j][i]; if(bin[k][j][i]>max)max=bin[k][j][i]; if(bin[k][j][i]<min)min=bin[k][j][i]; } } } numcu=(maxx-minx+1-(2*iIGNOREOUTER))*(maxy-miny+1-(2*iIGNOREOUTER))*(maxz-minz+1-(2*iIGNOREOUTER)); if(bCALCDIV){ norm=((double)numcu*(double)numfr) / (double)tot; }else{ norm=1.0; } for(k=0;k<nbin[XX];k++) { if(k<minx+iIGNOREOUTER||k>maxx-iIGNOREOUTER)continue; for(j=0;j<nbin[YY];j++) { if(j<miny+iIGNOREOUTER||j>maxy-iIGNOREOUTER)continue; for(i=0;i<nbin[ZZ];i++) { if(i<minz+iIGNOREOUTER||i>maxz-iIGNOREOUTER)continue; fprintf(flp,"%12.6f ",norm*(double)bin[k][j][i]/(double)numfr); } fprintf(flp,"\n"); } fprintf(flp,"\n"); } ffclose(flp); /* printf("x=%d to %d\n",minx,maxx); */ /* printf("y=%d to %d\n",miny,maxy); */ /* printf("z=%d to %d\n",minz,maxz); */ if(bCALCDIV){ printf("Counts per frame in all %ld cubes divided by %le\n",numcu,1.0/norm); printf("Normalized data: average %le, min %le, max %le\n",1.0,norm*(double)min/(double)numfr,norm*(double)max/(double)numfr); }else{ printf("grid.cube contains counts per frame in all %ld cubes\n",numcu); printf("Raw data: average %le, min %le, max %le\n",1.0/norm,(double)min/(double)numfr,(double)max/(double)numfr); } thanx(stderr); return 0; }
int gmx_anaeig(int argc,char *argv[]) { static const char *desc[] = { "[TT]g_anaeig[tt] analyzes eigenvectors. The eigenvectors can be of a", "covariance matrix ([TT]g_covar[tt]) or of a Normal Modes analysis", "([TT]g_nmeig[tt]).[PAR]", "When a trajectory is projected on eigenvectors, all structures are", "fitted to the structure in the eigenvector file, if present, otherwise", "to the structure in the structure file. When no run input file is", "supplied, periodicity will not be taken into account. Most analyses", "are performed on eigenvectors [TT]-first[tt] to [TT]-last[tt], but when", "[TT]-first[tt] is set to -1 you will be prompted for a selection.[PAR]", "[TT]-comp[tt]: plot the vector components per atom of eigenvectors", "[TT]-first[tt] to [TT]-last[tt].[PAR]", "[TT]-rmsf[tt]: plot the RMS fluctuation per atom of eigenvectors", "[TT]-first[tt] to [TT]-last[tt] (requires [TT]-eig[tt]).[PAR]", "[TT]-proj[tt]: calculate projections of a trajectory on eigenvectors", "[TT]-first[tt] to [TT]-last[tt].", "The projections of a trajectory on the eigenvectors of its", "covariance matrix are called principal components (pc's).", "It is often useful to check the cosine content of the pc's,", "since the pc's of random diffusion are cosines with the number", "of periods equal to half the pc index.", "The cosine content of the pc's can be calculated with the program", "[TT]g_analyze[tt].[PAR]", "[TT]-2d[tt]: calculate a 2d projection of a trajectory on eigenvectors", "[TT]-first[tt] and [TT]-last[tt].[PAR]", "[TT]-3d[tt]: calculate a 3d projection of a trajectory on the first", "three selected eigenvectors.[PAR]", "[TT]-filt[tt]: filter the trajectory to show only the motion along", "eigenvectors [TT]-first[tt] to [TT]-last[tt].[PAR]", "[TT]-extr[tt]: calculate the two extreme projections along a trajectory", "on the average structure and interpolate [TT]-nframes[tt] frames", "between them, or set your own extremes with [TT]-max[tt]. The", "eigenvector [TT]-first[tt] will be written unless [TT]-first[tt] and", "[TT]-last[tt] have been set explicitly, in which case all eigenvectors", "will be written to separate files. Chain identifiers will be added", "when writing a [TT].pdb[tt] file with two or three structures (you", "can use [TT]rasmol -nmrpdb[tt] to view such a [TT].pdb[tt] file).[PAR]", " Overlap calculations between covariance analysis:[BR]", " [BB]Note:[bb] the analysis should use the same fitting structure[PAR]", "[TT]-over[tt]: calculate the subspace overlap of the eigenvectors in", "file [TT]-v2[tt] with eigenvectors [TT]-first[tt] to [TT]-last[tt]", "in file [TT]-v[tt].[PAR]", "[TT]-inpr[tt]: calculate a matrix of inner-products between", "eigenvectors in files [TT]-v[tt] and [TT]-v2[tt]. All eigenvectors", "of both files will be used unless [TT]-first[tt] and [TT]-last[tt]", "have been set explicitly.[PAR]", "When [TT]-v[tt], [TT]-eig[tt], [TT]-v2[tt] and [TT]-eig2[tt] are given,", "a single number for the overlap between the covariance matrices is", "generated. The formulas are:[BR]", " difference = sqrt(tr((sqrt(M1) - sqrt(M2))^2))[BR]", "normalized overlap = 1 - difference/sqrt(tr(M1) + tr(M2))[BR]", " shape overlap = 1 - sqrt(tr((sqrt(M1/tr(M1)) - sqrt(M2/tr(M2)))^2))[BR]", "where M1 and M2 are the two covariance matrices and tr is the trace", "of a matrix. The numbers are proportional to the overlap of the square", "root of the fluctuations. The normalized overlap is the most useful", "number, it is 1 for identical matrices and 0 when the sampled", "subspaces are orthogonal.[PAR]", "When the [TT]-entropy[tt] flag is given an entropy estimate will be", "computed based on the Quasiharmonic approach and based on", "Schlitter's formula." }; static int first=1,last=-1,skip=1,nextr=2,nskip=6; static real max=0.0,temp=298.15; static gmx_bool bSplit=FALSE,bEntropy=FALSE; t_pargs pa[] = { { "-first", FALSE, etINT, {&first}, "First eigenvector for analysis (-1 is select)" }, { "-last", FALSE, etINT, {&last}, "Last eigenvector for analysis (-1 is till the last)" }, { "-skip", FALSE, etINT, {&skip}, "Only analyse every nr-th frame" }, { "-max", FALSE, etREAL, {&max}, "Maximum for projection of the eigenvector on the average structure, " "max=0 gives the extremes" }, { "-nframes", FALSE, etINT, {&nextr}, "Number of frames for the extremes output" }, { "-split", FALSE, etBOOL, {&bSplit}, "Split eigenvector projections where time is zero" }, { "-entropy", FALSE, etBOOL, {&bEntropy}, "Compute entropy according to the Quasiharmonic formula or Schlitter's method." }, { "-temp", FALSE, etREAL, {&temp}, "Temperature for entropy calculations" }, { "-nevskip", FALSE, etINT, {&nskip}, "Number of eigenvalues to skip when computing the entropy due to the quasi harmonic approximation. When you do a rotational and/or translational fit prior to the covariance analysis, you get 3 or 6 eigenvalues that are very close to zero, and which should not be taken into account when computing the entropy." } }; #define NPA asize(pa) FILE *out; int status,trjout; t_topology top; int ePBC=-1; t_atoms *atoms=NULL; rvec *xtop,*xref1,*xref2,*xrefp=NULL; gmx_bool bDMR1,bDMA1,bDMR2,bDMA2; int nvec1,nvec2,*eignr1=NULL,*eignr2=NULL; rvec *x,*xread,*xav1,*xav2,**eigvec1=NULL,**eigvec2=NULL; matrix topbox; real xid,totmass,*sqrtm,*w_rls,t,lambda; int natoms,step; char *grpname; const char *indexfile; char title[STRLEN]; int i,j,d; int nout,*iout,noutvec,*outvec,nfit; atom_id *index,*ifit; const char *VecFile,*Vec2File,*topfile; const char *EigFile,*Eig2File; const char *CompFile,*RmsfFile,*ProjOnVecFile; const char *TwoDPlotFile,*ThreeDPlotFile; const char *FilterFile,*ExtremeFile; const char *OverlapFile,*InpMatFile; gmx_bool bFit1,bFit2,bM,bIndex,bTPS,bTop,bVec2,bProj; gmx_bool bFirstToLast,bFirstLastSet,bTraj,bCompare,bPDB3D; real *eigval1=NULL,*eigval2=NULL; int neig1,neig2; double **xvgdata; output_env_t oenv; gmx_rmpbc_t gpbc; t_filenm fnm[] = { { efTRN, "-v", "eigenvec", ffREAD }, { efTRN, "-v2", "eigenvec2", ffOPTRD }, { efTRX, "-f", NULL, ffOPTRD }, { efTPS, NULL, NULL, ffOPTRD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, "-eig", "eigenval", ffOPTRD }, { efXVG, "-eig2", "eigenval2", ffOPTRD }, { efXVG, "-comp", "eigcomp", ffOPTWR }, { efXVG, "-rmsf", "eigrmsf", ffOPTWR }, { efXVG, "-proj", "proj", ffOPTWR }, { efXVG, "-2d", "2dproj", ffOPTWR }, { efSTO, "-3d", "3dproj.pdb", ffOPTWR }, { efTRX, "-filt", "filtered", ffOPTWR }, { efTRX, "-extr", "extreme.pdb", ffOPTWR }, { efXVG, "-over", "overlap", ffOPTWR }, { efXPM, "-inpr", "inprod", ffOPTWR } }; #define NFILE asize(fnm) parse_common_args(&argc,argv, PCA_CAN_TIME | PCA_TIME_UNIT | PCA_CAN_VIEW | PCA_BE_NICE , NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL,&oenv); indexfile=ftp2fn_null(efNDX,NFILE,fnm); VecFile = opt2fn("-v",NFILE,fnm); Vec2File = opt2fn_null("-v2",NFILE,fnm); topfile = ftp2fn(efTPS,NFILE,fnm); EigFile = opt2fn_null("-eig",NFILE,fnm); Eig2File = opt2fn_null("-eig2",NFILE,fnm); CompFile = opt2fn_null("-comp",NFILE,fnm); RmsfFile = opt2fn_null("-rmsf",NFILE,fnm); ProjOnVecFile = opt2fn_null("-proj",NFILE,fnm); TwoDPlotFile = opt2fn_null("-2d",NFILE,fnm); ThreeDPlotFile = opt2fn_null("-3d",NFILE,fnm); FilterFile = opt2fn_null("-filt",NFILE,fnm); ExtremeFile = opt2fn_null("-extr",NFILE,fnm); OverlapFile = opt2fn_null("-over",NFILE,fnm); InpMatFile = ftp2fn_null(efXPM,NFILE,fnm); bTop = fn2bTPX(topfile); bProj = ProjOnVecFile || TwoDPlotFile || ThreeDPlotFile || FilterFile || ExtremeFile; bFirstLastSet = opt2parg_bSet("-first",NPA,pa) && opt2parg_bSet("-last",NPA,pa); bFirstToLast = CompFile || RmsfFile || ProjOnVecFile || FilterFile || OverlapFile || ((ExtremeFile || InpMatFile) && bFirstLastSet); bVec2 = Vec2File || OverlapFile || InpMatFile; bM = RmsfFile || bProj; bTraj = ProjOnVecFile || FilterFile || (ExtremeFile && (max==0)) || TwoDPlotFile || ThreeDPlotFile; bIndex = bM || bProj; bTPS = ftp2bSet(efTPS,NFILE,fnm) || bM || bTraj || FilterFile || (bIndex && indexfile); bCompare = Vec2File || Eig2File; bPDB3D = fn2ftp(ThreeDPlotFile)==efPDB; read_eigenvectors(VecFile,&natoms,&bFit1, &xref1,&bDMR1,&xav1,&bDMA1, &nvec1,&eignr1,&eigvec1,&eigval1); neig1 = DIM*natoms; /* Overwrite eigenvalues from separate files if the user provides them */ if (EigFile != NULL) { int neig_tmp = read_xvg(EigFile,&xvgdata,&i); if (neig_tmp != neig1) fprintf(stderr,"Warning: number of eigenvalues in xvg file (%d) does not mtch trr file (%d)\n",neig1,natoms); neig1 = neig_tmp; srenew(eigval1,neig1); for(j=0;j<neig1;j++) { real tmp = eigval1[j]; eigval1[j]=xvgdata[1][j]; if (debug && (eigval1[j] != tmp)) fprintf(debug,"Replacing eigenvalue %d. From trr: %10g, from xvg: %10g\n", j,tmp,eigval1[j]); } for(j=0;j<i;j++) sfree(xvgdata[j]); sfree(xvgdata); fprintf(stderr,"Read %d eigenvalues from %s\n",neig1,EigFile); } if (bEntropy) { if (bDMA1) { gmx_fatal(FARGS,"Can not calculate entropies from mass-weighted eigenvalues, redo the analysis without mass-weighting"); } calc_entropy_qh(stdout,neig1,eigval1,temp,nskip); calc_entropy_schlitter(stdout,neig1,nskip,eigval1,temp); } if (bVec2) { if (!Vec2File) gmx_fatal(FARGS,"Need a second eigenvector file to do this analysis."); read_eigenvectors(Vec2File,&neig2,&bFit2, &xref2,&bDMR2,&xav2,&bDMA2,&nvec2,&eignr2,&eigvec2,&eigval2); neig2 = DIM*neig2; if (neig2 != neig1) gmx_fatal(FARGS,"Dimensions in the eigenvector files don't match"); } if(Eig2File != NULL) { neig2 = read_xvg(Eig2File,&xvgdata,&i); srenew(eigval2,neig2); for(j=0;j<neig2;j++) eigval2[j]=xvgdata[1][j]; for(j=0;j<i;j++) sfree(xvgdata[j]); sfree(xvgdata); fprintf(stderr,"Read %d eigenvalues from %s\n",neig2,Eig2File); } if ((!bFit1 || xref1) && !bDMR1 && !bDMA1) bM=FALSE; if ((xref1==NULL) && (bM || bTraj)) bTPS=TRUE; xtop=NULL; nfit=0; ifit=NULL; w_rls=NULL; if (!bTPS) { bTop=FALSE; } else { bTop=read_tps_conf(ftp2fn(efTPS,NFILE,fnm), title,&top,&ePBC,&xtop,NULL,topbox,bM); atoms=&top.atoms; gpbc = gmx_rmpbc_init(&top.idef,ePBC,atoms->nr,topbox); gmx_rmpbc(gpbc,atoms->nr,topbox,xtop); /* Fitting is only required for the projection */ if (bProj && bFit1) { if (xref1 == NULL) { printf("\nNote: the structure in %s should be the same\n" " as the one used for the fit in g_covar\n",topfile); } printf("\nSelect the index group that was used for the least squares fit in g_covar\n"); get_index(atoms,indexfile,1,&nfit,&ifit,&grpname); snew(w_rls,atoms->nr); for(i=0; (i<nfit); i++) { if (bDMR1) { w_rls[ifit[i]] = atoms->atom[ifit[i]].m; } else { w_rls[ifit[i]] = 1.0; } } snew(xrefp,atoms->nr); if (xref1 != NULL) { for(i=0; (i<nfit); i++) { copy_rvec(xref1[i],xrefp[ifit[i]]); } } else { /* The top coordinates are the fitting reference */ for(i=0; (i<nfit); i++) { copy_rvec(xtop[ifit[i]],xrefp[ifit[i]]); } reset_x(nfit,ifit,atoms->nr,NULL,xrefp,w_rls); } } gmx_rmpbc_done(gpbc); } if (bIndex) { printf("\nSelect an index group of %d elements that corresponds to the eigenvectors\n",natoms); get_index(atoms,indexfile,1,&i,&index,&grpname); if (i!=natoms) gmx_fatal(FARGS,"you selected a group with %d elements instead of %d",i,natoms); printf("\n"); } snew(sqrtm,natoms); if (bM && bDMA1) { proj_unit="u\\S1/2\\Nnm"; for(i=0; (i<natoms); i++) sqrtm[i]=sqrt(atoms->atom[index[i]].m); } else { proj_unit="nm"; for(i=0; (i<natoms); i++) sqrtm[i]=1.0; } if (bVec2) { t=0; totmass=0; for(i=0; (i<natoms); i++) for(d=0;(d<DIM);d++) { t+=sqr((xav1[i][d]-xav2[i][d])*sqrtm[i]); totmass+=sqr(sqrtm[i]); } fprintf(stdout,"RMSD (without fit) between the two average structures:" " %.3f (nm)\n\n",sqrt(t/totmass)); } if (last==-1) last=natoms*DIM; if (first>-1) { if (bFirstToLast) { /* make an index from first to last */ nout=last-first+1; snew(iout,nout); for(i=0; i<nout; i++) iout[i]=first-1+i; } else if (ThreeDPlotFile) { /* make an index of first+(0,1,2) and last */ nout = bPDB3D ? 4 : 3; nout = min(last-first+1, nout); snew(iout,nout); iout[0]=first-1; iout[1]=first; if (nout>3) iout[2]=first+1; iout[nout-1]=last-1; } else { /* make an index of first and last */ nout=2; snew(iout,nout); iout[0]=first-1; iout[1]=last-1; } } else { printf("Select eigenvectors for output, end your selection with 0\n"); nout=-1; iout=NULL; do { nout++; srenew(iout,nout+1); if(1 != scanf("%d",&iout[nout])) { gmx_fatal(FARGS,"Error reading user input"); } iout[nout]--; } while (iout[nout]>=0); printf("\n"); } /* make an index of the eigenvectors which are present */ snew(outvec,nout); noutvec=0; for(i=0; i<nout; i++) { j=0; while ((j<nvec1) && (eignr1[j]!=iout[i])) j++; if ((j<nvec1) && (eignr1[j]==iout[i])) { outvec[noutvec]=j; noutvec++; } } fprintf(stderr,"%d eigenvectors selected for output",noutvec); if (noutvec <= 100) { fprintf(stderr,":"); for(j=0; j<noutvec; j++) fprintf(stderr," %d",eignr1[outvec[j]]+1); } fprintf(stderr,"\n"); if (CompFile) components(CompFile,natoms,eignr1,eigvec1,noutvec,outvec,oenv); if (RmsfFile) rmsf(RmsfFile,natoms,sqrtm,eignr1,eigvec1,noutvec,outvec,eigval1, neig1,oenv); if (bProj) project(bTraj ? opt2fn("-f",NFILE,fnm) : NULL, bTop ? &top : NULL,ePBC,topbox, ProjOnVecFile,TwoDPlotFile,ThreeDPlotFile,FilterFile,skip, ExtremeFile,bFirstLastSet,max,nextr,atoms,natoms,index, bFit1,xrefp,nfit,ifit,w_rls, sqrtm,xav1,eignr1,eigvec1,noutvec,outvec,bSplit, oenv); if (OverlapFile) overlap(OverlapFile,natoms, eigvec1,nvec2,eignr2,eigvec2,noutvec,outvec,oenv); if (InpMatFile) inprod_matrix(InpMatFile,natoms, nvec1,eignr1,eigvec1,nvec2,eignr2,eigvec2, bFirstLastSet,noutvec,outvec); if (bCompare) compare(natoms,nvec1,eigvec1,nvec2,eigvec2,eigval1,neig1,eigval2,neig2); if (!CompFile && !bProj && !OverlapFile && !InpMatFile && !bCompare && !bEntropy) { fprintf(stderr,"\nIf you want some output," " set one (or two or ...) of the output file options\n"); } view_all(oenv,NFILE, fnm); thanx(stdout); 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_trjorder(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] orders molecules according to the smallest distance", "to atoms in a reference group", "or on z-coordinate (with option [TT]-z[tt]).", "With distance ordering, it will ask for a group of reference", "atoms and a group of molecules. For each frame of the trajectory", "the selected molecules will be reordered according to the shortest", "distance between atom number [TT]-da[tt] in the molecule and all the", "atoms in the reference group. The center of mass of the molecules can", "be used instead of a reference atom by setting [TT]-da[tt] to 0.", "All atoms in the trajectory are written", "to the output trajectory.[PAR]", "[THISMODULE] can be useful for e.g. analyzing the n waters closest to a", "protein.", "In that case the reference group would be the protein and the group", "of molecules would consist of all the water atoms. When an index group", "of the first n waters is made, the ordered trajectory can be used", "with any GROMACS program to analyze the n closest waters.", "[PAR]", "If the output file is a [REF].pdb[ref] file, the distance to the reference target", "will be stored in the B-factor field in order to color with e.g. Rasmol.", "[PAR]", "With option [TT]-nshell[tt] the number of molecules within a shell", "of radius [TT]-r[tt] around the reference group are printed." }; static int na = 3, ref_a = 1; static real rcut = 0; static gmx_bool bCOM = FALSE, bZ = FALSE; t_pargs pa[] = { { "-na", FALSE, etINT, {&na}, "Number of atoms in a molecule" }, { "-da", FALSE, etINT, {&ref_a}, "Atom used for the distance calculation, 0 is COM" }, { "-com", FALSE, etBOOL, {&bCOM}, "Use the distance to the center of mass of the reference group" }, { "-r", FALSE, etREAL, {&rcut}, "Cutoff used for the distance calculation when computing the number of molecules in a shell around e.g. a protein" }, { "-z", FALSE, etBOOL, {&bZ}, "Order molecules on z-coordinate" } }; FILE *fp; t_trxstatus *out; t_trxstatus *status; gmx_bool bNShell, bPDBout; t_topology top; int ePBC; rvec *x, *xsol, xcom, dx; matrix box; t_pbc pbc; gmx_rmpbc_t gpbc; real t, totmass, mass, rcut2 = 0, n2; int natoms, nwat, ncut; char **grpname; int i, j, d, *isize, isize_ref = 0, isize_sol; atom_id sa, sr, *swi, **index, *ind_ref = NULL, *ind_sol; output_env_t oenv; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efTRO, "-o", "ordered", ffOPTWR }, { efXVG, "-nshell", "nshell", ffOPTWR } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, NULL, box, TRUE); sfree(x); /* get index groups */ printf("Select %sa group of molecules to be ordered:\n", bZ ? "" : "a group of reference atoms and "); snew(grpname, 2); snew(index, 2); snew(isize, 2); get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), bZ ? 1 : 2, isize, index, grpname); if (!bZ) { isize_ref = isize[0]; isize_sol = isize[1]; ind_ref = index[0]; ind_sol = index[1]; } else { isize_sol = isize[0]; ind_sol = index[0]; } natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); if (natoms > top.atoms.nr) { gmx_fatal(FARGS, "Number of atoms in the run input file is larger than in the trjactory"); } for (i = 0; (i < 2); i++) { for (j = 0; (j < isize[i]); j++) { if (index[i][j] > natoms) { gmx_fatal(FARGS, "An atom number in group %s is larger than the number of atoms in the trajectory"); } } } if ((isize_sol % na) != 0) { gmx_fatal(FARGS, "Number of atoms in the molecule group (%d) is not a multiple of na (%d)", isize[1], na); } nwat = isize_sol/na; if (ref_a > na) { gmx_fatal(FARGS, "The reference atom can not be larger than the number of atoms in a molecule"); } ref_a--; snew(xsol, nwat); snew(order, nwat); snew(swi, natoms); for (i = 0; (i < natoms); i++) { swi[i] = i; } out = NULL; fp = NULL; bNShell = ((opt2bSet("-nshell", NFILE, fnm)) || (opt2parg_bSet("-r", asize(pa), pa))); bPDBout = FALSE; if (bNShell) { rcut2 = rcut*rcut; fp = xvgropen(opt2fn("-nshell", NFILE, fnm), "Number of molecules", "Time (ps)", "N", oenv); printf("Will compute the number of molecules within a radius of %g\n", rcut); } if (!bNShell || opt2bSet("-o", NFILE, fnm)) { bPDBout = (fn2ftp(opt2fn("-o", NFILE, fnm)) == efPDB); if (bPDBout && !top.atoms.pdbinfo) { fprintf(stderr, "Creating pdbfino records\n"); snew(top.atoms.pdbinfo, top.atoms.nr); } out = open_trx(opt2fn("-o", NFILE, fnm), "w"); } gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms); do { gmx_rmpbc(gpbc, natoms, box, x); set_pbc(&pbc, ePBC, box); if (ref_a == -1) { /* Calculate the COM of all solvent molecules */ for (i = 0; i < nwat; i++) { totmass = 0; clear_rvec(xsol[i]); for (j = 0; j < na; j++) { sa = ind_sol[i*na+j]; mass = top.atoms.atom[sa].m; totmass += mass; for (d = 0; d < DIM; d++) { xsol[i][d] += mass*x[sa][d]; } } svmul(1.0/totmass, xsol[i], xsol[i]); } } else { /* Copy the reference atom of all solvent molecules */ for (i = 0; i < nwat; i++) { copy_rvec(x[ind_sol[i*na+ref_a]], xsol[i]); } } if (bZ) { for (i = 0; (i < nwat); i++) { sa = ind_sol[na*i]; order[i].i = sa; order[i].d2 = xsol[i][ZZ]; } } else if (bCOM) { totmass = 0; clear_rvec(xcom); for (i = 0; i < isize_ref; i++) { mass = top.atoms.atom[ind_ref[i]].m; totmass += mass; for (j = 0; j < DIM; j++) { xcom[j] += mass*x[ind_ref[i]][j]; } } svmul(1/totmass, xcom, xcom); for (i = 0; (i < nwat); i++) { sa = ind_sol[na*i]; pbc_dx(&pbc, xcom, xsol[i], dx); order[i].i = sa; order[i].d2 = norm2(dx); } } else { /* Set distance to first atom */ for (i = 0; (i < nwat); i++) { sa = ind_sol[na*i]; pbc_dx(&pbc, x[ind_ref[0]], xsol[i], dx); order[i].i = sa; order[i].d2 = norm2(dx); } for (j = 1; (j < isize_ref); j++) { sr = ind_ref[j]; for (i = 0; (i < nwat); i++) { pbc_dx(&pbc, x[sr], xsol[i], dx); n2 = norm2(dx); if (n2 < order[i].d2) { order[i].d2 = n2; } } } } if (bNShell) { ncut = 0; for (i = 0; (i < nwat); i++) { if (order[i].d2 <= rcut2) { ncut++; } } fprintf(fp, "%10.3f %8d\n", t, ncut); } if (out) { qsort(order, nwat, sizeof(*order), ocomp); for (i = 0; (i < nwat); i++) { for (j = 0; (j < na); j++) { swi[ind_sol[na*i]+j] = order[i].i+j; } } /* Store the distance as the B-factor */ if (bPDBout) { for (i = 0; (i < nwat); i++) { for (j = 0; (j < na); j++) { top.atoms.pdbinfo[order[i].i+j].bfac = std::sqrt(order[i].d2); } } } write_trx(out, natoms, swi, &top.atoms, 0, t, box, x, NULL, NULL); } } while (read_next_x(oenv, status, &t, x, box)); close_trj(status); if (out) { close_trx(out); } if (fp) { xvgrclose(fp); } gmx_rmpbc_done(gpbc); return 0; }
void calc_potential(const char *fn, int **index, int gnx[], double ***slPotential, double ***slCharge, double ***slField, int *nslices, const t_topology *top, int ePBC, int axis, int nr_grps, double *slWidth, double fudge_z, gmx_bool bSpherical, gmx_bool bCorrect, const gmx_output_env_t *oenv) { rvec *x0; /* coordinates without pbc */ matrix box; /* box (3x3) */ int natoms; /* nr. atoms in trj */ t_trxstatus *status; int i, n, /* loop indices */ teller = 0, ax1 = 0, ax2 = 0, nr_frames = 0, /* number of frames */ slice; /* current slice */ double slVolume; /* volume of slice for spherical averaging */ double qsum, nn; real t; double z; rvec xcm; gmx_rmpbc_t gpbc = NULL; switch (axis) { case 0: ax1 = 1; ax2 = 2; break; case 1: ax1 = 0; ax2 = 2; break; case 2: ax1 = 0; ax2 = 1; break; default: gmx_fatal(FARGS, "Invalid axes. Terminating\n"); } if ((natoms = read_first_x(oenv, &status, fn, &t, &x0, box)) == 0) { gmx_fatal(FARGS, "Could not read coordinates from statusfile\n"); } if (!*nslices) { *nslices = static_cast<int>(box[axis][axis] * 10.0); /* default value */ } fprintf(stderr, "\nDividing the box in %d slices\n", *nslices); snew(*slField, nr_grps); snew(*slCharge, nr_grps); snew(*slPotential, nr_grps); for (i = 0; i < nr_grps; i++) { snew((*slField)[i], *nslices); snew((*slCharge)[i], *nslices); snew((*slPotential)[i], *nslices); } gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms); /*********** Start processing trajectory ***********/ do { *slWidth = box[axis][axis]/(*nslices); teller++; gmx_rmpbc(gpbc, natoms, box, x0); /* calculate position of center of mass based on group 1 */ calc_xcm(x0, gnx[0], index[0], top->atoms.atom, xcm, FALSE); svmul(-1, xcm, xcm); for (n = 0; n < nr_grps; n++) { /* Check whether we actually have all positions of the requested index * group in the trajectory file */ if (gnx[n] > natoms) { gmx_fatal(FARGS, "You selected a group with %d atoms, but only %d atoms\n" "were found in the trajectory.\n", gnx[n], natoms); } for (i = 0; i < gnx[n]; i++) /* loop over all atoms in index file */ { if (bSpherical) { rvec_add(x0[index[n][i]], xcm, x0[index[n][i]]); /* only distance from origin counts, not sign */ slice = static_cast<int>(norm(x0[index[n][i]])/(*slWidth)); /* this is a nice check for spherical groups but not for all water in a cubic box since a lot will fall outside the sphere if (slice > (*nslices)) { fprintf(stderr,"Warning: slice = %d\n",slice); } */ (*slCharge)[n][slice] += top->atoms.atom[index[n][i]].q; } else { z = x0[index[n][i]][axis]; z = z + fudge_z; if (z < 0) { z += box[axis][axis]; } if (z > box[axis][axis]) { z -= box[axis][axis]; } /* determine which slice atom is in */ slice = static_cast<int>((z / (*slWidth))); (*slCharge)[n][slice] += top->atoms.atom[index[n][i]].q; } } } nr_frames++; } while (read_next_x(oenv, status, &t, x0, box)); gmx_rmpbc_done(gpbc); /*********** done with status file **********/ close_trj(status); /* slCharge now contains the total charge per slice, summed over all frames. Now divide by nr_frames and integrate twice */ if (bSpherical) { fprintf(stderr, "\n\nRead %d frames from trajectory. Calculating potential" "in spherical coordinates\n", nr_frames); } else { fprintf(stderr, "\n\nRead %d frames from trajectory. Calculating potential\n", nr_frames); } for (n = 0; n < nr_grps; n++) { for (i = 0; i < *nslices; i++) { if (bSpherical) { /* charge per volume is now the summed charge, divided by the nr of frames and by the volume of the slice it's in, 4pi r^2 dr */ slVolume = 4*M_PI * gmx::square(i) * gmx::square(*slWidth) * *slWidth; if (slVolume == 0) { (*slCharge)[n][i] = 0; } else { (*slCharge)[n][i] = (*slCharge)[n][i] / (nr_frames * slVolume); } } else { /* get charge per volume */ (*slCharge)[n][i] = (*slCharge)[n][i] * (*nslices) / (nr_frames * box[axis][axis] * box[ax1][ax1] * box[ax2][ax2]); } } /* Now we have charge densities */ } if (bCorrect && !bSpherical) { for (n = 0; n < nr_grps; n++) { nn = 0; qsum = 0; for (i = 0; i < *nslices; i++) { if (std::abs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN) { nn++; qsum += (*slCharge)[n][i]; } } qsum /= nn; for (i = 0; i < *nslices; i++) { if (std::abs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN) { (*slCharge)[n][i] -= qsum; } } } } for (n = 0; n < nr_grps; n++) { /* integrate twice to get field and potential */ p_integrate((*slField)[n], (*slCharge)[n], *nslices, *slWidth); } if (bCorrect && !bSpherical) { for (n = 0; n < nr_grps; n++) { nn = 0; qsum = 0; for (i = 0; i < *nslices; i++) { if (std::abs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN) { nn++; qsum += (*slField)[n][i]; } } qsum /= nn; for (i = 0; i < *nslices; i++) { if (std::abs((*slCharge)[n][i]) >= GMX_DOUBLE_MIN) { (*slField)[n][i] -= qsum; } } } } for (n = 0; n < nr_grps; n++) { p_integrate((*slPotential)[n], (*slField)[n], *nslices, *slWidth); } /* Now correct for eps0 and in spherical case for r*/ for (n = 0; n < nr_grps; n++) { for (i = 0; i < *nslices; i++) { if (bSpherical) { (*slPotential)[n][i] = ELC * (*slPotential)[n][i] * -1.0E9 / (EPS0 * i * (*slWidth)); (*slField)[n][i] = ELC * (*slField)[n][i] * 1E18 / (EPS0 * i * (*slWidth)); } else { (*slPotential)[n][i] = ELC * (*slPotential)[n][i] * -1.0E9 / EPS0; (*slField)[n][i] = ELC * (*slField)[n][i] * 1E18 / EPS0; } } } sfree(x0); /* free memory used by coordinate array */ }
static void dielectric(FILE *fmj, FILE *fmd, FILE *outf, FILE *fcur, FILE *mcor, FILE *fmjdsp, gmx_bool bNoJump, gmx_bool bACF, gmx_bool bINT, int ePBC, t_topology top, t_trxframe fr, real temp, real bfit, real efit, real bvit, real evit, t_trxstatus *status, int isize, int nmols, int nshift, int *index0, int indexm[], real mass2[], real qmol[], real eps_rf, const gmx_output_env_t *oenv) { int i, j; int valloc, nalloc, nfr, nvfr; int vshfr; real *xshfr = NULL; int *vfr = NULL; real refr = 0.0; real *cacf = NULL; real *time = NULL; real *djc = NULL; real corint = 0.0; real prefactorav = 0.0; real prefactor = 0.0; real volume; real volume_av = 0.0; real dk_s, dk_d, dk_f; real mj = 0.0; real mj2 = 0.0; real mjd = 0.0; real mjdav = 0.0; real md2 = 0.0; real mdav2 = 0.0; real sgk; rvec mja_tmp; rvec mjd_tmp; rvec mdvec; rvec *mu = NULL; rvec *xp = NULL; rvec *v0 = NULL; rvec *mjdsp = NULL; real *dsp2 = NULL; real t0; real rtmp; rvec tmp; rvec *mtrans = NULL; /* * Variables for the least-squares fit for Einstein-Helfand and Green-Kubo */ int bi, ei, ie, ii; real rest = 0.0; real sigma = 0.0; real malt = 0.0; real err = 0.0; real *xfit; real *yfit; gmx_rmpbc_t gpbc = NULL; /* * indices for EH */ ei = 0; bi = 0; /* * indices for GK */ ii = 0; ie = 0; t0 = 0; sgk = 0.0; /* This is the main loop over frames */ nfr = 0; nvfr = 0; vshfr = 0; nalloc = 0; valloc = 0; clear_rvec(mja_tmp); clear_rvec(mjd_tmp); clear_rvec(mdvec); clear_rvec(tmp); gpbc = gmx_rmpbc_init(&top.idef, ePBC, fr.natoms); do { refr = (nfr+1); if (nfr >= nalloc) { nalloc += 100; srenew(time, nalloc); srenew(mu, nalloc); srenew(mjdsp, nalloc); srenew(dsp2, nalloc); srenew(mtrans, nalloc); srenew(xshfr, nalloc); for (i = nfr; i < nalloc; i++) { clear_rvec(mjdsp[i]); clear_rvec(mu[i]); clear_rvec(mtrans[i]); dsp2[i] = 0.0; xshfr[i] = 0.0; } } GMX_RELEASE_ASSERT(time != NULL, "Memory not allocated correctly - time array is NULL"); if (nfr == 0) { t0 = fr.time; } time[nfr] = fr.time-t0; if (time[nfr] <= bfit) { bi = nfr; } if (time[nfr] <= efit) { ei = nfr; } if (bNoJump) { if (xp) { remove_jump(fr.box, fr.natoms, xp, fr.x); } else { snew(xp, fr.natoms); } for (i = 0; i < fr.natoms; i++) { copy_rvec(fr.x[i], xp[i]); } } gmx_rmpbc_trxfr(gpbc, &fr); calc_mj(top, ePBC, fr.box, bNoJump, nmols, indexm, fr.x, mtrans[nfr], mass2, qmol); for (i = 0; i < isize; i++) { j = index0[i]; svmul(top.atoms.atom[j].q, fr.x[j], fr.x[j]); rvec_inc(mu[nfr], fr.x[j]); } /*if(mod(nfr,nshift)==0){*/ if (nfr%nshift == 0) { for (j = nfr; j >= 0; j--) { rvec_sub(mtrans[nfr], mtrans[j], tmp); dsp2[nfr-j] += norm2(tmp); xshfr[nfr-j] += 1.0; } } if (fr.bV) { if (nvfr >= valloc) { valloc += 100; srenew(vfr, valloc); if (bINT) { srenew(djc, valloc); } srenew(v0, valloc); if (bACF) { srenew(cacf, valloc); } } if (time[nfr] <= bvit) { ii = nvfr; } if (time[nfr] <= evit) { ie = nvfr; } vfr[nvfr] = nfr; clear_rvec(v0[nvfr]); if (bACF) { cacf[nvfr] = 0.0; } if (bINT) { djc[nvfr] = 0.0; } for (i = 0; i < isize; i++) { j = index0[i]; svmul(mass2[j], fr.v[j], fr.v[j]); svmul(qmol[j], fr.v[j], fr.v[j]); rvec_inc(v0[nvfr], fr.v[j]); } fprintf(fcur, "%.3f\t%.6f\t%.6f\t%.6f\n", time[nfr], v0[nfr][XX], v0[nfr][YY], v0[nfr][ZZ]); if (bACF || bINT) { /*if(mod(nvfr,nshift)==0){*/ if (nvfr%nshift == 0) { for (j = nvfr; j >= 0; j--) { if (bACF) { cacf[nvfr-j] += iprod(v0[nvfr], v0[j]); } if (bINT) { djc[nvfr-j] += iprod(mu[vfr[j]], v0[nvfr]); } } vshfr++; } } nvfr++; } volume = det(fr.box); volume_av += volume; rvec_inc(mja_tmp, mtrans[nfr]); mjd += iprod(mu[nfr], mtrans[nfr]); rvec_inc(mdvec, mu[nfr]); mj2 += iprod(mtrans[nfr], mtrans[nfr]); md2 += iprod(mu[nfr], mu[nfr]); fprintf(fmj, "%.3f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\n", time[nfr], mtrans[nfr][XX], mtrans[nfr][YY], mtrans[nfr][ZZ], mj2/refr, norm(mja_tmp)/refr); fprintf(fmd, "%.3f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\t%8.5f\n", \ time[nfr], mu[nfr][XX], mu[nfr][YY], mu[nfr][ZZ], md2/refr, norm(mdvec)/refr); nfr++; } while (read_next_frame(oenv, status, &fr)); gmx_rmpbc_done(gpbc); volume_av /= refr; prefactor = 1.0; prefactor /= 3.0*EPSILON0*volume_av*BOLTZ*temp; prefactorav = E_CHARGE*E_CHARGE; prefactorav /= volume_av*BOLTZMANN*temp*NANO*6.0; fprintf(stderr, "Prefactor fit E-H: 1 / 6.0*V*k_B*T: %g\n", prefactorav); calc_mjdsp(fmjdsp, prefactorav, dsp2, time, nfr, xshfr); /* * Now we can average and calculate the correlation functions */ mj2 /= refr; mjd /= refr; md2 /= refr; svmul(1.0/refr, mdvec, mdvec); svmul(1.0/refr, mja_tmp, mja_tmp); mdav2 = norm2(mdvec); mj = norm2(mja_tmp); mjdav = iprod(mdvec, mja_tmp); printf("\n\nAverage translational dipole moment M_J [enm] after %d frames (|M|^2): %f %f %f (%f)\n", nfr, mja_tmp[XX], mja_tmp[YY], mja_tmp[ZZ], mj2); printf("\n\nAverage molecular dipole moment M_D [enm] after %d frames (|M|^2): %f %f %f (%f)\n", nfr, mdvec[XX], mdvec[YY], mdvec[ZZ], md2); if (v0 != NULL) { if (bINT) { printf("\nCalculating M_D - current correlation integral ... \n"); corint = calc_cacf(mcor, prefactorav/EPSI0, djc, time, nvfr, vfr, ie, nshift); } if (bACF) { printf("\nCalculating current autocorrelation ... \n"); sgk = calc_cacf(outf, prefactorav/PICO, cacf, time, nvfr, vfr, ie, nshift); if (ie > ii) { snew(xfit, ie-ii+1); snew(yfit, ie-ii+1); for (i = ii; i <= ie; i++) { xfit[i-ii] = std::log(time[vfr[i]]); rtmp = std::abs(cacf[i]); yfit[i-ii] = std::log(rtmp); } lsq_y_ax_b(ie-ii, xfit, yfit, &sigma, &malt, &err, &rest); malt = std::exp(malt); sigma += 1.0; malt *= prefactorav*2.0e12/sigma; sfree(xfit); sfree(yfit); } } } /* Calculation of the dielectric constant */ fprintf(stderr, "\n********************************************\n"); dk_s = calceps(prefactor, md2, mj2, mjd, eps_rf, FALSE); fprintf(stderr, "\nAbsolute values:\n epsilon=%f\n", dk_s); fprintf(stderr, " <M_D^2> , <M_J^2>, <(M_J*M_D)^2>: (%f, %f, %f)\n\n", md2, mj2, mjd); fprintf(stderr, "********************************************\n"); dk_f = calceps(prefactor, md2-mdav2, mj2-mj, mjd-mjdav, eps_rf, FALSE); fprintf(stderr, "\n\nFluctuations:\n epsilon=%f\n\n", dk_f); fprintf(stderr, "\n deltaM_D , deltaM_J, deltaM_JD: (%f, %f, %f)\n", md2-mdav2, mj2-mj, mjd-mjdav); fprintf(stderr, "\n********************************************\n"); if (bINT) { dk_d = calceps(prefactor, md2-mdav2, mj2-mj, corint, eps_rf, TRUE); fprintf(stderr, "\nStatic dielectric constant using integral and fluctuations: %f\n", dk_d); fprintf(stderr, "\n < M_JM_D > via integral: %.3f\n", -1.0*corint); } fprintf(stderr, "\n***************************************************"); fprintf(stderr, "\n\nAverage volume V=%f nm^3 at T=%f K\n", volume_av, temp); fprintf(stderr, "and corresponding refactor 1.0 / 3.0*V*k_B*T*EPSILON_0: %f \n", prefactor); if (bACF && (ii < nvfr)) { fprintf(stderr, "Integral and integrated fit to the current acf yields at t=%f:\n", time[vfr[ii]]); fprintf(stderr, "sigma=%8.3f (pure integral: %.3f)\n", sgk-malt*std::pow(time[vfr[ii]], sigma), sgk); } if (ei > bi) { fprintf(stderr, "\nStart fit at %f ps (%f).\n", time[bi], bfit); fprintf(stderr, "End fit at %f ps (%f).\n\n", time[ei], efit); snew(xfit, ei-bi+1); snew(yfit, ei-bi+1); for (i = bi; i <= ei; i++) { xfit[i-bi] = time[i]; yfit[i-bi] = dsp2[i]; } lsq_y_ax_b(ei-bi, xfit, yfit, &sigma, &malt, &err, &rest); sigma *= 1e12; dk_d = calceps(prefactor, md2, 0.5*malt/prefactorav, corint, eps_rf, TRUE); fprintf(stderr, "Einstein-Helfand fit to the MSD of the translational dipole moment yields:\n\n"); fprintf(stderr, "sigma=%.4f\n", sigma); fprintf(stderr, "translational fraction of M^2: %.4f\n", 0.5*malt/prefactorav); fprintf(stderr, "Dielectric constant using EH: %.4f\n", dk_d); sfree(xfit); sfree(yfit); } else { fprintf(stderr, "Too few points for a fit.\n"); } if (v0 != NULL) { sfree(v0); } if (bACF) { sfree(cacf); } if (bINT) { sfree(djc); } sfree(time); sfree(mjdsp); sfree(mu); }
int gmx_traj(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] plots coordinates, velocities, forces and/or the box.", "With [TT]-com[tt] the coordinates, velocities and forces are", "calculated for the center of mass of each group.", "When [TT]-mol[tt] is set, the numbers in the index file are", "interpreted as molecule numbers and the same procedure as with", "[TT]-com[tt] is used for each molecule.[PAR]", "Option [TT]-ot[tt] plots the temperature of each group,", "provided velocities are present in the trajectory file.", "No corrections are made for constrained degrees of freedom!", "This implies [TT]-com[tt].[PAR]", "Options [TT]-ekt[tt] and [TT]-ekr[tt] plot the translational and", "rotational kinetic energy of each group,", "provided velocities are present in the trajectory file.", "This implies [TT]-com[tt].[PAR]", "Options [TT]-cv[tt] and [TT]-cf[tt] write the average velocities", "and average forces as temperature factors to a [REF].pdb[ref] file with", "the average coordinates or the coordinates at [TT]-ctime[tt].", "The temperature factors are scaled such that the maximum is 10.", "The scaling can be changed with the option [TT]-scale[tt].", "To get the velocities or forces of one", "frame set both [TT]-b[tt] and [TT]-e[tt] to the time of", "desired frame. When averaging over frames you might need to use", "the [TT]-nojump[tt] option to obtain the correct average coordinates.", "If you select either of these option the average force and velocity", "for each atom are written to an [REF].xvg[ref] file as well", "(specified with [TT]-av[tt] or [TT]-af[tt]).[PAR]", "Option [TT]-vd[tt] computes a velocity distribution, i.e. the", "norm of the vector is plotted. In addition in the same graph", "the kinetic energy distribution is given." }; static gmx_bool bMol = FALSE, bCom = FALSE, bPBC = TRUE, bNoJump = FALSE; static gmx_bool bX = TRUE, bY = TRUE, bZ = TRUE, bNorm = FALSE, bFP = FALSE; static int ngroups = 1; static real ctime = -1, scale = 0, binwidth = 1; t_pargs pa[] = { { "-com", FALSE, etBOOL, {&bCom}, "Plot data for the com of each group" }, { "-pbc", FALSE, etBOOL, {&bPBC}, "Make molecules whole for COM" }, { "-mol", FALSE, etBOOL, {&bMol}, "Index contains molecule numbers iso atom numbers" }, { "-nojump", FALSE, etBOOL, {&bNoJump}, "Remove jumps of atoms across the box" }, { "-x", FALSE, etBOOL, {&bX}, "Plot X-component" }, { "-y", FALSE, etBOOL, {&bY}, "Plot Y-component" }, { "-z", FALSE, etBOOL, {&bZ}, "Plot Z-component" }, { "-ng", FALSE, etINT, {&ngroups}, "Number of groups to consider" }, { "-len", FALSE, etBOOL, {&bNorm}, "Plot vector length" }, { "-fp", FALSE, etBOOL, {&bFP}, "Full precision output" }, { "-bin", FALSE, etREAL, {&binwidth}, "Binwidth for velocity histogram (nm/ps)" }, { "-ctime", FALSE, etREAL, {&ctime}, "Use frame at this time for x in [TT]-cv[tt] and [TT]-cf[tt] instead of the average x" }, { "-scale", FALSE, etREAL, {&scale}, "Scale factor for [REF].pdb[ref] output, 0 is autoscale" } }; FILE *outx = NULL, *outv = NULL, *outf = NULL, *outb = NULL, *outt = NULL; FILE *outekt = NULL, *outekr = NULL; t_topology top; int ePBC; real *mass, time; const char *indexfn; t_trxframe fr, frout; int flags, nvhisto = 0, *vhisto = NULL; rvec *xtop, *xp = NULL; rvec *sumx = NULL, *sumv = NULL, *sumf = NULL; matrix topbox; t_trxstatus *status; t_trxstatus *status_out = NULL; gmx_rmpbc_t gpbc = NULL; int i, j; int nr_xfr, nr_vfr, nr_ffr; char **grpname; int *isize0, *isize; int **index0, **index; int *atndx; t_block *mols; gmx_bool bTop, bOX, bOXT, bOV, bOF, bOB, bOT, bEKT, bEKR, bCV, bCF; gmx_bool bDim[4], bDum[4], bVD; char sffmt[STRLEN], sffmt6[STRLEN]; const char *box_leg[6] = { "XX", "YY", "ZZ", "YX", "ZX", "ZY" }; gmx_output_env_t *oenv; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, "-ox", "coord", ffOPTWR }, { efTRX, "-oxt", "coord", ffOPTWR }, { efXVG, "-ov", "veloc", ffOPTWR }, { efXVG, "-of", "force", ffOPTWR }, { efXVG, "-ob", "box", ffOPTWR }, { efXVG, "-ot", "temp", ffOPTWR }, { efXVG, "-ekt", "ektrans", ffOPTWR }, { efXVG, "-ekr", "ekrot", ffOPTWR }, { efXVG, "-vd", "veldist", ffOPTWR }, { efPDB, "-cv", "veloc", ffOPTWR }, { efPDB, "-cf", "force", ffOPTWR }, { efXVG, "-av", "all_veloc", ffOPTWR }, { efXVG, "-af", "all_force", ffOPTWR } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_TIME_UNIT | PCA_CAN_VIEW, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } if (bMol) { fprintf(stderr, "Interpreting indexfile entries as molecules.\n" "Using center of mass.\n"); } bOX = opt2bSet("-ox", NFILE, fnm); bOXT = opt2bSet("-oxt", NFILE, fnm); bOV = opt2bSet("-ov", NFILE, fnm); bOF = opt2bSet("-of", NFILE, fnm); bOB = opt2bSet("-ob", NFILE, fnm); bOT = opt2bSet("-ot", NFILE, fnm); bEKT = opt2bSet("-ekt", NFILE, fnm); bEKR = opt2bSet("-ekr", NFILE, fnm); bCV = opt2bSet("-cv", NFILE, fnm) || opt2bSet("-av", NFILE, fnm); bCF = opt2bSet("-cf", NFILE, fnm) || opt2bSet("-af", NFILE, fnm); bVD = opt2bSet("-vd", NFILE, fnm) || opt2parg_bSet("-bin", asize(pa), pa); if (bMol || bOT || bEKT || bEKR) { bCom = TRUE; } bDim[XX] = bX; bDim[YY] = bY; bDim[ZZ] = bZ; bDim[DIM] = bNorm; if (bFP) { sprintf(sffmt, "\t%s", gmx_real_fullprecision_pfmt); } else { sprintf(sffmt, "\t%%g"); } sprintf(sffmt6, "%s%s%s%s%s%s", sffmt, sffmt, sffmt, sffmt, sffmt, sffmt); bTop = read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, NULL, topbox, bCom && (bOX || bOXT || bOV || bOT || bEKT || bEKR)); sfree(xtop); if ((bMol || bCV || bCF) && !bTop) { gmx_fatal(FARGS, "Need a run input file for option -mol, -cv or -cf"); } if (bMol) { indexfn = ftp2fn(efNDX, NFILE, fnm); } else { indexfn = ftp2fn_null(efNDX, NFILE, fnm); } if (!(bCom && !bMol)) { ngroups = 1; } snew(grpname, ngroups); snew(isize0, ngroups); snew(index0, ngroups); get_index(&(top.atoms), indexfn, ngroups, isize0, index0, grpname); if (bMol) { mols = &(top.mols); atndx = mols->index; ngroups = isize0[0]; snew(isize, ngroups); snew(index, ngroups); for (i = 0; i < ngroups; i++) { if (index0[0][i] < 0 || index0[0][i] >= mols->nr) { gmx_fatal(FARGS, "Molecule index (%d) is out of range (%d-%d)", index0[0][i]+1, 1, mols->nr); } isize[i] = atndx[index0[0][i]+1] - atndx[index0[0][i]]; snew(index[i], isize[i]); for (j = 0; j < isize[i]; j++) { index[i][j] = atndx[index0[0][i]] + j; } } } else { isize = isize0; index = index0; } if (bCom) { snew(mass, top.atoms.nr); for (i = 0; i < top.atoms.nr; i++) { mass[i] = top.atoms.atom[i].m; } } else { mass = NULL; } flags = 0; if (bOX) { flags = flags | TRX_READ_X; outx = xvgropen(opt2fn("-ox", NFILE, fnm), bCom ? "Center of mass" : "Coordinate", output_env_get_xvgr_tlabel(oenv), "Coordinate (nm)", oenv); make_legend(outx, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv); } if (bOXT) { flags = flags | TRX_READ_X; status_out = open_trx(opt2fn("-oxt", NFILE, fnm), "w"); } if (bOV) { flags = flags | TRX_READ_V; outv = xvgropen(opt2fn("-ov", NFILE, fnm), bCom ? "Center of mass velocity" : "Velocity", output_env_get_xvgr_tlabel(oenv), "Velocity (nm/ps)", oenv); make_legend(outv, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv); } if (bOF) { flags = flags | TRX_READ_F; outf = xvgropen(opt2fn("-of", NFILE, fnm), "Force", output_env_get_xvgr_tlabel(oenv), "Force (kJ mol\\S-1\\N nm\\S-1\\N)", oenv); make_legend(outf, ngroups, isize0[0], index0[0], grpname, bCom, bMol, bDim, oenv); } if (bOB) { outb = xvgropen(opt2fn("-ob", NFILE, fnm), "Box vector elements", output_env_get_xvgr_tlabel(oenv), "(nm)", oenv); xvgr_legend(outb, 6, box_leg, oenv); } if (bOT) { bDum[XX] = FALSE; bDum[YY] = FALSE; bDum[ZZ] = FALSE; bDum[DIM] = TRUE; flags = flags | TRX_READ_V; outt = xvgropen(opt2fn("-ot", NFILE, fnm), "Temperature", output_env_get_xvgr_tlabel(oenv), "(K)", oenv); make_legend(outt, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv); } if (bEKT) { bDum[XX] = FALSE; bDum[YY] = FALSE; bDum[ZZ] = FALSE; bDum[DIM] = TRUE; flags = flags | TRX_READ_V; outekt = xvgropen(opt2fn("-ekt", NFILE, fnm), "Center of mass translation", output_env_get_xvgr_tlabel(oenv), "Energy (kJ mol\\S-1\\N)", oenv); make_legend(outekt, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv); } if (bEKR) { bDum[XX] = FALSE; bDum[YY] = FALSE; bDum[ZZ] = FALSE; bDum[DIM] = TRUE; flags = flags | TRX_READ_X | TRX_READ_V; outekr = xvgropen(opt2fn("-ekr", NFILE, fnm), "Center of mass rotation", output_env_get_xvgr_tlabel(oenv), "Energy (kJ mol\\S-1\\N)", oenv); make_legend(outekr, ngroups, isize[0], index[0], grpname, bCom, bMol, bDum, oenv); } if (bVD) { flags = flags | TRX_READ_V; } if (bCV) { flags = flags | TRX_READ_X | TRX_READ_V; } if (bCF) { flags = flags | TRX_READ_X | TRX_READ_F; } if ((flags == 0) && !bOB) { fprintf(stderr, "Please select one or more output file options\n"); exit(0); } read_first_frame(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &fr, flags); if ((bOV || bOF) && fn2ftp(ftp2fn(efTRX, NFILE, fnm)) == efXTC) { gmx_fatal(FARGS, "Cannot extract velocities or forces since your input XTC file does not contain them."); } if (bCV || bCF) { snew(sumx, fr.natoms); } if (bCV) { snew(sumv, fr.natoms); } if (bCF) { snew(sumf, fr.natoms); } nr_xfr = 0; nr_vfr = 0; nr_ffr = 0; if (bCom && bPBC) { gpbc = gmx_rmpbc_init(&top.idef, ePBC, fr.natoms); } do { time = output_env_conv_time(oenv, fr.time); if (fr.bX && bNoJump && fr.bBox) { if (xp) { remove_jump(fr.box, fr.natoms, xp, fr.x); } else { snew(xp, fr.natoms); } for (i = 0; i < fr.natoms; i++) { copy_rvec(fr.x[i], xp[i]); } } if (fr.bX && bCom && bPBC) { gmx_rmpbc_trxfr(gpbc, &fr); } if (bVD && fr.bV) { update_histo(isize[0], index[0], fr.v, &nvhisto, &vhisto, binwidth); } if (bOX && fr.bX) { print_data(outx, time, fr.x, mass, bCom, ngroups, isize, index, bDim, sffmt); } if (bOXT && fr.bX) { frout = fr; if (!frout.bAtoms) { frout.atoms = &top.atoms; frout.bAtoms = TRUE; } write_trx_x(status_out, &frout, mass, bCom, ngroups, isize, index); } if (bOV && fr.bV) { print_data(outv, time, fr.v, mass, bCom, ngroups, isize, index, bDim, sffmt); } if (bOF && fr.bF) { print_data(outf, time, fr.f, NULL, bCom, ngroups, isize, index, bDim, sffmt); } if (bOB && fr.bBox) { fprintf(outb, "\t%g", fr.time); fprintf(outb, sffmt6, fr.box[XX][XX], fr.box[YY][YY], fr.box[ZZ][ZZ], fr.box[YY][XX], fr.box[ZZ][XX], fr.box[ZZ][YY]); fprintf(outb, "\n"); } if (bOT && fr.bV) { fprintf(outt, " %g", time); for (i = 0; i < ngroups; i++) { fprintf(outt, sffmt, temp(fr.v, mass, isize[i], index[i])); } fprintf(outt, "\n"); } if (bEKT && fr.bV) { fprintf(outekt, " %g", time); for (i = 0; i < ngroups; i++) { fprintf(outekt, sffmt, ektrans(fr.v, mass, isize[i], index[i])); } fprintf(outekt, "\n"); } if (bEKR && fr.bX && fr.bV) { fprintf(outekr, " %g", time); for (i = 0; i < ngroups; i++) { fprintf(outekr, sffmt, ekrot(fr.x, fr.v, mass, isize[i], index[i])); } fprintf(outekr, "\n"); } if ((bCV || bCF) && fr.bX && (ctime < 0 || (fr.time >= ctime*0.999999 && fr.time <= ctime*1.000001))) { for (i = 0; i < fr.natoms; i++) { rvec_inc(sumx[i], fr.x[i]); } nr_xfr++; } if (bCV && fr.bV) { for (i = 0; i < fr.natoms; i++) { rvec_inc(sumv[i], fr.v[i]); } nr_vfr++; } if (bCF && fr.bF) { for (i = 0; i < fr.natoms; i++) { rvec_inc(sumf[i], fr.f[i]); } nr_ffr++; } } while (read_next_frame(oenv, status, &fr)); if (gpbc != NULL) { gmx_rmpbc_done(gpbc); } /* clean up a bit */ close_trj(status); if (bOX) { xvgrclose(outx); } if (bOXT) { close_trx(status_out); } if (bOV) { xvgrclose(outv); } if (bOF) { xvgrclose(outf); } if (bOB) { xvgrclose(outb); } if (bOT) { xvgrclose(outt); } if (bEKT) { xvgrclose(outekt); } if (bEKR) { xvgrclose(outekr); } if (bVD) { print_histo(opt2fn("-vd", NFILE, fnm), nvhisto, vhisto, binwidth, oenv); } if (bCV || bCF) { if (nr_xfr > 1) { if (ePBC != epbcNONE && !bNoJump) { fprintf(stderr, "\nWARNING: More than one frame was used for option -cv or -cf\n" "If atoms jump across the box you should use the -nojump or -ctime option\n\n"); } for (i = 0; i < isize[0]; i++) { svmul(1.0/nr_xfr, sumx[index[0][i]], sumx[index[0][i]]); } } else if (nr_xfr == 0) { fprintf(stderr, "\nWARNING: No coordinate frames found for option -cv or -cf\n\n"); } } if (bCV) { write_pdb_bfac(opt2fn("-cv", NFILE, fnm), opt2fn("-av", NFILE, fnm), "average velocity", &(top.atoms), ePBC, topbox, isize[0], index[0], nr_xfr, sumx, nr_vfr, sumv, bDim, scale, oenv); } if (bCF) { write_pdb_bfac(opt2fn("-cf", NFILE, fnm), opt2fn("-af", NFILE, fnm), "average force", &(top.atoms), ePBC, topbox, isize[0], index[0], nr_xfr, sumx, nr_ffr, sumf, bDim, scale, oenv); } /* view it */ view_all(oenv, NFILE, fnm); return 0; }
void calc_h2order(const char *fn, atom_id index[], int ngx, rvec **slDipole, real **slOrder, real *slWidth, int *nslices, t_topology *top, int ePBC, int axis, gmx_bool bMicel, atom_id micel[], int nmic, const output_env_t oenv) { rvec *x0, /* coordinates with pbc */ dipole, /* dipole moment due to one molecules */ normal, com; /* center of mass of micel, with bMicel */ rvec *dip; /* sum of dipoles, unnormalized */ matrix box; /* box (3x3) */ t_trxstatus *status; real t, /* time from trajectory */ *sum, /* sum of all cosines of dipoles, per slice */ *frame; /* order over one frame */ int natoms, /* nr. atoms in trj */ i,j,teller = 0, slice=0, /* current slice number */ *count; /* nr. of atoms in one slice */ gmx_rmpbc_t gpbc=NULL; if ((natoms = read_first_x(oenv,&status,fn,&t,&x0,box)) == 0) gmx_fatal(FARGS,"Could not read coordinates from statusfile\n"); if (! *nslices) *nslices = (int)(box[axis][axis] * 10); /* default value */ switch(axis) { case 0: normal[0] = 1; normal[1] = 0; normal[2] = 0; break; case 1: normal[0] = 0; normal[1] = 1; normal[2] = 0; break; case 2: normal[0] = 0; normal[1] = 0; normal[2] = 1; break; default: gmx_fatal(FARGS,"No valid value for -axis-. Exiting.\n"); /* make compiler happy */ normal[0] = 1; normal[1] = 0; normal[2] = 0; } clear_rvec(dipole); snew(count, *nslices); snew(sum, *nslices); snew(dip, *nslices); snew(frame, *nslices); *slWidth = box[axis][axis]/(*nslices); fprintf(stderr,"Box divided in %d slices. Initial width of slice: %f\n", *nslices, *slWidth); teller = 0; gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box); /*********** Start processing trajectory ***********/ do { *slWidth = box[axis][axis]/(*nslices); teller++; gmx_rmpbc(gpbc,natoms,box,x0); if (bMicel) calc_xcm(x0, nmic, micel, top->atoms.atom, com, FALSE); for (i = 0; i < ngx/3; i++) { /* put all waters in box */ for (j = 0; j < DIM; j++) { if (x0[index[3*i]][j] < 0) { x0[index[3*i]][j] += box[j][j]; x0[index[3*i+1]][j] += box[j][j]; x0[index[3*i+2]][j] += box[j][j]; } if (x0[index[3*i]][j] > box[j][j]) { x0[index[3*i]][j] -= box[j][j]; x0[index[3*i+1]][j] -= box[j][j]; x0[index[3*i+2]][j] -= box[j][j]; } } for (j = 0; j < DIM; j++) dipole[j] = x0[index[3*i]][j] * top->atoms.atom[index[3*i]].q + x0[index[3*i+1]][j] * top->atoms.atom[index[3*i+1]].q + x0[index[3*i+2]][j] * top->atoms.atom[index[3*i+2]].q; /* now we have a dipole vector. Might as well safe it. Then the rest depends on whether we're dealing with a flat or a spherical interface. */ if (bMicel) { /* this is for spherical interfaces */ rvec_sub(com, x0[index[3*i]], normal); /* vector from Oxygen to COM */ slice = norm(normal)/(*slWidth); /* spherical slice */ sum[slice] += iprod(dipole, normal) / (norm(dipole) * norm(normal)); frame[slice] += iprod(dipole, normal) / (norm(dipole) * norm(normal)); count[slice]++; } else { /* this is for flat interfaces */ /* determine which slice atom is in */ slice = (x0[index[3*i]][axis] / (*slWidth)); if (slice < 0 || slice >= *nslices) { fprintf(stderr,"Coordinate: %f ",x0[index[3*i]][axis]); fprintf(stderr,"HELP PANIC! slice = %d, OUT OF RANGE!\n",slice); } else { rvec_add(dipole, dip[slice], dip[slice]); /* Add dipole to total. mag[slice] is total dipole in axis direction */ sum[slice] += iprod(dipole,normal)/norm(dipole); frame[slice] += iprod(dipole,normal)/norm(dipole); /* increase count for that slice */ count[slice]++; } } } } while (read_next_x(oenv,status,&t,natoms,x0,box)); /*********** done with status file **********/ fprintf(stderr,"\nRead trajectory. Printing parameters to file\n"); gmx_rmpbc_done(gpbc); for (i = 0; i < *nslices; i++) /* average over frames */ { fprintf(stderr,"%d waters in slice %d\n",count[i],i); if (count[i] > 0) /* divide by number of molecules in each slice */ { sum[i] = sum[i] / count[i]; dip[i][XX] = dip[i][XX] / count[i]; dip[i][YY] = dip[i][YY] / count[i]; dip[i][ZZ] = dip[i][ZZ] / count[i]; } else fprintf(stderr,"No water in slice %d\n",i); } *slOrder = sum; /* copy a pointer, I hope */ *slDipole = dip; sfree(x0); /* free memory used by coordinate arrays */ }
int gmx_helixorient(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] calculates the coordinates and direction of the average", "axis inside an alpha helix, and the direction/vectors of both the", "C[GRK]alpha[grk] and (optionally) a sidechain atom relative to the axis.[PAR]", "As input, you need to specify an index group with C[GRK]alpha[grk] atoms", "corresponding to an [GRK]alpha[grk]-helix of continuous residues. Sidechain", "directions require a second index group of the same size, containing", "the heavy atom in each residue that should represent the sidechain.[PAR]", "[BB]Note[bb] that this program does not do any fitting of structures.[PAR]", "We need four C[GRK]alpha[grk] coordinates to define the local direction of the helix", "axis.[PAR]", "The tilt/rotation is calculated from Euler rotations, where we define", "the helix axis as the local [IT]x[it]-axis, the residues/C[GRK]alpha[grk] vector as [IT]y[it], and the", "[IT]z[it]-axis from their cross product. We use the Euler Y-Z-X rotation, meaning", "we first tilt the helix axis (1) around and (2) orthogonal to the residues", "vector, and finally apply the (3) rotation around it. For debugging or other", "purposes, we also write out the actual Euler rotation angles as [TT]theta[1-3].xvg[tt]" }; t_topology *top = NULL; real t; rvec *x = NULL; matrix box; t_trxstatus *status; int natoms; real theta1, theta2, theta3; int i, j, teller = 0; int iCA, iSC; int *ind_CA; int *ind_SC; char *gn_CA; char *gn_SC; rvec v1, v2; rvec *x_CA, *x_SC; rvec *r12; rvec *r23; rvec *r34; rvec *diff13; rvec *diff24; rvec *helixaxis; rvec *residuehelixaxis; rvec *residueorigin; rvec *residuevector; rvec *sidechainvector; rvec *residuehelixaxis_t0; rvec *residuevector_t0; rvec *axis3_t0; rvec *residuehelixaxis_tlast; rvec *residuevector_tlast; rvec *axis3_tlast; rvec refaxes[3], newaxes[3]; rvec unitaxes[3]; rvec rot_refaxes[3], rot_newaxes[3]; real tilt, rotation; rvec *axis3; real *twist, *residuetwist; real *radius, *residueradius; real *rise, *residuerise; real *residuebending; real tmp; real weight[3]; t_pbc pbc; matrix A; FILE *fpaxis, *fpcenter, *fptilt, *fprotation; FILE *fpradius, *fprise, *fptwist; FILE *fptheta1, *fptheta2, *fptheta3; FILE *fpbending; int ePBC; gmx_output_env_t *oenv; gmx_rmpbc_t gpbc = NULL; static gmx_bool bSC = FALSE; static gmx_bool bIncremental = FALSE; static t_pargs pa[] = { { "-sidechain", FALSE, etBOOL, {&bSC}, "Calculate sidechain directions relative to helix axis too." }, { "-incremental", FALSE, etBOOL, {&bIncremental}, "Calculate incremental rather than total rotation/tilt." }, }; #define NPA asize(pa) t_filenm fnm[] = { { efTPR, NULL, NULL, ffREAD }, { efTRX, "-f", NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efDAT, "-oaxis", "helixaxis", ffWRITE }, { efDAT, "-ocenter", "center", ffWRITE }, { efXVG, "-orise", "rise", ffWRITE }, { efXVG, "-oradius", "radius", ffWRITE }, { efXVG, "-otwist", "twist", ffWRITE }, { efXVG, "-obending", "bending", ffWRITE }, { efXVG, "-otilt", "tilt", ffWRITE }, { efXVG, "-orot", "rotation", ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME, NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC); for (i = 0; i < 3; i++) { weight[i] = 1.0; } /* read index files */ printf("Select a group of Calpha atoms corresponding to a single continuous helix:\n"); get_index(&(top->atoms), ftp2fn_null(efNDX, NFILE, fnm), 1, &iCA, &ind_CA, &gn_CA); snew(x_CA, iCA); snew(x_SC, iCA); /* sic! */ snew(r12, iCA-3); snew(r23, iCA-3); snew(r34, iCA-3); snew(diff13, iCA-3); snew(diff24, iCA-3); snew(helixaxis, iCA-3); snew(twist, iCA); snew(residuetwist, iCA); snew(radius, iCA); snew(residueradius, iCA); snew(rise, iCA); snew(residuerise, iCA); snew(residueorigin, iCA); snew(residuehelixaxis, iCA); snew(residuevector, iCA); snew(sidechainvector, iCA); snew(residuebending, iCA); snew(residuehelixaxis_t0, iCA); snew(residuevector_t0, iCA); snew(axis3_t0, iCA); snew(residuehelixaxis_tlast, iCA); snew(residuevector_tlast, iCA); snew(axis3_tlast, iCA); snew(axis3, iCA); if (bSC) { printf("Select a group of atoms defining the sidechain direction (1/residue):\n"); get_index(&(top->atoms), ftp2fn_null(efNDX, NFILE, fnm), 1, &iSC, &ind_SC, &gn_SC); if (iSC != iCA) { gmx_fatal(FARGS, "Number of sidechain atoms (%d) != number of CA atoms (%d)", iSC, iCA); } } natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); fpaxis = gmx_ffopen(opt2fn("-oaxis", NFILE, fnm), "w"); fpcenter = gmx_ffopen(opt2fn("-ocenter", NFILE, fnm), "w"); fprise = gmx_ffopen(opt2fn("-orise", NFILE, fnm), "w"); fpradius = gmx_ffopen(opt2fn("-oradius", NFILE, fnm), "w"); fptwist = gmx_ffopen(opt2fn("-otwist", NFILE, fnm), "w"); fpbending = gmx_ffopen(opt2fn("-obending", NFILE, fnm), "w"); fptheta1 = gmx_ffopen("theta1.xvg", "w"); fptheta2 = gmx_ffopen("theta2.xvg", "w"); fptheta3 = gmx_ffopen("theta3.xvg", "w"); if (bIncremental) { fptilt = xvgropen(opt2fn("-otilt", NFILE, fnm), "Incremental local helix tilt", "Time(ps)", "Tilt (degrees)", oenv); fprotation = xvgropen(opt2fn("-orot", NFILE, fnm), "Incremental local helix rotation", "Time(ps)", "Rotation (degrees)", oenv); } else { fptilt = xvgropen(opt2fn("-otilt", NFILE, fnm), "Cumulative local helix tilt", "Time(ps)", "Tilt (degrees)", oenv); fprotation = xvgropen(opt2fn("-orot", NFILE, fnm), "Cumulative local helix rotation", "Time(ps)", "Rotation (degrees)", oenv); } clear_rvecs(3, unitaxes); unitaxes[0][0] = 1; unitaxes[1][1] = 1; unitaxes[2][2] = 1; gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms); do { /* initialisation for correct distance calculations */ set_pbc(&pbc, ePBC, box); /* make molecules whole again */ gmx_rmpbc(gpbc, natoms, box, x); /* copy coords to our smaller arrays */ for (i = 0; i < iCA; i++) { copy_rvec(x[ind_CA[i]], x_CA[i]); if (bSC) { copy_rvec(x[ind_SC[i]], x_SC[i]); } } for (i = 0; i < iCA-3; i++) { rvec_sub(x_CA[i+1], x_CA[i], r12[i]); rvec_sub(x_CA[i+2], x_CA[i+1], r23[i]); rvec_sub(x_CA[i+3], x_CA[i+2], r34[i]); rvec_sub(r12[i], r23[i], diff13[i]); rvec_sub(r23[i], r34[i], diff24[i]); /* calculate helix axis */ cprod(diff13[i], diff24[i], helixaxis[i]); svmul(1.0/norm(helixaxis[i]), helixaxis[i], helixaxis[i]); tmp = cos_angle(diff13[i], diff24[i]); twist[i] = 180.0/M_PI * std::acos( tmp ); radius[i] = std::sqrt( norm(diff13[i])*norm(diff24[i]) ) / (2.0* (1.0-tmp) ); rise[i] = std::abs(iprod(r23[i], helixaxis[i])); svmul(radius[i]/norm(diff13[i]), diff13[i], v1); svmul(radius[i]/norm(diff24[i]), diff24[i], v2); rvec_sub(x_CA[i+1], v1, residueorigin[i+1]); rvec_sub(x_CA[i+2], v2, residueorigin[i+2]); } residueradius[0] = residuetwist[0] = residuerise[0] = 0; residueradius[1] = radius[0]; residuetwist[1] = twist[0]; residuerise[1] = rise[0]; residuebending[0] = residuebending[1] = 0; for (i = 2; i < iCA-2; i++) { residueradius[i] = 0.5*(radius[i-2]+radius[i-1]); residuetwist[i] = 0.5*(twist[i-2]+twist[i-1]); residuerise[i] = 0.5*(rise[i-2]+rise[i-1]); residuebending[i] = 180.0/M_PI*std::acos( cos_angle(helixaxis[i-2], helixaxis[i-1]) ); } residueradius[iCA-2] = radius[iCA-4]; residuetwist[iCA-2] = twist[iCA-4]; residuerise[iCA-2] = rise[iCA-4]; residueradius[iCA-1] = residuetwist[iCA-1] = residuerise[iCA-1] = 0; residuebending[iCA-2] = residuebending[iCA-1] = 0; clear_rvec(residueorigin[0]); clear_rvec(residueorigin[iCA-1]); /* average helix axes to define them on the residues. * Just extrapolate second first/list atom. */ copy_rvec(helixaxis[0], residuehelixaxis[0]); copy_rvec(helixaxis[0], residuehelixaxis[1]); for (i = 2; i < iCA-2; i++) { rvec_add(helixaxis[i-2], helixaxis[i-1], residuehelixaxis[i]); svmul(0.5, residuehelixaxis[i], residuehelixaxis[i]); } copy_rvec(helixaxis[iCA-4], residuehelixaxis[iCA-2]); copy_rvec(helixaxis[iCA-4], residuehelixaxis[iCA-1]); /* Normalize the axis */ for (i = 0; i < iCA; i++) { svmul(1.0/norm(residuehelixaxis[i]), residuehelixaxis[i], residuehelixaxis[i]); } /* calculate vector from origin to residue CA */ fprintf(fpaxis, "%15.12g ", t); fprintf(fpcenter, "%15.12g ", t); fprintf(fprise, "%15.12g ", t); fprintf(fpradius, "%15.12g ", t); fprintf(fptwist, "%15.12g ", t); fprintf(fpbending, "%15.12g ", t); for (i = 0; i < iCA; i++) { if (i == 0 || i == iCA-1) { fprintf(fpaxis, "%15.12g %15.12g %15.12g ", 0.0, 0.0, 0.0); fprintf(fpcenter, "%15.12g %15.12g %15.12g ", 0.0, 0.0, 0.0); fprintf(fprise, "%15.12g ", 0.0); fprintf(fpradius, "%15.12g ", 0.0); fprintf(fptwist, "%15.12g ", 0.0); fprintf(fpbending, "%15.12g ", 0.0); } else { rvec_sub( bSC ? x_SC[i] : x_CA[i], residueorigin[i], residuevector[i]); svmul(1.0/norm(residuevector[i]), residuevector[i], residuevector[i]); cprod(residuehelixaxis[i], residuevector[i], axis3[i]); fprintf(fpaxis, "%15.12g %15.12g %15.12g ", residuehelixaxis[i][0], residuehelixaxis[i][1], residuehelixaxis[i][2]); fprintf(fpcenter, "%15.12g %15.12g %15.12g ", residueorigin[i][0], residueorigin[i][1], residueorigin[i][2]); fprintf(fprise, "%15.12g ", residuerise[i]); fprintf(fpradius, "%15.12g ", residueradius[i]); fprintf(fptwist, "%15.12g ", residuetwist[i]); fprintf(fpbending, "%15.12g ", residuebending[i]); } } fprintf(fprise, "\n"); fprintf(fpradius, "\n"); fprintf(fpaxis, "\n"); fprintf(fpcenter, "\n"); fprintf(fptwist, "\n"); fprintf(fpbending, "\n"); if (teller == 0) { for (i = 0; i < iCA; i++) { copy_rvec(residuehelixaxis[i], residuehelixaxis_t0[i]); copy_rvec(residuevector[i], residuevector_t0[i]); copy_rvec(axis3[i], axis3_t0[i]); } } else { fprintf(fptilt, "%15.12g ", t); fprintf(fprotation, "%15.12g ", t); fprintf(fptheta1, "%15.12g ", t); fprintf(fptheta2, "%15.12g ", t); fprintf(fptheta3, "%15.12g ", t); for (i = 0; i < iCA; i++) { if (i == 0 || i == iCA-1) { tilt = rotation = 0; } else { if (!bIncremental) { /* Total rotation & tilt */ copy_rvec(residuehelixaxis_t0[i], refaxes[0]); copy_rvec(residuevector_t0[i], refaxes[1]); copy_rvec(axis3_t0[i], refaxes[2]); } else { /* Rotation/tilt since last step */ copy_rvec(residuehelixaxis_tlast[i], refaxes[0]); copy_rvec(residuevector_tlast[i], refaxes[1]); copy_rvec(axis3_tlast[i], refaxes[2]); } copy_rvec(residuehelixaxis[i], newaxes[0]); copy_rvec(residuevector[i], newaxes[1]); copy_rvec(axis3[i], newaxes[2]); /* rotate reference frame onto unit axes */ calc_fit_R(3, 3, weight, unitaxes, refaxes, A); for (j = 0; j < 3; j++) { mvmul(A, refaxes[j], rot_refaxes[j]); mvmul(A, newaxes[j], rot_newaxes[j]); } /* Determine local rotation matrix A */ calc_fit_R(3, 3, weight, rot_newaxes, rot_refaxes, A); /* Calculate euler angles, from rotation order y-z-x, where * x is helixaxis, y residuevector, and z axis3. * * A contains rotation column vectors. */ theta1 = 180.0/M_PI*std::atan2(A[0][2], A[0][0]); theta2 = 180.0/M_PI*std::asin(-A[0][1]); theta3 = 180.0/M_PI*std::atan2(A[2][1], A[1][1]); tilt = std::sqrt(theta1*theta1+theta2*theta2); rotation = theta3; fprintf(fptheta1, "%15.12g ", theta1); fprintf(fptheta2, "%15.12g ", theta2); fprintf(fptheta3, "%15.12g ", theta3); } fprintf(fptilt, "%15.12g ", tilt); fprintf(fprotation, "%15.12g ", rotation); } fprintf(fptilt, "\n"); fprintf(fprotation, "\n"); fprintf(fptheta1, "\n"); fprintf(fptheta2, "\n"); fprintf(fptheta3, "\n"); } for (i = 0; i < iCA; i++) { copy_rvec(residuehelixaxis[i], residuehelixaxis_tlast[i]); copy_rvec(residuevector[i], residuevector_tlast[i]); copy_rvec(axis3[i], axis3_tlast[i]); } teller++; } while (read_next_x(oenv, status, &t, x, box)); gmx_rmpbc_done(gpbc); gmx_ffclose(fpaxis); gmx_ffclose(fpcenter); xvgrclose(fptilt); xvgrclose(fprotation); gmx_ffclose(fprise); gmx_ffclose(fpradius); gmx_ffclose(fptwist); gmx_ffclose(fpbending); gmx_ffclose(fptheta1); gmx_ffclose(fptheta2); gmx_ffclose(fptheta3); close_trj(status); return 0; }
void sas_plot(int nfile,t_filenm fnm[],real solsize,int ndots, real qcut,gmx_bool bSave,real minarea,gmx_bool bPBC, real dgs_default,gmx_bool bFindex, const output_env_t oenv) { FILE *fp,*fp2,*fp3=NULL,*vp; const char *flegend[] = { "Hydrophobic", "Hydrophilic", "Total", "D Gsolv" }; const char *vlegend[] = { "Volume (nm\\S3\\N)", "Density (g/l)" }; const char *or_and_oa_legend[] = { "Average (nm\\S2\\N)", "Standard deviation (nm\\S2\\N)" }; const char *vfile; real t; gmx_atomprop_t aps=NULL; gmx_rmpbc_t gpbc=NULL; t_trxstatus *status; int ndefault; int i,j,ii,nfr,natoms,flag,nsurfacedots,res; rvec *xtop,*x; matrix topbox,box; t_topology top; char title[STRLEN]; int ePBC; gmx_bool bTop; t_atoms *atoms; gmx_bool *bOut,*bPhobic; gmx_bool bConnelly; gmx_bool bResAt,bITP,bDGsol; real *radius,*dgs_factor=NULL,*area=NULL,*surfacedots=NULL; real at_area,*atom_area=NULL,*atom_area2=NULL; real *res_a=NULL,*res_area=NULL,*res_area2=NULL; real totarea,totvolume,totmass=0,density,harea,tarea,fluc2; atom_id **index,*findex; int *nx,nphobic,npcheck,retval; char **grpname,*fgrpname; real dgsolv; bITP = opt2bSet("-i",nfile,fnm); bResAt = opt2bSet("-or",nfile,fnm) || opt2bSet("-oa",nfile,fnm) || bITP; bTop = read_tps_conf(ftp2fn(efTPS,nfile,fnm),title,&top,&ePBC, &xtop,NULL,topbox,FALSE); atoms = &(top.atoms); if (!bTop) { fprintf(stderr,"No tpr file, will not compute Delta G of solvation\n"); bDGsol = FALSE; } else { bDGsol = strcmp(*(atoms->atomtype[0]),"?") != 0; if (!bDGsol) { fprintf(stderr,"Warning: your tpr file is too old, will not compute " "Delta G of solvation\n"); } else { printf("In case you use free energy of solvation predictions:\n"); please_cite(stdout,"Eisenberg86a"); } } aps = gmx_atomprop_init(); if ((natoms=read_first_x(oenv,&status,ftp2fn(efTRX,nfile,fnm), &t,&x,box))==0) gmx_fatal(FARGS,"Could not read coordinates from statusfile\n"); if ((ePBC != epbcXYZ) || (TRICLINIC(box))) { fprintf(stderr,"\n\nWARNING: non-rectangular boxes may give erroneous results or crashes.\n" "Analysis based on vacuum simulations (with the possibility of evaporation)\n" "will certainly crash the analysis.\n\n"); } snew(nx,2); snew(index,2); snew(grpname,2); fprintf(stderr,"Select a group for calculation of surface and a group for output:\n"); get_index(atoms,ftp2fn_null(efNDX,nfile,fnm),2,nx,index,grpname); if (bFindex) { fprintf(stderr,"Select a group of hydrophobic atoms:\n"); get_index(atoms,ftp2fn_null(efNDX,nfile,fnm),1,&nphobic,&findex,&fgrpname); } snew(bOut,natoms); for(i=0; i<nx[1]; i++) bOut[index[1][i]] = TRUE; /* Now compute atomic readii including solvent probe size */ snew(radius,natoms); snew(bPhobic,nx[0]); if (bResAt) { snew(atom_area,nx[0]); snew(atom_area2,nx[0]); snew(res_a,atoms->nres); snew(res_area,atoms->nres); snew(res_area2,atoms->nres); } if (bDGsol) snew(dgs_factor,nx[0]); /* Get a Van der Waals radius for each atom */ ndefault = 0; for(i=0; (i<natoms); i++) { if (!gmx_atomprop_query(aps,epropVDW, *(atoms->resinfo[atoms->atom[i].resind].name), *(atoms->atomname[i]),&radius[i])) ndefault++; /* radius[i] = calc_radius(*(top->atoms.atomname[i])); */ radius[i] += solsize; } if (ndefault > 0) fprintf(stderr,"WARNING: could not find a Van der Waals radius for %d atoms\n",ndefault); /* Determine which atom is counted as hydrophobic */ if (bFindex) { npcheck = 0; for(i=0; (i<nx[0]); i++) { ii = index[0][i]; for(j=0; (j<nphobic); j++) { if (findex[j] == ii) { bPhobic[i] = TRUE; if (bOut[ii]) npcheck++; } } } if (npcheck != nphobic) gmx_fatal(FARGS,"Consistency check failed: not all %d atoms in the hydrophobic index\n" "found in the normal index selection (%d atoms)",nphobic,npcheck); } else nphobic = 0; for(i=0; (i<nx[0]); i++) { ii = index[0][i]; if (!bFindex) { bPhobic[i] = fabs(atoms->atom[ii].q) <= qcut; if (bPhobic[i] && bOut[ii]) nphobic++; } if (bDGsol) if (!gmx_atomprop_query(aps,epropDGsol, *(atoms->resinfo[atoms->atom[ii].resind].name), *(atoms->atomtype[ii]),&(dgs_factor[i]))) dgs_factor[i] = dgs_default; if (debug) fprintf(debug,"Atom %5d %5s-%5s: q= %6.3f, r= %6.3f, dgsol= %6.3f, hydrophobic= %s\n", ii+1,*(atoms->resinfo[atoms->atom[ii].resind].name), *(atoms->atomname[ii]), atoms->atom[ii].q,radius[ii]-solsize,dgs_factor[i], BOOL(bPhobic[i])); } fprintf(stderr,"%d out of %d atoms were classified as hydrophobic\n", nphobic,nx[1]); fp=xvgropen(opt2fn("-o",nfile,fnm),"Solvent Accessible Surface","Time (ps)", "Area (nm\\S2\\N)",oenv); xvgr_legend(fp,asize(flegend) - (bDGsol ? 0 : 1),flegend,oenv); vfile = opt2fn_null("-tv",nfile,fnm); if (vfile) { if (!bTop) { gmx_fatal(FARGS,"Need a tpr file for option -tv"); } vp=xvgropen(vfile,"Volume and Density","Time (ps)","",oenv); xvgr_legend(vp,asize(vlegend),vlegend,oenv); totmass = 0; ndefault = 0; for(i=0; (i<nx[0]); i++) { real mm; ii = index[0][i]; /* if (!query_atomprop(atomprop,epropMass, *(top->atoms.resname[top->atoms.atom[ii].resnr]), *(top->atoms.atomname[ii]),&mm)) ndefault++; totmass += mm; */ totmass += atoms->atom[ii].m; } if (ndefault) fprintf(stderr,"WARNING: Using %d default masses for density calculation, which most likely are inaccurate\n",ndefault); } else vp = NULL; gmx_atomprop_destroy(aps); if (bPBC) gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box); nfr=0; do { if (bPBC) gmx_rmpbc(gpbc,natoms,box,x); bConnelly = (nfr==0 && opt2bSet("-q",nfile,fnm)); if (bConnelly) { if (!bTop) gmx_fatal(FARGS,"Need a tpr file for Connelly plot"); flag = FLAG_ATOM_AREA | FLAG_DOTS; } else { flag = FLAG_ATOM_AREA; } if (vp) { flag = flag | FLAG_VOLUME; } if (debug) write_sto_conf("check.pdb","pbc check",atoms,x,NULL,ePBC,box); retval = nsc_dclm_pbc(x,radius,nx[0],ndots,flag,&totarea, &area,&totvolume,&surfacedots,&nsurfacedots, index[0],ePBC,bPBC ? box : NULL); if (retval) gmx_fatal(FARGS,"Something wrong in nsc_dclm_pbc"); if (bConnelly) connelly_plot(ftp2fn(efPDB,nfile,fnm), nsurfacedots,surfacedots,x,atoms, &(top.symtab),ePBC,box,bSave); harea = 0; tarea = 0; dgsolv = 0; if (bResAt) for(i=0; i<atoms->nres; i++) res_a[i] = 0; for(i=0; (i<nx[0]); i++) { ii = index[0][i]; if (bOut[ii]) { at_area = area[i]; if (bResAt) { atom_area[i] += at_area; atom_area2[i] += sqr(at_area); res_a[atoms->atom[ii].resind] += at_area; } tarea += at_area; if (bDGsol) dgsolv += at_area*dgs_factor[i]; if (bPhobic[i]) harea += at_area; } } if (bResAt) for(i=0; i<atoms->nres; i++) { res_area[i] += res_a[i]; res_area2[i] += sqr(res_a[i]); } fprintf(fp,"%10g %10g %10g %10g",t,harea,tarea-harea,tarea); if (bDGsol) fprintf(fp," %10g\n",dgsolv); else fprintf(fp,"\n"); /* Print volume */ if (vp) { density = totmass*AMU/(totvolume*NANO*NANO*NANO); fprintf(vp,"%12.5e %12.5e %12.5e\n",t,totvolume,density); } if (area) { sfree(area); area = NULL; } if (surfacedots) { sfree(surfacedots); surfacedots = NULL; } nfr++; } while (read_next_x(oenv,status,&t,natoms,x,box)); if (bPBC) gmx_rmpbc_done(gpbc); fprintf(stderr,"\n"); close_trj(status); ffclose(fp); if (vp) ffclose(vp); /* if necessary, print areas per atom to file too: */ if (bResAt) { for(i=0; i<atoms->nres; i++) { res_area[i] /= nfr; res_area2[i] /= nfr; } for(i=0; i<nx[0]; i++) { atom_area[i] /= nfr; atom_area2[i] /= nfr; } fprintf(stderr,"Printing out areas per atom\n"); fp = xvgropen(opt2fn("-or",nfile,fnm),"Area per residue over the trajectory","Residue", "Area (nm\\S2\\N)",oenv); xvgr_legend(fp, asize(or_and_oa_legend),or_and_oa_legend,oenv); fp2 = xvgropen(opt2fn("-oa",nfile,fnm),"Area per atom over the trajectory","Atom #", "Area (nm\\S2\\N)",oenv); xvgr_legend(fp2, asize(or_and_oa_legend),or_and_oa_legend,oenv); if (bITP) { fp3 = ftp2FILE(efITP,nfile,fnm,"w"); fprintf(fp3,"[ position_restraints ]\n" "#define FCX 1000\n" "#define FCY 1000\n" "#define FCZ 1000\n" "; Atom Type fx fy fz\n"); } for(i=0; i<nx[0]; i++) { ii = index[0][i]; res = atoms->atom[ii].resind; if (i==nx[0]-1 || res!=atoms->atom[index[0][i+1]].resind) { fluc2 = res_area2[res]-sqr(res_area[res]); if (fluc2 < 0) fluc2 = 0; fprintf(fp,"%10d %10g %10g\n", atoms->resinfo[res].nr,res_area[res],sqrt(fluc2)); } fluc2 = atom_area2[i]-sqr(atom_area[i]); if (fluc2 < 0) fluc2 = 0; fprintf(fp2,"%d %g %g\n",index[0][i]+1,atom_area[i],sqrt(fluc2)); if (bITP && (atom_area[i] > minarea)) fprintf(fp3,"%5d 1 FCX FCX FCZ\n",ii+1); } if (bITP) ffclose(fp3); ffclose(fp); } /* Be a good citizen, keep our memory free! */ sfree(x); sfree(nx); for(i=0;i<2;i++) { sfree(index[i]); sfree(grpname[i]); } sfree(bOut); sfree(radius); sfree(bPhobic); if(bResAt) { sfree(atom_area); sfree(atom_area2); sfree(res_a); sfree(res_area); sfree(res_area2); } if(bDGsol) { sfree(dgs_factor); } }
void sgangle_plot_single(const char *fn,const char *afile,const char *dfile, const char *d1file, const char *d2file, atom_id index1[], int gnx1, char *grpn1, atom_id index2[], int gnx2, char *grpn2, t_topology *top,int ePBC, const output_env_t oenv) { FILE *sg_angle, /* xvgr file with angles */ *sg_distance = NULL, /* xvgr file with distances */ *sg_distance1 = NULL,/* xvgr file with distance between plane and atom */ *sg_distance2 = NULL;/* xvgr file with distance between plane and atom2 */ real t, /* time */ angle, /* cosine of angle between two groups */ distance, /* distance between two groups. */ distance1, /* distance between plane and one of two atoms */ distance2; /* same for second of two atoms */ t_trxstatus *status; int natoms,teller=0; int i; rvec *x0; /* coordinates, and coordinates corrected for pb */ rvec *xzero; matrix box; char buf[256]; /* for xvgr title */ gmx_rmpbc_t gpbc=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,"Angle between %s and %s",grpn1,grpn2); sg_angle = xvgropen(afile,buf,"Time (ps)","Cos(angle) ",oenv); if (dfile) { sprintf(buf,"Distance between %s and %s",grpn1,grpn2); sg_distance = xvgropen(dfile,buf,"Time (ps)","Distance (nm)",oenv); } if (d1file) { sprintf(buf,"Distance between plane and first atom of vector"); sg_distance1 = xvgropen(d1file,buf,"Time (ps)","Distance (nm)",oenv); } if (d2file) { sprintf(buf,"Distance between plane and second atom of vector"); sg_distance2 = xvgropen(d2file,buf,"Time (ps","Distance (nm)",oenv); } snew(xzero,natoms); gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box); do { teller++; gmx_rmpbc(gpbc,natoms,box,x0); if (teller==1) { for(i=0;i<natoms;i++) copy_rvec(x0[i],xzero[i]); } calc_angle_single(ePBC,box, xzero,x0,index1,index2,gnx1,gnx2,&angle, &distance,&distance1,&distance2); fprintf(sg_angle,"%12g %12g %12g\n",t,angle,acos(angle)*180.0/M_PI); if (dfile) fprintf(sg_distance,"%12g %12g\n",t,distance); if (d1file) fprintf(sg_distance1,"%12g %12g\n",t,distance1); if (d2file) fprintf(sg_distance2,"%12g %12g\n",t,distance1); } while (read_next_x(oenv,status,&t,natoms,x0,box)); gmx_rmpbc_done(gpbc); fprintf(stderr,"\n"); close_trj(status); ffclose(sg_angle); if (dfile) ffclose(sg_distance); if (d1file) ffclose(sg_distance1); if (d2file) ffclose(sg_distance2); sfree(x0); }
int gmx_disre(int argc,char *argv[]) { const char *desc[] = { "g_disre computes violations of distance restraints.", "If necessary all protons can be added to a protein molecule ", "using the protonate program.[PAR]", "The program always", "computes the instantaneous violations rather than time-averaged,", "because this analysis is done from a trajectory file afterwards", "it does not make sense to use time averaging. However,", "the time averaged values per restraint are given in the log file.[PAR]", "An index file may be used to select specific restraints for", "printing.[PAR]", "When the optional[TT]-q[tt] flag is given a pdb file coloured by the", "amount of average violations.[PAR]", "When the [TT]-c[tt] option is given, an index file will be read", "containing the frames in your trajectory corresponding to the clusters", "(defined in another manner) that you want to analyze. For these clusters", "the program will compute average violations using the third power", "averaging algorithm and print them in the log file." }; static int ntop = 0; static int nlevels = 20; static real max_dr = 0; static gmx_bool bThird = TRUE; t_pargs pa[] = { { "-ntop", FALSE, etINT, {&ntop}, "Number of large violations that are stored in the log file every step" }, { "-maxdr", FALSE, etREAL, {&max_dr}, "Maximum distance violation in matrix output. If less than or equal to 0 the maximum will be determined by the data." }, { "-nlevels", FALSE, etINT, {&nlevels}, "Number of levels in the matrix output" }, { "-third", FALSE, etBOOL, {&bThird}, "Use inverse third power averaging or linear for matrix output" } }; FILE *out=NULL,*aver=NULL,*numv=NULL,*maxxv=NULL,*xvg=NULL; t_tpxheader header; t_inputrec ir; gmx_mtop_t mtop; rvec *xtop; gmx_localtop_t *top; t_atoms *atoms=NULL; t_forcerec *fr; t_fcdata fcd; t_nrnb nrnb; t_commrec *cr; t_graph *g; int ntopatoms,natoms,i,j,kkk; t_trxstatus *status; real t; rvec *x,*f,*xav=NULL; matrix box; gmx_bool bPDB; int isize; atom_id *index=NULL,*ind_fit=NULL; char *grpname; t_cluster_ndx *clust=NULL; t_dr_result dr,*dr_clust=NULL; char **leg; real *vvindex=NULL,*w_rls=NULL; t_mdatoms *mdatoms; t_pbc pbc,*pbc_null; int my_clust; FILE *fplog; output_env_t oenv; gmx_rmpbc_t gpbc=NULL; t_filenm fnm[] = { { efTPX, NULL, NULL, ffREAD }, { efTRX, "-f", NULL, ffREAD }, { efXVG, "-ds", "drsum", ffWRITE }, { efXVG, "-da", "draver", ffWRITE }, { efXVG, "-dn", "drnum", ffWRITE }, { efXVG, "-dm", "drmax", ffWRITE }, { efXVG, "-dr", "restr", ffWRITE }, { efLOG, "-l", "disres", ffWRITE }, { efNDX, NULL, "viol", ffOPTRD }, { efPDB, "-q", "viol", ffOPTWR }, { efNDX, "-c", "clust", ffOPTRD }, { efXPM, "-x", "matrix", ffOPTWR } }; #define NFILE asize(fnm) cr = init_par(&argc,&argv); CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE, NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv); gmx_log_open(ftp2fn(efLOG,NFILE,fnm),cr,FALSE,0,&fplog); if (ntop) init5(ntop); read_tpxheader(ftp2fn(efTPX,NFILE,fnm),&header,FALSE,NULL,NULL); snew(xtop,header.natoms); read_tpx(ftp2fn(efTPX,NFILE,fnm),&ir,box,&ntopatoms,xtop,NULL,NULL,&mtop); bPDB = opt2bSet("-q",NFILE,fnm); if (bPDB) { snew(xav,ntopatoms); snew(ind_fit,ntopatoms); snew(w_rls,ntopatoms); for(kkk=0; (kkk<ntopatoms); kkk++) { w_rls[kkk] = 1; ind_fit[kkk] = kkk; } snew(atoms,1); *atoms = gmx_mtop_global_atoms(&mtop); if (atoms->pdbinfo == NULL) { snew(atoms->pdbinfo,atoms->nr); } } top = gmx_mtop_generate_local_top(&mtop,&ir); g = NULL; pbc_null = NULL; if (ir.ePBC != epbcNONE) { if (ir.bPeriodicMols) pbc_null = &pbc; else g = mk_graph(fplog,&top->idef,0,mtop.natoms,FALSE,FALSE); } if (ftp2bSet(efNDX,NFILE,fnm)) { rd_index(ftp2fn(efNDX,NFILE,fnm),1,&isize,&index,&grpname); xvg=xvgropen(opt2fn("-dr",NFILE,fnm),"Inidividual Restraints","Time (ps)", "nm",oenv); snew(vvindex,isize); snew(leg,isize); for(i=0; (i<isize); i++) { index[i]++; snew(leg[i],12); sprintf(leg[i],"index %d",index[i]); } xvgr_legend(xvg,isize,(const char**)leg,oenv); } else isize=0; ir.dr_tau=0.0; init_disres(fplog,&mtop,&ir,NULL,FALSE,&fcd,NULL); natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); snew(f,5*natoms); init_dr_res(&dr,fcd.disres.nres); if (opt2bSet("-c",NFILE,fnm)) { clust = cluster_index(fplog,opt2fn("-c",NFILE,fnm)); snew(dr_clust,clust->clust->nr+1); for(i=0; (i<=clust->clust->nr); i++) init_dr_res(&dr_clust[i],fcd.disres.nres); } else { out =xvgropen(opt2fn("-ds",NFILE,fnm), "Sum of Violations","Time (ps)","nm",oenv); aver=xvgropen(opt2fn("-da",NFILE,fnm), "Average Violation","Time (ps)","nm",oenv); numv=xvgropen(opt2fn("-dn",NFILE,fnm), "# Violations","Time (ps)","#",oenv); maxxv=xvgropen(opt2fn("-dm",NFILE,fnm), "Largest Violation","Time (ps)","nm",oenv); } mdatoms = init_mdatoms(fplog,&mtop,ir.efep!=efepNO); atoms2md(&mtop,&ir,0,NULL,0,mtop.natoms,mdatoms); update_mdatoms(mdatoms,ir.init_lambda); fr = mk_forcerec(); fprintf(fplog,"Made forcerec\n"); init_forcerec(fplog,oenv,fr,NULL,&ir,&mtop,cr,box,FALSE,NULL,NULL,NULL, FALSE,-1); init_nrnb(&nrnb); if (ir.ePBC != epbcNONE) gpbc = gmx_rmpbc_init(&top->idef,ir.ePBC,natoms,box); j=0; do { if (ir.ePBC != epbcNONE) { if (ir.bPeriodicMols) set_pbc(&pbc,ir.ePBC,box); else gmx_rmpbc(gpbc,natoms,box,x); } if (clust) { if (j > clust->maxframe) gmx_fatal(FARGS,"There are more frames in the trajectory than in the cluster index file. t = %8f\n",t); my_clust = clust->inv_clust[j]; range_check(my_clust,0,clust->clust->nr); check_viol(fplog,cr,&(top->idef.il[F_DISRES]), top->idef.iparams,top->idef.functype, x,f,fr,pbc_null,g,dr_clust,my_clust,isize,index,vvindex,&fcd); } else check_viol(fplog,cr,&(top->idef.il[F_DISRES]), top->idef.iparams,top->idef.functype, x,f,fr,pbc_null,g,&dr,0,isize,index,vvindex,&fcd); if (bPDB) { reset_x(atoms->nr,ind_fit,atoms->nr,NULL,x,w_rls); do_fit(atoms->nr,w_rls,x,x); if (j == 0) { /* Store the first frame of the trajectory as 'characteristic' * for colouring with violations. */ for(kkk=0; (kkk<atoms->nr); kkk++) copy_rvec(x[kkk],xav[kkk]); } } if (!clust) { if (isize > 0) { fprintf(xvg,"%10g",t); for(i=0; (i<isize); i++) fprintf(xvg," %10g",vvindex[i]); fprintf(xvg,"\n"); } fprintf(out, "%10g %10g\n",t,dr.sumv); fprintf(aver, "%10g %10g\n",t,dr.averv); fprintf(maxxv,"%10g %10g\n",t,dr.maxv); fprintf(numv, "%10g %10d\n",t,dr.nv); } j++; } while (read_next_x(oenv,status,&t,natoms,x,box)); close_trj(status); if (ir.ePBC != epbcNONE) gmx_rmpbc_done(gpbc); if (clust) { dump_clust_stats(fplog,fcd.disres.nres,&(top->idef.il[F_DISRES]), top->idef.iparams,clust->clust,dr_clust, clust->grpname,isize,index); } else { dump_stats(fplog,j,fcd.disres.nres,&(top->idef.il[F_DISRES]), top->idef.iparams,&dr,isize,index, bPDB ? atoms : NULL); if (bPDB) { write_sto_conf(opt2fn("-q",NFILE,fnm), "Coloured by average violation in Angstrom", atoms,xav,NULL,ir.ePBC,box); } dump_disre_matrix(opt2fn_null("-x",NFILE,fnm),&dr,fcd.disres.nres, j,&top->idef,&mtop,max_dr,nlevels,bThird); ffclose(out); ffclose(aver); ffclose(numv); ffclose(maxxv); if (isize > 0) { ffclose(xvg); do_view(oenv,opt2fn("-dr",NFILE,fnm),"-nxy"); } do_view(oenv,opt2fn("-dn",NFILE,fnm),"-nxy"); do_view(oenv,opt2fn("-da",NFILE,fnm),"-nxy"); do_view(oenv,opt2fn("-ds",NFILE,fnm),"-nxy"); do_view(oenv,opt2fn("-dm",NFILE,fnm),"-nxy"); } thanx(stderr); if (gmx_parallel_env_initialized()) gmx_finalize(); gmx_log_close(fplog); 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_rotmat(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] plots the rotation matrix required for least squares fitting", "a conformation onto the reference conformation provided with", "[TT]-s[tt]. Translation is removed before fitting.", "The output are the three vectors that give the new directions", "of the x, y and z directions of the reference conformation,", "for example: (zx,zy,zz) is the orientation of the reference", "z-axis in the trajectory frame.", "[PAR]", "This tool is useful for, for instance,", "determining the orientation of a molecule", "at an interface, possibly on a trajectory produced with", "[TT]gmx trjconv -fit rotxy+transxy[tt] to remove the rotation", "in the [IT]x-y[it] plane.", "[PAR]", "Option [TT]-ref[tt] determines a reference structure for fitting,", "instead of using the structure from [TT]-s[tt]. The structure with", "the lowest sum of RMSD's to all other structures is used.", "Since the computational cost of this procedure grows with", "the square of the number of frames, the [TT]-skip[tt] option", "can be useful. A full fit or only a fit in the [IT]x-y[it] plane can", "be performed.", "[PAR]", "Option [TT]-fitxy[tt] fits in the [IT]x-y[it] plane before determining", "the rotation matrix." }; const char *reffit[] = { NULL, "none", "xyz", "xy", NULL }; static int skip = 1; static gmx_bool bFitXY = FALSE, bMW = TRUE; t_pargs pa[] = { { "-ref", FALSE, etENUM, {reffit}, "Determine the optimal reference structure" }, { "-skip", FALSE, etINT, {&skip}, "Use every nr-th frame for [TT]-ref[tt]" }, { "-fitxy", FALSE, etBOOL, {&bFitXY}, "Fit the x/y rotation before determining the rotation" }, { "-mw", FALSE, etBOOL, {&bMW}, "Use mass weighted fitting" } }; FILE *out; t_trxstatus *status; t_topology top; int ePBC; rvec *x_ref, *x; matrix box, R; real t; int natoms, i; char *grpname, title[256]; int gnx; gmx_rmpbc_t gpbc = NULL; atom_id *index; output_env_t oenv; real *w_rls; const char *leg[] = { "xx", "xy", "xz", "yx", "yy", "yz", "zx", "zy", "zz" }; #define NLEG asize(leg) t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "rotmat", ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &x_ref, NULL, box, bMW); gpbc = gmx_rmpbc_init(&top.idef, ePBC, top.atoms.nr); gmx_rmpbc(gpbc, top.atoms.nr, box, x_ref); get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpname); if (reffit[0][0] != 'n') { get_refx(oenv, ftp2fn(efTRX, NFILE, fnm), reffit[0][2] == 'z' ? 3 : 2, skip, gnx, index, bMW, &top, ePBC, x_ref); } natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); snew(w_rls, natoms); for (i = 0; i < gnx; i++) { if (index[i] >= natoms) { gmx_fatal(FARGS, "Atom index (%d) is larger than the number of atoms in the trajecory (%d)", index[i]+1, natoms); } w_rls[index[i]] = (bMW ? top.atoms.atom[index[i]].m : 1.0); } if (reffit[0][0] == 'n') { reset_x(gnx, index, natoms, NULL, x_ref, w_rls); } out = xvgropen(ftp2fn(efXVG, NFILE, fnm), "Fit matrix", "Time (ps)", "", oenv); xvgr_legend(out, NLEG, leg, oenv); do { gmx_rmpbc(gpbc, natoms, box, x); reset_x(gnx, index, natoms, NULL, x, w_rls); if (bFitXY) { do_fit_ndim(2, natoms, w_rls, x_ref, x); } calc_fit_R(DIM, natoms, w_rls, x_ref, x, R); fprintf(out, "%7g %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f\n", t, R[XX][XX], R[XX][YY], R[XX][ZZ], R[YY][XX], R[YY][YY], R[YY][ZZ], R[ZZ][XX], R[ZZ][YY], R[ZZ][ZZ]); } while (read_next_x(oenv, status, &t, x, box)); gmx_rmpbc_done(gpbc); close_trj(status); gmx_ffclose(out); do_view(oenv, ftp2fn(efXVG, NFILE, fnm), "-nxy"); return 0; }
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; }
static void get_refx(output_env_t oenv, const char *trxfn, int nfitdim, int skip, int gnx, int *index, gmx_bool bMW, t_topology *top, int ePBC, rvec *x_ref) { int natoms, nfr_all, nfr, i, j, a, r, c, min_fr; t_trxstatus *status; real *ti, min_t; double tot_mass, msd, *srmsd, min_srmsd, srmsd_tot; rvec *x, **xi; real xf; matrix box, R; real *w_rls; gmx_rmpbc_t gpbc = NULL; nfr_all = 0; nfr = 0; snew(ti, 100); snew(xi, 100); natoms = read_first_x(oenv, &status, trxfn, &ti[nfr], &x, box); snew(w_rls, gnx); tot_mass = 0; for (a = 0; a < gnx; a++) { if (index[a] >= natoms) { gmx_fatal(FARGS, "Atom index (%d) is larger than the number of atoms in the trajecory (%d)", index[a]+1, natoms); } w_rls[a] = (bMW ? top->atoms.atom[index[a]].m : 1.0); tot_mass += w_rls[a]; } gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms); do { if (nfr_all % skip == 0) { gmx_rmpbc(gpbc, natoms, box, x); snew(xi[nfr], gnx); for (i = 0; i < gnx; i++) { copy_rvec(x[index[i]], xi[nfr][i]); } reset_x(gnx, NULL, gnx, NULL, xi[nfr], w_rls); nfr++; if (nfr % 100 == 0) { srenew(ti, nfr+100); srenew(xi, nfr+100); } } nfr_all++; } while (read_next_x(oenv, status, &ti[nfr], x, box)); close_trj(status); sfree(x); gmx_rmpbc_done(gpbc); snew(srmsd, nfr); for (i = 0; i < nfr; i++) { printf("\rProcessing frame %d of %d", i, nfr); for (j = i+1; j < nfr; j++) { calc_fit_R(nfitdim, gnx, w_rls, xi[i], xi[j], R); msd = 0; for (a = 0; a < gnx; a++) { for (r = 0; r < DIM; r++) { xf = 0; for (c = 0; c < DIM; c++) { xf += R[r][c]*xi[j][a][c]; } msd += w_rls[a]*sqr(xi[i][a][r] - xf); } } msd /= tot_mass; srmsd[i] += sqrt(msd); srmsd[j] += sqrt(msd); } sfree(xi[i]); } printf("\n"); sfree(w_rls); min_srmsd = GMX_REAL_MAX; min_fr = -1; min_t = -1; srmsd_tot = 0; for (i = 0; i < nfr; i++) { srmsd[i] /= (nfr - 1); if (srmsd[i] < min_srmsd) { min_srmsd = srmsd[i]; min_fr = i; min_t = ti[i]; } srmsd_tot += srmsd[i]; } sfree(srmsd); printf("Average RMSD between all structures: %.3f\n", srmsd_tot/nfr); printf("Structure with lowest RMSD to all others: time %g, av. RMSD %.3f\n", min_t, min_srmsd); for (a = 0; a < gnx; a++) { copy_rvec(xi[min_fr][a], x_ref[index[a]]); } sfree(xi); }
int gmx_dist(int argc,char *argv[]) { const char *desc[] = { "[TT]g_dist[tt] can calculate the distance between the centers of mass of two", "groups of atoms as a function of time. The total distance and its", "[IT]x[it]-, [IT]y[it]-, and [IT]z[it]-components are plotted.[PAR]", "Or when [TT]-dist[tt] is set, print all the atoms in group 2 that are", "closer than a certain distance to the center of mass of group 1.[PAR]", "With options [TT]-lt[tt] and [TT]-dist[tt] the number of contacts", "of all atoms in group 2 that are closer than a certain distance", "to the center of mass of group 1 are plotted as a function of the time", "that the contact was continuously present.[PAR]", "Other programs that calculate distances are [TT]g_mindist[tt]", "and [TT]g_bond[tt]." }; t_topology *top=NULL; int ePBC; real t,t0,cut2,dist2; rvec *x=NULL,*v=NULL,dx; matrix box; t_trxstatus *status; int natoms; int g,d,i,j,res,teller=0; atom_id aid; int ngrps; /* the number of index groups */ atom_id **index,max; /* the index for the atom numbers */ int *isize; /* the size of each group */ char **grpname; /* the name of each group */ rvec *com; real *mass; FILE *fp=NULL,*fplt=NULL; gmx_bool bCutoff,bPrintDist,bLifeTime; t_pbc *pbc; int *contact_time=NULL,*ccount=NULL,ccount_nalloc=0,sum; char buf[STRLEN]; output_env_t oenv; gmx_rmpbc_t gpbc=NULL; const char *leg[4] = { "|d|","d\\sx\\N","d\\sy\\N","d\\sz\\N" }; static real cut=0; static t_pargs pa[] = { { "-dist", FALSE, etREAL, {&cut}, "Print all atoms in group 2 closer than dist to the center of mass of group 1" } }; #define NPA asize(pa) t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPX, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "dist", ffOPTWR }, { efXVG, "-lt", "lifetime", ffOPTWR }, }; #define NFILE asize(fnm) CopyRight(stderr,argv[0]); parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE, NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL,&oenv); bCutoff = opt2parg_bSet("-dist",NPA,pa); cut2 = cut*cut; bLifeTime = opt2bSet("-lt",NFILE,fnm); bPrintDist = (bCutoff && !bLifeTime); top=read_top(ftp2fn(efTPX,NFILE,fnm),&ePBC); /* read index files */ ngrps = 2; snew(com,ngrps); snew(grpname,ngrps); snew(index,ngrps); snew(isize,ngrps); get_index(&top->atoms,ftp2fn(efNDX,NFILE,fnm),ngrps,isize,index,grpname); /* calculate mass */ max=0; snew(mass,ngrps); for(g=0;(g<ngrps);g++) { mass[g]=0; for(i=0;(i<isize[g]);i++) { if (index[g][i]>max) max=index[g][i]; if (index[g][i] >= top->atoms.nr) gmx_fatal(FARGS,"Atom number %d, item %d of group %d, is larger than number of atoms in the topolgy (%d)\n",index[g][i]+1,i+1,g+1,top->atoms.nr+1); mass[g]+=top->atoms.atom[index[g][i]].m; } } natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); t0 = t; if (max>=natoms) gmx_fatal(FARGS,"Atom number %d in an index group is larger than number of atoms in the trajectory (%d)\n",(int)max+1,natoms); if (!bCutoff) { /* open output file */ fp = xvgropen(ftp2fn(efXVG,NFILE,fnm), "Distance","Time (ps)","Distance (nm)",oenv); xvgr_legend(fp,4,leg,oenv); } else { ngrps = 1; if (bLifeTime) snew(contact_time,isize[1]); } if (ePBC != epbcNONE) snew(pbc,1); else pbc = NULL; gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box); do { /* initialisation for correct distance calculations */ if (pbc) { set_pbc(pbc,ePBC,box); /* make molecules whole again */ gmx_rmpbc(gpbc,natoms,box,x); } /* calculate center of masses */ for(g=0;(g<ngrps);g++) { if (isize[g] == 1) { copy_rvec(x[index[g][0]],com[g]); } else { for(d=0;(d<DIM);d++) { com[g][d]=0; for(i=0;(i<isize[g]);i++) { com[g][d] += x[index[g][i]][d] * top->atoms.atom[index[g][i]].m; } com[g][d] /= mass[g]; } } } if (!bCutoff) { /* write to output */ fprintf(fp,"%12.7f ",t); for(g=0;(g<ngrps/2);g++) { if (pbc) pbc_dx(pbc,com[2*g],com[2*g+1],dx); else rvec_sub(com[2*g],com[2*g+1],dx); fprintf(fp,"%12.7f %12.7f %12.7f %12.7f", norm(dx),dx[XX],dx[YY],dx[ZZ]); } fprintf(fp,"\n"); } else { for(i=0;(i<isize[1]);i++) { j=index[1][i]; if (pbc) pbc_dx(pbc,x[j],com[0],dx); else rvec_sub(x[j],com[0],dx); dist2 = norm2(dx); if (dist2<cut2) { if (bPrintDist) { res=top->atoms.atom[j].resind; fprintf(stdout,"\rt: %g %d %s %d %s %g (nm)\n", t,top->atoms.resinfo[res].nr,*top->atoms.resinfo[res].name, j+1,*top->atoms.atomname[j],sqrt(dist2)); } if (bLifeTime) contact_time[i]++; } else { if (bLifeTime) { if (contact_time[i]) { add_contact_time(&ccount,&ccount_nalloc,contact_time[i]-1); contact_time[i] = 0; } } } } } teller++; } while (read_next_x(oenv,status,&t,natoms,x,box)); gmx_rmpbc_done(gpbc); if (!bCutoff) ffclose(fp); close_trj(status); if (bCutoff && bLifeTime) { /* Add the contacts still present in the last frame */ for(i=0; i<isize[1]; i++) if (contact_time[i]) add_contact_time(&ccount,&ccount_nalloc,contact_time[i]-1); sprintf(buf,"%s - %s within %g nm", grpname[0],grpname[1],cut); fp = xvgropen(opt2fn("-lt",NFILE,fnm), buf,"Time (ps)","Number of contacts",oenv); for(i=0; i<min(ccount_nalloc,teller-1); i++) { /* Account for all subintervals of longer intervals */ sum = 0; for(j=i; j<ccount_nalloc; j++) sum += (j-i+1)*ccount[j]; fprintf(fp,"%10.3f %10.3f\n",i*(t-t0)/(teller-1),sum/(double)(teller-i)); } ffclose(fp); } thanx(stderr); return 0; }
static void density_in_time (const char *fn, atom_id **index, int gnx[], real bw, real bwz, int nsttblock, real *****Densdevel, int *xslices, int *yslices, int *zslices, int *tblock, t_topology *top, int ePBC, int axis, gmx_bool bCenter, gmx_bool bps1d, const gmx_output_env_t *oenv) { /* * *****Densdevel pointer to array of density values in slices and frame-blocks Densdevel[*nsttblock][*xslices][*yslices][*zslices] * Densslice[x][y][z] * nsttblock - nr of frames in each time-block * bw widths of normal slices * * axis - axis direction (normal to slices) * nndx - number ot atoms in **index * grpn - group number in index */ t_trxstatus *status; gmx_rmpbc_t gpbc = NULL; matrix box; /* Box - 3x3 -each step*/ rvec *x0; /* List of Coord without PBC*/ int i, j, /* loop indices, checks etc*/ ax1 = 0, ax2 = 0, /* tangent directions */ framenr = 0, /* frame number in trajectory*/ slicex, slicey, slicez; /*slice # of x y z position */ real ***Densslice = NULL; /* Density-slice in one frame*/ real dscale; /*physical scaling factor*/ real t, x, y, z; /* time and coordinates*/ rvec bbww; *tblock = 0; /* blocknr in block average - initialise to 0*/ /* Axis: X=0, Y=1,Z=2 */ switch (axis) { case 0: ax1 = YY; ax2 = ZZ; /*Surface: YZ*/ break; case 1: ax1 = ZZ; ax2 = XX; /* Surface : XZ*/ break; case 2: ax1 = XX; ax2 = YY; /* Surface XY*/ break; default: gmx_fatal(FARGS, "Invalid axes. Terminating\n"); } if (read_first_x(oenv, &status, fn, &t, &x0, box) == 0) { gmx_fatal(FARGS, "Could not read coordinates from file"); /* Open trajectory for read*/ } *zslices = 1+static_cast<int>(std::floor(box[axis][axis]/bwz)); *yslices = 1+static_cast<int>(std::floor(box[ax2][ax2]/bw)); *xslices = 1+static_cast<int>(std::floor(box[ax1][ax1]/bw)); if (bps1d) { if (*xslices < *yslices) { *xslices = 1; } else { *yslices = 1; } } fprintf(stderr, "\nDividing the box in %5d x %5d x %5d slices with binw %f along axis %d\n", *xslices, *yslices, *zslices, bw, axis ); /****Start trajectory processing***/ /*Initialize Densdevel and PBC-remove*/ gpbc = gmx_rmpbc_init(&top->idef, ePBC, top->atoms.nr); *Densdevel = NULL; do { bbww[XX] = box[ax1][ax1]/ *xslices; bbww[YY] = box[ax2][ax2]/ *yslices; bbww[ZZ] = box[axis][axis]/ *zslices; gmx_rmpbc(gpbc, top->atoms.nr, box, x0); /*Reset Densslice every nsttblock steps*/ /* The first conditional is for clang to understand that this branch is * always taken the first time. */ if (Densslice == NULL || framenr % nsttblock == 0) { snew(Densslice, *xslices); for (i = 0; i < *xslices; i++) { snew(Densslice[i], *yslices); for (j = 0; j < *yslices; j++) { snew(Densslice[i][j], *zslices); } } /* Allocate Memory to extra frame in Densdevel - rather stupid approach: * A single frame each time, although only every nsttblock steps. */ srenew(*Densdevel, *tblock+1); (*Densdevel)[*tblock] = Densslice; } dscale = (*xslices)*(*yslices)*(*zslices)*AMU/ (box[ax1][ax1]*box[ax2][ax2]*box[axis][axis]*nsttblock*(NANO*NANO*NANO)); if (bCenter) { center_coords(&top->atoms, box, x0, axis); } for (j = 0; j < gnx[0]; j++) { /*Loop over all atoms in selected index*/ x = x0[index[0][j]][ax1]; y = x0[index[0][j]][ax2]; z = x0[index[0][j]][axis]; while (x < 0) { x += box[ax1][ax1]; } while (x > box[ax1][ax1]) { x -= box[ax1][ax1]; } while (y < 0) { y += box[ax2][ax2]; } while (y > box[ax2][ax2]) { y -= box[ax2][ax2]; } while (z < 0) { z += box[axis][axis]; } while (z > box[axis][axis]) { z -= box[axis][axis]; } slicex = static_cast<int>(x/bbww[XX]) % *xslices; slicey = static_cast<int>(y/bbww[YY]) % *yslices; slicez = static_cast<int>(z/bbww[ZZ]) % *zslices; Densslice[slicex][slicey][slicez] += (top->atoms.atom[index[0][j]].m*dscale); } framenr++; if (framenr % nsttblock == 0) { /*Implicit incrementation of Densdevel via renewal of Densslice*/ /*only every nsttblock steps*/ (*tblock)++; } } while (read_next_x(oenv, status, &t, x0, box)); /*Free memory we no longer need and exit.*/ gmx_rmpbc_done(gpbc); close_trj(status); if (0) { FILE *fp; fp = fopen("koko.xvg", "w"); for (j = 0; (j < *zslices); j++) { fprintf(fp, "%5d", j); for (i = 0; (i < *tblock); i++) { fprintf(fp, " %10g", (*Densdevel)[i][9][1][j]); } fprintf(fp, "\n"); } fclose(fp); } }
static void project(const char *trajfile,t_topology *top,int ePBC,matrix topbox, const char *projfile,const char *twodplotfile, const char *threedplotfile, const char *filterfile,int skip, const char *extremefile,gmx_bool bExtrAll,real extreme, int nextr, t_atoms *atoms,int natoms,atom_id *index, gmx_bool bFit,rvec *xref,int nfit,atom_id *ifit,real *w_rls, real *sqrtm,rvec *xav, int *eignr,rvec **eigvec, int noutvec,int *outvec, gmx_bool bSplit, const output_env_t oenv) { FILE *xvgrout=NULL; int nat,i,j,d,v,vec,nfr,nframes=0,snew_size,frame; t_trxstatus *out=NULL; t_trxstatus *status; int noutvec_extr,imin,imax; real *pmin,*pmax; atom_id *all_at; matrix box; rvec *xread,*x; real t,inp,**inprod=NULL,min=0,max=0; char str[STRLEN],str2[STRLEN],**ylabel,*c; real fact; gmx_rmpbc_t gpbc=NULL; snew(x,natoms); if (bExtrAll) noutvec_extr=noutvec; else noutvec_extr=1; if (trajfile) { snew(inprod,noutvec+1); if (filterfile) { fprintf(stderr,"Writing a filtered trajectory to %s using eigenvectors\n", filterfile); for(i=0; i<noutvec; i++) fprintf(stderr,"%d ",outvec[i]+1); fprintf(stderr,"\n"); out=open_trx(filterfile,"w"); } snew_size=0; nfr=0; nframes=0; nat=read_first_x(oenv,&status,trajfile,&t,&xread,box); if (nat>atoms->nr) gmx_fatal(FARGS,"the number of atoms in your trajectory (%d) is larger than the number of atoms in your structure file (%d)",nat,atoms->nr); snew(all_at,nat); if (top) gpbc = gmx_rmpbc_init(&top->idef,ePBC,nat,box); for(i=0; i<nat; i++) all_at[i]=i; do { if (nfr % skip == 0) { if (top) gmx_rmpbc(gpbc,nat,box,xread); if (nframes>=snew_size) { snew_size+=100; for(i=0; i<noutvec+1; i++) srenew(inprod[i],snew_size); } inprod[noutvec][nframes]=t; /* calculate x: a fitted struture of the selected atoms */ if (bFit) { reset_x(nfit,ifit,nat,NULL,xread,w_rls); do_fit(nat,w_rls,xref,xread); } for (i=0; i<natoms; i++) copy_rvec(xread[index[i]],x[i]); for(v=0; v<noutvec; v++) { vec=outvec[v]; /* calculate (mass-weighted) projection */ inp=0; for (i=0; i<natoms; i++) { inp+=(eigvec[vec][i][0]*(x[i][0]-xav[i][0])+ eigvec[vec][i][1]*(x[i][1]-xav[i][1])+ eigvec[vec][i][2]*(x[i][2]-xav[i][2]))*sqrtm[i]; } inprod[v][nframes]=inp; } if (filterfile) { for(i=0; i<natoms; i++) for(d=0; d<DIM; d++) { /* misuse xread for output */ xread[index[i]][d] = xav[i][d]; for(v=0; v<noutvec; v++) xread[index[i]][d] += inprod[v][nframes]*eigvec[outvec[v]][i][d]/sqrtm[i]; } write_trx(out,natoms,index,atoms,0,t,box,xread,NULL,NULL); } nframes++; } nfr++; } while (read_next_x(oenv,status,&t,nat,xread,box)); close_trx(status); sfree(x); if (filterfile) close_trx(out); } else snew(xread,atoms->nr); if (top) gmx_rmpbc_done(gpbc); if (projfile) { snew(ylabel,noutvec); for(v=0; v<noutvec; v++) { sprintf(str,"vec %d",eignr[outvec[v]]+1); ylabel[v]=strdup(str); } sprintf(str,"projection on eigenvectors (%s)",proj_unit); write_xvgr_graphs(projfile, noutvec, 1, str, NULL, output_env_get_xvgr_tlabel(oenv), (const char **)ylabel, nframes, inprod[noutvec], inprod, NULL, output_env_get_time_factor(oenv), FALSE, bSplit,oenv); } if (twodplotfile) { sprintf(str,"projection on eigenvector %d (%s)", eignr[outvec[0]]+1,proj_unit); sprintf(str2,"projection on eigenvector %d (%s)", eignr[outvec[noutvec-1]]+1,proj_unit); xvgrout=xvgropen(twodplotfile,"2D projection of trajectory",str,str2, oenv); for(i=0; i<nframes; i++) { if ( bSplit && i>0 && abs(inprod[noutvec][i])<1e-5 ) fprintf(xvgrout,"&\n"); fprintf(xvgrout,"%10.5f %10.5f\n",inprod[0][i],inprod[noutvec-1][i]); } ffclose(xvgrout); } if (threedplotfile) { t_atoms atoms; rvec *x; real *b=NULL; matrix box; char *resnm,*atnm, pdbform[STRLEN]; gmx_bool bPDB, b4D; FILE *out; if (noutvec < 3) gmx_fatal(FARGS,"You have selected less than 3 eigenvectors"); /* initialize */ bPDB = fn2ftp(threedplotfile)==efPDB; clear_mat(box); box[XX][XX] = box[YY][YY] = box[ZZ][ZZ] = 1; b4D = bPDB && (noutvec >= 4); if (b4D) { fprintf(stderr, "You have selected four or more eigenvectors:\n" "fourth eigenvector will be plotted " "in bfactor field of pdb file\n"); sprintf(str,"4D proj. of traj. on eigenv. %d, %d, %d and %d", eignr[outvec[0]]+1,eignr[outvec[1]]+1, eignr[outvec[2]]+1,eignr[outvec[3]]+1); } else { sprintf(str,"3D proj. of traj. on eigenv. %d, %d and %d", eignr[outvec[0]]+1,eignr[outvec[1]]+1,eignr[outvec[2]]+1); } init_t_atoms(&atoms,nframes,FALSE); snew(x,nframes); snew(b,nframes); atnm=strdup("C"); resnm=strdup("PRJ"); if(nframes>10000) fact=10000.0/nframes; else fact=1.0; for(i=0; i<nframes; i++) { atoms.atomname[i] = &atnm; atoms.atom[i].resind = i; atoms.resinfo[i].name = &resnm; atoms.resinfo[i].nr = ceil(i*fact); atoms.resinfo[i].ic = ' '; x[i][XX]=inprod[0][i]; x[i][YY]=inprod[1][i]; x[i][ZZ]=inprod[2][i]; if (b4D) b[i] =inprod[3][i]; } if ( ( b4D || bSplit ) && bPDB ) { strcpy(pdbform,get_pdbformat()); strcat(pdbform,"%8.4f%8.4f\n"); out=ffopen(threedplotfile,"w"); fprintf(out,"HEADER %s\n",str); if ( b4D ) fprintf(out,"REMARK %s\n","fourth dimension plotted as B-factor"); j=0; for(i=0; i<atoms.nr; i++) { if ( j>0 && bSplit && abs(inprod[noutvec][i])<1e-5 ) { fprintf(out,"TER\n"); j=0; } fprintf(out,pdbform,"ATOM",i+1,"C","PRJ",' ',j+1, PR_VEC(10*x[i]), 1.0, 10*b[i]); if (j>0) fprintf(out,"CONECT%5d%5d\n", i, i+1); j++; } fprintf(out,"TER\n"); ffclose(out); } else write_sto_conf(threedplotfile,str,&atoms,x,NULL,ePBC,box); free_t_atoms(&atoms,FALSE); } if (extremefile) { snew(pmin,noutvec_extr); snew(pmax,noutvec_extr); if (extreme==0) { fprintf(stderr,"%11s %17s %17s\n","eigenvector","Minimum","Maximum"); fprintf(stderr, "%11s %10s %10s %10s %10s\n","","value","frame","value","frame"); imin = 0; imax = 0; for(v=0; v<noutvec_extr; v++) { for(i=0; i<nframes; i++) { if (inprod[v][i]<inprod[v][imin]) imin = i; if (inprod[v][i]>inprod[v][imax]) imax = i; } pmin[v] = inprod[v][imin]; pmax[v] = inprod[v][imax]; fprintf(stderr,"%7d %10.6f %10d %10.6f %10d\n", eignr[outvec[v]]+1, pmin[v],imin,pmax[v],imax); } } else { pmin[0] = -extreme; pmax[0] = extreme; } /* build format string for filename: */ strcpy(str,extremefile);/* copy filename */ c=strrchr(str,'.'); /* find where extention begins */ strcpy(str2,c); /* get extention */ sprintf(c,"%%d%s",str2); /* append '%s' and extention to filename */ for(v=0; v<noutvec_extr; v++) { /* make filename using format string */ if (noutvec_extr==1) strcpy(str2,extremefile); else sprintf(str2,str,eignr[outvec[v]]+1); fprintf(stderr,"Writing %d frames along eigenvector %d to %s\n", nextr,outvec[v]+1,str2); out=open_trx(str2,"w"); for(frame=0; frame<nextr; frame++) { if ((extreme==0) && (nextr<=3)) for(i=0; i<natoms; i++) { atoms->resinfo[atoms->atom[index[i]].resind].chainid = 'A' + frame; } for(i=0; i<natoms; i++) for(d=0; d<DIM; d++) xread[index[i]][d] = (xav[i][d] + (pmin[v]*(nextr-frame-1)+pmax[v]*frame)/(nextr-1) *eigvec[outvec[v]][i][d]/sqrtm[i]); write_trx(out,natoms,index,atoms,0,frame,topbox,xread,NULL,NULL); } close_trx(out); } sfree(pmin); sfree(pmax); } fprintf(stderr,"\n"); }
int gmx_do_dssp(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] ", "reads a trajectory file and computes the secondary structure for", "each time frame ", "calling the dssp program. If you do not have the dssp program,", "get it from http://swift.cmbi.ru.nl/gv/dssp. [THISMODULE] assumes ", "that the dssp executable is located in ", "[TT]/usr/local/bin/dssp[tt]. If this is not the case, then you should", "set an environment variable [TT]DSSP[tt] pointing to the dssp", "executable, e.g.: [PAR]", "[TT]setenv DSSP /opt/dssp/bin/dssp[tt][PAR]", "Since version 2.0.0, dssp is invoked with a syntax that differs", "from earlier versions. If you have an older version of dssp,", "use the [TT]-ver[tt] option to direct do_dssp to use the older syntax.", "By default, do_dssp uses the syntax introduced with version 2.0.0.", "Even newer versions (which at the time of writing are not yet released)", "are assumed to have the same syntax as 2.0.0.[PAR]", "The structure assignment for each residue and time is written to an", "[TT].xpm[tt] matrix file. This file can be visualized with for instance", "[TT]xv[tt] and can be converted to postscript with [TT]xpm2ps[tt].", "Individual chains are separated by light grey lines in the [TT].xpm[tt] and", "postscript files.", "The number of residues with each secondary structure type and the", "total secondary structure ([TT]-sss[tt]) count as a function of", "time are also written to file ([TT]-sc[tt]).[PAR]", "Solvent accessible surface (SAS) per residue can be calculated, both in", "absolute values (A^2) and in fractions of the maximal accessible", "surface of a residue. The maximal accessible surface is defined as", "the accessible surface of a residue in a chain of glycines.", "[BB]Note[bb] that the program [gmx-sas] can also compute SAS", "and that is more efficient.[PAR]", "Finally, this program can dump the secondary structure in a special file", "[TT]ssdump.dat[tt] for usage in the program [gmx-chi]. Together", "these two programs can be used to analyze dihedral properties as a", "function of secondary structure type." }; static gmx_bool bVerbose; static const char *ss_string = "HEBT"; static int dsspVersion = 2; t_pargs pa[] = { { "-v", FALSE, etBOOL, {&bVerbose}, "HIDDENGenerate miles of useless information" }, { "-sss", FALSE, etSTR, {&ss_string}, "Secondary structures for structure count"}, { "-ver", FALSE, etINT, {&dsspVersion}, "DSSP major version. Syntax changed with version 2"} }; t_trxstatus *status; FILE *tapein; FILE *ss, *acc, *fTArea, *tmpf; const char *fnSCount, *fnArea, *fnTArea, *fnAArea; const char *leg[] = { "Phobic", "Phylic" }; t_topology top; int ePBC; t_atoms *atoms; t_matrix mat; int nres, nr0, naccr, nres_plus_separators; gmx_bool *bPhbres, bDoAccSurf; real t; int i, j, natoms, nframe = 0; matrix box = {{0}}; int gnx; char *grpnm, *ss_str; atom_id *index; rvec *xp, *x; int *average_area; real **accr, *accr_ptr = NULL, *av_area, *norm_av_area; char pdbfile[32], tmpfile[32], title[256]; char dssp[256]; const char *dptr; output_env_t oenv; gmx_rmpbc_t gpbc = NULL; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efDAT, "-ssdump", "ssdump", ffOPTWR }, { efMAP, "-map", "ss", ffLIBRD }, { efXPM, "-o", "ss", ffWRITE }, { efXVG, "-sc", "scount", ffWRITE }, { efXPM, "-a", "area", ffOPTWR }, { efXVG, "-ta", "totarea", ffOPTWR }, { efXVG, "-aa", "averarea", ffOPTWR } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW | PCA_TIME_UNIT, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } fnSCount = opt2fn("-sc", NFILE, fnm); fnArea = opt2fn_null("-a", NFILE, fnm); fnTArea = opt2fn_null("-ta", NFILE, fnm); fnAArea = opt2fn_null("-aa", NFILE, fnm); bDoAccSurf = (fnArea || fnTArea || fnAArea); read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &xp, NULL, box, FALSE); atoms = &(top.atoms); check_oo(atoms); bPhbres = bPhobics(atoms); get_index(atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &gnx, &index, &grpnm); nres = 0; nr0 = -1; for (i = 0; (i < gnx); i++) { if (atoms->atom[index[i]].resind != nr0) { nr0 = atoms->atom[index[i]].resind; nres++; } } fprintf(stderr, "There are %d residues in your selected group\n", nres); strcpy(pdbfile, "ddXXXXXX"); gmx_tmpnam(pdbfile); if ((tmpf = fopen(pdbfile, "w")) == NULL) { sprintf(pdbfile, "%ctmp%cfilterXXXXXX", DIR_SEPARATOR, DIR_SEPARATOR); gmx_tmpnam(pdbfile); if ((tmpf = fopen(pdbfile, "w")) == NULL) { gmx_fatal(FARGS, "Can not open tmp file %s", pdbfile); } } else { fclose(tmpf); } strcpy(tmpfile, "ddXXXXXX"); gmx_tmpnam(tmpfile); if ((tmpf = fopen(tmpfile, "w")) == NULL) { sprintf(tmpfile, "%ctmp%cfilterXXXXXX", DIR_SEPARATOR, DIR_SEPARATOR); gmx_tmpnam(tmpfile); if ((tmpf = fopen(tmpfile, "w")) == NULL) { gmx_fatal(FARGS, "Can not open tmp file %s", tmpfile); } } else { fclose(tmpf); } if ((dptr = getenv("DSSP")) == NULL) { dptr = "/usr/local/bin/dssp"; } if (!gmx_fexist(dptr)) { gmx_fatal(FARGS, "DSSP executable (%s) does not exist (use setenv DSSP)", dptr); } if (dsspVersion >= 2) { if (dsspVersion > 2) { printf("\nWARNING: You use DSSP version %d, which is not explicitly\nsupported by do_dssp. Assuming version 2 syntax.\n\n", dsspVersion); } sprintf(dssp, "%s -i %s -o %s > /dev/null %s", dptr, pdbfile, tmpfile, bVerbose ? "" : "2> /dev/null"); } else { sprintf(dssp, "%s %s %s %s > /dev/null %s", dptr, bDoAccSurf ? "" : "-na", pdbfile, tmpfile, bVerbose ? "" : "2> /dev/null"); } fprintf(stderr, "dssp cmd='%s'\n", dssp); if (fnTArea) { fTArea = xvgropen(fnTArea, "Solvent Accessible Surface Area", output_env_get_xvgr_tlabel(oenv), "Area (nm\\S2\\N)", oenv); xvgr_legend(fTArea, 2, leg, oenv); } else { fTArea = NULL; } mat.map = NULL; mat.nmap = readcmap(opt2fn("-map", NFILE, fnm), &(mat.map)); natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); if (natoms > atoms->nr) { gmx_fatal(FARGS, "\nTrajectory does not match topology!"); } if (gnx > natoms) { gmx_fatal(FARGS, "\nTrajectory does not match selected group!"); } snew(average_area, atoms->nres); snew(av_area, atoms->nres); snew(norm_av_area, atoms->nres); accr = NULL; naccr = 0; gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms); do { t = output_env_conv_time(oenv, t); if (bDoAccSurf && nframe >= naccr) { naccr += 10; srenew(accr, naccr); for (i = naccr-10; i < naccr; i++) { snew(accr[i], 2*atoms->nres-1); } } gmx_rmpbc(gpbc, natoms, box, x); tapein = gmx_ffopen(pdbfile, "w"); write_pdbfile_indexed(tapein, NULL, atoms, x, ePBC, box, ' ', -1, gnx, index, NULL, TRUE); gmx_ffclose(tapein); if (0 != system(dssp)) { gmx_fatal(FARGS, "Failed to execute command: %s\n", "Try specifying your dssp version with the -ver option.", dssp); } /* strip_dssp returns the number of lines found in the dssp file, i.e. * the number of residues plus the separator lines */ if (bDoAccSurf) { accr_ptr = accr[nframe]; } nres_plus_separators = strip_dssp(tmpfile, nres, bPhbres, t, accr_ptr, fTArea, &mat, average_area, oenv); remove(tmpfile); remove(pdbfile); nframe++; } while (read_next_x(oenv, status, &t, x, box)); fprintf(stderr, "\n"); close_trj(status); if (fTArea) { xvgrclose(fTArea); } gmx_rmpbc_done(gpbc); prune_ss_legend(&mat); ss = opt2FILE("-o", NFILE, fnm, "w"); mat.flags = 0; write_xpm_m(ss, mat); gmx_ffclose(ss); if (opt2bSet("-ssdump", NFILE, fnm)) { ss = opt2FILE("-ssdump", NFILE, fnm, "w"); snew(ss_str, nres+1); fprintf(ss, "%d\n", nres); for (j = 0; j < mat.nx; j++) { for (i = 0; (i < mat.ny); i++) { ss_str[i] = mat.map[mat.matrix[j][i]].code.c1; } ss_str[i] = '\0'; fprintf(ss, "%s\n", ss_str); } gmx_ffclose(ss); sfree(ss_str); } analyse_ss(fnSCount, &mat, ss_string, oenv); if (bDoAccSurf) { write_sas_mat(fnArea, accr, nframe, nres_plus_separators, &mat); for (i = 0; i < atoms->nres; i++) { av_area[i] = (average_area[i] / (real)nframe); } norm_acc(atoms, nres, av_area, norm_av_area); if (fnAArea) { acc = xvgropen(fnAArea, "Average Accessible Area", "Residue", "A\\S2", oenv); for (i = 0; (i < nres); i++) { fprintf(acc, "%5d %10g %10g\n", i+1, av_area[i], norm_av_area[i]); } xvgrclose(acc); } } view_all(oenv, NFILE, fnm); return 0; }
int gmx_covar(int argc,char *argv[]) { const char *desc[] = { "[TT]g_covar[tt] calculates and diagonalizes the (mass-weighted)", "covariance matrix.", "All structures are fitted to the structure in the structure file.", "When this is not a run input file periodicity will not be taken into", "account. When the fit and analysis groups are identical and the analysis", "is non mass-weighted, the fit will also be non mass-weighted.", "[PAR]", "The eigenvectors are written to a trajectory file ([TT]-v[tt]).", "When the same atoms are used for the fit and the covariance analysis,", "the reference structure for the fit is written first with t=-1.", "The average (or reference when [TT]-ref[tt] is used) structure is", "written with t=0, the eigenvectors", "are written as frames with the eigenvector number as timestamp.", "[PAR]", "The eigenvectors can be analyzed with [TT]g_anaeig[tt].", "[PAR]", "Option [TT]-ascii[tt] writes the whole covariance matrix to", "an ASCII file. The order of the elements is: x1x1, x1y1, x1z1, x1x2, ...", "[PAR]", "Option [TT]-xpm[tt] writes the whole covariance matrix to an [TT].xpm[tt] file.", "[PAR]", "Option [TT]-xpma[tt] writes the atomic covariance matrix to an [TT].xpm[tt] file,", "i.e. for each atom pair the sum of the xx, yy and zz covariances is", "written.", "[PAR]", "Note that the diagonalization of a matrix requires memory and time", "that will increase at least as fast as than the square of the number", "of atoms involved. It is easy to run out of memory, in which", "case this tool will probably exit with a 'Segmentation fault'. You", "should consider carefully whether a reduced set of atoms will meet", "your needs for lower costs." }; static gmx_bool bFit=TRUE,bRef=FALSE,bM=FALSE,bPBC=TRUE; static int end=-1; t_pargs pa[] = { { "-fit", FALSE, etBOOL, {&bFit}, "Fit to a reference structure"}, { "-ref", FALSE, etBOOL, {&bRef}, "Use the deviation from the conformation in the structure file instead of from the average" }, { "-mwa", FALSE, etBOOL, {&bM}, "Mass-weighted covariance analysis"}, { "-last", FALSE, etINT, {&end}, "Last eigenvector to write away (-1 is till the last)" }, { "-pbc", FALSE, etBOOL, {&bPBC}, "Apply corrections for periodic boundary conditions" } }; FILE *out; t_trxstatus *status; t_trxstatus *trjout; t_topology top; int ePBC; t_atoms *atoms; rvec *x,*xread,*xref,*xav,*xproj; matrix box,zerobox; real *sqrtm,*mat,*eigval,sum,trace,inv_nframes; real t,tstart,tend,**mat2; real xj,*w_rls=NULL; real min,max,*axis; int ntopatoms,step; int natoms,nat,count,nframes0,nframes,nlevels; gmx_large_int_t ndim,i,j,k,l; int WriteXref; const char *fitfile,*trxfile,*ndxfile; const char *eigvalfile,*eigvecfile,*averfile,*logfile; const char *asciifile,*xpmfile,*xpmafile; char str[STRLEN],*fitname,*ananame,*pcwd; int d,dj,nfit; atom_id *index,*ifit; gmx_bool bDiffMass1,bDiffMass2; time_t now; char timebuf[STRLEN]; t_rgb rlo,rmi,rhi; real *tmp; output_env_t oenv; gmx_rmpbc_t gpbc=NULL; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXVG, NULL, "eigenval", ffWRITE }, { efTRN, "-v", "eigenvec", ffWRITE }, { efSTO, "-av", "average.pdb", ffWRITE }, { efLOG, NULL, "covar", ffWRITE }, { efDAT, "-ascii","covar", ffOPTWR }, { efXPM, "-xpm","covar", ffOPTWR }, { efXPM, "-xpma","covara", 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); clear_mat(zerobox); fitfile = ftp2fn(efTPS,NFILE,fnm); trxfile = ftp2fn(efTRX,NFILE,fnm); ndxfile = ftp2fn_null(efNDX,NFILE,fnm); eigvalfile = ftp2fn(efXVG,NFILE,fnm); eigvecfile = ftp2fn(efTRN,NFILE,fnm); averfile = ftp2fn(efSTO,NFILE,fnm); logfile = ftp2fn(efLOG,NFILE,fnm); asciifile = opt2fn_null("-ascii",NFILE,fnm); xpmfile = opt2fn_null("-xpm",NFILE,fnm); xpmafile = opt2fn_null("-xpma",NFILE,fnm); read_tps_conf(fitfile,str,&top,&ePBC,&xref,NULL,box,TRUE); atoms=&top.atoms; if (bFit) { printf("\nChoose a group for the least squares fit\n"); get_index(atoms,ndxfile,1,&nfit,&ifit,&fitname); if (nfit < 3) gmx_fatal(FARGS,"Need >= 3 points to fit!\n"); } else nfit=0; printf("\nChoose a group for the covariance analysis\n"); get_index(atoms,ndxfile,1,&natoms,&index,&ananame); bDiffMass1=FALSE; if (bFit) { snew(w_rls,atoms->nr); for(i=0; (i<nfit); i++) { w_rls[ifit[i]]=atoms->atom[ifit[i]].m; if (i) bDiffMass1 = bDiffMass1 || (w_rls[ifit[i]]!=w_rls[ifit[i-1]]); } } bDiffMass2=FALSE; snew(sqrtm,natoms); for(i=0; (i<natoms); i++) if (bM) { sqrtm[i]=sqrt(atoms->atom[index[i]].m); if (i) bDiffMass2 = bDiffMass2 || (sqrtm[i]!=sqrtm[i-1]); } else sqrtm[i]=1.0; if (bFit && bDiffMass1 && !bDiffMass2) { bDiffMass1 = natoms != nfit; i=0; for (i=0; (i<natoms) && !bDiffMass1; i++) bDiffMass1 = index[i] != ifit[i]; if (!bDiffMass1) { fprintf(stderr,"\n" "Note: the fit and analysis group are identical,\n" " while the fit is mass weighted and the analysis is not.\n" " Making the fit non mass weighted.\n\n"); for(i=0; (i<nfit); i++) w_rls[ifit[i]]=1.0; } } /* Prepare reference frame */ if (bPBC) { gpbc = gmx_rmpbc_init(&top.idef,ePBC,atoms->nr,box); gmx_rmpbc(gpbc,atoms->nr,box,xref); } if (bFit) reset_x(nfit,ifit,atoms->nr,NULL,xref,w_rls); snew(x,natoms); snew(xav,natoms); ndim=natoms*DIM; if (sqrt(GMX_LARGE_INT_MAX)<ndim) { gmx_fatal(FARGS,"Number of degrees of freedoms to large for matrix.\n"); } snew(mat,ndim*ndim); fprintf(stderr,"Calculating the average structure ...\n"); nframes0 = 0; nat=read_first_x(oenv,&status,trxfile,&t,&xread,box); if (nat != atoms->nr) fprintf(stderr,"\nWARNING: number of atoms in tpx (%d) and trajectory (%d) do not match\n",natoms,nat); do { nframes0++; /* calculate x: a fitted struture of the selected atoms */ if (bPBC) gmx_rmpbc(gpbc,nat,box,xread); if (bFit) { reset_x(nfit,ifit,nat,NULL,xread,w_rls); do_fit(nat,w_rls,xref,xread); } for (i=0; i<natoms; i++) rvec_inc(xav[i],xread[index[i]]); } while (read_next_x(oenv,status,&t,nat,xread,box)); close_trj(status); inv_nframes = 1.0/nframes0; for(i=0; i<natoms; i++) for(d=0; d<DIM; d++) { xav[i][d] *= inv_nframes; xread[index[i]][d] = xav[i][d]; } write_sto_conf_indexed(opt2fn("-av",NFILE,fnm),"Average structure", atoms,xread,NULL,epbcNONE,zerobox,natoms,index); sfree(xread); fprintf(stderr,"Constructing covariance matrix (%dx%d) ...\n",(int)ndim,(int)ndim); nframes=0; nat=read_first_x(oenv,&status,trxfile,&t,&xread,box); tstart = t; do { nframes++; tend = t; /* calculate x: a (fitted) structure of the selected atoms */ if (bPBC) gmx_rmpbc(gpbc,nat,box,xread); if (bFit) { reset_x(nfit,ifit,nat,NULL,xread,w_rls); do_fit(nat,w_rls,xref,xread); } if (bRef) for (i=0; i<natoms; i++) rvec_sub(xread[index[i]],xref[index[i]],x[i]); else for (i=0; i<natoms; i++) rvec_sub(xread[index[i]],xav[i],x[i]); for (j=0; j<natoms; j++) { for (dj=0; dj<DIM; dj++) { k=ndim*(DIM*j+dj); xj=x[j][dj]; for (i=j; i<natoms; i++) { l=k+DIM*i; for(d=0; d<DIM; d++) mat[l+d] += x[i][d]*xj; } } } } while (read_next_x(oenv,status,&t,nat,xread,box) && (bRef || nframes < nframes0)); close_trj(status); gmx_rmpbc_done(gpbc); fprintf(stderr,"Read %d frames\n",nframes); if (bRef) { /* copy the reference structure to the ouput array x */ snew(xproj,natoms); for (i=0; i<natoms; i++) copy_rvec(xref[index[i]],xproj[i]); } else { xproj = xav; } /* correct the covariance matrix for the mass */ inv_nframes = 1.0/nframes; for (j=0; j<natoms; j++) for (dj=0; dj<DIM; dj++) for (i=j; i<natoms; i++) { k = ndim*(DIM*j+dj)+DIM*i; for (d=0; d<DIM; d++) mat[k+d] = mat[k+d]*inv_nframes*sqrtm[i]*sqrtm[j]; } /* symmetrize the matrix */ for (j=0; j<ndim; j++) for (i=j; i<ndim; i++) mat[ndim*i+j]=mat[ndim*j+i]; trace=0; for(i=0; i<ndim; i++) trace+=mat[i*ndim+i]; fprintf(stderr,"\nTrace of the covariance matrix: %g (%snm^2)\n", trace,bM ? "u " : ""); if (asciifile) { out = ffopen(asciifile,"w"); for (j=0; j<ndim; j++) { for (i=0; i<ndim; i+=3) fprintf(out,"%g %g %g\n", mat[ndim*j+i],mat[ndim*j+i+1],mat[ndim*j+i+2]); } ffclose(out); } if (xpmfile) { min = 0; max = 0; snew(mat2,ndim); for (j=0; j<ndim; j++) { mat2[j] = &(mat[ndim*j]); for (i=0; i<=j; i++) { if (mat2[j][i] < min) min = mat2[j][i]; if (mat2[j][j] > max) max = mat2[j][i]; } } snew(axis,ndim); for(i=0; i<ndim; i++) axis[i] = i+1; rlo.r = 0; rlo.g = 0; rlo.b = 1; rmi.r = 1; rmi.g = 1; rmi.b = 1; rhi.r = 1; rhi.g = 0; rhi.b = 0; out = ffopen(xpmfile,"w"); nlevels = 80; write_xpm3(out,0,"Covariance",bM ? "u nm^2" : "nm^2", "dim","dim",ndim,ndim,axis,axis, mat2,min,0.0,max,rlo,rmi,rhi,&nlevels); ffclose(out); sfree(axis); sfree(mat2); } if (xpmafile) { min = 0; max = 0; snew(mat2,ndim/DIM); for (i=0; i<ndim/DIM; i++) snew(mat2[i],ndim/DIM); for (j=0; j<ndim/DIM; j++) { for (i=0; i<=j; i++) { mat2[j][i] = 0; for(d=0; d<DIM; d++) mat2[j][i] += mat[ndim*(DIM*j+d)+DIM*i+d]; if (mat2[j][i] < min) min = mat2[j][i]; if (mat2[j][j] > max) max = mat2[j][i]; mat2[i][j] = mat2[j][i]; } } snew(axis,ndim/DIM); for(i=0; i<ndim/DIM; i++) axis[i] = i+1; rlo.r = 0; rlo.g = 0; rlo.b = 1; rmi.r = 1; rmi.g = 1; rmi.b = 1; rhi.r = 1; rhi.g = 0; rhi.b = 0; out = ffopen(xpmafile,"w"); nlevels = 80; write_xpm3(out,0,"Covariance",bM ? "u nm^2" : "nm^2", "atom","atom",ndim/DIM,ndim/DIM,axis,axis, mat2,min,0.0,max,rlo,rmi,rhi,&nlevels); ffclose(out); sfree(axis); for (i=0; i<ndim/DIM; i++) sfree(mat2[i]); sfree(mat2); } /* call diagonalization routine */ fprintf(stderr,"\nDiagonalizing ...\n"); fflush(stderr); snew(eigval,ndim); snew(tmp,ndim*ndim); memcpy(tmp,mat,ndim*ndim*sizeof(real)); eigensolver(tmp,ndim,0,ndim,eigval,mat); sfree(tmp); /* now write the output */ sum=0; for(i=0; i<ndim; i++) sum+=eigval[i]; fprintf(stderr,"\nSum of the eigenvalues: %g (%snm^2)\n", sum,bM ? "u " : ""); if (fabs(trace-sum)>0.01*trace) fprintf(stderr,"\nWARNING: eigenvalue sum deviates from the trace of the covariance matrix\n"); fprintf(stderr,"\nWriting eigenvalues to %s\n",eigvalfile); sprintf(str,"(%snm\\S2\\N)",bM ? "u " : ""); out=xvgropen(eigvalfile, "Eigenvalues of the covariance matrix", "Eigenvector index",str,oenv); for (i=0; (i<ndim); i++) fprintf (out,"%10d %g\n",(int)i+1,eigval[ndim-1-i]); ffclose(out); if (end==-1) { if (nframes-1 < ndim) end=nframes-1; else end=ndim; } if (bFit) { /* misuse lambda: 0/1 mass weighted analysis no/yes */ if (nfit==natoms) { WriteXref = eWXR_YES; for(i=0; i<nfit; i++) copy_rvec(xref[ifit[i]],x[i]); } else WriteXref = eWXR_NO; } else { /* misuse lambda: -1 for no fit */ WriteXref = eWXR_NOFIT; } write_eigenvectors(eigvecfile,natoms,mat,TRUE,1,end, WriteXref,x,bDiffMass1,xproj,bM,eigval); out = ffopen(logfile,"w"); time(&now); gmx_ctime_r(&now,timebuf,STRLEN); fprintf(out,"Covariance analysis log, written %s\n",timebuf); fprintf(out,"Program: %s\n",argv[0]); #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__) pcwd=_getcwd(str,STRLEN); #else pcwd=getcwd(str,STRLEN); #endif if(NULL==pcwd) { gmx_fatal(FARGS,"Current working directory is undefined"); } fprintf(out,"Working directory: %s\n\n",str); fprintf(out,"Read %d frames from %s (time %g to %g %s)\n",nframes,trxfile, output_env_conv_time(oenv,tstart),output_env_conv_time(oenv,tend),output_env_get_time_unit(oenv)); if (bFit) fprintf(out,"Read reference structure for fit from %s\n",fitfile); if (ndxfile) fprintf(out,"Read index groups from %s\n",ndxfile); fprintf(out,"\n"); fprintf(out,"Analysis group is '%s' (%d atoms)\n",ananame,natoms); if (bFit) fprintf(out,"Fit group is '%s' (%d atoms)\n",fitname,nfit); else fprintf(out,"No fit was used\n"); fprintf(out,"Analysis is %smass weighted\n", bDiffMass2 ? "":"non-"); if (bFit) fprintf(out,"Fit is %smass weighted\n", bDiffMass1 ? "":"non-"); fprintf(out,"Diagonalized the %dx%d covariance matrix\n",(int)ndim,(int)ndim); fprintf(out,"Trace of the covariance matrix before diagonalizing: %g\n", trace); fprintf(out,"Trace of the covariance matrix after diagonalizing: %g\n\n", sum); fprintf(out,"Wrote %d eigenvalues to %s\n",(int)ndim,eigvalfile); if (WriteXref == eWXR_YES) fprintf(out,"Wrote reference structure to %s\n",eigvecfile); fprintf(out,"Wrote average structure to %s and %s\n",averfile,eigvecfile); fprintf(out,"Wrote eigenvectors %d to %d to %s\n",1,end,eigvecfile); ffclose(out); fprintf(stderr,"Wrote the log to %s\n",logfile); thanx(stderr); return 0; }
int gmx_rotacf(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] calculates the rotational correlation function", "for molecules. Atom triplets (i,j,k) must be given in the index", "file, defining two vectors ij and jk. The rotational ACF", "is calculated as the autocorrelation function of the vector", "n = ij x jk, i.e. the cross product of the two vectors.", "Since three atoms span a plane, the order of the three atoms", "does not matter. Optionally, by invoking the [TT]-d[tt] switch, you can", "calculate the rotational correlation function for linear molecules", "by specifying atom pairs (i,j) in the index file.", "[PAR]", "EXAMPLES[PAR]", "[TT]gmx rotacf -P 1 -nparm 2 -fft -n index -o rotacf-x-P1", "-fa expfit-x-P1 -beginfit 2.5 -endfit 20.0[tt][PAR]", "This will calculate the rotational correlation function using a first", "order Legendre polynomial of the angle of a vector defined by the index", "file. The correlation function will be fitted from 2.5 ps until 20.0 ps", "to a two-parameter exponential." }; static gmx_bool bVec = FALSE, bAver = TRUE; t_pargs pa[] = { { "-d", FALSE, etBOOL, {&bVec}, "Use index doublets (vectors) for correlation function instead of triplets (planes)" }, { "-aver", FALSE, etBOOL, {&bAver}, "Average over molecules" } }; t_trxstatus *status; int isize; atom_id *index; char *grpname; rvec *x, *x_s; matrix box; real **c1; rvec xij, xjk, n; int i, m, teller, n_alloc, natoms, nvec, ai, aj, ak; unsigned long mode; real t, t0, t1, dt; gmx_rmpbc_t gpbc = NULL; t_topology *top; int ePBC; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPR, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffREAD }, { efXVG, "-o", "rotacf", ffWRITE } }; #define NFILE asize(fnm) int npargs; t_pargs *ppa; output_env_t oenv; npargs = asize(pa); ppa = add_acf_pargs(&npargs, pa); if (!parse_common_args(&argc, argv, PCA_CAN_VIEW | PCA_CAN_TIME, NFILE, fnm, npargs, ppa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname); if (bVec) { nvec = isize/2; } else { nvec = isize/3; } if (((isize % 3) != 0) && !bVec) { gmx_fatal(FARGS, "number of index elements not multiple of 3, " "these can not be atom triplets\n"); } if (((isize % 2) != 0) && bVec) { gmx_fatal(FARGS, "number of index elements not multiple of 2, " "these can not be atom doublets\n"); } top = read_top(ftp2fn(efTPR, NFILE, fnm), &ePBC); snew(c1, nvec); for (i = 0; (i < nvec); i++) { c1[i] = NULL; } n_alloc = 0; natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); snew(x_s, natoms); gpbc = gmx_rmpbc_init(&(top->idef), ePBC, natoms); /* Start the loop over frames */ t0 = t; teller = 0; do { if (teller >= n_alloc) { n_alloc += 100; for (i = 0; (i < nvec); i++) { srenew(c1[i], DIM*n_alloc); } } t1 = t; /* Remove periodicity */ gmx_rmpbc_copy(gpbc, natoms, box, x, x_s); /* Compute crossproducts for all vectors, if triplets. * else, just get the vectors in case of doublets. */ if (bVec == FALSE) { for (i = 0; (i < nvec); i++) { ai = index[3*i]; aj = index[3*i+1]; ak = index[3*i+2]; rvec_sub(x_s[ai], x_s[aj], xij); rvec_sub(x_s[aj], x_s[ak], xjk); cprod(xij, xjk, n); for (m = 0; (m < DIM); m++) { c1[i][DIM*teller+m] = n[m]; } } } else { for (i = 0; (i < nvec); i++) { ai = index[2*i]; aj = index[2*i+1]; rvec_sub(x_s[ai], x_s[aj], n); for (m = 0; (m < DIM); m++) { c1[i][DIM*teller+m] = n[m]; } } } /* Increment loop counter */ teller++; } while (read_next_x(oenv, status, &t, x, box)); close_trj(status); fprintf(stderr, "\nDone with trajectory\n"); gmx_rmpbc_done(gpbc); /* Autocorrelation function */ if (teller < 2) { fprintf(stderr, "Not enough frames for correlation function\n"); } else { dt = (t1 - t0)/(teller-1); mode = eacVector; do_autocorr(ftp2fn(efXVG, NFILE, fnm), oenv, "Rotational Correlation Function", teller, nvec, c1, dt, mode, bAver); } do_view(oenv, ftp2fn(efXVG, NFILE, fnm), NULL); return 0; }
int gmx_mdmat(int argc, char *argv[]) { const char *desc[] = { "[TT]g_mdmat[tt] makes distance matrices consisting of the smallest distance", "between residue pairs. With [TT]-frames[tt], these distance matrices can be", "stored in order to see differences in tertiary structure as a", "function of time. If you choose your options unwisely, this may generate", "a large output file. By default, only an averaged matrix over the whole", "trajectory is output.", "Also a count of the number of different atomic contacts between", "residues over the whole trajectory can be made.", "The output can be processed with [TT]xpm2ps[tt] to make a PostScript (tm) plot." }; static real truncate = 1.5; static gmx_bool bAtom = FALSE; static int nlevels = 40; t_pargs pa[] = { { "-t", FALSE, etREAL, {&truncate}, "trunc distance" }, { "-nlevels", FALSE, etINT, {&nlevels}, "Discretize distance in this number of levels" } }; t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efXPM, "-mean", "dm", ffWRITE }, { efXPM, "-frames", "dmf", ffOPTWR }, { efXVG, "-no", "num", ffOPTWR }, }; #define NFILE asize(fnm) FILE *out = NULL, *fp; t_topology top; int ePBC; t_atoms useatoms; int isize; atom_id *index; char *grpname; int *rndx, *natm, prevres, newres; int i, j, nres, natoms, nframes, it, trxnat; t_trxstatus *status; int nr0; gmx_bool bCalcN, bFrames; real t, ratio; char title[256], label[234]; t_rgb rlo, rhi; rvec *x; real **mdmat, *resnr, **totmdmat; int **nmat, **totnmat; real *mean_n; int *tot_n; matrix box; output_env_t oenv; gmx_rmpbc_t gpbc = NULL; CopyRight(stderr, argv[0]); parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_BE_NICE, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv); fprintf(stderr, "Will truncate at %f nm\n", truncate); bCalcN = opt2bSet("-no", NFILE, fnm); bFrames = opt2bSet("-frames", NFILE, fnm); if (bCalcN) { fprintf(stderr, "Will calculate number of different contacts\n"); } read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &x, NULL, box, FALSE); fprintf(stderr, "Select group for analysis\n"); get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpname); natoms = isize; snew(useatoms.atom, natoms); snew(useatoms.atomname, natoms); useatoms.nres = 0; snew(useatoms.resinfo, natoms); prevres = top.atoms.atom[index[0]].resind; newres = 0; for (i = 0; (i < isize); i++) { int ii = index[i]; useatoms.atomname[i] = top.atoms.atomname[ii]; if (top.atoms.atom[ii].resind != prevres) { prevres = top.atoms.atom[ii].resind; newres++; useatoms.resinfo[i] = top.atoms.resinfo[prevres]; if (debug) { fprintf(debug, "New residue: atom %5s %5s %6d, index entry %5d, newres %5d\n", *(top.atoms.resinfo[top.atoms.atom[ii].resind].name), *(top.atoms.atomname[ii]), ii, i, newres); } } useatoms.atom[i].resind = newres; } useatoms.nres = newres+1; useatoms.nr = isize; rndx = res_ndx(&(useatoms)); natm = res_natm(&(useatoms)); nres = useatoms.nres; fprintf(stderr, "There are %d residues with %d atoms\n", nres, natoms); snew(resnr, nres); snew(mdmat, nres); snew(nmat, nres); snew(totnmat, nres); snew(mean_n, nres); snew(tot_n, nres); for (i = 0; (i < nres); i++) { snew(mdmat[i], nres); snew(nmat[i], natoms); snew(totnmat[i], natoms); resnr[i] = i+1; } snew(totmdmat, nres); for (i = 0; (i < nres); i++) { snew(totmdmat[i], nres); } trxnat = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); nframes = 0; rlo.r = 1.0, rlo.g = 1.0, rlo.b = 1.0; rhi.r = 0.0, rhi.g = 0.0, rhi.b = 0.0; gpbc = gmx_rmpbc_init(&top.idef, ePBC, trxnat, box); if (bFrames) { out = opt2FILE("-frames", NFILE, fnm, "w"); } do { gmx_rmpbc(gpbc, trxnat, box, x); nframes++; calc_mat(nres, natoms, rndx, x, index, truncate, mdmat, nmat, ePBC, box); for (i = 0; (i < nres); i++) { for (j = 0; (j < natoms); j++) { if (nmat[i][j]) { totnmat[i][j]++; } } } for (i = 0; (i < nres); i++) { for (j = 0; (j < nres); j++) { totmdmat[i][j] += mdmat[i][j]; } } if (bFrames) { sprintf(label, "t=%.0f ps", t); write_xpm(out, 0, label, "Distance (nm)", "Residue Index", "Residue Index", nres, nres, resnr, resnr, mdmat, 0, truncate, rlo, rhi, &nlevels); } } while (read_next_x(oenv, status, &t, trxnat, x, box)); fprintf(stderr, "\n"); close_trj(status); gmx_rmpbc_done(gpbc); if (bFrames) { ffclose(out); } fprintf(stderr, "Processed %d frames\n", nframes); for (i = 0; (i < nres); i++) { for (j = 0; (j < nres); j++) { totmdmat[i][j] /= nframes; } } write_xpm(opt2FILE("-mean", NFILE, fnm, "w"), 0, "Mean smallest distance", "Distance (nm)", "Residue Index", "Residue Index", nres, nres, resnr, resnr, totmdmat, 0, truncate, rlo, rhi, &nlevels); if (bCalcN) { tot_nmat(nres, natoms, nframes, totnmat, tot_n, mean_n); fp = xvgropen(ftp2fn(efXVG, NFILE, fnm), "Increase in number of contacts", "Residue", "Ratio", oenv); fprintf(fp, "@ legend on\n"); fprintf(fp, "@ legend box on\n"); fprintf(fp, "@ legend loctype view\n"); fprintf(fp, "@ legend 0.75, 0.8\n"); fprintf(fp, "@ legend string 0 \"Total/mean\"\n"); fprintf(fp, "@ legend string 1 \"Total\"\n"); fprintf(fp, "@ legend string 2 \"Mean\"\n"); fprintf(fp, "@ legend string 3 \"# atoms\"\n"); fprintf(fp, "@ legend string 4 \"Mean/# atoms\"\n"); fprintf(fp, "#%3s %8s %3s %8s %3s %8s\n", "res", "ratio", "tot", "mean", "natm", "mean/atm"); for (i = 0; (i < nres); i++) { if (mean_n[i] == 0) { ratio = 1; } else { ratio = tot_n[i]/mean_n[i]; } fprintf(fp, "%3d %8.3f %3d %8.3f %3d %8.3f\n", i+1, ratio, tot_n[i], mean_n[i], natm[i], mean_n[i]/natm[i]); } ffclose(fp); } thanx(stderr); return 0; }
static void calc_tetra_order_parm(const char *fnNDX, const char *fnTPS, const char *fnTRX, const char *sgfn, const char *skfn, int nslice, int slice_dim, const char *sgslfn, const char *skslfn, const gmx_output_env_t *oenv) { FILE *fpsg = NULL, *fpsk = NULL; t_topology top; int ePBC; t_trxstatus *status; int natoms; real t; rvec *xtop, *x; matrix box; real sg, sk; atom_id **index; char **grpname; int i, *isize, ng, nframes; real *sg_slice, *sg_slice_tot, *sk_slice, *sk_slice_tot; gmx_rmpbc_t gpbc = NULL; read_tps_conf(fnTPS, &top, &ePBC, &xtop, NULL, box, FALSE); snew(sg_slice, nslice); snew(sk_slice, nslice); snew(sg_slice_tot, nslice); snew(sk_slice_tot, nslice); ng = 1; /* get index groups */ printf("Select the group that contains the atoms you want to use for the tetrahedrality order parameter calculation:\n"); snew(grpname, ng); snew(index, ng); snew(isize, ng); get_index(&top.atoms, fnNDX, ng, isize, index, grpname); /* Analyze trajectory */ natoms = read_first_x(oenv, &status, fnTRX, &t, &x, box); if (natoms > top.atoms.nr) { gmx_fatal(FARGS, "Topology (%d atoms) does not match trajectory (%d atoms)", top.atoms.nr, natoms); } check_index(NULL, ng, index[0], NULL, natoms); fpsg = xvgropen(sgfn, "S\\sg\\N Angle Order Parameter", "Time (ps)", "S\\sg\\N", oenv); fpsk = xvgropen(skfn, "S\\sk\\N Distance Order Parameter", "Time (ps)", "S\\sk\\N", oenv); /* loop over frames */ gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms); nframes = 0; do { find_nearest_neighbours(ePBC, natoms, box, x, isize[0], index[0], &sg, &sk, nslice, slice_dim, sg_slice, sk_slice, gpbc); for (i = 0; (i < nslice); i++) { sg_slice_tot[i] += sg_slice[i]; sk_slice_tot[i] += sk_slice[i]; } fprintf(fpsg, "%f %f\n", t, sg); fprintf(fpsk, "%f %f\n", t, sk); nframes++; } while (read_next_x(oenv, status, &t, x, box)); close_trj(status); gmx_rmpbc_done(gpbc); sfree(grpname); sfree(index); sfree(isize); xvgrclose(fpsg); xvgrclose(fpsk); fpsg = xvgropen(sgslfn, "S\\sg\\N Angle Order Parameter / Slab", "(nm)", "S\\sg\\N", oenv); fpsk = xvgropen(skslfn, "S\\sk\\N Distance Order Parameter / Slab", "(nm)", "S\\sk\\N", oenv); for (i = 0; (i < nslice); i++) { fprintf(fpsg, "%10g %10g\n", (i+0.5)*box[slice_dim][slice_dim]/nslice, sg_slice_tot[i]/nframes); fprintf(fpsk, "%10g %10g\n", (i+0.5)*box[slice_dim][slice_dim]/nslice, sk_slice_tot[i]/nframes); } xvgrclose(fpsg); xvgrclose(fpsk); }
int gmx_rmsf(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] computes the root mean square fluctuation (RMSF, i.e. standard ", "deviation) of atomic positions in the trajectory (supplied with [TT]-f[tt])", "after (optionally) fitting to a reference frame (supplied with [TT]-s[tt]).[PAR]", "With option [TT]-oq[tt] the RMSF values are converted to B-factor", "values, which are written to a [REF].pdb[ref] file with the coordinates, of the", "structure file, or of a [REF].pdb[ref] file when [TT]-q[tt] is specified.", "Option [TT]-ox[tt] writes the B-factors to a file with the average", "coordinates.[PAR]", "With the option [TT]-od[tt] the root mean square deviation with", "respect to the reference structure is calculated.[PAR]", "With the option [TT]-aniso[tt], [THISMODULE] will compute anisotropic", "temperature factors and then it will also output average coordinates", "and a [REF].pdb[ref] file with ANISOU records (corresonding to the [TT]-oq[tt]", "or [TT]-ox[tt] option). Please note that the U values", "are orientation-dependent, so before comparison with experimental data", "you should verify that you fit to the experimental coordinates.[PAR]", "When a [REF].pdb[ref] input file is passed to the program and the [TT]-aniso[tt]", "flag is set", "a correlation plot of the Uij will be created, if any anisotropic", "temperature factors are present in the [REF].pdb[ref] file.[PAR]", "With option [TT]-dir[tt] the average MSF (3x3) matrix is diagonalized.", "This shows the directions in which the atoms fluctuate the most and", "the least." }; static gmx_bool bRes = FALSE, bAniso = FALSE, bFit = TRUE; t_pargs pargs[] = { { "-res", FALSE, etBOOL, {&bRes}, "Calculate averages for each residue" }, { "-aniso", FALSE, etBOOL, {&bAniso}, "Compute anisotropic termperature factors" }, { "-fit", FALSE, etBOOL, {&bFit}, "Do a least squares superposition before computing RMSF. Without this you must make sure that the reference structure and the trajectory match." } }; int natom; int i, m, teller = 0; real t, *w_rls; t_topology top; int ePBC; t_atoms *pdbatoms, *refatoms; matrix box, pdbbox; rvec *x, *pdbx, *xref; t_trxstatus *status; const char *label; FILE *fp; /* the graphics file */ const char *devfn, *dirfn; int resind; gmx_bool bReadPDB; int *index; int isize; char *grpnames; real bfac, pdb_bfac, *Uaver; double **U, *xav; int aid; rvec *rmsd_x = nullptr; double *rmsf, invcount, totmass; int d; real count = 0; rvec xcm; gmx_rmpbc_t gpbc = nullptr; gmx_output_env_t *oenv; const char *leg[2] = { "MD", "X-Ray" }; t_filenm fnm[] = { { efTRX, "-f", nullptr, ffREAD }, { efTPS, nullptr, nullptr, ffREAD }, { efNDX, nullptr, nullptr, ffOPTRD }, { efPDB, "-q", nullptr, ffOPTRD }, { efPDB, "-oq", "bfac", ffOPTWR }, { efPDB, "-ox", "xaver", ffOPTWR }, { efXVG, "-o", "rmsf", ffWRITE }, { efXVG, "-od", "rmsdev", ffOPTWR }, { efXVG, "-oc", "correl", ffOPTWR }, { efLOG, "-dir", "rmsf", ffOPTWR } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW, NFILE, fnm, asize(pargs), pargs, asize(desc), desc, 0, nullptr, &oenv)) { return 0; } bReadPDB = ftp2bSet(efPDB, NFILE, fnm); devfn = opt2fn_null("-od", NFILE, fnm); dirfn = opt2fn_null("-dir", NFILE, fnm); read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xref, nullptr, box, TRUE); const char *title = *top.name; snew(w_rls, top.atoms.nr); fprintf(stderr, "Select group(s) for root mean square calculation\n"); get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), 1, &isize, &index, &grpnames); /* Set the weight */ for (i = 0; i < isize; i++) { w_rls[index[i]] = top.atoms.atom[index[i]].m; } /* Malloc the rmsf arrays */ snew(xav, isize*DIM); snew(U, isize); for (i = 0; i < isize; i++) { snew(U[i], DIM*DIM); } snew(rmsf, isize); if (devfn) { snew(rmsd_x, isize); } if (bReadPDB) { t_topology *top_pdb; snew(top_pdb, 1); /* Read coordinates twice */ read_tps_conf(opt2fn("-q", NFILE, fnm), top_pdb, nullptr, nullptr, nullptr, pdbbox, FALSE); snew(pdbatoms, 1); *pdbatoms = top_pdb->atoms; read_tps_conf(opt2fn("-q", NFILE, fnm), top_pdb, nullptr, &pdbx, nullptr, pdbbox, FALSE); /* TODO Should this assert that top_pdb->atoms.nr == top.atoms.nr? * See discussion at https://gerrit.gromacs.org/#/c/6430/1 */ title = *top_pdb->name; snew(refatoms, 1); *refatoms = top_pdb->atoms; sfree(top_pdb); } else { pdbatoms = &top.atoms; refatoms = &top.atoms; pdbx = xref; snew(pdbatoms->pdbinfo, pdbatoms->nr); pdbatoms->havePdbInfo = TRUE; copy_mat(box, pdbbox); } if (bFit) { sub_xcm(xref, isize, index, top.atoms.atom, xcm, FALSE); } natom = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box); if (bFit) { gpbc = gmx_rmpbc_init(&top.idef, ePBC, natom); } /* Now read the trj again to compute fluctuations */ teller = 0; do { if (bFit) { /* Remove periodic boundary */ gmx_rmpbc(gpbc, natom, box, x); /* Set center of mass to zero */ sub_xcm(x, isize, index, top.atoms.atom, xcm, FALSE); /* Fit to reference structure */ do_fit(natom, w_rls, xref, x); } /* Calculate Anisotropic U Tensor */ for (i = 0; i < isize; i++) { aid = index[i]; for (d = 0; d < DIM; d++) { xav[i*DIM + d] += x[aid][d]; for (m = 0; m < DIM; m++) { U[i][d*DIM + m] += x[aid][d]*x[aid][m]; } } } if (devfn) { /* Calculate RMS Deviation */ for (i = 0; (i < isize); i++) { aid = index[i]; for (d = 0; (d < DIM); d++) { rmsd_x[i][d] += gmx::square(x[aid][d]-xref[aid][d]); } } } count += 1.0; teller++; } while (read_next_x(oenv, status, &t, x, box)); close_trx(status); if (bFit) { gmx_rmpbc_done(gpbc); } invcount = 1.0/count; snew(Uaver, DIM*DIM); totmass = 0; for (i = 0; i < isize; i++) { for (d = 0; d < DIM; d++) { xav[i*DIM + d] *= invcount; } for (d = 0; d < DIM; d++) { for (m = 0; m < DIM; m++) { U[i][d*DIM + m] = U[i][d*DIM + m]*invcount - xav[i*DIM + d]*xav[i*DIM + m]; Uaver[3*d+m] += top.atoms.atom[index[i]].m*U[i][d*DIM + m]; } } totmass += top.atoms.atom[index[i]].m; } for (d = 0; d < DIM*DIM; d++) { Uaver[d] /= totmass; } if (bRes) { for (d = 0; d < DIM*DIM; d++) { average_residues(nullptr, U, d, isize, index, w_rls, &top.atoms); } } if (bAniso) { for (i = 0; i < isize; i++) { aid = index[i]; pdbatoms->pdbinfo[aid].bAnisotropic = TRUE; pdbatoms->pdbinfo[aid].uij[U11] = static_cast<int>(1e6*U[i][XX*DIM + XX]); pdbatoms->pdbinfo[aid].uij[U22] = static_cast<int>(1e6*U[i][YY*DIM + YY]); pdbatoms->pdbinfo[aid].uij[U33] = static_cast<int>(1e6*U[i][ZZ*DIM + ZZ]); pdbatoms->pdbinfo[aid].uij[U12] = static_cast<int>(1e6*U[i][XX*DIM + YY]); pdbatoms->pdbinfo[aid].uij[U13] = static_cast<int>(1e6*U[i][XX*DIM + ZZ]); pdbatoms->pdbinfo[aid].uij[U23] = static_cast<int>(1e6*U[i][YY*DIM + ZZ]); } } if (bRes) { label = "Residue"; } else { label = "Atom"; } for (i = 0; i < isize; i++) { rmsf[i] = U[i][XX*DIM + XX] + U[i][YY*DIM + YY] + U[i][ZZ*DIM + ZZ]; } if (dirfn) { fprintf(stdout, "\n"); print_dir(stdout, Uaver); fp = gmx_ffopen(dirfn, "w"); print_dir(fp, Uaver); gmx_ffclose(fp); } for (i = 0; i < isize; i++) { sfree(U[i]); } sfree(U); /* Write RMSF output */ if (bReadPDB) { bfac = 8.0*M_PI*M_PI/3.0*100; fp = xvgropen(ftp2fn(efXVG, NFILE, fnm), "B-Factors", label, "(A\\b\\S\\So\\N\\S2\\N)", oenv); xvgr_legend(fp, 2, leg, oenv); for (i = 0; (i < isize); i++) { if (!bRes || i+1 == isize || top.atoms.atom[index[i]].resind != top.atoms.atom[index[i+1]].resind) { resind = top.atoms.atom[index[i]].resind; pdb_bfac = find_pdb_bfac(pdbatoms, &top.atoms.resinfo[resind], *(top.atoms.atomname[index[i]])); fprintf(fp, "%5d %10.5f %10.5f\n", bRes ? top.atoms.resinfo[top.atoms.atom[index[i]].resind].nr : index[i]+1, rmsf[i]*bfac, pdb_bfac); } } xvgrclose(fp); } else { fp = xvgropen(ftp2fn(efXVG, NFILE, fnm), "RMS fluctuation", label, "(nm)", oenv); for (i = 0; i < isize; i++) { if (!bRes || i+1 == isize || top.atoms.atom[index[i]].resind != top.atoms.atom[index[i+1]].resind) { fprintf(fp, "%5d %8.4f\n", bRes ? top.atoms.resinfo[top.atoms.atom[index[i]].resind].nr : index[i]+1, std::sqrt(rmsf[i])); } } xvgrclose(fp); } for (i = 0; i < isize; i++) { pdbatoms->pdbinfo[index[i]].bfac = 800*M_PI*M_PI/3.0*rmsf[i]; } if (devfn) { for (i = 0; i < isize; i++) { rmsf[i] = (rmsd_x[i][XX]+rmsd_x[i][YY]+rmsd_x[i][ZZ])/count; } if (bRes) { average_residues(rmsf, nullptr, 0, isize, index, w_rls, &top.atoms); } /* Write RMSD output */ fp = xvgropen(devfn, "RMS Deviation", label, "(nm)", oenv); for (i = 0; i < isize; i++) { if (!bRes || i+1 == isize || top.atoms.atom[index[i]].resind != top.atoms.atom[index[i+1]].resind) { fprintf(fp, "%5d %8.4f\n", bRes ? top.atoms.resinfo[top.atoms.atom[index[i]].resind].nr : index[i]+1, std::sqrt(rmsf[i])); } } xvgrclose(fp); } if (opt2bSet("-oq", NFILE, fnm)) { /* Write a .pdb file with B-factors and optionally anisou records */ for (i = 0; i < isize; i++) { rvec_inc(pdbx[index[i]], xcm); } write_sto_conf_indexed(opt2fn("-oq", NFILE, fnm), title, pdbatoms, pdbx, nullptr, ePBC, pdbbox, isize, index); } if (opt2bSet("-ox", NFILE, fnm)) { rvec *bFactorX; snew(bFactorX, top.atoms.nr); for (i = 0; i < isize; i++) { for (d = 0; d < DIM; d++) { bFactorX[index[i]][d] = xcm[d] + xav[i*DIM + d]; } } /* Write a .pdb file with B-factors and optionally anisou records */ write_sto_conf_indexed(opt2fn("-ox", NFILE, fnm), title, pdbatoms, bFactorX, nullptr, ePBC, pdbbox, isize, index); sfree(bFactorX); } if (bAniso) { correlate_aniso(opt2fn("-oc", NFILE, fnm), refatoms, pdbatoms, oenv); do_view(oenv, opt2fn("-oc", NFILE, fnm), "-nxy"); } do_view(oenv, opt2fn("-o", NFILE, fnm), "-nxy"); if (devfn) { do_view(oenv, opt2fn("-od", NFILE, fnm), "-nxy"); } return 0; }
void calc_order(const char *fn, atom_id *index, atom_id *a, rvec **order, real ***slOrder, real *slWidth, int nslices, gmx_bool bSliced, gmx_bool bUnsat, t_topology *top, int ePBC, int ngrps, int axis, gmx_bool permolecule, gmx_bool radial, gmx_bool distcalc, const char *radfn, real ***distvals, const gmx_output_env_t *oenv) { /* if permolecule = TRUE, order parameters will be calculed per molecule * and stored in slOrder with #slices = # molecules */ rvec *x0, /* coordinates with pbc */ *x1, /* coordinates without pbc */ dist; /* vector between two atoms */ matrix box; /* box (3x3) */ t_trxstatus *status; rvec cossum, /* sum of vector angles for three axes */ Sx, Sy, Sz, /* the three molecular axes */ tmp1, tmp2, /* temp. rvecs for calculating dot products */ frameorder; /* order parameters for one frame */ real *slFrameorder; /* order parameter for one frame, per slice */ real length, /* total distance between two atoms */ t, /* time from trajectory */ z_ave, z1, z2; /* average z, used to det. which slice atom is in */ int natoms, /* nr. atoms in trj */ nr_tails, /* nr tails, to check if index file is correct */ size = 0, /* nr. of atoms in group. same as nr_tails */ i, j, m, k, teller = 0, slice, /* current slice number */ nr_frames = 0; int *slCount; /* nr. of atoms in one slice */ real sdbangle = 0; /* sum of these angles */ gmx_bool use_unitvector = FALSE; /* use a specified unit vector instead of axis to specify unit normal*/ rvec direction, com, dref, dvec; int comsize, distsize; atom_id *comidx = NULL, *distidx = NULL; char *grpname = NULL; t_pbc pbc; real arcdist, tmpdist; gmx_rmpbc_t gpbc = NULL; /* PBC added for center-of-mass vector*/ /* Initiate the pbc structure */ std::memset(&pbc, 0, sizeof(pbc)); if ((natoms = read_first_x(oenv, &status, fn, &t, &x0, box)) == 0) { gmx_fatal(FARGS, "Could not read coordinates from statusfile\n"); } nr_tails = index[1] - index[0]; fprintf(stderr, "Number of elements in first group: %d\n", nr_tails); /* take first group as standard. Not rocksolid, but might catch error in index*/ if (permolecule) { nslices = nr_tails; bSliced = FALSE; /*force slices off */ fprintf(stderr, "Calculating order parameters for each of %d molecules\n", nslices); } if (radial) { use_unitvector = TRUE; fprintf(stderr, "Select an index group to calculate the radial membrane normal\n"); get_index(&top->atoms, radfn, 1, &comsize, &comidx, &grpname); } if (distcalc) { if (grpname != NULL) { sfree(grpname); } fprintf(stderr, "Select an index group to use as distance reference\n"); get_index(&top->atoms, radfn, 1, &distsize, &distidx, &grpname); bSliced = FALSE; /*force slices off*/ } if (use_unitvector && bSliced) { fprintf(stderr, "Warning: slicing and specified unit vectors are not currently compatible\n"); } snew(slCount, nslices); snew(*slOrder, nslices); for (i = 0; i < nslices; i++) { snew((*slOrder)[i], ngrps); } if (distcalc) { snew(*distvals, nslices); for (i = 0; i < nslices; i++) { snew((*distvals)[i], ngrps); } } snew(*order, ngrps); snew(slFrameorder, nslices); snew(x1, natoms); if (bSliced) { *slWidth = box[axis][axis]/nslices; fprintf(stderr, "Box divided in %d slices. Initial width of slice: %f\n", nslices, *slWidth); } #if 0 nr_tails = index[1] - index[0]; fprintf(stderr, "Number of elements in first group: %d\n", nr_tails); /* take first group as standard. Not rocksolid, but might catch error in index*/ #endif teller = 0; gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms); /*********** Start processing trajectory ***********/ do { if (bSliced) { *slWidth = box[axis][axis]/nslices; } teller++; set_pbc(&pbc, ePBC, box); gmx_rmpbc_copy(gpbc, natoms, box, x0, x1); /* Now loop over all groups. There are ngrps groups, the order parameter can be calculated for grp 1 to grp ngrps - 1. For each group, loop over all atoms in group, which is index[i] to (index[i+1] - 1) See block.h. Of course, in this case index[i+1] -index[i] has to be the same for all groups, namely the number of tails. i just runs over all atoms in a tail, so for DPPC ngrps = 16 and i runs from 1 to 14, including 14 */ if (radial) { /*center-of-mass determination*/ com[XX] = 0.0; com[YY] = 0.0; com[ZZ] = 0.0; for (j = 0; j < comsize; j++) { rvec_inc(com, x1[comidx[j]]); } svmul(1.0/comsize, com, com); } if (distcalc) { dref[XX] = 0.0; dref[YY] = 0.0; dref[ZZ] = 0.0; for (j = 0; j < distsize; j++) { rvec_inc(dist, x1[distidx[j]]); } svmul(1.0/distsize, dref, dref); if (radial) { pbc_dx(&pbc, dref, com, dvec); unitv(dvec, dvec); } } for (i = 1; i < ngrps - 1; i++) { clear_rvec(frameorder); size = index[i+1] - index[i]; if (size != nr_tails) { gmx_fatal(FARGS, "grp %d does not have same number of" " elements as grp 1\n", i); } for (j = 0; j < size; j++) { if (radial) /*create unit vector*/ { pbc_dx(&pbc, x1[a[index[i]+j]], com, direction); unitv(direction, direction); /*DEBUG*/ /*if (j==0) fprintf(stderr,"X %f %f %f\tcom %f %f %f\tdirection %f %f %f\n",x1[a[index[i]+j]][0],x1[a[index[i]+j]][1],x1[a[index[i]+j]][2],com[0],com[1],com[2], direction[0],direction[1],direction[2]);*/ } if (bUnsat) { /* Using convention for unsaturated carbons */ /* first get Sz, the vector from Cn to Cn+1 */ rvec_sub(x1[a[index[i+1]+j]], x1[a[index[i]+j]], dist); length = norm(dist); check_length(length, a[index[i]+j], a[index[i+1]+j]); svmul(1.0/length, dist, Sz); /* this is actually the cosine of the angle between the double bond and axis, because Sz is normalized and the two other components of the axis on the bilayer are zero */ if (use_unitvector) { sdbangle += gmx_angle(direction, Sz); /*this can probably be optimized*/ } else { sdbangle += std::acos(Sz[axis]); } } else { /* get vector dist(Cn-1,Cn+1) for tail atoms */ rvec_sub(x1[a[index[i+1]+j]], x1[a[index[i-1]+j]], dist); length = norm(dist); /* determine distance between two atoms */ check_length(length, a[index[i-1]+j], a[index[i+1]+j]); svmul(1.0/length, dist, Sz); /* Sz is now the molecular axis Sz, normalized and all that */ } /* now get Sx. Sx is normal to the plane of Cn-1, Cn and Cn+1 so we can use the outer product of Cn-1->Cn and Cn+1->Cn, I hope */ rvec_sub(x1[a[index[i+1]+j]], x1[a[index[i]+j]], tmp1); rvec_sub(x1[a[index[i-1]+j]], x1[a[index[i]+j]], tmp2); cprod(tmp1, tmp2, Sx); svmul(1.0/norm(Sx), Sx, Sx); /* now we can get Sy from the outer product of Sx and Sz */ cprod(Sz, Sx, Sy); svmul(1.0/norm(Sy), Sy, Sy); /* the square of cosine of the angle between dist and the axis. Using the innerproduct, but two of the three elements are zero Determine the sum of the orderparameter of all atoms in group */ if (use_unitvector) { cossum[XX] = sqr(iprod(Sx, direction)); /* this is allowed, since Sa is normalized */ cossum[YY] = sqr(iprod(Sy, direction)); cossum[ZZ] = sqr(iprod(Sz, direction)); } else { cossum[XX] = sqr(Sx[axis]); /* this is allowed, since Sa is normalized */ cossum[YY] = sqr(Sy[axis]); cossum[ZZ] = sqr(Sz[axis]); } for (m = 0; m < DIM; m++) { frameorder[m] += 0.5 * (3.0 * cossum[m] - 1.0); } if (bSliced) { /* get average coordinate in box length for slicing, determine which slice atom is in, increase count for that slice. slFrameorder and slOrder are reals, not rvecs. Only the component [axis] of the order tensor is kept, until I find it necessary to know the others too */ z1 = x1[a[index[i-1]+j]][axis]; z2 = x1[a[index[i+1]+j]][axis]; z_ave = 0.5 * (z1 + z2); if (z_ave < 0) { z_ave += box[axis][axis]; } if (z_ave > box[axis][axis]) { z_ave -= box[axis][axis]; } slice = static_cast<int>((0.5 + (z_ave / (*slWidth))) - 1); slCount[slice]++; /* determine slice, increase count */ slFrameorder[slice] += 0.5 * (3 * cossum[axis] - 1); } else if (permolecule) { /* store per-molecule order parameter * To just track single-axis order: (*slOrder)[j][i] += 0.5 * (3 * iprod(cossum,direction) - 1); * following is for Scd order: */ (*slOrder)[j][i] += -1* (1.0/3.0 * (3 * cossum[XX] - 1) + 1.0/3.0 * 0.5 * (3.0 * cossum[YY] - 1)); } if (distcalc) { if (radial) { /* bin order parameter by arc distance from reference group*/ arcdist = gmx_angle(dvec, direction); (*distvals)[j][i] += arcdist; } else if (i == 1) { /* Want minimum lateral distance to first group calculated */ tmpdist = trace(box); /* should be max value */ for (k = 0; k < distsize; k++) { pbc_dx(&pbc, x1[distidx[k]], x1[a[index[i]+j]], dvec); /* at the moment, just remove dvec[axis] */ dvec[axis] = 0; tmpdist = std::min(tmpdist, norm2(dvec)); } //fprintf(stderr, "Min dist %f; trace %f\n", tmpdist, trace(box)); (*distvals)[j][i] += std::sqrt(tmpdist); } } } /* end loop j, over all atoms in group */ for (m = 0; m < DIM; m++) { (*order)[i][m] += (frameorder[m]/size); } if (!permolecule) { /*Skip following if doing per-molecule*/ for (k = 0; k < nslices; k++) { if (slCount[k]) /* if no elements, nothing has to be added */ { (*slOrder)[k][i] += slFrameorder[k]/slCount[k]; slFrameorder[k] = 0; slCount[k] = 0; } } } /* end loop i, over all groups in indexfile */ } nr_frames++; } while (read_next_x(oenv, status, &t, x0, box)); /*********** done with status file **********/ fprintf(stderr, "\nRead trajectory. Printing parameters to file\n"); gmx_rmpbc_done(gpbc); /* average over frames */ for (i = 1; i < ngrps - 1; i++) { svmul(1.0/nr_frames, (*order)[i], (*order)[i]); fprintf(stderr, "Atom %d Tensor: x=%g , y=%g, z=%g\n", i, (*order)[i][XX], (*order)[i][YY], (*order)[i][ZZ]); if (bSliced || permolecule) { for (k = 0; k < nslices; k++) { (*slOrder)[k][i] /= nr_frames; } } if (distcalc) { for (k = 0; k < nslices; k++) { (*distvals)[k][i] /= nr_frames; } } } if (bUnsat) { fprintf(stderr, "Average angle between double bond and normal: %f\n", 180*sdbangle/(nr_frames * size*M_PI)); } sfree(x0); /* free memory used by coordinate arrays */ sfree(x1); if (comidx != NULL) { sfree(comidx); } if (distidx != NULL) { sfree(distidx); } if (grpname != NULL) { sfree(grpname); } }