3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
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
33 * Green Red Orange Magenta Azure Cyan Skyblue
51 #include "gmx_fatal.h"
58 static void dump_dih_trn(int nframes
,int nangles
,real
**dih
,const char *fn
,
64 matrix box
= {{2,0,0},{0,2,0},{0,0,2}};
71 printf("There are %d dihedrals. Will fill %d atom positions with cos/sin\n",
74 trn
= open_trn(fn
,"w");
75 for(i
=0; (i
<nframes
); i
++) {
77 for(j
=0; (j
<nangles
); j
++) {
78 for(m
=0; (m
<2); m
++) {
79 x
[k
][l
] = (m
== 0) ? cos(dih
[j
][i
]) : sin(dih
[j
][i
]);
87 fwrite_trn(trn
,i
,(real
)i
*dt
,0,box
,na
,x
,NULL
,NULL
);
93 int gmx_g_angle(int argc
,char *argv
[])
95 static const char *desc
[] = {
96 "g_angle computes the angle distribution for a number of angles",
97 "or dihedrals. This way you can check whether your simulation",
98 "is correct. With option -ov you can plot the average angle of",
99 "a group of angles as a function of time. With the -all option",
100 "the first graph is the average, the rest are the individual angles.[PAR]",
101 "With the -of option g_angle also calculates the fraction of trans",
102 "dihedrals (only for dihedrals) as function of time, but this is",
103 "probably only fun for a selected few.[PAR]",
104 "With option -oc a dihedral correlation function is calculated.[PAR]",
105 "It should be noted that the indexfile should contain",
106 "atom-triples for angles or atom-quadruplets for dihedrals.",
107 "If this is not the case, the program will crash.[PAR]",
108 "With option [TT]-or[tt] a trajectory file is dumped containing cos and",
109 "sin of selected dihedral angles which subsequently can be used as",
110 "input for a PCA analysis using [TT]g_covar[tt]."
112 static const char *opt
[] = { NULL
, "angle", "dihedral", "improper", "ryckaert-bellemans", NULL
};
113 static gmx_bool bALL
=FALSE
,bChandler
=FALSE
,bAverCorr
=FALSE
,bPBC
=TRUE
;
114 static real binwidth
=1;
116 { "-type", FALSE
, etENUM
, {opt
},
117 "Type of angle to analyse" },
118 { "-all", FALSE
, etBOOL
, {&bALL
},
119 "Plot all angles separately in the averages file, in the order of appearance in the index file." },
120 { "-binwidth", FALSE
, etREAL
, {&binwidth
},
121 "binwidth (degrees) for calculating the distribution" },
122 { "-periodic", FALSE
, etBOOL
, {&bPBC
},
123 "Print dihedral angles modulo 360 degrees" },
124 { "-chandler", FALSE
, etBOOL
, {&bChandler
},
125 "Use Chandler correlation function (N[trans] = 1, N[gauche] = 0) rather than cosine correlation function. Trans is defined as phi < -60 || phi > 60." },
126 { "-avercorr", FALSE
, etBOOL
, {&bAverCorr
},
127 "Average the correlation functions for the individual angles/dihedrals" }
129 static const char *bugs
[] = {
130 "Counting transitions only works for dihedrals with multiplicity 3"
138 real maxang
,Jc
,S2
,norm_fac
,maxstat
;
140 int nframes
,maxangstat
,mult
,*angstat
;
141 int i
,j
,total
,nangles
,natoms
,nat2
,first
,last
,angind
;
142 gmx_bool bAver
,bRb
,bPeriodic
,
143 bFrac
, /* calculate fraction too? */
144 bTrans
, /* worry about transtions too? */
145 bCorr
; /* correlation function ? */
146 real t
,aa
,aver
,aver2
,aversig
,fraction
; /* fraction trans dihedrals */
149 real
**dih
=NULL
; /* mega array with all dih. angles at all times*/
151 real
*time
,*trans_frac
,*aver_angle
;
153 { efTRX
, "-f", NULL
, ffREAD
},
154 { efNDX
, NULL
, "angle", ffREAD
},
155 { efXVG
, "-od", "angdist", ffWRITE
},
156 { efXVG
, "-ov", "angaver", ffOPTWR
},
157 { efXVG
, "-of", "dihfrac", ffOPTWR
},
158 { efXVG
, "-ot", "dihtrans", ffOPTWR
},
159 { efXVG
, "-oh", "trhisto", ffOPTWR
},
160 { efXVG
, "-oc", "dihcorr", ffOPTWR
},
161 { efTRR
, "-or", NULL
, ffOPTWR
}
163 #define NFILE asize(fnm)
168 CopyRight(stderr
,argv
[0]);
170 ppa
= add_acf_pargs(&npargs
,pa
);
171 parse_common_args(&argc
,argv
,PCA_CAN_VIEW
| PCA_CAN_TIME
| PCA_BE_NICE
,
172 NFILE
,fnm
,npargs
,ppa
,asize(desc
),desc
,asize(bugs
),bugs
,
192 if (opt2bSet("-or",NFILE
,fnm
)) {
194 gmx_fatal(FARGS
,"Can not combine angles with trn dump");
196 please_cite(stdout
,"Mu2005a");
199 /* Calculate bin size */
200 maxangstat
=(int)(maxang
/binwidth
+0.5);
201 binwidth
=maxang
/maxangstat
;
203 rd_index(ftp2fn(efNDX
,NFILE
,fnm
),1,&isize
,&index
,&grpname
);
205 if ((isize
% mult
) != 0)
206 gmx_fatal(FARGS
,"number of index elements not multiple of %d, "
207 "these can not be %s\n",
208 mult
,(mult
==3) ? "angle triplets" : "dihedral quadruplets");
211 /* Check whether specific analysis has to be performed */
212 bCorr
=opt2bSet("-oc",NFILE
,fnm
);
213 bAver
=opt2bSet("-ov",NFILE
,fnm
);
214 bTrans
=opt2bSet("-ot",NFILE
,fnm
);
215 bFrac
=opt2bSet("-of",NFILE
,fnm
);
217 if (bChandler
&& !bCorr
)
221 fprintf(stderr
,"Warning:"
222 " calculating fractions as defined in this program\n"
223 "makes sense for Ryckaert Bellemans dihs. only. Ignoring -of\n\n");
227 if ( (bTrans
|| bFrac
|| bCorr
) && mult
==3)
228 gmx_fatal(FARGS
,"Can only do transition, fraction or correlation\n"
229 "on dihedrals. Select -d\n");
232 * We need to know the nr of frames so we can allocate memory for an array
233 * with all dihedral angles at all timesteps. Works for me.
235 if (bTrans
|| bCorr
|| bALL
|| opt2bSet("-or",NFILE
,fnm
))
238 snew(angstat
,maxangstat
);
240 read_ang_dih(ftp2fn(efTRX
,NFILE
,fnm
),(mult
== 3),
241 bALL
|| bCorr
|| bTrans
|| opt2bSet("-or",NFILE
,fnm
),
242 bRb
,bPBC
,maxangstat
,angstat
,
243 &nframes
,&time
,isize
,index
,&trans_frac
,&aver_angle
,dih
,
246 dt
=(time
[nframes
-1]-time
[0])/(nframes
-1);
249 sprintf(title
,"Average Angle: %s",grpname
);
250 out
=xvgropen(opt2fn("-ov",NFILE
,fnm
),
251 title
,"Time (ps)","Angle (degrees)",oenv
);
252 for(i
=0; (i
<nframes
); i
++) {
253 fprintf(out
,"%10.5f %8.3f",time
[i
],aver_angle
[i
]*RAD2DEG
);
255 for(j
=0; (j
<nangles
); j
++)
258 fprintf(out
," %8.3f",atan2(sin(dd
),cos(dd
))*RAD2DEG
);
261 fprintf(out
," %8.3f",dih
[j
][i
]*RAD2DEG
);
267 if (opt2bSet("-or",NFILE
,fnm
))
268 dump_dih_trn(nframes
,nangles
,dih
,opt2fn("-or",NFILE
,fnm
),dt
);
271 sprintf(title
,"Trans fraction: %s",grpname
);
272 out
=xvgropen(opt2fn("-of",NFILE
,fnm
),
273 title
,"Time (ps)","Fraction",oenv
);
275 for(i
=0; (i
<nframes
); i
++) {
276 fprintf(out
,"%10.5f %10.3f\n",time
[i
],trans_frac
[i
]);
277 tfrac
+= trans_frac
[i
];
282 fprintf(stderr
,"Average trans fraction: %g\n",tfrac
);
287 ana_dih_trans(opt2fn("-ot",NFILE
,fnm
),opt2fn("-oh",NFILE
,fnm
),
288 dih
,nframes
,nangles
,grpname
,time
[0],dt
,bRb
,oenv
);
291 /* Autocorrelation function */
293 fprintf(stderr
,"Not enough frames for correlation function\n");
297 real dval
,sixty
=DEG2RAD
*60;
300 for(i
=0; (i
<nangles
); i
++)
301 for(j
=0; (j
<nframes
); j
++) {
304 bTest
=(dval
> -sixty
) && (dval
< sixty
);
306 bTest
=(dval
< -sixty
) || (dval
> sixty
);
308 dih
[i
][j
] = dval
-tfrac
;
317 do_autocorr(opt2fn("-oc",NFILE
,fnm
), oenv
,
318 "Dihedral Autocorrelation Function",
319 nframes
,nangles
,dih
,dt
,mode
,bAverCorr
);
324 /* Determine the non-zero part of the distribution */
325 for(first
=0; (first
< maxangstat
-1) && (angstat
[first
+1] == 0); first
++)
327 for(last
=maxangstat
-1; (last
> 0) && (angstat
[last
-1] == 0) ; last
--)
331 for(i
=0; (i
<nframes
); i
++) {
332 aver
+= RAD2DEG
*aver_angle
[i
];
333 aver2
+= sqr(RAD2DEG
*aver_angle
[i
]);
335 aver
/= (real
) nframes
;
336 aver2
/= (real
) nframes
;
337 aversig
= sqrt(aver2
-sqr(aver
));
338 printf("Found points in the range from %d to %d (max %d)\n",
339 first
,last
,maxangstat
);
340 printf(" < angle > = %g\n",aver
);
341 printf("< angle^2 > = %g\n",aver2
);
342 printf("Std. Dev. = %g\n",aversig
);
345 sprintf(title
,"Angle Distribution: %s",grpname
);
347 sprintf(title
,"Dihedral Distribution: %s",grpname
);
349 calc_distribution_props(maxangstat
,angstat
,-180.0,0,NULL
,&S2
);
350 fprintf(stderr
,"Order parameter S^2 = %g\n",S2
);
353 bPeriodic
=(mult
==4) && (first
==0) && (last
==maxangstat
-1);
355 out
=xvgropen(opt2fn("-od",NFILE
,fnm
),title
,"Degrees","",oenv
);
356 if (output_env_get_print_xvgr_codes(oenv
))
357 fprintf(out
,"@ subtitle \"average angle: %g\\So\\N\"\n",aver
);
358 norm_fac
=1.0/(nangles
*nframes
*binwidth
);
361 for(i
=first
; (i
<=last
); i
++)
362 maxstat
=max(maxstat
,angstat
[i
]*norm_fac
);
363 fprintf(out
,"@with g0\n");
364 fprintf(out
,"@ world xmin -180\n");
365 fprintf(out
,"@ world xmax 180\n");
366 fprintf(out
,"@ world ymin 0\n");
367 fprintf(out
,"@ world ymax %g\n",maxstat
*1.05);
368 fprintf(out
,"@ xaxis tick major 60\n");
369 fprintf(out
,"@ xaxis tick minor 30\n");
370 fprintf(out
,"@ yaxis tick major 0.005\n");
371 fprintf(out
,"@ yaxis tick minor 0.0025\n");
373 for(i
=first
; (i
<=last
); i
++)
374 fprintf(out
,"%10g %10f\n",i
*binwidth
+180.0-maxang
,angstat
[i
]*norm_fac
);
376 /* print first bin again as last one */
377 fprintf(out
,"%10g %10f\n",180.0,angstat
[0]*norm_fac
);
381 do_view(oenv
,opt2fn("-od",NFILE
,fnm
),"-nxy");
383 do_view(oenv
,opt2fn("-ov",NFILE
,fnm
),"-nxy");