Browse Source

get turns, bridges, ladders and helix oop

Thomas Forest 4 years ago
parent
commit
2505792465
5 changed files with 359 additions and 311 deletions
  1. 213 8
      src/atom.py
  2. 13 2
      src/dssp.py
  3. 66 0
      src/geom.py
  4. 66 0
      src/geom.py~
  5. 1 301
      src/structure.py

+ 213 - 8
src/atom.py View File

@@ -1,4 +1,5 @@
1 1
 import math
2
+from structure import *
2 3
 class Atom:
3 4
 
4 5
     def dist_atoms(self, atom2):
@@ -34,21 +35,225 @@ class Residue:
34 35
     def h_bond(self, res2):
35 36
         if("H" not in res2.atoms.keys()):
36 37
             return(False)
37
-        # elementary charge in Coulomb
38
-        #e = 1.602176634 * 10*math.exp(-19)
39
-        # dimensionnal factor f
38
+        # dimensionnal factor, in kcal/mole
40 39
         f = 332
41 40
         # partial charges
42 41
         q1 = 0.42
43 42
         q2 = 0.20
44
-        # r, distance between O-N atoms, in angströms
43
+        # distance between O-N atoms, in angströms
45 44
         r_ON = self.atoms["O"].dist_atoms(res2.atoms["N"])
46
-        # r, distance between C-H atoms, in angströms
45
+        # distance between C-H atoms, in angströms
47 46
         r_CH = self.atoms["C"].dist_atoms(res2.atoms["H"])
48
-        # r, distance between O-H atoms, in angströms
47
+        # distance between O-H atoms, in angströms
49 48
         r_OH = self.atoms["O"].dist_atoms(res2.atoms["H"])
50
-        # r, distance between C-N atoms, in angströms
49
+        # distance between C-N atoms, in angströms
51 50
         r_CN = self.atoms["C"].dist_atoms(res2.atoms["N"])
52
-        # Electrostatic interaction energy, in kcal/mole
51
+        # electrostatic interaction energy, in kcal/mole
53 52
         E = q1*q2*(1/r_ON + 1/r_CH - 1/r_OH - 1/r_CN)*f
54 53
         return(E)
