biotite 0.41.1__cp311-cp311-macosx_10_16_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/__init__.py +19 -0
- biotite/application/__init__.py +43 -0
- biotite/application/application.py +265 -0
- biotite/application/autodock/__init__.py +12 -0
- biotite/application/autodock/app.py +505 -0
- biotite/application/blast/__init__.py +14 -0
- biotite/application/blast/alignment.py +83 -0
- biotite/application/blast/webapp.py +421 -0
- biotite/application/clustalo/__init__.py +12 -0
- biotite/application/clustalo/app.py +238 -0
- biotite/application/dssp/__init__.py +12 -0
- biotite/application/dssp/app.py +152 -0
- biotite/application/localapp.py +306 -0
- biotite/application/mafft/__init__.py +12 -0
- biotite/application/mafft/app.py +122 -0
- biotite/application/msaapp.py +374 -0
- biotite/application/muscle/__init__.py +13 -0
- biotite/application/muscle/app3.py +254 -0
- biotite/application/muscle/app5.py +171 -0
- biotite/application/sra/__init__.py +18 -0
- biotite/application/sra/app.py +456 -0
- biotite/application/tantan/__init__.py +12 -0
- biotite/application/tantan/app.py +222 -0
- biotite/application/util.py +59 -0
- biotite/application/viennarna/__init__.py +18 -0
- biotite/application/viennarna/rnaalifold.py +304 -0
- biotite/application/viennarna/rnafold.py +269 -0
- biotite/application/viennarna/rnaplot.py +187 -0
- biotite/application/viennarna/util.py +72 -0
- biotite/application/webapp.py +77 -0
- biotite/copyable.py +71 -0
- biotite/database/__init__.py +23 -0
- biotite/database/entrez/__init__.py +15 -0
- biotite/database/entrez/check.py +61 -0
- biotite/database/entrez/dbnames.py +89 -0
- biotite/database/entrez/download.py +223 -0
- biotite/database/entrez/key.py +44 -0
- biotite/database/entrez/query.py +223 -0
- biotite/database/error.py +15 -0
- biotite/database/pubchem/__init__.py +21 -0
- biotite/database/pubchem/download.py +260 -0
- biotite/database/pubchem/error.py +20 -0
- biotite/database/pubchem/query.py +827 -0
- biotite/database/pubchem/throttle.py +99 -0
- biotite/database/rcsb/__init__.py +13 -0
- biotite/database/rcsb/download.py +167 -0
- biotite/database/rcsb/query.py +959 -0
- biotite/database/uniprot/__init__.py +13 -0
- biotite/database/uniprot/check.py +32 -0
- biotite/database/uniprot/download.py +134 -0
- biotite/database/uniprot/query.py +209 -0
- biotite/file.py +251 -0
- biotite/sequence/__init__.py +73 -0
- biotite/sequence/align/__init__.py +49 -0
- biotite/sequence/align/alignment.py +658 -0
- biotite/sequence/align/banded.cpython-311-darwin.so +0 -0
- biotite/sequence/align/banded.pyx +652 -0
- biotite/sequence/align/buckets.py +69 -0
- biotite/sequence/align/cigar.py +434 -0
- biotite/sequence/align/kmeralphabet.cpython-311-darwin.so +0 -0
- biotite/sequence/align/kmeralphabet.pyx +574 -0
- biotite/sequence/align/kmersimilarity.cpython-311-darwin.so +0 -0
- biotite/sequence/align/kmersimilarity.pyx +233 -0
- biotite/sequence/align/kmertable.cpython-311-darwin.so +0 -0
- biotite/sequence/align/kmertable.pyx +3400 -0
- biotite/sequence/align/localgapped.cpython-311-darwin.so +0 -0
- biotite/sequence/align/localgapped.pyx +892 -0
- biotite/sequence/align/localungapped.cpython-311-darwin.so +0 -0
- biotite/sequence/align/localungapped.pyx +279 -0
- biotite/sequence/align/matrix.py +405 -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/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.cpython-311-darwin.so +0 -0
- biotite/sequence/align/multiple.pyx +620 -0
- biotite/sequence/align/pairwise.cpython-311-darwin.so +0 -0
- biotite/sequence/align/pairwise.pyx +587 -0
- biotite/sequence/align/permutation.cpython-311-darwin.so +0 -0
- biotite/sequence/align/permutation.pyx +305 -0
- biotite/sequence/align/primes.txt +821 -0
- biotite/sequence/align/selector.cpython-311-darwin.so +0 -0
- biotite/sequence/align/selector.pyx +956 -0
- biotite/sequence/align/statistics.py +265 -0
- biotite/sequence/align/tracetable.cpython-311-darwin.so +0 -0
- biotite/sequence/align/tracetable.pxd +64 -0
- biotite/sequence/align/tracetable.pyx +370 -0
- biotite/sequence/alphabet.py +566 -0
- biotite/sequence/annotation.py +829 -0
- biotite/sequence/codec.cpython-311-darwin.so +0 -0
- biotite/sequence/codec.pyx +155 -0
- biotite/sequence/codon.py +466 -0
- biotite/sequence/codon_tables.txt +202 -0
- biotite/sequence/graphics/__init__.py +33 -0
- biotite/sequence/graphics/alignment.py +1034 -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 +39 -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 +139 -0
- biotite/sequence/graphics/dendrogram.py +184 -0
- biotite/sequence/graphics/features.py +510 -0
- biotite/sequence/graphics/logo.py +110 -0
- biotite/sequence/graphics/plasmid.py +661 -0
- biotite/sequence/io/__init__.py +12 -0
- biotite/sequence/io/fasta/__init__.py +22 -0
- biotite/sequence/io/fasta/convert.py +273 -0
- biotite/sequence/io/fasta/file.py +278 -0
- biotite/sequence/io/fastq/__init__.py +19 -0
- biotite/sequence/io/fastq/convert.py +120 -0
- biotite/sequence/io/fastq/file.py +551 -0
- biotite/sequence/io/genbank/__init__.py +17 -0
- biotite/sequence/io/genbank/annotation.py +277 -0
- biotite/sequence/io/genbank/file.py +575 -0
- biotite/sequence/io/genbank/metadata.py +324 -0
- biotite/sequence/io/genbank/sequence.py +172 -0
- biotite/sequence/io/general.py +192 -0
- biotite/sequence/io/gff/__init__.py +26 -0
- biotite/sequence/io/gff/convert.py +133 -0
- biotite/sequence/io/gff/file.py +434 -0
- biotite/sequence/phylo/__init__.py +36 -0
- biotite/sequence/phylo/nj.cpython-311-darwin.so +0 -0
- biotite/sequence/phylo/nj.pyx +221 -0
- biotite/sequence/phylo/tree.cpython-311-darwin.so +0 -0
- biotite/sequence/phylo/tree.pyx +1169 -0
- biotite/sequence/phylo/upgma.cpython-311-darwin.so +0 -0
- biotite/sequence/phylo/upgma.pyx +164 -0
- biotite/sequence/profile.py +456 -0
- biotite/sequence/search.py +116 -0
- biotite/sequence/seqtypes.py +556 -0
- biotite/sequence/sequence.py +374 -0
- biotite/structure/__init__.py +132 -0
- biotite/structure/atoms.py +1455 -0
- biotite/structure/basepairs.py +1415 -0
- biotite/structure/bonds.cpython-311-darwin.so +0 -0
- biotite/structure/bonds.pyx +1933 -0
- biotite/structure/box.py +592 -0
- biotite/structure/celllist.cpython-311-darwin.so +0 -0
- biotite/structure/celllist.pyx +849 -0
- biotite/structure/chains.py +298 -0
- biotite/structure/charges.cpython-311-darwin.so +0 -0
- biotite/structure/charges.pyx +520 -0
- biotite/structure/compare.py +274 -0
- biotite/structure/density.py +114 -0
- biotite/structure/dotbracket.py +216 -0
- biotite/structure/error.py +31 -0
- biotite/structure/filter.py +585 -0
- biotite/structure/geometry.py +697 -0
- biotite/structure/graphics/__init__.py +13 -0
- biotite/structure/graphics/atoms.py +226 -0
- biotite/structure/graphics/rna.py +282 -0
- biotite/structure/hbond.py +409 -0
- biotite/structure/info/__init__.py +25 -0
- biotite/structure/info/atom_masses.json +121 -0
- biotite/structure/info/atoms.py +82 -0
- biotite/structure/info/bonds.py +145 -0
- biotite/structure/info/ccd/README.rst +8 -0
- biotite/structure/info/ccd/amino_acids.txt +1663 -0
- biotite/structure/info/ccd/carbohydrates.txt +1135 -0
- biotite/structure/info/ccd/components.bcif +0 -0
- biotite/structure/info/ccd/nucleotides.txt +798 -0
- biotite/structure/info/ccd.py +95 -0
- biotite/structure/info/groups.py +90 -0
- biotite/structure/info/masses.py +123 -0
- biotite/structure/info/misc.py +144 -0
- biotite/structure/info/radii.py +197 -0
- biotite/structure/info/standardize.py +196 -0
- biotite/structure/integrity.py +268 -0
- biotite/structure/io/__init__.py +30 -0
- biotite/structure/io/ctab.py +72 -0
- biotite/structure/io/dcd/__init__.py +13 -0
- biotite/structure/io/dcd/file.py +65 -0
- biotite/structure/io/general.py +257 -0
- biotite/structure/io/gro/__init__.py +14 -0
- biotite/structure/io/gro/file.py +343 -0
- biotite/structure/io/mmtf/__init__.py +21 -0
- biotite/structure/io/mmtf/assembly.py +214 -0
- biotite/structure/io/mmtf/convertarray.cpython-311-darwin.so +0 -0
- biotite/structure/io/mmtf/convertarray.pyx +341 -0
- biotite/structure/io/mmtf/convertfile.cpython-311-darwin.so +0 -0
- biotite/structure/io/mmtf/convertfile.pyx +501 -0
- biotite/structure/io/mmtf/decode.cpython-311-darwin.so +0 -0
- biotite/structure/io/mmtf/decode.pyx +152 -0
- biotite/structure/io/mmtf/encode.cpython-311-darwin.so +0 -0
- biotite/structure/io/mmtf/encode.pyx +183 -0
- biotite/structure/io/mmtf/file.py +233 -0
- biotite/structure/io/mol/__init__.py +20 -0
- biotite/structure/io/mol/convert.py +115 -0
- biotite/structure/io/mol/ctab.py +414 -0
- biotite/structure/io/mol/header.py +116 -0
- biotite/structure/io/mol/mol.py +193 -0
- biotite/structure/io/mol/sdf.py +916 -0
- biotite/structure/io/netcdf/__init__.py +13 -0
- biotite/structure/io/netcdf/file.py +63 -0
- biotite/structure/io/npz/__init__.py +20 -0
- biotite/structure/io/npz/file.py +152 -0
- biotite/structure/io/pdb/__init__.py +20 -0
- biotite/structure/io/pdb/convert.py +293 -0
- biotite/structure/io/pdb/file.py +1240 -0
- biotite/structure/io/pdb/hybrid36.cpython-311-darwin.so +0 -0
- biotite/structure/io/pdb/hybrid36.pyx +242 -0
- biotite/structure/io/pdbqt/__init__.py +15 -0
- biotite/structure/io/pdbqt/convert.py +107 -0
- biotite/structure/io/pdbqt/file.py +640 -0
- biotite/structure/io/pdbx/__init__.py +23 -0
- biotite/structure/io/pdbx/bcif.py +648 -0
- biotite/structure/io/pdbx/cif.py +1032 -0
- biotite/structure/io/pdbx/component.py +246 -0
- biotite/structure/io/pdbx/convert.py +1597 -0
- biotite/structure/io/pdbx/encoding.cpython-311-darwin.so +0 -0
- biotite/structure/io/pdbx/encoding.pyx +950 -0
- biotite/structure/io/pdbx/legacy.py +267 -0
- biotite/structure/io/tng/__init__.py +13 -0
- biotite/structure/io/tng/file.py +46 -0
- biotite/structure/io/trajfile.py +710 -0
- biotite/structure/io/trr/__init__.py +13 -0
- biotite/structure/io/trr/file.py +46 -0
- biotite/structure/io/xtc/__init__.py +13 -0
- biotite/structure/io/xtc/file.py +46 -0
- biotite/structure/mechanics.py +75 -0
- biotite/structure/molecules.py +353 -0
- biotite/structure/pseudoknots.py +642 -0
- biotite/structure/rdf.py +243 -0
- biotite/structure/repair.py +253 -0
- biotite/structure/residues.py +562 -0
- biotite/structure/resutil.py +178 -0
- biotite/structure/sasa.cpython-311-darwin.so +0 -0
- biotite/structure/sasa.pyx +322 -0
- biotite/structure/sequence.py +112 -0
- biotite/structure/sse.py +327 -0
- biotite/structure/superimpose.py +727 -0
- biotite/structure/transform.py +504 -0
- biotite/structure/util.py +98 -0
- biotite/temp.py +86 -0
- biotite/version.py +16 -0
- biotite/visualize.py +251 -0
- biotite-0.41.1.dist-info/METADATA +187 -0
- biotite-0.41.1.dist-info/RECORD +340 -0
- biotite-0.41.1.dist-info/WHEEL +4 -0
- biotite-0.41.1.dist-info/licenses/LICENSE.rst +30 -0
|
@@ -0,0 +1,183 @@
|
|
|
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.mmtf"
|
|
6
|
+
__author__ = "Patrick Kunzmann"
|
|
7
|
+
__all__ = ["encode_array"]
|
|
8
|
+
|
|
9
|
+
cimport cython
|
|
10
|
+
cimport numpy as np
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
ctypedef np.int8_t int8
|
|
15
|
+
ctypedef np.int16_t int16
|
|
16
|
+
ctypedef np.int32_t int32
|
|
17
|
+
ctypedef np.uint8_t uint8
|
|
18
|
+
ctypedef np.uint16_t uint16
|
|
19
|
+
ctypedef np.uint32_t uint32
|
|
20
|
+
ctypedef np.uint64_t uint64
|
|
21
|
+
ctypedef np.float32_t float32
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def encode_array(np.ndarray array, int codec, int param):
|
|
25
|
+
# Pass-through: 32-bit floating-point number array
|
|
26
|
+
if codec == 1:
|
|
27
|
+
array = array.astype(np.float32, copy=False)
|
|
28
|
+
return array.astype(">f4").tobytes()
|
|
29
|
+
# Pass-through: 8-bit signed integer array
|
|
30
|
+
elif codec == 2:
|
|
31
|
+
array = array.astype(np.int8, copy=False)
|
|
32
|
+
return array.astype(">i1").tobytes()
|
|
33
|
+
# Pass-through: 16-bit signed integer array
|
|
34
|
+
elif codec == 3:
|
|
35
|
+
array = array.astype(np.int16, copy=False)
|
|
36
|
+
return array.astype(">i2").tobytes()
|
|
37
|
+
# Pass-through: 32-bit signed integer array
|
|
38
|
+
elif codec == 4:
|
|
39
|
+
array = array.astype(np.int32, copy=False)
|
|
40
|
+
return array.astype(">i4").tobytes()
|
|
41
|
+
# UTF8/ASCII fixed-length string array
|
|
42
|
+
elif codec == 5:
|
|
43
|
+
dtype = np.dtype("U" + str(param))
|
|
44
|
+
array = array.astype(dtype, copy=False)
|
|
45
|
+
return array.astype(np.dtype("S" + str(param))).tobytes()
|
|
46
|
+
# Run-length encoded character array
|
|
47
|
+
elif codec == 6:
|
|
48
|
+
array = array.astype("U1", copy=False)
|
|
49
|
+
array = _encode_run_length(np.frombuffer(array, dtype=np.int32))
|
|
50
|
+
return array.astype(">i4").tobytes()
|
|
51
|
+
# Run-length encoded 32-bit signed integer array
|
|
52
|
+
elif codec == 7:
|
|
53
|
+
array = array.astype(np.int32, copy=False)
|
|
54
|
+
return _encode_run_length(array).astype(">i4").tobytes()
|
|
55
|
+
# Delta & run-length encoded 32-bit signed integer array
|
|
56
|
+
elif codec == 8:
|
|
57
|
+
array = array.astype(np.int32, copy=False)
|
|
58
|
+
return _encode_run_length(_encode_delta(array)).astype(">i4").tobytes()
|
|
59
|
+
# Integer & run-length encoded 32-bit floating-point number array
|
|
60
|
+
elif codec == 9:
|
|
61
|
+
array = array.astype(np.float32, copy=False)
|
|
62
|
+
return _encode_run_length(
|
|
63
|
+
_encode_integer(param, array).astype(np.int32)
|
|
64
|
+
).astype(">i4").tobytes()
|
|
65
|
+
# Integer & delta encoded
|
|
66
|
+
# & two-byte-packed 32-bit floating-point number array
|
|
67
|
+
elif codec == 10:
|
|
68
|
+
array = array.astype(np.float32, copy=False)
|
|
69
|
+
return _encode_packed(
|
|
70
|
+
True, _encode_delta(
|
|
71
|
+
_encode_integer(param, array).astype(np.int32)
|
|
72
|
+
)
|
|
73
|
+
).astype(">i2").tobytes()
|
|
74
|
+
# Integer encoded 32-bit floating-point number array
|
|
75
|
+
elif codec == 11:
|
|
76
|
+
array = array.astype(np.float32, copy=False)
|
|
77
|
+
return _encode_integer(param, array).astype(">i2").tobytes()
|
|
78
|
+
# Integer & two-byte-packed 32-bit floating-point number array
|
|
79
|
+
elif codec == 12:
|
|
80
|
+
array = array.astype(np.float32, copy=False)
|
|
81
|
+
return _encode_packed(
|
|
82
|
+
True, _encode_integer(param, array).astype(np.int32)
|
|
83
|
+
).astype(">i2").tobytes()
|
|
84
|
+
# Integer & one-byte-packed 32-bit floating-point number array
|
|
85
|
+
elif codec == 13:
|
|
86
|
+
array = array.astype(np.float32, copy=False)
|
|
87
|
+
return _encode_packed(
|
|
88
|
+
False, _encode_integer(param, array).astype(np.int32)
|
|
89
|
+
).astype(">i1").tobytes()
|
|
90
|
+
# Two-byte-packed 32-bit signed integer array
|
|
91
|
+
elif codec == 14:
|
|
92
|
+
array = array.astype(np.int32, copy=False)
|
|
93
|
+
return _encode_packed(True, array).astype(">i2").tobytes()
|
|
94
|
+
# One-byte-packed 32-bit signed integer array
|
|
95
|
+
elif codec == 15:
|
|
96
|
+
array = array.astype(np.int32, copy=False)
|
|
97
|
+
return _encode_packed(False, array).astype(">i1").tobytes()
|
|
98
|
+
else:
|
|
99
|
+
raise ValueError(f"Unknown codec with ID {codec}")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _encode_delta(int32[:] array):
|
|
103
|
+
cdef int32[:] output = np.zeros(array.shape[0], np.int32)
|
|
104
|
+
output[0] = array[0]
|
|
105
|
+
cdef int i = 0
|
|
106
|
+
for i in range(1, array.shape[0]):
|
|
107
|
+
output[i] = array[i] - array[i-1]
|
|
108
|
+
return np.asarray(output)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _encode_run_length(int32[:] array):
|
|
112
|
+
# Pessimistic allocation of output array
|
|
113
|
+
# -> Run length is 1 for every element
|
|
114
|
+
cdef int32[:] output = np.zeros(array.shape[0] * 2, dtype=np.int32)
|
|
115
|
+
cdef int i=0, j=0
|
|
116
|
+
cdef int val = array[0]
|
|
117
|
+
cdef int run_length = 0
|
|
118
|
+
cdef int curr_val
|
|
119
|
+
for i in range(array.shape[0]):
|
|
120
|
+
curr_val = array[i]
|
|
121
|
+
if curr_val == val:
|
|
122
|
+
run_length += 1
|
|
123
|
+
else:
|
|
124
|
+
# New element -> Write element with run-length
|
|
125
|
+
output[j] = val
|
|
126
|
+
output[j+1] = run_length
|
|
127
|
+
j += 2
|
|
128
|
+
val = curr_val
|
|
129
|
+
run_length = 1
|
|
130
|
+
# Write last element
|
|
131
|
+
output[j] = val
|
|
132
|
+
output[j+1] = run_length
|
|
133
|
+
j += 2
|
|
134
|
+
# Trim to correct size
|
|
135
|
+
return np.asarray(output)[:j]
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@cython.cdivision(True)
|
|
139
|
+
def _encode_packed(bint two_byte, int32[:] array):
|
|
140
|
+
cdef int min_val, max_val
|
|
141
|
+
cdef int i=0, j=0
|
|
142
|
+
if two_byte:
|
|
143
|
+
min_val = np.iinfo(np.int16).min
|
|
144
|
+
max_val = np.iinfo(np.int16).max
|
|
145
|
+
else:
|
|
146
|
+
min_val = np.iinfo(np.int8).min
|
|
147
|
+
max_val = np.iinfo(np.int8).max
|
|
148
|
+
# Get length of output array
|
|
149
|
+
# by summing up required length of each element
|
|
150
|
+
cdef int number
|
|
151
|
+
cdef int length = 0
|
|
152
|
+
for i in range(array.shape[0]):
|
|
153
|
+
number = array[i]
|
|
154
|
+
if number < 0:
|
|
155
|
+
length += number // min_val +1
|
|
156
|
+
elif number > 0:
|
|
157
|
+
length += number // max_val +1
|
|
158
|
+
else:
|
|
159
|
+
# e = 0
|
|
160
|
+
length += 1
|
|
161
|
+
# Fill output
|
|
162
|
+
cdef int16[:] output = np.zeros(length, dtype=np.int16)
|
|
163
|
+
cdef int remainder
|
|
164
|
+
j = 0
|
|
165
|
+
for i in range(array.shape[0]):
|
|
166
|
+
remainder = array[i]
|
|
167
|
+
if remainder < 0:
|
|
168
|
+
while remainder <= min_val:
|
|
169
|
+
remainder -= min_val
|
|
170
|
+
output[j] = min_val
|
|
171
|
+
j += 1
|
|
172
|
+
elif remainder > 0:
|
|
173
|
+
while remainder >= max_val:
|
|
174
|
+
remainder -= max_val
|
|
175
|
+
output[j] = max_val
|
|
176
|
+
j += 1
|
|
177
|
+
output[j] = remainder
|
|
178
|
+
j += 1
|
|
179
|
+
return np.asarray(output)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _encode_integer(int divisor, np.ndarray array):
|
|
183
|
+
return np.multiply(array, divisor)
|
|
@@ -0,0 +1,233 @@
|
|
|
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.mmtf"
|
|
6
|
+
__author__ = "Patrick Kunzmann"
|
|
7
|
+
__all__ = ["MMTFFile"]
|
|
8
|
+
|
|
9
|
+
import io
|
|
10
|
+
from collections.abc import MutableMapping
|
|
11
|
+
import struct
|
|
12
|
+
import copy
|
|
13
|
+
import numpy as np
|
|
14
|
+
import msgpack
|
|
15
|
+
import warnings
|
|
16
|
+
from ....file import File, is_binary, is_open_compatible
|
|
17
|
+
from ...error import BadStructureError
|
|
18
|
+
from .decode import decode_array
|
|
19
|
+
from .encode import encode_array
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class MMTFFile(File, MutableMapping):
|
|
23
|
+
"""
|
|
24
|
+
This class represents a MMTF file.
|
|
25
|
+
|
|
26
|
+
When reading a file, the *MessagePack* unpacker is used to create
|
|
27
|
+
a dictionary of the file content.
|
|
28
|
+
This dictionary is accessed by indexing the :class:`MMTFFile`
|
|
29
|
+
instance directly with the dictionary keys.
|
|
30
|
+
If the dictionary value is an encoded array, the value automatically
|
|
31
|
+
decoded.
|
|
32
|
+
Decoded arrays are always returned as :class:`ndarray` instances.
|
|
33
|
+
|
|
34
|
+
DEPRECATED: Use :class:`biotite.structure.io.pdbx.BinaryCIFFile`
|
|
35
|
+
instead.
|
|
36
|
+
|
|
37
|
+
Examples
|
|
38
|
+
--------
|
|
39
|
+
|
|
40
|
+
>>> import os.path
|
|
41
|
+
>>> mmtf_file = MMTFFile.read(os.path.join(path_to_structures, "1l2y.mmtf"))
|
|
42
|
+
>>> print(mmtf_file["title"])
|
|
43
|
+
NMR Structure of Trp-Cage Miniprotein Construct TC5b
|
|
44
|
+
>>> print(mmtf_file["chainNameList"])
|
|
45
|
+
['A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A'
|
|
46
|
+
'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A'
|
|
47
|
+
'A' 'A']
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self):
|
|
51
|
+
warnings.warn(
|
|
52
|
+
"'MMTFFile' is deprecated, use 'BinaryCIFFile' instead",
|
|
53
|
+
DeprecationWarning
|
|
54
|
+
)
|
|
55
|
+
super().__init__()
|
|
56
|
+
self._content = {}
|
|
57
|
+
self._content["mmtfVersion"] = "1.0.0"
|
|
58
|
+
self._content["mmtfProducer"] = "UNKNOWN"
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def read(self, file):
|
|
62
|
+
"""
|
|
63
|
+
Read a MMTF file.
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
file : file-like object or str
|
|
68
|
+
The file to be read.
|
|
69
|
+
Alternatively a file path can be supplied.
|
|
70
|
+
|
|
71
|
+
Returns
|
|
72
|
+
-------
|
|
73
|
+
file_object : MMTFFile
|
|
74
|
+
The parsed file.
|
|
75
|
+
"""
|
|
76
|
+
mmtf_file = MMTFFile()
|
|
77
|
+
# File name
|
|
78
|
+
if is_open_compatible(file):
|
|
79
|
+
with open(file, "rb") as f:
|
|
80
|
+
mmtf_file._content = msgpack.unpackb(
|
|
81
|
+
f.read(), use_list=True, raw=False
|
|
82
|
+
)
|
|
83
|
+
# File object
|
|
84
|
+
else:
|
|
85
|
+
if not is_binary(file):
|
|
86
|
+
raise TypeError("A file opened in 'binary' mode is required")
|
|
87
|
+
mmtf_file._content = msgpack.unpackb(
|
|
88
|
+
file.read(), use_list=True, raw=False
|
|
89
|
+
)
|
|
90
|
+
return mmtf_file
|
|
91
|
+
|
|
92
|
+
def write(self, file):
|
|
93
|
+
"""
|
|
94
|
+
Write contents into a MMTF file.
|
|
95
|
+
|
|
96
|
+
Parameters
|
|
97
|
+
----------
|
|
98
|
+
file : file-like object or str
|
|
99
|
+
The file to be written to.
|
|
100
|
+
Alternatively, a file path can be supplied.
|
|
101
|
+
"""
|
|
102
|
+
packed_bytes = msgpack.packb(
|
|
103
|
+
self._content, use_bin_type=True, default=_encode_numpy
|
|
104
|
+
)
|
|
105
|
+
if is_open_compatible(file):
|
|
106
|
+
with open(file, "wb") as f:
|
|
107
|
+
f.write(packed_bytes)
|
|
108
|
+
else:
|
|
109
|
+
if not is_binary(file):
|
|
110
|
+
raise TypeError("A file opened in 'binary' mode is required")
|
|
111
|
+
file.write(packed_bytes)
|
|
112
|
+
|
|
113
|
+
def __copy_fill__(self, clone):
|
|
114
|
+
super().__copy_fill__(clone)
|
|
115
|
+
clone._content = copy.deepcopy(self._content)
|
|
116
|
+
|
|
117
|
+
def get_codec(self, key):
|
|
118
|
+
"""
|
|
119
|
+
Obtain the codec ID of an MMTF encoded value.
|
|
120
|
+
|
|
121
|
+
Parameters
|
|
122
|
+
----------
|
|
123
|
+
key : str
|
|
124
|
+
The key for the potentially encoded value.
|
|
125
|
+
|
|
126
|
+
Returns
|
|
127
|
+
-------
|
|
128
|
+
codec : int or None
|
|
129
|
+
The codec ID. `None` if the value is not encoded.
|
|
130
|
+
"""
|
|
131
|
+
data = self._content[key]
|
|
132
|
+
if isinstance(data, bytes) and data[0] == 0:
|
|
133
|
+
codec = struct.unpack(">i", data[0:4])[0]
|
|
134
|
+
return codec
|
|
135
|
+
else:
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
def get_length(self, key):
|
|
139
|
+
"""
|
|
140
|
+
Obtain the length of an MMTF encoded value.
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
key : str
|
|
145
|
+
The key for the potentially encoded value.
|
|
146
|
+
|
|
147
|
+
Returns
|
|
148
|
+
-------
|
|
149
|
+
codec : int or None
|
|
150
|
+
The length of the `bytes` array.
|
|
151
|
+
`None` if the value is not encoded.
|
|
152
|
+
"""
|
|
153
|
+
data = self._content[key]
|
|
154
|
+
if isinstance(data, bytes) and data[0] == 0:
|
|
155
|
+
length = struct.unpack(">i", data[4:8])[0]
|
|
156
|
+
return length
|
|
157
|
+
else:
|
|
158
|
+
return None
|
|
159
|
+
|
|
160
|
+
def get_param(self, key):
|
|
161
|
+
"""
|
|
162
|
+
Obtain the parameter of an MMTF encoded value.
|
|
163
|
+
|
|
164
|
+
Parameters
|
|
165
|
+
----------
|
|
166
|
+
key : str
|
|
167
|
+
The key for the potentially encoded value.
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
codec : int or None
|
|
172
|
+
The parameter of the encoded value.
|
|
173
|
+
`None` if the value is not encoded.
|
|
174
|
+
"""
|
|
175
|
+
data = self._content[key]
|
|
176
|
+
if isinstance(data, bytes) and data[0] == 0:
|
|
177
|
+
param = struct.unpack(">i", data[8:12])[0]
|
|
178
|
+
return param
|
|
179
|
+
else:
|
|
180
|
+
return None
|
|
181
|
+
|
|
182
|
+
def set_array(self, key, array, codec, param=0):
|
|
183
|
+
length = len(array)
|
|
184
|
+
raw_bytes = encode_array(array, codec, param)
|
|
185
|
+
data = struct.pack(">i", codec) \
|
|
186
|
+
+ struct.pack(">i", length) \
|
|
187
|
+
+ struct.pack(">i", param) \
|
|
188
|
+
+ raw_bytes
|
|
189
|
+
self._content[key] = data
|
|
190
|
+
|
|
191
|
+
def __getitem__(self, key):
|
|
192
|
+
data = self._content[key]
|
|
193
|
+
if isinstance(data, bytes) and data[0] == 0:
|
|
194
|
+
# MMTF specific format -> requires decoding
|
|
195
|
+
codec = struct.unpack(">i", data[0:4 ])[0]
|
|
196
|
+
length = struct.unpack(">i", data[4:8 ])[0]
|
|
197
|
+
param = struct.unpack(">i", data[8:12])[0]
|
|
198
|
+
raw_bytes = data[12:]
|
|
199
|
+
return decode_array(codec, raw_bytes, param)
|
|
200
|
+
else:
|
|
201
|
+
return data
|
|
202
|
+
|
|
203
|
+
def __setitem__(self, key, item):
|
|
204
|
+
if isinstance(item, np.ndarray):
|
|
205
|
+
raise TypeError("Arrays that need to be encoded must be addeed "
|
|
206
|
+
"via 'set_array()'")
|
|
207
|
+
self._content[key] = item
|
|
208
|
+
|
|
209
|
+
def __delitem__(self, key):
|
|
210
|
+
del self._content[key]
|
|
211
|
+
|
|
212
|
+
def __iter__(self):
|
|
213
|
+
return self._content.__iter__()
|
|
214
|
+
|
|
215
|
+
def __len__(self):
|
|
216
|
+
return len(self._content)
|
|
217
|
+
|
|
218
|
+
def __contains__(self, item):
|
|
219
|
+
return item in self._content
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _encode_numpy(item):
|
|
223
|
+
"""
|
|
224
|
+
Convert NumPy scalar types to native Python types,
|
|
225
|
+
as *Msgpack* cannot handle NumPy types (e.g. float32).
|
|
226
|
+
|
|
227
|
+
The function is given to the Msgpack packer as value for the
|
|
228
|
+
`default` parameter.
|
|
229
|
+
"""
|
|
230
|
+
if isinstance(item, np.generic):
|
|
231
|
+
return item.item()
|
|
232
|
+
else:
|
|
233
|
+
raise TypeError(f"can not serialize '{type(item).__name__}' object")
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
The MOL format is used to depict atom positions and bonds for small
|
|
7
|
+
molecules.
|
|
8
|
+
This subpackage is used for reading and writing an :class:`AtomArray`
|
|
9
|
+
in this format.
|
|
10
|
+
Additionally, reading data from the SDF format, which is a wrapper
|
|
11
|
+
around MOL, is also supported.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
__name__ = "biotite.structure.io.mol"
|
|
15
|
+
__author__ = "Patrick Kunzmann"
|
|
16
|
+
|
|
17
|
+
from .convert import *
|
|
18
|
+
from .header import *
|
|
19
|
+
from .mol import *
|
|
20
|
+
from .sdf import *
|
|
@@ -0,0 +1,115 @@
|
|
|
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.mol"
|
|
6
|
+
__author__ = "Patrick Kunzmann"
|
|
7
|
+
__all__ = ["get_structure", "set_structure"]
|
|
8
|
+
|
|
9
|
+
from .mol import MOLFile
|
|
10
|
+
from .sdf import SDFile, SDRecord
|
|
11
|
+
from ...bonds import BondType
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_structure(mol_file, record_name=None):
|
|
15
|
+
"""
|
|
16
|
+
Get an :class:`AtomArray` from the MOL file.
|
|
17
|
+
|
|
18
|
+
Ths function is a thin wrapper around
|
|
19
|
+
:meth:`MOLFile.get_structure()`.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
mol_file : MOLFile or SDFile or SDRecord
|
|
24
|
+
The file.
|
|
25
|
+
record_name : str, optional
|
|
26
|
+
Has only an effect when `mol_file` is a :class:`SDFile`.
|
|
27
|
+
The name of the record in the SD file.
|
|
28
|
+
By default, the first record is used.
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
array : AtomArray
|
|
33
|
+
This :class:`AtomArray` contains the optional ``charge``
|
|
34
|
+
annotation and has an associated :class:`BondList`.
|
|
35
|
+
All other annotation categories, except ``element`` are
|
|
36
|
+
empty.
|
|
37
|
+
"""
|
|
38
|
+
record = _get_record(mol_file, record_name)
|
|
39
|
+
return record.get_structure()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def set_structure(mol_file, atoms, default_bond_type=BondType.ANY,
|
|
43
|
+
version=None, record_name=None):
|
|
44
|
+
"""
|
|
45
|
+
Set the :class:`AtomArray` for the MOL file.
|
|
46
|
+
|
|
47
|
+
Ths function is a thin wrapper around
|
|
48
|
+
:meth:`MOLFile.set_structure()`.
|
|
49
|
+
|
|
50
|
+
Parameters
|
|
51
|
+
----------
|
|
52
|
+
mol_file : MOLFile
|
|
53
|
+
The MOL file.
|
|
54
|
+
array : AtomArray
|
|
55
|
+
The array to be saved into this file.
|
|
56
|
+
Must have an associated :class:`BondList`.
|
|
57
|
+
Bond type fallback for the *Bond block*, if a
|
|
58
|
+
:class:`BondType` has no CTAB counterpart.
|
|
59
|
+
By default, each such bond is treated as
|
|
60
|
+
:attr:`BondType.ANY`.
|
|
61
|
+
default_bond_type : BondType, optional
|
|
62
|
+
Bond type fallback for the *Bond block*, if a :class:`BondType`
|
|
63
|
+
has no CTAB counterpart.
|
|
64
|
+
By default, each such bond is treated as :attr:`BondType.ANY`.
|
|
65
|
+
version : {"V2000", "V3000"}, optional
|
|
66
|
+
The version of the CTAB format.
|
|
67
|
+
``"V2000"`` uses the *Atom* and *Bond* block, while ``"V3000"``
|
|
68
|
+
uses the *Properties* block.
|
|
69
|
+
By default, ``"V2000"`` is used, unless the number of atoms or
|
|
70
|
+
bonds exceeds 999, in which case ``"V3000"`` is used.
|
|
71
|
+
record_name : str, optional
|
|
72
|
+
Has only an effect when `mol_file` is a :class:`SDFile`.
|
|
73
|
+
The name of the record.
|
|
74
|
+
Default is the first record of the file.
|
|
75
|
+
If the file is empty, a new record will be created.
|
|
76
|
+
"""
|
|
77
|
+
record = _get_or_create_record(mol_file, record_name)
|
|
78
|
+
record.set_structure(atoms, default_bond_type, version)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _get_record(file, record_name):
|
|
82
|
+
if isinstance(file, (MOLFile, SDRecord)):
|
|
83
|
+
return file
|
|
84
|
+
elif isinstance(file, SDFile):
|
|
85
|
+
# Determine record
|
|
86
|
+
if record_name is None:
|
|
87
|
+
return file.record
|
|
88
|
+
else:
|
|
89
|
+
return file[record_name]
|
|
90
|
+
else:
|
|
91
|
+
raise TypeError(
|
|
92
|
+
f"Unsupported file type '{type(file).__name__}'"
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _get_or_create_record(file, record_name):
|
|
97
|
+
if isinstance(file, (MOLFile, SDRecord)):
|
|
98
|
+
return file
|
|
99
|
+
elif isinstance(file, SDFile):
|
|
100
|
+
if record_name is None:
|
|
101
|
+
if len(file) > 0:
|
|
102
|
+
# Choose first record by default
|
|
103
|
+
record_name = next(iter(file.keys()))
|
|
104
|
+
else:
|
|
105
|
+
# File is empty -> invent a new record name
|
|
106
|
+
record_name = "Molecule"
|
|
107
|
+
|
|
108
|
+
if record_name not in file:
|
|
109
|
+
record = SDRecord()
|
|
110
|
+
file[record_name] = record
|
|
111
|
+
return file[record_name]
|
|
112
|
+
else:
|
|
113
|
+
raise TypeError(
|
|
114
|
+
f"Unsupported file type '{type(file).__name__}'"
|
|
115
|
+
)
|