biotite 0.39.0__cp310-cp310-win_amd64.whl → 0.40.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.

Files changed (104) hide show
  1. biotite/__init__.py +3 -3
  2. biotite/application/dssp/app.py +18 -18
  3. biotite/database/rcsb/download.py +19 -14
  4. biotite/sequence/align/banded.c +258 -237
  5. biotite/sequence/align/banded.cp310-win_amd64.pyd +0 -0
  6. biotite/sequence/align/kmeralphabet.c +243 -222
  7. biotite/sequence/align/kmeralphabet.cp310-win_amd64.pyd +0 -0
  8. biotite/sequence/align/kmersimilarity.c +215 -196
  9. biotite/sequence/align/kmersimilarity.cp310-win_amd64.pyd +0 -0
  10. biotite/sequence/align/kmertable.cp310-win_amd64.pyd +0 -0
  11. biotite/sequence/align/kmertable.cpp +233 -205
  12. biotite/sequence/align/localgapped.c +258 -237
  13. biotite/sequence/align/localgapped.cp310-win_amd64.pyd +0 -0
  14. biotite/sequence/align/localungapped.c +235 -214
  15. biotite/sequence/align/localungapped.cp310-win_amd64.pyd +0 -0
  16. biotite/sequence/align/multiple.c +255 -234
  17. biotite/sequence/align/multiple.cp310-win_amd64.pyd +0 -0
  18. biotite/sequence/align/pairwise.c +274 -253
  19. biotite/sequence/align/pairwise.cp310-win_amd64.pyd +0 -0
  20. biotite/sequence/align/permutation.c +215 -196
  21. biotite/sequence/align/permutation.cp310-win_amd64.pyd +0 -0
  22. biotite/sequence/align/selector.c +217 -197
  23. biotite/sequence/align/selector.cp310-win_amd64.pyd +0 -0
  24. biotite/sequence/align/tracetable.c +215 -195
  25. biotite/sequence/align/tracetable.cp310-win_amd64.pyd +0 -0
  26. biotite/sequence/codec.c +235 -214
  27. biotite/sequence/codec.cp310-win_amd64.pyd +0 -0
  28. biotite/sequence/phylo/nj.c +215 -196
  29. biotite/sequence/phylo/nj.cp310-win_amd64.pyd +0 -0
  30. biotite/sequence/phylo/tree.c +227 -202
  31. biotite/sequence/phylo/tree.cp310-win_amd64.pyd +0 -0
  32. biotite/sequence/phylo/upgma.c +215 -196
  33. biotite/sequence/phylo/upgma.cp310-win_amd64.pyd +0 -0
  34. biotite/structure/basepairs.py +7 -12
  35. biotite/structure/bonds.c +1175 -1226
  36. biotite/structure/bonds.cp310-win_amd64.pyd +0 -0
  37. biotite/structure/celllist.c +217 -197
  38. biotite/structure/celllist.cp310-win_amd64.pyd +0 -0
  39. biotite/structure/charges.c +1052 -1101
  40. biotite/structure/charges.cp310-win_amd64.pyd +0 -0
  41. biotite/structure/filter.py +30 -37
  42. biotite/structure/info/__init__.py +5 -8
  43. biotite/structure/info/atoms.py +25 -67
  44. biotite/structure/info/bonds.py +46 -100
  45. biotite/structure/info/ccd/README.rst +8 -0
  46. biotite/structure/info/ccd/amino_acids.txt +1646 -0
  47. biotite/structure/info/ccd/carbohydrates.txt +1133 -0
  48. biotite/structure/info/ccd/components.bcif +0 -0
  49. biotite/structure/info/ccd/nucleotides.txt +797 -0
  50. biotite/structure/info/ccd.py +95 -0
  51. biotite/structure/info/groups.py +90 -0
  52. biotite/structure/info/masses.py +21 -20
  53. biotite/structure/info/misc.py +11 -22
  54. biotite/structure/info/standardize.py +17 -12
  55. biotite/structure/io/__init__.py +2 -4
  56. biotite/structure/io/ctab.py +1 -1
  57. biotite/structure/io/general.py +37 -43
  58. biotite/structure/io/mmtf/__init__.py +3 -0
  59. biotite/structure/io/mmtf/convertarray.c +219 -198
  60. biotite/structure/io/mmtf/convertarray.cp310-win_amd64.pyd +0 -0
  61. biotite/structure/io/mmtf/convertfile.c +217 -197
  62. biotite/structure/io/mmtf/convertfile.cp310-win_amd64.pyd +0 -0
  63. biotite/structure/io/mmtf/decode.c +225 -204
  64. biotite/structure/io/mmtf/decode.cp310-win_amd64.pyd +0 -0
  65. biotite/structure/io/mmtf/encode.c +215 -196
  66. biotite/structure/io/mmtf/encode.cp310-win_amd64.pyd +0 -0
  67. biotite/structure/io/mmtf/file.py +34 -26
  68. biotite/structure/io/npz/__init__.py +3 -0
  69. biotite/structure/io/npz/file.py +21 -18
  70. biotite/structure/io/pdb/__init__.py +3 -3
  71. biotite/structure/io/pdb/file.py +5 -3
  72. biotite/structure/io/pdb/hybrid36.c +63 -43
  73. biotite/structure/io/pdb/hybrid36.cp310-win_amd64.pyd +0 -0
  74. biotite/structure/io/pdbqt/file.py +32 -32
  75. biotite/structure/io/pdbx/__init__.py +13 -6
  76. biotite/structure/io/pdbx/bcif.py +649 -0
  77. biotite/structure/io/pdbx/cif.py +1028 -0
  78. biotite/structure/io/pdbx/component.py +243 -0
  79. biotite/structure/io/pdbx/convert.py +707 -359
  80. biotite/structure/io/pdbx/encoding.c +112813 -0
  81. biotite/structure/io/pdbx/encoding.cp310-win_amd64.pyd +0 -0
  82. biotite/structure/io/pdbx/error.py +14 -0
  83. biotite/structure/io/pdbx/legacy.py +267 -0
  84. biotite/structure/molecules.py +151 -151
  85. biotite/structure/sasa.c +215 -196
  86. biotite/structure/sasa.cp310-win_amd64.pyd +0 -0
  87. biotite/structure/superimpose.py +158 -115
  88. {biotite-0.39.0.dist-info → biotite-0.40.0.dist-info}/METADATA +2 -2
  89. {biotite-0.39.0.dist-info → biotite-0.40.0.dist-info}/RECORD +92 -90
  90. {biotite-0.39.0.dist-info → biotite-0.40.0.dist-info}/WHEEL +1 -1
  91. biotite/structure/info/amino_acids.json +0 -1556
  92. biotite/structure/info/amino_acids.py +0 -42
  93. biotite/structure/info/carbohydrates.json +0 -1122
  94. biotite/structure/info/carbohydrates.py +0 -39
  95. biotite/structure/info/intra_bonds.msgpack +0 -0
  96. biotite/structure/info/link_types.msgpack +0 -1
  97. biotite/structure/info/nucleotides.json +0 -772
  98. biotite/structure/info/nucleotides.py +0 -39
  99. biotite/structure/info/residue_masses.msgpack +0 -0
  100. biotite/structure/info/residue_names.msgpack +0 -3
  101. biotite/structure/info/residues.msgpack +0 -0
  102. biotite/structure/io/pdbx/file.py +0 -652
  103. {biotite-0.39.0.dist-info → biotite-0.40.0.dist-info}/LICENSE.rst +0 -0
  104. {biotite-0.39.0.dist-info → biotite-0.40.0.dist-info}/top_level.txt +0 -0