54
+
55
+    def get_turns(self, residues, turns):
56
+        """
57
+        Get all the turns from a specific residue.
58
+        """
59
+        i = residues.index(self)
60
+        for j in range(3,6):
61
+                if(i+j<len(residues)):
62
+                    if(self.h_bond(residues[i+j])<-0.5):
63
+                        print(j,"TURN", residues[i].resid, residues[i+j].resid)
64
+                        turns[i] = Turn(j,residues[i].resid)
65
+
66
+    def get_bridges(self, residues):
67
+        bridges = {}
68
+        bridge = {}
69
+        strongest_bridge = {}
70
+        i = residues.index(self)
71
+        if(i >= 1 and i < len(residues)-4):
72
+            E_min = 0
73
+            for j in range(i+2,len(residues)-1):
74
+                # select triplet with the minimal energy 
75
+
76
+                if(residues[i-1].h_bond(residues[j])<-0.5
77
+                   and residues[j].h_bond(residues[i+1])<-0.5):
78
+                    bridge = {'res1':residues[i-1].h_bond(residues[j]),
79
+                              'res2':residues[j].h_bond(residues[i+1]),
80
+                              'ipos':residues[i].resid,
81
+                              'jpos':residues[j].resid,
82
+                              'btype':"para"}
83
+
84
+                if(residues[j-1].h_bond(residues[i])<-0.5
85
+                   and residues[i].h_bond(residues[j+1])<-0.5):
86
+                    bridge = {'res1':residues[j-1].h_bond(residues[i]),
87
+                              'res2':residues[i].h_bond(residues[j+1]),
88
+                              'ipos':residues[i].resid,
89
+                              'jpos':residues[j].resid,
90
+                              'btype':"para"}
91
+
92
+                if(residues[i].h_bond(residues[j])<-0.5
93
+                   and residues[j].h_bond(residues[i])<-0.5):
94
+                    bridge = {'res1':residues[i].h_bond(residues[j]),
95
+                              'res2':residues[j].h_bond(residues[i]),
96
+                              'ipos':residues[i].resid,
97
+                              'jpos':residues[j].resid,
98
+                              'btype':"anti"}
99
+
100
+                if(residues[i-1].h_bond(residues[j+1])<-0.5
101
+                   and residues[j-1].h_bond(residues[i+1])<-0.5):
102
+                    bridge = {'res1':residues[i-1].h_bond(residues[j+1]),
103
+                              'res2':residues[j-1].h_bond(residues[i+1]),
104
+                              'ipos':residues[i].resid,
105
+                              'jpos':residues[j].resid,
106
+                              'btype':"anti"}
107
+
108
+                if(bridge):
109
+                    if(bridge['res1']+bridge['res2']<E_min):
110
+                        E_min = bridge['res1']+bridge['res2']
111
+                        strongest_bridge = bridge
112
+                        bridge = {}
113
+                        coord_bridge = [i,j]
114
+            # finally add the strongest bridge at i and j pos
115
+            if(strongest_bridge):
116
+                bridges[coord_bridge[0]] = (Bridge(strongest_bridge['btype'],
117
+                                                            strongest_bridge['ipos'],
118
+                                                            strongest_bridge['jpos']))
119
+                bridges[coord_bridge[1]] = (Bridge(strongest_bridge['btype'],
120
+                                                            strongest_bridge['jpos'],
121
+                                                            strongest_bridge['ipos']))
122
+        if(len(bridges)>0):
123
+            return(bridges[coord_bridge[0]])
124
+        else:
125
+            return(False)
126
+
127
+    def get_helix(self, residues, turns):
128
+        """
129
+        Return if there is an helix at a given residue,
130
+        as well as its type.
131
+        """
132
+        i = residues.index(self)
133
+        # if there are no turns or it is the first residue, skip
134
+        if not turns or i == 0:
135
+            return False
136
+        if (i <= len(residues)):
137
+            if(i in turns.keys() and i-1 in turns.keys()):
138
+                print(turns[i].turn_type,"- HELIX at", residues[i].resid)
139
+                return(turns[i].turn_type, residues[i].resid)
140
+        return(False)
141
+    
142
+    def get_ladders(self, residues, ladders):
143
+        i = residues.index(self)
144
+        if i != 0:
145
+            if self.get_bridges(residues):
146
+                if (residues[i-1].get_bridges(residues)):
147
+                    local_bridge = self.get_bridges(residues)
148
+                    consec_bridge = residues[i-1].get_bridges(residues)
149
+                    if local_bridge.bridge_type == consec_bridge.bridge_type:
150
+                        print("ladder", consec_bridge.res_num, local_bridge.res_num)
151
+                        ladders[i] = {'start':i-1,
152
+                                      'end':i,
153
+                                      'bridges':[consec_bridge, local_bridge]}
154
+
155
+    def get_ladders2(self, bridges, residues):
156
+        ladders = {}
157
+        i = residues.index(self)
158
+        if i != 0:
159
+            k = 1
160
+            if i in bridges.keys():
161
+                temp_bridges = [bridges[i]]
162
+                while ((i+k in bridges.keys()) and
163
+                       (bridges[i].bridge_type == bridges[i+k].bridge_type)):
164
+                    temp_bridges.append(bridges[i+k])
165
+                    k+=1
166
+            if k>1:
167
+                print("ladder", bridges[i].res_num, bridges[i+k-1].res_num)
168
+                ladders[i] = {'start':bridges[i].res_num,
169
+                              'end':bridges[i+k-1].res_num,
170
+                              'bridges':temp_bridges}
171
+                i+=k-1
172
+            else:
173
+                i+=1
174
+        return ladders
175
+    
176
+def get_sheets(ladders):
177
+    """
178
+    Bridges between ladders.
179
+    Check if 1 bridge between one ladder and one or more other ladders.
180
+    Iterate over all residues of one ladder and check if bridge with other residues
181
+    of the other ladders.
182
+    """
183
+    sheets = {}
184
+    for ladder in ladders:
185
+        for ladd2 in ladders:
186
+            for bridge in ladders[ladder]['bridges']:
187
+                if bridge.res_partner in res_list(ladders[ladd2]):
188
+                    print("ladder",ladders[ladder]['start'], ladders[ladder]['end'],"bridge",bridge.res_num, bridge.res_partner,
189
+                    "ladder 2",ladders[ladd2]['start'], ladders[ladd2]['end'])
190
+            #print("stop ladder 2")
191
+        print("stop ladder 1")            
192
+
193
+def res_list(ladder):
194
+    # TODO : method in ladder class
195
+    l=[]
196
+    for i in range(ladder['start'], ladder['end']):
197
+        l.append(i)
198
+    return(l)
199
+                   
200
+def get_bends(residues):
201
+    bends = {}
202
+    for i in range(2,len(residues)-2):
203
+        angle = math.degrees(vector_angles(vectors_substr(position_vector(residues[i].atoms["CA"].coords),
204
+                                                          position_vector(residues[i-2].atoms["CA"].coords)),
205
+                                           vectors_substr(position_vector(residues[i+2].atoms["CA"].coords),
206
+                                                          position_vector(residues[i].atoms["CA"].coords))))
207
+        if(angle>70):
208
+            print("angle", residues[i].resid, angle)
209
+            bends[residues[i].resid] = angle
210
+    return(bends)
211
+
212
+def get_chirality(residues):
213
+
214
+    for i in range(1,len(residues)-2):
215
+        chirality = {}
216
+        angle = calc_dihedral(residues[i-1].atoms["CA"].coords,
217
+                              residues[i].atoms["CA"].coords,
218
+                              residues[i+1].atoms["CA"].coords,
219
+                              residues[i+2].atoms["CA"].coords)
220
+        
221
+        if(angle>0 and angle<=180):
222
+            sign="+"
223
+            print("chirality", residues[i].resid, "+", angle)
224
+            
225
+        if(angle<=0 and angle > -180):
226
+            sign="-"
227
+            print("chirality", residues[i].resid, "-", angle)
228
+            
229
+        chirality[residues[i].resid] = sign
230
+        
231
+    return chirality
232
+
233
+
234
+def get_phi_psi(residues):
235
+    for i in range(len(residues)):
236
+        if(i==0):
237
+            phi = 360.0
238
+        else:
239
+            phi = calc_dihedral(residues[i-1].atoms["C"].coords,
240
+                                residues[i].atoms["N"].coords,
241
+                                residues[i].atoms["CA"].coords,
242
+                                residues[i].atoms["C"].coords)
243
+        if(i==len(residues)-1):
244
+            psi = 360.0
245
+        else:
246
+            psi = calc_dihedral(residues[i].atoms["N"].coords,
247
+                                residues[i].atoms["CA"].coords,
248
+                                residues[i].atoms["C"].coords,
249
+                                residues[i+1].atoms["N"].coords)
250
+
251
+        print("ANGLES", i, phi, psi)
252
+
253
+def get_TCO(res1, res2):
254
+    CO_res1 = vector_from_pos(res1.atoms["C"].coords,
255
+                              res1.atoms["O"].coords)
256
+    CO_res2 = vector_from_pos(res2.atoms["C"].coords,
257
+                              res2.atoms["O"].coords)
258
+    angle = vector_angles(CO_res1, CO_res2)
259
+    return(math.cos(angle))

