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
56 static void dump_dih(int nframes
,char *title
,real time
[],real dih
[])
62 sprintf(fname
,"dih.%s",title
);
63 printf("A dihedral transition occurred in %s\n",fname
);
64 printf("Do you want to plot it to %s ? (y/n) ",fname
);
66 out
=ffopen(fname
,"w");
67 for(i
=0; (i
<nframes
); i
++)
68 fprintf(out
,"%10.3f %12.5e\n",time
[i
],dih
[i
]);
72 static void ana_dih(FILE *out
,char *index
,int nframes
,real dih
[],t_dih
*dd
)
75 real mind
,maxd
,sum
,av
,var
,prev
,width
;
78 mind
=5400,maxd
=-5400,sum
=0,av
=0,var
=0;
81 for(i
=0; (i
<nframes
); i
++) {
82 if ((dih
[i
]-prev
) > 180) {
86 else if ((dih
[i
]-prev
) < -180)
91 mind
=min(mind
,dih
[i
]);
92 maxd
=max(maxd
,dih
[i
]);
95 for(i
=0; (i
<nframes
); i
++)
98 width
=(360.0/dd
->mult
);
99 bTrans
=((maxd
- mind
) > width
);
101 fprintf(out
,"%-10s %10.3f %10.3f %10.3f %10.3f %10.3f %-10s%3.0f\n",
102 index
,mind
,av
,maxd
,var
,sqrt(var
),
103 bTrans
? "Yep" : "",width
);
106 static int find_min(real phi
,int ntab
,real phitab
[])
112 /* Set closest minimum to the first one */
114 mind
=fabs(phi
-phitab
[0]);
116 for(i
=1; (i
<ntab
); i
++) {
117 mm
=fabs(phi
-phitab
[i
]);
123 if (mind
< width
*0.5 )
129 static int vphi(t_dih
*dih
,real phi
,int mult
)
131 static real m2
[] = { 90, 270 };
132 static real m3
[] = { 60, 180, 300 };
133 static real m4
[] = { 45, 135, 225, 315 };
134 static real m6
[] = { 30, 90, 150, 210, 270, 330 };
139 phiref
=RAD2DEG
*(phi
-dih
->phi0
);
147 vpp
=find_min(phiref
,2,m2
);
150 vpp
=find_min(phiref
,3,m3
);
153 vpp
=find_min(phiref
,4,m4
);
156 vpp
=find_min(phiref
,6,m6
);
159 gmx_fatal(FARGS
,"No such multiplicity %d",dih
->mult
);
168 typedef struct t_cluster
{
172 struct t_cluster
*next
;
175 static t_cluster
*search_cluster(t_cluster
*cl
,char *minimum
)
179 while (ccl
!= NULL
) {
180 if (strcmp(minimum
,ccl
->minimum
)==0)
187 static void add_cluster(t_cluster
**cl
,int ndih
,char *minimum
)
195 ccl
->minimum
=strdup(minimum
);
202 while (loper
->next
!= NULL
)
208 static void p_cluster(FILE *out
,t_cluster
*cl
)
212 fprintf(out
,"* * * C L U S T E R A N A L Y S I S * * *\n\n");
213 fprintf(out
," Frequency Dihedral minima\n");
215 while (loper
!= NULL
) {
216 fprintf(out
,"%10d %s\n",loper
->freq
,loper
->minimum
);
221 static void ana_cluster(FILE *out
, t_xrama
*xr
,real
**dih
,real time
[],
222 t_topology
*top
,int nframes
,int mult
)
224 t_cluster
*cl
=NULL
,*scl
;
228 /* Number of dihedrals + terminating NULL
229 * this allows for using string routines
231 snew(minimum
,xr
->ndih
+1);
233 for(i
=0; (i
<nframes
); i
++) {
235 for(j
=0; (j
<xr
->ndih
); j
++) {
236 minimum
[j
] = vphi(&xr
->dih
[j
],dih
[j
][i
],
237 mult
== -1 ? xr
->dih
[j
].mult
: mult
);
238 if (minimum
[j
] == NOMIN
)
242 if ((scl
=search_cluster(cl
,minimum
)) == NULL
)
243 add_cluster(&cl
,xr
->ndih
,minimum
);
253 static void ana_trans(FILE *out
, t_xrama
*xr
,real
**dih
,real time
[],
254 t_topology
*top
,int nframes
, const output_env_t oenv
)
257 real prev_phi
,prev_psi
;
261 fprintf(out
,"\n\t* * * D I H E D R A L S T A T I S T I C S * * *\n\n");
262 fprintf(out
,"%-10s %10s %10s %10s %10s %10s %10s\n",
263 "index","minimum","average","maximum","variance","std.dev",
265 for(i
=0; (i
>xr
->ndih
); i
++) {
266 sprintf(buf
,"dih-%d",i
);
267 ana_dih(out
,buf
,nframes
,dih
[i
],&(xr
->dih
[i
]));
269 for(i
=0; (i
<xr
->npp
); i
++) {
270 sprintf(buf
,"%s",xr
->pp
[i
].label
);
271 outd
=xvgropen(buf
,"Dihedral Angles","Time (ps)","Degrees",oenv
);
275 prev_phi
=dih
[phi
][0];
276 prev_psi
=dih
[psi
][0];
277 for(j
=0; (j
<nframes
); j
++) {
279 if ((dih
[phi
][j
]-prev_phi
) > 180)
281 else if ((dih
[phi
][j
]-prev_phi
) < -180)
283 prev_phi
=dih
[phi
][j
];
284 if ((dih
[psi
][j
]-prev_psi
) > 180)
286 else if ((dih
[psi
][j
]-prev_psi
) < -180)
288 prev_psi
=dih
[psi
][j
];
289 fprintf(outd
,"%10g %10g %10g\n",time
[j
],prev_phi
,prev_psi
);
295 int gmx_dih(int argc
,char *argv
[])
297 const char *desc
[] = {
298 "g_dih can do two things. The default is to analyze dihedral transitions",
299 "by merely computing all the dihedral angles defined in your topology",
300 "for the whole trajectory. When a dihedral flips over to another minimum",
301 "an angle/time plot is made.[PAR]",
302 "The opther option is to discretize the dihedral space into a number of",
303 "bins, and group each conformation in dihedral space in the",
304 "appropriate bin. The output is then given as a number of dihedral",
305 "conformations sorted according to occupancy."
307 static int mult
= -1;
308 static bool bSA
= FALSE
;
310 { "-sa", FALSE
, etBOOL
, {&bSA
},
311 "Perform cluster analysis in dihedral space instead of analysing dihedral transitions." },
312 { "-mult", FALSE
, etINT
, {&mult
},
313 "mulitiplicity for dihedral angles (by default read from topology)" }
320 int i
,nframes
,maxframes
=1000;
323 { efTRX
, "-f", NULL
, ffREAD
},
324 { efTPX
, NULL
, NULL
, ffREAD
},
325 { efOUT
, NULL
, NULL
, ffWRITE
}
327 #define NFILE asize(fnm)
329 CopyRight(stderr
,argv
[0]);
330 parse_common_args(&argc
,argv
,PCA_CAN_VIEW
| PCA_CAN_TIME
| PCA_BE_NICE
,
331 NFILE
,fnm
,asize(pa
),pa
,asize(desc
),desc
,0,NULL
,&oenv
);
334 fprintf(stderr
,"Using %d for dihedral multiplicity rather than topology values\n",mult
);
337 init_rama(oenv
,ftp2fn(efTRX
,NFILE
,fnm
),
338 ftp2fn(efTPX
,NFILE
,fnm
),xr
,3);
339 top
=read_top(ftp2fn(efTPX
,NFILE
,fnm
),NULL
);
341 /* Brute force malloc, may be too big... */
343 for(i
=0; (i
<xr
->ndih
); i
++)
344 snew(dih
[i
],maxframes
);
345 snew(time
,maxframes
);
347 fprintf(stderr
,"\n");
349 while (new_data(xr
)) {
350 for(i
=0; (i
<xr
->ndih
); i
++) {
351 dd
=xr
->dih
[i
].ang
*RAD2DEG
;
360 if (nframes
> maxframes
) {
362 for(i
=0; (i
<xr
->ndih
); i
++)
363 srenew(dih
[i
],maxframes
);
364 srenew(time
,maxframes
);
368 fprintf(stderr
,"\nCalculated all dihedrals, now analysing...\n");
370 out
=ftp2FILE(efOUT
,NFILE
,fnm
,"w");
373 /* Cluster and structure analysis */
374 ana_cluster(out
,xr
,dih
,time
,top
,nframes
,mult
);
377 /* Analyse transitions... */
378 ana_trans(out
,xr
,dih
,time
,top
,nframes
,oenv
);