Essential subroutines

Introduction

One of the big advantages that a novel WHAT IF programmer gets is the availability of a large number of ready-to-go tools. We have adopted the strategy that tools should be intelligent. Additionally, all intelligence should sit at the deepest possible level. For example, a function that should return TRUE/FALSE depending on two atoms being covalently bound or not, should give the correct answer, no matter in what funny exceptional situation these two atoms are.

This chapter describes those principles and some of the rules that we use upon writing WHAT IF code. Many of these rules make good sense at first sight. Some of these rules are only meant to clarify code to colleagues in the project. If the same task is always performed using the same code construct things are more easily understood.

WHAT IF is centered around the so-called SOUP. This SOUP is a fictive thing, encoded in about one hunderd include files that together hold a couple hundred common blocks.

In this chapter we will discuss also the so called general tools. The tools that form the interface between the user and the soup, and the things that form the interface between your subroutine and the soup.

Very important COMMON parameters

The following parameters are crucial for almost all WHAT IF subroutines.

Soup counters

NUMSOU            Number of molecules in the soup
NUMAAT            Number of entities at the residue level
NUMAAF            Number of residues (protein, nucleic acid)
NUMH2O            Number of water groups
NUMCOF            Number of drugs/ligands
NUMCON            Total number of connectivities for drugs/ligands

MITNUM(9)         Number of MOL-items per MOL-object
MITEMS(9,2,100)   Start/end of MOL-items in MOL-objects
MITEXT(9,100)     Names of MOL-items
ISITEM(9,100)     Status of MOL-items at screen ON/OFF

The molecule poarameters in SOUADM

SOUADM(1,ISOUP)   Number of first residue in molecule ISOUP
SOUADM(2,ISOUP)   Number of last residue in molecule ISOUP
SOUADM(3,ISOUP)   Number of residues in molecule ISOUP
SOUADM(4,ISOUP)   Number of atoms in molecule ISOUP
SOUADM(5,ISOUP)   Molecule type of ISOUP
               -1 Undefined
               0: Bug in program
               1: Protein
               2: Drug/ligand with more than 1 atom
               3: Nucleic acid
               4: Drug/ligand with just 1 atom
               5: Water
SOUADM(6,ISOUP)   Pointer to first connectivity for non-topologied drug
               -1 There are no connectivities
               N  N is pointer in connectivity arrays
SOUADM(7,ISOUP)   Number of connectivities for non-topologied drug

The chain administration in CHAINN

CHAINN(1,IAA)     Location of residue in chainn
               0: Single atomic entity, but more likely a bug
               1: N-terminal residue
               2: Somewhere in the middle
               3: C-terminal residue
CHAINN(2,IAA)     Number of the molecule this residue resides in
Use WIFIR1 and WIFIR3 to find out if CHAINN(1,IAA) is 1 or 3 resp.

Direct mode graphics parameters in JUNIOR

In DIRECT mode, JUNIAA(IAA) determines what will be displayed for residue IAA:
JUNIAA(IAA)    0: Display nothing
               1: Whole residue
               2: C-alpha
               3: Backbone
               4: Side chain
               5: C-alpha + side chain

Extra space for temporary big arrays in ESPACE

The WHAT IF ESPACE concept is a very powerful way to save memory usage in a FORTRAN program. Here are some guidelines.

Reasons to use ESPACE

There are two reasons to use ESPACE in WHAT IF:
   1.  Communication of arrays between a few routines
   2.  Local storage of more than a few kilobytes of data.
In case 1, ESPACE can be used in a .INC file that is shared between the routines. For an example see the hbond2.f module, it includes HB2INC.INC and ESPACE.INC in almost every routine.

In case 2, ESPACE can be used in the routine itself.

You should not use ESPACE for small things (like INTEGER A(100) or CHARACTER*80 LOCLIN). All of the current compilers used for WHAT IF will only reserve those kind of variables during the actual execution of that subroutine, and it will not take up any space otherwise. Optimizers don't know how to handle ESPACE equivalenced data, so if you use it, your code will execute much slower.

How does it work?

Simple:
      INCLUDE 'ESPACE.INC'
      INTEGER AR(100000)
      EQUIVALENCE (AR, ESPACE(2000001))

Where in ESPACE do I put my data?

- That depends on when you expect to run your code (is it only invoked as an option, or is it called from all-over WHAT IF), and what code you want to call during your storage. EG: since the HB2 code uses every place in ESPACE from about 600000-end, if you want your routine to be callable from within HB2, it needs to use ESPACE below 600000.

- There is a convention that small arrays that do not need to be kept are stored in low areas (1-20000), and big communication arrays high (500000-end).

- It is better to start on a round memory location (N=k*5000+1).

How do I know when things go wrong?

If you use "somebody else's" ESPACE space, or somebody else uses yours, there is no way your own code can find out about this happening. But there is a solution:

Tne routine ESP001

      SUBROUTINE ESP001 (ISTART,IEND,PURPOS)
The routine ESP001 should be used just before you start using the ESPACE, to tell the ESPACE management that you want to use that. ISTART and IEND represent the first and last ESPACE location you will need. Each call of ESP001 in the program should use a different "PURPOSE" integer: these are declared at the top of the espace.f module. Example:
      PARAMETER    (MAXA=40000)
      INTEGER      A(MAXA)
      EQUIVALENCE  (A,ESPACE(100001))
      CALL ESP001 (100001,100000+MAXA,345)
Keep in mind that ESPACE counts in 4-byte units: a CHARACTER*80 takes up 20 slots.

Tne routine ESP123

      SUBROUTINE ESP123 (ISTART,IEND,PURPOS,NAME)
After you finish using ESPACE, you can call ESP123 to check whether nobody has tried to use your data. This check will trigger a core dump if it fails for a WHAT IF developer. You need to make sure that the first three parameters are identical to the corresponding call of ESP001, and that NAME is a string with the name of the subroutine (eg 'WIF002')

Tne routine ESP002

      LOGICAL FUNCTION ESP002(ISTART,IEND,PURPOS)
ESP123 is for when you do not know how to handle it when your data is found to be overwritten. An alternative if you do know how to rescue yourself is to ask the ESP routines whether the data is still there. The function ESP002 (called with identical options as ESP001) will return .FALSE. if your data is still intact, and .TRUE. if it was overwritten by somebody else since the ESP001.

This mechanism is used in DGLOOP to load the database only when it is strictly necessary.

ESP0* Warning

ESP001 and ESP123/ESP002 only work well if EVERY usage of ESPACE calls ESP001. So: if you're not interested in your own code not working properly, you can leave out the ESP123 call at the end, but the ESP001 call is obligatory to make sure that other routines can detect that you overwrote their data!

List of tools routines

WHAT IF uses a large number of tools subroutines. These routines are partly written by us, partly adapted from public domain subroutine libraries. There is no copyright notice in these routines, and they can thus freely be copied to other programs. We expect however, that those people who copy these routines properly acknowledge us.

Unless stated otherwise, all vectors have length 3.

All matrices are square

NUM indicates the dimension of vectors or matrices

Normally the first parameters are results, the last parameters are input to the subroutine or function.

Subroutines start with GVS, functions with GVF

Unless stated otherwise, these routines are bug-free


