biotite 1.1.0__cp312-cp312-macosx_11_0_arm64.whl → 1.3.0__cp312-cp312-macosx_11_0_arm64.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/localapp.py +2 -2
- biotite/application/msaapp.py +10 -10
- biotite/application/muscle/app3.py +3 -3
- biotite/application/muscle/app5.py +3 -3
- biotite/application/sra/app.py +0 -5
- biotite/application/util.py +21 -1
- biotite/application/viennarna/rnaalifold.py +8 -8
- biotite/application/viennarna/rnaplot.py +10 -8
- 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 +2 -3
- biotite/database/uniprot/check.py +2 -2
- biotite/database/uniprot/download.py +2 -5
- biotite/database/uniprot/query.py +3 -4
- biotite/file.py +14 -2
- biotite/interface/__init__.py +19 -0
- biotite/interface/openmm/__init__.py +20 -0
- biotite/interface/openmm/state.py +93 -0
- biotite/interface/openmm/system.py +227 -0
- biotite/interface/pymol/__init__.py +201 -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 +19 -0
- biotite/interface/rdkit/mol.py +490 -0
- biotite/interface/version.py +94 -0
- biotite/interface/warning.py +19 -0
- biotite/sequence/align/__init__.py +0 -4
- biotite/sequence/align/alignment.py +33 -11
- biotite/sequence/align/banded.cpython-312-darwin.so +0 -0
- biotite/sequence/align/banded.pyx +22 -22
- biotite/sequence/align/cigar.py +2 -2
- biotite/sequence/align/kmeralphabet.cpython-312-darwin.so +0 -0
- biotite/sequence/align/kmeralphabet.pyx +2 -2
- biotite/sequence/align/kmersimilarity.cpython-312-darwin.so +0 -0
- biotite/sequence/align/kmertable.cpython-312-darwin.so +0 -0
- biotite/sequence/align/kmertable.pyx +6 -6
- biotite/sequence/align/localgapped.cpython-312-darwin.so +0 -0
- biotite/sequence/align/localgapped.pyx +47 -47
- biotite/sequence/align/localungapped.cpython-312-darwin.so +0 -0
- biotite/sequence/align/localungapped.pyx +10 -10
- biotite/sequence/align/matrix.py +12 -3
- biotite/sequence/align/multiple.cpython-312-darwin.so +0 -0
- biotite/sequence/align/multiple.pyx +1 -2
- biotite/sequence/align/pairwise.cpython-312-darwin.so +0 -0
- biotite/sequence/align/pairwise.pyx +37 -39
- biotite/sequence/align/permutation.cpython-312-darwin.so +0 -0
- biotite/sequence/align/selector.cpython-312-darwin.so +0 -0
- biotite/sequence/align/selector.pyx +2 -2
- biotite/sequence/align/statistics.py +1 -1
- biotite/sequence/align/tracetable.cpython-312-darwin.so +0 -0
- biotite/sequence/alphabet.py +2 -2
- biotite/sequence/annotation.py +19 -13
- biotite/sequence/codec.cpython-312-darwin.so +0 -0
- biotite/sequence/codon.py +1 -2
- biotite/sequence/graphics/alignment.py +25 -39
- 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.cpython-312-darwin.so +0 -0
- biotite/sequence/phylo/tree.cpython-312-darwin.so +0 -0
- biotite/sequence/phylo/upgma.cpython-312-darwin.so +0 -0
- biotite/sequence/profile.py +19 -25
- biotite/sequence/search.py +0 -1
- biotite/sequence/seqtypes.py +12 -5
- biotite/sequence/sequence.py +1 -2
- biotite/structure/__init__.py +2 -0
- biotite/structure/alphabet/i3d.py +1 -2
- biotite/structure/alphabet/pb.py +1 -2
- biotite/structure/alphabet/unkerasify.py +8 -2
- biotite/structure/atoms.py +35 -27
- biotite/structure/basepairs.py +39 -40
- biotite/structure/bonds.cpython-312-darwin.so +0 -0
- biotite/structure/bonds.pyx +8 -5
- biotite/structure/box.py +159 -23
- biotite/structure/celllist.cpython-312-darwin.so +0 -0
- biotite/structure/celllist.pyx +83 -68
- biotite/structure/chains.py +17 -55
- biotite/structure/charges.cpython-312-darwin.so +0 -0
- biotite/structure/compare.py +420 -13
- biotite/structure/density.py +1 -1
- biotite/structure/dotbracket.py +31 -32
- biotite/structure/filter.py +8 -8
- biotite/structure/geometry.py +15 -15
- biotite/structure/graphics/rna.py +19 -16
- biotite/structure/hbond.py +18 -21
- biotite/structure/info/atoms.py +11 -2
- biotite/structure/info/ccd.py +0 -2
- biotite/structure/info/components.bcif +0 -0
- biotite/structure/info/groups.py +0 -3
- biotite/structure/info/misc.py +0 -1
- biotite/structure/info/radii.py +92 -22
- biotite/structure/info/standardize.py +1 -2
- 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 +39 -13
- biotite/structure/io/pdb/convert.py +86 -5
- biotite/structure/io/pdb/file.py +90 -24
- biotite/structure/io/pdb/hybrid36.cpython-312-darwin.so +0 -0
- biotite/structure/io/pdbqt/file.py +4 -4
- biotite/structure/io/pdbx/bcif.py +22 -7
- biotite/structure/io/pdbx/cif.py +20 -7
- biotite/structure/io/pdbx/component.py +6 -0
- biotite/structure/io/pdbx/compress.py +71 -34
- biotite/structure/io/pdbx/convert.py +429 -77
- biotite/structure/io/pdbx/encoding.cpython-312-darwin.so +0 -0
- biotite/structure/io/pdbx/encoding.pyx +39 -23
- biotite/structure/io/trajfile.py +9 -6
- biotite/structure/io/util.py +38 -0
- biotite/structure/mechanics.py +0 -1
- biotite/structure/molecules.py +0 -15
- biotite/structure/pseudoknots.py +13 -19
- biotite/structure/repair.py +2 -4
- biotite/structure/residues.py +20 -48
- biotite/structure/rings.py +335 -0
- biotite/structure/sasa.cpython-312-darwin.so +0 -0
- biotite/structure/sasa.pyx +30 -30
- biotite/structure/segments.py +123 -9
- biotite/structure/sequence.py +0 -1
- biotite/structure/spacegroups.json +1567 -0
- biotite/structure/spacegroups.license +26 -0
- biotite/structure/sse.py +0 -2
- biotite/structure/superimpose.py +75 -253
- biotite/structure/tm.py +581 -0
- biotite/structure/transform.py +232 -26
- biotite/structure/util.py +3 -3
- biotite/version.py +9 -4
- biotite/visualize.py +111 -1
- {biotite-1.1.0.dist-info → biotite-1.3.0.dist-info}/METADATA +8 -36
- {biotite-1.1.0.dist-info → biotite-1.3.0.dist-info}/RECORD +160 -138
- {biotite-1.1.0.dist-info → biotite-1.3.0.dist-info}/WHEEL +3 -1
- {biotite-1.1.0.dist-info → biotite-1.3.0.dist-info}/licenses/LICENSE.rst +0 -0
biotite/structure/transform.py
CHANGED
|
@@ -10,6 +10,7 @@ that can be applied on structures.
|
|
|
10
10
|
__name__ = "biotite.structure"
|
|
11
11
|
__author__ = "Patrick Kunzmann", "Claude J. Rogers"
|
|
12
12
|
__all__ = [
|
|
13
|
+
"AffineTransformation",
|
|
13
14
|
"translate",
|
|
14
15
|
"rotate",
|
|
15
16
|
"rotate_centered",
|
|
@@ -20,10 +21,215 @@ __all__ = [
|
|
|
20
21
|
|
|
21
22
|
import numpy as np
|
|
22
23
|
from biotite.structure.atoms import Atom, AtomArray, AtomArrayStack, coord
|
|
23
|
-
from biotite.structure.geometry import centroid
|
|
24
24
|
from biotite.structure.util import matrix_rotate, norm_vector, vector_dot
|
|
25
25
|
|
|
26
26
|
|
|
27
|
+
class AffineTransformation:
|
|
28
|
+
"""
|
|
29
|
+
An affine transformation, consisting of translations and a rotation.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
center_translation : ndarray, shape=(3,) or shape=(m,3), dtype=float
|
|
34
|
+
The translation vector for moving the centroid into the
|
|
35
|
+
origin.
|
|
36
|
+
rotation : ndarray, shape=(3,3) or shape=(m,3,3), dtype=float
|
|
37
|
+
The rotation matrix.
|
|
38
|
+
target_translation : ndarray, shape=(m,3), dtype=float
|
|
39
|
+
The translation vector for moving the structure onto the
|
|
40
|
+
fixed one.
|
|
41
|
+
|
|
42
|
+
Attributes
|
|
43
|
+
----------
|
|
44
|
+
center_translation, rotation, target_translation : ndarray
|
|
45
|
+
Same as the parameters.
|
|
46
|
+
The dimensions are always expanded to *(m,3)* or *(m,3,3)*,
|
|
47
|
+
respectively.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self, center_translation, rotation, target_translation):
|
|
51
|
+
self.center_translation = _expand_dims(center_translation, 2)
|
|
52
|
+
self.rotation = _expand_dims(rotation, 3)
|
|
53
|
+
self.target_translation = _expand_dims(target_translation, 2)
|
|
54
|
+
|
|
55
|
+
def apply(self, atoms):
|
|
56
|
+
"""
|
|
57
|
+
Apply this transformation on the given structure.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
atoms : AtomArray or AtomArrayStack or ndarray, shape(n,), dtype=float or ndarray, shape(m,n), dtype=float
|
|
62
|
+
The structure to apply the transformation on.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
transformed : AtomArray or AtomArrayStack or ndarray, shape(n,), dtype=float or ndarray, shape(m,n), dtype=float
|
|
67
|
+
A copy of the `atoms` structure, with transformations applied.
|
|
68
|
+
Only coordinates are returned, if coordinates were given in `atoms`.
|
|
69
|
+
|
|
70
|
+
Examples
|
|
71
|
+
--------
|
|
72
|
+
|
|
73
|
+
>>> coord = np.arange(15).reshape(5,3)
|
|
74
|
+
>>> print(coord)
|
|
75
|
+
[[ 0 1 2]
|
|
76
|
+
[ 3 4 5]
|
|
77
|
+
[ 6 7 8]
|
|
78
|
+
[ 9 10 11]
|
|
79
|
+
[12 13 14]]
|
|
80
|
+
>>> # Rotates 90 degrees around the z-axis
|
|
81
|
+
>>> transform = AffineTransformation(
|
|
82
|
+
... center_translation=np.array([0,0,0]),
|
|
83
|
+
... rotation=np.array([
|
|
84
|
+
... [0, -1, 0],
|
|
85
|
+
... [1, 0, 0],
|
|
86
|
+
... [0, 0, 1]
|
|
87
|
+
... ]),
|
|
88
|
+
... target_translation=np.array([0,0,0])
|
|
89
|
+
... )
|
|
90
|
+
>>> print(transform.apply(coord))
|
|
91
|
+
[[ -1. 0. 2.]
|
|
92
|
+
[ -4. 3. 5.]
|
|
93
|
+
[ -7. 6. 8.]
|
|
94
|
+
[-10. 9. 11.]
|
|
95
|
+
[-13. 12. 14.]]
|
|
96
|
+
"""
|
|
97
|
+
mobile_coord = coord(atoms)
|
|
98
|
+
original_shape = mobile_coord.shape
|
|
99
|
+
mobile_coord = _reshape_to_3d(mobile_coord)
|
|
100
|
+
if (
|
|
101
|
+
self.rotation.shape[0] != 1
|
|
102
|
+
and mobile_coord.shape[0] != self.rotation.shape[0]
|
|
103
|
+
):
|
|
104
|
+
raise IndexError(
|
|
105
|
+
f"Number of transformations is {self.rotation.shape[0]}, "
|
|
106
|
+
f"but number of structure models is {mobile_coord.shape[0]}"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
superimposed_coord = mobile_coord.copy()
|
|
110
|
+
superimposed_coord += self.center_translation[:, np.newaxis, :]
|
|
111
|
+
superimposed_coord = _multi_matmul(self.rotation, superimposed_coord)
|
|
112
|
+
superimposed_coord += self.target_translation[:, np.newaxis, :]
|
|
113
|
+
|
|
114
|
+
superimposed_coord = superimposed_coord.reshape(original_shape)
|
|
115
|
+
if isinstance(atoms, np.ndarray):
|
|
116
|
+
return superimposed_coord
|
|
117
|
+
else:
|
|
118
|
+
superimposed = atoms.copy()
|
|
119
|
+
superimposed.coord = superimposed_coord
|
|
120
|
+
return superimposed
|
|
121
|
+
|
|
122
|
+
def as_matrix(self):
|
|
123
|
+
"""
|
|
124
|
+
Get the translations and rotation as a combined 4x4
|
|
125
|
+
transformation matrix.
|
|
126
|
+
|
|
127
|
+
Multiplying this matrix with coordinates in the form
|
|
128
|
+
*(x, y, z, 1)* will apply the same transformation as
|
|
129
|
+
:meth:`apply()` to coordinates in the form *(x, y, z)*.
|
|
130
|
+
|
|
131
|
+
Returns
|
|
132
|
+
-------
|
|
133
|
+
transformation_matrix : ndarray, shape=(m,4,4), dtype=float
|
|
134
|
+
The transformation matrix.
|
|
135
|
+
*m* is the number of models in the transformation.
|
|
136
|
+
|
|
137
|
+
Examples
|
|
138
|
+
--------
|
|
139
|
+
|
|
140
|
+
>>> coord = np.arange(15).reshape(5,3)
|
|
141
|
+
>>> print(coord)
|
|
142
|
+
[[ 0 1 2]
|
|
143
|
+
[ 3 4 5]
|
|
144
|
+
[ 6 7 8]
|
|
145
|
+
[ 9 10 11]
|
|
146
|
+
[12 13 14]]
|
|
147
|
+
>>> # Rotates 90 degrees around the z-axis
|
|
148
|
+
>>> transform = AffineTransformation(
|
|
149
|
+
... center_translation=np.array([0,0,0]),
|
|
150
|
+
... rotation=np.array([
|
|
151
|
+
... [0, -1, 0],
|
|
152
|
+
... [1, 0, 0],
|
|
153
|
+
... [0, 0, 1]
|
|
154
|
+
... ]),
|
|
155
|
+
... target_translation=np.array([0,0,0])
|
|
156
|
+
... )
|
|
157
|
+
>>> print(transform.apply(coord))
|
|
158
|
+
[[ -1. 0. 2.]
|
|
159
|
+
[ -4. 3. 5.]
|
|
160
|
+
[ -7. 6. 8.]
|
|
161
|
+
[-10. 9. 11.]
|
|
162
|
+
[-13. 12. 14.]]
|
|
163
|
+
>>> # Use a 4x4 matrix for transformation as alternative
|
|
164
|
+
>>> coord_4 = np.concatenate([coord, np.ones((len(coord), 1))], axis=-1)
|
|
165
|
+
>>> print(coord_4)
|
|
166
|
+
[[ 0. 1. 2. 1.]
|
|
167
|
+
[ 3. 4. 5. 1.]
|
|
168
|
+
[ 6. 7. 8. 1.]
|
|
169
|
+
[ 9. 10. 11. 1.]
|
|
170
|
+
[12. 13. 14. 1.]]
|
|
171
|
+
>>> print((transform.as_matrix()[0] @ coord_4.T).T)
|
|
172
|
+
[[ -1. 0. 2. 1.]
|
|
173
|
+
[ -4. 3. 5. 1.]
|
|
174
|
+
[ -7. 6. 8. 1.]
|
|
175
|
+
[-10. 9. 11. 1.]
|
|
176
|
+
[-13. 12. 14. 1.]]
|
|
177
|
+
"""
|
|
178
|
+
n_models = self.rotation.shape[0]
|
|
179
|
+
rotation_mat = _3d_identity(n_models, 4)
|
|
180
|
+
rotation_mat[:, :3, :3] = self.rotation
|
|
181
|
+
center_translation_mat = _3d_identity(n_models, 4)
|
|
182
|
+
center_translation_mat[:, :3, 3] = self.center_translation
|
|
183
|
+
target_translation_mat = _3d_identity(n_models, 4)
|
|
184
|
+
target_translation_mat[:, :3, 3] = self.target_translation
|
|
185
|
+
return target_translation_mat @ rotation_mat @ center_translation_mat
|
|
186
|
+
|
|
187
|
+
def __eq__(self, other):
|
|
188
|
+
if not isinstance(other, AffineTransformation):
|
|
189
|
+
return False
|
|
190
|
+
if not np.array_equal(self.center_translation, other.center_translation):
|
|
191
|
+
return False
|
|
192
|
+
if not np.array_equal(self.rotation, other.rotation):
|
|
193
|
+
return False
|
|
194
|
+
if not np.array_equal(self.target_translation, other.target_translation):
|
|
195
|
+
return False
|
|
196
|
+
return True
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _expand_dims(array, n_dims):
|
|
200
|
+
"""
|
|
201
|
+
Expand the dimensions of an `ndarray` to a certain number of
|
|
202
|
+
dimensions.
|
|
203
|
+
"""
|
|
204
|
+
while array.ndim < n_dims:
|
|
205
|
+
array = array[np.newaxis, ...]
|
|
206
|
+
return array
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _3d_identity(m, n):
|
|
210
|
+
"""
|
|
211
|
+
Create an array of *m* identity matrices of shape *(n, n)*
|
|
212
|
+
"""
|
|
213
|
+
matrices = np.zeros((m, n, n), dtype=float)
|
|
214
|
+
indices = np.arange(n)
|
|
215
|
+
matrices[:, indices, indices] = 1
|
|
216
|
+
return matrices
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _reshape_to_3d(coord):
|
|
220
|
+
"""
|
|
221
|
+
Reshape the coordinate array to 3D, if it is 2D.
|
|
222
|
+
"""
|
|
223
|
+
if coord.ndim < 2:
|
|
224
|
+
raise ValueError("Coordinates must be at least two-dimensional")
|
|
225
|
+
if coord.ndim == 2:
|
|
226
|
+
return coord[np.newaxis, ...]
|
|
227
|
+
elif coord.ndim == 3:
|
|
228
|
+
return coord
|
|
229
|
+
else:
|
|
230
|
+
raise ValueError("Coordinates must be at most three-dimensional")
|
|
231
|
+
|
|
232
|
+
|
|
27
233
|
def translate(atoms, vector):
|
|
28
234
|
"""
|
|
29
235
|
Translate the given atoms or coordinates by a given vector.
|
|
@@ -33,7 +239,7 @@ def translate(atoms, vector):
|
|
|
33
239
|
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
34
240
|
The atoms of which the coordinates are transformed.
|
|
35
241
|
The coordinates can be directly provided as :class:`ndarray`.
|
|
36
|
-
vector: array-like, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
242
|
+
vector : array-like, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
37
243
|
The translation vector :math:`(x, y, z)`.
|
|
38
244
|
|
|
39
245
|
Returns
|
|
@@ -64,7 +270,7 @@ def rotate(atoms, angles):
|
|
|
64
270
|
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
65
271
|
The atoms of which the coordinates are transformed.
|
|
66
272
|
The coordinates can be directly provided as :class:`ndarray`.
|
|
67
|
-
angles: array-like, length=3
|
|
273
|
+
angles : array-like, length=3
|
|
68
274
|
The rotation angles in radians around *x*, *y* and *z*.
|
|
69
275
|
|
|
70
276
|
Returns
|
|
@@ -75,8 +281,8 @@ def rotate(atoms, angles):
|
|
|
75
281
|
|
|
76
282
|
See Also
|
|
77
283
|
--------
|
|
78
|
-
rotate_centered
|
|
79
|
-
rotate_about_axis
|
|
284
|
+
rotate_centered : Rotate atoms about the centroid.
|
|
285
|
+
rotate_about_axis : Rotate atoms about a given axis.
|
|
80
286
|
|
|
81
287
|
Examples
|
|
82
288
|
--------
|
|
@@ -136,7 +342,7 @@ def rotate_centered(atoms, angles):
|
|
|
136
342
|
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
137
343
|
The atoms of which the coordinates are transformed.
|
|
138
344
|
The coordinates can be directly provided as :class:`ndarray`.
|
|
139
|
-
angles: array-like, length=3
|
|
345
|
+
angles : array-like, length=3
|
|
140
346
|
The rotation angles in radians around axes *x*, *y* and *z*.
|
|
141
347
|
|
|
142
348
|
Returns
|
|
@@ -147,9 +353,12 @@ def rotate_centered(atoms, angles):
|
|
|
147
353
|
|
|
148
354
|
See Also
|
|
149
355
|
--------
|
|
150
|
-
rotate
|
|
151
|
-
rotate_about_axis
|
|
356
|
+
rotate : Rotate atoms about the origin.
|
|
357
|
+
rotate_about_axis : Rotate atoms about a given axis.
|
|
152
358
|
"""
|
|
359
|
+
# Avoid circular import
|
|
360
|
+
from biotite.structure.geometry import centroid
|
|
361
|
+
|
|
153
362
|
if len(coord(atoms).shape) == 1:
|
|
154
363
|
# Single value -> centered rotation does not change coordinates
|
|
155
364
|
return atoms.copy()
|
|
@@ -193,8 +402,8 @@ def rotate_about_axis(atoms, axis, angle, support=None):
|
|
|
193
402
|
|
|
194
403
|
See Also
|
|
195
404
|
--------
|
|
196
|
-
rotate
|
|
197
|
-
rotate_centered
|
|
405
|
+
rotate : Rotate atoms about the origin.
|
|
406
|
+
rotate_centered : Rotate atoms about the centroid.
|
|
198
407
|
|
|
199
408
|
Examples
|
|
200
409
|
--------
|
|
@@ -293,11 +502,6 @@ def orient_principal_components(atoms, order=None):
|
|
|
293
502
|
The atoms with coordinates centered at the orgin and aligned with
|
|
294
503
|
xyz axes.
|
|
295
504
|
|
|
296
|
-
See Also
|
|
297
|
-
--------
|
|
298
|
-
rotate_centered
|
|
299
|
-
rotate_about_axis
|
|
300
|
-
|
|
301
505
|
Examples
|
|
302
506
|
--------
|
|
303
507
|
Align principal components to xyz axes (default), or specify the order
|
|
@@ -321,8 +525,7 @@ def orient_principal_components(atoms, order=None):
|
|
|
321
525
|
row, col = coords.shape
|
|
322
526
|
if (row < 3) or (col != 3):
|
|
323
527
|
raise ValueError(
|
|
324
|
-
f"Expected at least 3 entries, {row} given,"
|
|
325
|
-
f" and 3 dimensions, {col} given."
|
|
528
|
+
f"Expected at least 3 entries, {row} given, and 3 dimensions, {col} given."
|
|
326
529
|
)
|
|
327
530
|
if order is None:
|
|
328
531
|
order = np.array([0, 1, 2])
|
|
@@ -400,11 +603,6 @@ def align_vectors(
|
|
|
400
603
|
A copy of the input atoms or coordinates with the applied
|
|
401
604
|
transformation.
|
|
402
605
|
|
|
403
|
-
See Also
|
|
404
|
-
--------
|
|
405
|
-
rotate
|
|
406
|
-
rotate_centered
|
|
407
|
-
|
|
408
606
|
Examples
|
|
409
607
|
--------
|
|
410
608
|
Align two different residues at their CA-CB bond, i.e. the CA and CB
|
|
@@ -467,13 +665,11 @@ def align_vectors(
|
|
|
467
665
|
# check that original and target direction are vectors of shape (3,)
|
|
468
666
|
if origin_direction.shape != (3,):
|
|
469
667
|
raise ValueError(
|
|
470
|
-
f"Expected origin vector to have shape (3,), "
|
|
471
|
-
f"got {origin_direction.shape}"
|
|
668
|
+
f"Expected origin vector to have shape (3,), got {origin_direction.shape}"
|
|
472
669
|
)
|
|
473
670
|
if target_direction.shape != (3,):
|
|
474
671
|
raise ValueError(
|
|
475
|
-
f"Expected target vector to have shape (3,), "
|
|
476
|
-
f"got {target_direction.shape}"
|
|
672
|
+
f"Expected target vector to have shape (3,), got {target_direction.shape}"
|
|
477
673
|
)
|
|
478
674
|
if np.linalg.norm(origin_direction) == 0:
|
|
479
675
|
raise ValueError("Length of the origin vector is 0")
|
|
@@ -528,3 +724,13 @@ def _put_back(input_atoms, transformed):
|
|
|
528
724
|
return moved_atoms
|
|
529
725
|
else:
|
|
530
726
|
return transformed
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
def _multi_matmul(matrices, vectors):
|
|
730
|
+
"""
|
|
731
|
+
Calculate the matrix multiplication of m matrices
|
|
732
|
+
with m x n vectors.
|
|
733
|
+
"""
|
|
734
|
+
return np.transpose(
|
|
735
|
+
np.matmul(matrices, np.transpose(vectors, axes=(0, 2, 1))), axes=(0, 2, 1)
|
|
736
|
+
)
|
biotite/structure/util.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# information.
|
|
4
4
|
|
|
5
5
|
"""
|
|
6
|
-
Utility functions for in internal use in `Bio.Structure` package
|
|
6
|
+
Utility functions for in internal use in `Bio.Structure` package.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
__name__ = "biotite.structure"
|
|
@@ -28,7 +28,7 @@ def vector_dot(v1, v2):
|
|
|
28
28
|
|
|
29
29
|
Parameters
|
|
30
30
|
----------
|
|
31
|
-
v1,v2 : ndarray
|
|
31
|
+
v1, v2 : ndarray
|
|
32
32
|
The arrays to calculate the product from.
|
|
33
33
|
The vectors are represented by the last axis.
|
|
34
34
|
|
|
@@ -63,7 +63,7 @@ def distance(v1, v2):
|
|
|
63
63
|
|
|
64
64
|
Parameters
|
|
65
65
|
----------
|
|
66
|
-
v1,v2 : ndarray
|
|
66
|
+
v1, v2 : ndarray
|
|
67
67
|
The arrays to calculate the product from.
|
|
68
68
|
The vectors are represented by the last axis.
|
|
69
69
|
|
biotite/version.py
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
# file generated by
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
|
|
5
|
+
|
|
3
6
|
TYPE_CHECKING = False
|
|
4
7
|
if TYPE_CHECKING:
|
|
5
|
-
from typing import Tuple
|
|
8
|
+
from typing import Tuple
|
|
9
|
+
from typing import Union
|
|
10
|
+
|
|
6
11
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
7
12
|
else:
|
|
8
13
|
VERSION_TUPLE = object
|
|
@@ -12,5 +17,5 @@ __version__: str
|
|
|
12
17
|
__version_tuple__: VERSION_TUPLE
|
|
13
18
|
version_tuple: VERSION_TUPLE
|
|
14
19
|
|
|
15
|
-
__version__ = version = '1.
|
|
16
|
-
__version_tuple__ = version_tuple = (1,
|
|
20
|
+
__version__ = version = '1.3.0'
|
|
21
|
+
__version_tuple__ = version_tuple = (1, 3, 0)
|
biotite/visualize.py
CHANGED
|
@@ -4,12 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
__name__ = "biotite"
|
|
6
6
|
__author__ = "Patrick Kunzmann"
|
|
7
|
-
__all__ = ["colors", "set_font_size_in_coord", "AdaptiveFancyArrow"]
|
|
7
|
+
__all__ = ["colors", "plot_scaled_text", "set_font_size_in_coord", "AdaptiveFancyArrow"]
|
|
8
8
|
|
|
9
|
+
import warnings
|
|
9
10
|
from collections import OrderedDict
|
|
10
11
|
import numpy as np
|
|
11
12
|
from numpy.linalg import norm
|
|
12
13
|
|
|
14
|
+
_FONT_PROPERTY_KEYS = ["family", "style", "variant", "weight", "stretch", "size"]
|
|
15
|
+
|
|
16
|
+
|
|
13
17
|
# Biotite themed colors
|
|
14
18
|
colors = OrderedDict(
|
|
15
19
|
[
|
|
@@ -27,6 +31,105 @@ colors = OrderedDict(
|
|
|
27
31
|
)
|
|
28
32
|
|
|
29
33
|
|
|
34
|
+
def plot_scaled_text(
|
|
35
|
+
axes, text, x, y, width=None, height=None, mode="unlocked", **kwargs
|
|
36
|
+
):
|
|
37
|
+
"""
|
|
38
|
+
Create a :class:`matplotlib.textpath.TextPath`, whose text size is given in
|
|
39
|
+
coordinates instead of font size.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
axes : Axes
|
|
44
|
+
The axes to draw the text on.
|
|
45
|
+
text : str
|
|
46
|
+
The text to be drawn.
|
|
47
|
+
x, y : float
|
|
48
|
+
The lower left position of the text.
|
|
49
|
+
width, height : float, optional
|
|
50
|
+
The width/height `text` should have in its reference coordinate system.
|
|
51
|
+
At least one value must be supplied.
|
|
52
|
+
mode : {'proportional', 'unlocked', 'maximum', 'minimum'}, optional
|
|
53
|
+
Defines how the text size is scaled.
|
|
54
|
+
The scaling mode:
|
|
55
|
+
|
|
56
|
+
- *proportional* - The width and height are scaled by the
|
|
57
|
+
same extent.
|
|
58
|
+
Either `width` or `height` must be set for this mode.
|
|
59
|
+
- *unlocked* - The width and the height are scaled by
|
|
60
|
+
different extents, changing the aspect ratio of the text.
|
|
61
|
+
Both `width` and `height` must be set for this mode.
|
|
62
|
+
- *maximum* - The width and the height are scaled by
|
|
63
|
+
the same extent, so that they are at maximum as large
|
|
64
|
+
as the supplied `width`/`height`.
|
|
65
|
+
Both `width` and `height` must be set for this mode.
|
|
66
|
+
- *minimum* - The width and the height are scaled by
|
|
67
|
+
the same extent, so that they are at minimum as large
|
|
68
|
+
as the supplied `width`/`height`.
|
|
69
|
+
Both `width` and `height` must be set for this mode.
|
|
70
|
+
|
|
71
|
+
**kwargs
|
|
72
|
+
Additional parameters for the :class:`matplotlib.font_manager.FontProperties`
|
|
73
|
+
of the text or the created :class:`matplotlib.patches.PathPatch`.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
patch : matplotlib.patches.PathPatch
|
|
78
|
+
The patch that represents the text.
|
|
79
|
+
"""
|
|
80
|
+
from matplotlib.patches import PathPatch
|
|
81
|
+
from matplotlib.textpath import TextPath
|
|
82
|
+
from matplotlib.transforms import Affine2D
|
|
83
|
+
|
|
84
|
+
# The larger the size, the more there is an offset at the x-axis
|
|
85
|
+
# -> Keep font size small to reduce this error to a minimum
|
|
86
|
+
# The size is transformed to the desired size afterwards anyway
|
|
87
|
+
font_property_kwargs = {
|
|
88
|
+
key: kwargs.pop(key) for key in _FONT_PROPERTY_KEYS if key in kwargs
|
|
89
|
+
}
|
|
90
|
+
path = TextPath((x, y), text, size=1e-3, prop=font_property_kwargs)
|
|
91
|
+
bbox = path.get_extents()
|
|
92
|
+
|
|
93
|
+
if mode == "proportional":
|
|
94
|
+
if width is None:
|
|
95
|
+
# Proportional scaling based on height
|
|
96
|
+
scale_y = height / bbox.height
|
|
97
|
+
scale_x = scale_y
|
|
98
|
+
elif height is None:
|
|
99
|
+
# Proportional scaling based on width
|
|
100
|
+
scale_x = width / bbox.width
|
|
101
|
+
scale_y = scale_x
|
|
102
|
+
else:
|
|
103
|
+
raise ValueError(
|
|
104
|
+
"width or height are mutually exclusive in 'proportional' mode"
|
|
105
|
+
)
|
|
106
|
+
elif mode == "unlocked":
|
|
107
|
+
scale_x = width / bbox.width
|
|
108
|
+
scale_y = height / bbox.height
|
|
109
|
+
elif mode == "minimum":
|
|
110
|
+
scale_x = width / bbox.width
|
|
111
|
+
scale_y = height / bbox.height
|
|
112
|
+
scale = max(scale_x, scale_y)
|
|
113
|
+
scale_x, scale_y = scale, scale
|
|
114
|
+
elif mode == "maximum":
|
|
115
|
+
scale_x = width / bbox.width
|
|
116
|
+
scale_y = height / bbox.height
|
|
117
|
+
scale = min(scale_x, scale_y)
|
|
118
|
+
scale_x, scale_y = scale, scale
|
|
119
|
+
|
|
120
|
+
path = (
|
|
121
|
+
Affine2D()
|
|
122
|
+
.translate(-bbox.x0, -bbox.y0)
|
|
123
|
+
.scale(scale_x, scale_y)
|
|
124
|
+
.translate(bbox.x0, bbox.y0)
|
|
125
|
+
.transform_path(path)
|
|
126
|
+
)
|
|
127
|
+
patch = PathPatch(path, **kwargs)
|
|
128
|
+
axes.add_patch(patch)
|
|
129
|
+
|
|
130
|
+
return patch
|
|
131
|
+
|
|
132
|
+
|
|
30
133
|
def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
|
|
31
134
|
"""
|
|
32
135
|
Specifiy the font size of an existing `Text` object in coordinates
|
|
@@ -38,6 +141,8 @@ def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
|
|
|
38
141
|
The scaling can be proportional or non-proportional, depending
|
|
39
142
|
the `mode`.
|
|
40
143
|
|
|
144
|
+
DEPRECATED: Use :func:`plot_scaled_text()` instead.
|
|
145
|
+
|
|
41
146
|
Parameters
|
|
42
147
|
----------
|
|
43
148
|
text : Text:
|
|
@@ -125,6 +230,11 @@ def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
|
|
|
125
230
|
affine = Affine2D().scale(scale_x, scale_y) + affine
|
|
126
231
|
renderer.draw_path(gc, tpath, affine, rgbFace)
|
|
127
232
|
|
|
233
|
+
warnings.warn(
|
|
234
|
+
"Deprecated, use 'biotite.graphics.text.plot_scaled_text()' instead.",
|
|
235
|
+
DeprecationWarning,
|
|
236
|
+
)
|
|
237
|
+
|
|
128
238
|
if mode in ["unlocked", "minimum", "maximum"]:
|
|
129
239
|
if width is None or height is None:
|
|
130
240
|
raise TypeError(f"Width and height must be set in '{mode}' mode")
|
|
@@ -1,46 +1,16 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: biotite
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: A comprehensive library for computational molecular biology
|
|
5
5
|
Project-URL: homepage, https://www.biotite-python.org
|
|
6
6
|
Project-URL: repository, https://github.com/biotite-dev/biotite
|
|
7
7
|
Project-URL: documentation, https://www.biotite-python.org
|
|
8
8
|
Author: The Biotite contributors
|
|
9
|
-
License: BSD
|
|
10
|
-
--------------------
|
|
11
|
-
|
|
12
|
-
Copyright 2017, The Biotite contributors
|
|
13
|
-
All rights reserved.
|
|
14
|
-
|
|
15
|
-
Redistribution and use in source and binary forms, with or without modification,
|
|
16
|
-
are permitted provided that the following conditions are met:
|
|
17
|
-
|
|
18
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
|
19
|
-
list of conditions and the following disclaimer.
|
|
20
|
-
|
|
21
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
22
|
-
this list of conditions and the following disclaimer in the documentation and/or
|
|
23
|
-
other materials provided with the distribution.
|
|
24
|
-
|
|
25
|
-
3. Neither the name of the copyright holder nor the names of its contributors
|
|
26
|
-
may be used to endorse or promote products derived from this software without
|
|
27
|
-
specific prior written permission.
|
|
28
|
-
|
|
29
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
30
|
-
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
31
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
32
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
33
|
-
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
34
|
-
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
35
|
-
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
36
|
-
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
37
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
38
|
-
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
9
|
+
License-Expression: BSD-3-Clause
|
|
39
10
|
License-File: LICENSE.rst
|
|
40
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
41
12
|
Classifier: Intended Audience :: Developers
|
|
42
13
|
Classifier: Intended Audience :: Science/Research
|
|
43
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
44
14
|
Classifier: Natural Language :: English
|
|
45
15
|
Classifier: Operating System :: MacOS
|
|
46
16
|
Classifier: Operating System :: Microsoft :: Windows
|
|
@@ -48,14 +18,16 @@ Classifier: Operating System :: POSIX :: Linux
|
|
|
48
18
|
Classifier: Programming Language :: Python :: 3
|
|
49
19
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
50
20
|
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
51
|
-
Requires-Python: >=3.
|
|
21
|
+
Requires-Python: >=3.11
|
|
52
22
|
Requires-Dist: biotraj<2.0,>=1.0
|
|
53
23
|
Requires-Dist: msgpack>=0.5.6
|
|
54
24
|
Requires-Dist: networkx>=2.0
|
|
55
25
|
Requires-Dist: numpy>=1.25
|
|
26
|
+
Requires-Dist: packaging>=24.0
|
|
56
27
|
Requires-Dist: requests>=2.12
|
|
57
28
|
Provides-Extra: lint
|
|
58
|
-
Requires-Dist:
|
|
29
|
+
Requires-Dist: numpydoc==1.8.0; extra == 'lint'
|
|
30
|
+
Requires-Dist: ruff==0.9.7; extra == 'lint'
|
|
59
31
|
Provides-Extra: test
|
|
60
32
|
Requires-Dist: pytest; extra == 'test'
|
|
61
33
|
Requires-Dist: pytest-codspeed; extra == 'test'
|
|
@@ -186,5 +158,5 @@ Contribution
|
|
|
186
158
|
|
|
187
159
|
Interested in improving *Biotite*?
|
|
188
160
|
Have a look at the
|
|
189
|
-
`contribution guidelines <https://www.biotite-python.org/
|
|
161
|
+
`contribution guidelines <https://www.biotite-python.org/latest/contribution/index.html>`_.
|
|
190
162
|
Feel free to join our community chat on `Discord <https://discord.gg/cUjDguF>`_.
|