+ 13 - 2
src/dssp.py View File

@@ -2,6 +2,7 @@ import pdb
2 2
 import atom
3 3
 import sys
4 4
 from structure import *
5
+from atom import *
5 6
 
6 7
 def print_dssp():
7 8
 
@@ -21,8 +22,8 @@ else:
21 22
     #print(get_bridges(pdb_file.residues))
22 23
 
23 24
 
24
-    turns = get_turns(pdb_file.residues)
25
-    get_helix(pdb_file.residues, turns)
25
+    #turns = get_turns(pdb_file.residues)
26
+    #get_helix(pdb_file.residues, turns)
26 27
     get_bends(pdb_file.residues)
27 28
     # get_chirality(pdb_file.residues)
28 29
     # bridges = get_bridges(pdb_file.residues)
@@ -47,3 +48,13 @@ else:
47 48
     #get_phi_psi(residues)
48 49
     #print(residues[2].atoms, residues[0].resid, residues[1].resid)
49 50
     print(get_TCO(residues[2],residues[3]))
51
+
52
+    turns = {}
53
+    ladders = {}
54
+    for i,res in enumerate(residues):
55
+        # res.get_turns(residues, turns)
56
+        # res.get_helix(residues, turns)
57
+        res.get_bridges(residues)
58
+        res.get_ladders(residues, ladders)
59
+        
60
+ 