================================================================================
OPERATIONS INVOLVING ONLY VECTORS
================================================================================
GVFANG (VECT1,VECT2)              Angle in radians between VECT1 and VECT2.
GVFNGN (VECT1,VECT2,NUM)          As GVFANG for longer vectors.
GVFDP3 (VECT1,VECT2)              GVFDP3 = VECT1 . VECT2 (dot product).
GVFDPN (VECT1,VECT2,NUM)          GVFDPN = VECT1 . VECT2 (idem).
GVFDV3 (VECT1,VECT2)              GVFDV3 = d(VECT1,VECT2) (distance).
GVFLNV (VECT)                     Returns length of VECT.
GVFLNN (VECT,NUM)                 Returns length of VECT.
GVSAV3 (VECT1,VECT2)              VECT1 = VECT1 + VECT2.
GVSAVN (VECT1,VECT2,NUM)          VECT1 = VECT1 + VECT2.
GVSCP3 (VECT1,VECT2,VECT3)        VECT1 = VECT2 x VECT3 (cross product).
GVSNRV (VNORM,VECT1,VECT2,VECT3)  VNORM othogonal to plane(VECT1,VECT2,VECT3)
GVSAOR (VECT1,VECT2,NUM)          Make VECT1 orthogonal VECT2. 
GVSSCV (VECT,LENGTH)              Set length of VECT to LENGTH.
GVSNM3 (VECT)                     Normalizes VECT.
GVSNMN (VECT,NUM)                 Normalizes VECT.
GVSBV3 (VECT1,VECT2,VECT3)        VECT1 = VECT2 + VECT3.
GVSSV3 (VECT1,VECT2)              VECT1 = VECT1 - VECT2.
GVSTV3 (VECT1,VECT2,VECT3)        VECT1 = VECT2 - VECT3.
GVFTOR (VECT1,VECT2,VECT3,VECT4)  Returns torsion angle.

================================================================================
OPERATIONS INVOLVING ONLY MATRICES
================================================================================
GVFDET (RMAT)                     Returns the determinant of RMAT(3,3).
GVSREN (RMAT)                     Renormalizes RMAT.
GVFGTA (RMAT)                     Returns the angle that RMAT rotates.
GVSEIG (...)                      Calculates eigen-values for GVSREN.
GVSTPS (RMAT,NUM)                 RMAT gets transposed.
GVSTP2 (RMAT1,RMAT2,NUM)          RMAT1 = RMAT2 transposed.
GVS3X3 (RMAT1,RMAT2,RMAT3)        RMAT1 = RMAT2*RMAT3. 3*3 Matrices.
GVS4X4 (RMAT1,RMAT2,RMAT3)        RMAT1 = RMAT2*RMAT3. 4*4 Matrices.
GVSNX3 (RMAT1,RMAT2)              RMAT1 = RMAT1*RMAT2.
GVSNXN (RMAT1,RMAT2,RMAT3,NUM)    RMAT1=RMAT2*RMAT3.
GVSMIV (RMAT,NUM)                 RMAT becomes RMAT-inv.
GVSMI2 (RMAT1,RMAT2,NUM)          RMAT1 becomes RMAT2-inv.
GVSMTM (RMAT1,RMAT2,NUM)          RMAT1 becomes RMAT2.
GVSMTA (RMAT,ANGLES)              If RMAT is proper rotation, return ANGLES.
GVSMXM (RMAT,ANGLE)               RMAT rotates ANGLE radians around X-axis.
GVSMYM (RMAT,ANGLE)               RMAT rotates ANGLE radians around Y-axis.
GVSMZM (RMAT,ANGLE)               RMAT rotates ANGLE radians around Z-axis.
GVSMGM (RMAT,VECT,ANGLE)          RMAT rotates ANGLE radians around VECT.
GVSMTU (RMAT,NUM)                 RMAT is set to unity.
GVFIMU (RMAT)                     Returns TRUE is RMAT is unitary matrix.
GVSSVC (...)                      Singular value decomposition
GVSSVCX (...)                     Singular value decomposition
GVSKSB (...)                      Singular value decomposition

================================================================================
OPERATIONS INVOLVING VECTORS AND MATRICES
================================================================================
GVSMV3 (VECT1,RMAT,VECT2)         VECT1=RMAT*VECT2.
GVSMVV (VECT,RMAT)                VECT=RMAT*VECT.
GVSMPV (VECT1,RMAT,VECT2)         VECT1=RMAT*VECT1+VECT2.
GVSMVP (VECT1,RMAT,VECT2)         VECT1=RMAT(INV)*(VECT1-VECT2).
GVSMVN (VECT1,RMAT,VECT2,NUM)     VECT1=RMAT*VECT2.

================================================================================
OTHER VECTOR OPERATIONS (these things are not well tested)
================================================================================
GVFDPL (TVEC,RVEC,XYZ)            d(XYZ,TVEC+p*RVEC) distance(point,line).
GVFPPL (TVEC,RVEC,XYZ,PXYZ) Returns distance of projection of XYZ on
        line TVEC+p*RVEC to TVEC. PXYZ becomes projection of XYZ on line.
GVSPTL (VECT1,VECT2,A,B,C) Given two vectors in a plane, return A,B, and
        C in l : A*X + B*Y = C.
GVSPLN (XYZ,NUM,A,B,C,D,RMS) Determine plane through NUM points.
GVSL3D (XYZ,NUM,DIRVEC,POSVEC) Get best line through points in 3D.

================================================================================
TEXT STRING MANIPULATION
================================================================================
GVFFCP (CROW,CHAR,NUM,LEN)        Returns element number of CHAR in CROW.
GVFISN (CHAR)                     True if CHAR(*1) is a digit.
GVFICN (CHAR)                     True if CHAR(*1) is character in alphabet or digit.
GVFISC (CHAR)                     True if CHAR(*1) is character in alphabet.
GVFSTC (NUM)                      Returns NUM-th character in alphabet (or '0').
GVFWNB (CHAR)                     Returns value of digit CHAR(*1), or -1.
GVFLEN (TEXT)                     Returns length of non blank part of TEXT.
GVFPOS (TEXT,SUBTXT)              Returns first location of SUBTXT in TEXT.
GVFPCS (TEXT,SUBTXT)              As GVFPOS, including trailing blanks in SUBTXT
GVFPLS (TEXT,SUBTXT)              Returns last location of SUBTXT in TEXT.
GVSCUC (TEXT)                     Converts TEXT to upper case.
GVSCLC (TEXT)                     Converts TEXT to lower case.
GVSWLC (TEXT)                     Warn if TEXT contains lower case.
GVSSHN (TEXT,NUM)                 Left shift by NUM characters.
GVSSHL (TEXT)                     Left shift to remove leading blanks.
GVSSHR (TEXT,LEN)                 Right shift to remove trailing blanks.
GVSSTX (TEXT1,TEXT2)              TEXT1=TEXT2.
GVSTCP (TEXT)                     Remove blanks by shifting characters to left.
GVSRDB (TEXT)                     Replaces multiple blanks by single blanks.
GVSSLN (TEXT1,TEXT2)              TEXT1 = Left shifted TEXT2.
GVSCPT (TEXT1,TEXT2,LEN,NUM)      TEXT1()(1:LEN)=TEXT2()(1:LEN)
GVSCPT (TEXT1,TEXT2,LEN,NUM)      TEXT1()(1:LEN)=TEXT2()(1:LEN)
GVSCPC (TEXT1,TEXT2)              TEXT1=TEXT1&TEXT2
GVSCCC (TEXT1,TEXT2,TEXT3)        TEXT1=TEXT2&TEXT3
GVSCC3 (TEXT1,TEXT2,TEXT3,TEXT4)  TEXT1=TEXT2&TEXT3&TEXT4
GVSCC4 (...)                      As GVSCC3, but for 4 TEXT strings
GVSCC5 (...)                      As GVSCC3, but for 5 TEXT strings
GVSCC6 (...)                      As GVSCC3, but for 6 TEXT strings
GVST6C (TEXT1,TEXT2,BOOL)         Puts two text's concatenated at terminal.
GVSBOX (TEXT)                     Puts TEXT in fancy box at screen.
GVSBX2 (TEXT1,TEXT2)              Puts TEXT1 and TEXT2 in box at screen.
GVFSCP (TEXT1,TEXT2,IERR)         String compare 1>2 -> -1; 1=2 -> 0; 1<2 -> 1
GVFWCH (CHAR)                     Returns position of CHAR in the alfabet
GVSCBC (TEXT1,TEXT2)              Glues TEXT2 at the tail of TEXT1 (better use GVSCPC)
GVSCST (TEXT)                     Initializes tail of TEXT with blanks
GVSDTC (CHR,NUM)                  Sets CHR at character equivalent '0' - '9' of NUM 0 - 9
GVSNTC (CHR,NUM)                  Sets CHR at NUM-th character of alphabet
GVSFMT (TEXT)                     Sets the COMMON string FMT at the indicated format

