md-manager 2.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- md_manager/CUTABI/CUTABI.py +324 -0
- md_manager/CUTABI/__init__.py +1 -0
- md_manager/CUTABI/test_CUTABI.py +151 -0
- md_manager/FILES/GRO_.py +32 -0
- md_manager/FILES/PDB_.py +100 -0
- md_manager/FILES/Traj_.py +200 -0
- md_manager/FILES/XTC_.py +38 -0
- md_manager/FILES/XYZ_.py +40 -0
- md_manager/FILES/__init__.py +5 -0
- md_manager/FILES/utils.py +43 -0
- md_manager/NMA/_ANM.py +302 -0
- md_manager/NMA/__init__.py +1 -0
- md_manager/__init__.py +4 -0
- md_manager/conformation.py +451 -0
- md_manager/core.py +383 -0
- md_manager/df_manipulation.py +42 -0
- md_manager/df_operations.py +445 -0
- md_manager/md_files.py +576 -0
- md_manager/parameters.py +70 -0
- md_manager-2.3.1.dist-info/LICENSE +661 -0
- md_manager-2.3.1.dist-info/METADATA +40 -0
- md_manager-2.3.1.dist-info/RECORD +24 -0
- md_manager-2.3.1.dist-info/WHEEL +5 -0
- md_manager-2.3.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
from ..conformation import chain_theta_angles, chain_gamma_angles
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from scipy.spatial import distance_matrix
|
|
6
|
+
|
|
7
|
+
__all__ = ["helix_criterion", "sheet_criterion", "predict_alpha_helix", "predict_beta_sheets"]
|
|
8
|
+
|
|
9
|
+
def helix_criterion(theta:pd.Series, gamma:pd.Series) -> pd.Series:
|
|
10
|
+
"""
|
|
11
|
+
Identify the positions of alpha-helices in a protein structure based on conformational angles.
|
|
12
|
+
|
|
13
|
+
This function evaluates the conformational angles (`θ` and `γ`) of a protein's backbone
|
|
14
|
+
and returns a boolean Series indicating the positions where alpha-helices are present. The
|
|
15
|
+
identification is based on the CUTABI criteria for the angle thresholds.
|
|
16
|
+
|
|
17
|
+
The criteria used for identifying alpha-helices are presented here:
|
|
18
|
+
https://www.frontiersin.org/journals/molecular-biosciences/articles/10.3389/fmolb.2021.786123/full
|
|
19
|
+
|
|
20
|
+
Parameters:
|
|
21
|
+
theta : pandas.Series
|
|
22
|
+
A Series containing the θ (theta) angles for each residue in the protein structure, in degrees.
|
|
23
|
+
The index should correspond to the residue identifiers.
|
|
24
|
+
gamma : pandas.Series
|
|
25
|
+
A Series containing the γ (gamma) angles for each residue in the protein structure, in degrees.
|
|
26
|
+
The index must match the index of the `theta` Series.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
pandas.Series
|
|
30
|
+
A boolean Series with the same index as the input, where `True` indicates the position of an
|
|
31
|
+
alpha-helix (based on the CUTABI criteria) and `False` otherwise.
|
|
32
|
+
|
|
33
|
+
Raises:
|
|
34
|
+
ValueError
|
|
35
|
+
If the indexes of `theta` and `gamma` do not match.
|
|
36
|
+
KeyError
|
|
37
|
+
If either `theta` or `gamma` contains invalid or missing data (e.g., NaN values).
|
|
38
|
+
|
|
39
|
+
Example:
|
|
40
|
+
>>> import pandas as pd
|
|
41
|
+
>>> theta = pd.Series([85, 90, 100, 70], index=[1, 2, 3, 4])
|
|
42
|
+
>>> gamma = pd.Series([35, 50, 75, 25], index=[1, 2, 3, 4])
|
|
43
|
+
>>> helix_criterion(theta, gamma)
|
|
44
|
+
1 True
|
|
45
|
+
2 True
|
|
46
|
+
3 True
|
|
47
|
+
4 False
|
|
48
|
+
dtype: bool
|
|
49
|
+
|
|
50
|
+
Notes:
|
|
51
|
+
- Ensure that both `theta` and `gamma` angles are provided in degrees and correspond to
|
|
52
|
+
the same residues (i.e., have identical indexes).
|
|
53
|
+
- The criteria for `θ` and `γ` are specific to CUTABI and may not detect other types of
|
|
54
|
+
secondary structures.
|
|
55
|
+
- This function assumes a residue-level representation of the protein structure, where each
|
|
56
|
+
row in the input Series corresponds to a residue.
|
|
57
|
+
"""
|
|
58
|
+
helix = pd.Series(False, index = theta.index)
|
|
59
|
+
|
|
60
|
+
# CUTABI parameters
|
|
61
|
+
theta_min, theta_max = (80.0, 105.0) # threshold for theta values
|
|
62
|
+
gamma_min, gamma_max = (30.0, 80.0) # threshold for gamma values
|
|
63
|
+
|
|
64
|
+
theta_criterion = (theta > theta_min) & (theta < theta_max)
|
|
65
|
+
gamma_criterion = (gamma > gamma_min) & (gamma < gamma_max)
|
|
66
|
+
tmp = pd.DataFrame({"Theta" : theta_criterion, "Gamma": gamma_criterion})
|
|
67
|
+
|
|
68
|
+
for win in tmp.rolling(4):
|
|
69
|
+
if win.Theta.all() & win.Gamma[1:-1].all():
|
|
70
|
+
helix[win.index] = True
|
|
71
|
+
|
|
72
|
+
return helix
|
|
73
|
+
|
|
74
|
+
def sheet_criterion(theta:pd.Series, gamma:pd.Series, xyz:pd.DataFrame) -> pd.Series:
|
|
75
|
+
"""
|
|
76
|
+
Identify the positions of beta-sheets in a protein structure based on conformational angles and spatial coordinates.
|
|
77
|
+
|
|
78
|
+
This function evaluates the conformational angles (`θ` and `γ`) of a protein's backbone, as well as
|
|
79
|
+
the 3D coordinates of the Cα atoms, to determine the positions of beta-sheets. Beta-sheets are identified
|
|
80
|
+
based on specific ranges of conformational angles combined with spatial criteria derived from the Cα
|
|
81
|
+
atom positions.
|
|
82
|
+
|
|
83
|
+
The criteria used for identifying beta-sheets are presented here:
|
|
84
|
+
https://www.frontiersin.org/journals/molecular-biosciences/articles/10.3389/fmolb.2021.786123/full
|
|
85
|
+
|
|
86
|
+
Parameters:
|
|
87
|
+
theta : pandas.Series
|
|
88
|
+
A Series containing the θ (theta) angles for each residue in the protein structure, in degrees.
|
|
89
|
+
The index should correspond to the residue identifiers.
|
|
90
|
+
gamma : pandas.Series
|
|
91
|
+
A Series containing the γ (gamma) angles for each residue in the protein structure, in degrees.
|
|
92
|
+
The index must match the index of the `theta` Series.
|
|
93
|
+
xyz : pandas.DataFrame
|
|
94
|
+
A DataFrame containing the 3D coordinates of the Cα atoms for each residue in the structure.
|
|
95
|
+
The DataFrame must have the following columns:
|
|
96
|
+
- 'x', 'y', 'z': 3D Cartesian coordinates of the Cα atoms.
|
|
97
|
+
The index of the DataFrame must match the indexes of the `theta` and `gamma` Series.
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
pandas.Series
|
|
101
|
+
A boolean Series with the same index as the input, where `True` indicates the position of a
|
|
102
|
+
beta-sheet and `False` otherwise.
|
|
103
|
+
|
|
104
|
+
Raises:
|
|
105
|
+
ValueError
|
|
106
|
+
If the indexes of `theta`, `gamma`, and `xyz` do not match.
|
|
107
|
+
KeyError
|
|
108
|
+
If the `xyz` DataFrame is missing required columns ['x', 'y', 'z'].
|
|
109
|
+
|
|
110
|
+
Example:
|
|
111
|
+
>>> import pandas as pd
|
|
112
|
+
>>> theta = pd.Series([-120, -130, -140, 70], index=[1, 2, 3, 4])
|
|
113
|
+
>>> gamma = pd.Series([120, 130, 140, 80], index=[1, 2, 3, 4])
|
|
114
|
+
>>> xyz = pd.DataFrame({
|
|
115
|
+
... 'x': [0.0, 1.0, 2.0, 3.0],
|
|
116
|
+
... 'y': [0.0, 0.5, 1.5, 2.0],
|
|
117
|
+
... 'z': [0.0, -1.0, -1.5, -2.0]
|
|
118
|
+
... }, index=[1, 2, 3, 4])
|
|
119
|
+
>>> sheet_criterion(theta, gamma, xyz)
|
|
120
|
+
1 True
|
|
121
|
+
2 True
|
|
122
|
+
3 True
|
|
123
|
+
4 False
|
|
124
|
+
dtype: bool
|
|
125
|
+
|
|
126
|
+
Notes:
|
|
127
|
+
- This function assumes the residue indexes in `theta`, `gamma`, and `xyz` align perfectly and represent
|
|
128
|
+
the same structure.
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
sheet = pd.Series(False, index = theta.index)
|
|
132
|
+
|
|
133
|
+
# CUTABI parameters :
|
|
134
|
+
theta_min, theta_max = (100.0, 155.0) # threshold for theta values
|
|
135
|
+
gamma_lim = 80.0 # threshold for abs(gamma) values
|
|
136
|
+
|
|
137
|
+
contact_threshold = 5.5 # threshold for K;I & K+1;I+-1 distances
|
|
138
|
+
contact_threshold2 = 6.8 # threshold for K+1;I+-2 distances
|
|
139
|
+
|
|
140
|
+
angle_criterion = pd.Series(False, index = sheet.index)
|
|
141
|
+
|
|
142
|
+
theta_criterion = (theta > theta_min) & (theta < theta_max)
|
|
143
|
+
gamma_criterion = gamma.abs() > gamma_lim
|
|
144
|
+
tmp = pd.DataFrame({"Theta" : theta_criterion, "Gamma": gamma_criterion})
|
|
145
|
+
|
|
146
|
+
for win in tmp.rolling(2):
|
|
147
|
+
if win.Theta.all() & win.Gamma[0:1].all():
|
|
148
|
+
angle_criterion[win.index] = True
|
|
149
|
+
|
|
150
|
+
inter_atom_distance = distance_matrix(xyz, xyz)
|
|
151
|
+
|
|
152
|
+
# Parallel sheet detection :
|
|
153
|
+
test1 = inter_atom_distance[:-1, :-2] < contact_threshold # K -I criterion
|
|
154
|
+
test2 = inter_atom_distance[1:, 1:-1] < contact_threshold # K+1-I+1 criterion
|
|
155
|
+
test3 = inter_atom_distance[1:,2:] < contact_threshold2 # K+1-I+2 criterion
|
|
156
|
+
|
|
157
|
+
distance_criterion = test1 & test2 & test3
|
|
158
|
+
I, K = np.where(distance_criterion)
|
|
159
|
+
for i, k in zip(I, K):
|
|
160
|
+
if k > i+2:
|
|
161
|
+
idx = [k, k+1, i, i+1]
|
|
162
|
+
if angle_criterion.iloc[idx].all():
|
|
163
|
+
sheet.iloc[idx] = True
|
|
164
|
+
|
|
165
|
+
# Anti-parallel sheet detection :
|
|
166
|
+
test1 = inter_atom_distance[:-1, 2:] < contact_threshold # K - I criterion
|
|
167
|
+
test3 = inter_atom_distance[1:,:-2] < contact_threshold2 # K+1-I-2 criterion
|
|
168
|
+
|
|
169
|
+
distance_criterion = test1 & test2 & test3
|
|
170
|
+
I, K = np.where(distance_criterion)
|
|
171
|
+
I += 2 # because test1[0, 0] -> k = 0, i = 2
|
|
172
|
+
for i, k in zip(I, K):
|
|
173
|
+
if k > i+2:
|
|
174
|
+
idx = [k, k+1, i, i+1]
|
|
175
|
+
if angle_criterion.iloc[idx].all():
|
|
176
|
+
sheet.iloc[idx] = True
|
|
177
|
+
|
|
178
|
+
return sheet
|
|
179
|
+
|
|
180
|
+
def predict_alpha_helix(df:pd.DataFrame) -> pd.Series:
|
|
181
|
+
"""
|
|
182
|
+
Predict the positions of alpha-helices in a protein structure using the CUTABI criterion.
|
|
183
|
+
|
|
184
|
+
This function calculates the conformational angles (`θ` and `γ`) for each residue in the input
|
|
185
|
+
DataFrame based on the provided 3D coordinates (x, y, z) of the Cα atoms. The calculated angles
|
|
186
|
+
are then passed to the `helix_criterion` function to predict regions of alpha-helical secondary
|
|
187
|
+
structure. The prediction is based on the following thresholds, as defined by the CUTABI criterion.
|
|
188
|
+
|
|
189
|
+
Parameters:
|
|
190
|
+
df : pandas.DataFrame
|
|
191
|
+
A DataFrame containing the 3D coordinates for the Cα atoms of the protein structure. The DataFrame
|
|
192
|
+
must include the following columns:
|
|
193
|
+
- 'x', 'y', 'z': The 3D Cartesian coordinates of the Cα atoms.
|
|
194
|
+
The index should correspond to the residue identifiers.
|
|
195
|
+
- Optional columns required atomic name selection (e.g., 'name').
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
pandas.Series
|
|
199
|
+
A boolean Series with the same index as the input DataFrame, where `True` indicates the positions
|
|
200
|
+
of alpha-helices (based on the CUTABI criterion) and `False` otherwise.
|
|
201
|
+
|
|
202
|
+
Raises:
|
|
203
|
+
KeyError
|
|
204
|
+
If the input DataFrame is missing required columns ['x', 'y', 'z'].
|
|
205
|
+
|
|
206
|
+
ValueError
|
|
207
|
+
If the number of residues or coordinates is insufficient for computing the conformational angles.
|
|
208
|
+
|
|
209
|
+
Example:
|
|
210
|
+
>>> import pandas as pd
|
|
211
|
+
>>> data = pd.DataFrame({
|
|
212
|
+
... 'x': [0.0, 1.0, 2.0, 3.0],
|
|
213
|
+
... 'y': [0.0, 0.5, 1.5, 2.0],
|
|
214
|
+
... 'z': [0.0, -1.0, -1.5, -2.0]
|
|
215
|
+
... }, index=[1, 2, 3, 4])
|
|
216
|
+
>>> predict_alpha_helix(data)
|
|
217
|
+
1 True
|
|
218
|
+
2 True
|
|
219
|
+
3 True
|
|
220
|
+
4 False
|
|
221
|
+
dtype: bool
|
|
222
|
+
|
|
223
|
+
See Also:
|
|
224
|
+
- `helix_criterion`: The function used to evaluate the CUTABI criterion for alpha-helices based on
|
|
225
|
+
the angles `θ` and `γ`.
|
|
226
|
+
|
|
227
|
+
"""
|
|
228
|
+
alpha = pd.Series(False, index=df.index)
|
|
229
|
+
|
|
230
|
+
if not "name" in df:
|
|
231
|
+
CA = df.copy()
|
|
232
|
+
else:
|
|
233
|
+
names = set(df.name)
|
|
234
|
+
names.remove("CA")
|
|
235
|
+
if len(names) > 0:
|
|
236
|
+
CA = df.query("name == 'CA'")
|
|
237
|
+
else:
|
|
238
|
+
CA = df.copy()
|
|
239
|
+
|
|
240
|
+
if not "chain" in df:
|
|
241
|
+
CA["chain"] = "A"
|
|
242
|
+
|
|
243
|
+
for _, chain in CA.groupby("chain"):
|
|
244
|
+
theta = chain_theta_angles(chain)
|
|
245
|
+
gamma = chain_gamma_angles(chain)
|
|
246
|
+
alpha_chain = helix_criterion(theta, gamma)
|
|
247
|
+
|
|
248
|
+
alpha[alpha_chain.index] = alpha_chain.values
|
|
249
|
+
|
|
250
|
+
return alpha
|
|
251
|
+
|
|
252
|
+
def predict_beta_sheets(df:pd.DataFrame) -> pd.Series:
|
|
253
|
+
"""
|
|
254
|
+
Predict the positions of beta-sheets in a protein structure using the CUTABI criterion.
|
|
255
|
+
|
|
256
|
+
This function calculates the conformational angles (`θ` and `γ`) as well as inter-atomic distances for each residue in the input
|
|
257
|
+
DataFrame based on the provided 3D coordinates (x, y, z) of the Cα atoms. The calculated angles
|
|
258
|
+
are then passed to the `sheet_criterion` function to predict regions of alpha-helical secondary
|
|
259
|
+
structure. The prediction is based on the following thresholds, as defined by the CUTABI criterion.
|
|
260
|
+
|
|
261
|
+
Parameters:
|
|
262
|
+
df : pandas.DataFrame
|
|
263
|
+
A DataFrame containing the 3D coordinates for the Cα atoms of the protein structure. The DataFrame
|
|
264
|
+
must include the following columns:
|
|
265
|
+
- 'x', 'y', 'z': The 3D Cartesian coordinates of the Cα atoms.
|
|
266
|
+
The index should correspond to the residue identifiers.
|
|
267
|
+
- Optional columns required atomic name selection (e.g., 'name').
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
pandas.Series
|
|
271
|
+
A boolean Series with the same index as the input DataFrame, where `True` indicates the positions
|
|
272
|
+
of alpha-helices (based on the CUTABI criterion) and `False` otherwise.
|
|
273
|
+
|
|
274
|
+
Raises:
|
|
275
|
+
KeyError
|
|
276
|
+
If the input DataFrame is missing required columns ['x', 'y', 'z'].
|
|
277
|
+
|
|
278
|
+
ValueError
|
|
279
|
+
If the number of residues or coordinates is insufficient for computing the conformational angles.
|
|
280
|
+
|
|
281
|
+
Example:
|
|
282
|
+
>>> import pandas as pd
|
|
283
|
+
>>> data = pd.DataFrame({
|
|
284
|
+
... 'x': [0.0, 1.0, 2.0, 3.0],
|
|
285
|
+
... 'y': [0.0, 0.5, 1.5, 2.0],
|
|
286
|
+
... 'z': [0.0, -1.0, -1.5, -2.0]
|
|
287
|
+
... }, index=[1, 2, 3, 4])
|
|
288
|
+
>>> predict_alpha_helix(data)
|
|
289
|
+
1 True
|
|
290
|
+
2 True
|
|
291
|
+
3 True
|
|
292
|
+
4 False
|
|
293
|
+
dtype: bool
|
|
294
|
+
|
|
295
|
+
See Also:
|
|
296
|
+
- `sheet_criterion`: The function used to evaluate the CUTABI criterion for beta-sheets based on
|
|
297
|
+
the angles `θ` and `γ`.
|
|
298
|
+
|
|
299
|
+
"""
|
|
300
|
+
beta = pd.Series(False, index=df.index)
|
|
301
|
+
|
|
302
|
+
if not "name" in df:
|
|
303
|
+
CA = df.copy()
|
|
304
|
+
else:
|
|
305
|
+
names = set(df.name)
|
|
306
|
+
names.remove("CA")
|
|
307
|
+
if len(names) > 0:
|
|
308
|
+
CA = df.query("name == 'CA'")
|
|
309
|
+
else:
|
|
310
|
+
CA = df.copy()
|
|
311
|
+
|
|
312
|
+
if not "chain" in df:
|
|
313
|
+
CA["chain"] = "A"
|
|
314
|
+
|
|
315
|
+
for _, chain in CA.groupby("chain"):
|
|
316
|
+
theta = chain_theta_angles(chain)
|
|
317
|
+
gamma = chain_gamma_angles(chain)
|
|
318
|
+
xyz = chain[["x", "y", "z"]]
|
|
319
|
+
beta_chain = sheet_criterion(theta, gamma, xyz)
|
|
320
|
+
|
|
321
|
+
beta[beta_chain.index] = beta_chain.values
|
|
322
|
+
|
|
323
|
+
return beta
|
|
324
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .CUTABI import *
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
from ..df_operations import chain_theta_angles, chain_gamma_angles, check_chain_validity, InvalidChainException
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pandas as pd
|
|
5
|
+
from scipy.spatial import distance_matrix
|
|
6
|
+
|
|
7
|
+
def helix_criterion(theta:pd.Series, gamma:pd.Series) -> pd.Series:
|
|
8
|
+
"""
|
|
9
|
+
Takes the conformational angles of a single chain and returns a Series of boolean that indicates the position of alpha-helices.
|
|
10
|
+
|
|
11
|
+
Before calling this method, please make sure that the indexes of both Series are identical.
|
|
12
|
+
"""
|
|
13
|
+
helix = pd.Series(False, index = theta.index)
|
|
14
|
+
|
|
15
|
+
# CUTABI parameters
|
|
16
|
+
theta_min, theta_max = (80.0, 105.0) # threshold for theta values
|
|
17
|
+
gamma_min, gamma_max = (30.0, 80.0) # threshold for gamma values
|
|
18
|
+
|
|
19
|
+
theta_criterion = (theta > theta_min) & (theta < theta_max)
|
|
20
|
+
gamma_criterion = (gamma > gamma_min) & (gamma < gamma_max)
|
|
21
|
+
tmp = pd.DataFrame({"Theta" : theta_criterion, "Gamma": gamma_criterion})
|
|
22
|
+
|
|
23
|
+
for win in tmp.rolling(4):
|
|
24
|
+
if win.Theta.all() & win.Gamma[1:-1].all():
|
|
25
|
+
helix[win.index] = True
|
|
26
|
+
|
|
27
|
+
return helix
|
|
28
|
+
|
|
29
|
+
def sheet_criterion(theta:pd.Series, gamma:pd.Series, xyz:pd.DataFrame) -> pd.Series:
|
|
30
|
+
"""
|
|
31
|
+
Takes the conformational angles of a single chain as well as the coordinates of the CA atoms and returns a Series of boolean that indicates the position of beta-sheets.
|
|
32
|
+
|
|
33
|
+
Before calling this method, please make sure that the indexes of both Series and DataFrame are identical.
|
|
34
|
+
"""
|
|
35
|
+
sheet = pd.Series(False, index = theta.index)
|
|
36
|
+
|
|
37
|
+
# CUTABI parameters :
|
|
38
|
+
theta_min, theta_max = (100.0, 155.0) # threshold for theta values
|
|
39
|
+
gamma_lim = 80.0 # threshold for abs(gamma) values
|
|
40
|
+
|
|
41
|
+
contact_threshold = 5.5 # threshold for K;I & K+1;I+-1 distances
|
|
42
|
+
contact_threshold2 = 6.8 # threshold for K+1;I+-2 distances
|
|
43
|
+
|
|
44
|
+
angle_criterion = pd.Series(False, index = sheet.index)
|
|
45
|
+
|
|
46
|
+
theta_criterion = (theta > theta_min) & (theta < theta_max)
|
|
47
|
+
gamma_criterion = gamma.abs() > gamma_lim
|
|
48
|
+
tmp = pd.DataFrame({"Theta" : theta_criterion, "Gamma": gamma_criterion})
|
|
49
|
+
|
|
50
|
+
for win in tmp.rolling(2):
|
|
51
|
+
if win.Theta.all() & win.Gamma[0:1].all():
|
|
52
|
+
angle_criterion[win.index] = True
|
|
53
|
+
|
|
54
|
+
inter_atom_distance = distance_matrix(xyz, xyz)
|
|
55
|
+
|
|
56
|
+
# Parallel sheet detection :
|
|
57
|
+
test1 = inter_atom_distance[:-1, :-2] < contact_threshold # K -I criterion
|
|
58
|
+
test2 = inter_atom_distance[1:, 1:-1] < contact_threshold # K+1-I+1 criterion
|
|
59
|
+
test3 = inter_atom_distance[1:,2:] < contact_threshold2 # K+1-I+2 criterion
|
|
60
|
+
|
|
61
|
+
distance_criterion = test1 & test2 & test3
|
|
62
|
+
I, K = np.where(distance_criterion)
|
|
63
|
+
for i, k in zip(I, K):
|
|
64
|
+
if k > i+2:
|
|
65
|
+
idx = [k, k+1, i, i+1]
|
|
66
|
+
if angle_criterion.iloc[idx].all():
|
|
67
|
+
sheet.iloc[idx] = True
|
|
68
|
+
|
|
69
|
+
# Anti-parallel sheet detection :
|
|
70
|
+
test1 = inter_atom_distance[:-1, 2:] < contact_threshold # K - I criterion
|
|
71
|
+
test3 = inter_atom_distance[1:,:-2] < contact_threshold2 # K+1-I-2 criterion
|
|
72
|
+
|
|
73
|
+
distance_criterion = test1 & test2 & test3
|
|
74
|
+
I, K = np.where(distance_criterion)
|
|
75
|
+
I += 2 # because test1[0, 0] -> k = 0, i = 2
|
|
76
|
+
for i, k in zip(I, K):
|
|
77
|
+
if k > i+2:
|
|
78
|
+
idx = [k, k+1, i, i+1]
|
|
79
|
+
if angle_criterion.iloc[idx].all():
|
|
80
|
+
sheet.iloc[idx] = True
|
|
81
|
+
|
|
82
|
+
return sheet
|
|
83
|
+
|
|
84
|
+
def check_df_infos(df:pd.DataFrame) -> None:
|
|
85
|
+
if not "chain" in df:
|
|
86
|
+
df["chain"] = "A"
|
|
87
|
+
|
|
88
|
+
for _, tmp in df.groupby("chain"):
|
|
89
|
+
check_chain_validity(tmp)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def predict_alpha_helix(df:pd.DataFrame) -> pd.Series:
|
|
93
|
+
"""
|
|
94
|
+
Uses CUTABI criterion to predict the position of alpha-helices.
|
|
95
|
+
"""
|
|
96
|
+
alpha = pd.Series(False, index=df.index)
|
|
97
|
+
|
|
98
|
+
if not "name" in df:
|
|
99
|
+
CA = df.copy()
|
|
100
|
+
else:
|
|
101
|
+
names = set(df.name)
|
|
102
|
+
names.remove("CA")
|
|
103
|
+
if len(names) > 0:
|
|
104
|
+
CA = df.query("name == 'CA'")
|
|
105
|
+
else:
|
|
106
|
+
CA = df.copy()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
check_df_infos(CA)
|
|
110
|
+
|
|
111
|
+
for _, chain in CA.groupby("chain"):
|
|
112
|
+
theta = chain_theta_angles(chain)
|
|
113
|
+
gamma = chain_gamma_angles(chain)
|
|
114
|
+
alpha_chain = helix_criterion(theta, gamma)
|
|
115
|
+
|
|
116
|
+
alpha[alpha_chain.index] = alpha_chain.values
|
|
117
|
+
|
|
118
|
+
return alpha
|
|
119
|
+
|
|
120
|
+
def predict_beta_sheets(df:pd.DataFrame) -> pd.Series:
|
|
121
|
+
"""
|
|
122
|
+
Uses CUTABI criterion to predict the position of alpha-helices.
|
|
123
|
+
"""
|
|
124
|
+
beta = pd.Series(False, index=df.index)
|
|
125
|
+
|
|
126
|
+
if not "name" in df:
|
|
127
|
+
CA = df.copy()
|
|
128
|
+
else:
|
|
129
|
+
names = set(df.name)
|
|
130
|
+
names.remove("CA")
|
|
131
|
+
if len(names) > 0:
|
|
132
|
+
CA = df.query("name == 'CA'")
|
|
133
|
+
else:
|
|
134
|
+
CA = df.copy()
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
check_df_infos(CA)
|
|
138
|
+
|
|
139
|
+
for _, chain in CA.groupby("chain"):
|
|
140
|
+
theta = chain_theta_angles(chain)
|
|
141
|
+
gamma = chain_gamma_angles(chain)
|
|
142
|
+
xyz = chain[["x", "y", "z"]]
|
|
143
|
+
beta_chain = sheet_criterion(theta, gamma, xyz)
|
|
144
|
+
|
|
145
|
+
beta[beta_chain.index] = beta_chain.values
|
|
146
|
+
|
|
147
|
+
return beta
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
md_manager/FILES/GRO_.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from .Traj_ import Traj
|
|
2
|
+
from MDAnalysis.coordinates.GRO import GROWriter
|
|
3
|
+
|
|
4
|
+
class GRO(Traj):
|
|
5
|
+
default_params = dict(
|
|
6
|
+
# Read/Write mode:
|
|
7
|
+
mode = "r",
|
|
8
|
+
|
|
9
|
+
# Topology records:
|
|
10
|
+
return_topology = True,
|
|
11
|
+
return_alt = False,
|
|
12
|
+
return_chain = False,
|
|
13
|
+
return_occupancy = False,
|
|
14
|
+
return_b = False,
|
|
15
|
+
return_segi = False,
|
|
16
|
+
return_e = False,
|
|
17
|
+
return_q = False,
|
|
18
|
+
return_m = False,
|
|
19
|
+
|
|
20
|
+
# Data records
|
|
21
|
+
return_velocity = False,
|
|
22
|
+
#return_forces = False # TODO
|
|
23
|
+
|
|
24
|
+
# Secondary structures:
|
|
25
|
+
return_alpha = False,
|
|
26
|
+
return_beta = False,
|
|
27
|
+
ss_method = "CUTABI"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
def save(self, filename:str):
|
|
31
|
+
with GROWriter(filename) as gro:
|
|
32
|
+
gro.write(self.atoms)
|
md_manager/FILES/PDB_.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from .Traj_ import Traj
|
|
2
|
+
from MDAnalysis.coordinates.PDB import PDBWriter
|
|
3
|
+
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import sys
|
|
6
|
+
from urllib.request import urlopen
|
|
7
|
+
|
|
8
|
+
class PDB(Traj):
|
|
9
|
+
default_params = dict(
|
|
10
|
+
# Read/Write mode:
|
|
11
|
+
mode = "r",
|
|
12
|
+
|
|
13
|
+
# Topology records:
|
|
14
|
+
return_topology = True,
|
|
15
|
+
return_alt = True,
|
|
16
|
+
return_chain = True,
|
|
17
|
+
return_occupancy = True,
|
|
18
|
+
return_b = False,
|
|
19
|
+
return_segi = True,
|
|
20
|
+
return_e = False,
|
|
21
|
+
return_q = False,
|
|
22
|
+
return_m = False,
|
|
23
|
+
|
|
24
|
+
# Data records
|
|
25
|
+
return_velocity = False,
|
|
26
|
+
#return_forces = False # TODO
|
|
27
|
+
|
|
28
|
+
# Secondary structures:
|
|
29
|
+
return_alpha = False,
|
|
30
|
+
return_beta = False,
|
|
31
|
+
ss_method = "CUTABI"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def save(self, filename:str, multiframe=False):
|
|
35
|
+
with PDBWriter(filename, multiframe=multiframe) as pdb:
|
|
36
|
+
if multiframe:
|
|
37
|
+
self = iter(self)
|
|
38
|
+
for u in self.frame:
|
|
39
|
+
pdb.write(u)
|
|
40
|
+
|
|
41
|
+
else:
|
|
42
|
+
pdb.write(self.atoms)
|
|
43
|
+
|
|
44
|
+
def read_format(line:str) -> tuple[str, str, str, str, int, str, float, float, float, float, float, float, str, str, str]:
|
|
45
|
+
"""
|
|
46
|
+
Parses a line from a PDB file to extract atomic data.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
line (str): A single line from the PDB file, formatted according
|
|
50
|
+
to the PDB specification.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
tuple[str, str, str, str, int, str, float, float, float, float,
|
|
54
|
+
float, float, str, str, str]: A tuple containing atom information,
|
|
55
|
+
including:
|
|
56
|
+
- Atom name
|
|
57
|
+
- Alternate location indicator
|
|
58
|
+
- Residue name
|
|
59
|
+
- Chain identifier
|
|
60
|
+
- Residue sequence number
|
|
61
|
+
- Insertion code
|
|
62
|
+
- X, Y, and Z coordinates
|
|
63
|
+
- Occupancy and temperature factor
|
|
64
|
+
- Segment identifier, element symbol, and charge
|
|
65
|
+
"""
|
|
66
|
+
return (
|
|
67
|
+
line[:6].strip(),
|
|
68
|
+
#int(line[6:11].strip()),
|
|
69
|
+
line[12:16].strip(), # Atom name
|
|
70
|
+
line[16:17].strip(), # Alternate location indicator
|
|
71
|
+
line[17:20].strip() , # Residue name
|
|
72
|
+
line[21:22].strip(), # Chain identifier
|
|
73
|
+
int(line[22:26].strip()), # Residue sequence number
|
|
74
|
+
line[26:27].strip(), # Insertion code
|
|
75
|
+
float(line[30:38].strip()), # X coordinate
|
|
76
|
+
float(line[38:46].strip()), # Y coordinate
|
|
77
|
+
float(line[46:54].strip()), # Z coordinate
|
|
78
|
+
float(line[54:60].strip()) if line[54:60].strip() != "" else 1.0, # Occupancy
|
|
79
|
+
float(line[60:66].strip()) if line[60:66].strip() != "" else 0.0, # Temperature factor
|
|
80
|
+
line[72:76].strip(), # Segment identifier
|
|
81
|
+
line[76:78].strip(), # Element symbol
|
|
82
|
+
line[78:80].strip() # Charge on the atom
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def fetch_PDB(pdb_code:str, atom_only = False) -> pd.DataFrame:
|
|
86
|
+
url = f"https://files.rcsb.org/download/{pdb_code.lower()}.pdb"
|
|
87
|
+
response = urlopen(url)
|
|
88
|
+
|
|
89
|
+
txt = response.read()
|
|
90
|
+
lines = (txt.decode("utf-8") if sys.version_info[0] >= 3 else txt.decode("ascii")).splitlines()
|
|
91
|
+
|
|
92
|
+
data = [
|
|
93
|
+
read_format(line) for line in lines if line.startswith("ATOM") or (not atom_only and line.startswith("HETATM"))
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
df = pd.DataFrame(data, columns = ["record_name", "name", "alt", "resn", "chain", "resi", "insertion", "x", "y", "z", "occupancy", "b", "segi", "e", "q"])
|
|
97
|
+
df.index.name = "atom_id"
|
|
98
|
+
df.index += 1
|
|
99
|
+
|
|
100
|
+
return df
|