biotite 0.38.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.

Files changed (124) hide show
  1. biotite/__init__.py +3 -3
  2. biotite/application/application.py +33 -28
  3. biotite/application/dssp/app.py +18 -18
  4. biotite/application/sra/__init__.py +5 -0
  5. biotite/application/sra/app.py +337 -55
  6. biotite/database/entrez/__init__.py +2 -1
  7. biotite/database/entrez/check.py +14 -3
  8. biotite/database/entrez/download.py +20 -13
  9. biotite/database/entrez/key.py +44 -0
  10. biotite/database/entrez/query.py +38 -34
  11. biotite/database/pubchem/query.py +44 -44
  12. biotite/database/rcsb/download.py +19 -14
  13. biotite/database/rcsb/query.py +46 -46
  14. biotite/sequence/align/__init__.py +5 -1
  15. biotite/sequence/align/banded.c +1408 -1025
  16. biotite/sequence/align/banded.cp311-win_amd64.pyd +0 -0
  17. biotite/sequence/align/buckets.py +69 -0
  18. biotite/sequence/align/cigar.py +389 -0
  19. biotite/sequence/align/kmeralphabet.c +3220 -2850
  20. biotite/sequence/align/kmeralphabet.cp311-win_amd64.pyd +0 -0
  21. biotite/sequence/align/kmersimilarity.c +713 -663
  22. biotite/sequence/align/kmersimilarity.cp311-win_amd64.pyd +0 -0
  23. biotite/sequence/align/kmertable.cp311-win_amd64.pyd +0 -0
  24. biotite/sequence/align/kmertable.cpp +68398 -0
  25. biotite/sequence/align/localgapped.c +1507 -1074
  26. biotite/sequence/align/localgapped.cp311-win_amd64.pyd +0 -0
  27. biotite/sequence/align/localungapped.c +1143 -833
  28. biotite/sequence/align/localungapped.cp311-win_amd64.pyd +0 -0
  29. biotite/sequence/align/multiple.c +1569 -1092
  30. biotite/sequence/align/multiple.cp311-win_amd64.pyd +0 -0
  31. biotite/sequence/align/pairwise.c +1612 -1212
  32. biotite/sequence/align/pairwise.cp311-win_amd64.pyd +0 -0
  33. biotite/sequence/align/permutation.c +33259 -0
  34. biotite/sequence/align/permutation.cp311-win_amd64.pyd +0 -0
  35. biotite/sequence/align/primes.txt +821 -0
  36. biotite/sequence/align/{kmertable.c → selector.c} +9129 -16497
  37. biotite/sequence/align/selector.cp311-win_amd64.pyd +0 -0
  38. biotite/sequence/align/tracetable.c +685 -646
  39. biotite/sequence/align/tracetable.cp311-win_amd64.pyd +0 -0
  40. biotite/sequence/codec.c +1159 -841
  41. biotite/sequence/codec.cp311-win_amd64.pyd +0 -0
  42. biotite/sequence/graphics/alignment.py +212 -2
  43. biotite/sequence/io/genbank/annotation.py +11 -11
  44. biotite/sequence/phylo/nj.c +684 -636
  45. biotite/sequence/phylo/nj.cp311-win_amd64.pyd +0 -0
  46. biotite/sequence/phylo/tree.c +970 -673
  47. biotite/sequence/phylo/tree.cp311-win_amd64.pyd +0 -0
  48. biotite/sequence/phylo/upgma.c +672 -626
  49. biotite/sequence/phylo/upgma.cp311-win_amd64.pyd +0 -0
  50. biotite/structure/__init__.py +1 -1
  51. biotite/structure/atoms.py +1 -1
  52. biotite/structure/basepairs.py +7 -12
  53. biotite/structure/bonds.c +3861 -3749
  54. biotite/structure/bonds.cp311-win_amd64.pyd +0 -0
  55. biotite/structure/celllist.c +727 -707
  56. biotite/structure/celllist.cp311-win_amd64.pyd +0 -0
  57. biotite/structure/charges.c +1561 -1560
  58. biotite/structure/charges.cp311-win_amd64.pyd +0 -0
  59. biotite/structure/filter.py +30 -37
  60. biotite/structure/info/__init__.py +5 -8
  61. biotite/structure/info/atoms.py +25 -67
  62. biotite/structure/info/bonds.py +46 -100
  63. biotite/structure/info/ccd/README.rst +8 -0
  64. biotite/structure/info/ccd/amino_acids.txt +1646 -0
  65. biotite/structure/info/ccd/carbohydrates.txt +1133 -0
  66. biotite/structure/info/ccd/components.bcif +0 -0
  67. biotite/structure/info/ccd/nucleotides.txt +797 -0
  68. biotite/structure/info/ccd.py +95 -0
  69. biotite/structure/info/groups.py +90 -0
  70. biotite/structure/info/masses.py +21 -20
  71. biotite/structure/info/misc.py +11 -22
  72. biotite/structure/info/standardize.py +17 -12
  73. biotite/structure/io/__init__.py +2 -4
  74. biotite/structure/io/ctab.py +1 -1
  75. biotite/structure/io/general.py +37 -43
  76. biotite/structure/io/mmtf/__init__.py +3 -0
  77. biotite/structure/io/mmtf/convertarray.c +528 -365
  78. biotite/structure/io/mmtf/convertarray.cp311-win_amd64.pyd +0 -0
  79. biotite/structure/io/mmtf/convertfile.c +725 -676
  80. biotite/structure/io/mmtf/convertfile.cp311-win_amd64.pyd +0 -0
  81. biotite/structure/io/mmtf/decode.c +1070 -754
  82. biotite/structure/io/mmtf/decode.cp311-win_amd64.pyd +0 -0
  83. biotite/structure/io/mmtf/encode.c +727 -677
  84. biotite/structure/io/mmtf/encode.cp311-win_amd64.pyd +0 -0
  85. biotite/structure/io/mmtf/file.py +34 -26
  86. biotite/structure/io/npz/__init__.py +3 -0
  87. biotite/structure/io/npz/file.py +21 -18
  88. biotite/structure/io/pdb/__init__.py +3 -3
  89. biotite/structure/io/pdb/file.py +72 -70
  90. biotite/structure/io/pdb/hybrid36.c +540 -478
  91. biotite/structure/io/pdb/hybrid36.cp311-win_amd64.pyd +0 -0
  92. biotite/structure/io/pdbqt/file.py +82 -68
  93. biotite/structure/io/pdbx/__init__.py +13 -6
  94. biotite/structure/io/pdbx/bcif.py +649 -0
  95. biotite/structure/io/pdbx/cif.py +1028 -0
  96. biotite/structure/io/pdbx/component.py +243 -0
  97. biotite/structure/io/pdbx/convert.py +707 -359
  98. biotite/structure/io/pdbx/encoding.c +112813 -0
  99. biotite/structure/io/pdbx/encoding.cp311-win_amd64.pyd +0 -0
  100. biotite/structure/io/pdbx/error.py +14 -0
  101. biotite/structure/io/pdbx/legacy.py +267 -0
  102. biotite/structure/molecules.py +151 -151
  103. biotite/structure/residues.py +40 -40
  104. biotite/structure/sasa.c +713 -644
  105. biotite/structure/sasa.cp311-win_amd64.pyd +0 -0
  106. biotite/structure/superimpose.py +158 -115
  107. biotite/visualize.py +9 -11
  108. {biotite-0.38.0.dist-info → biotite-0.40.0.dist-info}/METADATA +2 -2
  109. {biotite-0.38.0.dist-info → biotite-0.40.0.dist-info}/RECORD +112 -102
  110. {biotite-0.38.0.dist-info → biotite-0.40.0.dist-info}/WHEEL +1 -1
  111. biotite/structure/info/amino_acids.json +0 -1556
  112. biotite/structure/info/amino_acids.py +0 -42
  113. biotite/structure/info/carbohydrates.json +0 -1122
  114. biotite/structure/info/carbohydrates.py +0 -39
  115. biotite/structure/info/intra_bonds.msgpack +0 -0
  116. biotite/structure/info/link_types.msgpack +0 -1
  117. biotite/structure/info/nucleotides.json +0 -772
  118. biotite/structure/info/nucleotides.py +0 -39
  119. biotite/structure/info/residue_masses.msgpack +0 -0
  120. biotite/structure/info/residue_names.msgpack +0 -3
  121. biotite/structure/info/residues.msgpack +0 -0
  122. biotite/structure/io/pdbx/file.py +0 -652
  123. {biotite-0.38.0.dist-info → biotite-0.40.0.dist-info}/LICENSE.rst +0 -0
  124. {biotite-0.38.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
+ )
biotite/visualize.py CHANGED
@@ -35,7 +35,7 @@ def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
35
35
  Instead of having the font size fixed in 'pt', the size of the text
