CG2AT-lite 0.2__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.
- cg2at_lite/__init__.py +1 -0
- cg2at_lite/bin/at_mod.py +673 -0
- cg2at_lite/bin/at_mod_np.py +91 -0
- cg2at_lite/bin/at_mod_p.py +695 -0
- cg2at_lite/bin/cg2at.py +195 -0
- cg2at_lite/bin/check_library.py +111 -0
- cg2at_lite/bin/g_var.py +105 -0
- cg2at_lite/bin/gen.py +1095 -0
- cg2at_lite/bin/gro.py +568 -0
- cg2at_lite/bin/read_in.py +281 -0
- cg2at_lite-0.2.dist-info/METADATA +776 -0
- cg2at_lite-0.2.dist-info/RECORD +16 -0
- cg2at_lite-0.2.dist-info/WHEEL +5 -0
- cg2at_lite-0.2.dist-info/entry_points.txt +2 -0
- cg2at_lite-0.2.dist-info/licenses/LICENSE +674 -0
- cg2at_lite-0.2.dist-info/top_level.txt +1 -0
cg2at_lite/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
cg2at_lite/bin/at_mod.py
ADDED
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
import os, sys
|
|
4
|
+
import numpy as np
|
|
5
|
+
import itertools
|
|
6
|
+
import math
|
|
7
|
+
from scipy.spatial import cKDTree
|
|
8
|
+
import gen, g_var, at_mod_p, read_in, gro
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### sanity checking
|
|
12
|
+
|
|
13
|
+
def sanity_check_fragments(res, cg, sin_bead):
|
|
14
|
+
#### fetches bead and atom info from fragment database
|
|
15
|
+
location = gen.fragment_location(res)
|
|
16
|
+
residue, fragment_mass = get_atomistic(location, res)
|
|
17
|
+
atom_list = []
|
|
18
|
+
bead_list = []
|
|
19
|
+
for group in residue.values():
|
|
20
|
+
for bead in group:
|
|
21
|
+
bead_list.append(bead)
|
|
22
|
+
if not sin_bead:
|
|
23
|
+
for atom in group[bead]:
|
|
24
|
+
atom_list.append(atom)
|
|
25
|
+
else:
|
|
26
|
+
if bead == sin_bead:
|
|
27
|
+
for atom in group[bead]:
|
|
28
|
+
atom_list.append(atom)
|
|
29
|
+
return sorted(bead_list), atom_list
|
|
30
|
+
|
|
31
|
+
def sanity_check_atoms(atom_list, res):
|
|
32
|
+
#### checks atom order
|
|
33
|
+
for at_num in range(1, len(atom_list)+1):
|
|
34
|
+
if at_num not in atom_list:
|
|
35
|
+
sys.exit('atom number '+str(at_num)+' is missing from fragment library: '+res+'\n')
|
|
36
|
+
|
|
37
|
+
def sanity_check_beads(bead_list, cg, res):
|
|
38
|
+
#### checks if bead is in fragment library
|
|
39
|
+
bead_list_new=[]
|
|
40
|
+
for bead in cg:
|
|
41
|
+
if bead not in bead_list:
|
|
42
|
+
new_bead = bead[1:]+bead[0]
|
|
43
|
+
if new_bead in bead_list and new_bead not in cg:
|
|
44
|
+
pass
|
|
45
|
+
else:
|
|
46
|
+
sys.exit('The bead '+bead+' is missing from the fragment library: '+res+'\n')
|
|
47
|
+
bead_list_new.append(bead)
|
|
48
|
+
return bead_list_new
|
|
49
|
+
|
|
50
|
+
def sanity_check_protein_other(res_type, test=False):
|
|
51
|
+
bead_list, atom_list = {},{}
|
|
52
|
+
for residue in g_var.cg_residues[res_type]:
|
|
53
|
+
for bead in g_var.cg_residues[res_type][residue]:
|
|
54
|
+
resname = g_var.cg_residues[res_type][residue][bead]['residue_name']
|
|
55
|
+
break
|
|
56
|
+
if resname not in bead_list or resname not in atom_list:
|
|
57
|
+
bead_list[resname], atom_list[resname] = sanity_check_fragments(resname, g_var.cg_residues[res_type][residue], False)
|
|
58
|
+
sanity_check_atoms(atom_list[resname], resname)
|
|
59
|
+
bead_list_cg = sanity_check_beads(bead_list[resname], g_var.cg_residues[res_type][residue], resname)
|
|
60
|
+
if bead_list[resname] != sorted(bead_list_cg):
|
|
61
|
+
if len(bead_list[resname]) == len(bead_list_cg):
|
|
62
|
+
fix_atom_wrap(bead_list[resname], bead_list_cg, res_type, residue)
|
|
63
|
+
else:
|
|
64
|
+
if not test:
|
|
65
|
+
print('There is a issue with residue: '+resname+' '+str(residue+1)+'. If expected ignore this message.' )
|
|
66
|
+
if res_type != 'OTHER':
|
|
67
|
+
sys.exit('number of atomistic fragments: '+str(len(bead_list[resname]))+' does not equal number of CG beads: '+str(len(bead_list_cg)))
|
|
68
|
+
|
|
69
|
+
def sanity_check_solvent(res_type):
|
|
70
|
+
bead_list, atom_list = {},{}
|
|
71
|
+
for residue in g_var.cg_residues[res_type]:
|
|
72
|
+
for bead in g_var.cg_residues[res_type][residue]:
|
|
73
|
+
sin_bead=bead
|
|
74
|
+
break
|
|
75
|
+
if sin_bead not in bead_list or sin_bead not in atom_list:
|
|
76
|
+
bead_list[sin_bead], atom_list[sin_bead] = sanity_check_fragments(res_type, g_var.cg_residues[res_type][residue], sin_bead)
|
|
77
|
+
sanity_check_atoms(atom_list[sin_bead], res_type)
|
|
78
|
+
sanity_check_beads(bead_list[sin_bead], g_var.cg_residues[res_type][residue], res_type)
|
|
79
|
+
|
|
80
|
+
def sanity_check_non_protein(res_type):
|
|
81
|
+
bead_list, atom_list = {},{}
|
|
82
|
+
if res_type not in bead_list or res_type not in atom_list:
|
|
83
|
+
bead_list[res_type], atom_list[res_type] = sanity_check_fragments(res_type, g_var.cg_residues[res_type], False)
|
|
84
|
+
sanity_check_atoms(atom_list[res_type], res_type)
|
|
85
|
+
for residue in g_var.cg_residues[res_type]:
|
|
86
|
+
bead_list_cg = sanity_check_beads(bead_list[res_type], g_var.cg_residues[res_type][residue], res_type)
|
|
87
|
+
if bead_list[res_type] != sorted(bead_list_cg):
|
|
88
|
+
if len(bead_list[res_type]) == len(bead_list_cg):
|
|
89
|
+
fix_atom_wrap(bead_list[res_type], bead_list_cg, res_type, residue)
|
|
90
|
+
else:
|
|
91
|
+
print('There is a issue with residue: '+res_type+' '+str(residue+1))
|
|
92
|
+
sys.exit('number of atomistic fragments: '+str(len(bead_list[res_type]))+' does not equal number of CG beads: '+str(len(bead_list_cg)))
|
|
93
|
+
|
|
94
|
+
def sanity_check():
|
|
95
|
+
#### runs through every bead and checks whether it exists
|
|
96
|
+
for res_type in g_var.cg_residues:
|
|
97
|
+
if res_type in ['PROTEIN', 'OTHER']:
|
|
98
|
+
sanity_check_protein_other(res_type)
|
|
99
|
+
elif res_type in g_var.sol_residues or res_type in g_var.ion_residues:
|
|
100
|
+
sanity_check_solvent(res_type)
|
|
101
|
+
else:
|
|
102
|
+
sanity_check_non_protein(res_type)
|
|
103
|
+
|
|
104
|
+
def fix_atom_wrap(bead_list_frag, bead_list_cg, section, resid):
|
|
105
|
+
for bead in bead_list_cg:
|
|
106
|
+
if bead not in bead_list_frag:
|
|
107
|
+
new_bead = bead[1:]+bead[0]
|
|
108
|
+
if new_bead in bead_list_frag and new_bead not in bead_list_cg:
|
|
109
|
+
g_var.cg_residues[section][resid][new_bead] = g_var.cg_residues[section][resid][bead]
|
|
110
|
+
del g_var.cg_residues[section][resid][bead]
|
|
111
|
+
else:
|
|
112
|
+
print('There is a issue with residue: '+section+' '+str(resid+1))
|
|
113
|
+
print('input file list:\n',sorted(bead_list_cg))
|
|
114
|
+
print('\ncannot find: '+bead+' or '+new_bead+' in fragment list:')
|
|
115
|
+
sys.exit(sorted(bead_list_frag))
|
|
116
|
+
|
|
117
|
+
##### Sanity check end
|
|
118
|
+
|
|
119
|
+
#### rotations section
|
|
120
|
+
|
|
121
|
+
def rotate_atom(coord, center,xyz_rot_apply):
|
|
122
|
+
#### rotates atom around center
|
|
123
|
+
coord = coord-center #### centers COM coordinates to 0,0,0
|
|
124
|
+
if np.any(xyz_rot_apply):
|
|
125
|
+
coord=np.array(coord).dot(xyz_rot_apply)
|
|
126
|
+
coord = coord+center #### translates coord back by original offset
|
|
127
|
+
return coord
|
|
128
|
+
|
|
129
|
+
def kabsch_rotate(at_connections,cg_connections):
|
|
130
|
+
## A solution for the best rotation to relate two sets of vectors. By WOLFGANG KABSCH
|
|
131
|
+
## http://en.wikipedia.org/wiki/Kabsch_algorithm
|
|
132
|
+
Cov_mat = np.dot(np.transpose(at_connections), cg_connections)
|
|
133
|
+
V, S, W = np.linalg.svd(Cov_mat)
|
|
134
|
+
reflection = np.linalg.det(V) * np.linalg.det(W)
|
|
135
|
+
if reflection < 0:
|
|
136
|
+
S[-1] = -S[-1]
|
|
137
|
+
V[:, -1] = -V[:, -1]
|
|
138
|
+
rot_mat = np.dot(V, W)
|
|
139
|
+
return rot_mat
|
|
140
|
+
|
|
141
|
+
## rotations end
|
|
142
|
+
## alignments
|
|
143
|
+
|
|
144
|
+
def find_cross_vector(ca):
|
|
145
|
+
#### finds cross vector of the atoms CA, CA+1, CA+2
|
|
146
|
+
AB = ca[0]-ca[1]
|
|
147
|
+
AC = ca[0]-ca[2]
|
|
148
|
+
cross_vector = np.cross(AB, AC)
|
|
149
|
+
cross_vector = cross_vector/np.linalg.norm(cross_vector)
|
|
150
|
+
return cross_vector
|
|
151
|
+
|
|
152
|
+
def noramlised_vector(c1, c2):
|
|
153
|
+
initial_vector= c1-c2
|
|
154
|
+
initial_vector = initial_vector/np.linalg.norm(initial_vector)
|
|
155
|
+
return initial_vector
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def align_to_vector(v1, v2):
|
|
159
|
+
#### returns the rotation matrix to rotate v1 to v2
|
|
160
|
+
v = np.cross(v1,v2)
|
|
161
|
+
c = np.dot(v1,v2)
|
|
162
|
+
s = np.linalg.norm(v)
|
|
163
|
+
|
|
164
|
+
rotation=np.array([[ 0, -v[2], v[1]],
|
|
165
|
+
[v[2], 0, -v[0]],
|
|
166
|
+
[-v[1], v[0], 0],
|
|
167
|
+
])
|
|
168
|
+
|
|
169
|
+
r = np.identity(3) - rotation + np.matmul(rotation,rotation) * ((1 - c)/(s**2))
|
|
170
|
+
return r
|
|
171
|
+
|
|
172
|
+
def align_at_frag_to_CG_frag(at_com, cg_com, group):
|
|
173
|
+
#### aligns atomistic fragment to cg bead
|
|
174
|
+
COM_vector=at_com-cg_com ### gets vector between COM of atoms in fragment and cg bead
|
|
175
|
+
for bead in group:
|
|
176
|
+
for atom in group[bead]: ### runs through atoms in fragments and centers on the cg bead
|
|
177
|
+
group[bead][atom]['coord']=group[bead][atom]['coord']-COM_vector
|
|
178
|
+
return group, COM_vector
|
|
179
|
+
|
|
180
|
+
def COM(mass, fragment):
|
|
181
|
+
#### returns center of mass of fragment
|
|
182
|
+
try:
|
|
183
|
+
if np.any(np.array(mass)[:,3]):
|
|
184
|
+
return np.average(np.array(mass)[:,:3], axis=0, weights=np.array(mass)[:,3])
|
|
185
|
+
except:
|
|
186
|
+
for bead in fragment:
|
|
187
|
+
print(bead, fragment[bead], '\n')
|
|
188
|
+
print(mass)
|
|
189
|
+
sys.exit('missing the mass one of the atoms in '+fragment[bead][1]['res_type'])
|
|
190
|
+
|
|
191
|
+
def rigid_fit(group, frag_mass, resid, cg):
|
|
192
|
+
#### rigid fits group to CG beads
|
|
193
|
+
rigid_mass_at = []
|
|
194
|
+
rigid_mass_cg = []
|
|
195
|
+
for bead in group:
|
|
196
|
+
rigid_mass_at+=frag_mass[bead]
|
|
197
|
+
rigid_mass_cg.append(cg[bead]['coord'])
|
|
198
|
+
rigid_mass_at = COM(rigid_mass_at, group)
|
|
199
|
+
rigid_mass_cg = np.mean(rigid_mass_cg, axis=0)
|
|
200
|
+
|
|
201
|
+
group, COM_vector = align_at_frag_to_CG_frag(rigid_mass_at, rigid_mass_cg, group)
|
|
202
|
+
at_frag_centers = {}
|
|
203
|
+
cg_frag_centers = {}
|
|
204
|
+
for bead in group:
|
|
205
|
+
cg_frag_centers[bead] = cg[bead]['coord']
|
|
206
|
+
at_frag_centers[bead] = COM(frag_mass[bead], bead)
|
|
207
|
+
at_frag_centers[bead] -= COM_vector
|
|
208
|
+
rigid_mass_cg, at_frag_centers, cg_frag_centers, group
|
|
209
|
+
return rigid_mass_cg, at_frag_centers, cg_frag_centers, group
|
|
210
|
+
|
|
211
|
+
## alignment end
|
|
212
|
+
|
|
213
|
+
## overlap checker
|
|
214
|
+
|
|
215
|
+
def overlapping_atoms(tree):
|
|
216
|
+
overlapped_ndx = tree.query_ball_tree(tree, r=g_var.args.ov)
|
|
217
|
+
overlapped_cut = [ndx for ndx in overlapped_ndx if len(ndx) >1]
|
|
218
|
+
overlapped_cut.sort()
|
|
219
|
+
overlapped=list(overlapped_cut for overlapped_cut,_ in itertools.groupby(overlapped_cut))
|
|
220
|
+
return overlapped
|
|
221
|
+
|
|
222
|
+
def check_atom_overlap(coordinates):
|
|
223
|
+
#### creates tree of atom coordinates
|
|
224
|
+
tree = cKDTree(coordinates)
|
|
225
|
+
overlapped = overlapping_atoms(tree)
|
|
226
|
+
#### runs through overlapping atoms and moves atom in a random diection until it is no longer overlapping
|
|
227
|
+
while len(overlapped) > 0:
|
|
228
|
+
for ndx_val, ndx in enumerate(overlapped):
|
|
229
|
+
if np.round((ndx_val/len(overlapped))*100,2).is_integer() and len(overlapped) > 30:
|
|
230
|
+
print('fixing '+str(len(overlapped))+' overlapped atoms: '+str(np.round((ndx_val/len(overlapped))*100,2))+' %', end='\r')
|
|
231
|
+
xyz_check = np.array([coordinates[ndx[0]][0]+np.random.uniform(-0.2, 0.2), coordinates[ndx[0]][1]+np.random.uniform(-0.2, 0.2),coordinates[ndx[0]][2]+np.random.uniform(-0.2, 0.2)])
|
|
232
|
+
while len(tree.query_ball_point(xyz_check, r=g_var.args.ov)) > 1:
|
|
233
|
+
xyz_check = np.array([coordinates[ndx[0]][0]+np.random.uniform(-0.2, 0.2), coordinates[ndx[0]][1]+np.random.uniform(-0.2, 0.2),coordinates[ndx[0]][2]+np.random.uniform(-0.2, 0.2)])
|
|
234
|
+
coordinates[ndx[0]]=xyz_check
|
|
235
|
+
tree = cKDTree(coordinates)
|
|
236
|
+
if len(overlapped) > 30:
|
|
237
|
+
print('{:<100}'.format(''), end='\r')
|
|
238
|
+
overlapped = overlapping_atoms(tree)
|
|
239
|
+
return coordinates
|
|
240
|
+
|
|
241
|
+
## overlap end
|
|
242
|
+
## get fragment information
|
|
243
|
+
|
|
244
|
+
def split_fragment_names(line, residue, resname):
|
|
245
|
+
bead = gen.strip_header(line)
|
|
246
|
+
group = g_var.res_top[resname]['GROUPS'][bead]
|
|
247
|
+
if group not in residue:
|
|
248
|
+
residue[group] = {}
|
|
249
|
+
if bead not in residue[group]:
|
|
250
|
+
residue[group][bead]={}
|
|
251
|
+
return residue, group, bead
|
|
252
|
+
|
|
253
|
+
def get_atomistic(frag_location, resname=False):
|
|
254
|
+
if not resname:
|
|
255
|
+
resname = frag_location.split('/')[-1][:-4]
|
|
256
|
+
#### read in atomistic fragments into dictionary
|
|
257
|
+
residue = {} ## a dictionary of bead in each residue eg residue[group][bead][atom number(1)][residue_name(ASP)/coordinates(coord)/atom name(C)/connectivity(2)/atom_mass(12)]
|
|
258
|
+
fragment_mass = {}
|
|
259
|
+
with open(frag_location, 'r') as pdb_input:
|
|
260
|
+
for line_nr, line in enumerate(pdb_input.readlines()):
|
|
261
|
+
if line.startswith('['):
|
|
262
|
+
residue, group, bead = split_fragment_names(line, residue, resname)
|
|
263
|
+
fragment_mass[bead]=[]
|
|
264
|
+
if line.startswith('ATOM'):
|
|
265
|
+
line_sep = gen.pdbatom(line) ## splits up pdb line
|
|
266
|
+
residue[group][bead][line_sep['atom_number']]={'coord':np.array([line_sep['x']*g_var.sf,line_sep['y']*g_var.sf,line_sep['z']*g_var.sf]),
|
|
267
|
+
'atom':line_sep['atom_name'],'resid':1, 'resid_ori':line_sep['residue_id'],'res_type':line_sep['residue_name'],
|
|
268
|
+
'frag_mass':1}
|
|
269
|
+
#### updates fragment mass
|
|
270
|
+
if not gen.is_hydrogen(line_sep['atom_name']):
|
|
271
|
+
if line_sep['atom_name'] in g_var.res_top[resname]['atom_masses']:
|
|
272
|
+
residue[group][bead][line_sep['atom_number']]['frag_mass']=g_var.res_top[resname]['atom_masses'][line_sep['atom_name']] ### updates atom masses with crude approximations
|
|
273
|
+
fragment_mass[bead].append([line_sep['x']*g_var.sf,line_sep['y']*g_var.sf,line_sep['z']*g_var.sf,g_var.res_top[resname]['atom_masses'][line_sep['atom_name']]])
|
|
274
|
+
else:
|
|
275
|
+
fragment_mass[bead].append([line_sep['x']*g_var.sf,line_sep['y']*g_var.sf,line_sep['z']*g_var.sf,1])
|
|
276
|
+
return residue, fragment_mass
|
|
277
|
+
|
|
278
|
+
def connectivity(cg, at_frag_centers, cg_frag_centers, group, group_number):
|
|
279
|
+
#### returns the connections between the atomistic and coarse grain beads
|
|
280
|
+
at_connection, cg_connection=[],[]
|
|
281
|
+
for bead in cg:
|
|
282
|
+
resname = cg[bead]['residue_name']
|
|
283
|
+
break
|
|
284
|
+
if resname in g_var.sorted_connect:
|
|
285
|
+
if len(g_var.sorted_connect[resname]) > 0:
|
|
286
|
+
for group_bead in group:
|
|
287
|
+
for bead_atom in group[group_bead]:
|
|
288
|
+
if bead_atom in g_var.sorted_connect[resname][int(group_number)]:
|
|
289
|
+
skip = False
|
|
290
|
+
for bead_connect in g_var.sorted_connect[resname][int(group_number)][bead_atom]:
|
|
291
|
+
if 'cg_connect' not in locals():
|
|
292
|
+
if bead_connect in cg:
|
|
293
|
+
cg_connect = [cg[bead_connect]['coord']]
|
|
294
|
+
else:
|
|
295
|
+
skip = True
|
|
296
|
+
else:
|
|
297
|
+
if bead_connect in cg:
|
|
298
|
+
cg_connect.append(cg[bead_connect]['coord'])
|
|
299
|
+
if not skip:
|
|
300
|
+
at_connection.append(group[group_bead][bead_atom]['coord'])
|
|
301
|
+
cg_connection.append(np.mean(np.array(cg_connect), axis=0))
|
|
302
|
+
if len(at_frag_centers) > 1:
|
|
303
|
+
for bead in at_frag_centers:
|
|
304
|
+
cg_connection.append(cg_frag_centers[bead])
|
|
305
|
+
at_connection.append(at_frag_centers[bead])
|
|
306
|
+
return at_connection, cg_connection
|
|
307
|
+
|
|
308
|
+
def get_rotation(cg_connect, at_connect, center, resname, group, cg_resid):
|
|
309
|
+
if len(at_connect) == len(cg_connect):
|
|
310
|
+
if len(cg_connect) == 0:
|
|
311
|
+
return gen.AnglesToRotMat([np.random.uniform(0, math.pi*2), np.random.uniform(0, math.pi*2), np.random.uniform(0, math.pi*2)])
|
|
312
|
+
else:
|
|
313
|
+
return kabsch_rotate(np.array(at_connect)-center, np.array(cg_connect)-center)
|
|
314
|
+
else:
|
|
315
|
+
print('atom connections: '+str(len(at_connect))+' does not match CG connections: '+str(len(cg_connect)))
|
|
316
|
+
sys.exit('residue number: '+str(cg_resid)+', residue type: '+str(resname)+', group: '+group)
|
|
317
|
+
|
|
318
|
+
def apply_rotations(atomistic_fragments,cg_resid, group_fit, center, xyz_rot_apply):
|
|
319
|
+
for bead in group_fit:
|
|
320
|
+
for atom in group_fit[bead]:
|
|
321
|
+
group_fit[bead][atom]['coord'] = rotate_atom(group_fit[bead][atom]['coord'], center, xyz_rot_apply)
|
|
322
|
+
atomistic_fragments[cg_resid][atom] = group_fit[bead][atom].copy()
|
|
323
|
+
return atomistic_fragments
|
|
324
|
+
|
|
325
|
+
### end fragment information
|
|
326
|
+
### linked residue connectivity start
|
|
327
|
+
|
|
328
|
+
def BB_connectivity(at_connections,cg_connections, cg_residues, at_residues, residue_number, BB_bead, resname):
|
|
329
|
+
con_atoms = {}
|
|
330
|
+
for atom in at_residues:
|
|
331
|
+
# resname = at_residues[atom]['res_type']
|
|
332
|
+
if at_residues[atom]['atom'] in g_var.res_top[resname]['CONNECT'][BB_bead]['atom']:
|
|
333
|
+
con_atoms[g_var.res_top[resname]['CONNECT'][BB_bead]['atom'].index(at_residues[atom]['atom'])]=atom
|
|
334
|
+
new_chain=False
|
|
335
|
+
for con in con_atoms:
|
|
336
|
+
con_resid = residue_number+g_var.res_top[resname]['CONNECT'][BB_bead]['dir'][con]
|
|
337
|
+
if con_resid in cg_residues:
|
|
338
|
+
xyz_cur = cg_residues[residue_number][BB_bead]['coord']
|
|
339
|
+
if g_var.res_top[resname]['CONNECT'][BB_bead]['Con_Bd'][con] in cg_residues[con_resid]:
|
|
340
|
+
xyz_con = cg_residues[con_resid][g_var.res_top[resname]['CONNECT'][BB_bead]['Con_Bd'][con]]['coord']
|
|
341
|
+
if gen.calculate_distance(xyz_con, xyz_cur) < 6:
|
|
342
|
+
cg_connections.append(xyz_con)
|
|
343
|
+
at_connections.append(at_residues[con_atoms[con]]['coord'])
|
|
344
|
+
else:
|
|
345
|
+
if g_var.res_top[resname]['CONNECT'][BB_bead]['dir'][con] > 0:
|
|
346
|
+
new_chain=True
|
|
347
|
+
else:
|
|
348
|
+
if g_var.res_top[resname]['CONNECT'][BB_bead]['dir'][con] > 0:
|
|
349
|
+
new_chain=True
|
|
350
|
+
else:
|
|
351
|
+
if g_var.res_top[resname]['CONNECT'][BB_bead]['dir'][con] > 0:
|
|
352
|
+
new_chain=True
|
|
353
|
+
return at_connections,cg_connections, new_chain
|
|
354
|
+
|
|
355
|
+
################################################################### Merged system
|
|
356
|
+
|
|
357
|
+
def merge_indivdual_chain_pdbs(file, end, res_type):
|
|
358
|
+
#### reads in each chain into merge list
|
|
359
|
+
merge, merged_coords = [],[]
|
|
360
|
+
count = 0
|
|
361
|
+
restraint_count = -1
|
|
362
|
+
for chain in range(0,g_var.system[res_type]):
|
|
363
|
+
merge_temp = []
|
|
364
|
+
if os.path.exists(file+'_'+str(chain)+end):
|
|
365
|
+
with open(file+'_'+str(chain)+end, 'r') as pdb_input:
|
|
366
|
+
merge_temp += read_in.filter_input(pdb_input.readlines(), False)
|
|
367
|
+
else:
|
|
368
|
+
sys.exit('cannot find chain: '+file+'_'+str(chain)+end)
|
|
369
|
+
if res_type+'_aligned' in file:
|
|
370
|
+
count, restraint_count = at_mod_p.create_disres(merge_temp, chain, file, count, restraint_count)
|
|
371
|
+
merge, merge_coords = fix_chirality(merge,merge_temp,merged_coords, res_type)
|
|
372
|
+
if res_type+'_aligned' not in file:
|
|
373
|
+
coords, index_conversion = index_conversion_generate(merge, merge_coords)
|
|
374
|
+
if 'aligned' in file.split('/')[-1]:
|
|
375
|
+
write_pdb(merge, merge_coords, {}, g_var.working_dir+'PROTEIN/PROTEIN_aligned_merged.pdb')
|
|
376
|
+
else:
|
|
377
|
+
write_pdb(merge, coords,index_conversion, g_var.working_dir+res_type+'/'+res_type+'_de_novo_merged.pdb')
|
|
378
|
+
|
|
379
|
+
def index_conversion_generate(merge, merge_coords):
|
|
380
|
+
index_conversion = {}
|
|
381
|
+
coords = []
|
|
382
|
+
for at_val, atom in enumerate(merge):
|
|
383
|
+
if not atom['atom_name'].startswith('M'):
|
|
384
|
+
index_conversion[at_val] = len(coords)
|
|
385
|
+
coords.append(merge_coords[at_val])
|
|
386
|
+
coords = check_atom_overlap(coords)
|
|
387
|
+
return coords, index_conversion
|
|
388
|
+
|
|
389
|
+
def write_pdb(merge, merge_coords, index_conversion, write_file):
|
|
390
|
+
#### creates merged pdb and writes chains to it
|
|
391
|
+
if not os.path.exists(write_file):
|
|
392
|
+
pdb_output=gen.create_pdb(write_file)
|
|
393
|
+
atom_counter=0
|
|
394
|
+
for line_val, line in enumerate(merge):
|
|
395
|
+
if line_val in index_conversion:
|
|
396
|
+
x, y, z = gen.trunc_coord(merge_coords[index_conversion[line_val]])
|
|
397
|
+
else:
|
|
398
|
+
if 'coord' in line:
|
|
399
|
+
x, y, z = gen.trunc_coord(line['coord'])
|
|
400
|
+
else:
|
|
401
|
+
x, y, z = gen.trunc_coord([line['x'],line['y'],line['z']])
|
|
402
|
+
if atom_counter >= 99_999:
|
|
403
|
+
atom_counter=1
|
|
404
|
+
else:
|
|
405
|
+
atom_counter+=1
|
|
406
|
+
pdb_output.write(g_var.pdbline%((atom_counter, line['atom_name'], line['residue_name'],' ',line['residue_id'],\
|
|
407
|
+
x,y,z,1,0))+'\n')
|
|
408
|
+
pdb_output.close()
|
|
409
|
+
|
|
410
|
+
def merge_system_pdbs(protein):
|
|
411
|
+
os.chdir(g_var.merged_directory)
|
|
412
|
+
#### create merged pdb
|
|
413
|
+
if not os.path.exists(g_var.merged_directory+'merged_cg2at'+protein+'.pdb'):
|
|
414
|
+
merge=[]
|
|
415
|
+
merge_coords=[]
|
|
416
|
+
#### run through every residue type in cg_residues
|
|
417
|
+
done = []
|
|
418
|
+
if 'novo' in protein:
|
|
419
|
+
print('checking for atom overlap in : '+protein[1:])
|
|
420
|
+
for segment, residue_type in enumerate(g_var.system):
|
|
421
|
+
if residue_type not in done:
|
|
422
|
+
if residue_type not in ['PROTEIN', 'OTHER']:
|
|
423
|
+
start_num = len(merge_coords)
|
|
424
|
+
merge, merge_coords = read_in_merged_pdbs(merge, merge_coords,
|
|
425
|
+
g_var.working_dir+residue_type+'/'+residue_type+'_merged.pdb')
|
|
426
|
+
g_var.np_blocks[residue_type]=[start_num,len(merge_coords)]
|
|
427
|
+
elif residue_type == 'OTHER':
|
|
428
|
+
merge, merge_coords = read_in_merged_pdbs(merge, merge_coords,
|
|
429
|
+
g_var.working_dir+residue_type+'/'+residue_type+'_de_novo_merged.pdb')
|
|
430
|
+
elif residue_type == 'PROTEIN':
|
|
431
|
+
merge, merge_coords = read_in_merged_pdbs(merge, merge_coords,
|
|
432
|
+
g_var.working_dir+residue_type+'/'+residue_type+protein+'_merged.pdb')
|
|
433
|
+
done.append(residue_type)
|
|
434
|
+
index_conversion = {}
|
|
435
|
+
if 'novo' in protein:
|
|
436
|
+
coords, index_conversion = index_conversion_generate(merge, merge_coords)
|
|
437
|
+
write_pdb(merge, coords, index_conversion, g_var.merged_directory+'merged_cg2at'+protein+'.pdb')
|
|
438
|
+
else:
|
|
439
|
+
write_pdb(merge, merge_coords, {}, g_var.merged_directory+'merged_cg2at'+protein+'.pdb')
|
|
440
|
+
|
|
441
|
+
def read_in_merged_pdbs(merge, merge_coords, location):
|
|
442
|
+
if os.path.exists(location):
|
|
443
|
+
#### opens pdb files and writes straight to merged_cg2at pdb
|
|
444
|
+
with open(location, 'r') as pdb_input:
|
|
445
|
+
read_in_atoms = read_in.filter_input(pdb_input.readlines(), False)
|
|
446
|
+
merge_coords += [[line_sep['x'],line_sep['y'],line_sep['z']] for line_sep in read_in_atoms ]
|
|
447
|
+
return merge+read_in_atoms, merge_coords
|
|
448
|
+
else:
|
|
449
|
+
sys.exit('cannot find minimised residue: \n'+ location)
|
|
450
|
+
|
|
451
|
+
def check_overlap_chain(chain, input,res_type):
|
|
452
|
+
if not os.path.exists(g_var.working_dir+res_type+'/'+res_type+'_'+input+str(chain)+'_gmx_checked.pdb'):
|
|
453
|
+
lines, coords = read_in_merged_pdbs([], [], res_type+'_'+input+str(chain)+'_gmx.pdb')
|
|
454
|
+
if res_type == 'PROTEIN':
|
|
455
|
+
coords = at_mod_p.correct_amide_h(lines, coords)
|
|
456
|
+
|
|
457
|
+
coords, index_conversion = index_conversion_generate(lines, coords)
|
|
458
|
+
write_pdb(lines, coords, index_conversion, g_var.working_dir+res_type+'/'+res_type+'_'+input+str(chain)+'_gmx_checked.pdb')
|
|
459
|
+
|
|
460
|
+
## fix chirality errors
|
|
461
|
+
|
|
462
|
+
def fetch_chiral_coord(merge_temp, residue_type):
|
|
463
|
+
chiral_atoms={}
|
|
464
|
+
coord=[]
|
|
465
|
+
for atom in range(len(merge_temp)):
|
|
466
|
+
if residue_type in ['PROTEIN', 'OTHER']:
|
|
467
|
+
resname = gen.check_alternate_resname(merge_temp[atom]['residue_name'])
|
|
468
|
+
else:
|
|
469
|
+
resname = gen.check_alternate_resname(residue_type)
|
|
470
|
+
if len(g_var.res_top[resname]['CHIRAL']['atoms']) > 0:
|
|
471
|
+
if merge_temp[atom]['atom_name'] in g_var.res_top[resname]['CHIRAL']['atoms']:
|
|
472
|
+
if merge_temp[atom]['residue_id'] not in chiral_atoms:
|
|
473
|
+
chiral_atoms[merge_temp[atom]['residue_id']]={}
|
|
474
|
+
chiral_atoms[merge_temp[atom]['residue_id']][merge_temp[atom]['atom_name']]=atom
|
|
475
|
+
coord.append(np.array([merge_temp[atom]['x'],merge_temp[atom]['y'],merge_temp[atom]['z']]))
|
|
476
|
+
return chiral_atoms, coord
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
def get_atom_move(merge_temp, resname, residue, chiral_group, chiral_atoms):
|
|
480
|
+
stat = merge_temp[chiral_atoms[residue][chiral_group]].copy()
|
|
481
|
+
atom_move = {'stat':np.array([stat['x'],stat['y'],stat['z']]), 'm':'', 'c1':'', 'c2':'', 'c3':''}
|
|
482
|
+
for chir_atom in atom_move:
|
|
483
|
+
if chir_atom != 'stat':
|
|
484
|
+
test = merge_temp[chiral_atoms[residue][g_var.res_top[resname]['CHIRAL'][chiral_group][chir_atom]]].copy()
|
|
485
|
+
atom_move[chir_atom]= np.array([test['x'],test['y'],test['z']])
|
|
486
|
+
if gen.calculate_distance(atom_move['stat'], atom_move[chir_atom]) > 10:
|
|
487
|
+
atom_move[chir_atom] = np.array(read_in.brute_mic(atom_move['stat'],atom_move[chir_atom]))
|
|
488
|
+
return atom_move
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def fix_chirality(merge, merge_temp, merged_coords, residue_type):
|
|
492
|
+
#### fixes chiral groups
|
|
493
|
+
chiral_atoms, coord = fetch_chiral_coord(merge_temp, residue_type)
|
|
494
|
+
for residue in chiral_atoms:
|
|
495
|
+
if residue_type in ['PROTEIN', 'OTHER']:
|
|
496
|
+
for atom in chiral_atoms[residue]:
|
|
497
|
+
resname = merge_temp[chiral_atoms[residue][atom]]['residue_name']
|
|
498
|
+
resname = gen.check_alternate_resname(resname)
|
|
499
|
+
break
|
|
500
|
+
else:
|
|
501
|
+
resname = gen.check_alternate_resname(residue_type)
|
|
502
|
+
|
|
503
|
+
for chiral_group in g_var.res_top[resname]['CHIRAL']:
|
|
504
|
+
if chiral_group != 'atoms':
|
|
505
|
+
atom_move = get_atom_move(merge_temp, resname, residue, chiral_group, chiral_atoms)
|
|
506
|
+
|
|
507
|
+
S_M = atom_move['m'] - atom_move['stat']
|
|
508
|
+
rotation = align_to_vector(S_M, [0,0,1])
|
|
509
|
+
c1_coord = (atom_move['c1'] - atom_move['stat']).dot(rotation)
|
|
510
|
+
c2_coord = (atom_move['c2'] - atom_move['stat']).dot(rotation)
|
|
511
|
+
c3_coord = (atom_move['c3'] - atom_move['stat']).dot(rotation)
|
|
512
|
+
|
|
513
|
+
if gen.angle_clockwise(c1_coord[0:2], c2_coord[0:2]) > gen.angle_clockwise(c1_coord[0:2], c3_coord[0:2]):
|
|
514
|
+
for ax_val, axis in enumerate(['x', 'y', 'z']):
|
|
515
|
+
merge_temp[chiral_atoms[residue][g_var.res_top[resname]['CHIRAL'][chiral_group]['m']]][axis] = merge_temp[chiral_atoms[residue][g_var.res_top[resname]['CHIRAL'][chiral_group]['m']]][axis] - (3*S_M[ax_val])
|
|
516
|
+
merge_temp[chiral_atoms[residue][chiral_group]][axis] = merge_temp[chiral_atoms[residue][chiral_group]][axis] - (S_M[ax_val])
|
|
517
|
+
coord[chiral_atoms[residue][g_var.res_top[resname]['CHIRAL'][chiral_group]['m']]] -= (2*S_M) #move_coord -
|
|
518
|
+
coord[chiral_atoms[residue][chiral_group]] -= (0.25*S_M)
|
|
519
|
+
merge+=merge_temp
|
|
520
|
+
merged_coords+=coord
|
|
521
|
+
return merge, merged_coords
|
|
522
|
+
|
|
523
|
+
def get_chiral_non_carbonyl(at):
|
|
524
|
+
chiral = {}
|
|
525
|
+
for atom in at:
|
|
526
|
+
if at[atom]['atom'] in g_var.res_top[at[atom]['res_type']]['CHIRAL']['atoms']:
|
|
527
|
+
chiral[at[atom]['atom']] = atom
|
|
528
|
+
return chiral
|
|
529
|
+
|
|
530
|
+
def correct_chiral_atoms(at, chiral):
|
|
531
|
+
for chiral_group in g_var.res_top[at[1]['res_type']]['CHIRAL']:
|
|
532
|
+
if chiral_group != 'atoms':
|
|
533
|
+
atom_list = [chiral[chiral_group]]
|
|
534
|
+
for chiral_atoms in ['c1','c2','c3']:
|
|
535
|
+
atom_list.append(chiral[g_var.res_top[at[1]['res_type']]['CHIRAL'][chiral_group][chiral_atoms]])
|
|
536
|
+
cross_vector_chiral = find_cross_vector( [at[atom_list[3]]['coord'], at[atom_list[2]]['coord'], at[atom_list[1]]['coord']])
|
|
537
|
+
norm_vector_chiral = noramlised_vector(at[chiral[g_var.res_top[at[1]['res_type']]['CHIRAL'][chiral_group]['m']]]['coord'], at[atom_list[0]]['coord'])
|
|
538
|
+
if not np.dot(cross_vector_chiral, norm_vector_chiral) > 0.5:
|
|
539
|
+
if g_var.res_top[at[1]['res_type']]['CHIRAL'][chiral_group]['m'] in chiral:
|
|
540
|
+
at[atom_list[0]]['coord'] = at[atom_list[0]]['coord'] + cross_vector_chiral*0.5
|
|
541
|
+
m = chiral[g_var.res_top[at[1]['res_type']]['CHIRAL'][chiral_group]['m']]
|
|
542
|
+
at[m]['coord'] = at[m]['coord'] + cross_vector_chiral*2
|
|
543
|
+
return at
|
|
544
|
+
|
|
545
|
+
## chirality end
|
|
546
|
+
## hydrogen orientaion checker
|
|
547
|
+
|
|
548
|
+
def check_hydrogens(residue):
|
|
549
|
+
#### finds the connecting carbons and their associated carbons [carbon atom, hydrogen ref number, connecting ref number]
|
|
550
|
+
for atom_num, atom in enumerate(residue):
|
|
551
|
+
resname=residue[atom]['res_type']
|
|
552
|
+
break
|
|
553
|
+
for atom in g_var.hydrogen[resname]:
|
|
554
|
+
h_coord = []
|
|
555
|
+
for group in g_var.sorted_connect[resname]:
|
|
556
|
+
if atom in g_var.sorted_connect[resname][group]:
|
|
557
|
+
for hydrogen in g_var.hydrogen[resname][atom]:
|
|
558
|
+
h_coord.append(residue[hydrogen]['coord'])
|
|
559
|
+
h_com=np.mean(np.array(h_coord), axis=0)
|
|
560
|
+
for heavy_bond in g_var.heavy_bond[resname][atom]:
|
|
561
|
+
for group_check in g_var.sorted_connect[resname]:
|
|
562
|
+
if heavy_bond in g_var.sorted_connect[resname][group_check] and group_check != group:
|
|
563
|
+
skip = False
|
|
564
|
+
if heavy_bond in residue:
|
|
565
|
+
con_heavy_atom = heavy_bond
|
|
566
|
+
con_heavy_atom_co = residue[con_heavy_atom]['coord']
|
|
567
|
+
else:
|
|
568
|
+
skip = True
|
|
569
|
+
if not skip:
|
|
570
|
+
#### vector between H COM and bonded carbon
|
|
571
|
+
vector=np.array([h_com[0]-residue[atom]['coord'][0],h_com[1]-residue[atom]['coord'][1],h_com[2]-residue[atom]['coord'][2]])
|
|
572
|
+
h_com_f=h_com+vector*2
|
|
573
|
+
d1 = gen.calculate_distance(h_com, con_heavy_atom_co)
|
|
574
|
+
d2 = gen.calculate_distance(h_com_f, con_heavy_atom_co)
|
|
575
|
+
if d2 < d1:
|
|
576
|
+
for h_at in g_var.hydrogen[resname][atom]:
|
|
577
|
+
residue[h_at]['coord']=residue[h_at]['coord']-vector*2
|
|
578
|
+
return residue
|
|
579
|
+
|
|
580
|
+
## check for threaded lipids
|
|
581
|
+
def check_ringed_lipids(protein):
|
|
582
|
+
print('Checking for ringed lipids')
|
|
583
|
+
if not os.path.exists(g_var.merged_directory+'checked_ringed_lipid_de_novo.pdb'):
|
|
584
|
+
if not os.path.exists(g_var.merged_directory+'merged_cg2at_threaded.pdb'):
|
|
585
|
+
os.chdir(g_var.merged_directory)
|
|
586
|
+
merge, merge_coords = read_in_merged_pdbs([], [], protein)
|
|
587
|
+
ringed=False
|
|
588
|
+
lipid_atoms = []
|
|
589
|
+
with open(g_var.merged_directory+'threaded_lipids.dat', 'w') as ring_ouput:
|
|
590
|
+
for at_val, atom in enumerate(merge):
|
|
591
|
+
resname = get_np_resname(at_val)
|
|
592
|
+
if resname in g_var.np_residues:
|
|
593
|
+
offset = fetch_start_of_residue_np(at_val, resname)
|
|
594
|
+
if atom['atom_number']-offset in g_var.heavy_bond[resname]:
|
|
595
|
+
for at_bond in g_var.heavy_bond[resname][atom['atom_number']-offset]:
|
|
596
|
+
at_bond -=1
|
|
597
|
+
if merge[at_bond+offset]['atom_number'] > merge[at_val]['atom_number']:
|
|
598
|
+
merge[at_bond+offset]['x'], merge[at_bond+offset]['y'], merge[at_bond+offset]['z'] = np.array(read_in.brute_mic(merge_coords[at_val],merge_coords[at_bond+offset]))
|
|
599
|
+
merge_coords[at_bond+offset] = merge[at_bond+offset]['x'], merge[at_bond+offset]['y'], merge[at_bond+offset]['z']
|
|
600
|
+
dist = gen.calculate_distance(merge_coords[at_val], merge_coords[at_bond+offset])
|
|
601
|
+
if 2 < dist < 6:
|
|
602
|
+
lipid_atoms.append([at_val, at_bond+offset, (np.array(merge_coords[at_val])+np.array(merge_coords[at_bond+offset]))/2])
|
|
603
|
+
ring_ouput.write('{0:6}{1:6}{2:2}{3:4}{4:2}{5:7}{6:5}{7:5}{8:5}{9:5}{10:5}{11:5}\n'.format(
|
|
604
|
+
'distance: ',str(np.round(dist,2)),'residue: ', merge[at_val]['residue_name'], merge[at_val]['residue_id'],
|
|
605
|
+
' atom_1: ', merge[at_val]['atom_name'],
|
|
606
|
+
'atom_2: ', merge[at_bond+offset]['atom_name'], 'rough line num: ', at_val, at_bond+offset))
|
|
607
|
+
ringed = True
|
|
608
|
+
if ringed or os.path.exists(g_var.merged_directory+'merged_cg2at_threaded.pdb'):
|
|
609
|
+
print('Found '+str(len(lipid_atoms))+' abnormal bonds, now attempting to fix.')
|
|
610
|
+
print('See this file for a complete list: '+g_var.merged_directory+'threaded_lipids.dat')
|
|
611
|
+
fix_threaded_lipids(lipid_atoms, merge, merge_coords)
|
|
612
|
+
else:
|
|
613
|
+
gen.file_copy_and_check(g_var.merged_directory+'MIN/merged_cg2at_de_novo_minimised.pdb', g_var.merged_directory+'checked_ringed_lipid_de_novo.pdb')
|
|
614
|
+
|
|
615
|
+
def fetch_start_of_residue(at, merge):
|
|
616
|
+
count = at
|
|
617
|
+
while True:
|
|
618
|
+
if merge[count]['residue_id'] != merge[at]['residue_id']:
|
|
619
|
+
count+=1
|
|
620
|
+
return count
|
|
621
|
+
else:
|
|
622
|
+
count-=1
|
|
623
|
+
|
|
624
|
+
def fetch_start_of_residue_np(atom, resname):
|
|
625
|
+
prev=g_var.np_blocks[resname][0]
|
|
626
|
+
range_np_block = g_var.np_blocks[resname][1]-g_var.np_blocks[resname][0]
|
|
627
|
+
for range_np_block_ind in range(g_var.np_blocks[resname][0],g_var.np_blocks[resname][1]+1, int(range_np_block/g_var.system[resname])):
|
|
628
|
+
if prev <= atom < range_np_block_ind:
|
|
629
|
+
return prev
|
|
630
|
+
prev = range_np_block_ind
|
|
631
|
+
|
|
632
|
+
def get_np_resname(atom):
|
|
633
|
+
for res_check in g_var.np_blocks:
|
|
634
|
+
if g_var.np_blocks[res_check][0] <= atom < g_var.np_blocks[res_check][1]:
|
|
635
|
+
return res_check
|
|
636
|
+
|
|
637
|
+
def fix_threaded_lipids(lipid_atoms, merge, merge_coords):
|
|
638
|
+
if not os.path.exists(g_var.merged_directory+'merged_cg2at_threaded.pdb'):
|
|
639
|
+
tree = cKDTree(merge_coords)
|
|
640
|
+
for threaded in lipid_atoms:
|
|
641
|
+
resname = get_np_resname(threaded[0])
|
|
642
|
+
|
|
643
|
+
atoms = tree.query_ball_point(threaded[2], r=3)
|
|
644
|
+
for at in atoms:
|
|
645
|
+
if merge[at]['residue_id'] != merge[threaded[0]]['residue_id']:
|
|
646
|
+
P_count = fetch_start_of_residue(at, merge)
|
|
647
|
+
break
|
|
648
|
+
|
|
649
|
+
NP_count = fetch_start_of_residue_np(threaded[0], resname)
|
|
650
|
+
bb = []
|
|
651
|
+
if 'P_count' not in locals():
|
|
652
|
+
sys.exit('There is an issue with the bond length detection')
|
|
653
|
+
for at in merge[P_count:]:
|
|
654
|
+
if at['residue_id'] != merge[P_count]['residue_id']:
|
|
655
|
+
break
|
|
656
|
+
if at['atom_name'] in g_var.res_top[at['residue_name']]['ATOMS']:
|
|
657
|
+
bb.append([at['x'], at['y'], at['z']])
|
|
658
|
+
bb = np.mean(np.array(bb), axis=0)
|
|
659
|
+
BB_M3 = (threaded[2]-bb)/np.linalg.norm((threaded[2]-bb))
|
|
660
|
+
|
|
661
|
+
for heavy_atom in threaded[:2]:
|
|
662
|
+
merge_coords[heavy_atom] += BB_M3*3
|
|
663
|
+
merge[heavy_atom]['x'], merge[heavy_atom]['y'], merge[heavy_atom]['z'] = merge_coords[heavy_atom]
|
|
664
|
+
for hydrogen in g_var.hydrogen[resname][heavy_atom-NP_count+1]:
|
|
665
|
+
merge_coords[NP_count+hydrogen-1] += BB_M3*3
|
|
666
|
+
merge[NP_count+hydrogen-1]['x'], merge[NP_count+hydrogen-1]['y'], merge[NP_count+hydrogen-1]['z'] = merge_coords[NP_count+hydrogen-1]
|
|
667
|
+
|
|
668
|
+
coords, index_conversion = index_conversion_generate(merge, merge_coords)
|
|
669
|
+
write_pdb(merge, coords, index_conversion, g_var.merged_directory+'merged_cg2at_threaded.pdb')
|
|
670
|
+
|
|
671
|
+
if not os.path.exists(g_var.merged_directory+'MIN/merged_cg2at_threaded_minimised.pdb'):
|
|
672
|
+
gro.minimise_merged_pdbs('_threaded')
|
|
673
|
+
gen.file_copy_and_check(g_var.merged_directory+'MIN/merged_cg2at_threaded_minimised.pdb', g_var.merged_directory+'checked_ringed_lipid_de_novo.pdb')
|