biotite 0.41.1__cp310-cp310-win_amd64.whl → 1.0.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/__init__.py +2 -3
- biotite/application/__init__.py +36 -10
- biotite/application/application.py +22 -11
- biotite/application/autodock/__init__.py +1 -1
- biotite/application/autodock/app.py +74 -79
- biotite/application/blast/__init__.py +1 -1
- biotite/application/blast/alignment.py +19 -10
- biotite/application/blast/webapp.py +92 -85
- biotite/application/clustalo/__init__.py +1 -1
- biotite/application/clustalo/app.py +46 -61
- biotite/application/dssp/__init__.py +1 -1
- biotite/application/dssp/app.py +8 -11
- biotite/application/localapp.py +62 -60
- biotite/application/mafft/__init__.py +1 -1
- biotite/application/mafft/app.py +16 -22
- biotite/application/msaapp.py +78 -89
- biotite/application/muscle/__init__.py +1 -1
- biotite/application/muscle/app3.py +50 -64
- biotite/application/muscle/app5.py +23 -31
- biotite/application/sra/__init__.py +1 -1
- biotite/application/sra/app.py +64 -68
- biotite/application/tantan/__init__.py +1 -1
- biotite/application/tantan/app.py +22 -45
- biotite/application/util.py +7 -9
- biotite/application/viennarna/rnaalifold.py +34 -28
- biotite/application/viennarna/rnafold.py +24 -39
- biotite/application/viennarna/rnaplot.py +36 -21
- biotite/application/viennarna/util.py +17 -12
- biotite/application/webapp.py +13 -14
- biotite/copyable.py +13 -13
- biotite/database/__init__.py +1 -1
- biotite/database/entrez/__init__.py +1 -1
- biotite/database/entrez/check.py +2 -3
- biotite/database/entrez/dbnames.py +7 -5
- biotite/database/entrez/download.py +55 -49
- biotite/database/entrez/key.py +1 -1
- biotite/database/entrez/query.py +62 -23
- biotite/database/error.py +2 -1
- biotite/database/pubchem/__init__.py +1 -1
- biotite/database/pubchem/download.py +43 -45
- biotite/database/pubchem/error.py +2 -2
- biotite/database/pubchem/query.py +34 -31
- biotite/database/pubchem/throttle.py +3 -4
- biotite/database/rcsb/__init__.py +1 -1
- biotite/database/rcsb/download.py +44 -52
- biotite/database/rcsb/query.py +85 -80
- biotite/database/uniprot/check.py +6 -3
- biotite/database/uniprot/download.py +6 -11
- biotite/database/uniprot/query.py +115 -31
- biotite/file.py +12 -31
- biotite/sequence/__init__.py +16 -5
- biotite/sequence/align/__init__.py +160 -6
- biotite/sequence/align/alignment.py +99 -90
- biotite/sequence/align/banded.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/buckets.py +12 -10
- biotite/sequence/align/cigar.py +43 -52
- biotite/sequence/align/kmeralphabet.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/kmeralphabet.pyx +55 -51
- 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 +3 -2
- biotite/sequence/align/localgapped.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/localungapped.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/matrix.py +81 -82
- biotite/sequence/align/multiple.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/multiple.pyx +35 -35
- biotite/sequence/align/pairwise.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/permutation.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/permutation.pyx +12 -4
- biotite/sequence/align/selector.cp310-win_amd64.pyd +0 -0
- biotite/sequence/align/selector.pyx +52 -54
- biotite/sequence/align/statistics.py +32 -33
- biotite/sequence/align/tracetable.cp310-win_amd64.pyd +0 -0
- biotite/sequence/alphabet.py +112 -126
- biotite/sequence/annotation.py +78 -77
- biotite/sequence/codec.cp310-win_amd64.pyd +0 -0
- biotite/sequence/codon.py +90 -79
- biotite/sequence/graphics/__init__.py +1 -1
- biotite/sequence/graphics/alignment.py +184 -103
- biotite/sequence/graphics/colorschemes.py +10 -12
- biotite/sequence/graphics/dendrogram.py +79 -34
- biotite/sequence/graphics/features.py +133 -99
- biotite/sequence/graphics/logo.py +22 -28
- biotite/sequence/graphics/plasmid.py +229 -178
- biotite/sequence/io/fasta/__init__.py +1 -1
- biotite/sequence/io/fasta/convert.py +44 -33
- biotite/sequence/io/fasta/file.py +42 -55
- biotite/sequence/io/fastq/__init__.py +1 -1
- biotite/sequence/io/fastq/convert.py +11 -14
- biotite/sequence/io/fastq/file.py +68 -112
- biotite/sequence/io/genbank/__init__.py +2 -2
- biotite/sequence/io/genbank/annotation.py +12 -20
- biotite/sequence/io/genbank/file.py +74 -76
- biotite/sequence/io/genbank/metadata.py +74 -62
- biotite/sequence/io/genbank/sequence.py +13 -14
- biotite/sequence/io/general.py +39 -30
- biotite/sequence/io/gff/__init__.py +2 -2
- biotite/sequence/io/gff/convert.py +10 -15
- biotite/sequence/io/gff/file.py +81 -65
- biotite/sequence/phylo/__init__.py +1 -1
- 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 +57 -28
- biotite/sequence/search.py +17 -15
- biotite/sequence/seqtypes.py +200 -164
- biotite/sequence/sequence.py +64 -64
- biotite/structure/__init__.py +3 -3
- biotite/structure/atoms.py +226 -240
- biotite/structure/basepairs.py +260 -271
- biotite/structure/bonds.cp310-win_amd64.pyd +0 -0
- biotite/structure/bonds.pyx +88 -100
- biotite/structure/box.py +67 -71
- biotite/structure/celllist.cp310-win_amd64.pyd +0 -0
- biotite/structure/chains.py +55 -39
- biotite/structure/charges.cp310-win_amd64.pyd +0 -0
- biotite/structure/compare.py +32 -32
- biotite/structure/density.py +13 -18
- biotite/structure/dotbracket.py +20 -22
- biotite/structure/error.py +10 -2
- biotite/structure/filter.py +82 -77
- biotite/structure/geometry.py +130 -119
- biotite/structure/graphics/atoms.py +60 -43
- biotite/structure/graphics/rna.py +81 -68
- biotite/structure/hbond.py +112 -93
- biotite/structure/info/__init__.py +0 -2
- biotite/structure/info/atoms.py +10 -11
- biotite/structure/info/bonds.py +41 -43
- biotite/structure/info/ccd.py +21 -7
- biotite/structure/info/groups.py +10 -15
- biotite/structure/info/masses.py +5 -10
- biotite/structure/info/misc.py +1 -1
- biotite/structure/info/radii.py +20 -20
- biotite/structure/info/standardize.py +15 -26
- biotite/structure/integrity.py +18 -71
- biotite/structure/io/__init__.py +3 -4
- biotite/structure/io/dcd/__init__.py +1 -1
- biotite/structure/io/dcd/file.py +22 -20
- biotite/structure/io/general.py +47 -61
- biotite/structure/io/gro/__init__.py +1 -1
- biotite/structure/io/gro/file.py +73 -72
- biotite/structure/io/mol/__init__.py +1 -1
- biotite/structure/io/mol/convert.py +8 -11
- biotite/structure/io/mol/ctab.py +37 -36
- biotite/structure/io/mol/header.py +14 -10
- biotite/structure/io/mol/mol.py +9 -53
- biotite/structure/io/mol/sdf.py +47 -50
- biotite/structure/io/netcdf/__init__.py +1 -1
- biotite/structure/io/netcdf/file.py +24 -23
- biotite/structure/io/pdb/__init__.py +1 -1
- biotite/structure/io/pdb/convert.py +32 -20
- biotite/structure/io/pdb/file.py +151 -172
- biotite/structure/io/pdb/hybrid36.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/pdbqt/__init__.py +1 -1
- biotite/structure/io/pdbqt/convert.py +17 -11
- biotite/structure/io/pdbqt/file.py +128 -80
- biotite/structure/io/pdbx/__init__.py +1 -2
- biotite/structure/io/pdbx/bcif.py +36 -52
- biotite/structure/io/pdbx/cif.py +64 -62
- biotite/structure/io/pdbx/component.py +10 -16
- biotite/structure/io/pdbx/convert.py +235 -246
- biotite/structure/io/pdbx/encoding.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/trajfile.py +76 -93
- biotite/structure/io/trr/__init__.py +1 -1
- biotite/structure/io/trr/file.py +12 -15
- biotite/structure/io/xtc/__init__.py +1 -1
- biotite/structure/io/xtc/file.py +11 -14
- biotite/structure/mechanics.py +9 -11
- biotite/structure/molecules.py +3 -4
- biotite/structure/pseudoknots.py +53 -67
- biotite/structure/rdf.py +23 -21
- biotite/structure/repair.py +137 -86
- biotite/structure/residues.py +26 -16
- biotite/structure/sasa.cp310-win_amd64.pyd +0 -0
- biotite/structure/{resutil.py → segments.py} +24 -23
- biotite/structure/sequence.py +10 -11
- biotite/structure/sse.py +100 -119
- biotite/structure/superimpose.py +39 -77
- biotite/structure/transform.py +97 -71
- biotite/structure/util.py +11 -13
- biotite/version.py +2 -2
- biotite/visualize.py +69 -55
- {biotite-0.41.1.dist-info → biotite-1.0.0.dist-info}/METADATA +6 -6
- biotite-1.0.0.dist-info/RECORD +322 -0
- {biotite-0.41.1.dist-info → biotite-1.0.0.dist-info}/WHEEL +1 -1
- biotite/structure/io/ctab.py +0 -72
- biotite/structure/io/mmtf/__init__.py +0 -21
- biotite/structure/io/mmtf/assembly.py +0 -214
- biotite/structure/io/mmtf/convertarray.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/convertarray.pyx +0 -341
- biotite/structure/io/mmtf/convertfile.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/convertfile.pyx +0 -501
- biotite/structure/io/mmtf/decode.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/decode.pyx +0 -152
- biotite/structure/io/mmtf/encode.cp310-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/encode.pyx +0 -183
- biotite/structure/io/mmtf/file.py +0 -233
- biotite/structure/io/npz/__init__.py +0 -20
- biotite/structure/io/npz/file.py +0 -152
- biotite/structure/io/pdbx/legacy.py +0 -267
- biotite/structure/io/tng/__init__.py +0 -13
- biotite/structure/io/tng/file.py +0 -46
- biotite/temp.py +0 -86
- biotite-0.41.1.dist-info/RECORD +0 -340
- {biotite-0.41.1.dist-info → biotite-1.0.0.dist-info}/licenses/LICENSE.rst +0 -0
biotite/structure/transform.py
CHANGED
|
@@ -9,20 +9,25 @@ that can be applied on structures.
|
|
|
9
9
|
|
|
10
10
|
__name__ = "biotite.structure"
|
|
11
11
|
__author__ = "Patrick Kunzmann", "Claude J. Rogers"
|
|
12
|
-
__all__ = [
|
|
13
|
-
|
|
12
|
+
__all__ = [
|
|
13
|
+
"translate",
|
|
14
|
+
"rotate",
|
|
15
|
+
"rotate_centered",
|
|
16
|
+
"rotate_about_axis",
|
|
17
|
+
"orient_principal_components",
|
|
18
|
+
"align_vectors",
|
|
19
|
+
]
|
|
14
20
|
|
|
15
21
|
import numpy as np
|
|
16
|
-
from .
|
|
17
|
-
from .
|
|
18
|
-
from .
|
|
19
|
-
from .util import norm_vector, vector_dot, matrix_rotate
|
|
22
|
+
from biotite.structure.atoms import Atom, AtomArray, AtomArrayStack, coord
|
|
23
|
+
from biotite.structure.geometry import centroid
|
|
24
|
+
from biotite.structure.util import matrix_rotate, norm_vector, vector_dot
|
|
20
25
|
|
|
21
26
|
|
|
22
27
|
def translate(atoms, vector):
|
|
23
28
|
"""
|
|
24
29
|
Translate the given atoms or coordinates by a given vector.
|
|
25
|
-
|
|
30
|
+
|
|
26
31
|
Parameters
|
|
27
32
|
----------
|
|
28
33
|
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
@@ -30,7 +35,7 @@ def translate(atoms, vector):
|
|
|
30
35
|
The coordinates can be directly provided as :class:`ndarray`.
|
|
31
36
|
vector: array-like, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
32
37
|
The translation vector :math:`(x, y, z)`.
|
|
33
|
-
|
|
38
|
+
|
|
34
39
|
Returns
|
|
35
40
|
-------
|
|
36
41
|
transformed : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
@@ -39,7 +44,7 @@ def translate(atoms, vector):
|
|
|
39
44
|
"""
|
|
40
45
|
positions = coord(atoms).copy()
|
|
41
46
|
vector = np.asarray(vector)
|
|
42
|
-
|
|
47
|
+
|
|
43
48
|
if vector.shape[-1] != 3:
|
|
44
49
|
raise ValueError("Translation vector must contain 3 coordinates")
|
|
45
50
|
positions += vector
|
|
@@ -50,10 +55,10 @@ def rotate(atoms, angles):
|
|
|
50
55
|
"""
|
|
51
56
|
Rotate the given atoms or coordinates about the *x*, *y* and *z*
|
|
52
57
|
axes by given angles.
|
|
53
|
-
|
|
58
|
+
|
|
54
59
|
The rotations are centered at the origin and are performed
|
|
55
60
|
sequentially in the order *x*, *y*, *z*.
|
|
56
|
-
|
|
61
|
+
|
|
57
62
|
Parameters
|
|
58
63
|
----------
|
|
59
64
|
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
@@ -61,13 +66,13 @@ def rotate(atoms, angles):
|
|
|
61
66
|
The coordinates can be directly provided as :class:`ndarray`.
|
|
62
67
|
angles: array-like, length=3
|
|
63
68
|
The rotation angles in radians around *x*, *y* and *z*.
|
|
64
|
-
|
|
69
|
+
|
|
65
70
|
Returns
|
|
66
71
|
-------
|
|
67
72
|
transformed : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
68
73
|
A copy of the input atoms or coordinates, rotated by the given
|
|
69
74
|
angles.
|
|
70
|
-
|
|
75
|
+
|
|
71
76
|
See Also
|
|
72
77
|
--------
|
|
73
78
|
rotate_centered
|
|
@@ -82,27 +87,39 @@ def rotate(atoms, angles):
|
|
|
82
87
|
>>> print(rotated)
|
|
83
88
|
[1.225e-16 2.000e+00 0.000e+00]
|
|
84
89
|
"""
|
|
85
|
-
from numpy import
|
|
90
|
+
from numpy import cos, sin
|
|
86
91
|
|
|
87
92
|
# Check if "angles" contains 3 angles for all dimensions
|
|
88
93
|
if len(angles) != 3:
|
|
89
94
|
raise ValueError("Translation vector must be container of length 3")
|
|
90
95
|
# Create rotation matrices for all 3 dimensions
|
|
91
|
-
rot_x = np.array(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
rot_x = np.array(
|
|
97
|
+
[
|
|
98
|
+
[1, 0, 0],
|
|
99
|
+
[0, cos(angles[0]), -sin(angles[0])],
|
|
100
|
+
[0, sin(angles[0]), cos(angles[0])],
|
|
101
|
+
]
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
rot_y = np.array(
|
|
105
|
+
[
|
|
106
|
+
[cos(angles[1]), 0, sin(angles[1])],
|
|
107
|
+
[0, 1, 0],
|
|
108
|
+
[-sin(angles[1]), 0, cos(angles[1])],
|
|
109
|
+
]
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
rot_z = np.array(
|
|
113
|
+
[
|
|
114
|
+
[cos(angles[2]), -sin(angles[2]), 0],
|
|
115
|
+
[sin(angles[2]), cos(angles[2]), 0],
|
|
116
|
+
[0, 0, 1],
|
|
117
|
+
]
|
|
118
|
+
)
|
|
119
|
+
|
|
103
120
|
positions = coord(atoms).copy()
|
|
104
121
|
positions = matrix_rotate(positions, rot_z @ rot_y @ rot_x)
|
|
105
|
-
|
|
122
|
+
|
|
106
123
|
return _put_back(atoms, positions)
|
|
107
124
|
|
|
108
125
|
|
|
@@ -110,10 +127,10 @@ def rotate_centered(atoms, angles):
|
|
|
110
127
|
"""
|
|
111
128
|
Rotate the given atoms or coordinates about the *x*, *y* and *z*
|
|
112
129
|
axes by given angles.
|
|
113
|
-
|
|
130
|
+
|
|
114
131
|
The rotations are centered at the centroid of the corresponding
|
|
115
132
|
structure and are performed sequentially in the order *x*, *y*, *z*.
|
|
116
|
-
|
|
133
|
+
|
|
117
134
|
Parameters
|
|
118
135
|
----------
|
|
119
136
|
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
@@ -121,13 +138,13 @@ def rotate_centered(atoms, angles):
|
|
|
121
138
|
The coordinates can be directly provided as :class:`ndarray`.
|
|
122
139
|
angles: array-like, length=3
|
|
123
140
|
The rotation angles in radians around axes *x*, *y* and *z*.
|
|
124
|
-
|
|
141
|
+
|
|
125
142
|
Returns
|
|
126
143
|
-------
|
|
127
144
|
transformed : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
128
145
|
A copy of the input atoms or coordinates, rotated by the given
|
|
129
146
|
angles.
|
|
130
|
-
|
|
147
|
+
|
|
131
148
|
See Also
|
|
132
149
|
--------
|
|
133
150
|
rotate
|
|
@@ -136,7 +153,7 @@ def rotate_centered(atoms, angles):
|
|
|
136
153
|
if len(coord(atoms).shape) == 1:
|
|
137
154
|
# Single value -> centered rotation does not change coordinates
|
|
138
155
|
return atoms.copy()
|
|
139
|
-
|
|
156
|
+
|
|
140
157
|
# Rotation around centroid requires moving centroid to origin
|
|
141
158
|
center = coord(centroid(atoms))
|
|
142
159
|
# 'centroid()' removes the second last dimesion
|
|
@@ -152,7 +169,7 @@ def rotate_about_axis(atoms, axis, angle, support=None):
|
|
|
152
169
|
"""
|
|
153
170
|
Rotate the given atoms or coordinates about a given axis by a given
|
|
154
171
|
angle.
|
|
155
|
-
|
|
172
|
+
|
|
156
173
|
Parameters
|
|
157
174
|
----------
|
|
158
175
|
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
@@ -167,13 +184,13 @@ def rotate_about_axis(atoms, axis, angle, support=None):
|
|
|
167
184
|
An optional support vector for the rotation axis, i.e. the
|
|
168
185
|
center of the rotation.
|
|
169
186
|
By default, the center of the rotation is at *(0,0,0)*.
|
|
170
|
-
|
|
187
|
+
|
|
171
188
|
Returns
|
|
172
189
|
-------
|
|
173
190
|
transformed : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
174
191
|
A copy of the input atoms or coordinates, rotated about the
|
|
175
192
|
given axis.
|
|
176
|
-
|
|
193
|
+
|
|
177
194
|
See Also
|
|
178
195
|
--------
|
|
179
196
|
rotate
|
|
@@ -194,7 +211,7 @@ def rotate_about_axis(atoms, axis, angle, support=None):
|
|
|
194
211
|
# Transform coordinates
|
|
195
212
|
# so that the axis support vector is at (0,0,0)
|
|
196
213
|
positions -= np.asarray(support)
|
|
197
|
-
|
|
214
|
+
|
|
198
215
|
# Normalize axis
|
|
199
216
|
axis = np.asarray(axis, dtype=np.float32).copy()
|
|
200
217
|
if np.linalg.norm(axis) == 0:
|
|
@@ -205,16 +222,30 @@ def rotate_about_axis(atoms, axis, angle, support=None):
|
|
|
205
222
|
sin_a = np.sin(angle)
|
|
206
223
|
cos_a = np.cos(angle)
|
|
207
224
|
icos_a = 1 - cos_a
|
|
208
|
-
x = axis[...,0]
|
|
209
|
-
y = axis[...,1]
|
|
210
|
-
z = axis[...,2]
|
|
225
|
+
x = axis[..., 0]
|
|
226
|
+
y = axis[..., 1]
|
|
227
|
+
z = axis[..., 2]
|
|
211
228
|
# Rotation matrix is taken from
|
|
212
229
|
# https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
|
|
213
|
-
rot_matrix = np.array(
|
|
214
|
-
[
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
230
|
+
rot_matrix = np.array(
|
|
231
|
+
[
|
|
232
|
+
[
|
|
233
|
+
cos_a + icos_a * x**2,
|
|
234
|
+
icos_a * x * y - z * sin_a,
|
|
235
|
+
icos_a * x * z + y * sin_a,
|
|
236
|
+
],
|
|
237
|
+
[
|
|
238
|
+
icos_a * x * y + z * sin_a,
|
|
239
|
+
cos_a + icos_a * y**2,
|
|
240
|
+
icos_a * y * z - x * sin_a,
|
|
241
|
+
],
|
|
242
|
+
[
|
|
243
|
+
icos_a * x * z - y * sin_a,
|
|
244
|
+
icos_a * y * z + x * sin_a,
|
|
245
|
+
cos_a + icos_a * z**2,
|
|
246
|
+
],
|
|
247
|
+
]
|
|
248
|
+
)
|
|
218
249
|
|
|
219
250
|
# For proper rotation reshape into a maximum of 2 dimensions
|
|
220
251
|
orig_ndim = positions.ndim
|
|
@@ -230,7 +261,7 @@ def rotate_about_axis(atoms, axis, angle, support=None):
|
|
|
230
261
|
if support is not None:
|
|
231
262
|
# Transform coordinates back to original support vector position
|
|
232
263
|
positions += np.asarray(support)
|
|
233
|
-
|
|
264
|
+
|
|
234
265
|
return _put_back(atoms, positions)
|
|
235
266
|
|
|
236
267
|
|
|
@@ -298,9 +329,7 @@ def orient_principal_components(atoms, order=None):
|
|
|
298
329
|
else:
|
|
299
330
|
order = np.asarray(order, dtype=int)
|
|
300
331
|
if order.shape != (3,):
|
|
301
|
-
raise ValueError(
|
|
302
|
-
f"Expected order to have shape (3,), not {order.shape}"
|
|
303
|
-
)
|
|
332
|
+
raise ValueError(f"Expected order to have shape (3,), not {order.shape}")
|
|
304
333
|
if not (np.sort(order) == np.arange(3)).all():
|
|
305
334
|
raise ValueError("Expected order to contain [0, 1, 2].")
|
|
306
335
|
|
|
@@ -333,8 +362,13 @@ def orient_principal_components(atoms, order=None):
|
|
|
333
362
|
return _put_back(atoms, centered)
|
|
334
363
|
|
|
335
364
|
|
|
336
|
-
def align_vectors(
|
|
337
|
-
|
|
365
|
+
def align_vectors(
|
|
366
|
+
atoms,
|
|
367
|
+
origin_direction,
|
|
368
|
+
target_direction,
|
|
369
|
+
origin_position=None,
|
|
370
|
+
target_position=None,
|
|
371
|
+
):
|
|
338
372
|
"""
|
|
339
373
|
Apply a transformation to atoms or coordinates, that would transfer
|
|
340
374
|
a origin vector to a target vector.
|
|
@@ -345,8 +379,8 @@ def align_vectors(atoms, origin_direction, target_direction,
|
|
|
345
379
|
This means, that the application of the transformation on the
|
|
346
380
|
origin vector would give the target vector.
|
|
347
381
|
Then the same transformation is applied to the given
|
|
348
|
-
atoms/coordinates.
|
|
349
|
-
|
|
382
|
+
atoms/coordinates.
|
|
383
|
+
|
|
350
384
|
Parameters
|
|
351
385
|
----------
|
|
352
386
|
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
@@ -359,13 +393,13 @@ def align_vectors(atoms, origin_direction, target_direction,
|
|
|
359
393
|
origin_position, target_position : array-like, length=3, optional
|
|
360
394
|
Optional support vectors for the origin or target, respectively.
|
|
361
395
|
By default, origin and target start at *(0,0,0)*.
|
|
362
|
-
|
|
396
|
+
|
|
363
397
|
Returns
|
|
364
398
|
-------
|
|
365
399
|
transformed : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
366
400
|
A copy of the input atoms or coordinates with the applied
|
|
367
401
|
transformation.
|
|
368
|
-
|
|
402
|
+
|
|
369
403
|
See Also
|
|
370
404
|
--------
|
|
371
405
|
rotate
|
|
@@ -428,12 +462,8 @@ def align_vectors(atoms, origin_direction, target_direction,
|
|
|
428
462
|
A 2 LEU HD22 H -6.255 7.544 -2.657
|
|
429
463
|
A 2 LEU HD23 H -5.592 8.445 -1.281
|
|
430
464
|
"""
|
|
431
|
-
origin_direction = np.asarray(
|
|
432
|
-
|
|
433
|
-
).squeeze()
|
|
434
|
-
target_direction = np.asarray(
|
|
435
|
-
target_direction, dtype=np.float32
|
|
436
|
-
).squeeze()
|
|
465
|
+
origin_direction = np.asarray(origin_direction, dtype=np.float32).squeeze()
|
|
466
|
+
target_direction = np.asarray(target_direction, dtype=np.float32).squeeze()
|
|
437
467
|
# check that original and target direction are vectors of shape (3,)
|
|
438
468
|
if origin_direction.shape != (3,):
|
|
439
469
|
raise ValueError(
|
|
@@ -449,9 +479,9 @@ def align_vectors(atoms, origin_direction, target_direction,
|
|
|
449
479
|
raise ValueError("Length of the origin vector is 0")
|
|
450
480
|
if np.linalg.norm(target_direction) == 0:
|
|
451
481
|
raise ValueError("Length of the target vector is 0")
|
|
452
|
-
if origin_position is not None:
|
|
482
|
+
if origin_position is not None:
|
|
453
483
|
origin_position = np.asarray(origin_position, dtype=np.float32)
|
|
454
|
-
if target_position is not None:
|
|
484
|
+
if target_position is not None:
|
|
455
485
|
target_position = np.asarray(target_position, dtype=np.float32)
|
|
456
486
|
|
|
457
487
|
positions = coord(atoms).copy()
|
|
@@ -459,7 +489,7 @@ def align_vectors(atoms, origin_direction, target_direction,
|
|
|
459
489
|
# Transform coordinates
|
|
460
490
|
# so that the position of the origin vector is at (0,0,0)
|
|
461
491
|
positions -= origin_position
|
|
462
|
-
|
|
492
|
+
|
|
463
493
|
# Normalize direction vectors
|
|
464
494
|
origin_direction = origin_direction.copy()
|
|
465
495
|
norm_vector(origin_direction)
|
|
@@ -468,11 +498,7 @@ def align_vectors(atoms, origin_direction, target_direction,
|
|
|
468
498
|
# Formula is taken from
|
|
469
499
|
# https://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d/476311#476311
|
|
470
500
|
vx, vy, vz = np.cross(origin_direction, target_direction)
|
|
471
|
-
v_c = np.array([
|
|
472
|
-
[ 0, -vz, vy],
|
|
473
|
-
[ vz, 0, -vx],
|
|
474
|
-
[-vy, vx, 0]
|
|
475
|
-
], dtype=float)
|
|
501
|
+
v_c = np.array([[0, -vz, vy], [vz, 0, -vx], [-vy, vx, 0]], dtype=float)
|
|
476
502
|
cos_a = vector_dot(origin_direction, target_direction)
|
|
477
503
|
if np.all(cos_a == -1):
|
|
478
504
|
raise ValueError(
|
|
@@ -480,9 +506,9 @@ def align_vectors(atoms, origin_direction, target_direction,
|
|
|
480
506
|
"cannot calculate rotation matrix"
|
|
481
507
|
)
|
|
482
508
|
rot_matrix = np.identity(3) + v_c + (v_c @ v_c) / (1 + cos_a)
|
|
483
|
-
|
|
509
|
+
|
|
484
510
|
positions = matrix_rotate(positions, rot_matrix)
|
|
485
|
-
|
|
511
|
+
|
|
486
512
|
if target_position is not None:
|
|
487
513
|
# Transform coordinates to position of the target vector
|
|
488
514
|
positions += target_position
|
|
@@ -501,4 +527,4 @@ def _put_back(input_atoms, transformed):
|
|
|
501
527
|
moved_atoms.coord = transformed
|
|
502
528
|
return moved_atoms
|
|
503
529
|
else:
|
|
504
|
-
return transformed
|
|
530
|
+
return transformed
|
biotite/structure/util.py
CHANGED
|
@@ -11,31 +11,30 @@ __author__ = "Patrick Kunzmann"
|
|
|
11
11
|
__all__ = ["vector_dot", "norm_vector", "distance", "matrix_rotate"]
|
|
12
12
|
|
|
13
13
|
import numpy as np
|
|
14
|
-
from .atoms import Atom, array
|
|
15
14
|
|
|
16
15
|
|
|
17
|
-
def vector_dot(v1,v2):
|
|
16
|
+
def vector_dot(v1, v2):
|
|
18
17
|
"""
|
|
19
18
|
Calculate vector dot product of two vectors.
|
|
20
|
-
|
|
19
|
+
|
|
21
20
|
Parameters
|
|
22
21
|
----------
|
|
23
22
|
v1,v2 : ndarray
|
|
24
23
|
The arrays to calculate the product from.
|
|
25
24
|
The vectors are represented by the last axis.
|
|
26
|
-
|
|
25
|
+
|
|
27
26
|
Returns
|
|
28
27
|
-------
|
|
29
28
|
product : float or ndarray
|
|
30
29
|
Scalar product over the last dimension of the arrays.
|
|
31
30
|
"""
|
|
32
|
-
return (v1*v2).sum(axis=-1)
|
|
31
|
+
return (v1 * v2).sum(axis=-1)
|
|
33
32
|
|
|
34
33
|
|
|
35
34
|
def norm_vector(v):
|
|
36
35
|
"""
|
|
37
36
|
Normalise a vector.
|
|
38
|
-
|
|
37
|
+
|
|
39
38
|
Parameters
|
|
40
39
|
----------
|
|
41
40
|
v : ndarray
|
|
@@ -47,25 +46,25 @@ def norm_vector(v):
|
|
|
47
46
|
v /= factor[..., np.newaxis]
|
|
48
47
|
else:
|
|
49
48
|
v /= factor
|
|
50
|
-
|
|
51
49
|
|
|
52
|
-
|
|
50
|
+
|
|
51
|
+
def distance(v1, v2):
|
|
53
52
|
"""
|
|
54
53
|
Calculate the distance between two position vectors.
|
|
55
|
-
|
|
54
|
+
|
|
56
55
|
Parameters
|
|
57
56
|
----------
|
|
58
57
|
v1,v2 : ndarray
|
|
59
58
|
The arrays to calculate the product from.
|
|
60
59
|
The vectors are represented by the last axis.
|
|
61
|
-
|
|
60
|
+
|
|
62
61
|
Returns
|
|
63
62
|
-------
|
|
64
63
|
product : float or ndarray
|
|
65
64
|
Vector distance over the last dimension of the array.
|
|
66
65
|
"""
|
|
67
66
|
dif = v1 - v2
|
|
68
|
-
return np.sqrt((dif*dif).sum(axis=-1))
|
|
67
|
+
return np.sqrt((dif * dif).sum(axis=-1))
|
|
69
68
|
|
|
70
69
|
|
|
71
70
|
def matrix_rotate(v, matrix):
|
|
@@ -78,7 +77,7 @@ def matrix_rotate(v, matrix):
|
|
|
78
77
|
The coordinates to rotate.
|
|
79
78
|
matrix : ndarray
|
|
80
79
|
The rotation matrix.
|
|
81
|
-
|
|
80
|
+
|
|
82
81
|
Returns
|
|
83
82
|
-------
|
|
84
83
|
rotated : ndarray
|
|
@@ -95,4 +94,3 @@ def matrix_rotate(v, matrix):
|
|
|
95
94
|
if orig_ndim > 2:
|
|
96
95
|
v = v.reshape(*orig_shape)
|
|
97
96
|
return v
|
|
98
|
-
|
biotite/version.py
CHANGED
biotite/visualize.py
CHANGED
|
@@ -6,25 +6,25 @@ __name__ = "biotite"
|
|
|
6
6
|
__author__ = "Patrick Kunzmann"
|
|
7
7
|
__all__ = ["colors", "set_font_size_in_coord", "AdaptiveFancyArrow"]
|
|
8
8
|
|
|
9
|
-
import abc
|
|
10
9
|
from collections import OrderedDict
|
|
11
10
|
import numpy as np
|
|
12
11
|
from numpy.linalg import norm
|
|
13
12
|
|
|
14
|
-
|
|
15
13
|
# Biotite themed colors
|
|
16
|
-
colors = OrderedDict(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
14
|
+
colors = OrderedDict(
|
|
15
|
+
[
|
|
16
|
+
("brightorange", "#ffb569ff"),
|
|
17
|
+
("lightorange", "#ff982dff"),
|
|
18
|
+
("orange", "#ff8405ff"),
|
|
19
|
+
("dimorange", "#dc7000ff"),
|
|
20
|
+
("darkorange", "#b45c00ff"),
|
|
21
|
+
("brightgreen", "#98e97fff"),
|
|
22
|
+
("lightgreen", "#6fe04cff"),
|
|
23
|
+
("green", "#52da2aff"),
|
|
24
|
+
("dimgreen", "#45bc20ff"),
|
|
25
|
+
("darkgreen", "#389a1aff"),
|
|
26
|
+
]
|
|
27
|
+
)
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
|
|
@@ -75,8 +75,8 @@ def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
|
|
|
75
75
|
This behavior is not equal for all initial font sizes (in 'pt'),
|
|
76
76
|
the boundaries for an initial size of 1 'pt' seem to be most exact.
|
|
77
77
|
"""
|
|
78
|
-
from matplotlib.transforms import Bbox, Affine2D
|
|
79
78
|
from matplotlib.patheffects import AbstractPathEffect
|
|
79
|
+
from matplotlib.transforms import Affine2D, Bbox
|
|
80
80
|
|
|
81
81
|
class TextScaler(AbstractPathEffect):
|
|
82
82
|
def __init__(self, text, width, height, mode):
|
|
@@ -85,11 +85,11 @@ def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
|
|
|
85
85
|
self._width = width
|
|
86
86
|
self._height = height
|
|
87
87
|
|
|
88
|
-
def draw_path(self, renderer, gc, tpath, affine, rgbFace=None):
|
|
88
|
+
def draw_path(self, renderer, gc, tpath, affine, rgbFace=None): # noqa: N803
|
|
89
89
|
ax = self._text.axes
|
|
90
90
|
try:
|
|
91
91
|
renderer = ax.get_figure().canvas.get_renderer()
|
|
92
|
-
except:
|
|
92
|
+
except Exception:
|
|
93
93
|
# Use cached renderer for backends, where
|
|
94
94
|
# `get_renderer()` is not available
|
|
95
95
|
# Based on the strategy from `Text.get_window_extent()`
|
|
@@ -127,25 +127,21 @@ def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
|
|
|
127
127
|
|
|
128
128
|
if mode in ["unlocked", "minimum", "maximum"]:
|
|
129
129
|
if width is None or height is None:
|
|
130
|
-
raise TypeError(
|
|
131
|
-
f"Width and height must be set in '{mode}' mode"
|
|
132
|
-
)
|
|
130
|
+
raise TypeError(f"Width and height must be set in '{mode}' mode")
|
|
133
131
|
elif mode == "proportional":
|
|
134
|
-
if
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
)
|
|
132
|
+
if not (width is None and height is not None) or not (
|
|
133
|
+
height is None and width is not None
|
|
134
|
+
):
|
|
135
|
+
raise TypeError(f"Either width or height must be set in '{mode}' mode")
|
|
139
136
|
else:
|
|
140
|
-
raise ValueError(
|
|
141
|
-
f"Unknown mode '{mode}'"
|
|
142
|
-
)
|
|
137
|
+
raise ValueError(f"Unknown mode '{mode}'")
|
|
143
138
|
text.set_path_effects([TextScaler(text, width, height, mode)])
|
|
144
139
|
|
|
140
|
+
|
|
145
141
|
try:
|
|
146
142
|
# Only create this class when matplotlib is installed
|
|
147
|
-
from matplotlib.transforms import Bbox
|
|
148
143
|
from matplotlib.patches import FancyArrow
|
|
144
|
+
from matplotlib.transforms import Bbox
|
|
149
145
|
|
|
150
146
|
class AdaptiveFancyArrow(FancyArrow):
|
|
151
147
|
"""
|
|
@@ -177,9 +173,19 @@ try:
|
|
|
177
173
|
`FancyArrow`.
|
|
178
174
|
"""
|
|
179
175
|
|
|
180
|
-
def __init__(
|
|
181
|
-
|
|
182
|
-
|
|
176
|
+
def __init__(
|
|
177
|
+
self,
|
|
178
|
+
x,
|
|
179
|
+
y,
|
|
180
|
+
dx,
|
|
181
|
+
dy,
|
|
182
|
+
tail_width,
|
|
183
|
+
head_width,
|
|
184
|
+
head_ratio,
|
|
185
|
+
draw_head=True,
|
|
186
|
+
shape="full",
|
|
187
|
+
**kwargs,
|
|
188
|
+
):
|
|
183
189
|
self._x = x
|
|
184
190
|
self._y = y
|
|
185
191
|
self._dx = dx
|
|
@@ -193,23 +199,25 @@ try:
|
|
|
193
199
|
if not draw_head:
|
|
194
200
|
head_width = tail_width
|
|
195
201
|
super().__init__(
|
|
196
|
-
x,
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
202
|
+
x,
|
|
203
|
+
y,
|
|
204
|
+
dx,
|
|
205
|
+
dy,
|
|
206
|
+
width=tail_width,
|
|
207
|
+
head_width=head_width,
|
|
208
|
+
overhang=0,
|
|
209
|
+
shape=shape,
|
|
210
|
+
length_includes_head=True,
|
|
211
|
+
**kwargs,
|
|
200
212
|
)
|
|
201
213
|
|
|
202
214
|
def draw(self, renderer):
|
|
203
|
-
arrow_box = Bbox([(0,0), (0,self._head_width)])
|
|
215
|
+
arrow_box = Bbox([(0, 0), (0, self._head_width)])
|
|
204
216
|
arrow_box_display = self.axes.transData.transform_bbox(arrow_box)
|
|
205
|
-
head_length_display = np.abs(
|
|
206
|
-
arrow_box_display.height * self._head_ratio
|
|
207
|
-
)
|
|
217
|
+
head_length_display = np.abs(arrow_box_display.height * self._head_ratio)
|
|
208
218
|
arrow_box_display.x1 = arrow_box_display.x0 + head_length_display
|
|
209
219
|
# Transfrom back to data coordinates for plotting
|
|
210
|
-
arrow_box = self.axes.transData.inverted().transform_bbox(
|
|
211
|
-
arrow_box_display
|
|
212
|
-
)
|
|
220
|
+
arrow_box = self.axes.transData.inverted().transform_bbox(arrow_box_display)
|
|
213
221
|
head_length = arrow_box.width
|
|
214
222
|
arrow_length = norm((self._dx, self._dy))
|
|
215
223
|
if head_length > arrow_length:
|
|
@@ -221,11 +229,19 @@ try:
|
|
|
221
229
|
|
|
222
230
|
# Renew the arrow's properties
|
|
223
231
|
super().__init__(
|
|
224
|
-
self._x,
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
232
|
+
self._x,
|
|
233
|
+
self._y,
|
|
234
|
+
self._dx,
|
|
235
|
+
self._dy,
|
|
236
|
+
width=self._tail_width,
|
|
237
|
+
head_width=self._head_width,
|
|
238
|
+
overhang=0,
|
|
239
|
+
shape=self._shape,
|
|
240
|
+
head_length=head_length,
|
|
241
|
+
length_includes_head=True,
|
|
242
|
+
axes=self.axes,
|
|
243
|
+
transform=self.get_transform(),
|
|
244
|
+
**self._kwargs,
|
|
229
245
|
)
|
|
230
246
|
self.set_clip_path(self.axes.patch)
|
|
231
247
|
super().draw(renderer)
|
|
@@ -234,18 +250,16 @@ try:
|
|
|
234
250
|
# Removes warning:
|
|
235
251
|
# unknown document: /tutorials/intermediate/constrainedlayout_guide
|
|
236
252
|
def get_in_layout(self):
|
|
237
|
-
"""
|
|
238
|
-
"""
|
|
253
|
+
""" """
|
|
239
254
|
return super().get_in_layout()
|
|
255
|
+
|
|
240
256
|
def set_in_layout(self, in_layout):
|
|
241
|
-
"""
|
|
242
|
-
"""
|
|
257
|
+
""" """
|
|
243
258
|
return super().set_in_layout(in_layout)
|
|
244
259
|
|
|
245
260
|
except ImportError:
|
|
246
|
-
|
|
247
261
|
# Dummy class that propagates a meaningful error,
|
|
248
262
|
# i.e. that Matplotlib is not installed
|
|
249
|
-
class AdaptiveFancyArrow
|
|
263
|
+
class AdaptiveFancyArrow:
|
|
250
264
|
def __init__(*args, **kwargs):
|
|
251
|
-
raise ModuleNotFoundError(
|
|
265
|
+
raise ModuleNotFoundError("No module named 'matplotlib'")
|