biotite 1.5.0__cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.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.cpython-314-x86_64-linux-gnu.so +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.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/kmeralphabet.pyx +595 -0
- biotite/sequence/align/kmersimilarity.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/kmersimilarity.pyx +233 -0
- biotite/sequence/align/kmertable.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/kmertable.pyx +3411 -0
- biotite/sequence/align/localgapped.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/localgapped.pyx +892 -0
- biotite/sequence/align/localungapped.cpython-314-x86_64-linux-gnu.so +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.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/multiple.pyx +619 -0
- biotite/sequence/align/pairwise.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/pairwise.pyx +585 -0
- biotite/sequence/align/permutation.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/permutation.pyx +313 -0
- biotite/sequence/align/primes.txt +821 -0
- biotite/sequence/align/selector.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/selector.pyx +954 -0
- biotite/sequence/align/statistics.py +264 -0
- biotite/sequence/align/tracetable.cpython-314-x86_64-linux-gnu.so +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.cpython-314-x86_64-linux-gnu.so +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.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/sequence/phylo/nj.pyx +221 -0
- biotite/sequence/phylo/tree.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/sequence/phylo/tree.pyx +1169 -0
- biotite/sequence/phylo/upgma.cpython-314-x86_64-linux-gnu.so +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.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/structure/bonds.pyx +2036 -0
- biotite/structure/box.py +724 -0
- biotite/structure/celllist.cpython-314-x86_64-linux-gnu.so +0 -0
- biotite/structure/celllist.pyx +864 -0
- biotite/structure/chains.py +310 -0
- biotite/structure/charges.cpython-314-x86_64-linux-gnu.so +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.cpython-314-x86_64-linux-gnu.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 +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.cpython-314-x86_64-linux-gnu.so +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.cpython-314-x86_64-linux-gnu.so +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 +6 -0
- biotite-1.5.0.dist-info/licenses/LICENSE.rst +30 -0
|
@@ -0,0 +1,688 @@
|
|
|
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.pdbqt"
|
|
6
|
+
__author__ = "Patrick Kunzmann, Daniel Bauer"
|
|
7
|
+
__all__ = ["PDBQTFile"]
|
|
8
|
+
|
|
9
|
+
import warnings
|
|
10
|
+
import numpy as np
|
|
11
|
+
from biotite.file import InvalidFileError, TextFile
|
|
12
|
+
from biotite.structure.atoms import AtomArray, AtomArrayStack
|
|
13
|
+
from biotite.structure.bonds import (
|
|
14
|
+
BondList,
|
|
15
|
+
BondType,
|
|
16
|
+
find_connected,
|
|
17
|
+
find_rotatable_bonds,
|
|
18
|
+
)
|
|
19
|
+
from biotite.structure.charges import partial_charges
|
|
20
|
+
from biotite.structure.error import BadStructureError
|
|
21
|
+
|
|
22
|
+
PARAMETRIZED_ELEMENTS = [
|
|
23
|
+
"H",
|
|
24
|
+
"C",
|
|
25
|
+
"N",
|
|
26
|
+
"O",
|
|
27
|
+
"P",
|
|
28
|
+
"S",
|
|
29
|
+
"F",
|
|
30
|
+
"Cl",
|
|
31
|
+
"Br",
|
|
32
|
+
"I",
|
|
33
|
+
"Mg",
|
|
34
|
+
"Ca",
|
|
35
|
+
"Mn",
|
|
36
|
+
"Fe",
|
|
37
|
+
"Zn",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class PDBQTFile(TextFile):
|
|
42
|
+
"""
|
|
43
|
+
This class represents an *AutoDock* PDBQT file.
|
|
44
|
+
|
|
45
|
+
This class only provides rudimentary support for reading/writing
|
|
46
|
+
the pure atom information.
|
|
47
|
+
|
|
48
|
+
EXPERIMENTAL: Future API changes are probable.
|
|
49
|
+
|
|
50
|
+
Examples
|
|
51
|
+
--------
|
|
52
|
+
|
|
53
|
+
Write biotin as flexible ligand into a PDBQT file:
|
|
54
|
+
|
|
55
|
+
>>> import os.path
|
|
56
|
+
>>> ligand = residue("BTN")
|
|
57
|
+
>>> file = PDBQTFile()
|
|
58
|
+
>>> mask = file.set_structure(ligand, rotatable_bonds="all")
|
|
59
|
+
>>> # Print removed nonpolar hydrogen atoms
|
|
60
|
+
>>> print(ligand[~mask])
|
|
61
|
+
HET 0 BTN H101 H 3.745 1.171 0.974
|
|
62
|
+
HET 0 BTN H102 H 4.071 1.343 -0.767
|
|
63
|
+
HET 0 BTN H91 H 2.802 -0.740 -1.211
|
|
64
|
+
HET 0 BTN H92 H 2.476 -0.912 0.530
|
|
65
|
+
HET 0 BTN H81 H 1.289 1.265 0.523
|
|
66
|
+
HET 0 BTN H82 H 1.616 1.437 -1.218
|
|
67
|
+
HET 0 BTN H71 H 0.346 -0.646 -1.662
|
|
68
|
+
HET 0 BTN H72 H 0.020 -0.818 0.079
|
|
69
|
+
HET 0 BTN H2 H -0.838 1.576 -1.627
|
|
70
|
+
HET 0 BTN H61 H -3.797 1.837 1.286
|
|
71
|
+
HET 0 BTN H62 H -3.367 2.738 -0.205
|
|
72
|
+
HET 0 BTN H5 H -4.307 0.812 -1.205
|
|
73
|
+
HET 0 BTN H4 H -2.451 -0.038 -2.252
|
|
74
|
+
>>> print(file)
|
|
75
|
+
ROOT
|
|
76
|
+
HETATM 1 C11 BTN 0 5.089 -0.280 0.173 1.00 0.00 0.258 C
|
|
77
|
+
HETATM 2 O11 BTN 0 4.956 -1.473 0.030 1.00 0.00 -0.264 OA
|
|
78
|
+
ENDROOT
|
|
79
|
+
BRANCH 1 3
|
|
80
|
+
HETATM 3 O12 BTN 0 6.299 0.233 0.444 1.00 0.00 -0.331 OA
|
|
81
|
+
HETATM 17 HO2 BTN 0 7.034 -0.391 0.517 1.00 0.00 0.221 HD
|
|
82
|
+
ENDBRANCH 1 3
|
|
83
|
+
BRANCH 1 4
|
|
84
|
+
HETATM 4 C10 BTN 0 3.896 0.631 0.039 1.00 0.00 0.105 C
|
|
85
|
+
BRANCH 4 5
|
|
86
|
+
HETATM 5 C9 BTN 0 2.651 -0.200 -0.276 1.00 0.00 0.010 C
|
|
87
|
+
BRANCH 5 6
|
|
88
|
+
HETATM 6 C8 BTN 0 1.440 0.725 -0.412 1.00 0.00 0.002 C
|
|
89
|
+
BRANCH 6 7
|
|
90
|
+
HETATM 7 C7 BTN 0 0.196 -0.106 -0.727 1.00 0.00 0.016 C
|
|
91
|
+
BRANCH 7 8
|
|
92
|
+
HETATM 8 C2 BTN 0 -1.015 0.819 -0.863 1.00 0.00 0.065 C
|
|
93
|
+
HETATM 9 S1 BTN 0 -1.419 1.604 0.751 1.00 0.00 -0.154 SA
|
|
94
|
+
HETATM 10 C6 BTN 0 -3.205 1.827 0.371 1.00 0.00 0.090 C
|
|
95
|
+
HETATM 11 C5 BTN 0 -3.530 0.581 -0.476 1.00 0.00 0.091 C
|
|
96
|
+
HETATM 12 N1 BTN 0 -3.970 -0.507 0.412 1.00 0.00 -0.239 NA
|
|
97
|
+
HETATM 13 C3 BTN 0 -3.141 -1.549 0.271 1.00 0.00 0.272 C
|
|
98
|
+
HETATM 14 O3 BTN 0 -3.271 -2.589 0.888 1.00 0.00 -0.259 OA
|
|
99
|
+
HETATM 15 N2 BTN 0 -2.154 -1.343 -0.612 1.00 0.00 -0.239 NA
|
|
100
|
+
HETATM 16 C4 BTN 0 -2.289 0.010 -1.175 1.00 0.00 0.093 C
|
|
101
|
+
HETATM 18 HN1 BTN 0 -4.738 -0.474 1.004 1.00 0.00 0.132 HD
|
|
102
|
+
HETATM 19 HN2 BTN 0 -1.462 -1.982 -0.843 1.00 0.00 0.132 HD
|
|
103
|
+
ENDBRANCH 7 8
|
|
104
|
+
ENDBRANCH 6 7
|
|
105
|
+
ENDBRANCH 5 6
|
|
106
|
+
ENDBRANCH 4 5
|
|
107
|
+
ENDBRANCH 1 4
|
|
108
|
+
TORSDOF 6
|
|
109
|
+
>>> file.write(os.path.join(path_to_directory, "1l2y_mod.pdb"))
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
def get_remarks(self, model=None):
|
|
113
|
+
"""
|
|
114
|
+
Get the content of ``REMARKS`` lines.
|
|
115
|
+
|
|
116
|
+
Parameters
|
|
117
|
+
----------
|
|
118
|
+
model : int, optional
|
|
119
|
+
If this parameter is given, the function will return a
|
|
120
|
+
string from the remarks corresponding to the given
|
|
121
|
+
model number (starting at 1).
|
|
122
|
+
Negative values are used to index models starting from the
|
|
123
|
+
last model insted of the first model.
|
|
124
|
+
If this parameter is omitted, a list of strings
|
|
125
|
+
containing all models will be returned, even if the
|
|
126
|
+
structure contains only one model.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
lines : str or list of str
|
|
131
|
+
The content of ``REMARKS`` lines, without the leading
|
|
132
|
+
``'REMARKS'``.
|
|
133
|
+
"""
|
|
134
|
+
# Line indices where a new model starts
|
|
135
|
+
model_start_i = np.array(
|
|
136
|
+
[i for i in range(len(self.lines)) if self.lines[i].startswith(("MODEL"))],
|
|
137
|
+
dtype=int,
|
|
138
|
+
)
|
|
139
|
+
# Line indices with ATOM or HETATM records
|
|
140
|
+
remark_line_i = np.array(
|
|
141
|
+
[i for i in range(len(self.lines)) if self.lines[i].startswith("REMARK")],
|
|
142
|
+
dtype=int,
|
|
143
|
+
)
|
|
144
|
+
# Structures containing only one model may omit MODEL record
|
|
145
|
+
# In these cases model starting index is set to 0
|
|
146
|
+
if len(model_start_i) == 0:
|
|
147
|
+
model_start_i = np.array([0])
|
|
148
|
+
|
|
149
|
+
if model is None:
|
|
150
|
+
# Add exclusive end of file
|
|
151
|
+
model_start_i = np.concatenate((model_start_i, [len(self.lines)]))
|
|
152
|
+
remarks = []
|
|
153
|
+
for i in range(len(model_start_i) - 1):
|
|
154
|
+
start = model_start_i[i]
|
|
155
|
+
stop = model_start_i[i + 1]
|
|
156
|
+
model_remark_line_i = remark_line_i[
|
|
157
|
+
(remark_line_i >= start) & (remark_line_i < stop)
|
|
158
|
+
]
|
|
159
|
+
remarks.append(
|
|
160
|
+
"\n".join([self.lines[i][7:] for i in model_remark_line_i])
|
|
161
|
+
)
|
|
162
|
+
return remarks
|
|
163
|
+
|
|
164
|
+
else:
|
|
165
|
+
last_model = len(model_start_i)
|
|
166
|
+
if model == 0:
|
|
167
|
+
raise ValueError("The model index must not be 0")
|
|
168
|
+
# Negative models mean index starting from last model
|
|
169
|
+
model = last_model + model + 1 if model < 0 else model
|
|
170
|
+
|
|
171
|
+
if model < last_model:
|
|
172
|
+
line_filter = (remark_line_i >= model_start_i[model - 1]) & (
|
|
173
|
+
remark_line_i < model_start_i[model]
|
|
174
|
+
)
|
|
175
|
+
elif model == last_model:
|
|
176
|
+
line_filter = remark_line_i >= model_start_i[model - 1]
|
|
177
|
+
else:
|
|
178
|
+
raise ValueError(
|
|
179
|
+
f"The file has {last_model} models, "
|
|
180
|
+
f"the given model {model} does not exist"
|
|
181
|
+
)
|
|
182
|
+
remark_line_i = remark_line_i[line_filter]
|
|
183
|
+
|
|
184
|
+
# Do not include 'REMARK ' itself -> begin from pos 8
|
|
185
|
+
return "\n".join([self.lines[i][7:] for i in remark_line_i])
|
|
186
|
+
|
|
187
|
+
def get_structure(self, model=None):
|
|
188
|
+
"""
|
|
189
|
+
Get an :class:`AtomArray` or :class:`AtomArrayStack` from the
|
|
190
|
+
PDBQT file.
|
|
191
|
+
|
|
192
|
+
Parameters
|
|
193
|
+
----------
|
|
194
|
+
model : int, optional
|
|
195
|
+
If this parameter is given, the function will return an
|
|
196
|
+
:class:`AtomArray` from the atoms corresponding to the given
|
|
197
|
+
model number (starting at 1).
|
|
198
|
+
Negative values are used to index models starting from the
|
|
199
|
+
last model insted of the first model.
|
|
200
|
+
If this parameter is omitted, an :class:`AtomArrayStack`
|
|
201
|
+
containing all models will be returned, even if the
|
|
202
|
+
structure contains only one model.
|
|
203
|
+
|
|
204
|
+
Returns
|
|
205
|
+
-------
|
|
206
|
+
array : AtomArray or AtomArrayStack
|
|
207
|
+
The return type depends on the `model` parameter.
|
|
208
|
+
"""
|
|
209
|
+
# Line indices where a new model starts
|
|
210
|
+
model_start_i = np.array(
|
|
211
|
+
[i for i in range(len(self.lines)) if self.lines[i].startswith(("MODEL"))],
|
|
212
|
+
dtype=int,
|
|
213
|
+
)
|
|
214
|
+
# Line indices with ATOM or HETATM records
|
|
215
|
+
atom_line_i = np.array(
|
|
216
|
+
[
|
|
217
|
+
i
|
|
218
|
+
for i in range(len(self.lines))
|
|
219
|
+
if self.lines[i].startswith(("ATOM", "HETATM"))
|
|
220
|
+
],
|
|
221
|
+
dtype=int,
|
|
222
|
+
)
|
|
223
|
+
# Structures containing only one model may omit MODEL record
|
|
224
|
+
# In these cases model starting index is set to 0
|
|
225
|
+
if len(model_start_i) == 0:
|
|
226
|
+
model_start_i = np.array([0])
|
|
227
|
+
|
|
228
|
+
if model is None:
|
|
229
|
+
depth = len(model_start_i)
|
|
230
|
+
length = self._get_model_length(model_start_i, atom_line_i)
|
|
231
|
+
array = AtomArrayStack(depth, length)
|
|
232
|
+
# Line indices for annotation determination
|
|
233
|
+
# Annotation is determined from model 1,
|
|
234
|
+
# therefore from ATOM records before second MODEL record
|
|
235
|
+
if len(model_start_i) == 1:
|
|
236
|
+
annot_i = atom_line_i
|
|
237
|
+
else:
|
|
238
|
+
annot_i = atom_line_i[atom_line_i < model_start_i[1]]
|
|
239
|
+
# Line indices for coordinate determination
|
|
240
|
+
coord_i = atom_line_i
|
|
241
|
+
|
|
242
|
+
else:
|
|
243
|
+
last_model = len(model_start_i)
|
|
244
|
+
if model == 0:
|
|
245
|
+
raise ValueError("The model index must not be 0")
|
|
246
|
+
# Negative models mean index starting from last model
|
|
247
|
+
model = last_model + model + 1 if model < 0 else model
|
|
248
|
+
|
|
249
|
+
if model < last_model:
|
|
250
|
+
line_filter = (atom_line_i >= model_start_i[model - 1]) & (
|
|
251
|
+
atom_line_i < model_start_i[model]
|
|
252
|
+
)
|
|
253
|
+
elif model == last_model:
|
|
254
|
+
line_filter = atom_line_i >= model_start_i[model - 1]
|
|
255
|
+
else:
|
|
256
|
+
raise ValueError(
|
|
257
|
+
f"The file has {last_model} models, "
|
|
258
|
+
f"the given model {model} does not exist"
|
|
259
|
+
)
|
|
260
|
+
annot_i = coord_i = atom_line_i[line_filter]
|
|
261
|
+
array = AtomArray(len(coord_i))
|
|
262
|
+
|
|
263
|
+
# Save atom IDs for later sorting into the original atom order
|
|
264
|
+
atom_id = np.zeros(array.array_length(), int)
|
|
265
|
+
|
|
266
|
+
# Create annotation arrays
|
|
267
|
+
chain_id = np.zeros(array.array_length(), array.chain_id.dtype)
|
|
268
|
+
res_id = np.zeros(array.array_length(), array.res_id.dtype)
|
|
269
|
+
ins_code = np.zeros(array.array_length(), array.ins_code.dtype)
|
|
270
|
+
res_name = np.zeros(array.array_length(), array.res_name.dtype)
|
|
271
|
+
hetero = np.zeros(array.array_length(), array.hetero.dtype)
|
|
272
|
+
atom_name = np.zeros(array.array_length(), array.atom_name.dtype)
|
|
273
|
+
element = np.zeros(array.array_length(), array.element.dtype)
|
|
274
|
+
|
|
275
|
+
# Fill annotation array
|
|
276
|
+
# i is index in array, line_i is line index
|
|
277
|
+
for i, line_i in enumerate(annot_i):
|
|
278
|
+
line = self.lines[line_i]
|
|
279
|
+
|
|
280
|
+
atom_id[i] = int(line[6:11])
|
|
281
|
+
chain_id[i] = line[21].strip()
|
|
282
|
+
res_id[i] = int(line[22:26])
|
|
283
|
+
ins_code[i] = line[26].strip()
|
|
284
|
+
res_name[i] = line[17:20].strip()
|
|
285
|
+
hetero[i] = False if line[0:4] == "ATOM" else True
|
|
286
|
+
atom_name[i] = line[12:16].strip()
|
|
287
|
+
element[i] = line[76:78].strip()
|
|
288
|
+
|
|
289
|
+
# Add annotation arrays to atom array (stack)
|
|
290
|
+
array.chain_id = chain_id
|
|
291
|
+
array.res_id = res_id
|
|
292
|
+
array.ins_code = ins_code
|
|
293
|
+
array.res_name = res_name
|
|
294
|
+
array.hetero = hetero
|
|
295
|
+
array.atom_name = atom_name
|
|
296
|
+
array.element = element
|
|
297
|
+
|
|
298
|
+
# Fill in coordinates
|
|
299
|
+
if isinstance(array, AtomArray):
|
|
300
|
+
for i, line_i in enumerate(coord_i):
|
|
301
|
+
line = self.lines[line_i]
|
|
302
|
+
array.coord[i, 0] = float(line[30:38])
|
|
303
|
+
array.coord[i, 1] = float(line[38:46])
|
|
304
|
+
array.coord[i, 2] = float(line[46:54])
|
|
305
|
+
|
|
306
|
+
elif isinstance(array, AtomArrayStack):
|
|
307
|
+
m = 0
|
|
308
|
+
i = 0
|
|
309
|
+
for line_i in atom_line_i:
|
|
310
|
+
if m < len(model_start_i) - 1 and line_i > model_start_i[m + 1]:
|
|
311
|
+
m += 1
|
|
312
|
+
i = 0
|
|
313
|
+
line = self.lines[line_i]
|
|
314
|
+
array.coord[m, i, 0] = float(line[30:38])
|
|
315
|
+
array.coord[m, i, 1] = float(line[38:46])
|
|
316
|
+
array.coord[m, i, 2] = float(line[46:54])
|
|
317
|
+
i += 1
|
|
318
|
+
|
|
319
|
+
# Sort into the original atom order
|
|
320
|
+
array = array[..., np.argsort(atom_id)]
|
|
321
|
+
|
|
322
|
+
return array
|
|
323
|
+
|
|
324
|
+
def set_structure(
|
|
325
|
+
self,
|
|
326
|
+
atoms,
|
|
327
|
+
charges=None,
|
|
328
|
+
atom_types=None,
|
|
329
|
+
rotatable_bonds=None,
|
|
330
|
+
root=None,
|
|
331
|
+
include_torsdof=True,
|
|
332
|
+
):
|
|
333
|
+
"""
|
|
334
|
+
Write an :class:`AtomArray` into the PDBQT file.
|
|
335
|
+
|
|
336
|
+
Parameters
|
|
337
|
+
----------
|
|
338
|
+
atoms : AtomArray, shape=(n,)
|
|
339
|
+
The atoms to be written into this file.
|
|
340
|
+
Must have an associated :class:`BondList`.
|
|
341
|
+
charges : ndarray, shape=(n,), dtype=float, optional
|
|
342
|
+
Partial charges for each atom in `atoms`.
|
|
343
|
+
By default, the charges are calculated using the PEOE method
|
|
344
|
+
(:func:`partial_charges()`).
|
|
345
|
+
atom_types : ndarray, shape=(n,), dtype="U1", optional
|
|
346
|
+
Custom *AutoDock* atom types for each atom in `atoms`.
|
|
347
|
+
rotatable_bonds : None or 'rigid' or 'all' or BondList, optional
|
|
348
|
+
This parameter describes, how rotatable bonds are handled,
|
|
349
|
+
with respect to ``ROOT``, ``BRANCH`` and ``ENDBRANCH``
|
|
350
|
+
lines.
|
|
351
|
+
|
|
352
|
+
- ``None`` - The molecule is handled as rigid receptor:
|
|
353
|
+
No ``ROOT``, ``BRANCH`` and ``ENDBRANCH`` lines will
|
|
354
|
+
be written.
|
|
355
|
+
- ``'rigid'`` - The molecule is handled as rigid ligand:
|
|
356
|
+
Only a ``ROOT`` line will be written.
|
|
357
|
+
- ``'all'`` - The molecule is handled as flexible
|
|
358
|
+
ligand:
|
|
359
|
+
A ``ROOT`` line will be written and all rotatable
|
|
360
|
+
bonds are included using ``BRANCH`` and ``ENDBRANCH``
|
|
361
|
+
lines.
|
|
362
|
+
- :class:`BondList` - The molecule is handled as
|
|
363
|
+
flexible ligand:
|
|
364
|
+
A ``ROOT`` line will be written and all bonds in the
|
|
365
|
+
given :class:`BondList` are considered flexible via
|
|
366
|
+
``BRANCH`` and ``ENDBRANCH`` lines.
|
|
367
|
+
|
|
368
|
+
root : int, optional
|
|
369
|
+
Specifies the index of the atom following the ``ROOT`` line.
|
|
370
|
+
Setting the root atom is useful for specifying the *anchor*
|
|
371
|
+
in flexible side chains.
|
|
372
|
+
This parameter has no effect, if `rotatable_bonds` is
|
|
373
|
+
``None``.
|
|
374
|
+
By default, the first atom is also the root atom.
|
|
375
|
+
include_torsdof : bool, optional
|
|
376
|
+
By default, a ``TORSDOF`` (torsional degrees of freedom)
|
|
377
|
+
record is written at the end of the file.
|
|
378
|
+
By setting this parameter to false, the record is omitted.
|
|
379
|
+
|
|
380
|
+
Returns
|
|
381
|
+
-------
|
|
382
|
+
mask : ndarray, shape=(n,), dtype=bool
|
|
383
|
+
A boolean mask, that is ``False`` for each atom of the input
|
|
384
|
+
``atoms``, that was removed due to being a nonpolar
|
|
385
|
+
hydrogen.
|
|
386
|
+
"""
|
|
387
|
+
# Check if AtomArray is suitable for PDBQT
|
|
388
|
+
max_atoms, max_residues = 99999, 9999
|
|
389
|
+
if atoms.array_length() > max_atoms:
|
|
390
|
+
warnings.warn(f"More then {max_atoms:,} atoms per model")
|
|
391
|
+
if (atoms.res_id > max_residues).any():
|
|
392
|
+
warnings.warn(f"Residue IDs exceed {max_residues:,}")
|
|
393
|
+
if np.isnan(atoms.coord).any():
|
|
394
|
+
raise BadStructureError("Coordinates contain 'NaN' values")
|
|
395
|
+
if any([len(name) > 1 for name in atoms.chain_id]):
|
|
396
|
+
raise BadStructureError("Some chain IDs exceed 1 character")
|
|
397
|
+
if any([len(name) > 3 for name in atoms.res_name]):
|
|
398
|
+
raise BadStructureError("Some residue names exceed 3 characters")
|
|
399
|
+
if any([len(name) > 4 for name in atoms.atom_name]):
|
|
400
|
+
raise BadStructureError("Some atom names exceed 4 characters")
|
|
401
|
+
|
|
402
|
+
if charges is None:
|
|
403
|
+
charges = partial_charges(atoms)
|
|
404
|
+
charges[np.isnan(charges)] = 0
|
|
405
|
+
else:
|
|
406
|
+
if np.isnan(charges).any():
|
|
407
|
+
raise ValueError("Input charges contain NaN values")
|
|
408
|
+
|
|
409
|
+
# Get AutoDock atom types and remove nonpolar hydrogen atoms
|
|
410
|
+
atoms, charges, types, mask = convert_atoms(atoms, charges)
|
|
411
|
+
# Overwrite calculated atom types with input atom types
|
|
412
|
+
if atom_types is not None:
|
|
413
|
+
types = atom_types[mask]
|
|
414
|
+
|
|
415
|
+
if rotatable_bonds is None:
|
|
416
|
+
# No rotatable bonds -> the BondList contains no bonds
|
|
417
|
+
rotatable_bonds = BondList(atoms.bonds.get_atom_count())
|
|
418
|
+
use_root = False
|
|
419
|
+
elif rotatable_bonds == "rigid":
|
|
420
|
+
rotatable_bonds = BondList(atoms.bonds.get_atom_count())
|
|
421
|
+
use_root = True
|
|
422
|
+
elif rotatable_bonds == "all":
|
|
423
|
+
rotatable_bonds = find_rotatable_bonds(atoms.bonds)
|
|
424
|
+
use_root = True
|
|
425
|
+
else:
|
|
426
|
+
if rotatable_bonds.ndim != 2 or rotatable_bonds.shape[1] != 2:
|
|
427
|
+
raise ValueError("An (nx2) array is expected for rotatable bonds")
|
|
428
|
+
rotatable_bonds = BondList(len(mask), np.asarray(rotatable_bonds))[mask]
|
|
429
|
+
use_root = True
|
|
430
|
+
|
|
431
|
+
if root is None:
|
|
432
|
+
root_index = 0
|
|
433
|
+
else:
|
|
434
|
+
# Find new index of root atom, since the index might have
|
|
435
|
+
# been shifted due to removed atoms
|
|
436
|
+
original_indices = np.arange(len(mask))
|
|
437
|
+
new_indices = original_indices[mask]
|
|
438
|
+
try:
|
|
439
|
+
root_index = np.where(new_indices == root)[0][0]
|
|
440
|
+
except IndexError:
|
|
441
|
+
raise ValueError(
|
|
442
|
+
"The given root atom index points to an nonpolar hydrogen "
|
|
443
|
+
"atom, that has been removed"
|
|
444
|
+
)
|
|
445
|
+
# Add bonds of the rigid root to rotatable bonds,
|
|
446
|
+
# as they probably have been filtered out,
|
|
447
|
+
# as the root is probably a terminal atom
|
|
448
|
+
for atom, bond_type in zip(*atoms.bonds.get_bonds(root_index)):
|
|
449
|
+
rotatable_bonds.add_bond(root_index, atom, bond_type)
|
|
450
|
+
|
|
451
|
+
# Break rotatable bonds
|
|
452
|
+
# for simple branch determination in '_write_atoms()'
|
|
453
|
+
atoms.bonds.remove_bonds(rotatable_bonds)
|
|
454
|
+
|
|
455
|
+
hetero = ["HETATM" if e else "ATOM" for e in atoms.hetero]
|
|
456
|
+
if "atom_id" in atoms.get_annotation_categories():
|
|
457
|
+
atom_id = atoms.atom_id
|
|
458
|
+
else:
|
|
459
|
+
atom_id = np.arange(1, atoms.array_length() + 1)
|
|
460
|
+
occupancy = np.ones(atoms.array_length())
|
|
461
|
+
b_factor = np.zeros(atoms.array_length())
|
|
462
|
+
|
|
463
|
+
# Convert rotatable bonds into array for easier handling
|
|
464
|
+
# The bond type is irrelevant from this point on
|
|
465
|
+
rotatable_bonds = rotatable_bonds.as_array()[:, :2]
|
|
466
|
+
|
|
467
|
+
self.lines = []
|
|
468
|
+
self._write_atoms(
|
|
469
|
+
atoms,
|
|
470
|
+
charges,
|
|
471
|
+
types,
|
|
472
|
+
atom_id,
|
|
473
|
+
hetero,
|
|
474
|
+
occupancy,
|
|
475
|
+
b_factor,
|
|
476
|
+
root_index,
|
|
477
|
+
rotatable_bonds,
|
|
478
|
+
np.zeros(len(rotatable_bonds), dtype=bool),
|
|
479
|
+
use_root,
|
|
480
|
+
)
|
|
481
|
+
if include_torsdof:
|
|
482
|
+
self.lines.append(f"TORSDOF {len(rotatable_bonds)}")
|
|
483
|
+
|
|
484
|
+
return mask
|
|
485
|
+
|
|
486
|
+
def _write_atoms(
|
|
487
|
+
self,
|
|
488
|
+
atoms,
|
|
489
|
+
charges,
|
|
490
|
+
types,
|
|
491
|
+
atom_id,
|
|
492
|
+
hetero,
|
|
493
|
+
occupancy,
|
|
494
|
+
b_factor,
|
|
495
|
+
root_atom,
|
|
496
|
+
rotatable_bonds,
|
|
497
|
+
visited_rotatable_bonds,
|
|
498
|
+
is_root,
|
|
499
|
+
):
|
|
500
|
+
if len(rotatable_bonds) != 0:
|
|
501
|
+
# Get the indices to atoms of this branch, i.e. a group of
|
|
502
|
+
# atoms that are connected by non-rotatable bonds
|
|
503
|
+
# Use 'find_connected()', since rotatable bonds were removed
|
|
504
|
+
# from the BondList before
|
|
505
|
+
this_branch_indices = find_connected(atoms.bonds, root_atom)
|
|
506
|
+
# The root atom of the branch, i.e. the atom connected by
|
|
507
|
+
# the rotatable bond should always be listed first
|
|
508
|
+
# -> Remove root atom and insert it at the beginning
|
|
509
|
+
this_branch_indices = np.insert(
|
|
510
|
+
this_branch_indices[this_branch_indices != root_atom], 0, root_atom
|
|
511
|
+
)
|
|
512
|
+
else:
|
|
513
|
+
# No rotatable bonds
|
|
514
|
+
# -> all atom are in root i.e. this branch
|
|
515
|
+
this_branch_indices = np.arange(atoms.array_length())
|
|
516
|
+
|
|
517
|
+
if is_root:
|
|
518
|
+
self.lines.append("ROOT")
|
|
519
|
+
for i in this_branch_indices:
|
|
520
|
+
self.lines.append(
|
|
521
|
+
f"{hetero[i]:6}"
|
|
522
|
+
f"{atom_id[i]:>5d} "
|
|
523
|
+
f"{atoms.atom_name[i]:4} "
|
|
524
|
+
f"{atoms.res_name[i]:3} "
|
|
525
|
+
f"{atoms.chain_id[i]:1}"
|
|
526
|
+
f"{atoms.res_id[i]:>4d}"
|
|
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}"
|
|
531
|
+
f"{occupancy[i]:>6.2f}"
|
|
532
|
+
f"{b_factor[i]:>6.2f} "
|
|
533
|
+
f"{charges[i]:>6.3f} "
|
|
534
|
+
f"{types[i]:2}"
|
|
535
|
+
)
|
|
536
|
+
if is_root:
|
|
537
|
+
self.lines.append("ENDROOT")
|
|
538
|
+
|
|
539
|
+
if len(rotatable_bonds) == 0:
|
|
540
|
+
# No rotatable bonds -> no branching
|
|
541
|
+
return
|
|
542
|
+
|
|
543
|
+
for k, (i, j) in enumerate(rotatable_bonds):
|
|
544
|
+
if visited_rotatable_bonds[k]:
|
|
545
|
+
continue
|
|
546
|
+
|
|
547
|
+
# Create a new branch for each rotatable bond,
|
|
548
|
+
# that connects to an atom of this branch
|
|
549
|
+
if i in this_branch_indices:
|
|
550
|
+
this_br_i = i
|
|
551
|
+
new_br_i = j
|
|
552
|
+
elif j in this_branch_indices:
|
|
553
|
+
this_br_i = j
|
|
554
|
+
new_br_i = i
|
|
555
|
+
else:
|
|
556
|
+
# Rotatable bond does not start from this branch
|
|
557
|
+
continue
|
|
558
|
+
|
|
559
|
+
# Mark rotatable bond as visited as otherwise branches would
|
|
560
|
+
# be created back and forth over the same rotatable bond and
|
|
561
|
+
# this method would never terminate
|
|
562
|
+
visited_rotatable_bonds[k] = True
|
|
563
|
+
|
|
564
|
+
self.lines.append(
|
|
565
|
+
f"BRANCH {atom_id[this_br_i]:>3d} {atom_id[new_br_i]:>3d}"
|
|
566
|
+
)
|
|
567
|
+
self._write_atoms(
|
|
568
|
+
atoms,
|
|
569
|
+
charges,
|
|
570
|
+
types,
|
|
571
|
+
atom_id,
|
|
572
|
+
hetero,
|
|
573
|
+
occupancy,
|
|
574
|
+
b_factor,
|
|
575
|
+
# The root atom of the branch
|
|
576
|
+
# is the other atom of the rotatable bond
|
|
577
|
+
new_br_i,
|
|
578
|
+
rotatable_bonds,
|
|
579
|
+
visited_rotatable_bonds,
|
|
580
|
+
False,
|
|
581
|
+
)
|
|
582
|
+
self.lines.append(
|
|
583
|
+
f"ENDBRANCH {atom_id[this_br_i]:>3d} {atom_id[new_br_i]:>3d}"
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
def _get_model_length(self, model_start_i, atom_line_i):
|
|
587
|
+
"""
|
|
588
|
+
Determine length of models and check that all models
|
|
589
|
+
have equal length.
|
|
590
|
+
"""
|
|
591
|
+
n_models = len(model_start_i)
|
|
592
|
+
length = None
|
|
593
|
+
for model_i in range(len(model_start_i)):
|
|
594
|
+
model_start = model_start_i[model_i]
|
|
595
|
+
model_stop = (
|
|
596
|
+
model_start_i[model_i + 1]
|
|
597
|
+
if model_i + 1 < n_models
|
|
598
|
+
else len(self.lines)
|
|
599
|
+
)
|
|
600
|
+
model_length = np.count_nonzero(
|
|
601
|
+
(atom_line_i >= model_start) & (atom_line_i < model_stop)
|
|
602
|
+
)
|
|
603
|
+
if length is None:
|
|
604
|
+
length = model_length
|
|
605
|
+
if model_length != length:
|
|
606
|
+
raise InvalidFileError(
|
|
607
|
+
f"Model {model_i + 1} has {model_length} atoms, "
|
|
608
|
+
f"but model 1 has {length} atoms, must be equal"
|
|
609
|
+
)
|
|
610
|
+
return length
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
def convert_atoms(atoms, charges):
|
|
614
|
+
"""
|
|
615
|
+
Convert atoms into *AutoDock* compatible atoms.
|
|
616
|
+
|
|
617
|
+
Parameters
|
|
618
|
+
----------
|
|
619
|
+
atoms : AtomArray
|
|
620
|
+
The atoms to be converted.
|
|
621
|
+
charges : ndarray, dtype=float
|
|
622
|
+
Partial charges for the atoms.
|
|
623
|
+
|
|
624
|
+
Returns
|
|
625
|
+
-------
|
|
626
|
+
converted_atoms : AtomArray
|
|
627
|
+
The input `atoms`, but with deleted nonpolar hydrogen atoms.
|
|
628
|
+
charges : ndarray, dtype=float
|
|
629
|
+
The input `charges`, but with deleted entries for nonpolar
|
|
630
|
+
hydrogen atoms.
|
|
631
|
+
atom_types : ndarray, dtype="U1"
|
|
632
|
+
The *AutoDock* atom types.
|
|
633
|
+
mask : ndarray, shape=(n,), dtype=bool
|
|
634
|
+
A boolean mask, that is ``False`` for each atom of the input
|
|
635
|
+
``atoms``, that was removed due to being a nonpolar hydrogen.
|
|
636
|
+
"""
|
|
637
|
+
charges = charges.copy()
|
|
638
|
+
all_bonds, all_bond_types = atoms.bonds.get_all_bonds()
|
|
639
|
+
|
|
640
|
+
atom_types = np.zeros(atoms.array_length(), dtype="U2")
|
|
641
|
+
hydrogen_removal_mask = np.zeros(atoms.array_length(), dtype=bool)
|
|
642
|
+
for i in range(atoms.array_length()):
|
|
643
|
+
element = atoms.element[i]
|
|
644
|
+
bonded_atoms = all_bonds[i][all_bonds[i] != -1]
|
|
645
|
+
if element == "H":
|
|
646
|
+
if len(bonded_atoms) == 0:
|
|
647
|
+
# Free proton
|
|
648
|
+
atom_types[i] = "H"
|
|
649
|
+
elif len(bonded_atoms) == 1:
|
|
650
|
+
j = bonded_atoms[0]
|
|
651
|
+
bonded_element = atoms.element[j]
|
|
652
|
+
if bonded_element == "C":
|
|
653
|
+
# Remove hydrogen and add its charge
|
|
654
|
+
# to charge of bonded carbon
|
|
655
|
+
charges[j] += charges[i]
|
|
656
|
+
hydrogen_removal_mask[i] = True
|
|
657
|
+
else:
|
|
658
|
+
atom_types[i] = "HD"
|
|
659
|
+
else:
|
|
660
|
+
raise BadStructureError(
|
|
661
|
+
"Structure contains hydrogen with multiple bonds"
|
|
662
|
+
)
|
|
663
|
+
elif element == "C":
|
|
664
|
+
if np.isin(
|
|
665
|
+
all_bond_types[i], [BondType.AROMATIC_SINGLE, BondType.AROMATIC_DOUBLE]
|
|
666
|
+
).any():
|
|
667
|
+
# Aromatic carbon
|
|
668
|
+
atom_types[i] = "A"
|
|
669
|
+
else:
|
|
670
|
+
# Alphatic carbon
|
|
671
|
+
atom_types[i] = "C"
|
|
672
|
+
elif element == "N":
|
|
673
|
+
atom_types[i] = "NA"
|
|
674
|
+
elif element == "O":
|
|
675
|
+
atom_types[i] = "OA"
|
|
676
|
+
elif element == "S":
|
|
677
|
+
atom_types[i] = "SA"
|
|
678
|
+
elif element.capitalize() in PARAMETRIZED_ELEMENTS:
|
|
679
|
+
atom_types[i] = element.capitalize()
|
|
680
|
+
else:
|
|
681
|
+
warnings.warn(
|
|
682
|
+
f"Element {element} is not paramtrized, "
|
|
683
|
+
f"using parameters for hydrogen instead"
|
|
684
|
+
)
|
|
685
|
+
atom_types[i] = "H"
|
|
686
|
+
|
|
687
|
+
mask = ~hydrogen_removal_mask
|
|
688
|
+
return atoms[mask], charges[mask], atom_types[mask], mask
|