biotite 1.1.0__cp312-cp312-macosx_11_0_arm64.whl → 1.2.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 +3 -1
- 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 +16 -0
- biotite/interface/openmm/state.py +93 -0
- biotite/interface/openmm/system.py +227 -0
- biotite/interface/pymol/__init__.py +198 -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 +15 -0
- biotite/interface/rdkit/mol.py +490 -0
- biotite/interface/version.py +71 -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 +21 -21
- 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/pairwise.cpython-312-darwin.so +0 -0
- biotite/sequence/align/pairwise.pyx +35 -35
- 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 +26 -26
- biotite/structure/bonds.cpython-312-darwin.so +0 -0
- biotite/structure/bonds.pyx +8 -5
- biotite/structure/box.py +19 -21
- biotite/structure/celllist.cpython-312-darwin.so +0 -0
- biotite/structure/celllist.pyx +83 -67
- biotite/structure/chains.py +5 -37
- 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 +27 -28
- biotite/structure/filter.py +8 -8
- biotite/structure/geometry.py +15 -15
- biotite/structure/hbond.py +17 -19
- 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 +2 -3
- biotite/structure/io/pdb/file.py +11 -22
- 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 +2 -2
- biotite/structure/io/pdbx/convert.py +222 -33
- biotite/structure/io/pdbx/encoding.cpython-312-darwin.so +0 -0
- 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 +7 -13
- biotite/structure/repair.py +2 -4
- biotite/structure/residues.py +13 -24
- biotite/structure/rings.py +335 -0
- biotite/structure/sasa.cpython-312-darwin.so +0 -0
- biotite/structure/sasa.pyx +2 -1
- biotite/structure/segments.py +68 -9
- biotite/structure/sequence.py +0 -1
- biotite/structure/sse.py +0 -2
- biotite/structure/superimpose.py +74 -62
- biotite/structure/tm.py +581 -0
- biotite/structure/transform.py +12 -25
- biotite/structure/util.py +3 -3
- biotite/version.py +9 -4
- biotite/visualize.py +111 -1
- {biotite-1.1.0.dist-info → biotite-1.2.0.dist-info}/METADATA +5 -3
- {biotite-1.1.0.dist-info → biotite-1.2.0.dist-info}/RECORD +155 -135
- {biotite-1.1.0.dist-info → biotite-1.2.0.dist-info}/WHEEL +0 -0
- {biotite-1.1.0.dist-info → biotite-1.2.0.dist-info}/licenses/LICENSE.rst +0 -0
biotite/structure/io/mol/ctab.py
CHANGED
|
@@ -19,24 +19,19 @@ from biotite.file import InvalidFileError
|
|
|
19
19
|
from biotite.structure.atoms import AtomArray, AtomArrayStack
|
|
20
20
|
from biotite.structure.bonds import BondList, BondType
|
|
21
21
|
from biotite.structure.error import BadStructureError
|
|
22
|
+
from biotite.structure.io.util import number_of_integer_digits
|
|
22
23
|
|
|
23
24
|
BOND_TYPE_MAPPING = {
|
|
24
25
|
1: BondType.SINGLE,
|
|
25
26
|
2: BondType.DOUBLE,
|
|
26
27
|
3: BondType.TRIPLE,
|
|
28
|
+
4: BondType.AROMATIC,
|
|
27
29
|
5: BondType.ANY,
|
|
28
|
-
6: BondType.
|
|
29
|
-
7: BondType.
|
|
30
|
+
6: BondType.AROMATIC_SINGLE,
|
|
31
|
+
7: BondType.AROMATIC_DOUBLE,
|
|
30
32
|
8: BondType.ANY,
|
|
31
33
|
}
|
|
32
|
-
BOND_TYPE_MAPPING_REV = {
|
|
33
|
-
BondType.SINGLE: 1,
|
|
34
|
-
BondType.DOUBLE: 2,
|
|
35
|
-
BondType.TRIPLE: 3,
|
|
36
|
-
BondType.AROMATIC_SINGLE: 1,
|
|
37
|
-
BondType.AROMATIC_DOUBLE: 2,
|
|
38
|
-
BondType.ANY: 8,
|
|
39
|
-
}
|
|
34
|
+
BOND_TYPE_MAPPING_REV = {v: k for k, v in BOND_TYPE_MAPPING.items()}
|
|
40
35
|
|
|
41
36
|
CHARGE_MAPPING = {0: 0, 1: 3, 2: 2, 3: 1, 5: -1, 6: -2, 7: -3}
|
|
42
37
|
CHARGE_MAPPING_REV = {val: key for key, val in CHARGE_MAPPING.items()}
|
|
@@ -56,7 +51,7 @@ def read_structure_from_ctab(ctab_lines):
|
|
|
56
51
|
----------
|
|
57
52
|
ctab_lines : lines of str
|
|
58
53
|
The lines containing the *ctab*.
|
|
59
|
-
Must begin with the *counts* line and end with the `M END` line
|
|
54
|
+
Must begin with the *counts* line and end with the `M END` line.
|
|
60
55
|
|
|
61
56
|
Returns
|
|
62
57
|
-------
|
|
@@ -71,7 +66,6 @@ def read_structure_from_ctab(ctab_lines):
|
|
|
71
66
|
`<https://discover.3ds.com/sites/default/files/2020-08/biovia_ctfileformats_2020.pdf>`_.
|
|
72
67
|
|
|
73
68
|
.. footbibliography::
|
|
74
|
-
|
|
75
69
|
"""
|
|
76
70
|
match _get_version(ctab_lines[0]):
|
|
77
71
|
case "V2000":
|
|
@@ -119,11 +113,10 @@ def write_structure_to_ctab(atoms, default_bond_type=BondType.ANY, version=None)
|
|
|
119
113
|
`<https://discover.3ds.com/sites/default/files/2020-08/biovia_ctfileformats_2020.pdf>`_.
|
|
120
114
|
|
|
121
115
|
.. footbibliography::
|
|
122
|
-
|
|
123
116
|
"""
|
|
124
117
|
if isinstance(atoms, AtomArrayStack):
|
|
125
118
|
raise TypeError(
|
|
126
|
-
"An 'AtomArrayStack' was given,
|
|
119
|
+
"An 'AtomArrayStack' was given, but only a single model can be written"
|
|
127
120
|
)
|
|
128
121
|
if atoms.bonds is None:
|
|
129
122
|
raise BadStructureError("Input AtomArray has no associated BondList")
|
|
@@ -141,8 +134,7 @@ def write_structure_to_ctab(atoms, default_bond_type=BondType.ANY, version=None)
|
|
|
141
134
|
atoms.array_length(), atoms.bonds.get_bond_count()
|
|
142
135
|
):
|
|
143
136
|
raise ValueError(
|
|
144
|
-
"The given number of atoms or bonds is too large "
|
|
145
|
-
"for V2000 format"
|
|
137
|
+
"The given number of atoms or bonds is too large for V2000 format"
|
|
146
138
|
)
|
|
147
139
|
return _write_structure_to_ctab_v2000(atoms, default_bond_type)
|
|
148
140
|
case "V3000":
|
|
@@ -174,7 +166,7 @@ def _read_structure_from_ctab_v2000(ctab_lines):
|
|
|
174
166
|
charge = CHARGE_MAPPING.get(int(line[36:39]))
|
|
175
167
|
if charge is None:
|
|
176
168
|
warnings.warn(
|
|
177
|
-
f"Cannot handle MDL charge type {int(line[36
|
|
169
|
+
f"Cannot handle MDL charge type {int(line[36:39])}, "
|
|
178
170
|
f"0 is used instead"
|
|
179
171
|
)
|
|
180
172
|
charge = 0
|
|
@@ -194,7 +186,7 @@ def _read_structure_from_ctab_v2000(ctab_lines):
|
|
|
194
186
|
bond_type = BOND_TYPE_MAPPING.get(int(line[6:9]))
|
|
195
187
|
if bond_type is None:
|
|
196
188
|
warnings.warn(
|
|
197
|
-
f"Cannot handle MDL bond type {int(line[6
|
|
189
|
+
f"Cannot handle MDL bond type {int(line[6:9])}, "
|
|
198
190
|
f"BondType.ANY is used instead"
|
|
199
191
|
)
|
|
200
192
|
bond_type = BondType.ANY
|
|
@@ -247,8 +239,7 @@ def _read_structure_from_ctab_v3000(ctab_lines):
|
|
|
247
239
|
bond_type = BOND_TYPE_MAPPING.get(v30_type)
|
|
248
240
|
if bond_type is None:
|
|
249
241
|
warnings.warn(
|
|
250
|
-
f"Cannot handle MDL bond type {v30_type}, "
|
|
251
|
-
f"BondType.ANY is used instead"
|
|
242
|
+
f"Cannot handle MDL bond type {v30_type}, BondType.ANY is used instead"
|
|
252
243
|
)
|
|
253
244
|
bond_type = BondType.ANY
|
|
254
245
|
bond_array[i, 0] = v30_atom_indices[v30_atom_index_1]
|
|
@@ -307,10 +298,17 @@ def _write_structure_to_ctab_v2000(atoms, default_bond_type):
|
|
|
307
298
|
" 0 0 0 0 0 0 0 1 V2000"
|
|
308
299
|
)
|
|
309
300
|
|
|
301
|
+
for i, coord_name in enumerate(["x", "y", "z"]):
|
|
302
|
+
n_coord_digits = number_of_integer_digits(atoms.coord[:, i])
|
|
303
|
+
if n_coord_digits > 5:
|
|
304
|
+
raise BadStructureError(
|
|
305
|
+
f"5 pre-decimal columns for {coord_name}-coordinates are "
|
|
306
|
+
f"available, but array would require {n_coord_digits}"
|
|
307
|
+
)
|
|
310
308
|
atom_lines = [
|
|
311
|
-
f"{atoms.coord[i,0]:>10.4f}"
|
|
312
|
-
f"{atoms.coord[i,1]:>10.4f}"
|
|
313
|
-
f"{atoms.coord[i,2]:>10.4f}"
|
|
309
|
+
f"{atoms.coord[i, 0]:>10.4f}"
|
|
310
|
+
f"{atoms.coord[i, 1]:>10.4f}"
|
|
311
|
+
f"{atoms.coord[i, 2]:>10.4f}"
|
|
314
312
|
f" {atoms.element[i].capitalize():3}"
|
|
315
313
|
f"{0:>2}" # Mass difference -> unused
|
|
316
314
|
f"{CHARGE_MAPPING_REV.get(charge[i], 0):>3d}"
|
|
@@ -321,7 +319,7 @@ def _write_structure_to_ctab_v2000(atoms, default_bond_type):
|
|
|
321
319
|
|
|
322
320
|
default_bond_value = BOND_TYPE_MAPPING_REV[default_bond_type]
|
|
323
321
|
bond_lines = [
|
|
324
|
-
f"{i+1:>3d}{j+1:>3d}"
|
|
322
|
+
f"{i + 1:>3d}{j + 1:>3d}"
|
|
325
323
|
f"{BOND_TYPE_MAPPING_REV.get(bond_type, default_bond_value):>3d}"
|
|
326
324
|
+ f"{0:>3d}"
|
|
327
325
|
* 4
|
|
@@ -337,7 +335,7 @@ def _write_structure_to_ctab_v2000(atoms, default_bond_type):
|
|
|
337
335
|
):
|
|
338
336
|
charge_lines.append(
|
|
339
337
|
f"M CHG{len(batch):>3d}"
|
|
340
|
-
+ "".join(f" {atom_i+1:>3d} {c:>3d}" for atom_i, c in batch)
|
|
338
|
+
+ "".join(f" {atom_i + 1:>3d} {c:>3d}" for atom_i, c in batch)
|
|
341
339
|
)
|
|
342
340
|
|
|
343
341
|
return [counts_line] + atom_lines + bond_lines + charge_lines + ["M END"]
|
|
@@ -351,12 +349,19 @@ def _write_structure_to_ctab_v3000(atoms, default_bond_type):
|
|
|
351
349
|
|
|
352
350
|
counts_line = f"COUNTS {atoms.array_length()} {atoms.bonds.get_bond_count()} 0 0 0"
|
|
353
351
|
|
|
352
|
+
for i, coord_name in enumerate(["x", "y", "z"]):
|
|
353
|
+
n_coord_digits = number_of_integer_digits(atoms.coord[:, i])
|
|
354
|
+
if n_coord_digits > 5:
|
|
355
|
+
raise BadStructureError(
|
|
356
|
+
f"5 pre-decimal columns for {coord_name}-coordinates are "
|
|
357
|
+
f"available, but array would require {n_coord_digits}"
|
|
358
|
+
)
|
|
354
359
|
atom_lines = [
|
|
355
360
|
f"{i + 1}"
|
|
356
361
|
f" {_quote(atoms.element[i].capitalize())}"
|
|
357
|
-
f" {atoms.coord[i,0]:.4f}"
|
|
358
|
-
f" {atoms.coord[i,1]:.4f}"
|
|
359
|
-
f" {atoms.coord[i,2]:.4f}"
|
|
362
|
+
f" {atoms.coord[i, 0]:.4f}"
|
|
363
|
+
f" {atoms.coord[i, 1]:.4f}"
|
|
364
|
+
f" {atoms.coord[i, 2]:.4f}"
|
|
360
365
|
# 'aamap' is unused
|
|
361
366
|
f" 0"
|
|
362
367
|
f" {_to_property(charges[i])}"
|
biotite/structure/io/mol/mol.py
CHANGED
biotite/structure/io/mol/sdf.py
CHANGED
|
@@ -78,7 +78,6 @@ class Metadata(MutableMapping):
|
|
|
78
78
|
>>> print(metadata[Metadata.Key(number=42, name="bar")])
|
|
79
79
|
dolor sit amet,
|
|
80
80
|
consectetur
|
|
81
|
-
|
|
82
81
|
"""
|
|
83
82
|
|
|
84
83
|
@dataclass(frozen=True, kw_only=True)
|
|
@@ -144,12 +143,18 @@ class Metadata(MutableMapping):
|
|
|
144
143
|
@staticmethod
|
|
145
144
|
def deserialize(text):
|
|
146
145
|
"""
|
|
147
|
-
Create
|
|
146
|
+
Create a :class:`Metadata.Key` object by deserializing the given text
|
|
147
|
+
content.
|
|
148
148
|
|
|
149
149
|
Parameters
|
|
150
150
|
----------
|
|
151
|
-
|
|
151
|
+
text : str
|
|
152
152
|
The content to be deserialized.
|
|
153
|
+
|
|
154
|
+
Returns
|
|
155
|
+
-------
|
|
156
|
+
key : Metadata.Key
|
|
157
|
+
The parsed key.
|
|
153
158
|
"""
|
|
154
159
|
# Omit the leading '>'
|
|
155
160
|
key_components = text[1:].split()
|
|
@@ -207,12 +212,17 @@ class Metadata(MutableMapping):
|
|
|
207
212
|
@staticmethod
|
|
208
213
|
def deserialize(text):
|
|
209
214
|
"""
|
|
210
|
-
Create
|
|
215
|
+
Create a :class:`Metadata` objtect by deserializing the given text content.
|
|
211
216
|
|
|
212
217
|
Parameters
|
|
213
218
|
----------
|
|
214
|
-
|
|
219
|
+
text : str
|
|
215
220
|
The content to be deserialized.
|
|
221
|
+
|
|
222
|
+
Returns
|
|
223
|
+
-------
|
|
224
|
+
metadata : Metadata
|
|
225
|
+
The parsed metadata.
|
|
216
226
|
"""
|
|
217
227
|
metadata = {}
|
|
218
228
|
current_key = None
|
|
@@ -423,19 +433,23 @@ class SDRecord:
|
|
|
423
433
|
self._metadata = Metadata(metadata)
|
|
424
434
|
else:
|
|
425
435
|
raise TypeError(
|
|
426
|
-
"Expected 'Metadata' or Mapping, "
|
|
427
|
-
f"but got '{type(metadata).__name__}'"
|
|
436
|
+
f"Expected 'Metadata' or Mapping, but got '{type(metadata).__name__}'"
|
|
428
437
|
)
|
|
429
438
|
|
|
430
439
|
@staticmethod
|
|
431
440
|
def deserialize(text):
|
|
432
441
|
"""
|
|
433
|
-
Create an
|
|
442
|
+
Create an :class:`SDRecord` by deserializing the given text content.
|
|
434
443
|
|
|
435
444
|
Parameters
|
|
436
445
|
----------
|
|
437
|
-
|
|
446
|
+
text : str
|
|
438
447
|
The content to be deserialized.
|
|
448
|
+
|
|
449
|
+
Returns
|
|
450
|
+
-------
|
|
451
|
+
record : SDRecord
|
|
452
|
+
The parsed record.
|
|
439
453
|
"""
|
|
440
454
|
lines = text.splitlines()
|
|
441
455
|
ctab_end = _get_ctab_stop(lines)
|
|
@@ -494,7 +508,7 @@ class SDRecord:
|
|
|
494
508
|
|
|
495
509
|
Parameters
|
|
496
510
|
----------
|
|
497
|
-
|
|
511
|
+
atoms : AtomArray
|
|
498
512
|
The array to be saved into this file.
|
|
499
513
|
Must have an associated :class:`BondList`.
|
|
500
514
|
default_bond_type : BondType, optional
|
|
@@ -539,6 +553,13 @@ class SDFile(File, MutableMapping):
|
|
|
539
553
|
:class:`SDRecord` object via :func:`get_structure()` or
|
|
540
554
|
:func:`set_structure()`, respectively.
|
|
541
555
|
|
|
556
|
+
Parameters
|
|
557
|
+
----------
|
|
558
|
+
records : dict (str -> SDRecord), optional
|
|
559
|
+
The initial records of the file.
|
|
560
|
+
Maps the record names to the corresponding :class:`SDRecord` objects.
|
|
561
|
+
By default no initial records are added.
|
|
562
|
+
|
|
542
563
|
Attributes
|
|
543
564
|
----------
|
|
544
565
|
record : CIFBlock
|
|
@@ -732,12 +753,17 @@ class SDFile(File, MutableMapping):
|
|
|
732
753
|
@staticmethod
|
|
733
754
|
def deserialize(text):
|
|
734
755
|
"""
|
|
735
|
-
Create an
|
|
756
|
+
Create an :class:`SDFile` by deserializing the given text content.
|
|
736
757
|
|
|
737
758
|
Parameters
|
|
738
759
|
----------
|
|
739
|
-
|
|
760
|
+
text : str
|
|
740
761
|
The content to be deserialized.
|
|
762
|
+
|
|
763
|
+
Returns
|
|
764
|
+
-------
|
|
765
|
+
file_object : SDFile
|
|
766
|
+
The parsed file.
|
|
741
767
|
"""
|
|
742
768
|
lines = text.splitlines()
|
|
743
769
|
record_ends = np.array(
|
|
@@ -896,7 +922,7 @@ def _to_metadata_key(key):
|
|
|
896
922
|
return Metadata.Key(name=key)
|
|
897
923
|
else:
|
|
898
924
|
raise TypeError(
|
|
899
|
-
"Expected 'Metadata.Key' or str,
|
|
925
|
+
f"Expected 'Metadata.Key' or str, but got '{type(key).__name__}'"
|
|
900
926
|
)
|
|
901
927
|
|
|
902
928
|
|
|
@@ -89,14 +89,13 @@ def get_structure(
|
|
|
89
89
|
-------
|
|
90
90
|
array : AtomArray or AtomArrayStack
|
|
91
91
|
The return type depends on the `model` parameter.
|
|
92
|
-
|
|
93
92
|
"""
|
|
94
93
|
return pdb_file.get_structure(model, altloc, extra_fields, include_bonds)
|
|
95
94
|
|
|
96
95
|
|
|
97
96
|
def set_structure(pdb_file, array, hybrid36=False):
|
|
98
97
|
"""
|
|
99
|
-
|
|
98
|
+
Write an :class:`AtomArray` or :class:`AtomArrayStack` into a
|
|
100
99
|
:class:`PDBFile`.
|
|
101
100
|
|
|
102
101
|
This function is a thin wrapper around the :class:`PDBFile` method
|
|
@@ -114,7 +113,7 @@ def set_structure(pdb_file, array, hybrid36=False):
|
|
|
114
113
|
array : AtomArray or AtomArrayStack
|
|
115
114
|
The structure to be written. If a stack is given, each array in
|
|
116
115
|
the stack will be in a separate model.
|
|
117
|
-
hybrid36: boolean, optional
|
|
116
|
+
hybrid36 : boolean, optional
|
|
118
117
|
Defines wether the file should be written in hybrid-36 format.
|
|
119
118
|
|
|
120
119
|
Notes
|
biotite/structure/io/pdb/file.py
CHANGED
|
@@ -24,6 +24,7 @@ from biotite.structure.io.pdb.hybrid36 import (
|
|
|
24
24
|
encode_hybrid36,
|
|
25
25
|
max_hybrid36_number,
|
|
26
26
|
)
|
|
27
|
+
from biotite.structure.io.util import number_of_integer_digits
|
|
27
28
|
from biotite.structure.repair import infer_elements
|
|
28
29
|
from biotite.structure.util import matrix_rotate
|
|
29
30
|
|
|
@@ -70,10 +71,10 @@ class PDBFile(TextFile):
|
|
|
70
71
|
records cannot be written.
|
|
71
72
|
Additionally, *REMARK* records can be read
|
|
72
73
|
|
|
73
|
-
See
|
|
74
|
+
See Also
|
|
74
75
|
--------
|
|
75
|
-
CIFFile
|
|
76
|
-
BinaryCIFFile
|
|
76
|
+
CIFFile : Interface to CIF files, a modern replacement for PDB files.
|
|
77
|
+
BinaryCIFFile : Interface to BinaryCIF files, a binary variant of CIF files.
|
|
77
78
|
|
|
78
79
|
Examples
|
|
79
80
|
--------
|
|
@@ -597,7 +598,7 @@ class PDBFile(TextFile):
|
|
|
597
598
|
The array or stack to be saved into this file. If a stack
|
|
598
599
|
is given, each array in the stack is saved as separate
|
|
599
600
|
model.
|
|
600
|
-
hybrid36: bool, optional
|
|
601
|
+
hybrid36 : bool, optional
|
|
601
602
|
Defines wether the file should be written in hybrid-36
|
|
602
603
|
format.
|
|
603
604
|
|
|
@@ -894,7 +895,7 @@ class PDBFile(TextFile):
|
|
|
894
895
|
if assembly_start_i is None:
|
|
895
896
|
if assembly_id is None:
|
|
896
897
|
raise InvalidFileError(
|
|
897
|
-
"File does not contain transformation
|
|
898
|
+
"File does not contain transformation expressions for assemblies"
|
|
898
899
|
)
|
|
899
900
|
else:
|
|
900
901
|
raise KeyError(f"The assembly ID '{assembly_id}' is not found")
|
|
@@ -1106,7 +1107,7 @@ class PDBFile(TextFile):
|
|
|
1106
1107
|
length = model_length
|
|
1107
1108
|
if model_length != length:
|
|
1108
1109
|
raise InvalidFileError(
|
|
1109
|
-
f"Model {model_i+1} has {model_length} atoms, "
|
|
1110
|
+
f"Model {model_i + 1} has {model_length} atoms, "
|
|
1110
1111
|
f"but model 1 has {length} atoms, must be equal"
|
|
1111
1112
|
)
|
|
1112
1113
|
return length
|
|
@@ -1248,21 +1249,21 @@ def _check_pdb_compatibility(array, hybrid36):
|
|
|
1248
1249
|
if any([len(name) > 4 for name in array.atom_name]):
|
|
1249
1250
|
raise BadStructureError("Some atom names exceed 4 characters")
|
|
1250
1251
|
for i, coord_name in enumerate(["x", "y", "z"]):
|
|
1251
|
-
n_coord_digits =
|
|
1252
|
+
n_coord_digits = number_of_integer_digits(array.coord[..., i])
|
|
1252
1253
|
if n_coord_digits > 4:
|
|
1253
1254
|
raise BadStructureError(
|
|
1254
1255
|
f"4 pre-decimal columns for {coord_name}-coordinates are "
|
|
1255
1256
|
f"available, but array would require {n_coord_digits}"
|
|
1256
1257
|
)
|
|
1257
1258
|
if "b_factor" in annot_categories:
|
|
1258
|
-
n_b_factor_digits =
|
|
1259
|
+
n_b_factor_digits = number_of_integer_digits(array.b_factor)
|
|
1259
1260
|
if n_b_factor_digits > 3:
|
|
1260
1261
|
raise BadStructureError(
|
|
1261
1262
|
"3 pre-decimal columns for B-factor are available, "
|
|
1262
1263
|
f"but array would require {n_b_factor_digits}"
|
|
1263
1264
|
)
|
|
1264
1265
|
if "occupancy" in annot_categories:
|
|
1265
|
-
n_occupancy_digits =
|
|
1266
|
+
n_occupancy_digits = number_of_integer_digits(array.occupancy)
|
|
1266
1267
|
if n_occupancy_digits > 3:
|
|
1267
1268
|
raise BadStructureError(
|
|
1268
1269
|
"3 pre-decimal columns for occupancy are available, "
|
|
@@ -1270,21 +1271,9 @@ def _check_pdb_compatibility(array, hybrid36):
|
|
|
1270
1271
|
)
|
|
1271
1272
|
if "charge" in annot_categories:
|
|
1272
1273
|
# The sign can be omitted is it is put into the adjacent column
|
|
1273
|
-
n_charge_digits =
|
|
1274
|
+
n_charge_digits = number_of_integer_digits(np.abs(array.charge))
|
|
1274
1275
|
if n_charge_digits > 1:
|
|
1275
1276
|
raise BadStructureError(
|
|
1276
1277
|
"1 column for charge is available, "
|
|
1277
1278
|
f"but array would require {n_charge_digits}"
|
|
1278
1279
|
)
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
def _number_of_integer_digits(values):
|
|
1282
|
-
"""
|
|
1283
|
-
Get the maximum number of characters needed to represent the
|
|
1284
|
-
pre-decimal positions of the given numeric values.
|
|
1285
|
-
"""
|
|
1286
|
-
values = values.astype(int, copy=False)
|
|
1287
|
-
n_digits = 0
|
|
1288
|
-
n_digits = max(n_digits, len(str(np.min(values))))
|
|
1289
|
-
n_digits = max(n_digits, len(str(np.max(values))))
|
|
1290
|
-
return n_digits
|
|
Binary file
|
|
@@ -525,9 +525,9 @@ class PDBQTFile(TextFile):
|
|
|
525
525
|
f"{atoms.chain_id[i]:1}"
|
|
526
526
|
f"{atoms.res_id[i]:>4d}"
|
|
527
527
|
f"{atoms.ins_code[i]:1} "
|
|
528
|
-
f"{atoms.coord[i,0]:>8.3f}"
|
|
529
|
-
f"{atoms.coord[i,1]:>8.3f}"
|
|
530
|
-
f"{atoms.coord[i,2]:>8.3f}"
|
|
528
|
+
f"{atoms.coord[i, 0]:>8.3f}"
|
|
529
|
+
f"{atoms.coord[i, 1]:>8.3f}"
|
|
530
|
+
f"{atoms.coord[i, 2]:>8.3f}"
|
|
531
531
|
f"{occupancy[i]:>6.2f}"
|
|
532
532
|
f"{b_factor[i]:>6.2f} "
|
|
533
533
|
f"{charges[i]:>6.3f} "
|
|
@@ -604,7 +604,7 @@ class PDBQTFile(TextFile):
|
|
|
604
604
|
length = model_length
|
|
605
605
|
if model_length != length:
|
|
606
606
|
raise InvalidFileError(
|
|
607
|
-
f"Model {model_i+1} has {model_length} atoms, "
|
|
607
|
+
f"Model {model_i + 1} has {model_length} atoms, "
|
|
608
608
|
f"but model 1 has {length} atoms, must be equal"
|
|
609
609
|
)
|
|
610
610
|
return length
|
|
@@ -195,7 +195,7 @@ class BinaryCIFColumn(_Component):
|
|
|
195
195
|
mask = BinaryCIFData(mask)
|
|
196
196
|
if len(data) != len(mask):
|
|
197
197
|
raise IndexError(
|
|
198
|
-
f"Data has length {len(data)},
|
|
198
|
+
f"Data has length {len(data)}, but mask has length {len(mask)}"
|
|
199
199
|
)
|
|
200
200
|
self._data = data
|
|
201
201
|
self._mask = mask
|
|
@@ -256,6 +256,11 @@ class BinaryCIFColumn(_Component):
|
|
|
256
256
|
``MaskValue.INAPPLICABLE`` or ``MaskValue.MISSING``.
|
|
257
257
|
By default, masked elements are converted to ``'.'`` or
|
|
258
258
|
``'?'`` depending on the :class:`MaskValue`.
|
|
259
|
+
|
|
260
|
+
Returns
|
|
261
|
+
-------
|
|
262
|
+
array : ndarray
|
|
263
|
+
The column data as array.
|
|
259
264
|
"""
|
|
260
265
|
if dtype is None:
|
|
261
266
|
dtype = self._data.array.dtype
|
|
@@ -341,12 +346,15 @@ class BinaryCIFCategory(_HierarchicalContainer):
|
|
|
341
346
|
into a :class:`BinaryCIFColumn`).
|
|
342
347
|
By default, an empty category is created.
|
|
343
348
|
Each column must have the same length.
|
|
349
|
+
row_count : int, optional
|
|
350
|
+
The number of rows in the category.
|
|
344
351
|
|
|
345
352
|
Attributes
|
|
346
353
|
----------
|
|
347
354
|
row_count : int
|
|
348
355
|
The number of rows in the category, i.e. the length of each
|
|
349
356
|
column.
|
|
357
|
+
By default, the row count is determined when the first column is added.
|
|
350
358
|
|
|
351
359
|
Examples
|
|
352
360
|
--------
|
|
@@ -526,6 +534,19 @@ class BinaryCIFFile(File, _HierarchicalContainer):
|
|
|
526
534
|
object, use the high-level :func:`get_structure()` or
|
|
527
535
|
:func:`set_structure()` function respectively.
|
|
528
536
|
|
|
537
|
+
Parameters
|
|
538
|
+
----------
|
|
539
|
+
blocks : dict (str -> BinaryCIFBlock), optional
|
|
540
|
+
The initial blocks of the file.
|
|
541
|
+
Maps the block names to the corresponding :class:`BinaryCIFBlock` objects.
|
|
542
|
+
By default no initial blocks are added.
|
|
543
|
+
|
|
544
|
+
Attributes
|
|
545
|
+
----------
|
|
546
|
+
block : BinaryCIFBlock
|
|
547
|
+
The sole block of the file.
|
|
548
|
+
If the file contains multiple blocks, an exception is raised.
|
|
549
|
+
|
|
529
550
|
Notes
|
|
530
551
|
-----
|
|
531
552
|
The content of *BinaryCIF* files are lazily deserialized:
|
|
@@ -534,12 +555,6 @@ class BinaryCIFFile(File, _HierarchicalContainer):
|
|
|
534
555
|
The decoded :class:`BinaryCIFBlock`/:class:`BinaryCIFCategory`
|
|
535
556
|
objects are cached for subsequent accesses.
|
|
536
557
|
|
|
537
|
-
Attributes
|
|
538
|
-
----------
|
|
539
|
-
block : BinaryCIFBlock
|
|
540
|
-
The sole block of the file.
|
|
541
|
-
If the file contains multiple blocks, an exception is raised.
|
|
542
|
-
|
|
543
558
|
Examples
|
|
544
559
|
--------
|
|
545
560
|
Read a *BinaryCIF* file and access its content:
|
biotite/structure/io/pdbx/cif.py
CHANGED
|
@@ -149,7 +149,7 @@ class CIFColumn:
|
|
|
149
149
|
mask = CIFData(mask, np.uint8)
|
|
150
150
|
if len(mask) != len(data):
|
|
151
151
|
raise IndexError(
|
|
152
|
-
f"Data has length {len(data)},
|
|
152
|
+
f"Data has length {len(data)}, but mask has length {len(mask)}"
|
|
153
153
|
)
|
|
154
154
|
self._data = data
|
|
155
155
|
self._mask = mask
|
|
@@ -215,6 +215,11 @@ class CIFColumn:
|
|
|
215
215
|
``MaskValue.INAPPLICABLE`` or ``MaskValue.MISSING``.
|
|
216
216
|
By default, masked elements are converted to ``'.'`` or
|
|
217
217
|
``'?'`` depending on the :class:`MaskValue`.
|
|
218
|
+
|
|
219
|
+
Returns
|
|
220
|
+
-------
|
|
221
|
+
array : ndarray
|
|
222
|
+
The column data as array.
|
|
218
223
|
"""
|
|
219
224
|
if self._mask is None:
|
|
220
225
|
return self._data.array.astype(dtype, copy=False)
|
|
@@ -721,6 +726,19 @@ class CIFFile(_Component, File, MutableMapping):
|
|
|
721
726
|
use the high-level :func:`get_structure()` or
|
|
722
727
|
:func:`set_structure()` function respectively.
|
|
723
728
|
|
|
729
|
+
Parameters
|
|
730
|
+
----------
|
|
731
|
+
blocks : dict (str -> CIFBlock), optional
|
|
732
|
+
The initial blocks of the file.
|
|
733
|
+
Maps the block names to the corresponding :class:`CIFBlock` objects.
|
|
734
|
+
By default no initial blocks are added.
|
|
735
|
+
|
|
736
|
+
Attributes
|
|
737
|
+
----------
|
|
738
|
+
block : CIFBlock
|
|
739
|
+
The sole block of the file.
|
|
740
|
+
If the file contains multiple blocks, an exception is raised.
|
|
741
|
+
|
|
724
742
|
Notes
|
|
725
743
|
-----
|
|
726
744
|
The content of CIF files are lazily deserialized:
|
|
@@ -731,12 +749,6 @@ class CIFFile(_Component, File, MutableMapping):
|
|
|
731
749
|
The deserialized :class:`CIFBlock`/:class:`CIFCategory` objects
|
|
732
750
|
are cached for subsequent accesses.
|
|
733
751
|
|
|
734
|
-
Attributes
|
|
735
|
-
----------
|
|
736
|
-
block : CIFBlock
|
|
737
|
-
The sole block of the file.
|
|
738
|
-
If the file contains multiple blocks, an exception is raised.
|
|
739
|
-
|
|
740
752
|
Examples
|
|
741
753
|
--------
|
|
742
754
|
Read a CIF file and access its content:
|
|
@@ -884,6 +896,7 @@ class CIFFile(_Component, File, MutableMapping):
|
|
|
884
896
|
block = CIFBlock.deserialize(block)
|
|
885
897
|
except Exception:
|
|
886
898
|
raise DeserializationError(f"Failed to deserialize block '{key}'")
|
|
899
|
+
block.name = key
|
|
887
900
|
# Update with deserialized object
|
|
888
901
|
self._blocks[key] = block
|
|
889
902
|
return block
|
|
@@ -120,6 +120,12 @@ class _HierarchicalContainer(_Component, MutableMapping, metaclass=ABCMeta):
|
|
|
120
120
|
A component is only deserialized from the serialized data, if it
|
|
121
121
|
is accessed.
|
|
122
122
|
The deserialized component is then cached in the container.
|
|
123
|
+
|
|
124
|
+
Parameters
|
|
125
|
+
----------
|
|
126
|
+
elements : dict, optional
|
|
127
|
+
The initial elements of the container.
|
|
128
|
+
By default no initial elements are added.
|
|
123
129
|
"""
|
|
124
130
|
|
|
125
131
|
def __init__(self, elements=None):
|
|
@@ -27,6 +27,8 @@ def compress(data, float_tolerance=1e-6):
|
|
|
27
27
|
----------
|
|
28
28
|
data : BinaryCIFFile or BinaryCIFBlock or BinaryCIFCategory or BinaryCIFColumn or BinaryCIFData
|
|
29
29
|
The data to compress.
|
|
30
|
+
float_tolerance : float, optional
|
|
31
|
+
The relative error that is accepted when compressing floating point numbers.
|
|
30
32
|
|
|
31
33
|
Returns
|
|
32
34
|
-------
|
|
@@ -35,8 +37,6 @@ def compress(data, float_tolerance=1e-6):
|
|
|
35
37
|
If no improved compression is found for a :class:`BinaryCIFData` array,
|
|
36
38
|
the input data is kept.
|
|
37
39
|
Hence, the return value is no deep copy of the input data.
|
|
38
|
-
float_tolerance : float, optional
|
|
39
|
-
The relative error that is accepted when compressing floating point numbers.
|
|
40
40
|
|
|
41
41
|
Examples
|
|
42
42
|
--------
|