Bioplib
Protein Structure C Library
 All Data Structures Files Functions Variables Typedefs Macros Pages
hbond.c
Go to the documentation of this file.
1 /* #define ALLOW_AXN */
2 /************************************************************************/
3 /**
4 
5  \file hbond.c
6 
7  \version V1.8
8  \date 20.07.15
9  \brief Report whether two residues are H-bonded using
10  Baker & Hubbard criteria
11 
12  \copyright (c) UCL / Dr. Andrew C. R. Martin 1996-2015
13  \author Dr. Andrew C. R. Martin
14  \par
15  Institute of Structural & Molecular Biology,
16  University College London,
17  Gower Street,
18  London.
19  WC1E 6BT.
20  \par
21  andrew@bioinf.org.uk
22  andrew.martin@ucl.ac.uk
23 
24 **************************************************************************
25 
26  This code is NOT IN THE PUBLIC DOMAIN, but it may be copied
27  according to the conditions laid out in the accompanying file
28  COPYING.DOC.
29 
30  The code may be modified as required, but any modifications must be
31  documented so that the person responsible can be identified.
32 
33  The code may not be sold commercially or included as part of a
34  commercial product except as described in the file COPYING.DOC.
35 
36 **************************************************************************
37 
38  Description:
39  ============
40 
41 
42 **************************************************************************
43 
44  Usage:
45  ======
46  NOTE, explicit hydrogens must be added to the PDB linked list before
47  calling this routine.
48 
49  The only external entry points are blIsHBonded() and blValidHBond()
50 
51 **************************************************************************
52 
53  Revision History:
54  =================
55 - V1.0 26.01.96 Original By: ACRM
56 - V1.1 09.02.96 Added #ifdef'd code to allow AE1/AE2 AD1/AD2
57 - V1.2 19.12.02 Fixed bug in walking over multiple H atoms
58 - V1.3 18.08.05 Fixed bug relating to sidechains like GLN/ASN
59 - V1.4 03.01.06 Proline backbone nitrogen cannot act as donor!
60  Also incorporated fix in ValidHBond() from 02.06.99
61  Inpharmatica version to handle NULL antecedent atoms
62 - V1.5 17.01.06 Added IsMCDonorHBonded() and IsMCAcceptorHBonded()
63 - V1.6 20.03.14 Updated message in Demo code. By: CTP
64 - V1.7 07.07.14 Use bl prefix for functions By: CTP
65 - V1.8 20.08.14 Added blSetMaxProteinHBondDADistance()
66  Added blFindHBond()
67  By: ACRM
68 
69 
70 *************************************************************************/
71 /* Doxygen
72  -------
73  #GROUP Handling PDB Data
74  #SUBGROUP Analyzing structures
75  #FUNCTION blIsHBonded()
76  Determines whether 2 residues are H-bonded
77 
78  #FUNCTION blValidHBond()
79  Determines whether a set of atoms form a valid H-bond
80 
81  #FUNCTION blIsMCDonorHBonded()
82  Determines whether 2 residues are H-bonded with the first
83  residue being a mainchain donor
84 
85  #FUNCTION blIsMCAcceptorHBonded()
86  Determines whether 2 residues are H-bonded with the first
87  residue being a mainchain acceptor
88 
89  #FUNCTION blSetMaxProteinHBondDADistance()
90  Overrides the default maximum distance between donor and acceptor.
91  NOTE THIS IS NOT THREAD-SAFE
92 
93  #FUNCTION blListAllHBonds()
94  Finds all HBonds between two specified residues
95 
96 */
97 /************************************************************************/
98 /* Includes
99 */
100 #include <math.h>
101 #include "MathType.h"
102 #include "SysDefs.h"
103 #include "pdb.h"
104 #include "macros.h"
105 #include "general.h"
106 #include "angle.h"
107 #include "hbond.h"
108 
109 /************************************************************************/
110 /* Defines and macros
111 */
112 #define DADIST 3.5
113 #define DADISTSQ (DADIST*DADIST)
114 #define HADIST 2.5
115 #define HADISTSQ (HADIST*HADIST)
116 
117 
118 /************************************************************************/
119 /* Globals
120 */
121 static REAL sDADistSq = DADISTSQ;
122 
123 /************************************************************************/
124 /* Prototypes
125 */
126 static BOOL FindBackboneAcceptor(PDB *res, PDB **AtomA, PDB **AtomP);
127 static BOOL FindBackboneDonor(PDB *res, PDB **AtomH, PDB **AtomD);
128 static BOOL FindSidechainAcceptor(PDB *res, PDB **AtomA, PDB **AtomP);
129 static BOOL FindSidechainDonor(PDB *res, PDB **AtomH, PDB **AtomD);
130 
131 
132 /************************************************************************/
133 /*>int blIsHBonded(PDB *res1, PDB *res2, int type)
134  -----------------------------------------------
135 *//**
136 
137  \param[in] *res1 First residue
138  \param[in] *res2 Second residue
139  \param[in] type HBond type to search for
140  \return HBond type found or 0 if none
141 
142  Determines whether 2 residues are H-bonded using the crude criteria
143  of Baker & Hubbard, 1984 (Prog. Biophys. & Mol. Biol, 44, 97-179)
144 
145  N.B. Explicit hydrogens must be added to the PDB linked list before
146  calling this routine!
147 
148  Searches may be made for any H-bond, or just for those involving
149  backbone or sidechain. These requirements may be combined in any
150  way for the two residues by ORing the appropriate flags in the type
151  variable.
152 
153 
154  The flags are:
155  HBOND_BACK1 (res1 b/b)
156  HBOND_BACK2 (res2 b/b)
157  HBOND_SIDE1 (res1 s/c)
158  HBOND_SIDE2 (res2 s/c)
159 
160 
161  The most common flag combinations are already provided:
162  HBOND_BB (b/b -- b/b)
163  HBOND_BS (b/b -- s/c)
164  HBOND_SS (s/c -- s/c)
165  HBOND_SB (s/c -- b/b)
166  HBOND_SIDECHAIN (s/c -- any)
167  HBOND_BACKBONE (b/b -- any)
168  HBOND_ANY (any -- any)
169 
170 - 25.01.96 Original By: ACRM
171 - 07.07.14 Use bl prefix for functions By: CTP
172 */
173 int blIsHBonded(PDB *res1, PDB *res2, int type)
174 {
175  PDB *AtomH, /* The hydrogen */
176  *AtomD, /* The hydrogen donor */
177  *AtomA, /* The acceptor */
178  *AtomP; /* The acceptor's antecedent */
179 
180  /* Find H-bonds involving the backbone of res1 */
181  if(ISSET(type, HBOND_BACK1))
182  {
183  if(FindBackboneDonor(res1, &AtomH, &AtomD))
184  {
185  if(ISSET(type, HBOND_BACK2))
186  {
187  if(FindBackboneAcceptor(res2, &AtomA, &AtomP))
188  {
189  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
190  return(HBOND_BACK1|HBOND_BACK2);
191  }
192  }
193  if(ISSET(type, HBOND_SIDE2))
194  {
195  /* Clear internal flags */
196  FindSidechainAcceptor(NULL, NULL, NULL);
197  while(FindSidechainAcceptor(res2, &AtomA, &AtomP))
198  {
199  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
200  return(HBOND_BACK1|HBOND_SIDE2);
201  }
202  }
203  }
204  if(FindBackboneAcceptor(res1, &AtomA, &AtomP))
205  {
206  if(ISSET(type, HBOND_BACK2))
207  {
208  if(FindBackboneDonor(res2, &AtomH, &AtomD))
209  {
210  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
211  return(HBOND_BACK1|HBOND_BACK2);
212  }
213  }
214  if(ISSET(type, HBOND_SIDE2))
215  {
216  /* Clear internal flags */
217  FindSidechainDonor(NULL, NULL, NULL);
218  while(FindSidechainDonor(res2, &AtomH, &AtomD))
219  {
220  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
221  return(HBOND_BACK1|HBOND_SIDE2);
222  }
223  }
224  }
225  }
226 
227  /* Find H-bonds involving sidechain of res1 */
228  if(ISSET(type, HBOND_SIDE1))
229  {
230  /* Clear internal flags */
231  FindSidechainDonor(NULL, NULL, NULL);
232  while(FindSidechainDonor(res1, &AtomH, &AtomD))
233  {
234  if(ISSET(type, HBOND_BACK2))
235  {
236  if(FindBackboneAcceptor(res2, &AtomA, &AtomP))
237  {
238  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
239  return(HBOND_SIDE1|HBOND_BACK2);
240  }
241  }
242  if(ISSET(type, HBOND_SIDE2))
243  {
244  /* Clear internal flags */
245  FindSidechainAcceptor(NULL, NULL, NULL);
246  while(FindSidechainAcceptor(res2, &AtomA, &AtomP))
247  {
248  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
249  return(HBOND_SIDE1|HBOND_SIDE2);
250  }
251  }
252  }
253  /* Clear internal flags */
254  FindSidechainAcceptor(NULL, NULL, NULL);
255  while(FindSidechainAcceptor(res1, &AtomA, &AtomP))
256  {
257  if(ISSET(type, HBOND_BACK2))
258  {
259  if(FindBackboneDonor(res2, &AtomH, &AtomD))
260  {
261  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
262  return(HBOND_SIDE1|HBOND_BACK2);
263  }
264  }
265  if(ISSET(type, HBOND_SIDE2))
266  {
267  /* Clear internal flags */
268  FindSidechainDonor(NULL, NULL, NULL);
269  while(FindSidechainDonor(res2, &AtomH, &AtomD))
270  {
271  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
272  return(HBOND_SIDE1|HBOND_SIDE2);
273  }
274  }
275  }
276  }
277 
278  return(0);
279 }
280 
281 
282 /************************************************************************/
283 /*>BOOL blValidHBond(PDB *AtomH, PDB *AtomD, PDB *AtomA, PDB *AtomP)
284  -----------------------------------------------------------------
285 *//**
286 
287  \param[in] *AtomH The hydrogen
288  \param[in] *AtomD The donor (to which the H is attached)
289  \param[in] *AtomA The acceptor
290  \param[in] *AtomP The antecedent to the acceptor
291  \return Valid?
292 
293  Determines whether a set of atoms form a valid H-bond using the
294  Baker and Hubbard criteria
295 
296 - 25.01.96 Original By: ACRM
297 - 02.06.99 Added NULL antecedent handling to allow calculation of
298  HBonds with missing antecedents. Previously AtomP==NULL
299  was handled as an invalid HBond.
300 - 07.07.14 Use bl prefix for functions By: CTP
301 - 20.07.15 Changed DADISTSQ to sDADistSq By: ACRM
302 */
303 BOOL blValidHBond(PDB *AtomH, PDB *AtomD, PDB *AtomA, PDB *AtomP)
304 {
305  REAL ang1, ang2;
306 
307  if(AtomD==NULL || AtomA==NULL)
308  {
309  return(FALSE);
310  }
311 
312  if(AtomH==NULL)
313  {
314  /* If antecedent not defined then just check the distance */
315  if(AtomP==NULL)
316  {
317  if(DISTSQ(AtomD, AtomA) < sDADistSq)
318  return(TRUE);
319  else
320  return(FALSE);
321  }
322 
323  ang1 = blAngle(AtomP->x, AtomP->y, AtomP->z,
324  AtomA->x, AtomA->y, AtomA->z,
325  AtomD->x, AtomD->y, AtomD->z);
326 
327  if((DISTSQ(AtomD, AtomA) < sDADistSq) &&
328  ang1 >= PI/2.0 &&
329  ang1 <= PI)
330  return(TRUE);
331  }
332  else
333  {
334  ang2 = blAngle(AtomD->x, AtomD->y, AtomD->z,
335  AtomH->x, AtomH->y, AtomH->z,
336  AtomA->x, AtomA->y, AtomA->z);
337 
338  /* If the antecedent isn't defined then just set ang1 to within
339  the allowed range
340  */
341  if(AtomP==NULL)
342  {
343  ang1 = 3.0*PI/4.0;
344  }
345  else
346  {
347  ang1 = blAngle(AtomP->x, AtomP->y, AtomP->z,
348  AtomA->x, AtomA->y, AtomA->z,
349  AtomH->x, AtomH->y, AtomH->z);
350  }
351 
352  if((DISTSQ(AtomH, AtomA) < HADISTSQ) &&
353  ang1 >= PI/2.0 &&
354  ang1 <= PI &&
355  ang2 >= PI/2.0 &&
356  ang2 <= PI)
357  return(TRUE);
358  }
359 
360  return(FALSE);
361 }
362 
363 
364 /************************************************************************/
365 /*>static BOOL FindBackboneAcceptor(PDB *res, PDB **AtomA, PDB **AtomP)
366  --------------------------------------------------------------------
367 *//**
368 
369  \param[in] *res Pointer to residue of interest
370  \param[out] **AtomA The acceptor atom
371  \param[out] **AtomP The antecedent (previous) atom
372  \return Success?
373 
374  Finds pointers to backbone acceptor atoms
375 
376 - 25.01.96 Original By: ACRM
377 - 07.07.14 Use bl prefix for functions By: CTP
378 */
379 static BOOL FindBackboneAcceptor(PDB *res, PDB **AtomA, PDB **AtomP)
380 {
381  PDB *p,
382  *NextRes;
383 
384  if(res == NULL)
385  {
386  return(FALSE);
387  }
388 
389  *AtomA = NULL;
390  *AtomP = NULL;
391 
392  NextRes = blFindNextResidue(res);
393  for(p=res; p!=NextRes; NEXT(p))
394  {
395  if(!strncmp(p->atnam,"O ",4) ||
396  !strncmp(p->atnam,"OXT ",4) ||
397  !strncmp(p->atnam,"O1 ",4) ||
398  !strncmp(p->atnam,"O2 ",4))
399  *AtomA = p;
400  if(!strncmp(p->atnam,"C ",4))
401  *AtomP = p;
402  }
403 
404  if(*AtomA && *AtomP)
405  return(TRUE);
406 
407  return(FALSE);
408 }
409 
410 
411 /************************************************************************/
412 /*>static BOOL FindBackboneDonor(PDB *res, PDB **AtomH, PDB **AtomD)
413  -----------------------------------------------------------------
414 *//**
415 
416  \param[in] *res Pointer to residue of interest
417  \param[out] **AtomH The hydrogen
418  \param[out] **AtomD The 'donor' atom
419  \return Success?
420 
421  Finds pointers to backbone donor atoms
422 
423 - 25.01.96 Original By: ACRM
424 - 03.01.06 Returns FALSE if this is a proline
425 - 07.07.14 Use bl prefix for functions By: CTP
426 */
427 static BOOL FindBackboneDonor(PDB *res, PDB **AtomH, PDB **AtomD)
428 {
429  PDB *p,
430  *NextRes;
431 
432  if((res == NULL) || (!strncmp(res->resnam, "PRO", 3)))
433  {
434  return(FALSE);
435  }
436 
437  *AtomH = NULL;
438  *AtomD = NULL;
439 
440  NextRes = blFindNextResidue(res);
441  for(p=res; p!=NextRes; NEXT(p))
442  {
443  if(!strncmp(p->atnam,"H ",4))
444  *AtomH = p;
445  if(!strncmp(p->atnam,"N ",4))
446  *AtomD = p;
447  }
448 
449  if(*AtomD)
450  return(TRUE);
451 
452  return(FALSE);
453 }
454 
455 
456 /************************************************************************/
457 /*>static BOOL FindSidechainAcceptor(PDB *res, PDB **AtomA, PDB **AtomP)
458  ---------------------------------------------------------------------
459 *//**
460 
461  \param[in] *res Pointer to residue of interest
462  \param[out] **AtomA The acceptor atom
463  \param[out] **AtomP The antecedent (previous) atom
464  \return Success?
465 
466  Finds pointers to sidechain acceptor atoms. Each call will return
467  a new set of atoms till all are found.
468 
469  Call with all parameters set to NULL before each new residue
470 
471 - 25.01.96 Original By: ACRM
472 - 09.02.96 Added #ifdef'd code to allow AE1/AE2 AD1/AD2
473 - 18.08.05 Fixed bug relating to sidechains like GLN/ASN - when finding
474  the antecedent for the NE2 and ND2 atoms respectively, it
475  would find OE1/OD1 rather than CD/CG. (See pprev code)
476 - 07.07.14 Use bl prefix for functions By: CTP
477 */
478 static BOOL FindSidechainAcceptor(PDB *res, PDB **AtomA, PDB **AtomP)
479 {
480  static PDB *p = NULL,
481  *prev = NULL,
482  *pprev = NULL,
483  *NextRes;
484  static BOOL First = TRUE;
485 
486  if(res == NULL)
487  {
488  /* Clear statics */
489  p = NULL;
490  prev = NULL;
491  /* ACRM+++ 18.08.05 */
492  pprev = NULL;
493  First = TRUE;
494 
495  return(FALSE);
496  }
497  if(First)
498  {
499  First = FALSE;
500  p = res;
501  NextRes = blFindNextResidue(res);
502  }
503 
504  for( ; p!=NextRes; NEXT(p))
505  {
506  if((p->atnam[0] == 'O' && strncmp(p->atnam, "O ", 4)
507  && strncmp(p->atnam, "O1 ", 4)
508  && strncmp(p->atnam, "O2 ", 4)
509  && strncmp(p->atnam, "OXT ", 4)) ||
510 #ifdef ALLOW_AXN
511  (p->atnam[0] == 'A') ||
512 #endif
513  (p->atnam[0] == 'N' && strncmp(p->atnam, "N ", 4)))
514  {
515  *AtomA = p;
516  *AtomP = prev;
517 
518 /* ACRM+++ 18.08.05 */
519  if((*AtomP) &&
520  ((*AtomP)->atnam_raw[2] == (*AtomA)->atnam_raw[2]))
521  {
522  *AtomP = pprev;
523  }
524  pprev = prev;
525 /* ACRM=== */
526 
527  prev = p;
528  NEXT(p);
529 
530  return(TRUE);
531  }
532  /* ACRM+++ 18.08.05 */
533  pprev = prev;
534 
535  prev = p;
536  }
537 
538  return(FALSE);
539 }
540 
541 
542 /************************************************************************/
543 /*>static BOOL FindSidechainDonor(PDB *res, PDB **AtomH, PDB **AtomD)
544  ------------------------------------------------------------------
545 *//**
546 
547  \param[in] *res Pointer to residue of interest
548  \param[out] **AtomH The hydrogen
549  \param[out] **AtomD The 'donor' atom
550  \return Success?
551 
552  Finds pointers to sidechain donor atoms. Each call will return
553  a new set of atoms till all are found.
554 
555  Call with all parameters set to NULL before each new residue
556 
557 - 25.01.96 Original By: ACRM
558 - 09.02.96 Added #ifdef'd code to allow AE1/AE2 AD1/AD2
559 - 19.12.02 Fixed bug in walking over multiple hydrogens. This fixes
560  a problem when the last ATOM residue is a donor and is
561  followed by only water (or mercury!) HETATMs
562  Also fixed a bug where a lone residue occurs which appears
563  to have just a hydrogen.
564 - 07.07.14 Use bl prefix for functions By: CTP
565 */
566 static BOOL FindSidechainDonor(PDB *res, PDB **AtomH, PDB **AtomD)
567 {
568  static PDB *p = NULL,
569  *prev = NULL,
570  *NextRes;
571  static BOOL First = TRUE;
572 
573  if(res == NULL)
574  {
575  /* Clear statics */
576  p = NULL;
577  prev = NULL;
578  First = TRUE;
579 
580  return(FALSE);
581  }
582  if(First)
583  {
584  First = FALSE;
585  p = res;
586  NextRes = blFindNextResidue(res);
587  }
588 
589  for( ; p!=NextRes; NEXT(p))
590  {
591 #ifdef ALLOW_AXN
592  if(p->atnam[0] == 'A')
593  {
594  *AtomD = p;
595  *AtomH = NULL;
596  prev = p;
597  NEXT(p);
598 
599  return(TRUE);
600  }
601 #endif
602  if(p->atnam[0] == 'H' && strncmp(p->atnam, "H ", 4))
603  {
604  *AtomH = p;
605  *AtomD = prev;
606 
607  if(*AtomD == NULL)
608  continue;
609 
610  /* Step over any multiple hydrogens */
611  while((p!=NULL) && (p!=NextRes) && (p->atnam[0] == 'H'))
612  {
613  prev = p;
614  NEXT(p);
615  }
616 
617  /* If the donor is an oxygen or a nitrogen on a lysine, the
618  preceding torsion is rotatable, so we don't know where the
619  H will be
620  */
621  if( (*AtomD)->atnam[0] == 'O' ||
622  ((*AtomD)->atnam[0] == 'N' &&
623  !strncmp((*AtomD)->resnam,"LYS",3)))
624  {
625  *AtomH = NULL;
626  }
627 
628  return(TRUE);
629  }
630  prev = p;
631  }
632 
633  return(FALSE);
634 }
635 
636 /************************************************************************/
637 /*>int blIsMCDonorHBonded(PDB *res1, PDB *res2, int type)
638  ------------------------------------------------------
639 *//**
640 
641  \param[in] *res1 First residue
642  \param[in] *res2 Second residue
643  \param[in] type HBond type to search for
644  \return HBond type found or 0 if none
645 
646  Determines whether 2 residues are H-bonded using the crude criteria
647  of Baker & Hubbard, 1984 (Prog. Biophys. & Mol. Biol, 44, 97-179)
648 
649  N.B. Explicit hydrogens must be added to the PDB linked list before
650  calling this routine!
651 
652  Searches for HBonds, in which the first residue is a mainchain donor
653  and the second residue is an acceptor. Type should be
654  HBOND_BACK2 or HBOND_SIDE2 depending whether the second residue
655  (the acceptor) is backbond or sidechain
656 
657 - 17.01.06 Original modified from IsHbonded() By: ACRM
658 - 07.07.14 Use bl prefix for functions By: CTP
659 */
660 int blIsMCDonorHBonded(PDB *res1, PDB *res2, int type)
661 {
662  PDB *AtomH, /* The hydrogen */
663  *AtomD, /* The hydrogen donor */
664  *AtomA, /* The acceptor */
665  *AtomP; /* The acceptor's antecedent */
666 
667  /* Find H-bonds involving the backbone of res1 */
668  if(FindBackboneDonor(res1, &AtomH, &AtomD))
669  {
670  if(ISSET(type, HBOND_BACK2))
671  {
672  if(FindBackboneAcceptor(res2, &AtomA, &AtomP))
673  {
674  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
675  return(HBOND_BACK2);
676  }
677  }
678  if(ISSET(type, HBOND_SIDE2))
679  {
680  /* Clear internal flags */
681  FindSidechainAcceptor(NULL, NULL, NULL);
682  while(FindSidechainAcceptor(res2, &AtomA, &AtomP))
683  {
684  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
685  return(HBOND_SIDE2);
686  }
687  }
688  }
689 
690  return(0);
691 }
692 
693 /************************************************************************/
694 /*>int blIsMCAcceptorHBonded(PDB *res1, PDB *res2, int type)
695  ---------------------------------------------------------
696 *//**
697 
698  \param[in] *res1 First residue
699  \param[in] *res2 Second residue
700  \param[in] type HBond type to search for
701  \return HBond type found or 0 if none
702 
703  Determines whether 2 residues are H-bonded using the crude criteria
704  of Baker & Hubbard, 1984 (Prog. Biophys. & Mol. Biol, 44, 97-179)
705 
706  N.B. Explicit hydrogens must be added to the PDB linked list before
707  calling this routine!
708 
709  Searches for HBonds, in which the first residue is a mainchain
710  acceptor and the second residue is a donor. Type should be
711  HBOND_BACK2 or HBOND_SIDE2 depending whether the second residue
712  (the acceptor) is backbond or sidechain
713 
714 - 17.01.06 Original By: ACRM
715 - 07.07.14 Use bl prefix for functions By: CTP
716 */
717 int blIsMCAcceptorHBonded(PDB *res1, PDB *res2, int type)
718 {
719  PDB *AtomH, /* The hydrogen */
720  *AtomD, /* The hydrogen donor */
721  *AtomA, /* The acceptor */
722  *AtomP; /* The acceptor's antecedent */
723 
724  /* Find H-bonds involving the backbone of res1 */
725  if(FindBackboneAcceptor(res1, &AtomA, &AtomP))
726  {
727  if(ISSET(type, HBOND_BACK2))
728  {
729  if(FindBackboneDonor(res2, &AtomH, &AtomD))
730  {
731  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
732  return(HBOND_BACK2);
733  }
734  }
735  if(ISSET(type, HBOND_SIDE2))
736  {
737  /* Clear internal flags */
738  FindSidechainDonor(NULL, NULL, NULL);
739  while(FindSidechainDonor(res2, &AtomH, &AtomD))
740  {
741  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
742  return(HBOND_BACK1|HBOND_SIDE2);
743  }
744  }
745  }
746 
747  return(0);
748 }
749 
750 
751 /************************************************************************/
752 /*>void blSetMaxProteinHBondDADistance(REAL dist)
753  ----------------------------------------------
754 *//**
755  \param[in] dist Distance
756 
757  Wrapper to set the static variable for maximum D-A distance
758 
759  16.06.99 Original By: ACRM
760 */
762 {
763  dist *= dist;
764  sDADistSq = dist;
765 }
766 
767 
768 /************************************************************************/
769 /*>HBLIST *blListAllHBonds(PDB *res1, PDB *res2)
770  ----------------------------------------------
771 *//**
772  \param[in] *res1 Pointer to first residue
773  \param[in] *res2 Pointer to second residue
774  \return Linked list of hydrogen bonds
775 
776  Finds all HBonds between two specified residues
777 
778 - 20.07.15 Original By: ACRM
779 - 21.07.15 Corrected to blValidHBond()
780 */
782 {
783  PDB *AtomH, /* The hydrogen */
784  *AtomD, /* The hydrogen donor */
785  *AtomA, /* The acceptor */
786  *AtomP; /* The acceptor's antecedent */
787  HBLIST *hb = NULL;
788 
789  int type = HBOND_ANY;
790 
791  /* Find H-bonds involving the backbone of res1 */
792  if(ISSET(type, HBOND_BACK1))
793  {
794  if(FindBackboneDonor(res1, &AtomH, &AtomD))
795  {
796  if(ISSET(type, HBOND_BACK2))
797  {
798  if(FindBackboneAcceptor(res2, &AtomA, &AtomP))
799  {
800  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
801  {
802  if((hb = malloc(sizeof(HBLIST)))==NULL)
803  return(NULL);
804  hb->next = NULL;
805  hb->donor = AtomD;
806  hb->acceptor = AtomA;
807  return(hb);
808  }
809 
810  }
811  }
812  if(ISSET(type, HBOND_SIDE2))
813  {
814  /* Clear internal flags */
815  FindSidechainAcceptor(NULL, NULL, NULL);
816  while(FindSidechainAcceptor(res2, &AtomA, &AtomP))
817  {
818  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
819  {
820  if((hb = malloc(sizeof(HBLIST)))==NULL)
821  return(NULL);
822  hb->next = NULL;
823  hb->donor = AtomD;
824  hb->acceptor = AtomA;
825  return(hb);
826  }
827  }
828  }
829  }
830  if(FindBackboneAcceptor(res1, &AtomA, &AtomP))
831  {
832  if(ISSET(type, HBOND_BACK2))
833  {
834  if(FindBackboneDonor(res2, &AtomH, &AtomD))
835  {
836  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
837  {
838  if((hb = malloc(sizeof(HBLIST)))==NULL)
839  return(NULL);
840  hb->next = NULL;
841  hb->donor = AtomD;
842  hb->acceptor = AtomA;
843  return(hb);
844  }
845  }
846  }
847  if(ISSET(type, HBOND_SIDE2))
848  {
849  /* Clear internal flags */
850  FindSidechainDonor(NULL, NULL, NULL);
851  while(FindSidechainDonor(res2, &AtomH, &AtomD))
852  {
853  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
854  {
855  if((hb = malloc(sizeof(HBLIST)))==NULL)
856  return(NULL);
857  hb->next = NULL;
858  hb->donor = AtomD;
859  hb->acceptor = AtomA;
860  return(hb);
861  }
862  }
863  }
864  }
865  }
866 
867  /* Find H-bonds involving sidechain of res1 */
868  if(ISSET(type, HBOND_SIDE1))
869  {
870  /* Clear internal flags */
871  FindSidechainDonor(NULL, NULL, NULL);
872  while(FindSidechainDonor(res1, &AtomH, &AtomD))
873  {
874  if(ISSET(type, HBOND_BACK2))
875  {
876  if(FindBackboneAcceptor(res2, &AtomA, &AtomP))
877  {
878  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
879  {
880  if((hb = malloc(sizeof(HBLIST)))==NULL)
881  return(NULL);
882  hb->next = NULL;
883  hb->donor = AtomD;
884  hb->acceptor = AtomA;
885  return(hb);
886  }
887  }
888  }
889  if(ISSET(type, HBOND_SIDE2))
890  {
891  /* Clear internal flags */
892  FindSidechainAcceptor(NULL, NULL, NULL);
893  while(FindSidechainAcceptor(res2, &AtomA, &AtomP))
894  {
895  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
896  {
897  if((hb = malloc(sizeof(HBLIST)))==NULL)
898  return(NULL);
899  hb->next = NULL;
900  hb->donor = AtomD;
901  hb->acceptor = AtomA;
902  return(hb);
903  }
904  }
905  }
906  }
907  /* Clear internal flags */
908  FindSidechainAcceptor(NULL, NULL, NULL);
909  while(FindSidechainAcceptor(res1, &AtomA, &AtomP))
910  {
911  if(ISSET(type, HBOND_BACK2))
912  {
913  if(FindBackboneDonor(res2, &AtomH, &AtomD))
914  {
915  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
916  {
917  if((hb = malloc(sizeof(HBLIST)))==NULL)
918  return(NULL);
919  hb->next = NULL;
920  hb->donor = AtomD;
921  hb->acceptor = AtomA;
922  return(hb);
923  }
924  }
925  }
926  if(ISSET(type, HBOND_SIDE2))
927  {
928  /* Clear internal flags */
929  FindSidechainDonor(NULL, NULL, NULL);
930  while(FindSidechainDonor(res2, &AtomH, &AtomD))
931  {
932  if(blValidHBond(AtomH, AtomD, AtomA, AtomP))
933  {
934  if((hb = malloc(sizeof(HBLIST)))==NULL)
935  return(NULL);
936  hb->next = NULL;
937  hb->donor = AtomD;
938  hb->acceptor = AtomA;
939  return(hb);
940  }
941  }
942  }
943  }
944  }
945 
946  return(NULL);
947 }
948 
949 
950 
951 
952 /*************************************************************************
953 ** **
954 ** DEMO CODE **
955 ** **
956 *************************************************************************/
957 #ifdef DEMO_CODE
958 
959 #include <stdio.h>
960 
961 int main(int argc, char **argv)
962 {
963  FILE *fp,
964  *pgp;
965  PDB *pdb,
966  *p, *q;
967  int natom,
968  nhyd;
969  BOOL noenv;
970 
971  if(argc != 2 || argv[1][0] == '-')
972  {
973  fprintf(stderr,"Usage: hbond <file.pdb>\n");
974  fprintf(stderr,"Generates a list of all HBonds in the PDB file\n");
975  return(0);
976  }
977 
978  /* Open the PDB file */
979  if((fp = fopen(argv[1],"r")))
980  {
981  /* Open the PGP file */
982  if((pgp = blOpenFile("Explicit.pgp","DATADIR","r",&noenv)))
983  {
984  /* Read the PDB file */
985  if((pdb = blReadPDB(fp, &natom)))
986  {
987  /* Add hydrogens */
988  if((nhyd = blHAddPDB(pgp, pdb)))
989  {
990  /* Loop through each residue */
991  for(p=pdb; p!=NULL; p=blFindNextResidue(p))
992  {
993  /* Loop through each following residue */
994  for(q=blFindNextResidue(p); q!=NULL; q=blFindNextResidue(q))
995  {
996  /* Print message if there is any HBond */
997  if(blIsHBonded(p, q, HBOND_ANY))
998  printf("%s%d%s HBonded to %s%d%s\n",
999  p->chain, p->resnum, p->insert,
1000  q->chain, q->resnum, q->insert);
1001  }
1002  }
1003  }
1004  else
1005  {
1006  fprintf(stderr,"No hydrogens added to PDB file\n");
1007  }
1008  }
1009  else
1010  {
1011  fprintf(stderr,"No atoms read from PDB file\n");
1012  }
1013  }
1014  else
1015  {
1016  fprintf(stderr,"Unable to open PGP file: Explicit.pgp\n");
1017  }
1018  }
1019  else
1020  {
1021  fprintf(stderr,"Unable to open PDB file: %s\n");
1022  }
1023 
1024  return(0);
1025 }
1026 #endif
int main(int argc, char **argv)
Definition: test.c:4
Include file for PDB routines.
struct _hblist * next
Definition: hbond.h:80
void blSetMaxProteinHBondDADistance(REAL dist)
Definition: hbond.c:761
Header file for hbond determining code.
int resnum
Definition: pdb.h:310
short BOOL
Definition: SysDefs.h:64
#define NULL
Definition: array2.c:99
Definition: pdb.h:298
#define PI
Definition: macros.h:215
#define HADISTSQ
Definition: hbond.c:115
#define FALSE
Definition: macros.h:223
#define DADISTSQ
Definition: hbond.c:113
#define NEXT(x)
Definition: macros.h:249
REAL blAngle(REAL xi, REAL yi, REAL zi, REAL xj, REAL yj, REAL zj, REAL xk, REAL yk, REAL zk)
Definition: angle.c:150
#define HBOND_ANY
Definition: hbond.h:76
Useful macros.
int blIsMCAcceptorHBonded(PDB *res1, PDB *res2, int type)
Definition: hbond.c:717
FILE * blOpenFile(char *filename, char *envvar, char *mode, BOOL *noenv)
Definition: OpenFile.c:146
int blIsHBonded(PDB *res1, PDB *res2, int type)
Definition: hbond.c:173
char atnam[8]
Definition: pdb.h:316
char resnam[8]
Definition: pdb.h:319
double REAL
Definition: MathType.h:67
REAL z
Definition: pdb.h:300
PDB * blReadPDB(FILE *fp, int *natom)
Definition: ReadPDB.c:419
int blIsMCDonorHBonded(PDB *res1, PDB *res2, int type)
Definition: hbond.c:660
int type
Definition: hash.h:80
Include file for angle functions.
#define ISSET(x, y)
Definition: macros.h:557
#define TRUE
Definition: macros.h:219
int blHAddPDB(FILE *fp, PDB *pdb)
Definition: HAddPDB.c:250
Header file for general purpose routines.
Definition: hbond.h:78
System-type variable type definitions.
PDB * blFindNextResidue(PDB *pdb)
Type definitions for maths.
#define DISTSQ(a, b)
Definition: macros.h:228
PDB * donor
Definition: hbond.h:81
#define HBOND_BACK2
Definition: hbond.h:65
char chain[blMAXCHAINLABEL]
Definition: pdb.h:321
PDB * acceptor
Definition: hbond.h:81
#define HBOND_SIDE2
Definition: hbond.h:67
REAL x
Definition: pdb.h:300
REAL y
Definition: pdb.h:300
HBLIST * blListAllHBonds(PDB *res1, PDB *res2)
Definition: hbond.c:781
BOOL blValidHBond(PDB *AtomH, PDB *AtomD, PDB *AtomA, PDB *AtomP)
Definition: hbond.c:303
char insert[8]
Definition: pdb.h:320
#define HBOND_BACK1
Definition: hbond.h:64
#define HBOND_SIDE1
Definition: hbond.h:66