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_nmens(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] generates an ensemble around an average structure", "in a subspace that is defined by a set of normal modes (eigenvectors).", "The eigenvectors are assumed to be mass-weighted.", "The position along each eigenvector is randomly taken from a Gaussian", "distribution with variance kT/eigenvalue.[PAR]", "By default the starting eigenvector is set to 7, since the first six", "normal modes are the translational and rotational degrees of freedom." }; static int nstruct = 100, first = 7, last = -1, seed = -1; static real temp = 300.0; t_pargs pa[] = { { "-temp", FALSE, etREAL, {&temp}, "Temperature in Kelvin" }, { "-seed", FALSE, etINT, {&seed}, "Random seed, -1 generates a seed from time and pid" }, { "-num", FALSE, etINT, {&nstruct}, "Number of structures to generate" }, { "-first", FALSE, etINT, {&first}, "First eigenvector to use (-1 is select)" }, { "-last", FALSE, etINT, {&last}, "Last eigenvector to use (-1 is till the last)" } }; #define NPA asize(pa) t_trxstatus *out; int status, trjout; t_topology top; int ePBC; t_atoms *atoms; rvec *xtop, *xref, *xav, *xout1, *xout2; gmx_bool bDMR, bDMA, bFit; int nvec, *eignr = NULL; rvec **eigvec = NULL; matrix box; real *eigval, totmass, *invsqrtm, t, disp; int natoms, neigval; char *grpname, title[STRLEN]; const char *indexfile; int i, j, d, s, v; int nout, *iout, noutvec, *outvec; atom_id *index; real rfac, invfr, rhalf, jr; int * eigvalnr; output_env_t oenv; gmx_rng_t rng; unsigned long jran; const unsigned long im = 0xffff; const unsigned long ia = 1093; const unsigned long ic = 18257; t_filenm fnm[] = { { efTRN, "-v", "eigenvec", ffREAD }, { efXVG, "-e", "eigenval", ffREAD }, { efTPS, NULL, NULL, ffREAD }, { efNDX, NULL, NULL, ffOPTRD }, { efTRO, "-o", "ensemble", ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, PCA_BE_NICE, NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } indexfile = ftp2fn_null(efNDX, NFILE, fnm); read_eigenvectors(opt2fn("-v", NFILE, fnm), &natoms, &bFit, &xref, &bDMR, &xav, &bDMA, &nvec, &eignr, &eigvec, &eigval); read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &xtop, NULL, box, bDMA); atoms = &top.atoms; 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(invsqrtm, natoms); if (bDMA) { for (i = 0; (i < natoms); i++) { invsqrtm[i] = gmx_invsqrt(atoms->atom[index[i]].m); } } else { for (i = 0; (i < natoms); i++) { invsqrtm[i] = 1.0; } } if (last == -1) { last = natoms*DIM; } if (first > -1) { /* 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 { 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 < nvec) && (eignr[j] != iout[i])) { j++; } if ((j < nvec) && (eignr[j] == iout[i])) { outvec[noutvec] = j; iout[noutvec] = iout[i]; noutvec++; } } fprintf(stderr, "%d eigenvectors selected for output\n", noutvec); if (seed == -1) { seed = (int)gmx_rng_make_seed(); rng = gmx_rng_init(seed); } else { rng = gmx_rng_init(seed); } fprintf(stderr, "Using seed %d and a temperature of %g K\n", seed, temp); snew(xout1, natoms); snew(xout2, atoms->nr); out = open_trx(ftp2fn(efTRO, NFILE, fnm), "w"); jran = (unsigned long)((real)im*gmx_rng_uniform_real(rng)); gmx_rng_destroy(rng); for (s = 0; s < nstruct; s++) { for (i = 0; i < natoms; i++) { copy_rvec(xav[i], xout1[i]); } for (j = 0; j < noutvec; j++) { v = outvec[j]; /* (r-0.5) n times: var_n = n * var_1 = n/12 n=4: var_n = 1/3, so multiply with 3 */ rfac = sqrt(3.0 * BOLTZ*temp/eigval[iout[j]]); rhalf = 2.0*rfac; rfac = rfac/(real)im; jran = (jran*ia+ic) & im; jr = (real)jran; jran = (jran*ia+ic) & im; jr += (real)jran; jran = (jran*ia+ic) & im; jr += (real)jran; jran = (jran*ia+ic) & im; jr += (real)jran; disp = rfac * jr - rhalf; for (i = 0; i < natoms; i++) { for (d = 0; d < DIM; d++) { xout1[i][d] += disp*eigvec[v][i][d]*invsqrtm[i]; } } } for (i = 0; i < natoms; i++) { copy_rvec(xout1[i], xout2[index[i]]); } t = s+1; write_trx(out, natoms, index, atoms, 0, t, box, xout2, NULL, NULL); fprintf(stderr, "\rGenerated %d structures", s+1); } fprintf(stderr, "\n"); close_trx(out); return 0; }
int gmx_dyndom(int argc, char *argv[]) { const char *desc[] = { "[TT]g_dyndom[tt] reads a [TT].pdb[tt] file output from DynDom", "(http://www.cmp.uea.ac.uk/dyndom/).", "It reads the coordinates, the coordinates of the rotation axis,", "and an index file containing the domains.", "Furthermore, it takes the first and last atom of the arrow file", "as command line arguments (head and tail) and", "finally it takes the translation vector (given in DynDom info file)", "and the angle of rotation (also as command line arguments). If the angle", "determined by DynDom is given, one should be able to recover the", "second structure used for generating the DynDom output.", "Because of limited numerical accuracy this should be verified by", "computing an all-atom RMSD (using [TT]g_confrms[tt]) rather than by file", "comparison (using diff).[PAR]", "The purpose of this program is to interpolate and extrapolate the", "rotation as found by DynDom. As a result unphysical structures with", "long or short bonds, or overlapping atoms may be produced. Visual", "inspection, and energy minimization may be necessary to", "validate the structure." }; static real trans0 = 0; static rvec head = { 0, 0, 0 }; static rvec tail = { 0, 0, 0 }; static real angle0 = 0, angle1 = 0, maxangle = 0; static int label = 0, nframes = 11; t_pargs pa[] = { { "-firstangle", FALSE, etREAL, {&angle0}, "Angle of rotation about rotation vector" }, { "-lastangle", FALSE, etREAL, {&angle1}, "Angle of rotation about rotation vector" }, { "-nframe", FALSE, etINT, {&nframes}, "Number of steps on the pathway" }, { "-maxangle", FALSE, etREAL, {&maxangle}, "DymDom dtermined angle of rotation about rotation vector" }, { "-trans", FALSE, etREAL, {&trans0}, "Translation (Angstrom) along rotation vector (see DynDom info file)" }, { "-head", FALSE, etRVEC, {head}, "First atom of the arrow vector" }, { "-tail", FALSE, etRVEC, {tail}, "Last atom of the arrow vector" } }; int i, j, natoms, isize; t_trxstatus *status; atom_id *index = NULL, *index_all; char title[256], *grpname; t_atoms atoms; real angle, trans; rvec *x, *v, *xout, *vout; matrix box; output_env_t oenv; t_filenm fnm[] = { { efPDB, "-f", "dyndom", ffREAD }, { efTRO, "-o", "rotated", ffWRITE }, { efNDX, "-n", "domains", ffREAD } }; #define NFILE asize(fnm) CopyRight(stderr, argv[0]); parse_common_args(&argc, argv, 0, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv); get_stx_coordnum (opt2fn("-f", NFILE, fnm), &natoms); init_t_atoms(&atoms, natoms, TRUE); snew(x, natoms); snew(v, natoms); read_stx_conf(opt2fn("-f", NFILE, fnm), title, &atoms, x, v, NULL, box); snew(xout, natoms); snew(vout, natoms); printf("Select group to rotate:\n"); rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname); printf("Going to rotate %s containg %d atoms\n", grpname, isize); snew(index_all, atoms.nr); for (i = 0; (i < atoms.nr); i++) { index_all[i] = i; } status = open_trx(opt2fn("-o", NFILE, fnm), "w"); label = 'A'; for (i = 0; (i < nframes); i++, label++) { angle = angle0 + (i*(angle1-angle0))/(nframes-1); trans = trans0*0.1*angle/maxangle; printf("Frame: %2d (label %c), angle: %8.3f deg., trans: %8.3f nm\n", i, label, angle, trans); rot_conf(&atoms, x, v, trans, angle, head, tail, box, isize, index, xout, vout); if (label > 'Z') { label -= 26; } for (j = 0; (j < atoms.nr); j++) { atoms.resinfo[atoms.atom[j].resind].chainid = label; } write_trx(status, atoms.nr, index_all, &atoms, i, angle, box, xout, vout, NULL); } close_trx(status); 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; }
int gmx_morph(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] does a linear interpolation of conformations in order to", "create intermediates. Of course these are completely unphysical, but", "that you may try to justify yourself. Output is in the form of a ", "generic trajectory. The number of intermediates can be controlled with", "the [TT]-ninterm[tt] flag. The first and last flag correspond to the way of", "interpolating: 0 corresponds to input structure 1 while", "1 corresponds to input structure 2.", "If you specify [TT]-first[tt] < 0 or [TT]-last[tt] > 1 extrapolation will be", "on the path from input structure x[SUB]1[sub] to x[SUB]2[sub]. In general, the coordinates", "of the intermediate x(i) out of N total intermediates correspond to:[PAR]", "x(i) = x[SUB]1[sub] + (first+(i/(N-1))*(last-first))*(x[SUB]2[sub]-x[SUB]1[sub])[PAR]", "Finally the RMSD with respect to both input structures can be computed", "if explicitly selected ([TT]-or[tt] option). In that case, an index file may be", "read to select the group from which the RMS is computed." }; t_filenm fnm[] = { { efSTX, "-f1", "conf1", ffREAD }, { efSTX, "-f2", "conf2", ffREAD }, { efTRX, "-o", "interm", ffWRITE }, { efXVG, "-or", "rms-interm", ffOPTWR }, { efNDX, "-n", "index", ffOPTRD } }; #define NFILE asize(fnm) static int ninterm = 11; static real first = 0.0; static real last = 1.0; static gmx_bool bFit = TRUE; t_pargs pa [] = { { "-ninterm", FALSE, etINT, {&ninterm}, "Number of intermediates" }, { "-first", FALSE, etREAL, {&first}, "Corresponds to first generated structure (0 is input x[SUB]1[sub], see above)" }, { "-last", FALSE, etREAL, {&last}, "Corresponds to last generated structure (1 is input x[SUB]2[sub], see above)" }, { "-fit", FALSE, etBOOL, {&bFit}, "Do a least squares fit of the second to the first structure before interpolating" } }; const char *leg[] = { "Ref = 1\\Sst\\N conf", "Ref = 2\\Snd\\N conf" }; FILE *fp = NULL; int i, isize, is_lsq, nat1, nat2; t_trxstatus *status; atom_id *index, *index_lsq, *index_all, *dummy; t_atoms atoms; rvec *x1, *x2, *xx, *v; matrix box; real rms1, rms2, fac, *mass; char title[STRLEN], *grpname; gmx_bool bRMS; output_env_t oenv; if (!parse_common_args(&argc, argv, PCA_CAN_VIEW, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } get_stx_coordnum (opt2fn("-f1", NFILE, fnm), &nat1); get_stx_coordnum (opt2fn("-f2", NFILE, fnm), &nat2); if (nat1 != nat2) { gmx_fatal(FARGS, "Number of atoms in first structure is %d, in second %d", nat1, nat2); } init_t_atoms(&atoms, nat1, TRUE); snew(x1, nat1); snew(x2, nat1); snew(xx, nat1); snew(v, nat1); read_stx_conf(opt2fn("-f1", NFILE, fnm), title, &atoms, x1, v, NULL, box); read_stx_conf(opt2fn("-f2", NFILE, fnm), title, &atoms, x2, v, NULL, box); snew(mass, nat1); snew(index_all, nat1); for (i = 0; (i < nat1); i++) { mass[i] = 1; index_all[i] = i; } if (bFit) { printf("Select group for LSQ superposition:\n"); get_index(&atoms, opt2fn_null("-n", NFILE, fnm), 1, &is_lsq, &index_lsq, &grpname); reset_x(is_lsq, index_lsq, nat1, index_all, x1, mass); reset_x(is_lsq, index_lsq, nat1, index_all, x2, mass); do_fit(nat1, mass, x1, x2); } bRMS = opt2bSet("-or", NFILE, fnm); if (bRMS) { fp = xvgropen(opt2fn("-or", NFILE, fnm), "RMSD", "Conf", "(nm)", oenv); xvgr_legend(fp, asize(leg), leg, oenv); printf("Select group for RMSD calculation:\n"); get_index(&atoms, opt2fn_null("-n", NFILE, fnm), 1, &isize, &index, &grpname); printf("You selected group %s, containing %d atoms\n", grpname, isize); rms1 = rmsdev_ind(isize, index, mass, x1, x2); fprintf(stderr, "RMSD between input conformations is %g nm\n", rms1); } snew(dummy, nat1); for (i = 0; (i < nat1); i++) { dummy[i] = i; } status = open_trx(ftp2fn(efTRX, NFILE, fnm), "w"); for (i = 0; (i < ninterm); i++) { fac = dointerp(nat1, x1, x2, xx, i, ninterm, first, last); write_trx(status, nat1, dummy, &atoms, i, fac, box, xx, NULL, NULL); if (bRMS) { rms1 = rmsdev_ind(isize, index, mass, x1, xx); rms2 = rmsdev_ind(isize, index, mass, x2, xx); fprintf(fp, "%10g %10g %10g\n", fac, rms1, rms2); } } close_trx(status); if (bRMS) { gmx_ffclose(fp); do_view(oenv, opt2fn("-or", NFILE, fnm), "-nxy"); } return 0; }
int gmx_nmtraj(int argc, char *argv[]) { const char *desc[] = { "[THISMODULE] generates an virtual trajectory from an eigenvector, ", "corresponding to a harmonic Cartesian oscillation around the average ", "structure. The eigenvectors should normally be mass-weighted, but you can ", "use non-weighted eigenvectors to generate orthogonal motions. ", "The output frames are written as a trajectory file covering an entire period, and ", "the first frame is the average structure. If you write the trajectory in (or convert to) ", "PDB format you can view it directly in PyMol and also render a photorealistic movie. ", "Motion amplitudes are calculated from the eigenvalues and a preset temperature, ", "assuming equipartition of the energy over all modes. To make the motion clearly visible ", "in PyMol you might want to amplify it by setting an unrealistically high temperature. ", "However, be aware that both the linear Cartesian displacements and mass weighting will ", "lead to serious structure deformation for high amplitudes - this is is simply a limitation ", "of the Cartesian normal mode model. By default the selected eigenvector is set to 7, since ", "the first six normal modes are the translational and rotational degrees of freedom." }; static real refamplitude = 0.25; static int nframes = 30; static real temp = 300.0; static const char *eignrvec = "7"; static const char *phasevec = "0.0"; t_pargs pa[] = { { "-eignr", FALSE, etSTR, {&eignrvec}, "String of eigenvectors to use (first is 1)" }, { "-phases", FALSE, etSTR, {&phasevec}, "String of phases (default is 0.0)" }, { "-temp", FALSE, etREAL, {&temp}, "Temperature (K)" }, { "-amplitude", FALSE, etREAL, {&refamplitude}, "Amplitude for modes with eigenvalue<=0" }, { "-nframes", FALSE, etINT, {&nframes}, "Number of frames to generate" } }; #define NPA asize(pa) t_trxstatus *out; t_topology top; int ePBC; t_atoms *atoms; rvec *xtop, *xref, *xav, *xout; int nvec, *eignr = NULL; rvec **eigvec = NULL; matrix box; int natoms; int i, j, k, kmode, d; gmx_bool bDMR, bDMA, bFit; real * eigval; int * dummy; real * invsqrtm; real fraction; int *out_eigidx; rvec * this_eigvec; real omega, Ekin, m, vel; int nmodes, nphases; int *imodes; real *amplitude; real *phases; const char *p; char *pe; output_env_t oenv; t_filenm fnm[] = { { efTPS, NULL, NULL, ffREAD }, { efTRN, "-v", "eigenvec", ffREAD }, { efTRO, "-o", "nmtraj", ffWRITE } }; #define NFILE asize(fnm) if (!parse_common_args(&argc, argv, 0, NFILE, fnm, NPA, pa, asize(desc), desc, 0, NULL, &oenv)) { return 0; } read_eigenvectors(opt2fn("-v", NFILE, fnm), &natoms, &bFit, &xref, &bDMR, &xav, &bDMA, &nvec, &eignr, &eigvec, &eigval); read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &xtop, NULL, box, bDMA); /* Find vectors and phases */ /* first find number of args in string */ nmodes = gmx::countWords(eignrvec); snew(imodes, nmodes); p = eignrvec; for (i = 0; i < nmodes; i++) { /* C indices start on 0 */ imodes[i] = std::strtol(p, &pe, 10)-1; p = pe; } /* Now read phases */ nphases = gmx::countWords(phasevec); if (nphases > nmodes) { gmx_fatal(FARGS, "More phases than eigenvector indices specified.\n"); } snew(phases, nmodes); p = phasevec; for (i = 0; i < nphases; i++) { phases[i] = strtod(p, &pe); p = pe; } if (nmodes > nphases) { printf("Warning: Setting phase of last %d modes to zero...\n", nmodes-nphases); } for (i = nphases; i < nmodes; i++) { phases[i] = 0; } atoms = &top.atoms; if (atoms->nr != natoms) { gmx_fatal(FARGS, "Different number of atoms in topology and eigenvectors.\n"); } snew(dummy, natoms); for (i = 0; i < natoms; i++) { dummy[i] = i; } /* Find the eigenvalue/vector to match our select one */ snew(out_eigidx, nmodes); for (i = 0; i < nmodes; i++) { out_eigidx[i] = -1; } for (i = 0; i < nvec; i++) { for (j = 0; j < nmodes; j++) { if (imodes[j] == eignr[i]) { out_eigidx[j] = i; } } } for (i = 0; i < nmodes; i++) { if (out_eigidx[i] == -1) { gmx_fatal(FARGS, "Could not find mode %d in eigenvector file.\n", imodes[i]); } } snew(invsqrtm, natoms); if (bDMA) { for (i = 0; (i < natoms); i++) { invsqrtm[i] = gmx_invsqrt(atoms->atom[i].m); } } else { for (i = 0; (i < natoms); i++) { invsqrtm[i] = 1.0; } } snew(xout, natoms); snew(amplitude, nmodes); printf("mode phases: %g %g\n", phases[0], phases[1]); for (i = 0; i < nmodes; i++) { kmode = out_eigidx[i]; this_eigvec = eigvec[kmode]; if ( (kmode >= 6) && (eigval[kmode] > 0)) { /* Derive amplitude from temperature and eigenvalue if we can */ /* Convert eigenvalue to angular frequency, in units s^(-1) */ omega = std::sqrt(eigval[kmode]*1.0E21/(AVOGADRO*AMU)); /* Harmonic motion will be x=x0 + A*sin(omega*t)*eigenvec. * The velocity is thus: * * v = A*omega*cos(omega*t)*eigenvec. * * And the average kinetic energy the integral of mass*v*v/2 over a * period: * * (1/4)*mass*A*omega*eigenvec * * For t =2*pi*n, all energy will be kinetic, and v=A*omega*eigenvec. * The kinetic energy will be sum(0.5*mass*v*v) if we temporarily set A to 1, * and the average over a period half of this. */ Ekin = 0; for (k = 0; k < natoms; k++) { m = atoms->atom[k].m; for (d = 0; d < DIM; d++) { vel = omega*this_eigvec[k][d]; Ekin += 0.5*0.5*m*vel*vel; } } /* Convert Ekin from amu*(nm/s)^2 to J, i.e., kg*(m/s)^2 * This will also be proportional to A^2 */ Ekin *= AMU*1E-18; /* Set the amplitude so the energy is kT/2 */ amplitude[i] = std::sqrt(0.5*BOLTZMANN*temp/Ekin); } else { amplitude[i] = refamplitude; } } out = open_trx(ftp2fn(efTRO, NFILE, fnm), "w"); /* Write a sine oscillation around the average structure, * modulated by the eigenvector with selected amplitude. */ for (i = 0; i < nframes; i++) { fraction = static_cast<real>(i)/nframes; for (j = 0; j < natoms; j++) { copy_rvec(xav[j], xout[j]); } for (k = 0; k < nmodes; k++) { kmode = out_eigidx[k]; this_eigvec = eigvec[kmode]; for (j = 0; j < natoms; j++) { for (d = 0; d < DIM; d++) { xout[j][d] += amplitude[k]*std::sin(2*M_PI*(fraction+phases[k]/360.0))*this_eigvec[j][d]; } } } write_trx(out, natoms, dummy, atoms, i, static_cast<real>(i)/nframes, box, xout, NULL, NULL); } fprintf(stderr, "\n"); close_trx(out); return 0; }
void dist_plot(const char *fn, const char *afile, const char *dfile, const char *nfile, const char *rfile, const char *xfile, real rcut, gmx_bool bMat, t_atoms *atoms, int ng, atom_id *index[], int gnx[], char *grpn[], gmx_bool bSplit, gmx_bool bMin, int nres, atom_id *residue, gmx_bool bPBC, int ePBC, gmx_bool bGroup, gmx_bool bEachResEachTime, gmx_bool bPrintResName, const output_env_t oenv) { FILE *atm, *dist, *num; t_trxstatus *trxout; char buf[256]; char **leg; real t, dmin, dmax, **mindres = NULL, **maxdres = NULL; int nmin, nmax; t_trxstatus *status; int i = -1, j, k, natoms; int min1, min2, max1, max2, min1r, min2r, max1r, max2r; atom_id oindex[2]; rvec *x0; matrix box; t_trxframe frout; gmx_bool bFirst; FILE *respertime = NULL; if ((natoms = read_first_x(oenv, &status, fn, &t, &x0, box)) == 0) { gmx_fatal(FARGS, "Could not read coordinates from statusfile\n"); } sprintf(buf, "%simum Distance", bMin ? "Min" : "Max"); dist = xvgropen(dfile, buf, output_env_get_time_label(oenv), "Distance (nm)", oenv); sprintf(buf, "Number of Contacts %s %g nm", bMin ? "<" : ">", rcut); num = nfile ? xvgropen(nfile, buf, output_env_get_time_label(oenv), "Number", oenv) : NULL; atm = afile ? ffopen(afile, "w") : NULL; trxout = xfile ? open_trx(xfile, "w") : NULL; if (bMat) { if (ng == 1) { snew(leg, 1); sprintf(buf, "Internal in %s", grpn[0]); leg[0] = strdup(buf); xvgr_legend(dist, 0, (const char**)leg, oenv); if (num) { xvgr_legend(num, 0, (const char**)leg, oenv); } } else { snew(leg, (ng*(ng-1))/2); for (i = j = 0; (i < ng-1); i++) { for (k = i+1; (k < ng); k++, j++) { sprintf(buf, "%s-%s", grpn[i], grpn[k]); leg[j] = strdup(buf); } } xvgr_legend(dist, j, (const char**)leg, oenv); if (num) { xvgr_legend(num, j, (const char**)leg, oenv); } } } else { snew(leg, ng-1); for (i = 0; (i < ng-1); i++) { sprintf(buf, "%s-%s", grpn[0], grpn[i+1]); leg[i] = strdup(buf); } xvgr_legend(dist, ng-1, (const char**)leg, oenv); if (num) { xvgr_legend(num, ng-1, (const char**)leg, oenv); } } if (bEachResEachTime) { sprintf(buf, "%simum Distance", bMin ? "Min" : "Max"); respertime = xvgropen(rfile, buf, output_env_get_time_label(oenv), "Distance (nm)", oenv); xvgr_legend(respertime, ng-1, (const char**)leg, oenv); if (bPrintResName) { fprintf(respertime, "# "); } for (j = 0; j < nres; j++) { fprintf(respertime, "%s%d ", *(atoms->resinfo[atoms->atom[index[0][residue[j]]].resind].name), atoms->atom[index[0][residue[j]]].resind); } fprintf(respertime, "\n"); } j = 0; if (nres) { snew(mindres, ng-1); snew(maxdres, ng-1); for (i = 1; i < ng; i++) { snew(mindres[i-1], nres); snew(maxdres[i-1], nres); for (j = 0; j < nres; j++) { mindres[i-1][j] = 1e6; } /* maxdres[*][*] is already 0 */ } } bFirst = TRUE; do { if (bSplit && !bFirst && abs(t/output_env_get_time_factor(oenv)) < 1e-5) { fprintf(dist, "&\n"); if (num) { fprintf(num, "&\n"); } if (atm) { fprintf(atm, "&\n"); } } fprintf(dist, "%12e", output_env_conv_time(oenv, t)); if (num) { fprintf(num, "%12e", output_env_conv_time(oenv, t)); } if (bMat) { if (ng == 1) { calc_dist(rcut, bPBC, ePBC, box, x0, gnx[0], gnx[0], index[0], index[0], bGroup, &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2); fprintf(dist, " %12e", bMin ? dmin : dmax); if (num) { fprintf(num, " %8d", bMin ? nmin : nmax); } } else { for (i = 0; (i < ng-1); i++) { for (k = i+1; (k < ng); k++) { calc_dist(rcut, bPBC, ePBC, box, x0, gnx[i], gnx[k], index[i], index[k], bGroup, &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2); fprintf(dist, " %12e", bMin ? dmin : dmax); if (num) { fprintf(num, " %8d", bMin ? nmin : nmax); } } } } } else { for (i = 1; (i < ng); i++) { calc_dist(rcut, bPBC, ePBC, box, x0, gnx[0], gnx[i], index[0], index[i], bGroup, &dmin, &dmax, &nmin, &nmax, &min1, &min2, &max1, &max2); fprintf(dist, " %12e", bMin ? dmin : dmax); if (num) { fprintf(num, " %8d", bMin ? nmin : nmax); } if (nres) { for (j = 0; j < nres; j++) { calc_dist(rcut, bPBC, ePBC, box, x0, residue[j+1]-residue[j], gnx[i], &(index[0][residue[j]]), index[i], bGroup, &dmin, &dmax, &nmin, &nmax, &min1r, &min2r, &max1r, &max2r); mindres[i-1][j] = min(mindres[i-1][j], dmin); maxdres[i-1][j] = max(maxdres[i-1][j], dmax); } } } } fprintf(dist, "\n"); if (num) { fprintf(num, "\n"); } if ( (bMin ? min1 : max1) != -1) { if (atm) { fprintf(atm, "%12e %12d %12d\n", output_env_conv_time(oenv, t), 1+(bMin ? min1 : max1), 1+(bMin ? min2 : max2)); } } if (trxout) { oindex[0] = bMin ? min1 : max1; oindex[1] = bMin ? min2 : max2; write_trx(trxout, 2, oindex, atoms, i, t, box, x0, NULL, NULL); } bFirst = FALSE; /*dmin should be minimum distance for residue and group*/ if (bEachResEachTime) { fprintf(respertime, "%12e", t); for (i = 1; i < ng; i++) { for (j = 0; j < nres; j++) { fprintf(respertime, " %7g", bMin ? mindres[i-1][j] : maxdres[i-1][j]); /*reset distances for next time point*/ mindres[i-1][j] = 1e6; maxdres[i-1][j] = 0; } } fprintf(respertime, "\n"); } } while (read_next_x(oenv, status, &t, x0, box)); close_trj(status); ffclose(dist); if (num) { ffclose(num); } if (atm) { ffclose(atm); } if (trxout) { close_trx(trxout); } if (nres && !bEachResEachTime) { FILE *res; sprintf(buf, "%simum Distance", bMin ? "Min" : "Max"); res = xvgropen(rfile, buf, "Residue (#)", "Distance (nm)", oenv); xvgr_legend(res, ng-1, (const char**)leg, oenv); for (j = 0; j < nres; j++) { fprintf(res, "%4d", j+1); for (i = 1; i < ng; i++) { fprintf(res, " %7g", bMin ? mindres[i-1][j] : maxdres[i-1][j]); } fprintf(res, "\n"); } } sfree(x0); }
int gmx_filter(int argc,char *argv[]) { const char *desc[] = { "[TT]g_filter[tt] performs frequency filtering on a trajectory.", "The filter shape is cos([GRK]pi[grk] t/A) + 1 from -A to +A, where A is given", "by the option [TT]-nf[tt] times the time step in the input trajectory.", "This filter reduces fluctuations with period A by 85%, with period", "2*A by 50% and with period 3*A by 17% for low-pass filtering.", "Both a low-pass and high-pass filtered trajectory can be written.[PAR]", "Option [TT]-ol[tt] writes a low-pass filtered trajectory.", "A frame is written every [TT]-nf[tt] input frames.", "This ratio of filter length and output interval ensures a good", "suppression of aliasing of high-frequency motion, which is useful for", "making smooth movies. Also averages of properties which are linear", "in the coordinates are preserved, since all input frames are weighted", "equally in the output.", "When all frames are needed, use the [TT]-all[tt] option.[PAR]", "Option [TT]-oh[tt] writes a high-pass filtered trajectory.", "The high-pass filtered coordinates are added to the coordinates", "from the structure file. When using high-pass filtering use [TT]-fit[tt]", "or make sure you use a trajectory that has been fitted on", "the coordinates in the structure file." }; static int nf=10; static gmx_bool bNoJump = TRUE,bFit = FALSE,bLowAll = FALSE; t_pargs pa[] = { { "-nf", FALSE, etINT, {&nf}, "Sets the filter length as well as the output interval for low-pass filtering" }, { "-all", FALSE, etBOOL, {&bLowAll}, "Write all low-pass filtered frames" }, { "-nojump", FALSE, etBOOL, {&bNoJump}, "Remove jumps of atoms across the box" }, { "-fit", FALSE, etBOOL, {&bFit}, "Fit all frames to a reference structure" } }; const char *topfile,*lowfile,*highfile; gmx_bool bTop=FALSE; t_topology top; int ePBC=-1; rvec *xtop; matrix topbox,*box,boxf; char title[256],*grpname; int isize; atom_id *index; real *w_rls=NULL; t_trxstatus *in; t_trxstatus *outl,*outh; int nffr,i,fr,nat,j,d,m; atom_id *ind; real flen,*filt,sum,*t; rvec xcmtop,xcm,**x,*ptr,*xf,*xn,*xp,hbox; output_env_t oenv; gmx_rmpbc_t gpbc=NULL; #define NLEG asize(leg) t_filenm fnm[] = { { efTRX, "-f", NULL, ffREAD }, { efTPS, NULL, NULL, ffOPTRD }, { efNDX, NULL, NULL, ffOPTRD }, { efTRO, "-ol", "lowpass", ffOPTWR }, { efTRO, "-oh", "highpass", ffOPTWR } }; #define NFILE asize(fnm) 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); highfile = opt2fn_null("-oh",NFILE,fnm); if (highfile) { topfile = ftp2fn(efTPS,NFILE,fnm); lowfile = opt2fn_null("-ol",NFILE,fnm); } else { topfile = ftp2fn_null(efTPS,NFILE,fnm); lowfile = opt2fn("-ol",NFILE,fnm); } if (topfile) { bTop = read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC, &xtop,NULL,topbox,TRUE); if (bTop) { gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,topbox); gmx_rmpbc(gpbc,top.atoms.nr,topbox,xtop); } } clear_rvec(xcmtop); if (bFit) { fprintf(stderr,"Select group for least squares fit\n"); get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpname); /* Set the weight */ snew(w_rls,top.atoms.nr); for(i=0; i<isize; i++) w_rls[index[i]] = top.atoms.atom[index[i]].m; calc_xcm(xtop,isize,index,top.atoms.atom,xcmtop,FALSE); for(j=0; j<top.atoms.nr; j++) rvec_dec(xtop[j],xcmtop); } /* The actual filter length flen can actually be any real number */ flen = 2*nf; /* nffr is the number of frames that we filter over */ nffr = 2*nf - 1; snew(filt,nffr); sum = 0; for(i=0; i<nffr; i++) { filt[i] = cos(2*M_PI*(i - nf + 1)/(real)flen) + 1; sum += filt[i]; } fprintf(stdout,"filter weights:"); for(i=0; i<nffr; i++) { filt[i] /= sum; fprintf(stdout," %5.3f",filt[i]); } fprintf(stdout,"\n"); snew(t,nffr); snew(x,nffr); snew(box,nffr); nat = read_first_x(oenv,&in,opt2fn("-f",NFILE,fnm), &(t[nffr - 1]),&(x[nffr - 1]),box[nffr - 1]); snew(ind,nat); for(i=0; i<nat; i++) ind[i] = i; /* x[nffr - 1] was already allocated by read_first_x */ for(i=0; i<nffr-1; i++) snew(x[i],nat); snew(xf,nat); if (lowfile) outl = open_trx(lowfile,"w"); else outl = 0; if (highfile) outh = open_trx(highfile,"w"); else outh = 0; fr = 0; do { xn = x[nffr - 1]; if (bNoJump && fr > 0) { xp = x[nffr - 2]; for(j=0; j<nat; j++) for(d=0; d<DIM; d++) hbox[d] = 0.5*box[nffr - 1][d][d]; for(i=0; i<nat; i++) for(m=DIM-1; m>=0; m--) if (hbox[m] > 0) { while (xn[i][m] - xp[i][m] <= -hbox[m]) for(d=0; d<=m; d++) xn[i][d] += box[nffr - 1][m][d]; while (xn[i][m] - xp[i][m] > hbox[m]) for(d=0; d<=m; d++) xn[i][d] -= box[nffr - 1][m][d]; } } if (bTop) { gmx_rmpbc(gpbc,nat,box[nffr - 1],xn); } if (bFit) { calc_xcm(xn,isize,index,top.atoms.atom,xcm,FALSE); for(j=0; j<nat; j++) rvec_dec(xn[j],xcm); do_fit(nat,w_rls,xtop,xn); for(j=0; j<nat; j++) rvec_inc(xn[j],xcmtop); } if (fr >= nffr && (outh || bLowAll || fr % nf == nf - 1)) { /* Lowpass filtering */ for(j=0; j<nat; j++) clear_rvec(xf[j]); clear_mat(boxf); for(i=0; i<nffr; i++) { for(j=0; j<nat; j++) for(d=0; d<DIM; d++) xf[j][d] += filt[i]*x[i][j][d]; for(j=0; j<DIM; j++) for(d=0; d<DIM; d++) boxf[j][d] += filt[i]*box[i][j][d]; } if (outl && (bLowAll || fr % nf == nf - 1)) write_trx(outl,nat,ind,topfile ? &(top.atoms) : NULL, 0,t[nf - 1],bFit ? topbox : boxf,xf,NULL,NULL); if (outh) { /* Highpass filtering */ for(j=0; j<nat; j++) for(d=0; d<DIM; d++) xf[j][d] = xtop[j][d] + x[nf - 1][j][d] - xf[j][d]; if (bFit) for(j=0; j<nat; j++) rvec_inc(xf[j],xcmtop); for(j=0; j<DIM; j++) for(d=0; d<DIM; d++) boxf[j][d] = topbox[j][d] + box[nf - 1][j][d] - boxf[j][d]; write_trx(outh,nat,ind,topfile ? &(top.atoms) : NULL, 0,t[nf - 1],bFit ? topbox : boxf,xf,NULL,NULL); } } /* Cycle all the pointer and the box by one */ ptr = x[0]; for(i=0; i<nffr-1; i++) { t[i] = t[i+1]; x[i] = x[i+1]; copy_mat(box[i+1],box[i]); } x[nffr - 1] = ptr; fr++; } while (read_next_x(oenv,in,&(t[nffr - 1]),nat,x[nffr - 1],box[nffr - 1])); if (bTop) gmx_rmpbc_done(gpbc); if (outh) close_trx(outh); if (outl) close_trx(outl); close_trx(in); return 0; }
static void analyze_clusters(int nf, t_clusters *clust, real **rmsd, int natom, t_atoms *atoms, rvec *xtps, real *mass, rvec **xx, real *time, int ifsize, atom_id *fitidx, int iosize, atom_id *outidx, char *trxfn, char *sizefn, char *transfn, char *ntransfn, char *clustidfn, bool bAverage, int write_ncl, int write_nst, real rmsmin,bool bFit, FILE *log,t_rgb rlo,t_rgb rhi) { FILE *fp=NULL; char buf[STRLEN],buf1[40],buf2[40],buf3[40],*trxsfn; int trxout=0,trxsout=0; int i,i1,cl,nstr,*structure,first=0,midstr; bool *bWrite=NULL; real r,clrmsd,midrmsd; rvec *xav=NULL; matrix zerobox; clear_mat(zerobox); ffprintf1(stderr,log,buf,"\nFound %d clusters\n\n",clust->ncl); trxsfn=NULL; if (trxfn) { /* do we write all structures? */ if (write_ncl) { trxsfn = parse_filename(trxfn, max(write_ncl,clust->ncl)); snew(bWrite,nf); } ffprintf2(stderr,log,buf,"Writing %s structure for each cluster to %s\n", bAverage ? "average" : "middle", trxfn); if (write_ncl) { /* find out what we want to tell the user: Writing [all structures|structures with rmsd > %g] for {all|first %d} clusters {with more than %d structures} to %s */ if (rmsmin>0.0) sprintf(buf1,"structures with rmsd > %g",rmsmin); else sprintf(buf1,"all structures"); buf2[0]=buf3[0]='\0'; if (write_ncl>=clust->ncl) { if (write_nst==0) sprintf(buf2,"all "); } else sprintf(buf2,"the first %d ",write_ncl); if (write_nst) sprintf(buf3," with more than %d structures",write_nst); sprintf(buf,"Writing %s for %sclusters%s to %s\n",buf1,buf2,buf3,trxsfn); ffprintf(stderr,log,buf); } /* Prepare a reference structure for the orientation of the clusters */ if (bFit) reset_x(ifsize,fitidx,natom,NULL,xtps,mass); trxout = open_trx(trxfn,"w"); /* Calculate the average structure in each cluster, * * all structures are fitted to the first struture of the cluster */ snew(xav,natom); } if (transfn || ntransfn) ana_trans(clust, nf, transfn, ntransfn, log,rlo,rhi); if (clustidfn) { fp=xvgropen(clustidfn,"Clusters",xvgr_tlabel(),"Cluster #"); fprintf(fp,"@ s0 symbol 2\n"); fprintf(fp,"@ s0 symbol size 0.2\n"); fprintf(fp,"@ s0 linestyle 0\n"); for(i=0; i<nf; i++) fprintf(fp,"%8g %8d\n",time[i],clust->cl[i]); ffclose(fp); } if (sizefn) { fp=xvgropen(sizefn,"Cluster Sizes","Cluster #","# Structures"); fprintf(fp,"@g%d type %s\n",0,"bar"); } snew(structure,nf); fprintf(log,"\n%3s | %3s %4s | %6s %4s | cluster members\n", "cl.","#st","rmsd","middle","rmsd"); for(cl=1; cl<=clust->ncl; cl++) { /* prepare structures (fit, middle, average) */ if (xav) for(i=0; i<natom;i++) clear_rvec(xav[i]); nstr=0; for(i1=0; i1<nf; i1++) if (clust->cl[i1] == cl) { structure[nstr] = i1; nstr++; if (trxfn && (bAverage || write_ncl) ) { if (bFit) reset_x(ifsize,fitidx,natom,NULL,xx[i1],mass); if (nstr == 1) first = i1; else if (bFit) do_fit(natom,mass,xx[first],xx[i1]); if (xav) for(i=0; i<natom; i++) rvec_inc(xav[i],xx[i1][i]); } } if (sizefn) fprintf(fp,"%8d %8d\n",cl,nstr); clrmsd = 0; midstr = 0; midrmsd = 10000; for(i1=0; i1<nstr; i1++) { r = 0; if (nstr > 1) { for(i=0; i<nstr; i++) if (i < i1) r += rmsd[structure[i]][structure[i1]]; else r += rmsd[structure[i1]][structure[i]]; r /= (nstr - 1); } if ( r < midrmsd ) { midstr = structure[i1]; midrmsd = r; } clrmsd += r; } clrmsd /= nstr; /* dump cluster info to logfile */ if (nstr > 1) { sprintf(buf1,"%5.3f",clrmsd); if (buf1[0] == '0') buf1[0] = ' '; sprintf(buf2,"%5.3f",midrmsd); if (buf2[0] == '0') buf2[0] = ' '; } else { sprintf(buf1,"%5s",""); sprintf(buf2,"%5s",""); } fprintf(log,"%3d | %3d%s | %6g%s |",cl,nstr,buf1,time[midstr],buf2); for(i=0; i<nstr; i++) { if ((i % 7 == 0) && i) sprintf(buf,"\n%3s | %3s %4s | %6s %4s |","","","","",""); else buf[0] = '\0'; i1 = structure[i]; fprintf(log,"%s %6g",buf,time[i1]); } fprintf(log,"\n"); /* write structures to trajectory file(s) */ if (trxfn) { if (write_ncl) for(i=0; i<nstr; i++) bWrite[i]=FALSE; if ( cl < write_ncl+1 && nstr > write_nst ) { /* Dump all structures for this cluster */ /* generate numbered filename (there is a %d in trxfn!) */ sprintf(buf,trxsfn,cl); trxsout = open_trx(buf,"w"); for(i=0; i<nstr; i++) { bWrite[i] = TRUE; if (rmsmin>0.0) for(i1=0; i1<i && bWrite[i]; i1++) if (bWrite[i1]) bWrite[i] = rmsd[structure[i1]][structure[i]] > rmsmin; if (bWrite[i]) write_trx(trxsout,iosize,outidx,atoms,i,time[structure[i]],zerobox, xx[structure[i]],NULL); } close_trx(trxsout); } /* Dump the average structure for this cluster */ if (bAverage) { for(i=0; i<natom; i++) svmul(1.0/nstr,xav[i],xav[i]); } else { for(i=0; i<natom; i++) copy_rvec(xx[midstr][i],xav[i]); if (bFit) reset_x(ifsize,fitidx,natom,NULL,xav,mass); } if (bFit) do_fit(natom,mass,xtps,xav); r = cl; write_trx(trxout,iosize,outidx,atoms,cl,time[midstr],zerobox,xav,NULL); } } /* clean up */ if (trxfn) { close_trx(trxout); sfree(xav); if (write_ncl) sfree(bWrite); } sfree(structure); if (trxsfn) sfree(trxsfn); }