Bioplib
Protein Structure C Library
 All Data Structures Files Functions Variables Typedefs Macros Pages
HAddPDB.c
Go to the documentation of this file.
1 /************************************************************************/
2 /**
3 
4  \file HAddPDB.c
5 
6  \version V2.22
7  \date 23.06.15
8  \brief Add hydrogens to a PDB linked list
9 
10  \copyright (c) UCL / Dr. Andrew C. R. Martin 1990-2015
11  \author Dr. Andrew C. R. Martin
12  \par
13  Institute of Structural & Molecular Biology,
14  University College London,
15  Gower Street,
16  London.
17  WC1E 6BT.
18  \par
19  andrew@bioinf.org.uk
20  andrew.martin@ucl.ac.uk
21 
22 **************************************************************************
23 
24  This code is NOT IN THE PUBLIC DOMAIN, but it may be copied
25  according to the conditions laid out in the accompanying file
26  COPYING.DOC.
27 
28  The code may be modified as required, but any modifications must be
29  documented so that the person responsible can be identified.
30 
31  The code may not be sold commercially or included as part of a
32  commercial product except as described in the file COPYING.DOC.
33 
34 **************************************************************************
35 
36  Description:
37  ============
38 
39  Routine to add hydrogens to a protein linked list of type PDB.
40  The routine allocates space for the new atoms and inserts them
41  into the list at the appropriate positions within the residues.
42 
43  N.B. Because of the variation in styles required for N-terminal Hs,
44  this routine adds *no* hydrogens to the N-terminal residue. FixPDB()
45  may be used for this purpose if CHARMM/CONGEN style hydrogens are
46  required.
47 
48 **************************************************************************
49 
50  Usage:
51  ======
52 
53 \code
54  nhyd = blHAddPDB(fp,pdb)
55 \endcode
56 
57  \param[in] *fp File containing proton generation
58  parameters.
59  \param[in,out] *pdb Linked list of protein structure.
60  \return Number of hydrogens added.
61 
62  The globally defined structure gHaddInfo gives information on the
63  number of each hydrogen type created. This structure is defined as
64  follows:
65 
66 \code
67  typdef struct
68  {
69  int Total, Total hydrogens
70  T1, Type 1 C-H's
71  T2, Type 2 C-H2's
72  T3, Type 3 C-H3's
73  T4, Type 4 sp2 C-H's,>N-H
74  T5; Type 5 O-H's =N-H's
75  } HADDINFO;
76 \endcode
77 
78  To examine these values in your code, reference the structure as:
79  extern HADDINFO gHaddInfo;
80 
81 **************************************************************************
82 
83  Revision History:
84  =================
85 - V2.0 16.05.90 AddH is changed to insert each set of atoms for each
86  PGP, on the fly, rather than building a complete list
87  of hydrogens and then merging the two lists. This allows
88  us to get round the problem of missing atoms, since
89  there will be no merging error.
90 
91 - V2.1 24.05.90 Returns the number fo hydrogens added. Also fixes bug
92  relating to number of type 2 and type 3 H's added.
93  Doesn't work under UNIX!
94 
95 - V2.2 15.07.91 A few bits of tidying up:
96  > Now uses macros.h rather than defining macros itself.
97  > Arrays now changed so should fix alignment problems
98  under UNIX.
99  > Now correctly checks return from forscanf() and no
100  longer reads characters to check EOF itself.
101  > Improves treatment of NTER residues where it now
102  generates H's on the first true residue. Residues
103  labelled NTER will be ignored. Calling FixNterH()
104  will move the H coords into the NTER residue if
105  required.
106  > Fixes reading of PGP files with blank lines
107  > Bug fix for type 3's
108  Currently untested under UNIX.
109 
110 - V2.3 27.07.93 Changed to use fsscanf() and I/O precision is double
111 - V2.4 08.03.94 Changed static variable names and added casts on
112  maths functions. Added Dummy atom handling in makeh().
113  A few other bits of tidying.
114 - V2.5 23.08.94 Added OpenPGPFile() routine
115 - V2.6 01.09.94 Fixed bug in some compilers in ReadPGP()
116 - V2.7 26.01.96 Wasn't handling insert codes in PDB.
117 - V2.8 24.05.99 Fixed two memory leaks in makeh()
118  Also skips HETATMs in GenH()
119 - V2.9 30.05.02 Changed PDB field from 'junk' to 'record_type'
120 - V2.10 05.12.02 Correctly sets the atnam_raw field
121 - V2.11 27.03.03 Fixed severe memory leak in AddH()
122 - V2.12 03.06.05 Added altpos
123 - V2.13 28.07.05 Added conditionals for msdos and Mac OS/X
124 - V2.14 28.11.05 No longer exits if previous C is missing
125 - V2.15 24.01.06 Fixed error message in GenH() which could try to print
126  from NULL pointer
127 - V2.16 20.03.14 Updated error message in GenH(). By: CTP
128 - V2.17 07.07.14 Use bl prefix for functions By: CTP
129 - V2.18 26.08.14 Moved use of ok variable into #ifdef SCREEN_INFO and
130  cleaned up use of n and nt variables instead of literal
131  strings
132 - V2.19 13.02.15 Handles elements By: ACRM
133 - V2.20 17.02.15 Handles segid and formal charge
134 - V2.21 23.02.15 Uses new blRenumAtomsPDB()
135 - V2.22 23.06.15 Various calls to CLEAR_PDB() to fix problems with
136  uninitialized CONECT data
137 
138 *************************************************************************/
139 /* Doxygen
140  -------
141  #GROUP Handling PDB Data
142  #SUBGROUP Modifying the structure
143  #FUNCTION blHAddPDB()
144  This routine adds hydrogens to a PDB linked list. Performs all
145  necessary functions.
146 
147  #FUNCTION blReadPGP()
148  Read a proton generation parameter file
149 
150  #FUNCTION blOpenPGPFile()
151  Open the PGP file
152 */
153 /************************************************************************/
154 /* Includes
155 */
156 #include <stdio.h>
157 #include <math.h>
158 #include <string.h>
159 #include <stdlib.h>
160 
161 #include "MathType.h"
162 #include "SysDefs.h"
163 #include "pdb.h"
164 #include "fsscanf.h"
165 #include "macros.h"
166 #include "general.h"
167 
168 /************************************************************************/
169 /* Defines and macros
170 */
171 #define MAXTYPE 300 /* Max number of H definitions in PGP file */
172 #define MAXLABEL 8 /* Max chars in a label */
173 #define MAXBUFF 160 /* Buffer size */
174 #define DATAENV "DATADIR" /* Unix environment variable for data */
175 #define DATADIR "AMDATA:" /* VMS/AMigaDOS assign for data */
176 #define EXPLPGP "Explicit.pgp" /* The PGP filename */
177 #define ALLHPGP "AllH.pgp" /* The PGP filename */
178 /* #define SCREEN_INFO */ /* Error messages output via screen() */
179 
180 /************************************************************************/
181 /* Define-dependent includes
182 */
183 #ifdef SCREEN_INFO
184 # include "WindIO.h"
185 #endif
186 
187 /************************************************************************/
188 /* Globals local to this file
189 */
190 static char sGRes[MAXTYPE][MAXLABEL],
191  sGAtom[MAXTYPE][MAXLABEL][MAXLABEL],
192  sGRName[MAXLABEL],
193  sGHName[MAXLABEL][MAXLABEL],
194  sGNat[MAXATINRES][MAXLABEL],
195  sIns;
196 static int sHType[MAXTYPE],
197  sNpgp,
198  sNo,
199  sKMax,
200  sNType1, sNType2, sNType3, sNType4, sNType5;
201 static REAL sGR[MAXTYPE],
202  sAlpha[MAXTYPE],
203  sBeta[MAXTYPE],
204  sGX[MAXATINRES], sGY[MAXATINRES], sGZ[MAXATINRES],
205  sFac;
206 
207 /************************************************************************/
208 /* Globals which are externally visible
209 */
211 
212 /************************************************************************/
213 /* Prototypes for static function
214 */
215 static int GenH(PDB *pdb, BOOL *err_flag);
216 static PDB *makeh(int HType, REAL BondLen, REAL alpha, REAL beta,
217  BOOL firstres);
218 static BOOL AddH(PDB *hlist, PDB **position, int HType);
219 static void SetRawAtnam(char *out, char *in);
220 static PDB *StripDummyH(PDB *pdb, int *nhyd);
221 
222 /************************************************************************/
223 /*>int blHAddPDB(FILE *fp, PDB *pdb)
224  ----------------------------------
225 *//**
226 
227  \param[in] *fp File pointer to PGP file
228  \param[in,out] *pdb PDB Linked list to which Hs are added
229  \return Number of Hs added. -1 on error.
230 
231  Globals: HADDINFO gHaddInfo Information on Hs added
232 
233  This routine adds hydrogens to a PDB linked list. Performs all
234  necessary functions.
235 
236  N.B. Because of the variation in styles required for N-terminal Hs,
237  this routine adds *no* hydrogens to the N-terminal residue. FixPDB()
238  may be used for this purpose if CHARMM/CONGEN style hydrogens are
239  required.
240 
241 - 16.05.90 Original By: ACRM
242 - 04.01.94 Changed check on return=NULL to 0
243 - 08.03.94 Only reads PGP on first call. err_flag changed to BOOL.
244 - 28.11.05 Removes any dummy hydrogens added because there were
245  missing atoms
246 - 07.07.14 Use bl prefix for functions By: CTP
247 - 23.02.15 Uses blRenumAtomsPDB() By: ACRM
248 - 20.03.15 Returns -1 on error since zero hydrogens may be valid
249 */
250 int blHAddPDB(FILE *fp, PDB *pdb)
251 {
252  int nhydrogens;
253  BOOL err_flag = FALSE;
254  static BOOL FirstCall = TRUE;
255 
256  if(FirstCall)
257  {
258  /* Read the parameter file */
259  FirstCall = FALSE;
260  if(!blReadPGP(fp))
261  return(-1);
262  }
263 
264  /* Generate the hydrogens */
265  if((nhydrogens=GenH(pdb,&err_flag))<=0)
266  return(nhydrogens);
267 
268 /* ACRM+++ 28.11.05 */
269  /* Remove dummy hydrogens (where atoms are missing) */
270  pdb = StripDummyH(pdb, &nhydrogens);
271 /* ACRM=== 28.11.05 */
272 
273  /* Renumber atoms in PDB linked list */
274  blRenumAtomsPDB(pdb, 1);
275 
276  return(nhydrogens);
277 }
278 
279 /************************************************************************/
280 /*>int blReadPGP(FILE *fp)
281  -----------------------
282 *//**
283 
284  \param[in] *fp Pointer to PGP file.
285  \return Number of parameters read. (0 on error)
286 
287  Read a proton generation parameter file. All data are placed in static
288  arrays used by the hydrogen adding routines.
289  Normally this routine is only called by the first call to HAddPDB().
290  It is only necessary to call this routine explicitly if the PGP file
291  is changed between calls to HAddPDB() and thus needs re-reading.
292 
293 - 16.05.90 Original By: ACRM
294 - 27.07.93 Changed to use fsscanf()
295 - 01.03.94 Changed static variable names
296 - 01.09.94 Moved n++ out of the fsscanf()
297 - 07.07.14 Use bl prefix for functions By: CTP
298 - 19.03.15 Skips comments
299 - 20.03.15 Returns 0 on error (MAXTYPE exceeded)
300 */
301 int blReadPGP(FILE *fp)
302 {
303  char buffer[MAXBUFF];
304  int n=0;
305 
306  while(fgets(buffer,159,fp))
307  {
308  /* Skip comments */
309  if((buffer[0] == '#')||(buffer[0] == '!'))
310  continue;
311 
312  if(++n >= MAXTYPE)
313  return(0);
314 
315  fsscanf(buffer,
316  "%4s%4s%1x%4s%1x%4s%1x%4s%1x%4s%1x%4s%1x%1d%10lf%10lf%10lf",
317  sGRes[n],
318  sGAtom[n][1],
319  sGAtom[n][2],
320  sGAtom[n][3],
321  sGAtom[n][4],
322  sGAtom[n][5],
323  sGAtom[n][6],
324  &(sHType[n]),
325  &(sGR[n]),
326  &(sAlpha[n]),
327  &(sBeta[n]));
328 
329 #ifdef DEBUG_READ
330  printf("%4s %4s %4s %4s %4s %4s %4s %1d %8.3f %8.3f %8.3f\n",
331  sGRes[n],sGAtom[n][1],sGAtom[n][2],sGAtom[n][3],sGAtom[n][4],
332  sGAtom[n][5],sGAtom[n][6],sHType[n],sGR[n],
333  sAlpha[n],sBeta[n]);
334 #endif
335 
336  if(sHType[n] != 0)
337  {
338  sAlpha[n] *= (PI/180.0);
339  sBeta[n] *= (PI/180.0);
340  }
341  } /* End of file */
342 
343  sNpgp = n;
344  return(sNpgp);
345 }
346 
347 /************************************************************************/
348 /*>static int GenH(PDB *pdb, BOOL *err_flag)
349  -----------------------------------------
350 *//**
351 
352  \param[in,out] *pdb PDB Linked to which Hs are added
353  \param[in,out] *err_flag Error flag
354  \return Number of hydrogens added (-1 on error)
355 
356  Does the actual work of generating a set of hydrogens
357 
358 - 16.05.90 Original By: ACRM
359 - 01.03.94 Changed static variable names
360 - 08.03.94 Changed err_flag to BOOL
361 - 26.01.96 Added check on insert code as well as resnum
362 - 28.11.05 Modified such that a missing preceeding C no longer causes
363  the routine to exit
364 - 24.01.06 Fixed error message which could try to print from NULL
365  pointer
366 - 20.03.14 Updated error message. By: CTP
367 - 18.03.15 Changed to use MAXATINRES and MAXBUFF By: ACRM
368 - 20.03.15 Now returns -1 on error since zero added hydrogens might
369  not be an error.
370 */
371 static int GenH(PDB *pdb, BOOL *err_flag)
372 {
373  BOOL firstres;
374  char *bl = " ",
375  *co = "CO ",
376  *c = "C ";
377  int k, n, m, j, ittot;
378  PDB *p,*q;
379  PDB *position[MAXATINRES],*hlist;
380 #ifdef SCREEN_INFO
381  char buffer[MAXBUFF];
382 #endif
383 
384  for(j=0;j<MAXATINRES;position[j++]=NULL);
385 
386  sFac = 0.5 * (REAL)sqrt((double)3.0);
387 
388  firstres = TRUE;
389 
390  /* Main loop */
391  sNType1=0; sNType2=0; sNType3=0; sNType4=0; sNType5=0;
392 
393  /* For the first residue, we don't have info for the previous C
394  so set sGNat[1] (the atom list for this residue) to a blank
395  */
396  strcpy(sGNat[1],bl);
397 
398  position[1]=NULL;
399 
400  /* For each atom in the PDB file */
401  for(p=pdb;p;)
402  {
403  if(!strncmp(p->record_type,"HETATM",6)) /* 24.05.99 */
404  {
405  NEXT(p);
406  continue;
407  }
408 
409 
410  /* Don't do anything with NTER residues except reset firstres */
411  if(!strncmp(p->resnam,"NTER",4))
412  {
413  firstres = TRUE;
414  NEXT(p);
415  continue;
416  }
417 
418  k=1; /* This is one as this position is reserved for the CO of
419  the previous residue
420  */
421 
422  /* Copy this residue into our global work arrays.
423  sGRName is the residue name
424  sGX[],sGY[],sGZ[] are the coordinates of the atoms
425  sGNat[] are the atom names
426  */
427  do
428  {
429  k++;
430  position[k] = p;
431 
432  sNo=p->resnum;
433  sIns=p->insert[0]; /* 26.01.96 */
434  strcpy(sGRName,p->resnam);
435 #ifdef DEBUG
436  printf("Group name is: %s\n",sGRName);
437 #endif
438  strcpy(sGNat[k],p->atnam);
439 #ifdef DEBUG
440  printf("Atom %d name: %s\n",k,sGNat[k]);
441 #endif
442  sGX[k] = p->x;
443  sGY[k] = p->y;
444  sGZ[k] = p->z;
445  NEXT(p);
446  if(!p) break;
447  } while((p != NULL) &&
448  (p->resnum == sNo) &&
449  (p->insert[0] == sIns)); /* 26.01.96 */
450 
451  /* sKMax is used to store the number of atoms in this residue */
452  sKMax = k;
453 
454  /* Go through each of the PGP's until we find this residue type */
455  for(n=1;n<=sNpgp;n++)
456  {
457 #ifdef DEBUG
458  printf("sGRes(%d)=%s\n",n,sGRes[n]);
459 #endif
460  if(strncmp(sGRName,sGRes[n],4)) continue;
461 #ifdef DEBUG
462  printf("Entry found for this res. in PGP\n");
463 #endif
464 
465  /* Having found the residue type, copy the associated PGP atom
466  list into the sGHName[] work array
467  */
468  for(m=1;m<=6;m++) strcpy(sGHName[m],sGAtom[n][m]);
469 
470  /* Now generate the hydrogen(s) associated with this PGP */
471  if((hlist = makeh(sHType[n],sGR[n],sAlpha[n],sBeta[n],firstres))
472  !=NULL)
473  {
474  /* And add it into the list, updating p to point to the new
475  end of this residue
476  */
477  if(!AddH(hlist,position,sHType[n])) return(-1);
478  }
479  if(*err_flag) return(-1);
480  }
481 
482  /* If this is the first residue then handle it as NTER */
483  if(firstres)
484  {
485 #ifdef DEBUG
486  printf("Rechecking for NTER...\n");
487 #endif
488  for(n=1;n<=sNpgp;n++)
489  {
490 #ifdef DEBUG
491  printf("sGRes(%d)=%s\n",n,sGRes[n]);
492 #endif
493  if(strncmp("NTER",sGRes[n],4)) continue;
494 #ifdef DEBUG
495  printf("Entry found for NTER in PGP.\n");
496 #endif
497 
498  /* Having found the residue type, copy the associated PGP atom
499  list into the sGHName[] work array
500  */
501  for(m=1;m<=6;m++) strcpy(sGHName[m],sGAtom[n][m]);
502 
503  /* Now generate the hydrogen associated with this PGP */
504  if((hlist = makeh(sHType[n],sGR[n],sAlpha[n],
505  sBeta[n],firstres))!=NULL)
506  {
507  /* And add it into the list, updating p to point to the new
508  end of this residue
509  */
510  if(!AddH(hlist,position,sHType[n])) return(-1);
511  }
512  if(*err_flag) return(-1);
513  }
514  }
515 
516  /* Next amino acid
517  Set up pointer for carbonyl of previous residue unless this
518  residue is a CTER when we set firstres to TRUE
519  */
520 
521  if(strncmp(sGRName,"CTER",4))
522  {
523  firstres = FALSE;
524  for(j=sKMax-1;j>0;j--) if(!strncmp(sGNat[j],c,4))break;
525  if(j==0)
526  {
527 #ifdef WARNINGS
528 #ifdef SCREEN_INFO
529  sprintf(buffer,"\nError==> genh() found no carbonyl carbon \
530 in residue %d\n\n",p->resnum);
531  screen(buffer);
532 #endif
533 /* ACRM--- 25.11.05
534  *err_flag=TRUE;
535  return(-1);
536 */
537 /* ACRM+++ 28.11.05 */
538 /* ACRM 24.01.06 */
539  if(p!=NULL)
540  {
541  fprintf(stderr,"Warning=> genh() found no carbonyl carbon \
542 preceeding residue %s%d%s\n", p->chain, p->resnum, p->insert);
543  }
544  else
545  {
546  fprintf(stderr,"Warning=> genh() found no carbonyl carbon \
547 preceeding the last residue\n");
548  }
549 #endif
550  sGX[1]=9999.0;
551  sGY[1]=9999.0;
552  sGZ[1]=9999.0;
553 
554 /* ACRM=== 28.11.05 */
555  }
556  else
557  {
558  sGX[1]=sGX[j];
559  sGY[1]=sGY[j];
560  sGZ[1]=sGZ[j];
561  }
562  strcpy(sGNat[1],co);
563  q=position[j];
564 
565  for(k=0;k<MAXATINRES;position[k++]=NULL);
566  position[1]=q;
567  }
568  else
569  {
570  firstres = TRUE;
571  }
572 
573  } /* Go back to the next atom/residue */
574 
575  ittot=sNType1+sNType2+sNType3+sNType4+sNType5;
576 
577  gHaddInfo.Total = ittot;
578  gHaddInfo.T1 = sNType1;
579  gHaddInfo.T2 = sNType2;
580  gHaddInfo.T3 = sNType3;
581  gHaddInfo.T4 = sNType4;
582  gHaddInfo.T5 = sNType5;
583 
584  return(ittot);
585 }
586 
587 /************************************************************************/
588 /*>static PDB *makeh(int HType, REAL BondLen, REAL alpha, REAL beta,
589  BOOL firstres)
590  -----------------------------------------------------------------
591 *//**
592 
593  \param[in] HType Hydrogen type number
594  \param[in] BondLen Length of the bond to the added hydrogen
595  \param[in] alpha The first angle defining the H coordinate
596  \param[in] beta The second angle defining the H coordinate
597  \param[in] firstres If set, don't add a planar hydrogen as it's
598  the first residue of a chain
599  \return Pointer to linked list of created hydrogens.
600  NULL if memory allocation fails or this is the
601  Nter N where we don't require a planar H or
602  all atoms have been done.
603 
604  Generate a set of hydrogen coordinates. The antecedent atoms are set
605  in static external variables. A linked list containing the
606  appropriate number of Hs is returned.
607 
608 - 16.05.90 Original By: ACRM
609 - 08.03.94 Added code to handle dummy atom positions (All occurences
610  of variable `Dummy'). Made assigned character strings static.
611 - 26.01.96 Now stores insert codes into hlist
612 - 24.05.99 Fixed two memory leaks
613 - 05.12.02 Added setting of atnam_raw
614 - 03.06.05 Added setting of altpos
615 - 07.07.14 Use bl prefix for functions By: CTP
616 - 26.08.14 Used n and nt variables consistently instead of literal
617  strings. Moved all use of 'ok' variable into SCREEN_INFO
618 - 13.02.15 Added setting of element type
619 */
620 static PDB *makeh(int HType, REAL BondLen, REAL alpha, REAL beta,
621  BOOL firstres)
622 {
623  static char *nt = "NT ",
624  *n = "N ";
625  REAL x1,y1,z1,x2,y2,z2,x3,y3,z3,
626  x4,y4,z4,x5,y5,z5,x6,y6,z6,
627  x21,y21,z21,r21,
628  x21p,y21p,z21p,r21p,
629  x23,y23,z23,r23,
630  xp23,yp23,zp23,rp23,
631  x24,y24,z24,r24,
632  x32,y32,z32,
633  xv25,yv25,zv25,rv25,
634  cosa,sina,
635  cosb,sinb,
636  cosax,cosay,cosaz,
637  xa,ya,za,xb,yb,zb,
638  xab,yab,zab,rab,
639  xmin,ymin,zmin,
640  xapb,yapb,zapb,rapb,
641  xplus,yplus,zplus,
642  xp,yp,zp,
643  xs,ys,zs,
644  xh,yh,zh,
645  xv,yv,zv,
646  scalpr;
647  int kount = 0,
648  num_ant,k;
649  unsigned short nt_point;
650  BOOL Dummy;
651  PDB *hlist,
652  *hlist_start = NULL;
653 
654  Dummy = FALSE;
655 
656  INIT(hlist_start, PDB);
657  if(hlist_start == NULL) return(NULL);
658 
659  CLEAR_PDB(hlist_start);
660  hlist = hlist_start;
661 
662  nt_point = 0;
663  if(HType==1) num_ant=4; else num_ant=3;
664 
665  /* Don't add a planar H to the Nter N. */
666  if(firstres && HType==4 && !strncmp(sGHName[2],n,4))
667  {
668  /* 24.05.99 Fixed memory leak */
669  free(hlist_start);
670  return(NULL);
671  }
672 
673  /* Work through the atoms in this residue (sGNat[]) and compare them
674  with the first 4 atoms in the PGP atom list in sGHName[], storing
675  the associated coordinates
676  */
677  for(k=1; k<=sKMax; k++)
678  {
679  if(nt_point)
680  {
681  strcpy(sGNat[nt_point],n);
682  nt_point=0;
683  }
684 
685  if(!strncmp(sGHName[1],sGNat[k],4))
686  {
687  if(!strncmp(sGNat[k],nt,4)) nt_point=k;
688  kount++;
689  x1=sGX[k];
690  y1=sGY[k];
691  z1=sGZ[k];
692 
693  /* Check for dummy atom */
694  if(x1 > (REAL)9998.0 &&
695  y1 > (REAL)9998.0 &&
696  z1 > (REAL)9998.0)
697  Dummy = TRUE;
698  }
699  else if(!strncmp(sGHName[2],sGNat[k],4))
700  {
701  if(!strncmp(sGNat[k],nt,4)) nt_point=k;
702  kount++;
703  x2=sGX[k];
704  y2=sGY[k];
705  z2=sGZ[k];
706 
707  /* Check for dummy atom */
708  if(x2 > (REAL)9998.0 &&
709  y2 > (REAL)9998.0 &&
710  z2 > (REAL)9998.0)
711  Dummy = TRUE;
712  }
713  else if(!strncmp(sGHName[3],sGNat[k],4))
714  {
715  if(!strncmp(sGNat[k],nt,4)) nt_point=k;
716  kount++;
717  x3=sGX[k];
718  y3=sGY[k];
719  z3=sGZ[k];
720 
721  /* Check for dummy atom */
722  if(x3 > (REAL)9998.0 &&
723  y3 > (REAL)9998.0 &&
724  z3 > (REAL)9998.0)
725  Dummy = TRUE;
726  }
727  else if(!strncmp(sGHName[4],sGNat[k],4))
728  {
729  if(!strncmp(sGNat[k],nt,4)) nt_point=k;
730  kount++;
731  x4=sGX[k];
732  y4=sGY[k];
733  z4=sGZ[k];
734 
735  /* Check for dummy atom */
736  if(x4 > (REAL)9998.0 &&
737  y4 > (REAL)9998.0 &&
738  z4 > (REAL)9998.0)
739  Dummy = TRUE;
740  }
741  } /* End of k loop around this residue */
742 
743  /* Check we found all the atoms we need for this PGP */
744  if(kount != num_ant)
745  {
746 #ifdef SCREEN_INFO
747  BOOL ok = FALSE;
748  int jj;
749 
750  if(firstres)
751  {
752  /* Check it's not the missing N in the first residue */
753  for(jj=1;jj<=4;jj++) if(!strncmp(sGHName[jj],n,4)) ok = TRUE;
754  }
755  else
756  {
757  /* Check it's not just the NT */
758  for(jj=1;jj<=4;jj++) if(!strncmp(sGHName[jj],nt,4)) ok = TRUE;
759  }
760  if(!ok)
761  {
762  char buffer[MAXBUFF];
763 
764  sprintf(buffer,"Error==> makeh() unable to find all atoms \
765 required by PGP parameter for %3s %5d%c\n",sGRName,sNo,sIns);
766  screen(buffer);
767  screen("Atoms required by PGP\n");
768  screen("SGHNAME: ");
769  for(jj=1;jj<=4;jj++)
770  {
771  sprintf(buffer," %4s",sGHName[jj]);
772  screen(buffer);
773  }
774  screen("\n");
775  screen("Atoms in current residue\n");
776  screen("SGNAT : ");
777  for(jj=1;jj<=sKMax;jj++)
778  {
779  sprintf(buffer," %4s",sGNat[jj]);
780  screen(buffer);
781  }
782  screen("\n");
783  }
784 #endif
785  /* 24.05.99 Fixed memory leak */
786  FREELIST(hlist_start, PDB);
787  return(NULL);
788  }
789 
790  x21=x2-x1;
791  y21=y2-y1;
792  z21=z2-z1;
793  r21=(REAL)sqrt((double)(x21*x21 + y21*y21 + z21*z21));
794 
795  x23=x2-x3;
796  y23=y2-y3;
797  z23=z2-z3;
798  r23=(REAL)sqrt((double)(x23*x23 + y23*y23 + z23*z23));
799 
800  if(HType == 1)
801  {
802  /* HTYPE 1: Generation of 1 tetrahedral H
803  --------------------------------------
804  */
805 
806  if(Dummy)
807  {
808  x5 = y5 = z5 = (REAL)9999.0;
809  }
810  else
811  {
812  x24=x2-x4;
813  y24=y2-y4;
814  z24=z2-z4;
815  r24=(REAL)sqrt((double)(x24*x24 + y24*y24 + z24*z24));
816  xv25=x21/r21+x24/r24+x23/r23;
817  yv25=y21/r21+y24/r24+y23/r23;
818  zv25=z21/r21+z24/r24+z23/r23;
819  rv25=(REAL)sqrt((double)(xv25*xv25 + yv25*yv25 + zv25*zv25));
820  x5=x2+BondLen*xv25/rv25;
821  y5=y2+BondLen*yv25/rv25;
822  z5=z2+BondLen*zv25/rv25;
823  }
824 
825  hlist->resnum=sNo;
826  hlist->insert[0]=sIns; /* 26.01.96 */
827  blPadterm(hlist->insert,4);
828  strcpy(hlist->atnam,sGHName[5]);
829  SetRawAtnam(hlist->atnam_raw, sGHName[5]); /* 05.12.02 */
830  hlist->altpos = ' '; /* 03.06.05 */
831  hlist->x=x5;
832  hlist->y=y5;
833  hlist->z=z5;
834  strcpy(hlist->element,"H"); /* 13.02.15 */
835  ALLOCNEXT(hlist,PDB);
836  if(hlist == NULL)
837  {
838  FREELIST(hlist_start, PDB);
839  return(NULL);
840  }
841  CLEAR_PDB(hlist);
842 
843 #ifdef DEBUG
844  printf("makeh() Type 1 allocated hlist = %d\n",(int)hlist);
845 #endif
846 
847  sNType1++;
848  } /* End of HTYPE 1 */
849  else /* All types other than HTYPE 1 */
850  {
851  cosa=(REAL)cos((double)alpha);
852  sina=(REAL)sin((double)alpha);
853  switch(HType)
854  {
855  case 2:
856  /* HTYPE 2: Generation of 2 tetrahedral H's
857  ----------------------------------------
858  */
859  if(Dummy)
860  {
861  x4 = y4 = z4 = (REAL)9999.0;
862  x5 = y5 = z5 = (REAL)9999.0;
863  }
864  else
865  {
866  xa=x21/r21;
867  ya=y21/r21;
868  za=z21/r21;
869  xb=x23/r23;
870  yb=y23/r23;
871  zb=z23/r23;
872  xab=xa-xb;
873  yab=ya-yb;
874  zab=za-zb;
875  rab=(REAL)sqrt((double)(xab*xab+yab*yab+zab*zab));
876  xmin=xab/rab;
877  ymin=yab/rab;
878  zmin=zab/rab;
879  xapb=xa+xb;
880  yapb=ya+yb;
881  zapb=za+zb;
882  rapb=(REAL)sqrt((double)(xapb*xapb+yapb*yapb+zapb*zapb));
883  xplus=xapb/rapb;
884  yplus=yapb/rapb;
885  zplus=zapb/rapb;
886  xs=yplus*zmin-zplus*ymin;
887  ys=zplus*xmin-xplus*zmin;
888  zs=xplus*ymin-yplus*xmin;
889  x4=x2+BondLen*(cosa*xplus+sina*xs);
890  y4=y2+BondLen*(cosa*yplus+sina*ys);
891  z4=z2+BondLen*(cosa*zplus+sina*zs);
892  x5=x2+BondLen*(cosa*xplus-sina*xs);
893  y5=y2+BondLen*(cosa*yplus-sina*ys);
894  z5=z2+BondLen*(cosa*zplus-sina*zs);
895  }
896 
897  hlist->resnum=sNo;
898  hlist->insert[0]=sIns; /* 26.01.96 */
899  blPadterm(hlist->insert,4);
900  strcpy(hlist->atnam,sGHName[4]);
901  SetRawAtnam(hlist->atnam_raw, sGHName[4]); /* 05.12.02 */
902  hlist->altpos = ' '; /* 03.06.05 */
903  hlist->x=x4;
904  hlist->y=y4;
905  hlist->z=z4;
906  strcpy(hlist->element,"H"); /* 13.02.15 */
907  ALLOCNEXT(hlist,PDB);
908  if(hlist == NULL)
909  {
910  FREELIST(hlist_start, PDB);
911  return(NULL);
912  }
913  CLEAR_PDB(hlist);
914 
915 #ifdef DEBUG
916  printf("makeh() Type 2a allocated hlist = %d\n",(int)hlist);
917 #endif
918 
919  hlist->resnum=sNo;
920  hlist->insert[0]=sIns; /* 26.01.96 */
921  blPadterm(hlist->insert,4);
922  strcpy(hlist->atnam,sGHName[5]);
923  SetRawAtnam(hlist->atnam_raw, sGHName[5]); /* 05.12.02 */
924  hlist->altpos = ' '; /* 03.06.05 */
925  hlist->x=x5;
926  hlist->y=y5;
927  hlist->z=z5;
928  strcpy(hlist->element,"H"); /* 13.02.15 */
929  ALLOCNEXT(hlist,PDB);
930  if(hlist == NULL)
931  {
932  FREELIST(hlist_start, PDB);
933  return(NULL);
934  }
935  CLEAR_PDB(hlist);
936 
937 #ifdef DEBUG
938  printf("makeh() Type 2b allocated hlist = %d\n",(int)hlist);
939 #endif
940 
941  sNType2+=2;
942  break;
943 
944 /* Initialisation for both these cases is the same */
945  case 3:
946  case 5:
947  if(!Dummy)
948  {
949  /* Don't bother with all this lot if we have a dummy atom */
950  x32=x3-x2;
951  y32=y3-y2;
952  z32=z3-z2;
953  xh=x32/r23;
954  yh=y32/r23;
955  zh=z32/r23;
956  scalpr=(x21*x32+y21*y32+z21*z32)/r23;
957  xp=scalpr*xh;
958  yp=scalpr*yh;
959  zp=scalpr*zh;
960  x21p=x21-xp;
961  y21p=y21-yp;
962  z21p=z21-zp;
963  r21p=(REAL)sqrt((double)(x21p*x21p+y21p*y21p+z21p*z21p));
964  xv=x21p/r21p;
965  yv=y21p/r21p;
966  zv=z21p/r21p;
967  xs=yh*zv-zh*yv;
968  ys=zh*xv-xh*zv;
969  zs=xh*yv-yh*xv;
970  cosax=cosa*xh;
971  cosay=cosa*yh;
972  cosaz=cosa*zh;
973  }
974 
975  if(HType==3)
976  {
977  /* HTYPE 3: Generation of 3 tetrahedral H's
978  ----------------------------------------
979  */
980  if(Dummy)
981  {
982  x4 = y4 = z4 = (REAL)9999.0;
983  x5 = y5 = z5 = (REAL)9999.0;
984  x6 = y6 = z6 = (REAL)9999.0;
985  }
986  else
987  {
988  x4=x3+BondLen*(cosax+sina*xv);
989  y4=y3+BondLen*(cosay+sina*yv);
990  z4=z3+BondLen*(cosaz+sina*zv);
991 
992  /* V2.2: Bug fix here: xy, ys, zs; not xs all the time! */
993  x5=x3+BondLen*(cosax+sina*(sFac*xs-0.5*xv));
994  y5=y3+BondLen*(cosay+sina*(sFac*ys-0.5*yv));
995  z5=z3+BondLen*(cosaz+sina*(sFac*zs-0.5*zv));
996  x6=x3+BondLen*(cosax+sina*(-sFac*xs-0.5*xv));
997  y6=y3+BondLen*(cosay+sina*(-sFac*ys-0.5*yv));
998  z6=z3+BondLen*(cosaz+sina*(-sFac*zs-0.5*zv));
999  }
1000 
1001  hlist->resnum=sNo;
1002  hlist->insert[0]=sIns; /* 26.01.96 */
1003  blPadterm(hlist->insert,4);
1004  strcpy(hlist->atnam,sGHName[4]);
1005  SetRawAtnam(hlist->atnam_raw, sGHName[4]); /* 05.12.02 */
1006  hlist->altpos = ' '; /* 03.06.05 */
1007  hlist->x=x4;
1008  hlist->y=y4;
1009  hlist->z=z4;
1010  strcpy(hlist->element,"H"); /* 13.02.15 */
1011  ALLOCNEXT(hlist,PDB);
1012  if(hlist == NULL)
1013  {
1014  FREELIST(hlist_start, PDB);
1015  return(NULL);
1016  }
1017  CLEAR_PDB(hlist);
1018 
1019 #ifdef DEBUG
1020  printf("makeh() Type 3a allocated hlist = %d\n",(int)hlist);
1021 #endif
1022 
1023  hlist->resnum=sNo;
1024  hlist->insert[0]=sIns; /* 26.01.96 */
1025  blPadterm(hlist->insert,4);
1026  strcpy(hlist->atnam,sGHName[5]);
1027  SetRawAtnam(hlist->atnam_raw, sGHName[5]); /* 05.12.02 */
1028  hlist->altpos = ' '; /* 03.06.05 */
1029  hlist->x=x5;
1030  hlist->y=y5;
1031  hlist->z=z5;
1032  strcpy(hlist->element,"H"); /* 13.02.15 */
1033  ALLOCNEXT(hlist,PDB);
1034  if(hlist == NULL)
1035  {
1036  FREELIST(hlist_start, PDB);
1037  return(NULL);
1038  }
1039  CLEAR_PDB(hlist);
1040 
1041 #ifdef DEBUG
1042  printf("makeh() Type 3b allocated hlist = %d\n",(int)hlist);
1043 #endif
1044 
1045  hlist->resnum=sNo;
1046  hlist->insert[0]=sIns; /* 26.01.96 */
1047  blPadterm(hlist->insert,4);
1048  strcpy(hlist->atnam,sGHName[6]);
1049  SetRawAtnam(hlist->atnam_raw, sGHName[6]); /* 05.12.02 */
1050  hlist->altpos = ' '; /* 03.06.05 */
1051  hlist->x=x6;
1052  hlist->y=y6;
1053  hlist->z=z6;
1054  strcpy(hlist->element,"H"); /* 13.02.15 */
1055  ALLOCNEXT(hlist,PDB);
1056  if(hlist == NULL)
1057  {
1058  FREELIST(hlist_start, PDB);
1059  return(NULL);
1060  }
1061  CLEAR_PDB(hlist);
1062 
1063 #ifdef DEBUG
1064  printf("makeh() Type 3c allocated hlist = %d\n",(int)hlist);
1065 #endif
1066 
1067  sNType3+=3;
1068  }
1069  else if(HType==5)
1070  {
1071  /* HTYPE 5: Generation of 1 H where an angle is specified
1072  ------------------------------------------------------
1073  */
1074  if(Dummy)
1075  {
1076  x4 = y4 = z4 = (REAL)9999.0;
1077  }
1078  else
1079  {
1080  cosb=(REAL)cos((double)beta);
1081  sinb=(REAL)sin((double)beta);
1082  x4=x3+BondLen*(cosax+sina*(cosb*xv+sinb*xs));
1083  y4=y3+BondLen*(cosay+sina*(cosb*yv+sinb*ys));
1084  z4=z3+BondLen*(cosaz+sina*(cosb*zv+sinb*zs));
1085  }
1086 
1087  hlist->resnum=sNo;
1088  hlist->insert[0]=sIns; /* 26.01.96 */
1089  blPadterm(hlist->insert,4);
1090  strcpy(hlist->atnam,sGHName[4]);
1091  SetRawAtnam(hlist->atnam_raw, sGHName[4]); /* 05.12.02 */
1092  hlist->altpos = ' '; /* 03.06.05 */
1093  hlist->x=x4;
1094  hlist->y=y4;
1095  hlist->z=z4;
1096  strcpy(hlist->element,"H"); /* 13.02.15 */
1097  ALLOCNEXT(hlist,PDB);
1098  if(hlist == NULL)
1099  {
1100  FREELIST(hlist_start, PDB);
1101  return(NULL);
1102  }
1103  CLEAR_PDB(hlist);
1104 
1105 #ifdef DEBUG
1106  printf("makeh() Type 5 allocated hlist = %d\n",(int)hlist);
1107 #endif
1108 
1109  sNType5++;
1110  }
1111  break;
1112 
1113  case 4:
1114  /* HTYPE 4: Generation of 1 sp2 H
1115  ------------------------------
1116  */
1117  if(Dummy)
1118  {
1119  x4 = y4 = z4 = (REAL)9999.0;
1120  }
1121  else
1122  {
1123  x32=x3-x2;
1124  y32=y3-y2;
1125  z32=z3-z2;
1126  scalpr=(x21*x32+y21*y32+z21*z32)/r21;
1127  xh=x21/r21;
1128  yh=y21/r21;
1129  zh=z21/r21;
1130  xp=scalpr*xh;
1131  yp=scalpr*yh;
1132  zp=scalpr*zh;
1133  xp23=xp+x23;
1134  yp23=yp+y23;
1135  zp23=zp+z23;
1136  rp23=(REAL)sqrt((double)(xp23*xp23+yp23*yp23+zp23*zp23));
1137  xv=xp23/rp23;
1138  yv=yp23/rp23;
1139  zv=zp23/rp23;
1140  x4=x2+BondLen*(sina*xv-cosa*xh);
1141  y4=y2+BondLen*(sina*yv-cosa*yh);
1142  z4=z2+BondLen*(sina*zv-cosa*zh);
1143  }
1144 
1145  hlist->resnum=sNo;
1146  hlist->insert[0]=sIns; /* 26.01.96 */
1147  blPadterm(hlist->insert,4);
1148  strcpy(hlist->atnam,sGHName[4]);
1149  SetRawAtnam(hlist->atnam_raw, sGHName[4]); /* 05.12.02 */
1150  hlist->altpos = ' '; /* 03.06.05 */
1151  hlist->x=x4;
1152  hlist->y=y4;
1153  hlist->z=z4;
1154  strcpy(hlist->element,"H"); /* 13.02.15 */
1155  ALLOCNEXT(hlist,PDB);
1156  if(hlist == NULL)
1157  {
1158  FREELIST(hlist_start, PDB);
1159  return(NULL);
1160  }
1161  CLEAR_PDB(hlist);
1162 
1163 #ifdef DEBUG
1164  printf("makeh() Type 4 allocated hlist = %d\n",(int)hlist);
1165 #endif
1166 
1167  sNType4++;
1168  } /* End of switch */
1169  } /* End of HTYPE 1 else clause */
1170 
1171  return(hlist_start);
1172 }
1173 
1174 /************************************************************************/
1175 /*>static BOOL AddH(PDB *hlist, PDB **position, int HType)
1176  -------------------------------------------------------
1177 *//**
1178 
1179  \param[in] *hlist Linked list of hydrogens to be merged
1180  \param[in] **position Array of PDB pointers for atoms in this
1181  residue
1182  \param[in] HType Hydrogen type
1183  \return Success?
1184 
1185  AddH() merges a list of hydrogens for this atom into the main pdb
1186  structure list. Returns FALSE if the procedure failed.
1187 
1188 - 16.05.90 Original By: ACRM
1189 - 05.12.02 Added setting of atnam_raw
1190 - 27.03.03 Fixed memory leak - free the hlist when finished
1191 - 03.06.05 Added setting of altpos
1192 - 13.02.15 Added copying of element type
1193 - 17.02.15 Added copying of segid and setting of formal_charge
1194 - 18.03.15 Changed to use MAXATINRES By: ACRM
1195 - 23.06.15 Various calls to CLEAR_PDB()
1196 */
1197 static BOOL AddH(PDB *hlist, PDB **position, int HType)
1198 {
1199  PDB *p,*q,*r,*s;
1200  int atomcount=0,
1201  k;
1202 
1203  /* Step through each atom in position list until we find the
1204  one corresponding to this PGP
1205  */
1206  for(k=1;k<MAXATINRES;k++)
1207  {
1208  q=hlist;
1209 
1210  if(!position[k]) continue;
1211  p = position[k];
1212 
1213  /* For PGP types 3 & 5, look for atom in column 3 */
1214  if((((HType==3)||(HType==5))
1215  &&(!(strncmp(p->atnam,sGHName[3],4))))||
1216  /* For PGP types 1,2,4 look in column 2 */
1217  (((HType==1)||(HType==2)||(HType==4))
1218  &&(!strncmp(p->atnam,sGHName[2],4))))
1219  {
1220 
1221  /* Copy the atoms from hlist into the PDB list */
1222  s=p;
1223  r=p->next; /* Store the pointer to the next record */
1224  ALLOCNEXT(p,PDB); /* Insert a record in the main list */
1225  if(p == NULL)
1226  {
1227  FREELIST(hlist, PDB); /* 27.03.03 Fixed memory leak */
1228  return(FALSE);
1229  }
1230  CLEAR_PDB(p); /* 23.06.15 */
1231 
1232  p->next=r; /* Update its pointer */
1233  strcpy(p->record_type,s->record_type); /* Copy the info into
1234  this record */
1235  p->atnum = ++atomcount;
1236  strcpy(p->atnam,q->atnam);
1237  strcpy(p->atnam_raw, q->atnam_raw); /* 05.12.02 */
1238  p->altpos = q->altpos; /* 03.06.05 */
1239  strcpy(p->resnam,s->resnam);
1240  strcpy(p->chain,s->chain);
1241  p->resnum=s->resnum;
1242  strcpy(p->insert,s->insert);
1243  p->x=q->x;
1244  p->y=q->y;
1245  p->z=q->z;
1246  p->occ=1.0;
1247  p->bval=20.0;
1248  strcpy(p->element,q->element); /* 13.02.15 */
1249  strcpy(p->segid, s->segid); /* 17.02.15 */
1250  p->formal_charge=0;
1251 
1252  if((HType==2)||(HType==3))
1253  {
1254  /* For these types there are 2 or three H's to add, so
1255  add another one
1256  */
1257  NEXT(q);
1258  s=p;
1259  r=p->next;
1260  ALLOCNEXT(p,PDB);
1261  if(p==NULL)
1262  {
1263  FREELIST(hlist, PDB); /* 27.03.03 Fixed memory leak */
1264  return(FALSE);
1265  }
1266  CLEAR_PDB(p); /* 23.06.15 */
1267 
1268  p->next=r;
1269  strcpy(p->record_type, s->record_type);
1270  p->atnum = ++atomcount;
1271  strcpy(p->atnam,q->atnam);
1272  strcpy(p->atnam_raw, q->atnam_raw); /* 05.12.02 */
1273  p->altpos = q->altpos; /* 03.06.05 */
1274  strcpy(p->resnam,s->resnam);
1275  strcpy(p->chain,s->chain);
1276  p->resnum=s->resnum;
1277  strcpy(p->insert,s->insert);
1278  p->x=q->x;
1279  p->y=q->y;
1280  p->z=q->z;
1281  p->occ=1.0;
1282  p->bval=20.0;
1283  strcpy(p->element,q->element); /* 13.02.15 */
1284  strcpy(p->segid, s->segid); /* 17.02.15 */
1285  p->formal_charge=0;
1286  }
1287  if(HType==3)
1288  {
1289  /* For this type there are 3 H's to add, so
1290  add another one
1291  */
1292  NEXT(q);
1293  s=p;
1294  r=p->next;
1295  ALLOCNEXT(p,PDB);
1296  if(p==NULL)
1297  {
1298  FREELIST(hlist, PDB); /* 27.03.03 Fixed memory leak */
1299  return(FALSE);
1300  }
1301  CLEAR_PDB(p); /* 23.06.15 */
1302 
1303  p->next=r;
1304  strcpy(p->record_type, s->record_type);
1305  p->atnum = ++atomcount;
1306  strcpy(p->atnam,q->atnam);
1307  strcpy(p->atnam_raw, q->atnam_raw); /* 05.12.02 */
1308  p->altpos = q->altpos; /* 03.06.05 */
1309  strcpy(p->resnam,s->resnam);
1310  strcpy(p->chain,s->chain);
1311  p->resnum=s->resnum;
1312  strcpy(p->insert,s->insert);
1313  p->x=q->x;
1314  p->y=q->y;
1315  p->z=q->z;
1316  p->occ=1.0;
1317  p->bval=20.0;
1318  strcpy(p->element,q->element); /* 13.02.15 */
1319  strcpy(p->segid, s->segid); /* 17.02.15 */
1320  p->formal_charge=0;
1321  }
1322  } /* End of matches */
1323  } /* End of main list */
1324 
1325  FREELIST(hlist, PDB); /* 27.03.03 Fixed memory leak */
1326  return(TRUE);
1327 }
1328 
1329 /************************************************************************/
1330 /*>FILE *blOpenPGPFile(char *pgpfile, BOOL AllHyd)
1331  -----------------------------------------------
1332 *//**
1333 
1334  \param[in] *pgpfile Name of a PGP file or NULL
1335  \param[in] AllHyd If name of PGP not specified, this
1336  flag specified whether all or explicit
1337  hydrogen file required
1338  \return File pointer
1339 
1340  Open the PGP file
1341 
1342 - 23.08.94 Original By: ACRM
1343 - 28.07.05 Added conditionals for msdos and Mac OS/X
1344 - 07.07.14 Use bl prefix for functions By: CTP
1345 - 18.03.15 Changed to use MAXBUFF By: ACRM
1346 */
1347 FILE *blOpenPGPFile(char *pgpfile, BOOL AllHyd)
1348 {
1349  char *datadir,
1350  buffer[MAXBUFF],
1351  basename[MAXBUFF];
1352  FILE *fp;
1353 
1354  /* If a filename has been specified, just open it and return */
1355  if(pgpfile != NULL && pgpfile[0])
1356  {
1357  fp = fopen(pgpfile,"r");
1358 
1359  return(fp);
1360  }
1361 
1362  /* No filename specified, so build our own name.
1363  Select the appropriate base name
1364  */
1365  if(AllHyd)
1366  strcpy(basename,ALLHPGP);
1367  else
1368  strcpy(basename,EXPLPGP);
1369 
1370  /*** FIXME: This should be changed to use OpenFile() instead ***/
1371 
1372  /* Try to open file in current directory */
1373  if((fp = fopen(basename,"r")) == NULL)
1374  {
1375  /* Failed so build alternative directory/filename */
1376 #if (unix || __unix__ || msdos || __msdos__ || __unix || __MACH__ || __APPLE__)
1377  datadir = getenv(DATAENV);
1378 
1379  if(datadir != NULL)
1380  {
1381  sprintf(buffer,"%s/%s",datadir,basename);
1382  fp = fopen(buffer,"r");
1383  }
1384 #ifdef SCREEN_INFO
1385  else
1386  {
1387  sprintf(buffer,"Error: The %s environment variable has not \
1388 been set.\n",DATAENV);
1389  screen(buffer);
1390  }
1391 #endif
1392 
1393 #else
1394  sprintf(buffer,"%s%s",DATADIR,basename);
1395  fp = fopen(buffer,"r");
1396 #endif
1397  }
1398 
1399  return(fp);
1400 }
1401 
1402 
1403 /************************************************************************/
1404 /*>static void SetRawAtnam(char *out, char *in)
1405  --------------------------------------------
1406 *//**
1407 
1408  \param[in] *in Input string
1409  \param[out] *out Output string
1410 
1411  Copies the input atom name (a 4-character name) and outputs it to
1412  a 4-character name starting with a space if the input string had
1413  trailing spaces. If the input string had no trailing spaces, the
1414  last character is moved to the front of the string. This creates
1415  hydrogen atom names in 'raw' format
1416 
1417 - 05.12.02 Original By: ACRM
1418 - 17.02.15 Terminates the out string when it is 4 or more characters
1419 - 18.03.15 Changed to use MAXLABEL
1420 */
1421 static void SetRawAtnam(char *out, char *in)
1422 {
1423  char instr[MAXLABEL];
1424 
1425  strncpy(instr, in, MAXLABEL-1);
1426  TERMAT(instr, ' ');
1427 
1428  if(strlen(instr) > 3)
1429  {
1430  out[0] = instr[3];
1431  out[1] = instr[0];
1432  out[2] = instr[1];
1433  out[3] = instr[2];
1434  out[4] = '\0'; /* 17.02.15 */
1435  }
1436  else
1437  {
1438  out[0] = ' ';
1439  strncpy(out+1, instr, 4);
1440  PADMINTERM(out, 4);
1441  }
1442  out[4] = '\0';
1443 }
1444 
1445 
1446 /************************************************************************/
1447 /*>static PDB *StripDummyH(PDB *pdb, int *nhyd)
1448  --------------------------------------------
1449 *//**
1450 
1451  \param[in] *pdb Start of PDB linked list
1452  \param[in,out] *nhyd Number of hydrogens
1453  \return New PDB linked list
1454 
1455  Strips any dummy hydrogens
1456 
1457 - 28.11.05 Original By: ACRM
1458 */
1459 static PDB *StripDummyH(PDB *pdb, int *nhyd)
1460 {
1461  PDB *p;
1462 
1463  for(p=pdb; p!=NULL;)
1464  {
1465  if((p->atnam[0] == 'H') &&
1466  (p->x > 9998.0) &&
1467  (p->y > 9998.0) &&
1468  (p->z > 9998.0))
1469  {
1470  DELETE(pdb, p, PDB);
1471  (*nhyd)--;
1472  }
1473  else
1474  {
1475  NEXT(p);
1476  }
1477  }
1478  return(pdb);
1479 }
1480 
#define ALLOCNEXT(x, y)
Definition: macros.h:251
Include file for PDB routines.
int resnum
Definition: pdb.h:310
short BOOL
Definition: SysDefs.h:64
#define NULL
Definition: array2.c:99
Definition: pdb.h:298
Header for window/normal interface routines.
#define PI
Definition: macros.h:215
#define DATAENV
Definition: HAddPDB.c:174
int T4
Definition: pdb.h:452
int T3
Definition: pdb.h:452
void blPadterm(char *string, int length)
Definition: padterm.c:117
#define ALLHPGP
Definition: HAddPDB.c:177
#define CLEAR_PDB(p)
Definition: pdb.h:460
#define DATADIR
Definition: HAddPDB.c:175
int T2
Definition: pdb.h:452
#define FALSE
Definition: macros.h:223
#define NEXT(x)
Definition: macros.h:249
char altpos
Definition: pdb.h:324
int T1
Definition: pdb.h:452
int atnum
Definition: pdb.h:309
char record_type[8]
Definition: pdb.h:315
#define MAXBUFF
Definition: HAddPDB.c:173
Useful macros.
#define MAXTYPE
Definition: HAddPDB.c:171
#define MAXLABEL
Definition: HAddPDB.c:172
char atnam[8]
Definition: pdb.h:316
int fsscanf(char *buffer, char *format,...)
Definition: fsscanf.c:177
char resnam[8]
Definition: pdb.h:319
REAL ymin
Definition: plotting.c:146
double REAL
Definition: MathType.h:67
REAL z
Definition: pdb.h:300
char element[8]
Definition: pdb.h:322
#define MAXATINRES
Definition: pdb.h:240
REAL xmin
Definition: plotting.c:146
#define EXPLPGP
Definition: HAddPDB.c:176
Include file for fsscanf()
#define TRUE
Definition: macros.h:219
int blHAddPDB(FILE *fp, PDB *pdb)
Definition: HAddPDB.c:250
int formal_charge
Definition: pdb.h:311
#define DELETE(x, y, z)
Definition: macros.h:284
char atnam_raw[8]
Definition: pdb.h:317
#define TERMAT(x, y)
Definition: macros.h:382
Header file for general purpose routines.
FILE * blOpenPGPFile(char *pgpfile, BOOL AllHyd)
Definition: HAddPDB.c:1347
#define FREELIST(y, z)
Definition: macros.h:264
Definition: pdb.h:450
char segid[8]
Definition: pdb.h:323
#define INIT(x, y)
Definition: macros.h:244
System-type variable type definitions.
REAL occ
Definition: pdb.h:300
Type definitions for maths.
struct pdb_entry * next
Definition: pdb.h:307
int blReadPGP(FILE *fp)
Definition: HAddPDB.c:301
int T5
Definition: pdb.h:452
char chain[blMAXCHAINLABEL]
Definition: pdb.h:321
int Total
Definition: pdb.h:452
REAL x
Definition: pdb.h:300
REAL y
Definition: pdb.h:300
REAL bval
Definition: pdb.h:300
HADDINFO gHaddInfo
Definition: HAddPDB.c:210
void blRenumAtomsPDB(PDB *pdb, int offset)
#define PADMINTERM(string, len)
Definition: macros.h:459
char insert[8]
Definition: pdb.h:320