+ 66 - 0
src/geom.py View File

@@ -0,0 +1,66 @@
1
+import math 
2
+def vector_from_pos(a, b):
3
+    xAB = b[0]-a[0]
4
+    yAB = b[1]-a[1]
5
+    zAB = b[2]-a[2]
6
+    coord_AB = [xAB,yAB,zAB]
7
+    return coord_AB
8
+
9
+def vector_norm(v):
10
+    norm = math.sqrt(v[0]**2 + v[1]**2 + v[2]**2)
11
+    return norm
12
+
13
+def dot_product(v1,v2):
14
+    dot_product = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]
15
+    return(dot_product)
16
+
17
+def position_vector(c):
18
+    vector = vector_from_pos([0,0,0],c)
19
+    return vector
20
+
21
+def vectors_substr(v1, v2):
22
+    return ([v1[0]-v2[0],
23
+             v1[1]-v2[1],
24
+             v1[2]-v2[2]])
25
+
26
+def vector_angles(v1,v2):
27
+    dot_prod = dot_product(v1,v2)
28
+    norm_v1 = vector_norm(v1)
29
+    norm_v2 = vector_norm(v2)
30
+    term = dot_prod/(abs(norm_v1)*abs(norm_v2))
31
+    rad_angle = math.acos(term)
32
+    return rad_angle
33
+
34
+def calc_dihedral(u1, u2, u3, u4):
35
+    """ Calculate dihedral angle method. From bioPython.PDB
36
+    (adapted to np.array)
37
+    Calculate the dihedral angle between 4 vectors
38
+    representing 4 connected points. The angle is in
39
+    [-pi, pi].
40
+
41
+    Adapted function of dihedral_angle_from_coordinates.py 
42
+    by Eric Alcaide.
43
+    Source : https://gist.github.com/EricAlcaide
44
+    URL : https://gist.github.com/EricAlcaide/30d6bfdb8358d3a57d010c9a501fda56
45
+    """
46
+    #convert coords to numpy arrays
47
+    u1 = np.array(u1)
48
+    u2 = np.array(u2)
49
+    u3 = np.array(u3)
50
+    u4 = np.array(u4)
51
+    
52
+    a1 = u2 - u1
53
+    a2 = u3 - u2
54
+    a3 = u4 - u3
55
+
56
+    v1 = np.cross(a1, a2)
57
+    v1 = v1 / (v1 * v1).sum(-1)**0.5
58
+    v2 = np.cross(a2, a3)
59
+    v2 = v2 / (v2 * v2).sum(-1)**0.5
60
+    porm = np.sign((v1 * a3).sum(-1))
61
+    rad = np.arccos((v1*v2).sum(-1) / ((v1**2).sum(-1) * (v2**2).sum(-1))**0.5)
62
+    if not porm == 0:
63
+        rad = rad * porm
64
+
65
+    deg_angle = rad*(180/math.pi)
66
+    return deg_angle

+ 66 - 0
src/geom.py~ View File

