Foldit Wiki

structure.GetHBonds[]

Function
table structure.GetHBonds()
Description
Returns table of hydrogen bond information.
V1 Function Name
New to V2

structure.GetHBonds returns a table containing information about the hydrogen bonds in the current protein. The table also contains information about any disulfide bridges that are present.

The table returned has one entry per hydrogen bond. Each entry in turn is a table of keyword-value pairs. The keywords in this table are:

  • bond_type - 0 for hydrogen bond, 1 for disulfide bridge
  • res1 - the residue/segment for the first side of the bond
  • atom1 - the atom number for the first side of the bond
  • res2 - the residue/segment for the second side of the bond
  • atom2 - the atom number for the second side of the bond
  • width - "width" generally ranges between 0.25 Å (bad) and 0.75 Å (good)

For a symmetry puzzle, the segment number returned in "res2" may be higher than the number of segments indicated by structure.GetCount, indicating the hydrogen bond ends on one of the symmetric chains. See normalizing a segment number for a discussion of how to handle this case.

Example[]

The three examples below show demonstrate how to work with the table returned by structure.GetHBonds. The first two examples show different ways to access the data. The third example demonstrates adding bands to match the hydrogen bonds.

The use of keyword-value pairs for the inner table is alternative to storing values in numbered columns. One advantage is that the keyword identifies each item, where a column number does not.

In the first example, the Lua code demonstrates calling structure.GetHBonds and listing the contents of the table. This approach uses an inner for loop to list each keyword and its value. The inner for loop uses the "pairs" operator to extract a keyword and its value. This avoids needing to know what the keywords are in advance:

