biotite 1.5.0__cp314-cp314-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 +18 -0
- biotite/application/__init__.py +69 -0
- biotite/application/application.py +276 -0
- biotite/application/autodock/__init__.py +12 -0
- biotite/application/autodock/app.py +500 -0
- biotite/application/blast/__init__.py +14 -0
- biotite/application/blast/alignment.py +92 -0
- biotite/application/blast/webapp.py +428 -0
- biotite/application/clustalo/__init__.py +12 -0
- biotite/application/clustalo/app.py +223 -0
- biotite/application/dssp/__init__.py +12 -0
- biotite/application/dssp/app.py +216 -0
- biotite/application/localapp.py +342 -0
- biotite/application/mafft/__init__.py +12 -0
- biotite/application/mafft/app.py +116 -0
- biotite/application/msaapp.py +363 -0
- biotite/application/muscle/__init__.py +13 -0
- biotite/application/muscle/app3.py +227 -0
- biotite/application/muscle/app5.py +163 -0
- biotite/application/sra/__init__.py +18 -0
- biotite/application/sra/app.py +447 -0
- biotite/application/tantan/__init__.py +12 -0
- biotite/application/tantan/app.py +199 -0
- biotite/application/util.py +77 -0
- biotite/application/viennarna/__init__.py +18 -0
- biotite/application/viennarna/rnaalifold.py +310 -0
- biotite/application/viennarna/rnafold.py +254 -0
- biotite/application/viennarna/rnaplot.py +208 -0
- biotite/application/viennarna/util.py +77 -0
- biotite/application/webapp.py +76 -0
- biotite/copyable.py +71 -0
- biotite/database/__init__.py +23 -0
- biotite/database/afdb/__init__.py +12 -0
- biotite/database/afdb/download.py +197 -0
- biotite/database/entrez/__init__.py +15 -0
- biotite/database/entrez/check.py +60 -0
- biotite/database/entrez/dbnames.py +101 -0
- biotite/database/entrez/download.py +228 -0
- biotite/database/entrez/key.py +44 -0
- biotite/database/entrez/query.py +263 -0
- biotite/database/error.py +16 -0
- biotite/database/pubchem/__init__.py +21 -0
- biotite/database/pubchem/download.py +258 -0
- biotite/database/pubchem/error.py +30 -0
- biotite/database/pubchem/query.py +819 -0
- biotite/database/pubchem/throttle.py +98 -0
- biotite/database/rcsb/__init__.py +13 -0
- biotite/database/rcsb/download.py +161 -0
- biotite/database/rcsb/query.py +963 -0
- biotite/database/uniprot/__init__.py +13 -0
- biotite/database/uniprot/check.py +40 -0
- biotite/database/uniprot/download.py +126 -0
- biotite/database/uniprot/query.py +292 -0
- biotite/file.py +244 -0
- biotite/interface/__init__.py +19 -0
- biotite/interface/openmm/__init__.py +20 -0
- biotite/interface/openmm/state.py +93 -0
- biotite/interface/openmm/system.py +227 -0
- biotite/interface/pymol/__init__.py +201 -0
- biotite/interface/pymol/cgo.py +346 -0
- biotite/interface/pymol/convert.py +185 -0
- biotite/interface/pymol/display.py +267 -0
- biotite/interface/pymol/object.py +1228 -0
- biotite/interface/pymol/shapes.py +178 -0
- biotite/interface/pymol/startup.py +169 -0
- biotite/interface/rdkit/__init__.py +19 -0
- biotite/interface/rdkit/mol.py +490 -0
- biotite/interface/version.py +94 -0
- biotite/interface/warning.py +19 -0
- biotite/sequence/__init__.py +84 -0
- biotite/sequence/align/__init__.py +199 -0
- biotite/sequence/align/alignment.py +702 -0
- biotite/sequence/align/banded.cp314-win_amd64.pyd +0 -0
- biotite/sequence/align/banded.pyx +652 -0
- biotite/sequence/align/buckets.py +71 -0
- biotite/sequence/align/cigar.py +425 -0
- biotite/sequence/align/kmeralphabet.cp314-win_amd64.pyd +0 -0
- biotite/sequence/align/kmeralphabet.pyx +595 -0
- biotite/sequence/align/kmersimilarity.cp314-win_amd64.pyd +0 -0
- biotite/sequence/align/kmersimilarity.pyx +233 -0
- biotite/sequence/align/kmertable.cp314-win_amd64.pyd +0 -0
- biotite/sequence/align/kmertable.pyx +3411 -0
- biotite/sequence/align/localgapped.cp314-win_amd64.pyd +0 -0
- biotite/sequence/align/localgapped.pyx +892 -0
- biotite/sequence/align/localungapped.cp314-win_amd64.pyd +0 -0
- biotite/sequence/align/localungapped.pyx +279 -0
- biotite/sequence/align/matrix.py +631 -0
- biotite/sequence/align/matrix_data/3Di.mat +24 -0
- biotite/sequence/align/matrix_data/BLOSUM100.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM30.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM35.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM40.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM45.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM50.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM50_13p.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM50_14.3.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM50_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM55.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM60.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM62.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM62_13p.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM62_14.3.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM62_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM65.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM70.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM75.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM80.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM85.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM90.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUMN.mat +31 -0
- biotite/sequence/align/matrix_data/CorBLOSUM49_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/CorBLOSUM57_13p.mat +25 -0
- biotite/sequence/align/matrix_data/CorBLOSUM57_14.3.mat +25 -0
- biotite/sequence/align/matrix_data/CorBLOSUM61_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/CorBLOSUM66_13p.mat +25 -0
- biotite/sequence/align/matrix_data/CorBLOSUM67_14.3.mat +25 -0
- biotite/sequence/align/matrix_data/DAYHOFF.mat +32 -0
- biotite/sequence/align/matrix_data/GONNET.mat +26 -0
- biotite/sequence/align/matrix_data/IDENTITY.mat +25 -0
- biotite/sequence/align/matrix_data/MATCH.mat +25 -0
- biotite/sequence/align/matrix_data/NUC.mat +25 -0
- biotite/sequence/align/matrix_data/PAM10.mat +34 -0
- biotite/sequence/align/matrix_data/PAM100.mat +34 -0
- biotite/sequence/align/matrix_data/PAM110.mat +34 -0
- biotite/sequence/align/matrix_data/PAM120.mat +34 -0
- biotite/sequence/align/matrix_data/PAM130.mat +34 -0
- biotite/sequence/align/matrix_data/PAM140.mat +34 -0
- biotite/sequence/align/matrix_data/PAM150.mat +34 -0
- biotite/sequence/align/matrix_data/PAM160.mat +34 -0
- biotite/sequence/align/matrix_data/PAM170.mat +34 -0
- biotite/sequence/align/matrix_data/PAM180.mat +34 -0
- biotite/sequence/align/matrix_data/PAM190.mat +34 -0
- biotite/sequence/align/matrix_data/PAM20.mat +34 -0
- biotite/sequence/align/matrix_data/PAM200.mat +34 -0
- biotite/sequence/align/matrix_data/PAM210.mat +34 -0
- biotite/sequence/align/matrix_data/PAM220.mat +34 -0
- biotite/sequence/align/matrix_data/PAM230.mat +34 -0
- biotite/sequence/align/matrix_data/PAM240.mat +34 -0
- biotite/sequence/align/matrix_data/PAM250.mat +34 -0
- biotite/sequence/align/matrix_data/PAM260.mat +34 -0
- biotite/sequence/align/matrix_data/PAM270.mat +34 -0
- biotite/sequence/align/matrix_data/PAM280.mat +34 -0
- biotite/sequence/align/matrix_data/PAM290.mat +34 -0
- biotite/sequence/align/matrix_data/PAM30.mat +34 -0
- biotite/sequence/align/matrix_data/PAM300.mat +34 -0
- biotite/sequence/align/matrix_data/PAM310.mat +34 -0
- biotite/sequence/align/matrix_data/PAM320.mat +34 -0
- biotite/sequence/align/matrix_data/PAM330.mat +34 -0
- biotite/sequence/align/matrix_data/PAM340.mat +34 -0
- biotite/sequence/align/matrix_data/PAM350.mat +34 -0
- biotite/sequence/align/matrix_data/PAM360.mat +34 -0
- biotite/sequence/align/matrix_data/PAM370.mat +34 -0
- biotite/sequence/align/matrix_data/PAM380.mat +34 -0
- biotite/sequence/align/matrix_data/PAM390.mat +34 -0
- biotite/sequence/align/matrix_data/PAM40.mat +34 -0
- biotite/sequence/align/matrix_data/PAM400.mat +34 -0
- biotite/sequence/align/matrix_data/PAM410.mat +34 -0
- biotite/sequence/align/matrix_data/PAM420.mat +34 -0
- biotite/sequence/align/matrix_data/PAM430.mat +34 -0
- biotite/sequence/align/matrix_data/PAM440.mat +34 -0
- biotite/sequence/align/matrix_data/PAM450.mat +34 -0
- biotite/sequence/align/matrix_data/PAM460.mat +34 -0
- biotite/sequence/align/matrix_data/PAM470.mat +34 -0
- biotite/sequence/align/matrix_data/PAM480.mat +34 -0
- biotite/sequence/align/matrix_data/PAM490.mat +34 -0
- biotite/sequence/align/matrix_data/PAM50.mat +34 -0
- biotite/sequence/align/matrix_data/PAM500.mat +34 -0
- biotite/sequence/align/matrix_data/PAM60.mat +34 -0
- biotite/sequence/align/matrix_data/PAM70.mat +34 -0
- biotite/sequence/align/matrix_data/PAM80.mat +34 -0
- biotite/sequence/align/matrix_data/PAM90.mat +34 -0
- biotite/sequence/align/matrix_data/PB.license +21 -0
- biotite/sequence/align/matrix_data/PB.mat +18 -0
- biotite/sequence/align/matrix_data/RBLOSUM52_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/RBLOSUM59_13p.mat +25 -0
- biotite/sequence/align/matrix_data/RBLOSUM59_14.3.mat +25 -0
- biotite/sequence/align/matrix_data/RBLOSUM64_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/RBLOSUM69_13p.mat +25 -0
- biotite/sequence/align/matrix_data/RBLOSUM69_14.3.mat +25 -0
- biotite/sequence/align/multiple.cp314-win_amd64.pyd +0 -0
- biotite/sequence/align/multiple.pyx +619 -0
- biotite/sequence/align/pairwise.cp314-win_amd64.pyd +0 -0
- biotite/sequence/align/pairwise.pyx +585 -0
- biotite/sequence/align/permutation.cp314-win_amd64.pyd +0 -0
- biotite/sequence/align/permutation.pyx +313 -0
- biotite/sequence/align/primes.txt +821 -0
- biotite/sequence/align/selector.cp314-win_amd64.pyd +0 -0
- biotite/sequence/align/selector.pyx +954 -0
- biotite/sequence/align/statistics.py +264 -0
- biotite/sequence/align/tracetable.cp314-win_amd64.pyd +0 -0
- biotite/sequence/align/tracetable.pxd +64 -0
- biotite/sequence/align/tracetable.pyx +370 -0
- biotite/sequence/alphabet.py +555 -0
- biotite/sequence/annotation.py +836 -0
- biotite/sequence/codec.cp314-win_amd64.pyd +0 -0
- biotite/sequence/codec.pyx +155 -0
- biotite/sequence/codon.py +476 -0
- biotite/sequence/codon_tables.txt +202 -0
- biotite/sequence/graphics/__init__.py +33 -0
- biotite/sequence/graphics/alignment.py +1101 -0
- biotite/sequence/graphics/color_schemes/3di_flower.json +48 -0
- biotite/sequence/graphics/color_schemes/autumn.json +51 -0
- biotite/sequence/graphics/color_schemes/blossom.json +51 -0
- biotite/sequence/graphics/color_schemes/clustalx_dna.json +11 -0
- biotite/sequence/graphics/color_schemes/clustalx_protein.json +28 -0
- biotite/sequence/graphics/color_schemes/flower.json +51 -0
- biotite/sequence/graphics/color_schemes/jalview_buried.json +31 -0
- biotite/sequence/graphics/color_schemes/jalview_hydrophobicity.json +31 -0
- biotite/sequence/graphics/color_schemes/jalview_prop_helix.json +31 -0
- biotite/sequence/graphics/color_schemes/jalview_prop_strand.json +31 -0
- biotite/sequence/graphics/color_schemes/jalview_prop_turn.json +31 -0
- biotite/sequence/graphics/color_schemes/jalview_taylor.json +28 -0
- biotite/sequence/graphics/color_schemes/jalview_zappo.json +28 -0
- biotite/sequence/graphics/color_schemes/ocean.json +51 -0
- biotite/sequence/graphics/color_schemes/pb_flower.json +40 -0
- biotite/sequence/graphics/color_schemes/rainbow_dna.json +11 -0
- biotite/sequence/graphics/color_schemes/rainbow_protein.json +30 -0
- biotite/sequence/graphics/color_schemes/spring.json +51 -0
- biotite/sequence/graphics/color_schemes/sunset.json +51 -0
- biotite/sequence/graphics/color_schemes/wither.json +51 -0
- biotite/sequence/graphics/colorschemes.py +170 -0
- biotite/sequence/graphics/dendrogram.py +231 -0
- biotite/sequence/graphics/features.py +544 -0
- biotite/sequence/graphics/logo.py +102 -0
- biotite/sequence/graphics/plasmid.py +712 -0
- biotite/sequence/io/__init__.py +12 -0
- biotite/sequence/io/fasta/__init__.py +22 -0
- biotite/sequence/io/fasta/convert.py +283 -0
- biotite/sequence/io/fasta/file.py +265 -0
- biotite/sequence/io/fastq/__init__.py +19 -0
- biotite/sequence/io/fastq/convert.py +117 -0
- biotite/sequence/io/fastq/file.py +507 -0
- biotite/sequence/io/genbank/__init__.py +17 -0
- biotite/sequence/io/genbank/annotation.py +269 -0
- biotite/sequence/io/genbank/file.py +573 -0
- biotite/sequence/io/genbank/metadata.py +336 -0
- biotite/sequence/io/genbank/sequence.py +173 -0
- biotite/sequence/io/general.py +201 -0
- biotite/sequence/io/gff/__init__.py +26 -0
- biotite/sequence/io/gff/convert.py +128 -0
- biotite/sequence/io/gff/file.py +449 -0
- biotite/sequence/phylo/__init__.py +36 -0
- biotite/sequence/phylo/nj.cp314-win_amd64.pyd +0 -0
- biotite/sequence/phylo/nj.pyx +221 -0
- biotite/sequence/phylo/tree.cp314-win_amd64.pyd +0 -0
- biotite/sequence/phylo/tree.pyx +1169 -0
- biotite/sequence/phylo/upgma.cp314-win_amd64.pyd +0 -0
- biotite/sequence/phylo/upgma.pyx +164 -0
- biotite/sequence/profile.py +561 -0
- biotite/sequence/search.py +117 -0
- biotite/sequence/seqtypes.py +720 -0
- biotite/sequence/sequence.py +373 -0
- biotite/setup_ccd.py +197 -0
- biotite/structure/__init__.py +135 -0
- biotite/structure/alphabet/__init__.py +25 -0
- biotite/structure/alphabet/encoder.py +332 -0
- biotite/structure/alphabet/encoder_weights_3di.kerasify +0 -0
- biotite/structure/alphabet/i3d.py +109 -0
- biotite/structure/alphabet/layers.py +86 -0
- biotite/structure/alphabet/pb.license +21 -0
- biotite/structure/alphabet/pb.py +170 -0
- biotite/structure/alphabet/unkerasify.py +128 -0
- biotite/structure/atoms.py +1562 -0
- biotite/structure/basepairs.py +1403 -0
- biotite/structure/bonds.cp314-win_amd64.pyd +0 -0
- biotite/structure/bonds.pyx +2036 -0
- biotite/structure/box.py +724 -0
- biotite/structure/celllist.cp314-win_amd64.pyd +0 -0
- biotite/structure/celllist.pyx +864 -0
- biotite/structure/chains.py +310 -0
- biotite/structure/charges.cp314-win_amd64.pyd +0 -0
- biotite/structure/charges.pyx +520 -0
- biotite/structure/compare.py +683 -0
- biotite/structure/density.py +109 -0
- biotite/structure/dotbracket.py +213 -0
- biotite/structure/error.py +39 -0
- biotite/structure/filter.py +591 -0
- biotite/structure/geometry.py +817 -0
- biotite/structure/graphics/__init__.py +13 -0
- biotite/structure/graphics/atoms.py +243 -0
- biotite/structure/graphics/rna.py +298 -0
- biotite/structure/hbond.py +425 -0
- biotite/structure/info/__init__.py +24 -0
- biotite/structure/info/atom_masses.json +121 -0
- biotite/structure/info/atoms.py +98 -0
- biotite/structure/info/bonds.py +149 -0
- biotite/structure/info/ccd.py +200 -0
- biotite/structure/info/components.bcif +0 -0
- biotite/structure/info/groups.py +128 -0
- biotite/structure/info/masses.py +121 -0
- biotite/structure/info/misc.py +137 -0
- biotite/structure/info/radii.py +267 -0
- biotite/structure/info/standardize.py +185 -0
- biotite/structure/integrity.py +213 -0
- biotite/structure/io/__init__.py +29 -0
- biotite/structure/io/dcd/__init__.py +13 -0
- biotite/structure/io/dcd/file.py +67 -0
- biotite/structure/io/general.py +243 -0
- biotite/structure/io/gro/__init__.py +14 -0
- biotite/structure/io/gro/file.py +343 -0
- biotite/structure/io/mol/__init__.py +20 -0
- biotite/structure/io/mol/convert.py +112 -0
- biotite/structure/io/mol/ctab.py +420 -0
- biotite/structure/io/mol/header.py +120 -0
- biotite/structure/io/mol/mol.py +149 -0
- biotite/structure/io/mol/sdf.py +940 -0
- biotite/structure/io/netcdf/__init__.py +13 -0
- biotite/structure/io/netcdf/file.py +64 -0
- biotite/structure/io/pdb/__init__.py +20 -0
- biotite/structure/io/pdb/convert.py +389 -0
- biotite/structure/io/pdb/file.py +1380 -0
- biotite/structure/io/pdb/hybrid36.cp314-win_amd64.pyd +0 -0
- biotite/structure/io/pdb/hybrid36.pyx +242 -0
- biotite/structure/io/pdbqt/__init__.py +15 -0
- biotite/structure/io/pdbqt/convert.py +113 -0
- biotite/structure/io/pdbqt/file.py +688 -0
- biotite/structure/io/pdbx/__init__.py +23 -0
- biotite/structure/io/pdbx/bcif.py +674 -0
- biotite/structure/io/pdbx/cif.py +1091 -0
- biotite/structure/io/pdbx/component.py +251 -0
- biotite/structure/io/pdbx/compress.py +362 -0
- biotite/structure/io/pdbx/convert.py +2113 -0
- biotite/structure/io/pdbx/encoding.cp314-win_amd64.pyd +0 -0
- biotite/structure/io/pdbx/encoding.pyx +1078 -0
- biotite/structure/io/trajfile.py +696 -0
- biotite/structure/io/trr/__init__.py +13 -0
- biotite/structure/io/trr/file.py +43 -0
- biotite/structure/io/util.py +38 -0
- biotite/structure/io/xtc/__init__.py +13 -0
- biotite/structure/io/xtc/file.py +43 -0
- biotite/structure/mechanics.py +72 -0
- biotite/structure/molecules.py +337 -0
- biotite/structure/pseudoknots.py +622 -0
- biotite/structure/rdf.py +245 -0
- biotite/structure/repair.py +302 -0
- biotite/structure/residues.py +716 -0
- biotite/structure/rings.py +451 -0
- biotite/structure/sasa.cp314-win_amd64.pyd +0 -0
- biotite/structure/sasa.pyx +322 -0
- biotite/structure/segments.py +328 -0
- biotite/structure/sequence.py +110 -0
- biotite/structure/spacegroups.json +1567 -0
- biotite/structure/spacegroups.license +26 -0
- biotite/structure/sse.py +306 -0
- biotite/structure/superimpose.py +511 -0
- biotite/structure/tm.py +581 -0
- biotite/structure/transform.py +736 -0
- biotite/structure/util.py +160 -0
- biotite/version.py +34 -0
- biotite/visualize.py +375 -0
- biotite-1.5.0.dist-info/METADATA +162 -0
- biotite-1.5.0.dist-info/RECORD +354 -0
- biotite-1.5.0.dist-info/WHEEL +4 -0
- biotite-1.5.0.dist-info/licenses/LICENSE.rst +30 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# This source code is part of the Biotite package and is distributed
|
|
2
|
+
# under the 3-Clause BSD License. Please see 'LICENSE.rst' for further
|
|
3
|
+
# information.
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
This subpackage provides support for the the modern PDBx file formats.
|
|
7
|
+
The :class:`CIFFile` class provides dictionary-like access to
|
|
8
|
+
every field in text-based *mmCIF* files.
|
|
9
|
+
:class:`BinaryCIFFile` provides analogous functionality for the
|
|
10
|
+
*BinaryCIF* format.
|
|
11
|
+
Additional utility functions allow reading and writing structures
|
|
12
|
+
from/to these files.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
__name__ = "biotite.structure.io.pdbx"
|
|
16
|
+
__author__ = "Patrick Kunzmann"
|
|
17
|
+
|
|
18
|
+
from .bcif import *
|
|
19
|
+
from .cif import *
|
|
20
|
+
from .component import *
|
|
21
|
+
from .compress import *
|
|
22
|
+
from .convert import *
|
|
23
|
+
from .encoding import *
|
|
@@ -0,0 +1,674 @@
|
|
|
1
|
+
# This source code is part of the Biotite package and is distributed
|
|
2
|
+
# under the 3-Clause BSD License. Please see 'LICENSE.rst' for further
|
|
3
|
+
# information.
|
|
4
|
+
|
|
5
|
+
__name__ = "biotite.structure.io.pdbx"
|
|
6
|
+
__author__ = "Patrick Kunzmann"
|
|
7
|
+
__all__ = [
|
|
8
|
+
"BinaryCIFFile",
|
|
9
|
+
"BinaryCIFBlock",
|
|
10
|
+
"BinaryCIFCategory",
|
|
11
|
+
"BinaryCIFColumn",
|
|
12
|
+
"BinaryCIFData",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
from collections.abc import Sequence
|
|
16
|
+
import msgpack
|
|
17
|
+
import numpy as np
|
|
18
|
+
from biotite.file import File, SerializationError, is_binary, is_open_compatible
|
|
19
|
+
from biotite.structure.io.pdbx.component import (
|
|
20
|
+
MaskValue,
|
|
21
|
+
_Component,
|
|
22
|
+
_HierarchicalContainer,
|
|
23
|
+
)
|
|
24
|
+
from biotite.structure.io.pdbx.encoding import (
|
|
25
|
+
create_uncompressed_encoding,
|
|
26
|
+
decode_stepwise,
|
|
27
|
+
deserialize_encoding,
|
|
28
|
+
encode_stepwise,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class BinaryCIFData(_Component):
|
|
33
|
+
r"""
|
|
34
|
+
This class represents the data in a :class:`BinaryCIFColumn`.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
array : array_like or int or float or str
|
|
39
|
+
The data array to be stored.
|
|
40
|
+
If a single item is given, it is converted into an array.
|
|
41
|
+
encoding : list of Encoding , optional
|
|
42
|
+
The encoding steps that are successively applied to the data.
|
|
43
|
+
By default, the data is stored uncompressed directly as bytes.
|
|
44
|
+
|
|
45
|
+
Attributes
|
|
46
|
+
----------
|
|
47
|
+
array : ndarray
|
|
48
|
+
The stored data array.
|
|
49
|
+
encoding : list of Encoding
|
|
50
|
+
The encoding steps.
|
|
51
|
+
|
|
52
|
+
Examples
|
|
53
|
+
--------
|
|
54
|
+
|
|
55
|
+
>>> data = BinaryCIFData([1, 2, 3])
|
|
56
|
+
>>> print(data.array)
|
|
57
|
+
[1 2 3]
|
|
58
|
+
>>> print(len(data))
|
|
59
|
+
3
|
|
60
|
+
>>> # A single item is converted into an array
|
|
61
|
+
>>> data = BinaryCIFData("apple")
|
|
62
|
+
>>> print(data.array)
|
|
63
|
+
['apple']
|
|
64
|
+
|
|
65
|
+
A well-chosen encoding can significantly reduce the serialized data
|
|
66
|
+
size:
|
|
67
|
+
|
|
68
|
+
>>> # Default uncompressed encoding
|
|
69
|
+
>>> array = np.arange(100)
|
|
70
|
+
>>> uncompressed_bytes = BinaryCIFData(array).serialize()["data"]
|
|
71
|
+
>>> print(len(uncompressed_bytes))
|
|
72
|
+
400
|
|
73
|
+
>>> # Delta encoding followed by run-length encoding
|
|
74
|
+
>>> # [0, 1, 2, ...] -> [0, 1, 1, ...] -> [0, 1, 1, 99]
|
|
75
|
+
>>> compressed_bytes = BinaryCIFData(
|
|
76
|
+
... array,
|
|
77
|
+
... encoding = [
|
|
78
|
+
... # [0, 1, 2, ...] -> [0, 1, 1, ...]
|
|
79
|
+
... DeltaEncoding(),
|
|
80
|
+
... # [0, 1, 1, ...] -> [0, 1, 1, 99]
|
|
81
|
+
... RunLengthEncoding(),
|
|
82
|
+
... # [0, 1, 1, 99] -> b"\x00\x00..."
|
|
83
|
+
... ByteArrayEncoding()
|
|
84
|
+
... ]
|
|
85
|
+
... ).serialize()["data"]
|
|
86
|
+
>>> print(len(compressed_bytes))
|
|
87
|
+
16
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
def __init__(self, array, encoding=None):
|
|
91
|
+
if not isinstance(array, (Sequence, np.ndarray)) or isinstance(array, str):
|
|
92
|
+
array = [array]
|
|
93
|
+
array = np.asarray(array)
|
|
94
|
+
if np.issubdtype(array.dtype, np.object_):
|
|
95
|
+
raise ValueError("Object arrays are not supported")
|
|
96
|
+
|
|
97
|
+
self._array = array
|
|
98
|
+
if encoding is None:
|
|
99
|
+
self._encoding = create_uncompressed_encoding(array)
|
|
100
|
+
else:
|
|
101
|
+
self._encoding = list(encoding)
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def array(self):
|
|
105
|
+
return self._array
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def encoding(self):
|
|
109
|
+
return self._encoding
|
|
110
|
+
|
|
111
|
+
@staticmethod
|
|
112
|
+
def subcomponent_class():
|
|
113
|
+
return None
|
|
114
|
+
|
|
115
|
+
@staticmethod
|
|
116
|
+
def supercomponent_class():
|
|
117
|
+
return BinaryCIFColumn
|
|
118
|
+
|
|
119
|
+
@staticmethod
|
|
120
|
+
def deserialize(content):
|
|
121
|
+
encoding = [deserialize_encoding(enc) for enc in content["encoding"]]
|
|
122
|
+
return BinaryCIFData(decode_stepwise(content["data"], encoding), encoding)
|
|
123
|
+
|
|
124
|
+
def serialize(self):
|
|
125
|
+
serialized_data = encode_stepwise(self._array, self._encoding)
|
|
126
|
+
if not isinstance(serialized_data, bytes):
|
|
127
|
+
raise SerializationError("Final encoding must return 'bytes'")
|
|
128
|
+
serialized_encoding = [enc.serialize() for enc in self._encoding]
|
|
129
|
+
return {"data": serialized_data, "encoding": serialized_encoding}
|
|
130
|
+
|
|
131
|
+
def __len__(self):
|
|
132
|
+
return len(self._array)
|
|
133
|
+
|
|
134
|
+
def __eq__(self, other):
|
|
135
|
+
if not isinstance(other, type(self)):
|
|
136
|
+
return False
|
|
137
|
+
if not np.array_equal(self._array, other._array):
|
|
138
|
+
return False
|
|
139
|
+
if self._encoding != other._encoding:
|
|
140
|
+
return False
|
|
141
|
+
return True
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class BinaryCIFColumn(_Component):
|
|
145
|
+
"""
|
|
146
|
+
This class represents a single column in a :class:`CIFCategory`.
|
|
147
|
+
|
|
148
|
+
Parameters
|
|
149
|
+
----------
|
|
150
|
+
data : BinaryCIFData or array_like or int or float or str
|
|
151
|
+
The data to be stored.
|
|
152
|
+
If no :class:`BinaryCIFData` is given, the passed argument is
|
|
153
|
+
coerced into such an object.
|
|
154
|
+
mask : BinaryCIFData or array_like, dtype=int or int
|
|
155
|
+
The mask to be stored.
|
|
156
|
+
If given, the mask indicates whether the `data` is
|
|
157
|
+
inapplicable (``.``) or missing (``?``) in some rows.
|
|
158
|
+
The data presence is indicated by values from the
|
|
159
|
+
:class:`MaskValue` enum.
|
|
160
|
+
If no :class:`BinaryCIFData` is given, the passed argument is
|
|
161
|
+
coerced into such an object.
|
|
162
|
+
By default, no mask is created.
|
|
163
|
+
|
|
164
|
+
Attributes
|
|
165
|
+
----------
|
|
166
|
+
data : BinaryCIFData
|
|
167
|
+
The stored data.
|
|
168
|
+
mask : BinaryCIFData
|
|
169
|
+
The mask that indicates whether certain data elements are
|
|
170
|
+
inapplicable or missing.
|
|
171
|
+
If no mask is present, this attribute is ``None``.
|
|
172
|
+
|
|
173
|
+
Examples
|
|
174
|
+
--------
|
|
175
|
+
|
|
176
|
+
>>> print(BinaryCIFColumn([1, 2, 3]).as_array())
|
|
177
|
+
[1 2 3]
|
|
178
|
+
>>> mask = [MaskValue.PRESENT, MaskValue.INAPPLICABLE, MaskValue.MISSING]
|
|
179
|
+
>>> # Mask values are only inserted into string arrays
|
|
180
|
+
>>> print(BinaryCIFColumn([1, 2, 3], mask).as_array(int))
|
|
181
|
+
[1 2 3]
|
|
182
|
+
>>> print(BinaryCIFColumn([1, 2, 3], mask).as_array(str))
|
|
183
|
+
['1' '.' '?']
|
|
184
|
+
>>> print(BinaryCIFColumn([1]).as_item())
|
|
185
|
+
1
|
|
186
|
+
>>> print(BinaryCIFColumn([1], mask=[MaskValue.MISSING]).as_item())
|
|
187
|
+
?
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
def __init__(self, data, mask=None):
|
|
191
|
+
if not isinstance(data, BinaryCIFData):
|
|
192
|
+
data = BinaryCIFData(data)
|
|
193
|
+
if mask is not None:
|
|
194
|
+
if not isinstance(mask, BinaryCIFData):
|
|
195
|
+
mask = BinaryCIFData(mask)
|
|
196
|
+
if len(data) != len(mask):
|
|
197
|
+
raise IndexError(
|
|
198
|
+
f"Data has length {len(data)}, but mask has length {len(mask)}"
|
|
199
|
+
)
|
|
200
|
+
self._data = data
|
|
201
|
+
self._mask = mask
|
|
202
|
+
|
|
203
|
+
@property
|
|
204
|
+
def data(self):
|
|
205
|
+
return self._data
|
|
206
|
+
|
|
207
|
+
@property
|
|
208
|
+
def mask(self):
|
|
209
|
+
return self._mask
|
|
210
|
+
|
|
211
|
+
@staticmethod
|
|
212
|
+
def subcomponent_class():
|
|
213
|
+
return BinaryCIFData
|
|
214
|
+
|
|
215
|
+
@staticmethod
|
|
216
|
+
def supercomponent_class():
|
|
217
|
+
return BinaryCIFCategory
|
|
218
|
+
|
|
219
|
+
def as_item(self):
|
|
220
|
+
"""
|
|
221
|
+
Get the only item in the data of this column.
|
|
222
|
+
|
|
223
|
+
If the data is masked as inapplicable or missing, ``'.'`` or
|
|
224
|
+
``'?'`` is returned, respectively.
|
|
225
|
+
If the data contains more than one item, an exception is raised.
|
|
226
|
+
|
|
227
|
+
Returns
|
|
228
|
+
-------
|
|
229
|
+
item : str or int or float
|
|
230
|
+
The item in the data.
|
|
231
|
+
"""
|
|
232
|
+
if self._mask is None:
|
|
233
|
+
return self._data.array.item()
|
|
234
|
+
mask = self._mask.array.item()
|
|
235
|
+
if mask is None or mask == MaskValue.PRESENT:
|
|
236
|
+
return self._data.array.item()
|
|
237
|
+
elif mask == MaskValue.INAPPLICABLE:
|
|
238
|
+
return "."
|
|
239
|
+
elif mask == MaskValue.MISSING:
|
|
240
|
+
return "?"
|
|
241
|
+
|
|
242
|
+
def as_array(self, dtype=None, masked_value=None):
|
|
243
|
+
"""
|
|
244
|
+
Get the data of this column as an :class:`ndarray`.
|
|
245
|
+
|
|
246
|
+
This is a shortcut to get ``BinaryCIFColumn.data.array``.
|
|
247
|
+
Furthermore, the mask is applied to the data.
|
|
248
|
+
|
|
249
|
+
Parameters
|
|
250
|
+
----------
|
|
251
|
+
dtype : dtype-like, optional
|
|
252
|
+
The data type the array should be converted to.
|
|
253
|
+
By default, the original type is used.
|
|
254
|
+
masked_value : str or int or float, optional
|
|
255
|
+
The value that should be used for masked elements, i.e.
|
|
256
|
+
``MaskValue.INAPPLICABLE`` or ``MaskValue.MISSING``.
|
|
257
|
+
By default, masked elements are converted to ``'.'`` or
|
|
258
|
+
``'?'`` depending on the :class:`MaskValue`.
|
|
259
|
+
|
|
260
|
+
Returns
|
|
261
|
+
-------
|
|
262
|
+
array : ndarray
|
|
263
|
+
The column data as array.
|
|
264
|
+
"""
|
|
265
|
+
if dtype is None:
|
|
266
|
+
dtype = self._data.array.dtype
|
|
267
|
+
|
|
268
|
+
if self._mask is None:
|
|
269
|
+
return self._data.array.astype(dtype, copy=False)
|
|
270
|
+
|
|
271
|
+
elif np.issubdtype(dtype, np.str_):
|
|
272
|
+
# Copy, as otherwise original data would be overwritten
|
|
273
|
+
# with mask values
|
|
274
|
+
array = self._data.array.astype(dtype, copy=True)
|
|
275
|
+
if masked_value is None:
|
|
276
|
+
array[self._mask.array == MaskValue.INAPPLICABLE] = "."
|
|
277
|
+
array[self._mask.array == MaskValue.MISSING] = "?"
|
|
278
|
+
else:
|
|
279
|
+
array[self._mask.array == MaskValue.INAPPLICABLE] = masked_value
|
|
280
|
+
array[self._mask.array == MaskValue.MISSING] = masked_value
|
|
281
|
+
return array
|
|
282
|
+
|
|
283
|
+
elif np.dtype(dtype).kind == self._data.array.dtype.kind:
|
|
284
|
+
if masked_value is None:
|
|
285
|
+
return self._data.array.astype(dtype, copy=False)
|
|
286
|
+
else:
|
|
287
|
+
array = self._data.array.astype(dtype, copy=True)
|
|
288
|
+
array[self._mask.array == MaskValue.INAPPLICABLE] = masked_value
|
|
289
|
+
array[self._mask.array == MaskValue.MISSING] = masked_value
|
|
290
|
+
return array
|
|
291
|
+
|
|
292
|
+
else:
|
|
293
|
+
# Array needs to be converted, but masked values are
|
|
294
|
+
# not necessarily convertible
|
|
295
|
+
# (e.g. '.' cannot be converted to int)
|
|
296
|
+
if masked_value is None:
|
|
297
|
+
array = np.zeros(len(self._data), dtype=dtype)
|
|
298
|
+
else:
|
|
299
|
+
array = np.full(len(self._data), masked_value, dtype=dtype)
|
|
300
|
+
|
|
301
|
+
present_mask = self._mask.array == MaskValue.PRESENT
|
|
302
|
+
array[present_mask] = self._data.array[present_mask].astype(dtype)
|
|
303
|
+
return array
|
|
304
|
+
|
|
305
|
+
@staticmethod
|
|
306
|
+
def deserialize(content):
|
|
307
|
+
return BinaryCIFColumn(
|
|
308
|
+
BinaryCIFData.deserialize(content["data"]),
|
|
309
|
+
BinaryCIFData.deserialize(content["mask"])
|
|
310
|
+
if content["mask"] is not None
|
|
311
|
+
else None,
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
def serialize(self):
|
|
315
|
+
return {
|
|
316
|
+
"data": self._data.serialize(),
|
|
317
|
+
"mask": self._mask.serialize() if self._mask is not None else None,
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
def __len__(self):
|
|
321
|
+
return len(self._data)
|
|
322
|
+
|
|
323
|
+
def __eq__(self, other):
|
|
324
|
+
if not isinstance(other, type(self)):
|
|
325
|
+
return False
|
|
326
|
+
if self._data != other._data:
|
|
327
|
+
return False
|
|
328
|
+
if self._mask != other._mask:
|
|
329
|
+
return False
|
|
330
|
+
return True
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
class BinaryCIFCategory(_HierarchicalContainer):
|
|
334
|
+
"""
|
|
335
|
+
This class represents a category in a :class:`BinaryCIFBlock`.
|
|
336
|
+
|
|
337
|
+
Columns can be accessed and modified like a dictionary.
|
|
338
|
+
The values are :class:`BinaryCIFColumn` objects.
|
|
339
|
+
|
|
340
|
+
Parameters
|
|
341
|
+
----------
|
|
342
|
+
columns : dict, optional
|
|
343
|
+
The columns of the category.
|
|
344
|
+
The keys are the column names and the values are the
|
|
345
|
+
:class:`BinaryCIFColumn` objects (or objects that can be coerced
|
|
346
|
+
into a :class:`BinaryCIFColumn`).
|
|
347
|
+
By default, an empty category is created.
|
|
348
|
+
Each column must have the same length.
|
|
349
|
+
row_count : int, optional
|
|
350
|
+
The number of rows in the category.
|
|
351
|
+
|
|
352
|
+
Attributes
|
|
353
|
+
----------
|
|
354
|
+
row_count : int
|
|
355
|
+
The number of rows in the category, i.e. the length of each
|
|
356
|
+
column.
|
|
357
|
+
By default, the row count is determined when the first column is added.
|
|
358
|
+
|
|
359
|
+
Examples
|
|
360
|
+
--------
|
|
361
|
+
|
|
362
|
+
>>> # Add column on creation
|
|
363
|
+
>>> category = BinaryCIFCategory({"fruit": ["apple", "banana"]})
|
|
364
|
+
>>> # Add column later on
|
|
365
|
+
>>> category["taste"] = ["delicious", "tasty"]
|
|
366
|
+
>>> # Add column the formal way
|
|
367
|
+
>>> category["color"] = BinaryCIFColumn(BinaryCIFData(["red", "yellow"]))
|
|
368
|
+
>>> # Access a column
|
|
369
|
+
>>> print(category["fruit"].as_array())
|
|
370
|
+
['apple' 'banana']
|
|
371
|
+
"""
|
|
372
|
+
|
|
373
|
+
def __init__(self, columns=None, row_count=None):
|
|
374
|
+
if columns is None:
|
|
375
|
+
columns = {}
|
|
376
|
+
else:
|
|
377
|
+
columns = {
|
|
378
|
+
key: BinaryCIFColumn(col)
|
|
379
|
+
if not isinstance(col, (BinaryCIFColumn, dict))
|
|
380
|
+
else col
|
|
381
|
+
for key, col in columns.items()
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
self._row_count = row_count
|
|
385
|
+
super().__init__(columns)
|
|
386
|
+
|
|
387
|
+
@property
|
|
388
|
+
def row_count(self):
|
|
389
|
+
if self._row_count is None:
|
|
390
|
+
# Row count is not determined yet
|
|
391
|
+
# -> check the length of the first column
|
|
392
|
+
self._row_count = len(next(iter(self.values())))
|
|
393
|
+
return self._row_count
|
|
394
|
+
|
|
395
|
+
@staticmethod
|
|
396
|
+
def subcomponent_class():
|
|
397
|
+
return BinaryCIFColumn
|
|
398
|
+
|
|
399
|
+
@staticmethod
|
|
400
|
+
def supercomponent_class():
|
|
401
|
+
return BinaryCIFBlock
|
|
402
|
+
|
|
403
|
+
@staticmethod
|
|
404
|
+
def deserialize(content):
|
|
405
|
+
return BinaryCIFCategory(
|
|
406
|
+
BinaryCIFCategory._deserialize_elements(content["columns"], "name"),
|
|
407
|
+
content["rowCount"],
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
def serialize(self):
|
|
411
|
+
if len(self) == 0:
|
|
412
|
+
raise SerializationError("At least one column is required")
|
|
413
|
+
|
|
414
|
+
for column_name, column in self.items():
|
|
415
|
+
if self._row_count is None:
|
|
416
|
+
self._row_count = len(column)
|
|
417
|
+
elif len(column) != self._row_count:
|
|
418
|
+
raise SerializationError(
|
|
419
|
+
f"All columns must have the same length, "
|
|
420
|
+
f"but '{column_name}' has length {len(column)}, "
|
|
421
|
+
f"while the first column has row_count {self._row_count}"
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
return {
|
|
425
|
+
"rowCount": self.row_count,
|
|
426
|
+
"columns": self._serialize_elements("name"),
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
def __setitem__(self, key, element):
|
|
430
|
+
if not isinstance(element, (BinaryCIFColumn, dict)):
|
|
431
|
+
element = BinaryCIFColumn(element)
|
|
432
|
+
super().__setitem__(key, element)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
class BinaryCIFBlock(_HierarchicalContainer):
|
|
436
|
+
"""
|
|
437
|
+
This class represents a block in a :class:`BinaryCIFFile`.
|
|
438
|
+
|
|
439
|
+
Categories can be accessed and modified like a dictionary.
|
|
440
|
+
The values are :class:`BinaryCIFCategory` objects.
|
|
441
|
+
|
|
442
|
+
Parameters
|
|
443
|
+
----------
|
|
444
|
+
categories : dict, optional
|
|
445
|
+
The categories of the block.
|
|
446
|
+
The keys are the category names and the values are the
|
|
447
|
+
:class:`BinaryCIFCategory` objects.
|
|
448
|
+
By default, an empty block is created.
|
|
449
|
+
|
|
450
|
+
Notes
|
|
451
|
+
-----
|
|
452
|
+
The category names do not include the leading underscore character.
|
|
453
|
+
This character is automatically added when the category is
|
|
454
|
+
serialized.
|
|
455
|
+
|
|
456
|
+
Examples
|
|
457
|
+
--------
|
|
458
|
+
|
|
459
|
+
>>> # Add category on creation
|
|
460
|
+
>>> block = BinaryCIFBlock({"foo": BinaryCIFCategory({"some_column": 1})})
|
|
461
|
+
>>> # Add category later on
|
|
462
|
+
>>> block["bar"] = BinaryCIFCategory({"another_column": [2, 3]})
|
|
463
|
+
>>> # Access a column
|
|
464
|
+
>>> print(block["bar"]["another_column"].as_array())
|
|
465
|
+
[2 3]
|
|
466
|
+
"""
|
|
467
|
+
|
|
468
|
+
def __init__(self, categories=None):
|
|
469
|
+
if categories is None:
|
|
470
|
+
categories = {}
|
|
471
|
+
super().__init__(
|
|
472
|
+
# Actual bcif files use leading '_' as category names
|
|
473
|
+
{"_" + name: category for name, category in categories.items()}
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
@staticmethod
|
|
477
|
+
def subcomponent_class():
|
|
478
|
+
return BinaryCIFCategory
|
|
479
|
+
|
|
480
|
+
@staticmethod
|
|
481
|
+
def supercomponent_class():
|
|
482
|
+
return BinaryCIFFile
|
|
483
|
+
|
|
484
|
+
@staticmethod
|
|
485
|
+
def deserialize(content):
|
|
486
|
+
return BinaryCIFBlock(
|
|
487
|
+
{
|
|
488
|
+
# The superclass uses leading '_' in category names,
|
|
489
|
+
# but on the level of this class, the leading '_' is omitted
|
|
490
|
+
name.lstrip("_"): category
|
|
491
|
+
for name, category in BinaryCIFBlock._deserialize_elements(
|
|
492
|
+
content["categories"], "name"
|
|
493
|
+
).items()
|
|
494
|
+
}
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
def serialize(self):
|
|
498
|
+
return {"categories": self._serialize_elements("name")}
|
|
499
|
+
|
|
500
|
+
def __getitem__(self, key):
|
|
501
|
+
try:
|
|
502
|
+
return super().__getitem__("_" + key)
|
|
503
|
+
except KeyError:
|
|
504
|
+
raise KeyError(key)
|
|
505
|
+
|
|
506
|
+
def __setitem__(self, key, element):
|
|
507
|
+
try:
|
|
508
|
+
return super().__setitem__("_" + key, element)
|
|
509
|
+
except KeyError:
|
|
510
|
+
raise KeyError(key)
|
|
511
|
+
|
|
512
|
+
def __delitem__(self, key):
|
|
513
|
+
try:
|
|
514
|
+
return super().__delitem__("_" + key)
|
|
515
|
+
except KeyError:
|
|
516
|
+
raise KeyError(key)
|
|
517
|
+
|
|
518
|
+
def __iter__(self):
|
|
519
|
+
return (key.lstrip("_") for key in super().__iter__())
|
|
520
|
+
|
|
521
|
+
def __contains__(self, key):
|
|
522
|
+
return super().__contains__("_" + key)
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
class BinaryCIFFile(File, _HierarchicalContainer):
|
|
526
|
+
"""
|
|
527
|
+
This class represents a *BinaryCIF* file.
|
|
528
|
+
|
|
529
|
+
The categories of the file can be accessed and modified like a
|
|
530
|
+
dictionary.
|
|
531
|
+
The values are :class:`BinaryCIFBlock` objects.
|
|
532
|
+
|
|
533
|
+
To parse or write a structure from/to a :class:`BinaryCIFFile`
|
|
534
|
+
object, use the high-level :func:`get_structure()` or
|
|
535
|
+
:func:`set_structure()` function respectively.
|
|
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
|
+
|
|
550
|
+
Notes
|
|
551
|
+
-----
|
|
552
|
+
The content of *BinaryCIF* files are lazily deserialized:
|
|
553
|
+
Only when a column is accessed, the time consuming data decoding
|
|
554
|
+
is performed.
|
|
555
|
+
The decoded :class:`BinaryCIFBlock`/:class:`BinaryCIFCategory`
|
|
556
|
+
objects are cached for subsequent accesses.
|
|
557
|
+
|
|
558
|
+
Examples
|
|
559
|
+
--------
|
|
560
|
+
Read a *BinaryCIF* file and access its content:
|
|
561
|
+
|
|
562
|
+
>>> import os.path
|
|
563
|
+
>>> file = BinaryCIFFile.read(os.path.join(path_to_structures, "1l2y.bcif"))
|
|
564
|
+
>>> print(file["1L2Y"]["citation_author"]["name"].as_array())
|
|
565
|
+
['Neidigh, J.W.' 'Fesinmeyer, R.M.' 'Andersen, N.H.']
|
|
566
|
+
>>> # Access the only block in the file
|
|
567
|
+
>>> print(file.block["entity"]["pdbx_description"].as_item())
|
|
568
|
+
TC5b
|
|
569
|
+
|
|
570
|
+
Create a *BinaryCIF* file and write it to disk:
|
|
571
|
+
|
|
572
|
+
>>> category = BinaryCIFCategory({"some_column": "some_value"})
|
|
573
|
+
>>> block = BinaryCIFBlock({"some_category": category})
|
|
574
|
+
>>> file = BinaryCIFFile({"some_block": block})
|
|
575
|
+
>>> file.write(os.path.join(path_to_directory, "some_file.bcif"))
|
|
576
|
+
"""
|
|
577
|
+
|
|
578
|
+
def __init__(self, blocks=None):
|
|
579
|
+
File.__init__(self)
|
|
580
|
+
_HierarchicalContainer.__init__(self, blocks)
|
|
581
|
+
|
|
582
|
+
@property
|
|
583
|
+
def block(self):
|
|
584
|
+
if len(self) == 0:
|
|
585
|
+
raise ValueError("There are no blocks in the file")
|
|
586
|
+
elif len(self) > 1:
|
|
587
|
+
raise ValueError("There are multiple blocks in the file")
|
|
588
|
+
else:
|
|
589
|
+
return self[next(iter(self))]
|
|
590
|
+
|
|
591
|
+
@staticmethod
|
|
592
|
+
def subcomponent_class():
|
|
593
|
+
return BinaryCIFBlock
|
|
594
|
+
|
|
595
|
+
@staticmethod
|
|
596
|
+
def supercomponent_class():
|
|
597
|
+
return None
|
|
598
|
+
|
|
599
|
+
@staticmethod
|
|
600
|
+
def deserialize(content):
|
|
601
|
+
return BinaryCIFFile(
|
|
602
|
+
BinaryCIFFile._deserialize_elements(content["dataBlocks"], "header")
|
|
603
|
+
)
|
|
604
|
+
|
|
605
|
+
def serialize(self):
|
|
606
|
+
return {"dataBlocks": self._serialize_elements("header")}
|
|
607
|
+
|
|
608
|
+
@classmethod
|
|
609
|
+
def read(cls, file):
|
|
610
|
+
"""
|
|
611
|
+
Read a *BinaryCIF* file.
|
|
612
|
+
|
|
613
|
+
Parameters
|
|
614
|
+
----------
|
|
615
|
+
file : file-like object or str
|
|
616
|
+
The file to be read.
|
|
617
|
+
Alternatively a file path can be supplied.
|
|
618
|
+
|
|
619
|
+
Returns
|
|
620
|
+
-------
|
|
621
|
+
file_object : BinaryCIFFile
|
|
622
|
+
The parsed file.
|
|
623
|
+
"""
|
|
624
|
+
# File name
|
|
625
|
+
if is_open_compatible(file):
|
|
626
|
+
with open(file, "rb") as f:
|
|
627
|
+
return BinaryCIFFile.deserialize(
|
|
628
|
+
msgpack.unpackb(f.read(), use_list=True, raw=False)
|
|
629
|
+
)
|
|
630
|
+
# File object
|
|
631
|
+
else:
|
|
632
|
+
if not is_binary(file):
|
|
633
|
+
raise TypeError("A file opened in 'binary' mode is required")
|
|
634
|
+
return BinaryCIFFile.deserialize(
|
|
635
|
+
msgpack.unpackb(file.read(), use_list=True, raw=False)
|
|
636
|
+
)
|
|
637
|
+
|
|
638
|
+
def write(self, file):
|
|
639
|
+
"""
|
|
640
|
+
Write contents into a *BinaryCIF* file.
|
|
641
|
+
|
|
642
|
+
Parameters
|
|
643
|
+
----------
|
|
644
|
+
file : file-like object or str
|
|
645
|
+
The file to be written to.
|
|
646
|
+
Alternatively, a file path can be supplied.
|
|
647
|
+
"""
|
|
648
|
+
serialized_content = self.serialize()
|
|
649
|
+
serialized_content["encoder"] = "biotite"
|
|
650
|
+
serialized_content["version"] = "0.3.0"
|
|
651
|
+
packed_bytes = msgpack.packb(
|
|
652
|
+
serialized_content, use_bin_type=True, default=_encode_numpy
|
|
653
|
+
)
|
|
654
|
+
if is_open_compatible(file):
|
|
655
|
+
with open(file, "wb") as f:
|
|
656
|
+
f.write(packed_bytes)
|
|
657
|
+
else:
|
|
658
|
+
if not is_binary(file):
|
|
659
|
+
raise TypeError("A file opened in 'binary' mode is required")
|
|
660
|
+
file.write(packed_bytes)
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
def _encode_numpy(item):
|
|
664
|
+
"""
|
|
665
|
+
Convert NumPy scalar types to native Python types,
|
|
666
|
+
as *Msgpack* cannot handle NumPy types (e.g. float32).
|
|
667
|
+
|
|
668
|
+
The function is given to the Msgpack packer as value for the
|
|
669
|
+
`default` parameter.
|
|
670
|
+
"""
|
|
671
|
+
if isinstance(item, np.generic):
|
|
672
|
+
return item.item()
|
|
673
|
+
else:
|
|
674
|
+
raise TypeError(f"can not serialize '{type(item).__name__}' object")
|