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, 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.
54 #include "gmx_fatal.h"
61 static void dump_dih_trn(int nframes,int nangles,real **dih,const char *fn,
67 matrix box = {{2,0,0},{0,2,0},{0,0,2}};
74 printf("There are %d dihedrals. Will fill %d atom positions with cos/sin\n",
77 trn = open_trn(fn,"w");
78 for(i=0; (i<nframes); i++) {
80 for(j=0; (j<nangles); j++) {
81 for(m=0; (m<2); m++) {
82 x[k][l] = (m == 0) ? cos(dih[j][i]) : sin(dih[j][i]);
90 fwrite_trn(trn,i,time[i],0,box,na,x,NULL,NULL);
96 int gmx_g_angle(int argc,char *argv[])
98 static const char *desc[] = {
99 "[TT]g_angle[tt] computes the angle distribution for a number of angles",
100 "or dihedrals. This way you can check whether your simulation",
101 "is correct. With option [TT]-ov[tt] you can plot the average angle of",
102 "a group of angles as a function of time. With the [TT]-all[tt] option",
103 "the first graph is the average, the rest are the individual angles.[PAR]",
104 "With the [TT]-of[tt] option, [TT]g_angle[tt] also calculates the fraction of trans",
105 "dihedrals (only for dihedrals) as function of time, but this is",
106 "probably only fun for a selected few.[PAR]",
107 "With option [TT]-oc[tt] a dihedral correlation function is calculated.[PAR]",
108 "It should be noted that the index file should contain",
109 "atom-triples for angles or atom-quadruplets for dihedrals.",
110 "If this is not the case, the program will crash.[PAR]",
111 "With option [TT]-or[tt] a trajectory file is dumped containing cos and",
112 "sin of selected dihedral angles which subsequently can be used as",
113 "input for a PCA analysis using [TT]g_covar[tt].[PAR]",
114 "Option [TT]-ot[tt] plots when transitions occur between",
115 "dihedral rotamers of multiplicity 3 and [TT]-oh[tt]",
116 "records a histogram of the times between such transitions,",
117 "assuming the input trajectory frames are equally spaced in time."
119 static const char *opt[] = { NULL, "angle", "dihedral", "improper", "ryckaert-bellemans", NULL };
120 static gmx_bool bALL=FALSE,bChandler=FALSE,bAverCorr=FALSE,bPBC=TRUE;
121 static real binwidth=1;
123 { "-type", FALSE, etENUM, {opt},
124 "Type of angle to analyse" },
125 { "-all", FALSE, etBOOL, {&bALL},
126 "Plot all angles separately in the averages file, in the order of appearance in the index file." },
127 { "-binwidth", FALSE, etREAL, {&binwidth},
128 "binwidth (degrees) for calculating the distribution" },
129 { "-periodic", FALSE, etBOOL, {&bPBC},
130 "Print dihedral angles modulo 360 degrees" },
131 { "-chandler", FALSE, etBOOL, {&bChandler},
132 "Use Chandler correlation function (N[trans] = 1, N[gauche] = 0) rather than cosine correlation function. Trans is defined as phi < -60 or phi > 60." },
133 { "-avercorr", FALSE, etBOOL, {&bAverCorr},
134 "Average the correlation functions for the individual angles/dihedrals" }
136 static const char *bugs[] = {
137 "Counting transitions only works for dihedrals with multiplicity 3"
145 real maxang,Jc,S2,norm_fac,maxstat;
147 int nframes,maxangstat,mult,*angstat;
148 int i,j,total,nangles,natoms,nat2,first,last,angind;
149 gmx_bool bAver,bRb,bPeriodic,
150 bFrac, /* calculate fraction too? */
151 bTrans, /* worry about transtions too? */
152 bCorr; /* correlation function ? */
153 real t,aa,aver,aver2,aversig,fraction; /* fraction trans dihedrals */
156 real **dih=NULL; /* mega array with all dih. angles at all times*/
158 real *time,*trans_frac,*aver_angle;
160 { efTRX, "-f", NULL, ffREAD },
161 { efNDX, NULL, "angle", ffREAD },
162 { efXVG, "-od", "angdist", ffWRITE },
163 { efXVG, "-ov", "angaver", ffOPTWR },
164 { efXVG, "-of", "dihfrac", ffOPTWR },
165 { efXVG, "-ot", "dihtrans", ffOPTWR },
166 { efXVG, "-oh", "trhisto", ffOPTWR },
167 { efXVG, "-oc", "dihcorr", ffOPTWR },
168 { efTRR, "-or", NULL, ffOPTWR }
170 #define NFILE asize(fnm)
175 CopyRight(stderr,argv[0]);
177 ppa = add_acf_pargs(&npargs,pa);
178 parse_common_args(&argc,argv,PCA_CAN_VIEW | PCA_CAN_TIME | PCA_BE_NICE,
179 NFILE,fnm,npargs,ppa,asize(desc),desc,asize(bugs),bugs,
199 if (opt2bSet("-or",NFILE,fnm)) {
201 gmx_fatal(FARGS,"Can not combine angles with trn dump");
203 please_cite(stdout,"Mu2005a");
206 /* Calculate bin size */
207 maxangstat=(int)(maxang/binwidth+0.5);
208 binwidth=maxang/maxangstat;
210 rd_index(ftp2fn(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
212 if ((isize % mult) != 0)
213 gmx_fatal(FARGS,"number of index elements not multiple of %d, "
214 "these can not be %s\n",
215 mult,(mult==3) ? "angle triplets" : "dihedral quadruplets");
218 /* Check whether specific analysis has to be performed */
219 bCorr=opt2bSet("-oc",NFILE,fnm);
220 bAver=opt2bSet("-ov",NFILE,fnm);
221 bTrans=opt2bSet("-ot",NFILE,fnm);
222 bFrac=opt2bSet("-of",NFILE,fnm);
223 if (bTrans && opt[0][0] != 'd') {
224 fprintf(stderr, "Option -ot should only accompany -type dihedral. Disabling -ot.\n");
228 if (bChandler && !bCorr)
232 fprintf(stderr,"Warning:"
233 " calculating fractions as defined in this program\n"
234 "makes sense for Ryckaert Bellemans dihs. only. Ignoring -of\n\n");
238 if ( (bTrans || bFrac || bCorr) && mult==3)
239 gmx_fatal(FARGS,"Can only do transition, fraction or correlation\n"
240 "on dihedrals. Select -d\n");
243 * We need to know the nr of frames so we can allocate memory for an array
244 * with all dihedral angles at all timesteps. Works for me.
246 if (bTrans || bCorr || bALL || opt2bSet("-or",NFILE,fnm))
249 snew(angstat,maxangstat);
251 read_ang_dih(ftp2fn(efTRX,NFILE,fnm),(mult == 3),
252 bALL || bCorr || bTrans || opt2bSet("-or",NFILE,fnm),
253 bRb,bPBC,maxangstat,angstat,
254 &nframes,&time,isize,index,&trans_frac,&aver_angle,dih,
257 dt=(time[nframes-1]-time[0])/(nframes-1);
260 sprintf(title,"Average Angle: %s",grpname);
261 out=xvgropen(opt2fn("-ov",NFILE,fnm),
262 title,"Time (ps)","Angle (degrees)",oenv);
263 for(i=0; (i<nframes); i++) {
264 fprintf(out,"%10.5f %8.3f",time[i],aver_angle[i]*RAD2DEG);
266 for(j=0; (j<nangles); j++)
269 fprintf(out," %8.3f",atan2(sin(dd),cos(dd))*RAD2DEG);
272 fprintf(out," %8.3f",dih[j][i]*RAD2DEG);
278 if (opt2bSet("-or",NFILE,fnm))
279 dump_dih_trn(nframes,nangles,dih,opt2fn("-or",NFILE,fnm),time);
282 sprintf(title,"Trans fraction: %s",grpname);
283 out=xvgropen(opt2fn("-of",NFILE,fnm),
284 title,"Time (ps)","Fraction",oenv);
286 for(i=0; (i<nframes); i++) {
287 fprintf(out,"%10.5f %10.3f\n",time[i],trans_frac[i]);
288 tfrac += trans_frac[i];
293 fprintf(stderr,"Average trans fraction: %g\n",tfrac);
298 ana_dih_trans(opt2fn("-ot",NFILE,fnm),opt2fn("-oh",NFILE,fnm),
299 dih,nframes,nangles,grpname,time,bRb,oenv);
302 /* Autocorrelation function */
304 fprintf(stderr,"Not enough frames for correlation function\n");
308 real dval,sixty=DEG2RAD*60;
311 for(i=0; (i<nangles); i++)
312 for(j=0; (j<nframes); j++) {
315 bTest=(dval > -sixty) && (dval < sixty);
317 bTest=(dval < -sixty) || (dval > sixty);
319 dih[i][j] = dval-tfrac;
328 do_autocorr(opt2fn("-oc",NFILE,fnm), oenv,
329 "Dihedral Autocorrelation Function",
330 nframes,nangles,dih,dt,mode,bAverCorr);
335 /* Determine the non-zero part of the distribution */
336 for(first=0; (first < maxangstat-1) && (angstat[first+1] == 0); first++)
338 for(last=maxangstat-1; (last > 0) && (angstat[last-1] == 0) ; last--)
342 for(i=0; (i<nframes); i++) {
343 aver += RAD2DEG*aver_angle[i];
344 aver2 += sqr(RAD2DEG*aver_angle[i]);
346 aver /= (real) nframes;
347 aver2 /= (real) nframes;
348 aversig = sqrt(aver2-sqr(aver));
349 printf("Found points in the range from %d to %d (max %d)\n",
350 first,last,maxangstat);
351 printf(" < angle > = %g\n",aver);
352 printf("< angle^2 > = %g\n",aver2);
353 printf("Std. Dev. = %g\n",aversig);
356 sprintf(title,"Angle Distribution: %s",grpname);
358 sprintf(title,"Dihedral Distribution: %s",grpname);
360 calc_distribution_props(maxangstat,angstat,-180.0,0,NULL,&S2);
361 fprintf(stderr,"Order parameter S^2 = %g\n",S2);
364 bPeriodic=(mult==4) && (first==0) && (last==maxangstat-1);
366 out=xvgropen(opt2fn("-od",NFILE,fnm),title,"Degrees","",oenv);
367 if (output_env_get_print_xvgr_codes(oenv))
368 fprintf(out,"@ subtitle \"average angle: %g\\So\\N\"\n",aver);
369 norm_fac=1.0/(nangles*nframes*binwidth);
372 for(i=first; (i<=last); i++)
373 maxstat=max(maxstat,angstat[i]*norm_fac);
374 fprintf(out,"@with g0\n");
375 fprintf(out,"@ world xmin -180\n");
376 fprintf(out,"@ world xmax 180\n");
377 fprintf(out,"@ world ymin 0\n");
378 fprintf(out,"@ world ymax %g\n",maxstat*1.05);
379 fprintf(out,"@ xaxis tick major 60\n");
380 fprintf(out,"@ xaxis tick minor 30\n");
381 fprintf(out,"@ yaxis tick major 0.005\n");
382 fprintf(out,"@ yaxis tick minor 0.0025\n");
384 for(i=first; (i<=last); i++)
385 fprintf(out,"%10g %10f\n",i*binwidth+180.0-maxang,angstat[i]*norm_fac);
387 /* print first bin again as last one */
388 fprintf(out,"%10g %10f\n",180.0,angstat[0]*norm_fac);
392 do_view(oenv,opt2fn("-od",NFILE,fnm),"-nxy");
394 do_view(oenv,opt2fn("-ov",NFILE,fnm),"-nxy");