biotite 1.0.1__cp310-cp310-win_amd64.whl → 1.2.0__cp310-cp310-win_amd64.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.
Potentially problematic release.
This version of biotite might be problematic. Click here for more details.
- biotite/application/application.py +3 -3
- biotite/application/autodock/app.py +1 -1
- biotite/application/blast/webapp.py +1 -1
- biotite/application/clustalo/app.py +1 -1
- biotite/application/dssp/app.py +13 -3
- biotite/application/localapp.py +36 -2
- biotite/application/msaapp.py +10 -10
- biotite/application/muscle/app3.py +5 -18
- biotite/application/muscle/app5.py +5 -5
- biotite/application/sra/app.py +0 -5
- biotite/application/util.py +22 -2
- biotite/application/viennarna/rnaalifold.py +8 -8
- biotite/application/viennarna/rnaplot.py +9 -3
- biotite/application/viennarna/util.py +1 -1
- biotite/application/webapp.py +1 -1
- biotite/database/afdb/__init__.py +12 -0
- biotite/database/afdb/download.py +191 -0
- biotite/database/entrez/dbnames.py +10 -0
- biotite/database/entrez/download.py +9 -10
- biotite/database/entrez/key.py +1 -1
- biotite/database/entrez/query.py +5 -4
- biotite/database/pubchem/download.py +6 -6
- biotite/database/pubchem/error.py +10 -0
- biotite/database/pubchem/query.py +12 -23
- biotite/database/rcsb/download.py +3 -2
- biotite/database/rcsb/query.py +8 -9
- biotite/database/uniprot/check.py +22 -17
- biotite/database/uniprot/download.py +3 -6
- biotite/database/uniprot/query.py +4 -5
- biotite/file.py +14 -2
- biotite/interface/__init__.py +19 -0
- biotite/interface/openmm/__init__.py +16 -0
- biotite/interface/openmm/state.py +93 -0
- biotite/interface/openmm/system.py +227 -0
- biotite/interface/pymol/__init__.py +198 -0
- biotite/interface/pymol/cgo.py +346 -0
- biotite/interface/pymol/convert.py +185 -0
- biotite/interface/pymol/display.py +267 -0
- biotite/interface/pymol/object.py +1226 -0
- biotite/interface/pymol/shapes.py +178 -0
- biotite/interface/pymol/startup.py +169 -0
- biotite/interface/rdkit/__init__.py +15 -0
- biotite/interface/rdkit/mol.py +490 -0
- biotite/interface/version.py +71 -0
- biotite/interface/warning.py +19 -0
- biotite/sequence/align/__init__.py +0 -4
- biotite/sequence/align/alignment.py +49 -14
- biotite/sequence/align/banded.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/banded.pyx +26 -26
- biotite/sequence/align/cigar.py +2 -2
- biotite/sequence/align/kmeralphabet.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/kmeralphabet.pyx +19 -2
- biotite/sequence/align/kmersimilarity.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/kmertable.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/kmertable.pyx +58 -48
- biotite/sequence/align/localgapped.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/localgapped.pyx +47 -47
- biotite/sequence/align/localungapped.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/localungapped.pyx +10 -10
- biotite/sequence/align/matrix.py +284 -57
- biotite/sequence/align/matrix_data/3Di.mat +24 -0
- biotite/sequence/align/matrix_data/PB.license +21 -0
- biotite/sequence/align/matrix_data/PB.mat +18 -0
- biotite/sequence/align/multiple.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/pairwise.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/pairwise.pyx +35 -35
- biotite/sequence/align/permutation.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/selector.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/selector.pyx +2 -2
- biotite/sequence/align/statistics.py +1 -1
- biotite/sequence/align/tracetable.cp310-win_amd64.pyd +0 -0
- biotite/sequence/alphabet.py +5 -2
- biotite/sequence/annotation.py +19 -13
- biotite/sequence/codec.cp310-win_amd64.pyd +0 -0
- biotite/sequence/codon.py +1 -2
- biotite/sequence/graphics/alignment.py +25 -39
- biotite/sequence/graphics/color_schemes/3di_flower.json +48 -0
- biotite/sequence/graphics/color_schemes/pb_flower.json +2 -1
- biotite/sequence/graphics/colorschemes.py +44 -11
- biotite/sequence/graphics/dendrogram.py +4 -2
- biotite/sequence/graphics/features.py +2 -2
- biotite/sequence/graphics/logo.py +10 -12
- biotite/sequence/io/fasta/convert.py +1 -2
- biotite/sequence/io/fasta/file.py +1 -1
- biotite/sequence/io/fastq/file.py +3 -3
- biotite/sequence/io/genbank/file.py +3 -3
- biotite/sequence/io/genbank/sequence.py +2 -0
- biotite/sequence/io/gff/convert.py +1 -1
- biotite/sequence/io/gff/file.py +1 -2
- biotite/sequence/phylo/nj.cp310-win_amd64.pyd +0 -0
- biotite/sequence/phylo/tree.cp310-win_amd64.pyd +0 -0
- biotite/sequence/phylo/upgma.cp310-win_amd64.pyd +0 -0
- biotite/sequence/profile.py +105 -29
- biotite/sequence/search.py +0 -1
- biotite/sequence/seqtypes.py +136 -8
- biotite/sequence/sequence.py +1 -2
- biotite/setup_ccd.py +197 -0
- biotite/structure/__init__.py +6 -3
- biotite/structure/alphabet/__init__.py +25 -0
- biotite/structure/alphabet/encoder.py +332 -0
- biotite/structure/alphabet/encoder_weights_3di.kerasify +0 -0
- biotite/structure/alphabet/i3d.py +109 -0
- biotite/structure/alphabet/layers.py +86 -0
- biotite/structure/alphabet/pb.license +21 -0
- biotite/structure/alphabet/pb.py +170 -0
- biotite/structure/alphabet/unkerasify.py +128 -0
- biotite/structure/atoms.py +163 -66
- biotite/structure/basepairs.py +26 -26
- biotite/structure/bonds.cp310-win_amd64.pyd +0 -0
- biotite/structure/bonds.pyx +79 -25
- biotite/structure/box.py +19 -21
- biotite/structure/celllist.cp310-win_amd64.pyd +0 -0
- biotite/structure/celllist.pyx +83 -67
- biotite/structure/chains.py +5 -37
- biotite/structure/charges.cp310-win_amd64.pyd +0 -0
- biotite/structure/compare.py +420 -13
- biotite/structure/density.py +1 -1
- biotite/structure/dotbracket.py +27 -28
- biotite/structure/filter.py +8 -8
- biotite/structure/geometry.py +74 -127
- biotite/structure/hbond.py +17 -19
- biotite/structure/info/__init__.py +1 -0
- biotite/structure/info/atoms.py +24 -15
- biotite/structure/info/bonds.py +12 -6
- biotite/structure/info/ccd.py +125 -34
- biotite/structure/info/{ccd/components.bcif → components.bcif} +0 -0
- biotite/structure/info/groups.py +62 -19
- biotite/structure/info/masses.py +9 -6
- biotite/structure/info/misc.py +15 -22
- biotite/structure/info/radii.py +92 -22
- biotite/structure/info/standardize.py +4 -4
- biotite/structure/integrity.py +4 -6
- biotite/structure/io/general.py +2 -2
- biotite/structure/io/gro/file.py +8 -9
- biotite/structure/io/mol/convert.py +1 -1
- biotite/structure/io/mol/ctab.py +33 -28
- biotite/structure/io/mol/mol.py +1 -1
- biotite/structure/io/mol/sdf.py +80 -53
- biotite/structure/io/pdb/convert.py +4 -3
- biotite/structure/io/pdb/file.py +85 -25
- biotite/structure/io/pdb/hybrid36.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/pdbqt/file.py +36 -36
- biotite/structure/io/pdbx/__init__.py +1 -0
- biotite/structure/io/pdbx/bcif.py +54 -15
- biotite/structure/io/pdbx/cif.py +92 -66
- biotite/structure/io/pdbx/component.py +15 -4
- biotite/structure/io/pdbx/compress.py +321 -0
- biotite/structure/io/pdbx/convert.py +410 -75
- biotite/structure/io/pdbx/encoding.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/pdbx/encoding.pyx +98 -17
- biotite/structure/io/trajfile.py +9 -6
- biotite/structure/io/util.py +38 -0
- biotite/structure/mechanics.py +0 -1
- biotite/structure/molecules.py +141 -156
- biotite/structure/pseudoknots.py +7 -13
- biotite/structure/repair.py +2 -4
- biotite/structure/residues.py +13 -24
- biotite/structure/rings.py +335 -0
- biotite/structure/sasa.cp310-win_amd64.pyd +0 -0
- biotite/structure/sasa.pyx +2 -1
- biotite/structure/segments.py +69 -11
- biotite/structure/sequence.py +0 -1
- biotite/structure/sse.py +0 -2
- biotite/structure/superimpose.py +74 -62
- biotite/structure/tm.py +581 -0
- biotite/structure/transform.py +12 -25
- biotite/structure/util.py +76 -4
- biotite/version.py +9 -4
- biotite/visualize.py +111 -1
- {biotite-1.0.1.dist-info → biotite-1.2.0.dist-info}/METADATA +6 -2
- {biotite-1.0.1.dist-info → biotite-1.2.0.dist-info}/RECORD +173 -143
- biotite/structure/info/ccd/README.rst +0 -8
- biotite/structure/info/ccd/amino_acids.txt +0 -1663
- biotite/structure/info/ccd/carbohydrates.txt +0 -1135
- biotite/structure/info/ccd/nucleotides.txt +0 -798
- {biotite-1.0.1.dist-info → biotite-1.2.0.dist-info}/WHEEL +0 -0
- {biotite-1.0.1.dist-info → biotite-1.2.0.dist-info}/licenses/LICENSE.rst +0 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
__name__ = "biotite.interface.pymol"
|
|
2
|
+
__author__ = "Patrick Kunzmann"
|
|
3
|
+
__all__ = [
|
|
4
|
+
"draw_cgo",
|
|
5
|
+
"get_cylinder_cgo",
|
|
6
|
+
"get_cone_cgo",
|
|
7
|
+
"get_sphere_cgo",
|
|
8
|
+
"get_point_cgo",
|
|
9
|
+
"get_line_cgo",
|
|
10
|
+
"get_multiline_cgo",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
import itertools
|
|
14
|
+
from enum import IntEnum
|
|
15
|
+
import numpy as np
|
|
16
|
+
from biotite.interface.pymol.object import PyMOLObject
|
|
17
|
+
from biotite.interface.pymol.startup import get_and_set_pymol_instance
|
|
18
|
+
|
|
19
|
+
_object_counter = 0
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class CGO(IntEnum):
|
|
23
|
+
# List compiled from uppercase attributes in 'pymol.cgo'
|
|
24
|
+
ALPHA = 25
|
|
25
|
+
ALPHA_TRIANGLE = 17
|
|
26
|
+
BEGIN = 2
|
|
27
|
+
CHAR = 23
|
|
28
|
+
COLOR = 6
|
|
29
|
+
CONE = 27
|
|
30
|
+
CUSTOM_CYLINDER = 15
|
|
31
|
+
CYLINDER = 9
|
|
32
|
+
DISABLE = 13
|
|
33
|
+
DOTWIDTH = 16
|
|
34
|
+
ELLIPSOID = 18
|
|
35
|
+
ENABLE = 12
|
|
36
|
+
END = 3
|
|
37
|
+
FONT = 19
|
|
38
|
+
FONT_AXES = 22
|
|
39
|
+
FONT_SCALE = 20
|
|
40
|
+
FONT_VERTEX = 21
|
|
41
|
+
LINES = 1
|
|
42
|
+
LINEWIDTH = 10
|
|
43
|
+
LINE_LOOP = 2
|
|
44
|
+
LINE_STRIP = 3
|
|
45
|
+
NORMAL = 5
|
|
46
|
+
NULL = 1
|
|
47
|
+
PICK_COLOR = 31
|
|
48
|
+
POINTS = 0
|
|
49
|
+
QUADRIC = 26
|
|
50
|
+
SAUSAGE = 14
|
|
51
|
+
SPHERE = 7
|
|
52
|
+
STOP = 0
|
|
53
|
+
TRIANGLE = 8
|
|
54
|
+
TRIANGLES = 4
|
|
55
|
+
TRIANGLE_FAN = 6
|
|
56
|
+
TRIANGLE_STRIP = 5
|
|
57
|
+
VERTEX = 4
|
|
58
|
+
WIDTHSCALE = 11
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def draw_cgo(cgo_list, name=None, pymol_instance=None, delete=True):
|
|
62
|
+
"""
|
|
63
|
+
Draw geometric shapes using *Compiled Graphics Objects* (CGOs).
|
|
64
|
+
|
|
65
|
+
Each CGO is represented by a list of floats, which can be obtained
|
|
66
|
+
via the ``get_xxx_cgo()`` functions.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
cgo_list : list of list of float
|
|
71
|
+
The CGOs to draw.
|
|
72
|
+
It is recommended to use a ``get_xxx_cgo()`` function to obtain
|
|
73
|
+
the elements for this list, if possible.
|
|
74
|
+
Otherwise, shapes may be drawn incorrectly or omitted entirely,
|
|
75
|
+
if a CGO is incorrectly formatted.
|
|
76
|
+
name : str, optional
|
|
77
|
+
The name of the newly created CGO object.
|
|
78
|
+
If omitted, a unique name is generated.
|
|
79
|
+
pymol_instance : module or SingletonPyMOL or PyMOL, optional
|
|
80
|
+
If *PyMOL* is used in library mode, the :class:`PyMOL`
|
|
81
|
+
or :class:`SingletonPyMOL` object is given here.
|
|
82
|
+
If otherwise *PyMOL* is used in GUI mode, the :mod:`pymol`
|
|
83
|
+
module is given.
|
|
84
|
+
By default the currently active *PyMOL* instance is used.
|
|
85
|
+
If no *PyMOL* instance is currently running,
|
|
86
|
+
*PyMOL* is started in library mode.
|
|
87
|
+
delete : bool, optional
|
|
88
|
+
If set to true, the underlying *PyMOL* object will be removed from the *PyMOL*
|
|
89
|
+
session, when the returned :class:`PyMOLObject` is garbage collected.
|
|
90
|
+
|
|
91
|
+
Returns
|
|
92
|
+
-------
|
|
93
|
+
pymol_object : PyMOLObject
|
|
94
|
+
The created :class:`PyMOLObject` representing the drawn CGOs.
|
|
95
|
+
"""
|
|
96
|
+
global _object_counter
|
|
97
|
+
if name is None:
|
|
98
|
+
name = f"biotite_cgo_{_object_counter}"
|
|
99
|
+
_object_counter += 1
|
|
100
|
+
pymol_instance = get_and_set_pymol_instance(pymol_instance)
|
|
101
|
+
pymol_instance.cmd.load_cgo(
|
|
102
|
+
# If CGO values are integers instead of floats
|
|
103
|
+
# the rendering may fail
|
|
104
|
+
[float(value) for value in list(itertools.chain(*cgo_list))],
|
|
105
|
+
name,
|
|
106
|
+
)
|
|
107
|
+
return PyMOLObject(name, pymol_instance, delete)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def get_cylinder_cgo(start, end, radius, start_color, end_color):
|
|
111
|
+
"""
|
|
112
|
+
Get the CGO for a cylinder.
|
|
113
|
+
|
|
114
|
+
Parameters
|
|
115
|
+
----------
|
|
116
|
+
start, end : array-like, shape=(3,)
|
|
117
|
+
The start and end position of the cylinder.
|
|
118
|
+
radius : float
|
|
119
|
+
The radius of the cylinder.
|
|
120
|
+
start_color, end_color : array-like, shape=(3,)
|
|
121
|
+
The color at the start and end of the cylinder given as RGB
|
|
122
|
+
values in the range *(0, 1)*.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
cgo : list of float
|
|
127
|
+
The CGO representation.
|
|
128
|
+
"""
|
|
129
|
+
_expect_length(start, "start", 3)
|
|
130
|
+
_expect_length(end, "end", 3)
|
|
131
|
+
_expect_length(start_color, "start_color", 3)
|
|
132
|
+
_expect_length(end_color, "end_color", 3)
|
|
133
|
+
_check_color(start_color)
|
|
134
|
+
_check_color(end_color)
|
|
135
|
+
return [CGO.CYLINDER, *start, *end, radius, *start_color, *end_color]
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def get_cone_cgo(
|
|
139
|
+
start, end, start_radius, end_radius, start_color, end_color, start_cap, end_cap
|
|
140
|
+
):
|
|
141
|
+
"""
|
|
142
|
+
Get the CGO for a cone.
|
|
143
|
+
|
|
144
|
+
Parameters
|
|
145
|
+
----------
|
|
146
|
+
start, end : array-like, shape=(3,)
|
|
147
|
+
The start and end position of the cone.
|
|
148
|
+
start_radius, end_radius : float
|
|
149
|
+
The radius of the cone at the start and end.
|
|
150
|
+
start_color, end_color : array-like, shape=(3,)
|
|
151
|
+
The color at the start and end of the cone given as RGB
|
|
152
|
+
values in the range *(0, 1)*.
|
|
153
|
+
start_cap, end_cap : bool
|
|
154
|
+
If true, a cap is drawn at the start or end of the cone.
|
|
155
|
+
Otherwise the cone is displayed as *open*.
|
|
156
|
+
|
|
157
|
+
Returns
|
|
158
|
+
-------
|
|
159
|
+
cgo : list of float
|
|
160
|
+
The CGO representation.
|
|
161
|
+
"""
|
|
162
|
+
_expect_length(start, "start", 3)
|
|
163
|
+
_expect_length(end, "end", 3)
|
|
164
|
+
_expect_length(start_color, "start_color", 3)
|
|
165
|
+
_expect_length(end_color, "end_color", 3)
|
|
166
|
+
_check_color(start_color)
|
|
167
|
+
_check_color(end_color)
|
|
168
|
+
return [
|
|
169
|
+
CGO.CONE,
|
|
170
|
+
*start,
|
|
171
|
+
*end,
|
|
172
|
+
start_radius,
|
|
173
|
+
end_radius,
|
|
174
|
+
*start_color,
|
|
175
|
+
*end_color,
|
|
176
|
+
start_cap,
|
|
177
|
+
end_cap,
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def get_sphere_cgo(pos, radius, color):
|
|
182
|
+
"""
|
|
183
|
+
Get the CGO for a sphere.
|
|
184
|
+
|
|
185
|
+
Parameters
|
|
186
|
+
----------
|
|
187
|
+
pos : array-like, shape=(3,)
|
|
188
|
+
The position of the sphere.
|
|
189
|
+
radius : float
|
|
190
|
+
The radius of the sphere.
|
|
191
|
+
color : array-like, shape=(3,)
|
|
192
|
+
The color of the sphere given as RGB values in the range
|
|
193
|
+
*(0, 1)*.
|
|
194
|
+
|
|
195
|
+
Returns
|
|
196
|
+
-------
|
|
197
|
+
cgo : list of float
|
|
198
|
+
The CGO representation.
|
|
199
|
+
"""
|
|
200
|
+
_expect_length(pos, "pos", 3)
|
|
201
|
+
_expect_length(color, "color", 3)
|
|
202
|
+
_check_color(color)
|
|
203
|
+
return [CGO.COLOR, *color, CGO.SPHERE, *pos, radius]
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def get_point_cgo(pos, color):
|
|
207
|
+
"""
|
|
208
|
+
Get the CGO for one or multiple points.
|
|
209
|
+
|
|
210
|
+
Parameters
|
|
211
|
+
----------
|
|
212
|
+
pos : array-like, shape=(3,), shape=(n,3)
|
|
213
|
+
The position(s) of the points.
|
|
214
|
+
color : array-like, shape=(3,) or shape=(n,3)
|
|
215
|
+
The color of the point(s) given as RGB values in the range
|
|
216
|
+
*(0, 1)*.
|
|
217
|
+
Either one color can be given that is used for all points or
|
|
218
|
+
an individual color for each point can be supplied.
|
|
219
|
+
|
|
220
|
+
Returns
|
|
221
|
+
-------
|
|
222
|
+
cgo : list of float
|
|
223
|
+
The CGO representation.
|
|
224
|
+
"""
|
|
225
|
+
pos = np.atleast_2d(pos)
|
|
226
|
+
color = _arrayfy(color, len(pos), 2)
|
|
227
|
+
|
|
228
|
+
for p in pos:
|
|
229
|
+
_expect_length(p, "pos", 3)
|
|
230
|
+
for c in color:
|
|
231
|
+
_expect_length(c, "color", 3)
|
|
232
|
+
_check_color(c)
|
|
233
|
+
|
|
234
|
+
vertices = []
|
|
235
|
+
for p, c in zip(pos, color):
|
|
236
|
+
vertices += [CGO.COLOR, *c, CGO.VERTEX, *p]
|
|
237
|
+
|
|
238
|
+
return [CGO.BEGIN, CGO.POINTS] + vertices + [CGO.END]
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def get_line_cgo(pos, color, width=1.0):
|
|
242
|
+
"""
|
|
243
|
+
Get the CGO for a line following the given positions.
|
|
244
|
+
|
|
245
|
+
Parameters
|
|
246
|
+
----------
|
|
247
|
+
pos : array-like, shape=(n,3)
|
|
248
|
+
The line follows these positions.
|
|
249
|
+
color : array-like, shape=(3,) or shape=(n,3)
|
|
250
|
+
The color of the line given as RGB values in the range
|
|
251
|
+
*(0, 1)*.
|
|
252
|
+
Either one color can be given that is used for all positions or
|
|
253
|
+
an individual color for each position can be supplied.
|
|
254
|
+
width : float, optional
|
|
255
|
+
The rendered width of the line.
|
|
256
|
+
The width is only visible after calling :func:`ray()`.
|
|
257
|
+
|
|
258
|
+
Returns
|
|
259
|
+
-------
|
|
260
|
+
cgo : list of float
|
|
261
|
+
The CGO representation.
|
|
262
|
+
"""
|
|
263
|
+
color = _arrayfy(color, len(pos), 2)
|
|
264
|
+
|
|
265
|
+
for p in pos:
|
|
266
|
+
_expect_length(p, "pos", 3)
|
|
267
|
+
for c in color:
|
|
268
|
+
_expect_length(c, "color", 3)
|
|
269
|
+
_check_color(c)
|
|
270
|
+
|
|
271
|
+
vertices = []
|
|
272
|
+
for p, c in zip(pos, color):
|
|
273
|
+
vertices += [CGO.COLOR, *c, CGO.VERTEX, *p]
|
|
274
|
+
|
|
275
|
+
return [CGO.LINEWIDTH, width, CGO.BEGIN, CGO.LINE_STRIP] + vertices + [CGO.END]
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def get_multiline_cgo(start, end, color, width=1.0):
|
|
279
|
+
"""
|
|
280
|
+
Get the CGO for one or multiple straight lines drawn from given
|
|
281
|
+
start to end positions.
|
|
282
|
+
|
|
283
|
+
Parameters
|
|
284
|
+
----------
|
|
285
|
+
start, end : array-like, shape=(3,) or shape=(n,3)
|
|
286
|
+
The *n* lines are drawn from the `start` to the `end` positions.
|
|
287
|
+
color : array-like, shape=(3,) or shape=(n,3)
|
|
288
|
+
The color of the lines given as RGB values in the range
|
|
289
|
+
*(0, 1)*.
|
|
290
|
+
Either one color can be given that is used for all lines or
|
|
291
|
+
an individual color for each line can be supplied.
|
|
292
|
+
width : float, optional
|
|
293
|
+
The rendered width of the lines.
|
|
294
|
+
The width is only visible after calling :func:`ray()`.
|
|
295
|
+
|
|
296
|
+
Returns
|
|
297
|
+
-------
|
|
298
|
+
cgo : list of float
|
|
299
|
+
The CGO representation.
|
|
300
|
+
"""
|
|
301
|
+
start = np.atleast_2d(start)
|
|
302
|
+
end = np.atleast_2d(end)
|
|
303
|
+
color = _arrayfy(color, len(start), 2)
|
|
304
|
+
|
|
305
|
+
if len(start) != len(end):
|
|
306
|
+
raise IndexError(
|
|
307
|
+
f"{len(start)} start positions are given, but {len(end)} end positions"
|
|
308
|
+
)
|
|
309
|
+
for p in start:
|
|
310
|
+
_expect_length(p, "start", 3)
|
|
311
|
+
for p in end:
|
|
312
|
+
_expect_length(p, "end", 3)
|
|
313
|
+
for c in color:
|
|
314
|
+
_expect_length(c, "color", 3)
|
|
315
|
+
_check_color(c)
|
|
316
|
+
|
|
317
|
+
vertices = []
|
|
318
|
+
for p1, p2, c in zip(start, end, color):
|
|
319
|
+
vertices += [CGO.COLOR, *c, CGO.VERTEX, *p1, CGO.VERTEX, *p2]
|
|
320
|
+
|
|
321
|
+
return [CGO.LINEWIDTH, width, CGO.BEGIN, CGO.LINES] + vertices + [CGO.END]
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def _expect_length(values, name, length):
|
|
325
|
+
if len(values) != length:
|
|
326
|
+
raise IndexError(
|
|
327
|
+
f"'{name}' has {len(values)} values, but {length} were expected"
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def _check_color(color):
|
|
332
|
+
if np.any(color) < 0 or np.any(color) > 1:
|
|
333
|
+
raise ValueError("Colors must be in range (0, 1)")
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def _arrayfy(value, length, min_dim):
|
|
337
|
+
"""
|
|
338
|
+
Expand value(s) to the given number of dimensions and repeat value
|
|
339
|
+
`length` number of times if only a single value is given.
|
|
340
|
+
"""
|
|
341
|
+
value = np.array(value, ndmin=min_dim)
|
|
342
|
+
if len(value) == 1 and length > 1:
|
|
343
|
+
value = np.repeat(value, length, axis=0)
|
|
344
|
+
elif len(value) != length:
|
|
345
|
+
raise IndexError(f"Expected {length} values, but got {len(value)}")
|
|
346
|
+
return value
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
__name__ = "biotite.interface.pymol"
|
|
2
|
+
__author__ = "Patrick Kunzmann"
|
|
3
|
+
__all__ = ["to_model", "from_model"]
|
|
4
|
+
|
|
5
|
+
import warnings
|
|
6
|
+
import numpy as np
|
|
7
|
+
from chempy import Atom, Bond
|
|
8
|
+
from chempy.models import Indexed as IndexedModel
|
|
9
|
+
import biotite.structure as struc
|
|
10
|
+
from biotite.interface import LossyConversionWarning
|
|
11
|
+
from biotite.sequence import ProteinSequence
|
|
12
|
+
|
|
13
|
+
# Bond orders in PyMOL (https://pymolwiki.org/index.php/Valence):
|
|
14
|
+
# 1: single bond, 2: double bond, 3:triple bond, 4:delocalized
|
|
15
|
+
_FORMAL_BOND_ORDER = {
|
|
16
|
+
struc.BondType.SINGLE: 1,
|
|
17
|
+
struc.BondType.DOUBLE: 2,
|
|
18
|
+
struc.BondType.TRIPLE: 3,
|
|
19
|
+
struc.BondType.AROMATIC_SINGLE: 1,
|
|
20
|
+
struc.BondType.AROMATIC_DOUBLE: 2,
|
|
21
|
+
}
|
|
22
|
+
_DELOKALIZED_BOND_ORDER = {
|
|
23
|
+
struc.BondType.SINGLE: 1,
|
|
24
|
+
struc.BondType.DOUBLE: 2,
|
|
25
|
+
struc.BondType.TRIPLE: 3,
|
|
26
|
+
struc.BondType.AROMATIC_SINGLE: 4,
|
|
27
|
+
struc.BondType.AROMATIC_DOUBLE: 4,
|
|
28
|
+
struc.BondType.AROMATIC: 4,
|
|
29
|
+
}
|
|
30
|
+
_BIOTITE_BOND_TYPES = {
|
|
31
|
+
1: struc.BondType.SINGLE,
|
|
32
|
+
2: struc.BondType.DOUBLE,
|
|
33
|
+
3: struc.BondType.TRIPLE,
|
|
34
|
+
4: struc.BondType.AROMATIC,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def to_model(atom_array, delocalize_bonds=False):
|
|
39
|
+
"""
|
|
40
|
+
Convert an :class:`AtomArray` into a :class:`chempy.models.Indexed`
|
|
41
|
+
object.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
atom_array : AtomArray
|
|
46
|
+
The structure to be converted.
|
|
47
|
+
delocalize_bonds : bool, optional
|
|
48
|
+
If set to true, use *PyMOL*'s delocalized bond order for aromatic bonds.
|
|
49
|
+
Otherwise, always use formal bond orders.
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
chempy_model : Indexed
|
|
54
|
+
The converted structure.
|
|
55
|
+
"""
|
|
56
|
+
if not np.isfinite(atom_array.coord).all():
|
|
57
|
+
raise ValueError("PyMOL does not support infinite or NaN coordinates")
|
|
58
|
+
|
|
59
|
+
model = IndexedModel()
|
|
60
|
+
|
|
61
|
+
annot_cat = atom_array.get_annotation_categories()
|
|
62
|
+
for i in range(atom_array.array_length()):
|
|
63
|
+
atom = Atom()
|
|
64
|
+
atom.segi = atom_array.chain_id[i]
|
|
65
|
+
atom.chain = atom_array.chain_id[i]
|
|
66
|
+
atom.resi_number = atom_array.res_id[i]
|
|
67
|
+
atom.ins_code = atom_array.ins_code[i]
|
|
68
|
+
res_name = atom_array.res_name[i]
|
|
69
|
+
atom.resn = res_name
|
|
70
|
+
if len(res_name) == 1:
|
|
71
|
+
atom.resn_code = res_name
|
|
72
|
+
else:
|
|
73
|
+
try:
|
|
74
|
+
atom.resn_code = ProteinSequence.convert_letter_3to1(res_name)
|
|
75
|
+
except KeyError:
|
|
76
|
+
atom.resn_code = "X"
|
|
77
|
+
atom.hetatm = 1 if atom_array.hetero[i] else 0
|
|
78
|
+
atom.name = atom_array.atom_name[i]
|
|
79
|
+
atom.symbol = atom_array.element[i]
|
|
80
|
+
if "b_factor" in annot_cat:
|
|
81
|
+
atom.b = atom_array.b_factor[i]
|
|
82
|
+
if "occupancy" in annot_cat:
|
|
83
|
+
atom.q = atom_array.occupancy[i]
|
|
84
|
+
if "charge" in annot_cat:
|
|
85
|
+
atom.formal_charge = atom_array.charge[i]
|
|
86
|
+
atom.coord = tuple(atom_array.coord[..., i, :])
|
|
87
|
+
atom.index = i + 1
|
|
88
|
+
model.add_atom(atom)
|
|
89
|
+
|
|
90
|
+
bond_order_mapping = (
|
|
91
|
+
_DELOKALIZED_BOND_ORDER if delocalize_bonds else _FORMAL_BOND_ORDER
|
|
92
|
+
)
|
|
93
|
+
unmappable_bond_types = []
|
|
94
|
+
if atom_array.bonds is not None:
|
|
95
|
+
for i, j, bond_type in atom_array.bonds.as_array():
|
|
96
|
+
bond = Bond()
|
|
97
|
+
order = bond_order_mapping.get(bond_type)
|
|
98
|
+
if order is None:
|
|
99
|
+
unmappable_bond_types.append(bond_type)
|
|
100
|
+
order = 1
|
|
101
|
+
bond.order = order
|
|
102
|
+
bond.index = [i, j]
|
|
103
|
+
model.add_bond(bond)
|
|
104
|
+
else:
|
|
105
|
+
warnings.warn("The given atom array (stack) has no associated bond information")
|
|
106
|
+
if unmappable_bond_types:
|
|
107
|
+
warnings.warn(
|
|
108
|
+
"The following bond types could not be mapped to PyMOL: "
|
|
109
|
+
+ ", ".join([struc.BondType(bt).name for bt in set(unmappable_bond_types)]),
|
|
110
|
+
LossyConversionWarning,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
return model
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def from_model(chempy_model, include_bonds=False):
|
|
117
|
+
"""
|
|
118
|
+
Convert a :class:`chempy.models.Indexed`
|
|
119
|
+
object into an :class:`AtomArray`.
|
|
120
|
+
|
|
121
|
+
The returned :class:`AtomArray` contains the optional annotation
|
|
122
|
+
categories ``b_factor``, ``occupancy``, ``charge`` and
|
|
123
|
+
``altloc_id``.
|
|
124
|
+
No *altloc* ID filtering is performed.
|
|
125
|
+
|
|
126
|
+
Parameters
|
|
127
|
+
----------
|
|
128
|
+
chempy_model : Indexed
|
|
129
|
+
The ``chempy`` model.
|
|
130
|
+
include_bonds : bool, optional
|
|
131
|
+
If set to true, an associated :class:`BondList` will be created
|
|
132
|
+
for the returned atom array.
|
|
133
|
+
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
atom_array : AtomArray
|
|
137
|
+
The converted structure.
|
|
138
|
+
"""
|
|
139
|
+
atoms = chempy_model.atom
|
|
140
|
+
|
|
141
|
+
bonds = chempy_model.bond
|
|
142
|
+
|
|
143
|
+
atom_array = struc.AtomArray(len(atoms))
|
|
144
|
+
|
|
145
|
+
# Add annotation arrays
|
|
146
|
+
atom_array.chain_id = np.array([a.chain for a in atoms], dtype="U3")
|
|
147
|
+
atom_array.res_id = np.array([a.resi_number for a in atoms], dtype=int)
|
|
148
|
+
atom_array.ins_code = np.array([a.ins_code for a in atoms], dtype="U1")
|
|
149
|
+
atom_array.res_name = np.array([a.resn for a in atoms], dtype="U3")
|
|
150
|
+
atom_array.hetero = np.array([a.hetatm for a in atoms], dtype=bool)
|
|
151
|
+
atom_array.atom_name = np.array([a.name for a in atoms], dtype="U6")
|
|
152
|
+
atom_array.element = np.array([a.symbol for a in atoms], dtype="U2")
|
|
153
|
+
|
|
154
|
+
atom_array.set_annotation(
|
|
155
|
+
"b_factor",
|
|
156
|
+
np.array([a.b if hasattr(a, "b") else 0 for a in atoms], dtype=float),
|
|
157
|
+
)
|
|
158
|
+
atom_array.set_annotation(
|
|
159
|
+
"occupancy",
|
|
160
|
+
np.array([a.q if hasattr(a, "q") else 1.0 for a in atoms], dtype=float),
|
|
161
|
+
)
|
|
162
|
+
atom_array.set_annotation(
|
|
163
|
+
"charge",
|
|
164
|
+
np.array(
|
|
165
|
+
[a.formal_charge if hasattr(a, "formal_charge") else 0 for a in atoms],
|
|
166
|
+
dtype=int,
|
|
167
|
+
),
|
|
168
|
+
)
|
|
169
|
+
atom_array.set_annotation(
|
|
170
|
+
"altloc_id",
|
|
171
|
+
np.array([a.alt if hasattr(a, "alt") else "" for a in atoms], dtype="U1"),
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
# Set coordinates
|
|
175
|
+
atom_array.coord = np.array([a.coord for a in atoms], dtype=np.float32)
|
|
176
|
+
|
|
177
|
+
# Add bonds
|
|
178
|
+
if include_bonds:
|
|
179
|
+
bond_array = np.array(
|
|
180
|
+
[[b.index[0], b.index[1], _BIOTITE_BOND_TYPES[b.order]] for b in bonds],
|
|
181
|
+
dtype=np.uint32,
|
|
182
|
+
)
|
|
183
|
+
atom_array.bonds = struc.BondList(len(atoms), bond_array)
|
|
184
|
+
|
|
185
|
+
return atom_array
|