@@ -0,0 +1,66 @@
1
+
2
+def vector_from_pos(a, b):
3
+    xAB = b[0]-a[0]
4
+    yAB = b[1]-a[1]
5
+    zAB = b[2]-a[2]
6
+    coord_AB = [xAB,yAB,zAB]
7
+    return coord_AB
8
+
9
+def vector_norm(v):
10
+    norm = math.sqrt(v[0]**2 + v[1]**2 + v[2]**2)
11
+    return norm
12
+
13
+def dot_product(v1,v2):
14
+    dot_product = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]
15
+    return(dot_product)
16
+
17
+def position_vector(c):
18
+    vector = vector_from_pos([0,0,0],c)
19
+    return vector
20
+
21
+def vectors_substr(v1, v2):
22
+    return ([v1[0]-v2[0],
23
+             v1[1]-v2[1],
24
+             v1[2]-v2[2]])
25
+
26
+def vector_angles(v1,v2):
27
+    dot_prod = dot_product(v1,v2)
28
+    norm_v1 = vector_norm(v1)
29
+    norm_v2 = vector_norm(v2)
30
+    term = dot_prod/(abs(norm_v1)*abs(norm_v2))
31
+    rad_angle = math.acos(term)
32
+    return rad_angle
33
+
34
+def calc_dihedral(u1, u2, u3, u4):
35
+    """ Calculate dihedral angle method. From bioPython.PDB
36
+    (adapted to np.array)
37
+    Calculate the dihedral angle between 4 vectors
38
+    representing 4 connected points. The angle is in
39
+    [-pi, pi].
40
+
41
+    Adapted function of dihedral_angle_from_coordinates.py 
42
+    by Eric Alcaide.
43
+    Source : https://gist.github.com/EricAlcaide
44
+    URL : https://gist.github.com/EricAlcaide/30d6bfdb8358d3a57d010c9a501fda56
45
+    """
46
+    #convert coords to numpy arrays
47
+    u1 = np.array(u1)
48
+    u2 = np.array(u2)
49
+    u3 = np.array(u3)
50
+    u4 = np.array(u4)
51
+    
52
+    a1 = u2 - u1
53
+    a2 = u3 - u2
54
+    a3 = u4 - u3
55
+
56
+    v1 = np.cross(a1, a2)
57
+    v1 = v1 / (v1 * v1).sum(-1)**0.5
58
+    v2 = np.cross(a2, a3)
59
+    v2 = v2 / (v2 * v2).sum(-1)**0.5
60
+    porm = np.sign((v1 * a3).sum(-1))
61
+    rad = np.arccos((v1*v2).sum(-1) / ((v1**2).sum(-1) * (v2**2).sum(-1))**0.5)
62
+    if not porm == 0:
63
+        rad = rad * porm
64
+
65
+    deg_angle = rad*(180/math.pi)
66
+    return deg_angle

+ 1 - 301
src/structure.py View File

@@ -1,5 +1,6 @@
1 1
 import math
2 2
 import numpy as np
3
+from geom import *
3 4
 
4 5
 class Structure:
5 6
     def __init__(self, res):
@@ -25,305 +26,4 @@ class Helix(Structure):
25 26
         self.residues = residues
26 27
         self.res_num = res_num
27 28
         Structure.res = res_num