bonds = structure.GetHBonds ()
print ( #bonds .. " hydrogen bonds found" )
for ii = 1, #bonds do
   for kk, vv in pairs ( bonds [ ii ] ) do
      print ( "bond " .. ii .. ", key = " .. kk .. ", value = " .. vv )
   end
end

The output would look like this:

20 hydrogen bonds found
bond 1, key = bond_type, value = 0
bond 1, key = res1, value = 1
bond 1, key = atom1, value = 1
bond 1, key = atom2, value = 8
bond 1, key = res2, value = 4
bond 1, key = width, value = 0.33105621678864
bond 2, key = bond_type, value = 0
bond 2, key = res1, value = 1
bond 2, key = atom1, value = 8
bond 2, key = atom2, value = 1
bond 2, key = res2, value = 3
bond 2, key = width, value = 0.39082163451182
bond 3, key = bond_type, value = 0
bond 3, key = res1, value = 2
bond 3, key = atom1, value = 9
bond 3, key = atom2, value = 7
bond 3, key = res2, value = 69
bond 3, key = width, value = 0.42546418678214
...and so on...

For structure.GetHBonds, we know the keywords for each entry. The keyword name can be used to address the values as a second dimension of the table, as the second example shows:

bonds = structure.GetHBonds ()
print ( #bonds .. " hydrogen bonds found" )

for ii = 1, #bonds do
   print ( "bond " .. ii .. 
       ", segment 1 = " .. bonds [ ii ] [ "res1" ] .. 
       ", atom 1 = " .. bonds [ ii ] [ "atom1" ] .. 
       ", segment 2 = " .. bonds [ ii ] [ "res2" ] ..
       ", atom 2 = " .. bonds [ ii ] [ "atom2" ] ..
       ", length = " .. bonds [ ii ] [ "width" ] )
end

The keyword names, such as "res1", "res2", and "width", must be enclosed in single or double quotes, as shown in the example.

The output from this example looks like this:

bond 1, segment 1 = 1, atom 1 = 1, segment 2 = 4, atom 2 = 8, width = 0.33105621678864
bond 2, segment 1 = 1, atom 1 = 8, segment 2 = 3, atom 2 = 1, width = 0.39082163451182
bond 3, segment 1 = 2, atom 1 = 9, segment 2 = 69, atom 2 = 7, width = 0.42546418678214
...and so on...

As a third example, the output from structure.GetHBonds can be used to add bands with band.AddBetweenSegments.

The segment number of the band ends are adjusted using the method described in normalizing a segment number. This allow the code to be used on a symmetry puzzle.

The length of the band created is obtained with band.GetLength, and reported along with the other information.

--
--  example 3 - add a band between the indicated atoms
--              get the current length of the band, 
--              report in a compact format
--  
function round ( ii )
    return ii - ii % 0.001
end    
--
--  normalSeg - convert possible symmetric segment number
--              to segment number and chain
--
--  arguments:
--
--  seg2   - segment number to convert
--  segcnt - length of chain
--  symnum - number of symmetric chains (0 to n)
--
--  returns:
--
--  seg    - segment number, in the range 1 to segcnt
--  symchn - symmetric chain number (0 to n)
--
function normalSeg ( seg2, segcnt, symnum )
    if seg2 <= segcnt or symnum == 0 then
        return seg2, 0 
    end
    local endz = {}
    for sym = 1, symnum do
        endz [ #endz + 1 ] = segcnt * sym + sym + 1
    end
    local adjseg = 0
    local adjsym = 0
    for rng = #endz, 1, -1 do 
        if seg2 >= endz [ rng ] then
            adjseg = seg2 - endz [ rng ] + 1
            adjsym = rng
            break
        end
    end
    return adjseg, adjsym
end
 
bonds = structure.GetHBonds ()
print ( #bonds .. " hydrogen bonds found" )
segcnt = structure.GetCount ()
symcnt = structure.GetSymCount ()      
for ii = 1, #bonds do
    local res2, chn = normalSeg (  bonds [ ii ] [ "res2" ], segcnt, symcnt )
    bx = band.AddBetweenSegments ( bonds [ ii ] [ "res1" ], res2,
            bonds [ ii ] [ "atom1" ], bonds [ ii ] [ "atom2" ], chn )
    if bx ~= nil and bx ~= 0 then
        blen = band.GetLength ( bx )
        print ( "bond " .. ii .. 
            ", " .. bonds [ ii ] [ "res1" ] .. 
            " ( " .. bonds [ ii ] [ "atom1" ] .. 
            " ) - " .. res2 ..
            " ( " .. bonds [ ii ] [ "atom2" ] ..
            " ), chain = " .. chn ..
            ", width = " .. round ( bonds [ ii ] [ "width" ] ) .. 
            ", current length = " .. round ( blen ) )
        end
end

Using the same puzzle and same pose as the previous examples, the output would look like:

bond 1, 1 ( 1 ) - 4 ( 8 ), chain = 0, width = 0.331, current length = 2.697
bond 2, 1 ( 8 ) - 3 ( 1 ), chain = 0, width = 0.39, current length = 2.891
bond 3, 2 ( 9 ) - 69 ( 7 ), chain = 0, width = 0.425, current length = 2.735
...and so on...

Normalizing the segment numbers is required for banding to work in a symmetry puzzle. In the output from the second example, this bond ends on a symmetric chain:

bond 15, segment 1 = 44, atom 1 = 12, segment 2 = 82, atom 2 = 8, width = 0.42676161277761

Segment 82 is not a valid segment number, since structure.GetCount returned 70 segments in this example.

For this case, the normalized output from the third example looks like this:

bond 15, 44 ( 12 ) - 11 ( 8 ), chain = 1, width = 0.426, current length = 2.656

Here's a description of how the segment numbering works in the symmetry puzzle used in this test, where the main chain was 70 segments long.

Segments 1 through 70 are on the main chain. Segment 71 is a pseudoresidue that's not part of any chain. The first symmetric chain starts at segment 72, and runs to segment 141. Hydrogen bond 15 ends on segment 82, which is on the second chain. So it's normalized segment number is 82 - 72 + 1 = 11.

While segment numbers start at 1, chain numbers as indicated by structure.GetSymCount start with chain 0, the main chain. The same numbering is used by band.AddBetweenSegments.

This discussion of chains applies only to symmetry puzzles with multiple identical chains. Other puzzles may contain multiple protein chains, but Foldit never explicitly identifies the chains. In this type of puzzle, the segment numbers are continuous. The ends of each chain can be identified by looking at atom counts of each segment, which change at the N terminal and C terminal of each chain.