2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team,
6 * check out http://www.gromacs.org for more information.
7 * Copyright (c) 2012,2013, by the GROMACS development team, led by
8 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9 * others, as listed in the AUTHORS file in the top-level source
10 * directory and at http://www.gromacs.org.
12 * GROMACS is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 2.1
15 * of the License, or (at your option) any later version.
17 * GROMACS is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with GROMACS; if not, see
24 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * If you want to redistribute modifications to GROMACS, please
28 * consider that scientific software is very special. Version
29 * control is crucial - bugs must be traceable. We will be happy to
30 * consider code for inclusion in the official distribution, but
31 * derived work must not be called official GROMACS. Details are found
32 * in the README & COPYING files - if they are missing, get the
33 * official version at http://www.gromacs.org.
35 * To help us fund GROMACS development, we humbly ask that you cite
36 * the research papers on the package. Check out http://www.gromacs.org.
53 #include "gmx_fatal.h"
66 int *res_ndx(t_atoms *atoms)
74 r0=atoms->atom[0].resind;
75 for(i=0; (i<atoms->nr); i++)
76 rndx[i]=atoms->atom[i].resind-r0;
81 int *res_natm(t_atoms *atoms)
88 snew(natm,atoms->nres);
89 r0=atoms->atom[0].resind;
91 for(i=0; (i<atoms->nres); i++) {
92 while ((atoms->atom[j].resind)-r0 == i) {
101 static void calc_mat(int nres, int natoms, int rndx[],
102 rvec x[], atom_id *index,
103 real trunc, real **mdmat,int **nmat,int ePBC,matrix box)
110 set_pbc(&pbc,ePBC,box);
112 for(resi=0; (resi<nres); resi++)
113 for(resj=0; (resj<nres); resj++)
114 mdmat[resi][resj]=FARAWAY;
115 for(i=0; (i<natoms); i++) {
117 for(j=i+1; (j<natoms); j++) {
119 pbc_dx(&pbc,x[index[i]],x[index[j]],ddx);
125 mdmat[resi][resj]=min(r2,mdmat[resi][resj]);
129 for(resi=0; (resi<nres); resi++) {
131 for(resj=resi+1; (resj<nres); resj++) {
132 r=sqrt(mdmat[resi][resj]);
139 static void tot_nmat(int nres, int natoms, int nframes, int **nmat,
140 int *tot_n, real *mean_n)
144 for (i=0; (i<nres); i++) {
145 for (j=0; (j<natoms); j++)
146 if (nmat[i][j] != 0) {
148 mean_n[i]+=nmat[i][j];
154 int gmx_mdmat(int argc,char *argv[])
156 const char *desc[] = {
157 "[TT]g_mdmat[tt] makes distance matrices consisting of the smallest distance",
158 "between residue pairs. With [TT]-frames[tt], these distance matrices can be",
159 "stored in order to see differences in tertiary structure as a",
160 "function of time. If you choose your options unwisely, this may generate",
161 "a large output file. By default, only an averaged matrix over the whole",
162 "trajectory is output.",
163 "Also a count of the number of different atomic contacts between",
164 "residues over the whole trajectory can be made.",
165 "The output can be processed with [TT]xpm2ps[tt] to make a PostScript (tm) plot."
167 static real truncate=1.5;
168 static gmx_bool bAtom=FALSE;
169 static int nlevels=40;
171 { "-t", FALSE, etREAL, {&truncate},
173 { "-nlevels", FALSE, etINT, {&nlevels},
174 "Discretize distance in this number of levels" }
177 { efTRX, "-f", NULL, ffREAD },
178 { efTPS, NULL, NULL, ffREAD },
179 { efNDX, NULL, NULL, ffOPTRD },
180 { efXPM, "-mean", "dm", ffWRITE },
181 { efXPM, "-frames", "dmf", ffOPTWR },
182 { efXVG, "-no", "num",ffOPTWR },
184 #define NFILE asize(fnm)
193 int *rndx,*natm,prevres,newres;
195 int i,j,nres,natoms,nframes,it,trxnat;
198 gmx_bool bCalcN,bFrames;
200 char title[256],label[234];
203 real **mdmat,*resnr,**totmdmat;
204 int **nmat,**totnmat;
209 gmx_rmpbc_t gpbc=NULL;
211 CopyRight(stderr,argv[0]);
213 parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE,NFILE,fnm,
214 asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
216 fprintf(stderr,"Will truncate at %f nm\n",truncate);
217 bCalcN = opt2bSet("-no",NFILE,fnm);
218 bFrames= opt2bSet("-frames",NFILE,fnm);
220 fprintf(stderr,"Will calculate number of different contacts\n");
222 read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x,NULL,box,FALSE);
224 fprintf(stderr,"Select group for analysis\n");
225 get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
228 snew(useatoms.atom,natoms);
229 snew(useatoms.atomname,natoms);
232 snew(useatoms.resinfo,natoms);
234 prevres = top.atoms.atom[index[0]].resind;
236 for(i=0;(i<isize);i++) {
238 useatoms.atomname[i]=top.atoms.atomname[ii];
239 if (top.atoms.atom[ii].resind != prevres) {
240 prevres = top.atoms.atom[ii].resind;
242 useatoms.resinfo[i] = top.atoms.resinfo[prevres];
244 fprintf(debug,"New residue: atom %5s %5s %6d, index entry %5d, newres %5d\n",
245 *(top.atoms.resinfo[top.atoms.atom[ii].resind].name),
246 *(top.atoms.atomname[ii]),
250 useatoms.atom[i].resind = newres;
252 useatoms.nres = newres+1;
255 rndx=res_ndx(&(useatoms));
256 natm=res_natm(&(useatoms));
258 fprintf(stderr,"There are %d residues with %d atoms\n",nres,natoms);
266 for(i=0; (i<nres); i++) {
268 snew(nmat[i],natoms);
269 snew(totnmat[i],natoms);
273 for(i=0; (i<nres); i++)
274 snew(totmdmat[i],nres);
276 trxnat=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
280 rlo.r=1.0, rlo.g=1.0, rlo.b=1.0;
281 rhi.r=0.0, rhi.g=0.0, rhi.b=0.0;
283 gpbc = gmx_rmpbc_init(&top.idef,ePBC,trxnat,box);
286 out=opt2FILE("-frames",NFILE,fnm,"w");
288 gmx_rmpbc(gpbc,trxnat,box,x);
290 calc_mat(nres,natoms,rndx,x,index,truncate,mdmat,nmat,ePBC,box);
291 for (i=0; (i<nres); i++)
292 for (j=0; (j<natoms); j++)
295 for (i=0; (i<nres); i++)
296 for (j=0; (j<nres); j++)
297 totmdmat[i][j] += mdmat[i][j];
299 sprintf(label,"t=%.0f ps",t);
300 write_xpm(out,0,label,"Distance (nm)","Residue Index","Residue Index",
301 nres,nres,resnr,resnr,mdmat,0,truncate,rlo,rhi,&nlevels);
303 } while (read_next_x(oenv,status,&t,trxnat,x,box));
304 fprintf(stderr,"\n");
306 gmx_rmpbc_done(gpbc);
310 fprintf(stderr,"Processed %d frames\n",nframes);
312 for (i=0; (i<nres); i++)
313 for (j=0; (j<nres); j++)
314 totmdmat[i][j] /= nframes;
315 write_xpm(opt2FILE("-mean",NFILE,fnm,"w"),0,"Mean smallest distance",
316 "Distance (nm)","Residue Index","Residue Index",
317 nres,nres,resnr,resnr,totmdmat,0,truncate,rlo,rhi,&nlevels);
320 tot_nmat(nres,natoms,nframes,totnmat,tot_n,mean_n);
321 fp=xvgropen(ftp2fn(efXVG,NFILE,fnm),
322 "Increase in number of contacts","Residue","Ratio",oenv);
323 fprintf(fp,"@ legend on\n");
324 fprintf(fp,"@ legend box on\n");
325 fprintf(fp,"@ legend loctype view\n");
326 fprintf(fp,"@ legend 0.75, 0.8\n");
327 fprintf(fp,"@ legend string 0 \"Total/mean\"\n");
328 fprintf(fp,"@ legend string 1 \"Total\"\n");
329 fprintf(fp,"@ legend string 2 \"Mean\"\n");
330 fprintf(fp,"@ legend string 3 \"# atoms\"\n");
331 fprintf(fp,"@ legend string 4 \"Mean/# atoms\"\n");
332 fprintf(fp,"#%3s %8s %3s %8s %3s %8s\n",
333 "res","ratio","tot","mean","natm","mean/atm");
334 for (i=0; (i<nres); i++) {
338 ratio=tot_n[i]/mean_n[i];
339 fprintf(fp,"%3d %8.3f %3d %8.3f %3d %8.3f\n",
340 i+1,ratio,tot_n[i],mean_n[i],natm[i],mean_n[i]/natm[i]);