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
42 #include "gmx_fatal.h"
46 #include "gmx_statistics.h"
51 static const char *etitles
[] = { "E-docked", "Free Energy" };
62 static t_pdbfile
*read_pdbf(const char *fn
)
71 get_stx_coordnum (fn
,&natoms
);
72 init_t_atoms(&(pdbf
->atoms
),natoms
,FALSE
);
74 read_stx_conf(fn
,buf
,&pdbf
->atoms
,pdbf
->x
,NULL
,&pdbf
->ePBC
,pdbf
->box
);
77 ptr
= fgets2(buf
,255,fp
);
79 if (strstr(buf
,"Intermolecular") != NULL
) {
80 ptr
= strchr(buf
,'=');
81 sscanf(ptr
+1,"%lf",&e
);
84 else if (strstr(buf
,"Estimated Free") != NULL
) {
85 ptr
= strchr(buf
,'=');
86 sscanf(ptr
+1,"%lf",&e
);
90 } while (ptr
!= NULL
);
96 static t_pdbfile
**read_em_all(const char *fn
,int *npdbf
)
100 char buf
[256],name
[256];
104 buf
[strlen(buf
)-4] = '\0';
109 sprintf(name
,"%s_%d.pdb",buf
,i
+1);
110 if ((bExist
= gmx_fexist(name
)) == TRUE
) {
111 pdbf
[i
] = read_pdbf(name
);
112 pdbf
[i
]->index
= i
+1;
116 srenew(pdbf
,maxpdbf
);
123 printf("Found %d pdb files\n",i
);
128 static bool bFreeSort
=FALSE
;
130 static int pdbf_comp(const void *a
,const void *b
)
136 pa
= *(t_pdbfile
**)a
;
137 pb
= *(t_pdbfile
**)b
;
139 dc
= pa
->cluster_id
- pb
->cluster_id
;
143 x
= pa
->efree
- pb
->efree
;
145 x
= pa
->edocked
- pb
->edocked
;
158 static void analyse_em_all(int npdb
,t_pdbfile
*pdbf
[], const char *edocked
,
159 const char *efree
, const output_env_t oenv
)
164 for(bFreeSort
= FALSE
; (bFreeSort
<= TRUE
); bFreeSort
++) {
165 qsort(pdbf
,npdb
,sizeof(pdbf
[0]),pdbf_comp
);
166 fp
= xvgropen(bFreeSort
? efree
: edocked
,
167 etitles
[bFreeSort
],"()","E (kJ/mol)",oenv
);
168 for(i
=0; (i
<npdb
); i
++)
169 fprintf(fp
,"%12lf\n",bFreeSort
? pdbf
[i
]->efree
: pdbf
[i
]->edocked
);
174 static void clust_stat(FILE *fp
,int start
,int end
,t_pdbfile
*pdbf
[])
180 ed
= gmx_stats_init();
181 ef
= gmx_stats_init();
182 for(i
=start
; (i
<end
); i
++) {
183 gmx_stats_add_point(ed
,i
-start
,pdbf
[i
]->edocked
,0,0);
184 gmx_stats_add_point(ef
,i
-start
,pdbf
[i
]->efree
,0,0);
186 gmx_stats_get_ase(ed
,&aver
,&sigma
,NULL
);
187 fprintf(fp
," <%12s> = %8.3f (+/- %6.3f)\n",etitles
[FALSE
],aver
,sigma
);
188 gmx_stats_get_ase(ef
,&aver
,&sigma
,NULL
);
189 fprintf(fp
," <%12s> = %8.3f (+/- %6.3f)\n",etitles
[TRUE
],aver
,sigma
);
196 static real
rmsd_dist(t_pdbfile
*pa
,t_pdbfile
*pb
,bool bRMSD
)
204 for(i
=0; (i
<pa
->atoms
.nr
); i
++) {
205 rvec_sub(pa
->x
[i
],pb
->x
[i
],dx
);
206 rmsd
+= iprod(dx
,dx
);
208 rmsd
= sqrt(rmsd
/pa
->atoms
.nr
);
214 for(i
=0; (i
<pa
->atoms
.nr
); i
++) {
215 rvec_inc(acm
,pa
->x
[i
]);
216 rvec_inc(bcm
,pb
->x
[i
]);
218 rvec_sub(acm
,bcm
,dx
);
219 for(i
=0; (i
<DIM
); i
++)
220 dx
[i
] /= pa
->atoms
.nr
;
226 static void line(FILE *fp
)
228 fprintf(fp
," - - - - - - - - - -\n");
231 static void cluster_em_all(FILE *fp
,int npdb
,t_pdbfile
*pdbf
[],
232 const char *pdbout
,bool bFree
,bool bRMSD
,real cutoff
)
239 qsort(pdbf
,npdb
,sizeof(pdbf
[0]),pdbf_comp
);
241 fprintf(fp
,"Statistics over all structures:\n");
242 clust_stat(fp
,0,npdb
,pdbf
);
245 /* Index to first structure in a cluster */
249 for(i
=1; (i
<npdb
); i
++) {
250 for(j
=0; (j
<ncluster
); j
++) {
251 rmsd
= rmsd_dist(pdbf
[cndx
[j
]],pdbf
[i
],bRMSD
);
252 if (rmsd
<= cutoff
) {
253 /* Structure i is in cluster j */
254 pdbf
[i
]->cluster_id
= pdbf
[cndx
[j
]]->cluster_id
;
259 /* New cluster! Cool! */
261 pdbf
[i
]->cluster_id
= ncluster
;
265 cndx
[ncluster
] = npdb
;
266 qsort(pdbf
,npdb
,sizeof(pdbf
[0]),pdbf_comp
);
270 for(i
=1; (i
<npdb
); i
++) {
271 if (pdbf
[i
]->cluster_id
!= pdbf
[i
-1]->cluster_id
) {
277 gmx_fatal(FARGS
,"Consistency error: j = %d, ncluster = %d",j
,ncluster
);
279 fprintf(fp
,"I found %d clusters based on %s and %s with a %.3f nm cut-off\n",
280 ncluster
,etitles
[bFree
],bRMSD
? "RMSD" : "distance",cutoff
);
282 for(j
=0; (j
<ncluster
); j
++) {
283 fprintf(fp
,"Cluster: %3d %s: %10.5f kJ/mol %3d elements\n",
285 bFree
? pdbf
[cndx
[j
]]->efree
: pdbf
[cndx
[j
]]->edocked
,
287 clust_stat(fp
,cndx
[j
],cndx
[j
+1],pdbf
);
288 for(k
=cndx
[j
]; (k
<cndx
[j
+1]); k
++)
289 fprintf(fp
," %3d",pdbf
[k
]->index
);
296 int main(int argc
,char *argv
[])
298 const char *desc
[] = {
299 "anadock analyses the results of an Autodock run and clusters the",
300 "structures together, based on distance or RMSD. The docked energy",
301 "and free energy estimates are analysed, and for each cluster the",
302 "energy statistics are printed.[PAR]",
303 "An alternative approach to this is to cluster the structures first",
304 "(using [TT]g_cluster[tt] and then sort the clusters on either lowest",
305 "energy or average energy."
308 { efPDB
, "-f", NULL
, ffREAD
},
309 { efPDB
, "-ox", "cluster", ffWRITE
},
310 { efXVG
, "-od", "edocked", ffWRITE
},
311 { efXVG
, "-of", "efree", ffWRITE
},
312 { efLOG
, "-g", "anadock", ffWRITE
}
315 #define NFILE asize(fnm)
316 static bool bFree
=FALSE
,bRMS
=TRUE
;
317 static real cutoff
= 0.2;
319 { "-free", FALSE
, etBOOL
, {&bFree
},
320 "Use Free energy estimate from autodock for sorting the classes" },
321 { "-rms", FALSE
, etBOOL
, {&bRMS
},
322 "Cluster on RMS or distance" },
323 { "-cutoff", FALSE
, etREAL
, {&cutoff
},
324 "Maximum RMSD/distance for belonging to the same cluster" }
326 #define NPA asize(pa)
329 t_pdbfile
**pdbf
=NULL
;
332 CopyRight(stderr
,argv
[0]);
333 parse_common_args(&argc
,argv
,0,NFILE
,fnm
,NPA
,pa
, asize(desc
),desc
,0,
336 fp
= ffopen(opt2fn("-g",NFILE
,fnm
),"w");
337 please_cite(stdout
,"Hetenyi2002b");
338 please_cite(fp
,"Hetenyi2002b");
340 pdbf
= read_em_all(opt2fn("-f",NFILE
,fnm
),&npdbf
);
342 analyse_em_all(npdbf
,pdbf
,opt2fn("-od",NFILE
,fnm
),opt2fn("-of",NFILE
,fnm
),
345 cluster_em_all(fp
,npdbf
,pdbf
,opt2fn("-ox",NFILE
,fnm
),