================================================================================
FILE HANDLING
================================================================================
GVFFOP (NUMUNT)  Returns TRUE if unit NUMUNT is open.
GVSOPF (TEXT,NUMUNT,TYPE)  Opens TEXT formatted sequential 
       at NUMUNT.
       TYPE = 'OLD' open old file.
       TYPE = 'NEW' open new file.
       TYPE = 'UNKNOWN' open old, if not exist, 
       open new file.
       TYPE = 'WARN' open new file, but warn if 
       it exists.
       TYPE = 'NOWARN' open new file, and do not 
       warn if it exists.
       If * is last character of TYPE, close unit 
       first.
GVSOUF (TEXT,NUMUNT,TYPE)  As GVSOPF for UNformatted files.
GVSOPS (TEXT,NUMUNT)  Opens unformatted sequential SCRATCH file.
GVSCLF (NUMUNT)  Closes unit NUMUNT.
GVSCPF (TEXT,NUMUNT)  Opens file TEXT for write at end at unit 
       NUMUNT. 
GVSCFF (FILE1,IUNIT1,FILE2,IUNIT2,IERR) Copies FILE2 into FILE1.
GVSCPL (TEXT,NUMUNT)  As GVSCPF but also writes contents of 
       TEXT to unit 6.
GVST56  Opens the terminal at units 5 and 6.
GVFISF (TEXT)  Becomes .TRUE. if file TEXT exists.
GVSMFN (TEXT1,TEXT2,DEFEXT)  Makes TEXT2 a proper file name using 
       TEXT1 and DEFEXT.
GVSREW (IUNIT) Rewinds unit IUNIT.
GVSLOP (WORK) Lists all open units.

================================================================================
ARRAY INITIALIZATION
================================================================================
GVSBTF (BROW,NUM)  Sets NUM LOGICALS to .FALSE.
GVSBTT (BROW,NUM)  Sets NUM LOGICALS to .TRUE.
GVSB1F (B1ROW,NUM)  Sets BOOL*1 to .FALSE.
GVSB1T (B1ROW,NUM)  Sets BOOL*1 to .TRUE.
GVSBY0 (BYTES,NUM)  Sets NUM BYTES to zero.
GVSCTB (CROW,NUM)  Sets NUM characters CROW to ' '.
GVSCTS (CROW,INDEX,NUM)  Sets NUM characters in INDEX elements in CROW to ' '.
GVSIT0 (IROW,NUM)  Sets IROW to zero.
GVS2T0 (IROW,NUM)  Sets IROW (INTEGER*2) to zero.
GVSITC (IROW,ICON,NUM)  Sets IROW to ICON.
GVSBYC (BROW,ICON,NUM)  Sets BROW (bytes) to ICON (integer).
GVSITI (IROW,NUM)  Sets IROW to 1,2,3,...,NUM.
GVS2TC (IROW,ICON,NUM) Sets IROW (integer*2) to ICON.
GVSITJ (IROW,ISTART,ISTEP,NUM)  Sets IROW to ISTART + 
       0,1,2,...,(NUM-1)*ISTEP.
GVSRT0 (ROW,NUM)  Sets ROW to zero.
GVSRTC (ROW,CON,NUM)  Sets ROW to CON.
GVSRTI (ROW,NUM)  Sets ROW to 1.0,2.0,3.0,...,float.
GVSRTJ (ROW,START,STEP,NUM)  Sets ROW to START+1,2,3,...
       ...,(NUM-1)*STEP.
GVSSEX (ROW,START,STEP,NUM)  As GVSRTJ and takes exponential.
GVSSQR (ROW,START,STEP,NUM)  As GVSRTJ and takes square root.

================================================================================
ARRAY OPERATIONS INVOLVING ONE ARRAY
================================================================================
GVFCBT (BOOLS,NUM) Counts the .TRUE.'s in BOOLS.
GVFCBF (BOOLS,NUM) Counts the .FALSE.'s in BOOLS.
GVFFBT (BOOLS,NUM) Finds first .TRUE. in BOOLS.
GVFLBT (BOOLS,NUM) Finds last .TRUE. in BOOLS.
GVSVPC (ROW,CON,NUM)  ROW = ROW + CON.
GVSVMC (ROW,CON,NUM)  ROW = ROW - CON.
GVSVXC (ROW,CON,NUM)  ROW = ROW * CON.
GVSVDC (ROW,CON,NUM)  ROW = ROW / CON.
GVSVX2 (ROW,NUM)  ROM = ROW**2.
GVSVDI (ROW,ICON,NUM)  ROW = ROW / FLOAT(ICON).
GVSVXI (ROW,ICON,NUM)  ROW = ROW * FLOAT(ICON).
GVSV1O (ROW,NUM)  ROW = 1.0/ROW. 0 remains 0.
GVSIXI (IROW,ICON,NUM)  IROW = IROW * ICON.
GVSIXR (IROW,CON,NUM)  IROW = NINT(IROW * ICON).
GVSIPC (IROW,ICON,NUM)  IROW = IROW + ICON.
GVSABS (ROW,NUM)  ROW = ABS(ROW).
GVSTQR (ROW1,ROW2,NUM)  ROW2 = SQRT(ROW1).
GVSNEG (ROW,NUM)  ROW = -ROW.
GVSMOD (IROW,ICON,NUM)  IROW = MOD(IROW,ICON).
GVSREV (ROW,NUM)  Reverses the order of elements in ROW.

