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.[PAR]",
101 "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 and 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 select few.[PAR]",
107 "With option [TT]-oc[tt], a dihedral correlation function is calculated.[PAR]",
108 "It should be noted that the index file must contain",
109 "atom triplets 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 principal components 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");