28
-        
29
-def get_turns(residues):
30
-    # TODO : prevent redondency of overlapping turns
31
-    turns = {}
32
-    for i,res in enumerate(residues):
33
-        for j in range(3,6):
34
-            if(i+j<len(residues)):
35
-                if(res.h_bond(residues[i+j])<-0.5):
36
-                    print(j,"TURN", residues[i].resid, residues[i+j].resid)
37
-                    turns[i] = Turn(j,residues[i].resid)
38
-    return(turns)
39
-
40
-def get_bridges(residues):
41
-    bridges = {}
42
-    bridge = {}
43
-    strongest_bridge = {}
44
-    for i in range(1,len(residues)-4):
45
-        E_min = 0
46
-        for j in range(i+2,len(residues)-1):
47
-            # select triplet with the minimal energy 
48
-
49
-            if(residues[i-1].h_bond(residues[j])<-0.5
50
-               and residues[j].h_bond(residues[i+1])<-0.5):
51
-                bridge = {'res1':residues[i-1].h_bond(residues[j]),
52
-                          'res2':residues[j].h_bond(residues[i+1]),
53
-                          'ipos':residues[i].resid,
54
-                          'jpos':residues[j].resid,
55
-                          'btype':"para"}
56
-                   
57
-            if(residues[j-1].h_bond(residues[i])<-0.5
58
-               and residues[i].h_bond(residues[j+1])<-0.5):
59
-                bridge = {'res1':residues[j-1].h_bond(residues[i]),
60
-                          'res2':residues[i].h_bond(residues[j+1]),
61
-                          'ipos':residues[i].resid,
62
-                          'jpos':residues[j].resid,
63
-                          'btype':"para"}
64
-
65
-            if(residues[i].h_bond(residues[j])<-0.5
66
-               and residues[j].h_bond(residues[i])<-0.5):
67
-                bridge = {'res1':residues[i].h_bond(residues[j]),
68
-                          'res2':residues[j].h_bond(residues[i]),
69
-                          'ipos':residues[i].resid,
70
-                          'jpos':residues[j].resid,
71
-                          'btype':"anti"}
72
-                   
73
-            if(residues[i-1].h_bond(residues[j+1])<-0.5
74
-               and residues[j-1].h_bond(residues[i+1])<-0.5):
75
-                bridge = {'res1':residues[i-1].h_bond(residues[j+1]),
76
-                          'res2':residues[j-1].h_bond(residues[i+1]),
77
-                          'ipos':residues[i].resid,
78
-                          'jpos':residues[j].resid,
79
-                          'btype':"anti"}
80
-
81
-            if(bridge):
82
-                if(bridge['res1']+bridge['res2']<E_min):
83
-                    E_min = bridge['res1']+bridge['res2']
84
-                    strongest_bridge = bridge
85
-                    bridge = {}
86
-                    coord_bridge = [i,j]
87
-        # finally add the strongest bridge at i and j pos
88
-        if(strongest_bridge):
89
-            bridges[coord_bridge[0]] = (Bridge(strongest_bridge['btype'],
90
-                                                        strongest_bridge['ipos'],
91
-                                                        strongest_bridge['jpos']))
92
-            bridges[coord_bridge[1]] = (Bridge(strongest_bridge['btype'],
93
-                                                        strongest_bridge['jpos'],
94
-                                                        strongest_bridge['ipos']))
95
-    if(len(bridges)>0):
96
-        return(bridges)
97
-    else:
98
-        return(False)
99
-
100
-# def get_bonds(residues):
101
-#     for i,res1 in enumerate(residues):
102
-#         E_min = 0
103
-#         strongest_bridge = []
104
-#         for j in range(-5,6):
105
-#             if(i+j < len(residues)):
106
-#                 res2 = residues[i+j]
107
-#                 if(res1.h_bond(res2)<-0.5) and (res1.h_bond(res2)<E_min):
108
-#                     E_min = res1.h_bond(res2)
109
-#                     strongest_bridge = [res1, res2]
110
-#         if(len(strongest_bridge)>0):
111
-#             diff = strongest_bridge[0].resid - strongest_bridge[1].resid
112
-#             if( abs (diff) > 1 and abs(diff)<=5):
113
-#                 print(diff)
114
-
115
-def get_bonds(residues):
116
-    bonds = {}
117
-    k = 0
118
-    for i,res in enumerate(residues):
119
-        E_min = 0
120
-        for j in range(-5,-2):
121
-            if(i+j<len(residues)):
122
-                if(residues[i+j].h_bond(res)<-0.5):
123
-                    k+=1
124
-                    #if(res.h_bond(residues[i+j])<E_min):
125
-                    E_min = res.h_bond(residues[i+j])
126
-                    res_a = res
127
-                    res_b = residues[i+j]
128
-                    if j not in bonds:
129
-                        bonds[j] = []
130
-                    bonds[j].append([res_a.resid, res_b.resid])
131
-                    #turns[residues[i].resid] = Turn(j,residues[i].resid)
132
-    for key in bonds.keys():
133
-        print(key, len(bonds[key]))
134
-
135
-    print("LH",k)
136
-    
137
-def get_helix(residues, turns):
138
-    i = 1
139
-    helix = []
140
-    while i <= len(residues):
141
-        if(i in turns.keys() and i-1 in turns.keys()):
142
-            k = 0
143
-            temp_res = []
144
-            while(i+k in turns):
145
-                k+=1
146
-                temp_res.append(residues[i])
147
-                last_res_pos = residues[i].resid+k
148
-            if(k>=1):
149
-                helix_size=last_res_pos - residues[i].resid
150
-                print(turns[i].turn_type,"- HELIX at", residues[i].resid)
151
-                helix.append(Helix(temp_res,residues[i].resid))
152
-            i = i+k
153
-        else:
154
-            i+=1
155
-    return(helix)
156
-
157
-def get_ladders(bridges, residues):
158
-    ladders = {}
159
-    i = 1
160
-    while i < len(residues):
161
-        k = 1
162
-        if i in bridges.keys():
163
-            temp_bridges = [bridges[i]]
164
-            while ((i+k in bridges.keys()) and
165
-                   (bridges[i].bridge_type == bridges[i+k].bridge_type)):
166
-                temp_bridges.append(bridges[i+k])
167
-                k+=1
168
-        if k>1:
169
-            ladders[i] = k-1
170
-            print("ladder", bridges[i].res_num, bridges[i+k-1].res_num)
171
-            ladders[i] = {'start':bridges[i].res_num,
172
-                          'end':bridges[i+k-1].res_num,
173
-                          'bridges':temp_bridges}
174
-            i+=k-1
175
-        else:
176
-            i+=1
177
-    return ladders
178 29
  