36
36
  scales to the specied width/height and adapts to changes in the
37
37
  plot's width/height.
38
- The scaling can be proportional or non-proportional, depending
38
+ The scaling can be proportional or non-proportional, depending
39
39
  the `mode`.
40
40
 
41
41
  Parameters
@@ -75,7 +75,7 @@ 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
78
+ from matplotlib.transforms import Bbox, Affine2D
79
79
  from matplotlib.patheffects import AbstractPathEffect
80
80
 
81
81
  class TextScaler(AbstractPathEffect):
@@ -98,7 +98,7 @@ def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
98
98
  raise
99
99
  bbox = text.get_window_extent(renderer)
100
100
  bbox = Bbox(ax.transData.inverted().transform(bbox))
101
-
101
+
102
102
  if self._mode == "proportional":
103
103
  if self._width is None:
104
104
  # Proportional scaling based on height
@@ -122,9 +122,9 @@ def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
122
122
  scale = min(scale_x, scale_y)
123
123
  scale_x, scale_y = scale, scale
124
124
 
125
- affine = affine.identity().scale(scale_x, scale_y) + affine
125
+ affine = Affine2D().scale(scale_x, scale_y) + affine
126
126
  renderer.draw_path(gc, tpath, affine, rgbFace)
127
-
127
+
128
128
  if mode in ["unlocked", "minimum", "maximum"]:
