biotite 0.39.0__cp311-cp311-win_amd64.whl → 0.40.0__cp311-cp311-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 +3 -3
- biotite/application/dssp/app.py +18 -18
- biotite/database/rcsb/download.py +19 -14
- biotite/sequence/align/banded.c +258 -237
- biotite/sequence/align/banded.cp311-win_amd64.pyd +0 -0
- biotite/sequence/align/kmeralphabet.c +243 -222
- biotite/sequence/align/kmeralphabet.cp311-win_amd64.pyd +0 -0
- biotite/sequence/align/kmersimilarity.c +215 -196
- biotite/sequence/align/kmersimilarity.cp311-win_amd64.pyd +0 -0
- biotite/sequence/align/kmertable.cp311-win_amd64.pyd +0 -0
- biotite/sequence/align/kmertable.cpp +233 -205
- biotite/sequence/align/localgapped.c +258 -237
- biotite/sequence/align/localgapped.cp311-win_amd64.pyd +0 -0
- biotite/sequence/align/localungapped.c +235 -214
- biotite/sequence/align/localungapped.cp311-win_amd64.pyd +0 -0
- biotite/sequence/align/multiple.c +255 -234
- biotite/sequence/align/multiple.cp311-win_amd64.pyd +0 -0
- biotite/sequence/align/pairwise.c +274 -253
- biotite/sequence/align/pairwise.cp311-win_amd64.pyd +0 -0
- biotite/sequence/align/permutation.c +215 -196
- biotite/sequence/align/permutation.cp311-win_amd64.pyd +0 -0
- biotite/sequence/align/selector.c +217 -197
- biotite/sequence/align/selector.cp311-win_amd64.pyd +0 -0
- biotite/sequence/align/tracetable.c +215 -195
- biotite/sequence/align/tracetable.cp311-win_amd64.pyd +0 -0
- biotite/sequence/codec.c +235 -214
- biotite/sequence/codec.cp311-win_amd64.pyd +0 -0
- biotite/sequence/phylo/nj.c +215 -196
- biotite/sequence/phylo/nj.cp311-win_amd64.pyd +0 -0
- biotite/sequence/phylo/tree.c +227 -202
- biotite/sequence/phylo/tree.cp311-win_amd64.pyd +0 -0
- biotite/sequence/phylo/upgma.c +215 -196
- biotite/sequence/phylo/upgma.cp311-win_amd64.pyd +0 -0
- biotite/structure/basepairs.py +7 -12
- biotite/structure/bonds.c +1175 -1226
- biotite/structure/bonds.cp311-win_amd64.pyd +0 -0
- biotite/structure/celllist.c +217 -197
- biotite/structure/celllist.cp311-win_amd64.pyd +0 -0
- biotite/structure/charges.c +1052 -1101
- biotite/structure/charges.cp311-win_amd64.pyd +0 -0
- biotite/structure/filter.py +30 -37
- biotite/structure/info/__init__.py +5 -8
- biotite/structure/info/atoms.py +25 -67
- biotite/structure/info/bonds.py +46 -100
- biotite/structure/info/ccd/README.rst +8 -0
- biotite/structure/info/ccd/amino_acids.txt +1646 -0
- biotite/structure/info/ccd/carbohydrates.txt +1133 -0
- biotite/structure/info/ccd/components.bcif +0 -0
- biotite/structure/info/ccd/nucleotides.txt +797 -0
- biotite/structure/info/ccd.py +95 -0
- biotite/structure/info/groups.py +90 -0
- biotite/structure/info/masses.py +21 -20
- biotite/structure/info/misc.py +11 -22
- biotite/structure/info/standardize.py +17 -12
- biotite/structure/io/__init__.py +2 -4
- biotite/structure/io/ctab.py +1 -1
- biotite/structure/io/general.py +37 -43
- biotite/structure/io/mmtf/__init__.py +3 -0
- biotite/structure/io/mmtf/convertarray.c +219 -198
- biotite/structure/io/mmtf/convertarray.cp311-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/convertfile.c +217 -197
- biotite/structure/io/mmtf/convertfile.cp311-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/decode.c +225 -204
- biotite/structure/io/mmtf/decode.cp311-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/encode.c +215 -196
- biotite/structure/io/mmtf/encode.cp311-win_amd64.pyd +0 -0
- biotite/structure/io/mmtf/file.py +34 -26
- biotite/structure/io/npz/__init__.py +3 -0
- biotite/structure/io/npz/file.py +21 -18
- biotite/structure/io/pdb/__init__.py +3 -3
- biotite/structure/io/pdb/file.py +5 -3
- biotite/structure/io/pdb/hybrid36.c +63 -43
- biotite/structure/io/pdb/hybrid36.cp311-win_amd64.pyd +0 -0
- biotite/structure/io/pdbqt/file.py +32 -32
- biotite/structure/io/pdbx/__init__.py +13 -6
- biotite/structure/io/pdbx/bcif.py +649 -0
- biotite/structure/io/pdbx/cif.py +1028 -0
- biotite/structure/io/pdbx/component.py +243 -0
- biotite/structure/io/pdbx/convert.py +707 -359
- biotite/structure/io/pdbx/encoding.c +112813 -0
- biotite/structure/io/pdbx/encoding.cp311-win_amd64.pyd +0 -0
- biotite/structure/io/pdbx/error.py +14 -0
- biotite/structure/io/pdbx/legacy.py +267 -0
- biotite/structure/molecules.py +151 -151
- biotite/structure/sasa.c +215 -196
- biotite/structure/sasa.cp311-win_amd64.pyd +0 -0
- biotite/structure/superimpose.py +158 -115
- {biotite-0.39.0.dist-info → biotite-0.40.0.dist-info}/METADATA +2 -2
- {biotite-0.39.0.dist-info → biotite-0.40.0.dist-info}/RECORD +92 -90
- {biotite-0.39.0.dist-info → biotite-0.40.0.dist-info}/WHEEL +1 -1
- biotite/structure/info/amino_acids.json +0 -1556
- biotite/structure/info/amino_acids.py +0 -42
- biotite/structure/info/carbohydrates.json +0 -1122
- biotite/structure/info/carbohydrates.py +0 -39
- biotite/structure/info/intra_bonds.msgpack +0 -0
- biotite/structure/info/link_types.msgpack +0 -1
- biotite/structure/info/nucleotides.json +0 -772
- biotite/structure/info/nucleotides.py +0 -39
- biotite/structure/info/residue_masses.msgpack +0 -0
- biotite/structure/info/residue_names.msgpack +0 -3
- biotite/structure/info/residues.msgpack +0 -0
- biotite/structure/io/pdbx/file.py +0 -652
- {biotite-0.39.0.dist-info → biotite-0.40.0.dist-info}/LICENSE.rst +0 -0
- {biotite-0.39.0.dist-info → biotite-0.40.0.dist-info}/top_level.txt +0 -0
|
Binary file
|
biotite/structure/superimpose.py
CHANGED
|
@@ -8,24 +8,86 @@ This module provides functions for structure superimposition.
|
|
|
8
8
|
|
|
9
9
|
__name__ = "biotite.structure"
|
|
10
10
|
__author__ = "Patrick Kunzmann, Claude J. Rogers"
|
|
11
|
-
__all__ = ["superimpose", "superimpose_apply"]
|
|
11
|
+
__all__ = ["superimpose", "superimpose_apply", "AffineTransformation"]
|
|
12
|
+
|
|
12
13
|
|
|
13
14
|
import numpy as np
|
|
14
15
|
from .atoms import coord
|
|
15
16
|
from .geometry import centroid
|
|
16
17
|
|
|
17
18
|
|
|
19
|
+
class AffineTransformation:
|
|
20
|
+
"""
|
|
21
|
+
An affine transformation, consisting of translations and a rotation.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
center_translation : ndarray, shape=(3,) or shape=(m,3), dtype=float
|
|
26
|
+
The translation vector for moving the centroid into the
|
|
27
|
+
origin.
|
|
28
|
+
rotation : ndarray, shape=(3,3) or shape=(m,3,3), dtype=float
|
|
29
|
+
The rotation matrix.
|
|
30
|
+
target_translation : ndarray, shape=(m,3), dtype=float
|
|
31
|
+
The translation vector for moving the structure onto the
|
|
32
|
+
fixed one.
|
|
33
|
+
|
|
34
|
+
Attributes
|
|
35
|
+
----------
|
|
36
|
+
center_translation, rotation, target_translation : ndarray
|
|
37
|
+
Same as the parameters.
|
|
38
|
+
"""
|
|
39
|
+
def __init__(self, center_translation, rotation, target_translation):
|
|
40
|
+
self.center_translation = center_translation
|
|
41
|
+
self.rotation = rotation
|
|
42
|
+
self.target_translation = target_translation
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def apply(self, atoms):
|
|
46
|
+
"""
|
|
47
|
+
Apply this transformation on the given structure.
|
|
48
|
+
|
|
49
|
+
Parameters
|
|
50
|
+
----------
|
|
51
|
+
atoms : AtomArray or AtomArrayStack or ndarray, shape(n,), dtype=float or ndarray, shape(m,n), dtype=float
|
|
52
|
+
The structure to apply the transformation on.
|
|
53
|
+
|
|
54
|
+
Returns
|
|
55
|
+
-------
|
|
56
|
+
transformed : AtomArray or AtomArrayStack or ndarray, shape(n,), dtype=float or ndarray, shape(m,n), dtype=float
|
|
57
|
+
A copy of the `atoms` structure,
|
|
58
|
+
with transformations applied.
|
|
59
|
+
Only coordinates are returned, if coordinates were given in
|
|
60
|
+
`atoms`.
|
|
61
|
+
"""
|
|
62
|
+
mobile_coord = coord(atoms)
|
|
63
|
+
original_shape = mobile_coord.shape
|
|
64
|
+
mobile_coord = _reshape_to_3d(mobile_coord)
|
|
65
|
+
|
|
66
|
+
superimposed_coord = mobile_coord.copy()
|
|
67
|
+
superimposed_coord += self.center_translation[:, np.newaxis, :]
|
|
68
|
+
superimposed_coord = _multi_matmul(self.rotation, superimposed_coord)
|
|
69
|
+
superimposed_coord += self.target_translation[:, np.newaxis, :]
|
|
70
|
+
|
|
71
|
+
superimposed_coord = superimposed_coord.reshape(original_shape)
|
|
72
|
+
if isinstance(atoms, np.ndarray):
|
|
73
|
+
return superimposed_coord
|
|
74
|
+
else:
|
|
75
|
+
superimposed = atoms.copy()
|
|
76
|
+
superimposed.coord = superimposed_coord
|
|
77
|
+
return superimposed
|
|
78
|
+
|
|
79
|
+
|
|
18
80
|
def superimpose(fixed, mobile, atom_mask=None):
|
|
19
81
|
"""
|
|
20
82
|
Superimpose structures onto a fixed structure.
|
|
21
|
-
|
|
83
|
+
|
|
22
84
|
The superimposition is performed using the Kabsch algorithm
|
|
23
85
|
:footcite:`Kabsch1976, Kabsch1978`, so that the RMSD between the
|
|
24
86
|
superimposed and the fixed structure is minimized.
|
|
25
|
-
|
|
87
|
+
|
|
26
88
|
Parameters
|
|
27
89
|
----------
|
|
28
|
-
fixed : AtomArray, shape(n,) or ndarray, shape(n,), dtype=float
|
|
90
|
+
fixed : AtomArray, shape(n,) or AtomArrayStack, shape(m,n) or ndarray, shape(n,), dtype=float or ndarray, shape(m,n), dtype=float
|
|
29
91
|
The fixed structure.
|
|
30
92
|
Alternatively coordinates can be given.
|
|
31
93
|
mobile: AtomArray, shape(n,) or AtomArrayStack, shape(m,n) or ndarray, shape(n,), dtype=float or ndarray, shape(m,n), dtype=float
|
|
@@ -41,7 +103,7 @@ def superimpose(fixed, mobile, atom_mask=None):
|
|
|
41
103
|
on the covered atoms instead of all atoms.
|
|
42
104
|
The returned superimposed structure will contain all atoms
|
|
43
105
|
of the input structure, regardless of this parameter.
|
|
44
|
-
|
|
106
|
+
|
|
45
107
|
Returns
|
|
46
108
|
-------
|
|
47
109
|
fitted : AtomArray or AtomArrayStack or ndarray, shape(n,), dtype=float or ndarray, shape(m,n), dtype=float
|
|
@@ -49,54 +111,43 @@ def superimpose(fixed, mobile, atom_mask=None):
|
|
|
49
111
|
superimposed on the fixed structure.
|
|
50
112
|
Only coordinates are returned, if coordinates were given in
|
|
51
113
|
`mobile`.
|
|
52
|
-
transformation :
|
|
53
|
-
|
|
54
|
-
`mobile`.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
The second element contains the rotation matrix.
|
|
59
|
-
The third element contains the translation vector for moving the
|
|
60
|
-
structure onto the fixed.
|
|
61
|
-
The three transformations are performed sequentially.
|
|
62
|
-
|
|
63
|
-
See Also
|
|
64
|
-
--------
|
|
65
|
-
superimpose_apply
|
|
66
|
-
|
|
114
|
+
transformation : AffineTransformation
|
|
115
|
+
This object contains the affine transformation(s) that were
|
|
116
|
+
applied on `mobile`.
|
|
117
|
+
:meth:`AffineTransformation.apply()` can be used to transform
|
|
118
|
+
another AtomArray in the same way.
|
|
119
|
+
|
|
67
120
|
Notes
|
|
68
121
|
-----
|
|
69
|
-
The `transformation`
|
|
70
|
-
|
|
71
|
-
:class:`AtomArray` in the same way.
|
|
72
|
-
This can come in handy, in case you want to superimpose two
|
|
122
|
+
The `transformation` can come in handy, in case you want to
|
|
123
|
+
superimpose two
|
|
73
124
|
structures with different amount of atoms.
|
|
74
125
|
Often the two structures need to be filtered in order to obtain the
|
|
75
126
|
same size and annotation arrays.
|
|
76
127
|
After superimposition the transformation can be applied on the
|
|
77
|
-
original structure using :
|
|
78
|
-
|
|
128
|
+
original structure using :meth:`AffineTransformation.apply()`.
|
|
129
|
+
|
|
79
130
|
References
|
|
80
131
|
----------
|
|
81
|
-
|
|
132
|
+
|
|
82
133
|
.. footbibliography::
|
|
83
|
-
|
|
134
|
+
|
|
84
135
|
Examples
|
|
85
136
|
--------
|
|
86
|
-
|
|
137
|
+
|
|
87
138
|
At first two models of a structure are taken and one of them is
|
|
88
139
|
randomly rotated/translated.
|
|
89
140
|
Consequently the RMSD is quite large:
|
|
90
|
-
|
|
141
|
+
|
|
91
142
|
>>> array1 = atom_array_stack[0]
|
|
92
143
|
>>> array2 = atom_array_stack[1]
|
|
93
144
|
>>> array2 = translate(array2, [1,2,3])
|
|
94
145
|
>>> array2 = rotate(array2, [1,2,3])
|
|
95
146
|
>>> print("{:.3f}".format(rmsd(array1, array2)))
|
|
96
147
|
11.260
|
|
97
|
-
|
|
148
|
+
|
|
98
149
|
RMSD decreases after superimposition of only CA atoms:
|
|
99
|
-
|
|
150
|
+
|
|
100
151
|
>>> array2_fit, transformation = superimpose(
|
|
101
152
|
... array1, array2, atom_mask=(array2.atom_name == "CA")
|
|
102
153
|
... )
|
|
@@ -110,95 +161,48 @@ def superimpose(fixed, mobile, atom_mask=None):
|
|
|
110
161
|
>>> print("{:.3f}".format(rmsd(array1, array2_fit)))
|
|
111
162
|
1.928
|
|
112
163
|
"""
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
mshape = m_coord.shape
|
|
117
|
-
mdim = m_coord.ndim
|
|
118
|
-
if f_coord.ndim != 2:
|
|
119
|
-
raise ValueError("Expected fixed array to be an AtomArray")
|
|
120
|
-
if mdim < 2:
|
|
121
|
-
raise ValueError(
|
|
122
|
-
"Expected mobile array to be an AtomArray or AtomArrayStack"
|
|
123
|
-
)
|
|
124
|
-
if mdim == 2:
|
|
125
|
-
# normalize inputs. Fixed coords has shape (n, 3)
|
|
126
|
-
# and mobile has shape (m, n, 3)
|
|
127
|
-
m_coord = m_coord[np.newaxis, ...]
|
|
128
|
-
|
|
129
|
-
nmodels = m_coord.shape[0]
|
|
130
|
-
if f_coord.shape[0] != m_coord.shape[1]:
|
|
131
|
-
raise ValueError(
|
|
132
|
-
f"Expected fixed array and mobile array to have the same number "
|
|
133
|
-
f"of atoms, but {f_coord.shape[0]} != {m_coord.shape[1]}"
|
|
134
|
-
)
|
|
164
|
+
# Bring coordinates into the same dimensionality
|
|
165
|
+
mob_coord = _reshape_to_3d(coord(mobile))
|
|
166
|
+
fix_coord = _reshape_to_3d(coord(fixed))
|
|
135
167
|
|
|
136
168
|
if atom_mask is not None:
|
|
137
169
|
# Implicitly this creates array copies
|
|
138
|
-
mob_filtered =
|
|
139
|
-
fix_filtered =
|
|
170
|
+
mob_filtered = mob_coord[:, atom_mask, :]
|
|
171
|
+
fix_filtered = fix_coord[:, atom_mask, :]
|
|
140
172
|
else:
|
|
141
|
-
mob_filtered = np.copy(
|
|
142
|
-
fix_filtered = np.copy(
|
|
143
|
-
|
|
173
|
+
mob_filtered = np.copy(mob_coord)
|
|
174
|
+
fix_filtered = np.copy(fix_coord)
|
|
175
|
+
|
|
144
176
|
# Center coordinates at (0,0,0)
|
|
145
177
|
mob_centroid = centroid(mob_filtered)
|
|
146
178
|
fix_centroid = centroid(fix_filtered)
|
|
147
|
-
mob_filtered
|
|
148
|
-
fix_filtered
|
|
149
|
-
|
|
150
|
-
s_coord = m_coord.copy() - mob_centroid[..., np.newaxis, :]
|
|
151
|
-
# Perform Kabsch algorithm for every model
|
|
152
|
-
transformations = [None] * nmodels
|
|
153
|
-
for i in range(nmodels):
|
|
154
|
-
rotation = _superimpose(fix_filtered, mob_filtered[i])
|
|
155
|
-
s_coord[i] = np.dot(rotation, s_coord[i].T).T
|
|
156
|
-
transformations[i] = (-mob_centroid[i], rotation, fix_centroid)
|
|
157
|
-
s_coord += fix_centroid
|
|
158
|
-
|
|
159
|
-
if isinstance(mobile, np.ndarray):
|
|
160
|
-
superimposed = s_coord.reshape(mshape)
|
|
161
|
-
else:
|
|
162
|
-
superimposed = mobile.copy()
|
|
163
|
-
superimposed.coord = s_coord.reshape(mshape)
|
|
179
|
+
mob_centered_filtered = mob_filtered - mob_centroid[:, np.newaxis, :]
|
|
180
|
+
fix_centered_filtered = fix_filtered - fix_centroid[:, np.newaxis, :]
|
|
164
181
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
182
|
+
rotation = _get_rotation_matrices(
|
|
183
|
+
fix_centered_filtered, mob_centered_filtered
|
|
184
|
+
)
|
|
185
|
+
transform = AffineTransformation(-mob_centroid, rotation, fix_centroid)
|
|
186
|
+
return transform.apply(mobile), transform
|
|
169
187
|
|
|
170
188
|
|
|
171
|
-
def
|
|
172
|
-
"""
|
|
173
|
-
Perform the Kabsch algorithm using only the coordinates.
|
|
189
|
+
def superimpose_apply(atoms, transformation):
|
|
174
190
|
"""
|
|
175
|
-
|
|
176
|
-
y = mob_centered
|
|
177
|
-
x = fix_centered
|
|
178
|
-
# Calculate covariance matrix
|
|
179
|
-
cov = np.dot(x.T, y)
|
|
180
|
-
v, s, w = np.linalg.svd(cov)
|
|
181
|
-
# Remove possibility of reflected atom coordinates
|
|
182
|
-
if np.linalg.det(v) * np.linalg.det(w) < 0:
|
|
183
|
-
v[:,-1] *= -1
|
|
184
|
-
rotation = np.dot(v,w)
|
|
185
|
-
return rotation
|
|
191
|
+
Superimpose structures using a given :class:`AffineTransformation`.
|
|
186
192
|
|
|
193
|
+
The :class:`AffineTransformation` can be obtained by prior
|
|
194
|
+
superimposition.
|
|
195
|
+
|
|
196
|
+
DEPRECATED: Use :func:`AffineTransformation.apply()` instead.
|
|
187
197
|
|
|
188
|
-
def superimpose_apply(atoms, transformation):
|
|
189
|
-
"""
|
|
190
|
-
Superimpose structures using a given transformation tuple.
|
|
191
|
-
|
|
192
|
-
The transformation tuple is obtained by prior superimposition.
|
|
193
|
-
|
|
194
198
|
Parameters
|
|
195
199
|
----------
|
|
196
200
|
atoms : AtomArray or ndarray, shape(n,), dtype=float
|
|
197
201
|
The structure to apply the transformation on.
|
|
198
202
|
Alternatively coordinates can be given.
|
|
199
|
-
transformation:
|
|
200
|
-
The transformation
|
|
201
|
-
|
|
203
|
+
transformation: AffineTransformation
|
|
204
|
+
The transformation, obtained by :func:`superimpose()`.
|
|
205
|
+
|
|
202
206
|
Returns
|
|
203
207
|
-------
|
|
204
208
|
fitted : AtomArray or AtomArrayStack
|
|
@@ -206,20 +210,59 @@ def superimpose_apply(atoms, transformation):
|
|
|
206
210
|
with transformations applied.
|
|
207
211
|
Only coordinates are returned, if coordinates were given in
|
|
208
212
|
`atoms`.
|
|
209
|
-
|
|
213
|
+
|
|
210
214
|
See Also
|
|
211
215
|
--------
|
|
212
216
|
superimpose
|
|
213
217
|
"""
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
218
|
+
return transformation.apply(atoms)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def _reshape_to_3d(coord):
|
|
222
|
+
"""
|
|
223
|
+
Reshape the coordinate array to 3D, if it is 2D.
|
|
224
|
+
"""
|
|
225
|
+
if coord.ndim < 2:
|
|
226
|
+
raise ValueError(
|
|
227
|
+
"Coordinates must be at least two-dimensional"
|
|
228
|
+
)
|
|
229
|
+
if coord.ndim == 2:
|
|
230
|
+
return coord[np.newaxis, ...]
|
|
231
|
+
elif coord.ndim == 3:
|
|
232
|
+
return coord
|
|
222
233
|
else:
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
234
|
+
raise ValueError(
|
|
235
|
+
"Coordinates must be at most three-dimensional"
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def _get_rotation_matrices(fixed, mobile):
|
|
240
|
+
"""
|
|
241
|
+
Get the rotation matrices to superimpose the given mobile
|
|
242
|
+
coordinates into the given fixed coordinates, minimizing the RMSD.
|
|
243
|
+
|
|
244
|
+
Uses the *Kabsch* algorithm.
|
|
245
|
+
Both sets of coordinates must already be centered at origin.
|
|
246
|
+
"""
|
|
247
|
+
# Calculate cross-covariance matrices
|
|
248
|
+
cov = np.sum(fixed[:,:,:,np.newaxis] * mobile[:,:,np.newaxis,:], axis=1)
|
|
249
|
+
v, s, w = np.linalg.svd(cov)
|
|
250
|
+
# Remove possibility of reflected atom coordinates
|
|
251
|
+
reflected_mask = (np.linalg.det(v) * np.linalg.det(w) < 0)
|
|
252
|
+
v[reflected_mask, :, -1] *= -1
|
|
253
|
+
matrices = np.matmul(v, w)
|
|
254
|
+
return matrices
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def _multi_matmul(matrices, vectors):
|
|
258
|
+
"""
|
|
259
|
+
Calculate the matrix multiplication of m matrices
|
|
260
|
+
with m x n vectors.
|
|
261
|
+
"""
|
|
262
|
+
return np.transpose(
|
|
263
|
+
np.matmul(
|
|
264
|
+
matrices,
|
|
265
|
+
np.transpose(vectors, axes=(0, 2, 1))
|
|
266
|
+
),
|
|
267
|
+
axes=(0, 2, 1)
|
|
268
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: biotite
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.40.0
|
|
4
4
|
Summary: A comprehensive library for computational molecular biology
|
|
5
5
|
Author: The Biotite contributors
|
|
6
6
|
License: BSD 3-Clause License
|
|
@@ -52,7 +52,7 @@ Requires-Python: >=3.7
|
|
|
52
52
|
Description-Content-Type: text/x-rst
|
|
53
53
|
License-File: LICENSE.rst
|
|
54
54
|
Requires-Dist: requests >=2.12
|
|
55
|
-
Requires-Dist: numpy
|
|
55
|
+
Requires-Dist: numpy <=2.0,>=1.14.5
|
|
56
56
|
Requires-Dist: msgpack >=0.5.6
|
|
57
57
|
Requires-Dist: networkx >=2.0
|
|
58
58
|
Provides-Extra: test
|