179
-def get_sheets(ladders):
180
-    """
181
-    Bridges between ladders.
182
-    Check if 1 bridge between one ladder and one or more other ladders.
183
-    Iterate over all residues of one ladder and check if bridge with other residues
184
-    of the other ladders.
185
-    """
186
-    sheets = {}
187
-    for ladder in ladders:
188
-        for ladd2 in ladders:
189
-            for bridge in ladders[ladder]['bridges']:
190
-                if bridge.res_partner in res_list(ladders[ladd2]):
191
-                    print("ladder",ladders[ladder]['start'], ladders[ladder]['end'],"bridge",bridge.res_num, bridge.res_partner,
192
-                    "ladder 2",ladders[ladd2]['start'], ladders[ladd2]['end'])
193
-            #print("stop ladder 2")
194
-        print("stop ladder 1")            
195
-
196
-def res_list(ladder):
197
-    # TODO : method in ladder class
198
-    l=[]
199
-    for i in range(ladder['start'], ladder['end']):
200
-        l.append(i)
201
-    return(l)
202
-                   
203
-def get_bends(residues):
204
-    bends = {}
205
-    for i in range(2,len(residues)-2):
206
-        angle = math.degrees(vector_angles(vectors_substr(position_vector(residues[i].atoms["CA"].coords),
207
-                                                          position_vector(residues[i-2].atoms["CA"].coords)),
208
-                                           vectors_substr(position_vector(residues[i+2].atoms["CA"].coords),
209
-                                                          position_vector(residues[i].atoms["CA"].coords))))
210
-        if(angle>70):
211
-            print("angle", residues[i].resid, angle)
212
-            bends[residues[i].resid] = angle
213
-    return(bends)
214
-
215
-def vector_from_pos(a, b):
216
-    xAB = b[0]-a[0]
217
-    yAB = b[1]-a[1]
218
-    zAB = b[2]-a[2]
219
-    coord_AB = [xAB,yAB,zAB]
220
-    return coord_AB
221
-
222
-def vector_norm(v):
223
-    norm = math.sqrt(v[0]**2 + v[1]**2 + v[2]**2)
224
-    return norm
225
-
226
-def dot_product(v1,v2):
227
-    dot_product = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]
228
-    return(dot_product)
229
-
230
-def position_vector(c):
231
-    vector = vector_from_pos([0,0,0],c)
232
-    return vector
233
-
234
-def vectors_substr(v1, v2):
235
-    return ([v1[0]-v2[0],
236
-             v1[1]-v2[1],
237
-             v1[2]-v2[2]])
238
-
239
-def vector_angles(v1,v2):
240
-    dot_prod = dot_product(v1,v2)
241
-    norm_v1 = vector_norm(v1)
242
-    norm_v2 = vector_norm(v2)
243
-    term = dot_prod/(abs(norm_v1)*abs(norm_v2))
244
-    rad_angle = math.acos(term)
245
-    return rad_angle
246
-
247
-def calc_dihedral(u1, u2, u3, u4):
248
-    """ Calculate dihedral angle method. From bioPython.PDB
249
-    (adapted to np.array)
250
-    Calculate the dihedral angle between 4 vectors
251
-    representing 4 connected points. The angle is in
252
-    [-pi, pi].
253
-
254
-    Adapted function of dihedral_angle_from_coordinates.py 
255
-    by Eric Alcaide.
256
-    Source : https://gist.github.com/EricAlcaide
257
-    URL : https://gist.github.com/EricAlcaide/30d6bfdb8358d3a57d010c9a501fda56
258
-    """
259
-    #convert coords to numpy arrays
260
-    u1 = np.array(u1)
261
-    u2 = np.array(u2)
262
-    u3 = np.array(u3)
263
-    u4 = np.array(u4)
264
-    
265
-    a1 = u2 - u1
266
-    a2 = u3 - u2
267
-    a3 = u4 - u3
268
-
269
-    v1 = np.cross(a1, a2)
270
-    v1 = v1 / (v1 * v1).sum(-1)**0.5
271
-    v2 = np.cross(a2, a3)
272
-    v2 = v2 / (v2 * v2).sum(-1)**0.5
273
-    porm = np.sign((v1 * a3).sum(-1))
274
-    rad = np.arccos((v1*v2).sum(-1) / ((v1**2).sum(-1) * (v2**2).sum(-1))**0.5)
275
-    if not porm == 0:
276
-        rad = rad * porm
277
-
278
-    deg_angle = rad*(180/math.pi)
279
-    return deg_angle
280
-
281
-
282
-def get_chirality(residues):
283
-
284
-    for i in range(1,len(residues)-2):
285
-        chirality = {}
286
-        angle = calc_dihedral(residues[i-1].atoms["CA"].coords,
287
-                              residues[i].atoms["CA"].coords,
288
-                              residues[i+1].atoms["CA"].coords,
289
-                              residues[i+2].atoms["CA"].coords)
290
-        
291
-        if(angle>0 and angle<=180):
292
-            sign="+"
293
-            print("chirality", residues[i].resid, "+", angle)
294
-            
295
-        if(angle<=0 and angle > -180):
296
-            sign="-"
297
-            print("chirality", residues[i].resid, "-", angle)
298
-            
299
-        chirality[residues[i].resid] = sign
300
-        
301
-    return chirality
302
-
303
-
304
-def get_phi_psi(residues):
305
-    for i in range(len(residues)):
306
-        if(i==0):
307
-            phi = 360.0
308
-        else:
309
-            phi = calc_dihedral(residues[i-1].atoms["C"].coords,
310
-                                residues[i].atoms["N"].coords,
311
-                                residues[i].atoms["CA"].coords,
312
-                                residues[i].atoms["C"].coords)
313
-        if(i==len(residues)-1):
314
-            psi = 360.0
315
-        else:
316
-            psi = calc_dihedral(residues[i].atoms["N"].coords,
317
-                                residues[i].atoms["CA"].coords,
318
-                                residues[i].atoms["C"].coords,
319
-                                residues[i+1].atoms["N"].coords)
320
-
321
-        print("ANGLES", i, phi, psi)
322
-
323
-def get_TCO(res1, res2):
324
-    CO_res1 = vector_from_pos(res1.atoms["C"].coords,
325
-                              res1.atoms["O"].coords)
326
-    CO_res2 = vector_from_pos(res2.atoms["C"].coords,
327
-                              res2.atoms["O"].coords)
328
-    angle = vector_angles(CO_res1, CO_res2)
329
-    return(math.cos(angle))