================================================================================
ARRAY OPERATIONS INVOLVING TWO ARRAYS
================================================================================
GVS2I4 (IROW4,IROW2)  Converts integer*2 into integer*4.
GVS4I2 (IROW2,IROW4)  Converts integer*4 into integer*2.
GVSVDV (ROW1,ROW2,NUM)  ROW1 = ROW1 / ROW2.
GVSVXV (ROW1,ROW2,NUM)  ROW1 = ROW1 * ROW2.
GVSVPV (ROW1,ROW2,NUM)  ROW1 = ROW1 + ROW2.
GVSVMV (ROW1,ROW2,NUM)  ROW1 = ROW1 - ROW2.
GVSIDV (IROW1,IROW2,NUM)  IROW1 = NINT(FLOAT(IROW1)/FLOAT(IROW2).
GVSIXV (IROW1,IROW2,NUM)  IROW1 = IROW1 * IROW2.
GVSIPV (IROW1,IROW2,NUM)  IROW1 = IROW1 + IROW2.
GVSIMV (IROW1,IROW2,NUM)  IROW1 = IROW1 - IROW2.
GVSCPR (ROW1,ROW2,NUM)  ROW1 = ROW2.
GVSCPI (IROW1,IROW2,NUM)  IROW1 = IROW2.
GVSCPB (BROW1,BROW2,NUM)  BROW1 = BROW2.
GVSCPT (TEXT1,TEXT2,LEN,NUM)  TEXT1()(1:LEN)=TEXT2()(1:LEN)
GVSFLT (ROW,IROW,NUM)  ROW = FLOAT(IROW).
GVFQFC (ROW1,ROW2,NUM)  SUM((ROW1-ROW2)**2)/NUM
GVFLDF (ROW1,ROW2,NUM)  MAX(ABS(ROW1-ROW2))
GVSBND (BROW1,BROW2,BROW3,NUM)  BROW1 = BROW2 .AND. BROW3.
GVSBOR (BROW1,BROW2,BROW3,NUM)  BROW1 = BROW2 .OR. BROW3.
GVFIRI (IROW1,IROW2,NUM)  Returns TRUE if IROW1 = IROW2.

================================================================================
OTHER ARRAY OPERATIONS
================================================================================
GVFFIP (IROW,ICON,NUM)  Returns the location of ICON in IROW.
GVFMX2 (ROW,WORK,NTH,NUM)  Returns the NTH largest value found in ROW.
GVFMAX (ROW,NUM)  Returns the largest value found in ROW.
GVFBMX (BROW,NUM)  Returns the largest value found in byte array BROW.
GVFMIN (ROW,NUM)  Returns the smallest value found in ROW.
GVFIMX (IROW,NUM)  Returns the largest value found in IROW.
GVFIMN (IROW,NUM)  Returns the smallest value found in IROW.
GVFISM (IROW,NUM)  Returns the sum of IROW.
GVFBSM (BROW,NUM)  Returns the sum of BROW (Byte row).
GVF2SM (I2ROW,NUM)  Returns the sum of I2ROW (Integer*2 row).
GVFRSM (ROW,NUM)  Returns the sum of ROW.
GVFIN0 (IROW,NUM) Returns the number of non-zero elements in IROW.
GVSCPS (ROW,BROW,NUM,NEWNUM) Compress ROW to keep BROW=.TRUE.
GVSMTH (IROW,IWORK,NUM,IWINDO,ITYPE,ICYCLS)   Smooths IROW, using IWORK,
         window (odd, 3-25) is IWINDO, Type = ITYPE, # of cycles=ICYCLS.
GVSPCK (IROW,BRON,NUMNOW,NUM) Packs IROW according to BROW. NUM -> NUMNOW.
GVSPCR (ROW,BRON,NUMNOW,NUM) Packs ROW according to BROW. NUM -> NUMNOW.
GVSSAV (ROW,AVE,NUM) Sets whole ROW at its average value

================================================================================
I/O OPERATIONS and TEXT manipulations
================================================================================
GVFFFA (N,A)  Reads N 4 byte Alphanumericals.
GVFFFC (N,CHAR)  Reads CHARacter of length N.
GVFFFF (N,REAL)  Reads N REAL's.
GVFFFI (N,INT)  Reads N INTegers.
GVFLFI (N,INT,LINE) Reads N INTegers from the CHAR*80 LINE
GVFLFR (N,REAL,LINE) Reads N REALs from the CHAR*80 LINE
GVSFFF (N,ROW) Get exactly N reals from user.
GVSFFI (N,IROW) Get exactly N integers from user.
GVFLFI (N,IROW,LINE) Reads up to N integers from LINE.
GVFLFR (N,ROW,LINE) Reads up to N reals from LINE.

GVSMTI (RMAT,TVEC,IERR) Gets a 3*4 matrix from the user.
GVSNL6 (NL)  Writes NL empty lines.
GVSNPG (NP)  Goes NP times to top of next page.
GVSNLU (NL,NUMUNT)  Writes NL empty lines at unit NUMUNT.
GVSBCH (IUNIT,TEXT) Writes TEXT with 5*5 characters. LEN(TEXT)<=13.
GVSCTC (CROW,CHAR,NUM)   Sets NUM chars in CROW to CHAR.
GVSLIN  Writes a line of 60 equal signs.
GVSWM3 (RMAT)  Writes RMAT.
GVSW2M (RMAT1,RMAT2)  Writes 2 matrices.
GVSW3M (RMAT1,RMAT2,RMAT3)  Writes 3 matrices.
GVSW4M (RMAT1,RMAT2,RMAT3,RMAT4)  Writes 4 matrices.
GVSWM4 (RMAT,RVEC)  Writes RMAT and VECT.
GVSW44 (RMAT) Writes a 4*4 matrix.
GVSFLF (FMT,R) Determines format (FMT) to print R with.
GVSFRA (TEXT,ARR,NUM,FMT) Writes ARR(1-NUM) in TEXT.
GVSWV3 (VECT,WORK) Writes VECT.

GVSTT6 (TEXT) Writes TEXT.
GVSTO6 (TEXT) Writes TEXT, but only to the terminal.
GVSTTU (NUMUNT,TEXT) Writes TEXT at unit NUMUNT.
GVSTTB (TEXT) Writes TEXT as bug message
GVSTTE (TEXT) Writes TEXT as error message
GVSTTI (TEXT,INT) Writes TEXT plus INT (integer)
GVSTOI (TEXT,INT) Writes TEXT plus INT (integer), but only to terminal
GVSTTL (TEXT,BOOL) Writes TEXT plus BOOL (logical)
GVSTTI2 (TEXT,INT1,INT2) Writes TEXT plus INT1 and INT2 (integers)
GVSTTR (TEXT,REAL) Writes TEXT plus REAL (real)
GVSTTR2 (TEXT,REAL1,REAL2) Writes TEXT plus REAL1 + REAL2 (reals)
GVSTTR2P (TEXT,REAL1,REAL2) As GVSTTR2 but removes double blanks
GVSTOR (TEXT,REAL) Writes TEXT plus REAL (real), but only to terminal
GVSWIL (TEXT,INT,IERR) Writes INT (integer) in TEXT
GVSWTL (TEXT1,TEXT2,INT,IERR) Writes TEXT2 and INT (integer) in TEXT1
GVSR2P (TEXT,REAL1,REAL2,MODE) REAL1 is value. REAL2 is error. Writes them in 
       TEXT. MODE=1, 3.456(13) if possible. MODE=2, always 3.456 +/- 0.013
SPLIT_LINE (TEXT1,TEXT2,TEXT3)    TEXT2 is first word of TEXT1; TEXT3 the rest

================================================================================
ATOMIC output routines LOCLIN is scratch string (that should be long enough)
================================================================================
                                   For all these routines the function is
DIF002  (IAA,VAL)                  providing detailed output. It is easy to
DIF003  (IAA,ICLU,LOCLIN)          guess what the parameters do. All parameters
DIF004  (IAA,VAL1,VAL2)            are passed to the DIF routines, they do not
DIF005  (IAA,IFAM,LOCLIN)          return anything.
DIF006  (IAA,VAL1,VAL2,VAL3)
DIF007  (IAA,V1,V2,V3,V4,V5,LOCLIN)
DIF007A (IAA,V1,V2,V3,V4,V5,V6,LOCLIN)
DIF008  (TEXT,IAA)
DIF008A (IAA,TEXT)
DIF009  (IAA,JAA)
DIF010  (IAA,JAA,TEXT,VAL)
DIF010A (IAA,JAA,TEXT)
DIF011  (IAA1,IAA2,JAA1,JAA2,TEXT,VAL,LOCLIN)
DIF012  (IAT,JAT,VAL)
DIF012A (IAT,JAT,VAL1,VAL2)
DIF012B (IAT,JAT,VAL1,VAL2,VAL3)
DIF013 (IAT,VAL)
DIF014 (IAA,JAA)
DIF015 (TEXT,IAT)
DIF016 (IAT,JAT)
DIF017 (NUMB,IAT,JAT)
DIF018 (NUMB,IAT,JAT,ISYM)
DIF019 (IAT,VAL1,VAL2)
DIF020 (TEXT1,IAA,TEXT2)
DIF022 (IAT,JAT,TEXT)
DIF023 (IAT,JAT,KAT,LAT,VAL1,VAL2)
DIF024 (IAT,JAT,KAT,VAL1,VAL2)
DIF025 (IAT)
DIF026 (ISOUP,TEXT,LOCLIN)
DIF028 (IAA)

================================================================================
GONIOMETRY AND OPERATIONS ON ANGLES
================================================================================
GVFACS (ANGLE)                    Returns ACOS(angle) in radians.
GVFDTR (ANGLE)                    Converts ANGLE from degrees to radians.
GVFRTD (ANGLE)                    Converts ANGLE from radians to degrees.
GVSTCS (ROW1,ROW2,NUM)            ROW2 = COS(ROW1).
GVSSCS (ROW,START,STEP,NUM)       As GVSRTJ and takes cosine.
GVSSSN (ROW,START,STEP,NUM)       As GVSRTJ and takes sine.
GVSSTN (ROW,START,STEP,NUM)       As GVSRTJ and takes tangent.
GVF360 (ANGLE)                    Brings ANGLE (degrees) within 0,360
GVF2PI (ANGLE)                    Brings ANGLE (radians) within 0,2*PI
GVFADF (ANGLE1,ANGLE2)            Gets smallest angular difference (degrees)

================================================================================
OPERATING SYSTEM AND OTHER MACHINE DEPENDENT TOOLS
WORK should be character*80
================================================================================
GVSCLP                            Clears the screen.
GVSCOP (FILE,WORK)                Copies file to local
GVSCPP (FILE2,FILE1,BIGLIN)       Copies FILE2 to FILE1
GVSMV (FILNEW,FILOLD,WORK)        Moves FILENEW to FILEOLD.
GVSCTR                            CONTROL_C controller.
GVSDIR                            Lists contents of default directory.
GVSNDR(TEXT)                      Returns the name of the default directory.
GVSTMI(IADRES)                    Initiates CPU timer.
GVSTMS(IADRES)                    Shows elapsed time, CPU time, IO etc. since GVSTMI.
GVSTIM                            Types DATE and TIME at terminal.
GVSTUM                            Types DATE and TIME at NUMUNT.
GVSTRT (IDAY,IMONTH,IYEAR,IHOUR,IMINUT,ISECND)  obvious...
GVSDOW (IDAY)                     IDAY=1 at sunday, IDAY=2 at monday, etc.
GVSIIP (MODE)                     MODE = char*5 becomes 'INTER' or 'BATCH'
GVSVMS (TEXT)                     Spawns interactive subprocess.
GVSPWN (TEXT)                     Spawns TEXT in batch mode.
GVSSPL (TEXT)                     Spawns and executes the command stored in TEXT.
GVSPRT (TEXT,COLOUR)              Sends TEXT to laserwriter. COLOUR=.TRUE. :colour.
GVSEXE (TEXT,WORK)                Executes program TEXT.
GVSEDT (TEXT)                     Edits file TEXT. WHAT IF holds till editor is closed.
GVSZIP (TEXT,WORK)                Edits file TEXT, but continues WHAT IF
GVSDEL (TEXT,MODE)                Deletes file TEXT. The ;* should not be given.
                                  MODE=WARN or NOWARN for to get error warnings or not.
GVSPAU (SECNDS)                   Execute a pause of SECNDS seconds.

================================================================================
SORTING 
================================================================================
GVSIRT (IROW,NUM,ITAG)  Sorts IROW increasing. ITAG is tag-row.
GVSDIS (IROW,NUM,ITAG)  Sorts IROW decreasing. ITAG is tag-row.
GVSORT (ROW,NUM,ITAG)  Sorts ROW increasing. ITAG is tag-row.
GVSDRT (ROW,NUM,ITAG)  Sorts ROW decreasing. ITAG is tag-row.
GVSCRT (CROW,LEN,NUM,ITAG)  Sorts CROW increasing. ITAG is tag-row. LEN 
       is the length of the character strings in CROW.
GVSRT1 (ROW,NUM)  Sorts ROW increasing. 
GVSIR1 (IROW,NUM)  Sorts IROW increasing. 
GVSDT1 (ROW,NUM)  Sorts ROW decreasing. 
GVSDT2 (IROW,NUM)  Sorts IROW decreasing. 
GVSBRT (BYTE1,BYTE2,NUM) Sorts BYTE1, and permutes BYTE2 the same.
GVS2RT (RA,RB,N) Sorts RA (int*2) increasing (permutes RB (int*2) too)
GVSWAP (CON1,CON2)  Swaps CON1 and CON2.
GVSW2P (ICON1,ICON2)  Swaps ICON1 and ICON2 (both integer*2)
GVSWBP (BYTE1,BYTE2)  Swaps BYTE1 and BYTE2.
GVSWLP (BOOL1,BOOL2)  Swaps BOOL1 and BOOL2.
GVSWIP (ICON1,ICON2)  Swaps ICON1 and ICON2.
GVSWCP (TEXT1,TEXT2)  Swaps TEXT1 and TEXT2.

================================================================================
 STATISTICS
================================================================================
GVSIAV (IROW,NUM,AVE,ADEV,SDEV,VAR,SKEW,CURT) Returns AVErage, 
        Average DEViation, Standard DEViation, VARiance, SKEWness,
        and CURTosis. See recipes 13.1. With IROW integers.
GVS2AV (IROW,NUM,AVE,ADEV,SDEV,VAR,SKEW,CURT) With IROW integers*2.
GVSBAV (BROW,NUM,AVE,ADEV,SDEV,VAR,SKEW,CURT) With BROW bytes.
GVSRAV (ROW,NUM,AVE,ADEV,SDEV,VAR,SKEW,CURT) With ROW reals.
GVSANZ As GVSRAV excluding near zeros in ROW.
GVSRLV (ROW,BOOLS,NUM,AVE,ADEV,SDEV,VAR,SKEW,CURT) With ROW reals.
        BOOLS determines what to use in ROW.
GVSPRS (AVE,ADEV,SDEV,VAR,SKEW,CURT) Writes results from statistics routines.
GVSUUT (IUNIT,AVE,ADEV,SDEV,VAR,SKEW,CURT) Writes results from statistics 
        routines to unit IUNIT.
GVSHIS (ROW,NUMR,IROW,NUMI) makes in IROW(1-NUMI) a histogram of ROW(1-NUMR).
GVSHUT (ROW,NUMR,IROW,NUMI) as GVSHIS, but with line printer output.
GVSHUT2 (ROW,NUM,IBINS,NUMBIN,ROWMIN,ROWMAX,INMBIN) as GVSHIS, with lp output.
GVSHLT (ROW,BOOLS,NUM,IBINS,NUMBIN) as GVSHIS, but with line printer output.
GVSPMM (ROW,NUM) Print minimum and maximum of ROW
GVSPMM (ROW,BOOLS,NUM) As GVSPMM, using only ROW where BOOLS is .TRUE.

================================================================================
COORDINATE TRANSFORMATION TOOLS
================================================================================
GVSSUP (NUM,XA,XB,R,T,QRMS)  Superpositions XB(3,NUM) on 
       XA(3,NUM), R is the matrix needed, T the vector, 
       QRMS is the RMS misplacement in Angstroms. R and T are applied.
GVSSPN (NUM,XA,XB,R,T,QRMS,QMAX)  Superpositions XB(3,NUM) on XA(3,NUM), 
       R is the matrix needed, T the vector, QRMS is the RMS misplacement 
       in Angstroms, QMAX is the maximal one. R and T are NOT applied.
GVSSNP (NUM,XA,XB,R,T,QRMS,QMAX)  Superpositions XB(3,NUM) on XA(3,NUM), 
       R is the matrix needed, T the vector, QRMS is the RMS misplacement 
       in Angstroms, QMAX is the maximal one. R and T are applied.
GVSCM1 (XYZ,NUM) Puts center of mass of XYZ(3,NUM) to 0,0,0.
GVSCM2 (XYZ,NUM,VECT) Add VECT to XYZ to get center of mass in (0,0,0).
       VECT should still be added.
GVSCM3 (XYZ,NUM,VECT) Add VECT to XYZ to get center of mass in (0,0,0).
       VECT is already added.
GVSCM4 (XYZ,NUM,VECT) Subtracts VECT from XYZ (Undoes GVSCM3)
GVSCM5 (XYZ,NUM,VECT) Adds VECT to XYZ.
GVSCMT (XYZ,BROW,NUM) Puts center of mass of tagged part of XYZ(3,NUM) 
       to 0,0,0; rest is translated too.
GVSCMA (XYZ,NUM,RMAT,VECT) Applies RMAT and VECT to XYZ.
GVSCMU (XYZ,NUM,RMAT,VECT) Undoes the application of RMAT and VECT to XYZ.
GVSRSP (XYZ1,XYZ2,NUM,DMAX,DAVE,DRMS) Determines average, mean
       and root mean square difference between XYZ1 and XYZ2.
GVSSP4 (NUM,XA,XB,R,T,QRMS,W)  Superpositions XB(3,NUM) on 
       XA(3,NUM), R is the matrix needed, T the vector, 
       QRMS is the RMS misplacement in Angstroms. W are the
       weigths use in determinig QRMS (not R and T!).
GVSAM1 (X,Y,Z,NUM,RMAT,TVEC) Apply RMAT on center of gravity; apply TVEC.

================================================================================
OTHER UTILITIES
================================================================================
GVFMPI  (CONT) Returns CONT * PI (=3.14 etc.)
GVFODD  (ICON)  Becomes TRUE if ICON is an odd integer.
GVFEVN  (ICON)  Becomes TRUE if ICON is an even integer.
GVFYON  (TEXT)  Prints text. RETURNS true upon yes (no=false).
GVFRAN  (ISEED,VALLOW,VALHGH) Returns random number in range. Use ISEED=0
        in the first call.
GVFIAN  (ISEED,IVLLOW,IVLHGH) Returns random number in range. Use ISEED=0
        in the first call.
GVFEND  (TEXT)  Returns .TRUE. upon QUIT,STOP,END, etc.
GVFIIN  (ICON1,ICON2,ICON3)  .TRUE. if ICON1 in between but 
        not equal ICON2 and ICON3
GVFIBN  (ICON1,ICON2,ICON3)  .TRUE. if ICON1 in between or 
        equal ICON2 and ICON3
GVFRIN  (CON1,CON2,CON3)  .TRUE. if CON1 in between or 
        equal CON2, CON3.
GVFRNG  (CON1,CON2,CON3) Returns CON1 in case CON1 is in range CON2-CON3, else
        the nearest of CON2 and CON3 will be returned.
GVFIRG  (ICON1,ICON2,ICON3) Returns ICON1 in case ICON1 is in range ICON2-CON3, 
        else the nearest of ICON2 and ICON3 will be returned.
GVFEND  (TEXT)  .TRUE. if TEXT contains QUIT, END, STOP, etc.
GVFDFN  (INT1,INT2,IDIFF) Returns TRUE if ABS(INT1-INT2).eq.IDIFF
GVSBEL  Rings the bell in the keyboard.
GVSCOD  Holds the terminal till return is hit.
GVSKIL  Creates a stackdump by dividing by zero.
GVSLKK  (X,Y,NUM,MWT,A,B,SIGA,SIGB,CHI2,Q) See Recipes page 508. (Use mwt=0
        if SIG (is errors on Y) is empty).
GVSMNF  (....) General function minimizer.
GVSOLV  (A,B,C,X1,X2,IMAG) Solve A*X*X+B*X+C=0. IMAG=.TRUE. if no real solutions
GVS3LK  (X,Y,Z,NUM,R,P) 3-dimensional LKK. R=direction of best line. P is point
        on that line. Algorithm probably not too good...

================================================================================
AMINO ACID TOOLS
================================================================================
GVSAA3 (AAROW,LEN)  Puts 3-letter code aa in CHAR*LEN AAROW(20).
GVFWGT (AA1)  Returns weight of aa (CHAR*1) AA1 '-' is H2O.

================================================================================
OPTIONS TO GET SOMETHING FROM THE USER. Unless mentioned otherwise: 
IERR=0 all OK; IERR=1 error or zero as input; IERR=2 user hit RETURN
================================================================================
GET_WORD (TEXT,IERR)              Get TEXT. 
NEED_WORD (TEXT1,TEXT2,IERR)      Get TEXT1. TEXT2=default. (IERR=0 or 1 only).
GET_FULL_LINE (TEXT,IERR)         Gets in TEXT the entire input line
NEED_FULL_LINE (TEXT,IERR)        As GET_FULL_LINE. TEXT2=default. (IERR=0 or 1 only).
NEED_F (REAL1,REAL2,IERR)         Gets REAL1. REAL2=default. (IERR=0 or 1 only).
NEED_IF (INT1,INT2,IERR)          Gets INT1. INT2=default. (IERR=0 or 1 only).
PEEK_WORD (TEXT,IERR)             Look what TEXT would be upon GET_WORD. (IERR=0 or 1 only).
AHEAD()                           Returns TRUE if type-ahead buffer contains something
POKE_AHEAD (TEXT)                 Poke TEXT in the type ahead buffer (for dirty hacks)
WIFBO0                            Warns user for 'No default' advises to use ZERO.
WIFBO1 (MODE,TEXT)                As WIFBO0, but with menu specific help
WIFGAA (AACID,INTEXT)             Promps user for an amino acid type (char*4).
WIFGAT (IAA,IAT,IERR)             Prompts user for an atom. 
WIFGPR (ISEQ1,ISEQ2)              Asks for range of database proteins.
WIFG2N (TEXT,ISEQ1,ISEQ2,DEFAULT) Get two numbers. TEXT=prompt. Defaults=1 to DEFAULT.
WIFGRS (IFT1,TEXT)                Get one residue from user. TEXT=prompt.
WIFGRN (IFT1,IFT2,TEXT)           Get a range from user. TEXT=prompt.
WIFWTF (TEXT,IERR)                Get ranges from user. Put in WRK1TF.
GRA008 (IAA,IAT)                  Prompts user to pick an atom.
GRA008A (TEXT,IAA,IAT)            As GRA008, but with TEXT as prompt.
GRA009 (IAA1,IAT1,IAA2,IAT2)      Prompts user to pick two atoms.

================================================================================
TOOLS TO ADDRESS RESIDUES, ATOMS, etc.
================================================================================
LOGICAL FUNCTION WIFIRA(IAA)      Return TRUE if IAA is protein.
LOGICAL FUNCTION WIFIRB(IAA)      Return TRUE if IAA is protein with only Ca and Cb.
LOGICAL FUNCTION WIFIRC(IAA)      Return TRUE if IAA is protein with only Ca.
LOGICAL FUNCTION WIFIRD(IAA)      Return TRUE if IAA is drug.
LOGICAL FUNCTION WIFIRN(IAA)      Return TRUE if IAA is nucleic acid.
LOGICAL FUNCTION WIFIRR(IAA)      Return TRUE if IAA is protein or nucleic acid.
LOGICAL FUNCTION WIFIRW(IAA)      Return TRUE if IAA is water.
LOGICAL FUNCTION WIFISS(IAA)      Return TRUE if IAA is part of Cys-Cys bridge.
LOGICAL FUNCTION WIFISA(ISOUP)    Return TRUE if ISOUP is protein.
LOGICAL FUNCTION WIFISC(ISOUP)    Return TRUE if ISOUP is protein with only Ca.
LOGICAL FUNCTION WIFISD(ISOUP)    Return TRUE if ISOUP is drug.
LOGICAL FUNCTION WIFISN(ISOUP)    Return TRUE if ISOUP is nucleic acid.
LOGICAL FUNCTION WIFISR(ISOUP)    Return TRUE if ISOUP is protein or nucleic acid.
LOGICAL FUNCTION WIFISW(ISOUP)    Return TRUE if ISOUP is water.
LOGICAL FUNCTION HASPROTEIN()     Return TRUE if SOUP contains any protein.
LOGICAL FUNCTION HASDNA()         Return TRUE if SOUP contains any nucleic acid.
LOGICAL FUNCTION ISSOUPCA()
LOGICAL FUNCTION ISSOUPUNK()

================================================================================
TOOLS TO DEAL WITH FILES AND UNITS.
================================================================================
GETFILE (NUMUNT,TEXT,FILE,IERR)   Open FILE at NUMUNT. TEXT=prompt. TEXT or FILE must be ' '
GETFILD (NUMUNT,TEXT,FILE,IERR)   Open FILE at NUMUNT. TEXT=prompt. FILE=default.
GETFILN (NUMUNT,TEXT,FILE,IERR)   Open FILE at NUMUNT. TEXT=prompt. TEXT or FILE must be ' '
GETUFILE (NUMUNT,TEXT,IERR)       Open old unformatted file. TEXT=prompt.
GETUFILN (NUMUNT,TEXT,IERR)       Open new unformatted file. TEXT=prompt.

GETCBETA (IAA,IERR)
GET_TEXTP (BOOL)
KILL_TEXTP (BOOL)
WIFTPN (TEXT,ADDONE,IERR)
RESET_INTERRUPT
ISLOGF (IERR)
MOVE_ATOM (IATIN,VECT)
OVRFLO (PARAM,INPVAL,DETECT)
TOO_MANY (TEXT)
SETIFT (IFT1,IFT2,JFT1,JFT2)
CLEAN_LINE (TEXT,NUMB,IERR)
WIFMMX (IFT1,IFT2,XYZMIN,XYZMAX,XYZCEN)
WIFMMX2 (IFT1,IFT2,XYZMIN,XYZMAX)
WIFMMX3 (XYZMIN,XYZMAX,XYZCEN)
WIFMMX4 (IFT1,IFT2)
WIFPPO (IANG)
WIFSDS (INDSSP,IERR)
WIFWAIT
FULLSTOP
RESETP
SETUSYM (USYM,IWF590)
MYTEST
REALHYD (IATIN,NUMRHY,IATRHY,XYZRHY)
TYPRNG (ITYPE,ILOW,IHGH,IERR)
WIF_PUSH_PPP (IWFPPP,VALUE)
WIF_DUMP_PPP
WIF_POP_PPP (IWFPPP)
WIFIERR (IERR,TEXT)
LOGICAL FUNCTION INTERRUPTED()
LOGICAL FUNCTION GRAPON()
INTEGER FUNCTION INDAA1(AACID)
INTEGER FUNCTION INDAA1R(AACID,ILOW,IHGH)
INTEGER FUNCTION INDAA3(AACIDIN)
LOGICAL FUNCTION ISINAA(NUM,IAA)
REAL FUNCTION WIFANG(IAT1,IAT2,IAT3)
REAL FUNCTION WIFDSP(IAA,JAA)
LOGICAL FUNCTION XYZNUL(IAT)
      LOGICAL FUNCTION WIFITW(IAT)
      LOGICAL FUNCTION WIFROK(IAA)
      LOGICAL FUNCTION WIFCOK(IAA)
      LOGICAL FUNCTION WIFBOK(IAA)
      LOGICAL FUNCTION WIFALL(IAA)
      LOGICAL FUNCTION WIFSOK(IFT1,IFT2)
      LOGICAL FUNCTION WIFTDS(INDSSP,INPCHR)

Tools to deal with bonds.

Warning: Complication

There are two kinds of connectivity.
 - One is the "SHOULD BE" connectivity, implied by the TOPOLOGY. 
   i.e. "HIS ND1 is bound to HIS CE1".
 - The other one is the "FOUND" connectivity, as for drug molecules
   without topology or for BOUND_TO's. 
These two can be fundamentally different: if we have a completely crazy NMR average, the 2nd connectivity might not bind the "HIS ND1, HIS CE1" pair.

The WHAT IF routines "FBOND" and "ARE_BOUND" are biased towards the first connectivity: If possible, topology will be used to determine whether a bond exists. The rest will be added later.

An important effect is that sometimes atoms can be returned that are .NOT.ISATOK. Those are connectivities implied by TOPOLOGY. But other atoms that are expected, like C-terminal OXT groups, will just NOT be reported if they are not present. This is because it is affected by an inter-residue bond.

The routines

There are two often needed options to get bound atoms: A query "are these atoms bonded" and "which atoms are bound to this atom". They are answered by two groups of routines in WHAT IF.

Group 1: ARE_BOUND

      LOGICAL FUNCTION ARE_BOUND(JAT1,JAT2)
      LOGICAL FUNCTION ARE_BOUNDS(IAT,JAT,ISYM)
      LOGICAL FUNCTION ARE_B13(IATIN,JATIN,ISYM)
      LOGICAL FUNCTION ARE_B14(IAT,JAT,ISYM,IBETWEEN,JBETWEEN,THOROUGH)
For these routines, IAT, JAT (and so on), ISYM and THOROUGH are input. They all return a logical. ARE_B14 also returns the 2 intermediate atoms.

The routine ARE_BOUND

Simple routine that can answer the simple question.

The routine ARE_BOUNDS

Can also see S-S bridges between symmetry related molecules, but only if USESYM (WIFPAR591) is switched on.

The routine ARE_B13

Will return .TRUE. if the two atoms have at least 1 bonded atoms in common This will also look at inter-molecule bonds, S-S bridges, inter-symmetry and everything.

The routine ARE_B14

If THOROUGH=.TRUE., similar to ARE_B13, but return TRUE if there are exactly 2 atoms between. If THOROUGH=.FALSE. it will assume that you have checked before that IAT and JAT are not bonded or 1-3 bonded, and leave out that expensive check.

If ARE_B14 returns true, the integers IBETWEEN and JBETWEEN will be set to make IAT-IBETWEEN-JBETWEEN-JAT a valid torsion angle.

ARE_B14 can not do inter-symmetry S-S bonds.

Group 2: FBOND

      SUBROUTINE FBONDI (IAT,JATARR,MAXNUM,NUM)
      SUBROUTINE FBOND (IAT,JATARR,MAXNUM,NUM)
      SUBROUTINE FBONDA (IAT,JATARR,MAXNUM,NUM)
      SUBROUTINE FBONDH (IAT,JATARR,MAXNUM,NUM)
      SUBROUTINE FBONDS (IAT,JATARR,JATSYM,MAXNUM,NUM)
For these routines, IAT and MAXNUM are input. JATARR and NUM (and JATSYM) are output. MAXNUM should be the maximum number (or larger) of atoms you expect to be bound. NO MESSAGE WILL BE DISPLAYED ON THE SCREEN If more than that number of bonds are found. This is to speed up the process if only 1 bound atom is needed.

NUM is the number of atoms found. JATARR(1:NUM) is the list of JAT's for the bound atoms.

Inter-symmetry S-S bonds are only handled by FBONDS, the other routines will never use symmetry.

WARNING. These routines also return atoms for which ISATOK is .FALSE.

The routine FBONDI

Internal routine. WIFPAR(1502) is used to make it change behaviour. Do not use.

The routine FBOND

Will return in JATARR and NUM all atoms bound to IAT

The routine FBONDA

Will return in JATARR and NUM all non-proton atoms bound to IAT

The routine FBONDH

Will return in JATARR and NUM all proton atoms bound to IAT

The routine FBONDS

Specialization of FBOND to return also inter-symmetry S-S bonds. Here, JATARR and JATSYM are parallel running arrays.

Finding nearby atoms

A different class of "near atom finder" is formed by the FCON group: "FCONAAI" and "FCONATI". FCON here means "find contacting". These routines are fully optimized including symmetry contacts.

All these routines need a set of ENVIRONMENT molecules set before they are called. Use eg "ENVTOT" or "ENVALL" once before a loop over the residues to set the USESOU array and initialize the symmetry.

Avoid changing the maximum distance "RAD" between residues and/or atoms frequently, as that will result in complete expensive re-initialization. The same is true for changing the ENVironment.

Do not use the obsolete routines FCONAA, FCONAA1, FCONAT, FCONAT1, as this frequently results in common block overlap.

The routine FCONAAI

      SUBROUTINE FCONAAI (IAA,RAD,FAST,JAAARR,JAASYM,NUM,MAXNUM)
Inputs are IAA, RAD, FAST and MAXNUM. If FAST=.TRUE., some false positive contacts are reported, but the execution is much faster.

Outputs are parallel running arrays JAAARR(1:NUM) and JAASYM(1:NUM) containing all residues that have a distance less than RAD from IAA. This includes all VDW radii, so 2 C atoms at 3.0 Angstrom inter-nuclear distance will be easily found to touch with a RAD of 1.0

If MAXNUM is exceeded and it is larger than 4, an error message is printed on the screen.

FCONAAI will never return residues that are not in the current NMR model.

The routine FCONATI

      SUBROUTINE FCONATI (IAT,RAD,JATARR,JATSYM,JATDST,NUM,MAXNUM)
Inputs are IAT, RAD and MAXNUM.

Outputs are parallel running arrays JATARR(1:NUM), JATSYM(1:NUM) and JATDST(1:NUM) containing all atoms that have a distance less than RAD from IAT. This includes all VDW radii, so 2 C atoms at 3.0 Angstrom inter-nuclear distance will be easily found to touch with a RAD of 1.0 The actual inter-nuclear distance is returned in JATDST.

If MAXNUM is exceeded and it is larger than 4, an error message is printed on the screen.

FCONATI will never return residues that are not in the current NMR model.

The routine FCONAA1I

Similar to FCONAAI, but gives all residues close to a "point" in 3D space. Read the source for help.

The routine FCONAT1I

Similar to FCONATI, but gives all atoms close to a "point" in 3D space. Read the source for help.

Symmetry implementation warning

The implementation of the symmetry matrices will never take any residue with IAA>NUMAAF into account to find matrices that are necessary to find contacts. In rare cases that can result in missing contacts/bonds between drugs.

This could theoretically be changed very easily: in SYMICMP the NUMAAF should be replaced by NUMAAT.

HOWEVER: Since currently water residues can be HUGE both in size and in number of atoms this will lead to dramatically exploded CPU times for EVERYTHING that has to do with symmetry (2-3 orders of magnitude is my guess). It may be kept in mind, though, for later times when WATER "molecules" can consist of multiple "residues", or for occasions where "splitwat" has made the groups smaller.

How to ask for user input from WHAT IF

Step 1

Show the introduction to the question if there is no typeahead waiting.
      CALL SHOW_TEXT_IF (?SOME_INTRO)

Step 2

Select the prompt to be used.
      CALL IPROMPT (TEXT)
      CALL I1PROMPT (TEXT, DEFAULTINTEGER)
      CALL I1XPROMPT (TEXT, UPPERLIMITINTEGER)
      CALL R1PROMPT (TEXT, DEFAULTREAL)
      CALL WPROMPT

Step 3

If you REALLY NEED an answer, select the message to be given when the user just presses <RETURN>
      CALL WIFBO1 (0,' ')       <- "Sorry there is no default"
      CALL WIFBO1 (1,TEXT)      <- prints "TEXT".
      CALL WIFBO1 (2...X,' ')   <- Calls a subroutine to help user. 
                                   See source to find out which one.

Step 4

Call the right input routine:
    If you really need all the input you request:

      CALL GVSFFF (NUMBER,ARRAY_OF_FLOATS)
      CALL GVSFFI (NUMBER,ARRAY_OF_INTEGERS)
               (You have to verify that user typed "0" yourself)
               (These two will just ask for more if not enough input)

      CALL NEED_I (INTEGER, DEFAULTINTEGER, IERR)  <= DEFAULT=0 if no default
      CALL NEED_F (FLOAT, DEFAULTFLOAT, IERR)      <= DEFAULT=0 if no default 
      CALL NEED_WORD (WORD, DEFAULTSTRING, IERR)
      CALL NEED_FULL_LINE (LINE, DEFAULTSTRING, IERR)
               (IERR=1 means user entered "0")

    If you'd just like to have some input:

      ACTUAL_NUMBER=GVFFFF(NUMBER,ARRAY_OF_FLOATS)
      ACTUAL_NUMBER=GVSFFI(NUMBER,ARRAY_OF_INTEGERS)
               (You have to verify that user typed "0" yourself)

      CALL GET_WORD (WORD, IERR)
      CALL GET_FULL_LINE (LINE,IERR)
               (IERR=1 means user entered "0",
                IERR=2 means user entered empty).

Step 5

If the input is not what you like:
     - Print a message to that effect.
     - CALL FLUSH_AHEAD
     - GOTO step 2