129
129
  if width is None or height is None:
130
130
  raise TypeError(
@@ -146,8 +146,6 @@ try:
146
146
  # Only create this class when matplotlib is installed
147
147
  from matplotlib.transforms import Bbox
148
148
  from matplotlib.patches import FancyArrow
149
- from matplotlib.patheffects import AbstractPathEffect
150
- import matplotlib.pyplot as plt
151
149
 
152
150
  class AdaptiveFancyArrow(FancyArrow):
153
151
  """
@@ -178,7 +176,7 @@ try:
178
176
  Other parameters that are used in the constructor of
179
177
  `FancyArrow`.
180
178
  """
181
-
179
+
182
180
  def __init__(self, x, y, dx, dy,
183
181
  tail_width, head_width, head_ratio, draw_head=True,
184
182
  shape="full", **kwargs):
@@ -219,7 +217,7 @@ try:
219
217
  # only draw the arrow head with reduced length
220
218
  head_length = arrow_length
221
219
  if not self._draw_head:
222
- head_length = 0
220
+ head_length = 0
223
221
 
224
222
  # Renew the arrow's properties
225
223
  super().__init__(
@@ -231,7 +229,7 @@ try:
231
229
  )
232
230
  self.set_clip_path(self.axes.patch)
233
231
  super().draw(renderer)
234
-
232
+
235
233
  # Override to replace docstring
236
234
  # Removes warning:
237
235
  # unknown document: /tutorials/intermediate/constrainedlayout_guide
@@ -245,7 +243,7 @@ try:
245
243
  return super().set_in_layout(in_layout)
246
244
 
247
245
  except ImportError:
248
-
246
+
249
247
  # Dummy class that propagates a meaningful error,
250
248
  # i.e. that Matplotlib is not installed
251
249
  class AdaptiveFancyArrow():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: biotite
3
- Version: 0.38.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