Made removing pbc non-static. This affects many analysis tools and small
[gromacs.git] / src / tools / gmx_mdmat.c
blob2cd9c1d26f6f2437e7bb65486dd87901c7e11804
1 /*
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 3.2.0
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
32 * And Hey:
33 * Green Red Orange Magenta Azure Cyan Skyblue
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <math.h>
40 #include <string.h>
42 #include "macros.h"
43 #include "vec.h"
44 #include "sysstuff.h"
45 #include "typedefs.h"
46 #include "filenm.h"
47 #include "statutil.h"
48 #include "copyrite.h"
49 #include "futil.h"
50 #include "gmx_fatal.h"
51 #include "smalloc.h"
52 #include "matio.h"
53 #include "xvgr.h"
54 #include "index.h"
55 #include "tpxio.h"
56 #include "rmpbc.h"
57 #include "pbc.h"
58 #include "gmx_ana.h"
61 #define FARAWAY 10000
63 int *res_ndx(t_atoms *atoms)
65 int *rndx;
66 int i,r0;
68 if (atoms->nr <= 0)
69 return NULL;
70 snew(rndx,atoms->nr);
71 r0=atoms->atom[0].resind;
72 for(i=0; (i<atoms->nr); i++)
73 rndx[i]=atoms->atom[i].resind-r0;
75 return rndx;
78 int *res_natm(t_atoms *atoms)
80 int *natm;
81 int i,j,r0;
83 if (atoms->nr <= 0)
84 return NULL;
85 snew(natm,atoms->nres);
86 r0=atoms->atom[0].resind;
87 j=0;
88 for(i=0; (i<atoms->nres); i++) {
89 while ((atoms->atom[j].resind)-r0 == i) {
90 natm[i]++;
91 j++;
95 return natm;
98 static void calc_mat(int nres, int natoms, int rndx[],
99 rvec x[], atom_id *index,
100 real trunc, real **mdmat,int **nmat,int ePBC,matrix box)
102 int i,j,resi,resj;
103 real trunc2,r,r2;
104 t_pbc pbc;
105 rvec ddx;
107 set_pbc(&pbc,ePBC,box);
108 trunc2=sqr(trunc);
109 for(resi=0; (resi<nres); resi++)
110 for(resj=0; (resj<nres); resj++)
111 mdmat[resi][resj]=FARAWAY;
112 for(i=0; (i<natoms); i++) {
113 resi=rndx[i];
114 for(j=i+1; (j<natoms); j++) {
115 resj=rndx[j];
116 pbc_dx(&pbc,x[index[i]],x[index[j]],ddx);
117 r2 = norm2(ddx);
118 if ( r2 < trunc2 ) {
119 nmat[resi][j]++;
120 nmat[resj][i]++;
122 mdmat[resi][resj]=min(r2,mdmat[resi][resj]);
126 for(resi=0; (resi<nres); resi++) {
127 mdmat[resi][resi]=0;
128 for(resj=resi+1; (resj<nres); resj++) {
129 r=sqrt(mdmat[resi][resj]);
130 mdmat[resi][resj]=r;
131 mdmat[resj][resi]=r;
136 static void tot_nmat(int nres, int natoms, int nframes, int **nmat,
137 int *tot_n, real *mean_n)
139 int i,j;
141 for (i=0; (i<nres); i++) {
142 for (j=0; (j<natoms); j++)
143 if (nmat[i][j] != 0) {
144 tot_n[i]++;
145 mean_n[i]+=nmat[i][j];
147 mean_n[i]/=nframes;
151 int gmx_mdmat(int argc,char *argv[])
153 const char *desc[] = {
154 "g_mdmat makes distance matrices consisting of the smallest distance",
155 "between residue pairs. With -frames these distance matrices can be",
156 "stored as a function",
157 "of time, to be able to see differences in tertiary structure as a",
158 "funcion of time. If you choose your options unwise, this may generate",
159 "a large output file. Default only an averaged matrix over the whole",
160 "trajectory is output.",
161 "Also a count of the number of different atomic contacts between",
162 "residues over the whole trajectory can be made.",
163 "The output can be processed with xpm2ps to make a PostScript (tm) plot."
165 static real truncate=1.5;
166 static bool bAtom=FALSE;
167 static int nlevels=40;
168 t_pargs pa[] = {
169 { "-t", FALSE, etREAL, {&truncate},
170 "trunc distance" },
171 { "-nlevels", FALSE, etINT, {&nlevels},
172 "Discretize distance in # levels" }
174 t_filenm fnm[] = {
175 { efTRX, "-f", NULL, ffREAD },
176 { efTPS, NULL, NULL, ffREAD },
177 { efNDX, NULL, NULL, ffOPTRD },
178 { efXPM, "-mean", "dm", ffWRITE },
179 { efXPM, "-frames", "dmf", ffOPTWR },
180 { efXVG, "-no", "num",ffOPTWR },
182 #define NFILE asize(fnm)
184 FILE *out=NULL,*fp;
185 t_topology top;
186 int ePBC;
187 t_atoms useatoms;
188 int isize;
189 atom_id *index;
190 char *grpname;
191 int *rndx,*natm,prevres,newres;
193 int i,j,nres,natoms,nframes,it,trxnat;
194 t_trxstatus *status;
195 int nr0;
196 bool bCalcN,bFrames;
197 real t,ratio;
198 char title[256],label[234];
199 t_rgb rlo,rhi;
200 rvec *x;
201 real **mdmat,*resnr,**totmdmat;
202 int **nmat,**totnmat;
203 real *mean_n;
204 int *tot_n;
205 matrix box;
206 output_env_t oenv;
207 gmx_rmpbc_t gpbc=NULL;
209 CopyRight(stderr,argv[0]);
211 parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE,NFILE,fnm,
212 asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
214 fprintf(stderr,"Will truncate at %f nm\n",truncate);
215 bCalcN = opt2bSet("-no",NFILE,fnm);
216 bFrames= opt2bSet("-frames",NFILE,fnm);
217 if ( bCalcN )
218 fprintf(stderr,"Will calculate number of different contacts\n");
220 read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x,NULL,box,FALSE);
222 fprintf(stderr,"Select group for analysis\n");
223 get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
225 natoms=isize;
226 snew(useatoms.atom,natoms);
227 snew(useatoms.atomname,natoms);
229 useatoms.nres = 0;
230 snew(useatoms.resinfo,natoms);
232 prevres = top.atoms.atom[index[0]].resind;
233 newres = 0;
234 for(i=0;(i<isize);i++) {
235 int ii = index[i];
236 useatoms.atomname[i]=top.atoms.atomname[ii];
237 if (top.atoms.atom[ii].resind != prevres) {
238 prevres = top.atoms.atom[ii].resind;
239 newres++;
240 useatoms.resinfo[i] = top.atoms.resinfo[prevres];
241 if (debug) {
242 fprintf(debug,"New residue: atom %5s %5s %6d, index entry %5d, newres %5d\n",
243 *(top.atoms.resinfo[top.atoms.atom[ii].resind].name),
244 *(top.atoms.atomname[ii]),
245 ii,i,newres);
248 useatoms.atom[i].resind = newres;
250 useatoms.nres = newres+1;
251 useatoms.nr = isize;
253 rndx=res_ndx(&(useatoms));
254 natm=res_natm(&(useatoms));
255 nres=useatoms.nres;
256 fprintf(stderr,"There are %d residues with %d atoms\n",nres,natoms);
258 snew(resnr,nres);
259 snew(mdmat,nres);
260 snew(nmat,nres);
261 snew(totnmat,nres);
262 snew(mean_n,nres);
263 snew(tot_n,nres);
264 for(i=0; (i<nres); i++) {
265 snew(mdmat[i],nres);
266 snew(nmat[i],natoms);
267 snew(totnmat[i],natoms);
268 resnr[i]=i+1;
270 snew(totmdmat,nres);
271 for(i=0; (i<nres); i++)
272 snew(totmdmat[i],nres);
274 trxnat=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
276 nframes=0;
278 rlo.r=1.0, rlo.g=1.0, rlo.b=1.0;
279 rhi.r=0.0, rhi.g=0.0, rhi.b=0.0;
281 gpbc = gmx_rmpbc_init(&top.idef,ePBC,trxnat,box);
283 if (bFrames)
284 out=opt2FILE("-frames",NFILE,fnm,"w");
285 do {
286 gmx_rmpbc(gpbc,box,x,x);
287 nframes++;
288 calc_mat(nres,natoms,rndx,x,index,truncate,mdmat,nmat,ePBC,box);
289 for (i=0; (i<nres); i++)
290 for (j=0; (j<natoms); j++)
291 if (nmat[i][j])
292 totnmat[i][j]++;
293 for (i=0; (i<nres); i++)
294 for (j=0; (j<nres); j++)
295 totmdmat[i][j] += mdmat[i][j];
296 if (bFrames) {
297 sprintf(label,"t=%.0f ps",t);
298 write_xpm(out,0,label,"Distance (nm)","Residue Index","Residue Index",
299 nres,nres,resnr,resnr,mdmat,0,truncate,rlo,rhi,&nlevels);
301 } while (read_next_x(oenv,status,&t,trxnat,x,box));
302 fprintf(stderr,"\n");
303 close_trj(status);
304 gmx_rmpbc_done(gpbc);
305 if (bFrames)
306 ffclose(out);
308 fprintf(stderr,"Processed %d frames\n",nframes);
310 for (i=0; (i<nres); i++)
311 for (j=0; (j<nres); j++)
312 totmdmat[i][j] /= nframes;
313 write_xpm(opt2FILE("-mean",NFILE,fnm,"w"),0,"Mean smallest distance",
314 "Distance (nm)","Residue Index","Residue Index",
315 nres,nres,resnr,resnr,totmdmat,0,truncate,rlo,rhi,&nlevels);
317 if ( bCalcN ) {
318 tot_nmat(nres,natoms,nframes,totnmat,tot_n,mean_n);
319 fp=xvgropen(ftp2fn(efXVG,NFILE,fnm),
320 "Increase in number of contacts","Residue","Ratio",oenv);
321 fprintf(fp,"@ legend on\n");
322 fprintf(fp,"@ legend box on\n");
323 fprintf(fp,"@ legend loctype view\n");
324 fprintf(fp,"@ legend 0.75, 0.8\n");
325 fprintf(fp,"@ legend string 0 \"Total/mean\"\n");
326 fprintf(fp,"@ legend string 1 \"Total\"\n");
327 fprintf(fp,"@ legend string 2 \"Mean\"\n");
328 fprintf(fp,"@ legend string 3 \"# atoms\"\n");
329 fprintf(fp,"@ legend string 4 \"Mean/# atoms\"\n");
330 fprintf(fp,"#%3s %8s %3s %8s %3s %8s\n",
331 "res","ratio","tot","mean","natm","mean/atm");
332 for (i=0; (i<nres); i++) {
333 if (mean_n[i]==0)
334 ratio=1;
335 else
336 ratio=tot_n[i]/mean_n[i];
337 fprintf(fp,"%3d %8.3f %3d %8.3f %3d %8.3f\n",
338 i+1,ratio,tot_n[i],mean_n[i],natm[i],mean_n[i]/natm[i]);
340 ffclose(fp);
343 thanx(stderr);
345 return 0;