Binary file
@@ -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 : tuple or tuple list
53
- The tuple contains the transformations that were applied on
54
- `mobile`. This can be used in `apply_superimposition()` in order
55
- to transform another AtomArray in the same way.
56
- The first element contains the translation vector for moving the
57
- centroid into the origin.
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` tuple can be used in
70
- :func:`superimpose_apply()` in order to transform another
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 :func:`superimpose_apply()`.
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
- m_coord = coord(mobile)
115
- f_coord = coord(fixed)
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 = m_coord[..., atom_mask, :]
139
- fix_filtered = f_coord[atom_mask, :]
170
+ mob_filtered = mob_coord[:, atom_mask, :]
171
+ fix_filtered = fix_coord[:, atom_mask, :]
140
172
  else:
141
- mob_filtered = np.copy(m_coord)
142
- fix_filtered = np.copy(f_coord)
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 -= mob_centroid[..., np.newaxis, :]
148
- fix_filtered -= fix_centroid
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
- if mdim == 2:
166
- return superimposed, transformations[0]
167
- else:
168
- return superimposed, transformations
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 _superimpose(fix_centered, mob_centered):
172
- """
173
- Perform the Kabsch algorithm using only the coordinates.
189
+ def superimpose_apply(atoms, transformation):
174
190
  """
175
- # Calculating rotation matrix
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: tuple, size=3
200
- The transformation tuple, obtained by :func:`superimpose()`.
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
- trans1, rot, trans2 = transformation
215
- s_coord = coord(atoms).copy()
216
- s_coord += trans1
217
- s_coord = np.dot(rot, s_coord.T).T
218
- s_coord += trans2
219
-
220
- if isinstance(atoms, np.ndarray):
221
- return s_coord
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
- transformed = atoms.copy()
224
- transformed.coord = s_coord
225
- return transformed
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.39.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 >=1.14.5
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