packmol-memgen-minimal 1.1.16__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.
- packmol_memgen/__init__.py +2 -0
- packmol_memgen/__version__.py +34 -0
- packmol_memgen/data/LICENSE.Apache-2.0 +201 -0
- packmol_memgen/data/extra_solvents.lib +789 -0
- packmol_memgen/data/frcmod.lipid_ext +97 -0
- packmol_memgen/data/frcmod.solvents +129 -0
- packmol_memgen/data/insane_lipids.txt +138 -0
- packmol_memgen/data/insane_solvents.txt +45 -0
- packmol_memgen/data/leaprc.extra_solvents +42 -0
- packmol_memgen/data/leaprc.lipid_ext +48 -0
- packmol_memgen/data/lipid_ext.lib +12312 -0
- packmol_memgen/data/martini_v3.0.0.itp +356605 -0
- packmol_memgen/data/memgen.parm +4082 -0
- packmol_memgen/data/pdbs.tar.gz +0 -0
- packmol_memgen/data/solvent.parm +14 -0
- packmol_memgen/example/example.sh +31 -0
- packmol_memgen/lib/__init__.py +0 -0
- packmol_memgen/lib/amber.py +77 -0
- packmol_memgen/lib/charmmlipid2amber/__init__.py +0 -0
- packmol_memgen/lib/charmmlipid2amber/charmmlipid2amber.csv +7164 -0
- packmol_memgen/lib/charmmlipid2amber/charmmlipid2amber.py +225 -0
- packmol_memgen/lib/pdbremix/LICENSE +21 -0
- packmol_memgen/lib/pdbremix/__init__.py +0 -0
- packmol_memgen/lib/pdbremix/_version.py +1 -0
- packmol_memgen/lib/pdbremix/amber.py +1103 -0
- packmol_memgen/lib/pdbremix/asa.py +227 -0
- packmol_memgen/lib/pdbremix/data/aminoacid.pdb +334 -0
- packmol_memgen/lib/pdbremix/data/binaries.json +26 -0
- packmol_memgen/lib/pdbremix/data/charmm22.parameter +2250 -0
- packmol_memgen/lib/pdbremix/data/charmm22.topology +1635 -0
- packmol_memgen/lib/pdbremix/data/color_b.py +682 -0
- packmol_memgen/lib/pdbremix/data/hin.lib +130 -0
- packmol_memgen/lib/pdbremix/data/hydroxide.lib +88 -0
- packmol_memgen/lib/pdbremix/data/make_chi.py +92 -0
- packmol_memgen/lib/pdbremix/data/opls.parameter +1108 -0
- packmol_memgen/lib/pdbremix/data/opls.topology +1869 -0
- packmol_memgen/lib/pdbremix/data/phd.frcmod +82 -0
- packmol_memgen/lib/pdbremix/data/phd.leaprc +4 -0
- packmol_memgen/lib/pdbremix/data/phd.prepin +35 -0
- packmol_memgen/lib/pdbremix/data/template.pdb +334 -0
- packmol_memgen/lib/pdbremix/data/znb.frcmod +24 -0
- packmol_memgen/lib/pdbremix/data/znb.leaprc +7 -0
- packmol_memgen/lib/pdbremix/data/znb.lib +69 -0
- packmol_memgen/lib/pdbremix/data.py +264 -0
- packmol_memgen/lib/pdbremix/fetch.py +102 -0
- packmol_memgen/lib/pdbremix/force.py +627 -0
- packmol_memgen/lib/pdbremix/gromacs.py +978 -0
- packmol_memgen/lib/pdbremix/lib/__init__.py +0 -0
- packmol_memgen/lib/pdbremix/lib/docopt.py +579 -0
- packmol_memgen/lib/pdbremix/lib/pyqcprot.py +305 -0
- packmol_memgen/lib/pdbremix/namd.py +1078 -0
- packmol_memgen/lib/pdbremix/pdbatoms.py +543 -0
- packmol_memgen/lib/pdbremix/pdbtext.py +120 -0
- packmol_memgen/lib/pdbremix/protein.py +311 -0
- packmol_memgen/lib/pdbremix/pymol.py +480 -0
- packmol_memgen/lib/pdbremix/rmsd.py +203 -0
- packmol_memgen/lib/pdbremix/simulate.py +420 -0
- packmol_memgen/lib/pdbremix/spacehash.py +73 -0
- packmol_memgen/lib/pdbremix/trajectory.py +286 -0
- packmol_memgen/lib/pdbremix/util.py +273 -0
- packmol_memgen/lib/pdbremix/v3.py +16 -0
- packmol_memgen/lib/pdbremix/v3array.py +482 -0
- packmol_memgen/lib/pdbremix/v3numpy.py +350 -0
- packmol_memgen/lib/pdbremix/volume.py +155 -0
- packmol_memgen/lib/utils.py +1017 -0
- packmol_memgen/main.py +2827 -0
- packmol_memgen_minimal-1.1.16.dist-info/METADATA +664 -0
- packmol_memgen_minimal-1.1.16.dist-info/RECORD +71 -0
- packmol_memgen_minimal-1.1.16.dist-info/WHEEL +4 -0
- packmol_memgen_minimal-1.1.16.dist-info/entry_points.txt +2 -0
- packmol_memgen_minimal-1.1.16.dist-info/licenses/LICENSE +338 -0
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
__doc__ = """
|
|
4
|
+
|
|
5
|
+
Intrface to PYMOL with useful pre-processing.
|
|
6
|
+
|
|
7
|
+
As well various functions use PYMOL as an image generator of
|
|
8
|
+
protein structures.
|
|
9
|
+
|
|
10
|
+
A key concept in this module is that a viewing frame can be
|
|
11
|
+
defined by two residues:
|
|
12
|
+
|
|
13
|
+
1. The center residue defines the viewing frame where the center
|
|
14
|
+
residue is in the middle of the screen directly over the
|
|
15
|
+
center of the system.
|
|
16
|
+
2. The top residue defines the z-rotation of the above frame such
|
|
17
|
+
that the top residue is directly above the center residue
|
|
18
|
+
in the viewing frame.
|
|
19
|
+
|
|
20
|
+
This can be used to define reasonably close viewing frames to
|
|
21
|
+
any conceivable viewing frame.Several of the functions thus take
|
|
22
|
+
center_res and top_res parameters to define the viewing frame of
|
|
23
|
+
reference in PYMOL.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
import os
|
|
27
|
+
from . import pdbatoms
|
|
28
|
+
from . import v3
|
|
29
|
+
from . import util
|
|
30
|
+
from . import data
|
|
31
|
+
from . import pdbtext
|
|
32
|
+
from . import protein
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_pymol_id_from_res_tag(tag):
|
|
36
|
+
chain_id, res_num, insert = pdbatoms.split_tag(tag)
|
|
37
|
+
if chain_id == " ":
|
|
38
|
+
return "resi %d" % res_num
|
|
39
|
+
else:
|
|
40
|
+
return "(chain %s and resi %d%s)" % (chain_id, res_num, insert)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# Functions to transform PDB before rendering in PYMOL
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_scale_max(max_bfactor, upper_bfactor):
|
|
47
|
+
scale_max = 4.0
|
|
48
|
+
if max_bfactor is not None and upper_bfactor is not None:
|
|
49
|
+
if max_bfactor < upper_bfactor:
|
|
50
|
+
scale_max *= max_bfactor / upper_bfactor
|
|
51
|
+
if scale_max < 1:
|
|
52
|
+
scale_max = 1
|
|
53
|
+
return scale_max
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def add_fake_water_atom(soup, res_type, bfactor):
|
|
57
|
+
dummy_atom = pdbatoms.Atom()
|
|
58
|
+
dummy_atom.pos = soup.atoms()[0].pos.copy()
|
|
59
|
+
dummy_atom.type = "O"
|
|
60
|
+
dummy_atom.bfactor = bfactor
|
|
61
|
+
dummy_res = pdbatoms.Residue(res_type, '', 9999)
|
|
62
|
+
dummy_res.insert_atom(dummy_atom)
|
|
63
|
+
soup.append_residue(dummy_res)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def rescale_positive_bfactors_pdb(pdb, lower_bfactor, upper_bfactor):
|
|
67
|
+
"""
|
|
68
|
+
Returns max_bfactor after rescale (needed for worm
|
|
69
|
+
calculation)
|
|
70
|
+
"""
|
|
71
|
+
soup = pdbatoms.Soup(pdb)
|
|
72
|
+
bfactors = [a.bfactor for a in soup.atoms()]
|
|
73
|
+
# cut-off max_values
|
|
74
|
+
if upper_bfactor:
|
|
75
|
+
bfactors = [upper_bfactor if b > upper_bfactor else b
|
|
76
|
+
for b in bfactors]
|
|
77
|
+
# will delete later within pymol script
|
|
78
|
+
add_fake_water_atom(soup, 'XXX', upper_bfactor)
|
|
79
|
+
# cut-off below min_val to zero
|
|
80
|
+
if lower_bfactor:
|
|
81
|
+
for j in range(len(bfactors)):
|
|
82
|
+
bfactors = [0 if b < lower_bfactor else b for b in bfactors]
|
|
83
|
+
for a, bfactor in zip(soup.atoms(), bfactors):
|
|
84
|
+
a.bfactor = bfactor
|
|
85
|
+
new_pdb = util.fname_variant(pdb)
|
|
86
|
+
soup.write_pdb(new_pdb)
|
|
87
|
+
return new_pdb, max(bfactors)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def rescale_positive_bfactors_of_pdbs(pdbs, lower_bfactor, upper_bfactor):
|
|
91
|
+
"Returns list of new_pdbs, and max_bfactor"
|
|
92
|
+
max_bfactor = 0
|
|
93
|
+
new_pdbs = []
|
|
94
|
+
for pdb in pdbs:
|
|
95
|
+
new_pdb, this_max_bfactor = rescale_positive_bfactors_pdb(
|
|
96
|
+
pdb, lower_bfactor, upper_bfactor)
|
|
97
|
+
if this_max_bfactor > max_bfactor:
|
|
98
|
+
max_bfactor = this_max_bfactor
|
|
99
|
+
new_pdbs.append(new_pdb)
|
|
100
|
+
return new_pdbs, max_bfactor
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def rescale_positive_negative_bfactors_pdb(
|
|
104
|
+
pdb, lower_bfactor, upper_bfactor):
|
|
105
|
+
"""
|
|
106
|
+
Returns max_bfactor after rescale
|
|
107
|
+
"""
|
|
108
|
+
soup = pdbatoms.Soup(pdb)
|
|
109
|
+
bfactors = [a.bfactor for a in soup.atoms()]
|
|
110
|
+
if upper_bfactor is None:
|
|
111
|
+
upper_bfactor = max(bfactors)
|
|
112
|
+
# cut-off max_values
|
|
113
|
+
if upper_bfactor:
|
|
114
|
+
for j in range(len(bfactors)):
|
|
115
|
+
if bfactors[j] > upper_bfactor:
|
|
116
|
+
bfactors[j] = upper_bfactor
|
|
117
|
+
if bfactors[j] < -upper_bfactor:
|
|
118
|
+
bfactors[j] = -upper_bfactor
|
|
119
|
+
# will delete later within pymol script
|
|
120
|
+
add_fake_water_atom(soup, 'XXX', upper_bfactor)
|
|
121
|
+
add_fake_water_atom(soup, 'XXX', -upper_bfactor)
|
|
122
|
+
# cut-off below min_val to zero
|
|
123
|
+
if lower_bfactor:
|
|
124
|
+
for j in range(len(bfactors)):
|
|
125
|
+
if -lower_bfactor < bfactors[j] < lower_bfactor:
|
|
126
|
+
bfactors[j] = 0.0
|
|
127
|
+
for a, bfactor in zip(soup.atoms(), bfactors):
|
|
128
|
+
a.bfactor = bfactor
|
|
129
|
+
new_pdb = util.fname_variant(pdb)
|
|
130
|
+
soup.write_pdb(new_pdb)
|
|
131
|
+
return new_pdb, max(bfactors)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def rescale_positive_negative_bfactor_pdbs(
|
|
135
|
+
pdbs, lower_bfactor, upper_bfactor):
|
|
136
|
+
"Returns list of new_pdbs, and max_bfactor"
|
|
137
|
+
max_bfactor = 0
|
|
138
|
+
new_pdbs = []
|
|
139
|
+
for pdb in pdbs:
|
|
140
|
+
new_pdb, this_max_bfactor = \
|
|
141
|
+
rescale_positive_negative_bfactors_pdb(
|
|
142
|
+
pdb, lower_bfactor, upper_bfactor)
|
|
143
|
+
if this_max_bfactor > max_bfactor:
|
|
144
|
+
max_bfactor = this_max_bfactor
|
|
145
|
+
new_pdbs.append(new_pdb)
|
|
146
|
+
return new_pdbs, max_bfactor
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# PYMOL script functions and snippets
|
|
150
|
+
|
|
151
|
+
def make_bgcolor_script(bg_color):
|
|
152
|
+
return "cmd.bg_color('%s');\n" % bg_color
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def make_load_pdbs_script(pdbs):
|
|
156
|
+
"Returns pymol script, name of pdbs"
|
|
157
|
+
script = ""
|
|
158
|
+
for pdb in pdbs:
|
|
159
|
+
script += "load %s\n" % pdb
|
|
160
|
+
script += "hide everything\n"
|
|
161
|
+
return script
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def make_separate_chain_colors_script(pdbs):
|
|
165
|
+
names = [os.path.basename(p).replace('.pdb', '')
|
|
166
|
+
for p in pdbs]
|
|
167
|
+
colors = ['util.color_chains("(%s and elem c)")\n' % n
|
|
168
|
+
for n in names]
|
|
169
|
+
return ''.join(colors)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
red_white_gradient_script = """\
|
|
173
|
+
run %s
|
|
174
|
+
color_b all, gradient=wr
|
|
175
|
+
""" % os.path.join(data.data_dir, "color_b.py")
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
blue_white_red_gradient_script = """\
|
|
179
|
+
cmd.spectrum("b", "blue_white_red", selection="all");
|
|
180
|
+
"""
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
cartoon_script = """
|
|
184
|
+
set cartoon_flat_sheets, 0
|
|
185
|
+
set cartoon_rect_width, 0.2
|
|
186
|
+
set cartoon_oval_width, 0.2
|
|
187
|
+
set cartoon_loop_radius, 0.2
|
|
188
|
+
set cartoon_tube_radius, 0.2
|
|
189
|
+
cartoon auto
|
|
190
|
+
show cartoon
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
putty_script = """
|
|
195
|
+
set cartoon_flat_sheets, 0
|
|
196
|
+
set cartoon_putty_scale_max, %(scale_max)f
|
|
197
|
+
set cartoon_putty_radius, 0.4
|
|
198
|
+
set cartoon_putty_scale_power, 1
|
|
199
|
+
cartoon putty
|
|
200
|
+
show cartoon
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def make_putty_script(scale_max):
|
|
205
|
+
return putty_script % { 'scale_max': scale_max }
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def make_sticks_above_bfactor_script(lower_bfactor):
|
|
209
|
+
script = ""
|
|
210
|
+
script += "select hot, b > %f or b < -%f\n" % \
|
|
211
|
+
(lower_bfactor, lower_bfactor)
|
|
212
|
+
script += "select cold, b < %f and b > -%f\n" % \
|
|
213
|
+
(lower_bfactor, lower_bfactor)
|
|
214
|
+
script += "show stick, hot\n"
|
|
215
|
+
script += "hide stick, cold\n"
|
|
216
|
+
script += "deselect\n"
|
|
217
|
+
return script
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def make_ligands_as_sticks_script(pdbs, color=""):
|
|
221
|
+
script = ""
|
|
222
|
+
for pdb in pdbs:
|
|
223
|
+
name = os.path.basename(pdb).replace('.pdb', '')
|
|
224
|
+
soup = pdbatoms.Soup(pdb)
|
|
225
|
+
for res in soup.residues():
|
|
226
|
+
if res.type not in data.res_name_to_char:
|
|
227
|
+
if res.type not in "HOH":
|
|
228
|
+
chain_id_script = ""
|
|
229
|
+
if res.chain_id.strip():
|
|
230
|
+
chain_id_script = "and chain %s" % res.chain_id
|
|
231
|
+
script += \
|
|
232
|
+
"show stick, %s %s and resn %s and resi %d\n" \
|
|
233
|
+
% (name, chain_id_script, res.type, res.num)
|
|
234
|
+
if color:
|
|
235
|
+
script += \
|
|
236
|
+
"color %s, %s %s and resn %s and resi %d\n" \
|
|
237
|
+
% (color, name, chain_id_script, res.type, res.num)
|
|
238
|
+
script += "show nonbonded\n"
|
|
239
|
+
return script
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
highlight_res_script = """
|
|
243
|
+
select highlight, %s
|
|
244
|
+
show stick, highlight
|
|
245
|
+
color green, highlight
|
|
246
|
+
"""
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def make_highlight_res_script(pymol_res_id):
|
|
250
|
+
return highlight_res_script % pymol_res_id
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
peptide_style_script = """
|
|
254
|
+
select bb, name ca+n+h+o+c+oxt+h1+h2+h3+ch3+hh31+hh32+hh33+3hh3+2hh3+1hh3
|
|
255
|
+
show sphere, bb
|
|
256
|
+
hide stick, bb
|
|
257
|
+
util.cbaw bb
|
|
258
|
+
select sc, not bb and not hydro
|
|
259
|
+
show stick, sc
|
|
260
|
+
hide sphere, sc
|
|
261
|
+
util.cbag sc
|
|
262
|
+
set sphere_quality, 2
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
hide_backbone_sticks_script = """
|
|
267
|
+
hide stick, hydro
|
|
268
|
+
select bb, name c+o+n+h+oxt
|
|
269
|
+
hide stick, bb
|
|
270
|
+
select nuc, resn A+U+T+C+G+A3+U3+T3+C3+G3+A5+U5+T5+C5+G5+DA+DT+DC+DG
|
|
271
|
+
select nuc_bb, name P+O1P+O2P+OP1+Op2+O3'+C3'+C2'+C1'+O4'+C4'+C5'+O5'
|
|
272
|
+
hide cartoon, nuc and not nuc_bb
|
|
273
|
+
deselect
|
|
274
|
+
"""
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def bfactor_script(pdb, lower_bfactor=None, upper_bfactor=None,
|
|
278
|
+
max_bfactor=None, is_putty=False):
|
|
279
|
+
"Returns script that displays bfactors of pdb"
|
|
280
|
+
script = make_load_pdbs_script([pdb])
|
|
281
|
+
script += red_white_gradient_script
|
|
282
|
+
if is_putty:
|
|
283
|
+
script += make_putty_script(get_scale_max(max_bfactor, upper_bfactor))
|
|
284
|
+
else:
|
|
285
|
+
script += cartoon_script
|
|
286
|
+
script += "cartoon tube\n"
|
|
287
|
+
if not is_putty:
|
|
288
|
+
if lower_bfactor is not None:
|
|
289
|
+
script += make_sticks_above_bfactor_script(lower_bfactor)
|
|
290
|
+
else:
|
|
291
|
+
script += "show stick\n"
|
|
292
|
+
script += make_ligands_as_sticks_script([pdb])
|
|
293
|
+
script += hide_backbone_sticks_script
|
|
294
|
+
return script
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def split_resname(resname):
|
|
299
|
+
"Returns (chain_id, res_num)"
|
|
300
|
+
words = resname.split(":")
|
|
301
|
+
if len(words) == 2:
|
|
302
|
+
return (words[0], int(words[1]))
|
|
303
|
+
else:
|
|
304
|
+
return (' ', int(words[0]))
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def find_ca_of_resname(atoms, resname):
|
|
308
|
+
chain_id, res_num = split_resname(resname)
|
|
309
|
+
for atom in atoms:
|
|
310
|
+
if chain_id == atom.chain_id and res_num == atom.res_num:
|
|
311
|
+
if "CA" == atom.type:
|
|
312
|
+
return atom
|
|
313
|
+
return None
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def get_pdb_transform(pdb, center_res, top_res):
|
|
317
|
+
"""
|
|
318
|
+
Returns a transformation matrix that centers pdb to
|
|
319
|
+
center_res on the z-axis and moves top_res above center_res
|
|
320
|
+
on the y-axis
|
|
321
|
+
"""
|
|
322
|
+
soup = pdbatoms.Soup(pdb)
|
|
323
|
+
atoms = soup.atoms()
|
|
324
|
+
soup_center = pdbatoms.get_center(atoms)
|
|
325
|
+
translation = v3.translation(-soup_center)
|
|
326
|
+
soup.transform(translation)
|
|
327
|
+
result = translation
|
|
328
|
+
|
|
329
|
+
center_atom = find_ca_of_resname(soup.atoms(), center_res)
|
|
330
|
+
view = v3.vector(0, 0, 1)
|
|
331
|
+
axis = v3.cross(view, center_atom.pos)
|
|
332
|
+
angle = v3.vec_dihedral(view, axis, center_atom.pos)
|
|
333
|
+
rotation = v3.rotation(axis, angle)
|
|
334
|
+
soup.transform(rotation)
|
|
335
|
+
result = v3.combine(rotation, result)
|
|
336
|
+
|
|
337
|
+
top_atom = find_ca_of_resname(soup.atoms(), top_res)
|
|
338
|
+
top_dir = v3.vector(0, 1, 0)
|
|
339
|
+
axis = view.copy()
|
|
340
|
+
angle = v3.vec_dihedral(top_dir, axis, top_atom.pos)
|
|
341
|
+
rotation2 = v3.rotation(axis, angle)
|
|
342
|
+
result = v3.combine(rotation2, result)
|
|
343
|
+
|
|
344
|
+
del soup
|
|
345
|
+
return result
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def run_pymol_script(pml, width=500, height=500):
|
|
350
|
+
is_quit = 'quit' in util.words_in_file(pml)
|
|
351
|
+
if is_quit:
|
|
352
|
+
pymol_batch = data.binary("pymol_batch")
|
|
353
|
+
cmd = pymol_batch + ' -c '
|
|
354
|
+
else:
|
|
355
|
+
pymol = data.binary("pymol")
|
|
356
|
+
cmd = pymol + " -q " # no splash screen
|
|
357
|
+
cmd += " -W %d -H %d " % (width, height)
|
|
358
|
+
cmd += pml
|
|
359
|
+
util.run_with_output(cmd)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
# Functions to generate PNG's with PYMOL
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def pdb_to_bfactor_png(
|
|
366
|
+
bfactor_pdb, png, lower_bfactor=None, upper_bfactor=None,
|
|
367
|
+
highlight_res=None, is_putty=False, is_sticks=True,
|
|
368
|
+
center_res=None, top_res=None, height=480, width=480):
|
|
369
|
+
"""
|
|
370
|
+
Generates a bfactor-colored .png using the standard white-to-red
|
|
371
|
+
color scheme with a useful set of options. highlight_res,
|
|
372
|
+
center_res & top_res follow the 'A:10' style of residue naming.
|
|
373
|
+
"""
|
|
374
|
+
|
|
375
|
+
pdb, max_bfactor = rescale_positive_bfactors_pdb(
|
|
376
|
+
bfactor_pdb, lower_bfactor, upper_bfactor)
|
|
377
|
+
temp_fnames = [pdb]
|
|
378
|
+
|
|
379
|
+
if center_res or top_res:
|
|
380
|
+
pdb = get_pdb_transform(pdb, center_res, top_res)
|
|
381
|
+
temp_fnames.append(pdb)
|
|
382
|
+
|
|
383
|
+
script = ""
|
|
384
|
+
|
|
385
|
+
script += bfactor_script(
|
|
386
|
+
pdb, lower_bfactor, upper_bfactor,
|
|
387
|
+
max_bfactor, is_putty)
|
|
388
|
+
|
|
389
|
+
if highlight_res is not None:
|
|
390
|
+
pymol_res_id = get_pymol_id_from_res_tag(highlight_res)
|
|
391
|
+
script += make_highlight_res_script(pymol_res_id)
|
|
392
|
+
script += hide_backbone_sticks_script
|
|
393
|
+
|
|
394
|
+
script += "clip far, -20\n"
|
|
395
|
+
script += "save %s\n" % png
|
|
396
|
+
script += "quit"
|
|
397
|
+
|
|
398
|
+
pml = util.fname_variant('temp.pml')
|
|
399
|
+
open(pml, 'w').write(script)
|
|
400
|
+
run_pymol_script(pml, width, height)
|
|
401
|
+
temp_fnames.append(pml)
|
|
402
|
+
|
|
403
|
+
util.clean_fname(*temp_fnames)
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def soup_to_bfactor_png(
|
|
407
|
+
soup, png, bfactors, lower_bfactor=None, upper_bfactor=None,
|
|
408
|
+
highlight_res=None, is_putty=False, is_sticks=True,
|
|
409
|
+
center_res=None, top_res=None, height=480, width=480):
|
|
410
|
+
"""
|
|
411
|
+
Wrapper around pdb_to_bfactor that loads in external values
|
|
412
|
+
for the residue bfactors with a reusable soup object.
|
|
413
|
+
"""
|
|
414
|
+
pdb = util.temp_fname('.pdb')
|
|
415
|
+
temp_fnames = [pdb]
|
|
416
|
+
soup.load_residue_bfactors(bfactors)
|
|
417
|
+
soup.write_pdb(pdb)
|
|
418
|
+
pdb_to_bfactor_png(
|
|
419
|
+
pdb, png, lower_bfactor, upper_bfactor,
|
|
420
|
+
highlight_res, is_putty, is_sticks,
|
|
421
|
+
center_res, top_res, height, width)
|
|
422
|
+
util.clean_fname(*temp_fnames)
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def make_pdbs_png(
|
|
426
|
+
png, pdbs, bgcolor="white", center_res=None, top_res=None,
|
|
427
|
+
highlight_res=None, is_sticks=True, is_putty=False,
|
|
428
|
+
width=480, height=480):
|
|
429
|
+
|
|
430
|
+
if 'transparent' in bgcolor:
|
|
431
|
+
script = 'set opaque_background, off\n'
|
|
432
|
+
else:
|
|
433
|
+
script = make_bgcolor_script(bgcolor)
|
|
434
|
+
|
|
435
|
+
temp_fnames = []
|
|
436
|
+
if center_res and top_res:
|
|
437
|
+
transform = get_pdb_transform(pdbs[0], center_res, top_res)
|
|
438
|
+
for i in range(len(pdbs)):
|
|
439
|
+
soup = pdbatoms.Soup(pdbs[i])
|
|
440
|
+
soup.transform(transform)
|
|
441
|
+
new_pdb = util.fname_variant(pdbs[i])
|
|
442
|
+
soup.write_pdb(new_pdb)
|
|
443
|
+
temp_fnames.append(new_pdb)
|
|
444
|
+
pdbs[i] = new_pdb
|
|
445
|
+
del soup
|
|
446
|
+
|
|
447
|
+
script += make_load_pdbs_script(pdbs)
|
|
448
|
+
script += make_separate_chain_colors_script(pdbs)
|
|
449
|
+
|
|
450
|
+
if is_putty:
|
|
451
|
+
script += make_putty_script(get_scale_max(
|
|
452
|
+
max_bfactor, upper_bfactor))
|
|
453
|
+
else:
|
|
454
|
+
script += cartoon_script
|
|
455
|
+
|
|
456
|
+
if not is_sticks:
|
|
457
|
+
script += "hide stick\n"
|
|
458
|
+
else:
|
|
459
|
+
script += "show stick\n"
|
|
460
|
+
|
|
461
|
+
script += make_ligands_as_sticks_script(pdbs)
|
|
462
|
+
|
|
463
|
+
if highlight_res:
|
|
464
|
+
script += make_highlight_res_script(highlight_res)
|
|
465
|
+
script += hide_backbone_sticks_script
|
|
466
|
+
|
|
467
|
+
# script += "clip far, 5\n"
|
|
468
|
+
script += "save %s\n" % png
|
|
469
|
+
script += "quit"
|
|
470
|
+
|
|
471
|
+
pml = util.fname_variant('temp.pml')
|
|
472
|
+
open(pml, 'w').write(script)
|
|
473
|
+
run_pymol_script(pml, width, height)
|
|
474
|
+
temp_fnames.append(pml)
|
|
475
|
+
|
|
476
|
+
util.clean_fname(*temp_fnames)
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
__doc__ = """
|
|
4
|
+
|
|
5
|
+
RMSD calculators and optimal rotation of sets of coordinates.
|
|
6
|
+
|
|
7
|
+
Two algorithms are provided:
|
|
8
|
+
|
|
9
|
+
1. The standard SVD decomposition using the numpy library.
|
|
10
|
+
2. The qcp quaternion-based method that doesn't need numpy.
|
|
11
|
+
|
|
12
|
+
The qcp method is particularly useful because it allows the
|
|
13
|
+
library to function without numpy such as when run with pypy.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from . import v3
|
|
17
|
+
from . import pdbatoms
|
|
18
|
+
import math
|
|
19
|
+
from .lib import pyqcprot
|
|
20
|
+
try:
|
|
21
|
+
import numpy
|
|
22
|
+
is_numpy = True
|
|
23
|
+
except:
|
|
24
|
+
is_numpy = False
|
|
25
|
+
|
|
26
|
+
standard_residues = {"CYS","MET","HIS","HSD","HIE","SER","GLN","ASP","GLU","TYR","THR","ALA","LEU","ILE","PHE","TRP","ARG","ASN","LYS","VAL","PRO","GLY"}
|
|
27
|
+
|
|
28
|
+
def numpy_svd_rmsd_rot(in_crds1, in_crds2):
|
|
29
|
+
"""
|
|
30
|
+
Returns rmsd and optional rotation between 2 sets of [nx3] arrays.
|
|
31
|
+
|
|
32
|
+
This requires numpy for svd decomposition.
|
|
33
|
+
The transform direction: transform(m, ref_crd) => target_crd.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
crds1 = numpy.array(in_crds1)
|
|
37
|
+
crds2 = numpy.array(in_crds2)
|
|
38
|
+
assert(crds1.shape[1] == 3)
|
|
39
|
+
assert(crds1.shape == crds2.shape)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
n_vec = numpy.shape(crds1)[0]
|
|
43
|
+
correlation_matrix = numpy.dot(numpy.transpose(crds1), crds2)
|
|
44
|
+
v, s, w = numpy.linalg.svd(correlation_matrix)
|
|
45
|
+
is_reflection = (numpy.linalg.det(v) * numpy.linalg.det(w)) < 0.0
|
|
46
|
+
|
|
47
|
+
if is_reflection:
|
|
48
|
+
s[-1] = - s[-1]
|
|
49
|
+
E0 = sum(sum(crds1 * crds1)) + \
|
|
50
|
+
sum(sum(crds2 * crds2))
|
|
51
|
+
rmsd_sq = (E0 - 2.0*sum(s)) / float(n_vec)
|
|
52
|
+
rmsd_sq = max([rmsd_sq, 0.0])
|
|
53
|
+
rmsd = numpy.sqrt(rmsd_sq)
|
|
54
|
+
|
|
55
|
+
if is_reflection:
|
|
56
|
+
v[-1,:] = -v[-1,:]
|
|
57
|
+
rot33 = numpy.dot(v, w)
|
|
58
|
+
m = v3.identity()
|
|
59
|
+
m[:3,:3] = rot33.transpose()
|
|
60
|
+
|
|
61
|
+
return rmsd, m
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def pyqcprot_rmsd_rot(crds1, crds2):
|
|
65
|
+
"""
|
|
66
|
+
Returns rmsd and optional rotation between 2 sets of [nx3] arrays.
|
|
67
|
+
|
|
68
|
+
This requires Joshua Adelman's pyqcrot library for quaternion-based
|
|
69
|
+
calculation of Theobauld. The transform direction:
|
|
70
|
+
transform(m, ref_crd) => target_crd.
|
|
71
|
+
"""
|
|
72
|
+
rms, rot9 = lib.pyqcprot.calc_rms_rot(crds1, crds2)
|
|
73
|
+
matrix = v3.identity()
|
|
74
|
+
for i in range(3):
|
|
75
|
+
for j in range(3):
|
|
76
|
+
v3.matrix_elem(matrix, i, j, rot9[i*3+j])
|
|
77
|
+
return rms, matrix
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def calc_rmsd_rot(crds1, crds2):
|
|
81
|
+
"""
|
|
82
|
+
Returns the rmsd and optimal rotation and chooses the method
|
|
83
|
+
depending on whether numpy is installed.
|
|
84
|
+
"""
|
|
85
|
+
if is_numpy:
|
|
86
|
+
return numpy_svd_rmsd_rot(crds1, crds2)
|
|
87
|
+
else:
|
|
88
|
+
return pyqcprot_rmsd_rot(crds1, crds2)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def sum_rmsd(crds1, crds2):
|
|
92
|
+
"""
|
|
93
|
+
Returns the direct rmsd between two sets of vectors *without*
|
|
94
|
+
doing any optimal rotation. If calculated between optimal sets,
|
|
95
|
+
should give the proper RMSD.
|
|
96
|
+
"""
|
|
97
|
+
sum_squared = 0.0
|
|
98
|
+
for crd1, crd2 in zip(crds1, crds2):
|
|
99
|
+
sum_squared += v3.distance(crd1, crd2)**2
|
|
100
|
+
return math.sqrt(sum_squared/float(len(crds1)))
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def get_superposable_atoms(soup, segments, atom_types, standard=False):
|
|
104
|
+
"""
|
|
105
|
+
Returns a list of atom indices to a soup, built from segments.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
segments (list): list of pairs of residue names in the soup,
|
|
109
|
+
such as ['A:1','A:3'], interpreted as the
|
|
110
|
+
two ends of a fragment in soup that we want
|
|
111
|
+
the atom index of
|
|
112
|
+
atom_types (list): list of atom_types in the residues that
|
|
113
|
+
we want to generate the indices from.
|
|
114
|
+
"""
|
|
115
|
+
result = []
|
|
116
|
+
allowed_i = []
|
|
117
|
+
residues = soup.residues()
|
|
118
|
+
if segments:
|
|
119
|
+
for res_tag_i, res_tag_j in segments:
|
|
120
|
+
i = soup.get_i_residue(str(res_tag_i))
|
|
121
|
+
j = soup.get_i_residue(str(res_tag_j))
|
|
122
|
+
if i > j:
|
|
123
|
+
i, j = j, i
|
|
124
|
+
allowed_i.extend(list(range(i,j+1)))
|
|
125
|
+
else:
|
|
126
|
+
allowed_i = list(range(len(residues)))
|
|
127
|
+
for i, residue in enumerate(residues):
|
|
128
|
+
if i in allowed_i:
|
|
129
|
+
if standard:
|
|
130
|
+
result.extend([a for a in residue.atoms()
|
|
131
|
+
if a.type in atom_types and residue.type in standard_residues])
|
|
132
|
+
else:
|
|
133
|
+
result.extend([a for a in residue.atoms()
|
|
134
|
+
if a.type in atom_types])
|
|
135
|
+
return result
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def rmsd_of_soups(
|
|
139
|
+
soup1, soup2, segments1=[], segments2=[],
|
|
140
|
+
atom_types=['CA'], transform_pdb1=None, standard=False):
|
|
141
|
+
"""
|
|
142
|
+
Returns the RMSD between two PDB structures and optionally
|
|
143
|
+
writes the best transformed structure of pdb1 in transform_pdb.
|
|
144
|
+
|
|
145
|
+
By default, it chooses the CA atoms in the soup.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
segments1 (list): list of pairs of residue names in pdb1,
|
|
149
|
+
such as ['A:1','A:3'], interpreted as the
|
|
150
|
+
two ends of a fragment in soup that we want
|
|
151
|
+
the atom index of
|
|
152
|
+
segments2 (list): same as above but for pdb2
|
|
153
|
+
atom_types (list): list of atom_types in the residues that
|
|
154
|
+
we want to generate the indices from.
|
|
155
|
+
"""
|
|
156
|
+
atoms1 = get_superposable_atoms(soup1, segments1, atom_types, standard)
|
|
157
|
+
atoms2 = get_superposable_atoms(soup2, segments2, atom_types, standard)
|
|
158
|
+
|
|
159
|
+
crds1 = [a.pos for a in atoms1]
|
|
160
|
+
crds2 = [a.pos for a in atoms2]
|
|
161
|
+
|
|
162
|
+
center1 = v3.get_center(crds1)
|
|
163
|
+
center2 = v3.get_center(crds2)
|
|
164
|
+
|
|
165
|
+
soup1.transform(v3.translation(-center1))
|
|
166
|
+
soup2.transform(v3.translation(-center2))
|
|
167
|
+
|
|
168
|
+
rmsd, transform_1_to_2 = calc_rmsd_rot(crds1, crds2)
|
|
169
|
+
|
|
170
|
+
if not transform_pdb1:
|
|
171
|
+
return rmsd
|
|
172
|
+
|
|
173
|
+
soup1.transform(transform_1_to_2)
|
|
174
|
+
|
|
175
|
+
soup1.transform(v3.translation(center2))
|
|
176
|
+
soup2.transform(v3.translation(center2))
|
|
177
|
+
|
|
178
|
+
soup1.write_pdb(transform_pdb1)
|
|
179
|
+
return sum_rmsd(crds1, crds2)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def rmsd_of_pdbs(
|
|
183
|
+
pdb1, pdb2, segments1=[], segments2=[],
|
|
184
|
+
atom_types=['CA'], transform_pdb1=None, standard=False):
|
|
185
|
+
"""
|
|
186
|
+
Returns the RMSD between two PDB structures and optionally
|
|
187
|
+
writes the best transformed structure of pdb1 in transform_pdb.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
segments1 (list): list of pairs of residue names in pdb1,
|
|
191
|
+
such as ['A:1','A:3'], interpreted as the
|
|
192
|
+
two ends of a fragment in soup that we want
|
|
193
|
+
the atom index of
|
|
194
|
+
segments2 (list): same as above but for pdb2
|
|
195
|
+
atom_types (list): list of atom_types in the residues that
|
|
196
|
+
we want to generate the indices from.
|
|
197
|
+
"""
|
|
198
|
+
soup1 = pdbatoms.Soup(pdb1)
|
|
199
|
+
soup2 = pdbatoms.Soup(pdb2)
|
|
200
|
+
return rmsd_of_soups(
|
|
201
|
+
soup1, soup2, segments1, segments2,
|
|
202
|
+
atom_types, transform_pdb1, standard)
|
|
203
|
+
|