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 * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
35 /* This file is completely threadsafe - keep it that way! */
51 static int in_strings(char *key
,int nstr
,const char **str
)
55 for(j
=0; (j
<nstr
); j
++)
56 if (strcmp(str
[j
],key
) == 0)
62 static bool hbond(rvec x
[],int i
,int j
,real distance
)
64 real tol
= distance
*distance
;
67 rvec_sub(x
[i
],x
[j
],tmp
);
69 return (iprod(tmp
,tmp
) < tol
);
72 static void chk_allhb(t_atoms
*pdba
,rvec x
[],t_blocka
*hb
,
73 bool donor
[],bool accept
[],real dist
)
78 snew(hb
->index
,natom
+1);
85 for(i
=0; (i
<natom
); i
++) {
87 for(j
=i
+1; (j
<natom
); j
++)
88 if ((accept
[j
]) && (hbond(x
,i
,j
,dist
)))
92 for(j
=i
+1; (j
<natom
); j
++)
93 if ((donor
[j
]) && (hbond(x
,i
,j
,dist
)))
101 static void pr_hbonds(FILE *fp
,t_blocka
*hb
,t_atoms
*pdba
)
105 fprintf(fp
,"Dumping all hydrogen bonds!\n");
106 for(i
=0; (i
<hb
->nr
); i
++) {
109 for(j
=j0
; (j
<j1
); j
++) {
111 fprintf(fp
,"%5s%4d%5s - %5s%4d%5s\n",
112 *pdba
->resinfo
[pdba
->atom
[i
].resind
].name
,
113 pdba
->resinfo
[pdba
->atom
[i
].resind
].nr
,*pdba
->atomname
[i
],
114 *pdba
->resinfo
[pdba
->atom
[k
].resind
].name
,
115 pdba
->resinfo
[pdba
->atom
[k
].resind
].nr
,*pdba
->atomname
[k
]);
120 static bool chk_hbonds(int i
,t_atoms
*pdba
, rvec x
[],
121 bool ad
[],bool hbond
[],rvec xh
,
122 real angle
,real dist
)
131 ri
= pdba
->atom
[i
].resind
;
133 for(j
=0; (j
<natom
); j
++) {
134 /* Check whether the other atom is a donor/acceptor and not i */
135 if ((ad
[j
]) && (j
!= i
)) {
136 /* Check whether the other atom is on the same ring as well */
137 if ((pdba
->atom
[j
].resind
!= ri
) ||
138 ((strcmp(*pdba
->atomname
[j
],"ND1") != 0) &&
139 (strcmp(*pdba
->atomname
[j
],"NE2") != 0))) {
141 d2
= distance2(x
[i
],x
[j
]);
142 rvec_sub(x
[i
],xh
,nh
);
143 rvec_sub(x
[aj
],xh
,oh
);
144 a
= RAD2DEG
* acos(cos_angle(nh
,oh
));
145 if ((d2
< dist2
) && (a
> angle
)) {
148 "HBOND between %s%d-%s and %s%d-%s is %g nm, %g deg\n",
149 *pdba
->resinfo
[pdba
->atom
[i
].resind
].name
,
150 pdba
->resinfo
[pdba
->atom
[i
].resind
].nr
,*pdba
->atomname
[i
],
151 *pdba
->resinfo
[pdba
->atom
[aj
].resind
].name
,
152 pdba
->resinfo
[pdba
->atom
[aj
].resind
].nr
,*pdba
->atomname
[aj
],
163 static void calc_ringh(rvec xattach
,rvec xb
,rvec xc
,rvec xh
)
168 /* Add a proton on a ring to atom attach at distance 0.1 nm */
169 rvec_sub(xattach
,xb
,tab
);
170 rvec_sub(xattach
,xc
,tac
);
171 rvec_add(tab
,tac
,xh
);
174 rvec_inc(xh
,xattach
);
177 void set_histp(t_atoms
*pdba
,rvec
*x
,real angle
,real dist
){
178 static const char *prot_acc
[] = {
179 "O", "OD1", "OD2", "OE1", "OE2", "OG", "OG1", "OH", "OW"
181 #define NPA asize(prot_acc)
182 static const char *prot_don
[] = {
183 "N", "NH1", "NH2", "NE", "ND1", "ND2", "NE2", "NZ", "OG", "OG1", "OH", "NE1", "OW"
185 #define NPD asize(prot_don)
187 bool *donor
,*acceptor
;
188 bool *hbond
,bHaveH
=FALSE
;
192 int i
,j
,nd
,na
,aj
,hisind
,his0
,type
=-1;
193 int nd1
,ne2
,cg
,cd2
,ce1
;
200 snew(acceptor
,natom
);
205 for(i
=0; (i
<natom
); i
++) {
206 if (in_strings(*pdba
->atomname
[i
],NPA
,prot_acc
) != -1) {
210 if (in_strings(*pdba
->atomname
[i
],NPD
,prot_don
) != -1) {
215 fprintf(stderr
,"There are %d donors and %d acceptors\n",nd
,na
);
216 chk_allhb(pdba
,x
,hb
,donor
,acceptor
,dist
);
218 pr_hbonds(debug
,hb
,pdba
);
219 fprintf(stderr
,"There are %d hydrogen bonds\n",hb
->nra
);
221 /* Now do the HIS stuff */
223 for(i
=0; (i
<natom
); ) {
224 if (strcasecmp(*pdba
->resinfo
[pdba
->atom
[i
].resind
].name
,"HIS") != 0)
227 if (pdba
->atom
[i
].resind
!= hisind
) {
228 hisind
=pdba
->atom
[i
].resind
;
230 /* Find the atoms in the ring */
231 nd1
=ne2
=cg
=cd2
=ce1
=-1;
232 for(j
=i
; (pdba
->atom
[j
].resind
==hisind
) && (j
<natom
); j
++) {
233 atomnm
=*pdba
->atomname
[j
];
234 if (strcmp(atomnm
,"CD2") == 0)
236 else if (strcmp(atomnm
,"CG") == 0)
238 else if (strcmp(atomnm
,"CE1") == 0)
240 else if (strcmp(atomnm
,"ND1") == 0)
242 else if (strcmp(atomnm
,"NE2") == 0)
246 if (!((cg
== -1 ) || (cd2
== -1) || (ce1
== -1) ||
247 (nd1
== -1) || (ne2
== -1))) {
248 calc_ringh(x
[nd1
],x
[cg
],x
[ce1
],xh1
);
249 calc_ringh(x
[ne2
],x
[ce1
],x
[cd2
],xh2
);
251 bHDd
= chk_hbonds(nd1
,pdba
,x
,acceptor
,hbond
,xh1
,angle
,dist
);
252 chk_hbonds(nd1
,pdba
,x
,donor
,hbond
,xh1
,angle
,dist
);
253 bHEd
= chk_hbonds(ne2
,pdba
,x
,acceptor
,hbond
,xh2
,angle
,dist
);
254 chk_hbonds(ne2
,pdba
,x
,donor
,hbond
,xh2
,angle
,dist
);
264 fprintf(stderr
,"Will use %s for residue %d\n",
265 hh
[type
],pdba
->resinfo
[hisind
].nr
);
268 gmx_fatal(FARGS
,"Incomplete ring in HIS%d",
269 pdba
->resinfo
[hisind
].nr
);
271 sfree(*pdba
->resinfo
[hisind
].name
);
272 *pdba
->resinfo
[hisind
].name
= strdup(hh
[type
]);