biotite 1.5.0__cp312-cp312-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-312-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-312-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/kmeralphabet.pyx +595 -0
- biotite/sequence/align/kmersimilarity.cpython-312-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/kmersimilarity.pyx +233 -0
- biotite/sequence/align/kmertable.cpython-312-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/kmertable.pyx +3411 -0
- biotite/sequence/align/localgapped.cpython-312-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/localgapped.pyx +892 -0
- biotite/sequence/align/localungapped.cpython-312-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-312-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/multiple.pyx +619 -0
- biotite/sequence/align/pairwise.cpython-312-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/pairwise.pyx +585 -0
- biotite/sequence/align/permutation.cpython-312-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-312-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-312-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-312-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-312-x86_64-linux-gnu.so +0 -0
- biotite/sequence/phylo/nj.pyx +221 -0
- biotite/sequence/phylo/tree.cpython-312-x86_64-linux-gnu.so +0 -0
- biotite/sequence/phylo/tree.pyx +1169 -0
- biotite/sequence/phylo/upgma.cpython-312-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-312-x86_64-linux-gnu.so +0 -0
- biotite/structure/bonds.pyx +2036 -0
- biotite/structure/box.py +724 -0
- biotite/structure/celllist.cpython-312-x86_64-linux-gnu.so +0 -0
- biotite/structure/celllist.pyx +864 -0
- biotite/structure/chains.py +310 -0
- biotite/structure/charges.cpython-312-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-312-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-312-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-312-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,817 @@
|
|
|
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 module provides functions for geometric measurements between atoms
|
|
7
|
+
in a structure, mainly lenghts and angles.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
__name__ = "biotite.structure"
|
|
11
|
+
__author__ = "Patrick Kunzmann"
|
|
12
|
+
__all__ = [
|
|
13
|
+
"displacement",
|
|
14
|
+
"index_displacement",
|
|
15
|
+
"distance",
|
|
16
|
+
"index_distance",
|
|
17
|
+
"angle",
|
|
18
|
+
"index_angle",
|
|
19
|
+
"dihedral",
|
|
20
|
+
"index_dihedral",
|
|
21
|
+
"dihedral_backbone",
|
|
22
|
+
"dihedral_side_chain",
|
|
23
|
+
"centroid",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
import functools
|
|
27
|
+
import numpy as np
|
|
28
|
+
from biotite.structure.atoms import AtomArray, AtomArrayStack, coord
|
|
29
|
+
from biotite.structure.box import coord_to_fraction, fraction_to_coord, is_orthogonal
|
|
30
|
+
from biotite.structure.filter import filter_amino_acids, filter_canonical_amino_acids
|
|
31
|
+
from biotite.structure.residues import get_residue_starts
|
|
32
|
+
from biotite.structure.util import (
|
|
33
|
+
coord_for_atom_name_per_residue,
|
|
34
|
+
norm_vector,
|
|
35
|
+
vector_dot,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# The names of the atoms participating in chi angle
|
|
39
|
+
_CHI_ATOMS = {
|
|
40
|
+
"ARG": [
|
|
41
|
+
("N", "CA", "CB", "CG"),
|
|
42
|
+
("CA", "CB", "CG", "CD"),
|
|
43
|
+
("CB", "CG", "CD", "NE"),
|
|
44
|
+
("CG", "CD", "NE", "CZ"),
|
|
45
|
+
],
|
|
46
|
+
"LEU": [
|
|
47
|
+
("N", "CA", "CB", "CG"),
|
|
48
|
+
# By convention chi2 is defined using CD1 instead of CD2
|
|
49
|
+
("CA", "CB", "CG", "CD1"),
|
|
50
|
+
],
|
|
51
|
+
"VAL": [("N", "CA", "CB", "CG1")],
|
|
52
|
+
"ILE": [("N", "CA", "CB", "CG1"), ("CA", "CB", "CG1", "CD1")],
|
|
53
|
+
"MET": [
|
|
54
|
+
("N", "CA", "CB", "CG"),
|
|
55
|
+
("CA", "CB", "CG", "SD"),
|
|
56
|
+
("CB", "CG", "SD", "CE"),
|
|
57
|
+
],
|
|
58
|
+
"LYS": [
|
|
59
|
+
("N", "CA", "CB", "CG"),
|
|
60
|
+
("CA", "CB", "CG", "CD"),
|
|
61
|
+
("CB", "CG", "CD", "CE"),
|
|
62
|
+
("CG", "CD", "CE", "NZ"),
|
|
63
|
+
],
|
|
64
|
+
"PHE": [
|
|
65
|
+
("N", "CA", "CB", "CG"),
|
|
66
|
+
("CA", "CB", "CG", "CD1"),
|
|
67
|
+
],
|
|
68
|
+
"TRP": [
|
|
69
|
+
("N", "CA", "CB", "CG"),
|
|
70
|
+
("CA", "CB", "CG", "CD1"),
|
|
71
|
+
],
|
|
72
|
+
"TYR": [
|
|
73
|
+
("N", "CA", "CB", "CG"),
|
|
74
|
+
("CA", "CB", "CG", "CD1"),
|
|
75
|
+
],
|
|
76
|
+
"ASN": [("N", "CA", "CB", "CG"), ("CA", "CB", "CG", "OD1")],
|
|
77
|
+
"GLN": [
|
|
78
|
+
("N", "CA", "CB", "CG"),
|
|
79
|
+
("CA", "CB", "CG", "CD"),
|
|
80
|
+
("CB", "CG", "CD", "OE1"),
|
|
81
|
+
],
|
|
82
|
+
"ASP": [("N", "CA", "CB", "CG"), ("CA", "CB", "CG", "OD1")],
|
|
83
|
+
"GLU": [
|
|
84
|
+
("N", "CA", "CB", "CG"),
|
|
85
|
+
("CA", "CB", "CG", "CD"),
|
|
86
|
+
("CB", "CG", "CD", "OE1"),
|
|
87
|
+
],
|
|
88
|
+
"CYS": [("N", "CA", "CB", "SG")],
|
|
89
|
+
"HIS": [("N", "CA", "CB", "CG"), ("CA", "CB", "CG", "ND1")],
|
|
90
|
+
"PRO": [("N", "CA", "CB", "CG"), ("CA", "CB", "CG", "CD")],
|
|
91
|
+
"SER": [("N", "CA", "CB", "OG")],
|
|
92
|
+
"THR": [("N", "CA", "CB", "OG1")],
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def displacement(atoms1, atoms2, box=None):
|
|
97
|
+
"""
|
|
98
|
+
Measure the displacement vector, i.e. the vector difference, from
|
|
99
|
+
one array of atom coordinates to another array of coordinates.
|
|
100
|
+
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
atoms1, atoms2 : ndarray, shape=(m,n,3) or ndarray, shape=(n,3) or ndarray, shape=(3,) or Atom or AtomArray or AtomArrayStack
|
|
104
|
+
The atoms to measure the displacement between.
|
|
105
|
+
The vector from `atoms1` to `atoms2` is measured.
|
|
106
|
+
The dimensions may vary.
|
|
107
|
+
Alternatively an ndarray containing the coordinates can be
|
|
108
|
+
provided.
|
|
109
|
+
Usual *NumPy* broadcasting rules apply.
|
|
110
|
+
box : ndarray, shape=(3,3) or shape=(m,3,3), optional
|
|
111
|
+
If this parameter is set, periodic boundary conditions are
|
|
112
|
+
taken into account (minimum-image convention), based on
|
|
113
|
+
the box vectors given with this parameter.
|
|
114
|
+
The shape *(m,3,3)* is only allowed, when the input coordinates
|
|
115
|
+
comprise multiple models.
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
disp : ndarray, shape=(m,n,3) or ndarray, shape=(n,3) or ndarray, shape=(3,)
|
|
120
|
+
The displacement vector(s). The shape is equal to the shape of
|
|
121
|
+
the input `atoms` with the highest dimensionality.
|
|
122
|
+
|
|
123
|
+
See Also
|
|
124
|
+
--------
|
|
125
|
+
index_displacement : The same calculation, but using atom indices.
|
|
126
|
+
"""
|
|
127
|
+
v1 = coord(atoms1)
|
|
128
|
+
v2 = coord(atoms2)
|
|
129
|
+
# Decide subtraction order based on shape, since an array can be
|
|
130
|
+
# only subtracted by an array with less dimensions
|
|
131
|
+
if len(v1.shape) <= len(v2.shape):
|
|
132
|
+
diff = v2 - v1
|
|
133
|
+
else:
|
|
134
|
+
diff = -(v1 - v2)
|
|
135
|
+
|
|
136
|
+
# Use minimum-image convention if box is given
|
|
137
|
+
if box is not None:
|
|
138
|
+
# Transform difference vector
|
|
139
|
+
# from coordinates into fractions of box vectors
|
|
140
|
+
# for faster calculation laster on
|
|
141
|
+
fractions = coord_to_fraction(diff, box)
|
|
142
|
+
# Move vectors into box
|
|
143
|
+
fractions = fractions % 1
|
|
144
|
+
# Check for each model if the box vectors are orthogonal
|
|
145
|
+
orthogonality = is_orthogonal(box)
|
|
146
|
+
disp = np.zeros(fractions.shape, dtype=diff.dtype)
|
|
147
|
+
if fractions.ndim == 1:
|
|
148
|
+
# Single atom
|
|
149
|
+
# Transform into two dimensions
|
|
150
|
+
# to match signature of '_displacement_xxx()'
|
|
151
|
+
fractions = fractions[np.newaxis, :]
|
|
152
|
+
disp = disp[np.newaxis, :]
|
|
153
|
+
if orthogonality:
|
|
154
|
+
_displacement_orthogonal_box(fractions, box, disp)
|
|
155
|
+
else:
|
|
156
|
+
_displacement_triclinic_box(
|
|
157
|
+
fractions.astype(diff.dtype, copy=False),
|
|
158
|
+
box.astype(diff.dtype, copy=False),
|
|
159
|
+
disp,
|
|
160
|
+
)
|
|
161
|
+
# Transform back
|
|
162
|
+
disp = disp[0]
|
|
163
|
+
if fractions.ndim == 2:
|
|
164
|
+
# Single model
|
|
165
|
+
if orthogonality:
|
|
166
|
+
_displacement_orthogonal_box(fractions, box, disp)
|
|
167
|
+
else:
|
|
168
|
+
_displacement_triclinic_box(
|
|
169
|
+
fractions.astype(diff.dtype, copy=False),
|
|
170
|
+
box.astype(diff.dtype, copy=False),
|
|
171
|
+
disp,
|
|
172
|
+
)
|
|
173
|
+
elif fractions.ndim == 3:
|
|
174
|
+
# Multiple models
|
|
175
|
+
# (Model count) x (Atom count)
|
|
176
|
+
for i in range(len(fractions)):
|
|
177
|
+
if box.ndim == 2:
|
|
178
|
+
box_for_model = box
|
|
179
|
+
orthogonality_for_model = orthogonality
|
|
180
|
+
elif box.ndim == 3:
|
|
181
|
+
box_for_model = box[i]
|
|
182
|
+
orthogonality_for_model = orthogonality[i]
|
|
183
|
+
else:
|
|
184
|
+
raise ValueError(f"{box.ndim} are to many box dimensions")
|
|
185
|
+
if orthogonality_for_model:
|
|
186
|
+
_displacement_orthogonal_box(fractions[i], box_for_model, disp[i])
|
|
187
|
+
else:
|
|
188
|
+
_displacement_triclinic_box(
|
|
189
|
+
fractions[i].astype(diff.dtype, copy=False),
|
|
190
|
+
box_for_model.astype(diff.dtype, copy=False),
|
|
191
|
+
disp[i],
|
|
192
|
+
)
|
|
193
|
+
else:
|
|
194
|
+
raise ValueError(f"{diff.shape} is an invalid shape for atom coordinates")
|
|
195
|
+
return disp
|
|
196
|
+
|
|
197
|
+
else:
|
|
198
|
+
return diff
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def index_displacement(*args, **kwargs):
|
|
202
|
+
"""
|
|
203
|
+
index_displacement(atoms, indices, periodic=False, box=None)
|
|
204
|
+
|
|
205
|
+
Measure the displacement, i.e. the vector difference, between pairs
|
|
206
|
+
of atoms.
|
|
207
|
+
|
|
208
|
+
The pairs refer to indices of a given atom array, whose pairwise
|
|
209
|
+
displacement should be calculated.
|
|
210
|
+
If an atom array stack is provided, the distances are calculated for
|
|
211
|
+
each frame/model.
|
|
212
|
+
In contrast to the :func:`distance()` function, this function is
|
|
213
|
+
able to take periodic boundary conditions into account.
|
|
214
|
+
|
|
215
|
+
Parameters
|
|
216
|
+
----------
|
|
217
|
+
atoms : AtomArray or AtomArrayStack or ndarray, shape=(n,3) or shape=(m,n,3)
|
|
218
|
+
The atoms the `indices` parameter refers to.
|
|
219
|
+
The pairwise distances are calculated for these pairs.
|
|
220
|
+
Alternatively, the atom coordinates can be directly provided as
|
|
221
|
+
:class:`ndarray`.
|
|
222
|
+
indices : ndarray, shape=(k,2)
|
|
223
|
+
Pairs of indices that point to `atoms`.
|
|
224
|
+
The displacement is measured from ``indices[x,0]`` to
|
|
225
|
+
``indices[x,1]``.
|
|
226
|
+
periodic : bool, optional
|
|
227
|
+
If set to true, periodic boundary conditions are taken into
|
|
228
|
+
account (minimum-image convention).
|
|
229
|
+
The `box` attribute of the `atoms` parameter is used for
|
|
230
|
+
calculation.
|
|
231
|
+
An alternative box can be provided via the `box` parameter.
|
|
232
|
+
By default, periodicity is ignored.
|
|
233
|
+
box : ndarray, shape=(3,3) or shape=(m,3,3), optional
|
|
234
|
+
If this parameter is set, the given box is used instead of the
|
|
235
|
+
`box` attribute of `atoms`.
|
|
236
|
+
|
|
237
|
+
Returns
|
|
238
|
+
-------
|
|
239
|
+
disp : ndarray, shape=(k,) or shape=(m,k)
|
|
240
|
+
The pairwise displacements.
|
|
241
|
+
If `atoms` is an atom array stack, The distances are
|
|
242
|
+
calculated for each model.
|
|
243
|
+
|
|
244
|
+
Warnings
|
|
245
|
+
--------
|
|
246
|
+
In case `periodic` is set to true and if the box is not orthorhombic
|
|
247
|
+
(at least one angle deviates from 90 degrees),
|
|
248
|
+
the calculation requires approximately 8 times as long as in the
|
|
249
|
+
orthorhombic case.
|
|
250
|
+
Furthermore, it is not guaranteed, that the lowest-distance periodic
|
|
251
|
+
copy is found for non-orthorhombic boxes; this is especially true
|
|
252
|
+
for heavily skewed boxes.
|
|
253
|
+
|
|
254
|
+
See Also
|
|
255
|
+
--------
|
|
256
|
+
displacement
|
|
257
|
+
"""
|
|
258
|
+
return _call_non_index_function(displacement, 2, *args, **kwargs)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def distance(atoms1, atoms2, box=None):
|
|
262
|
+
"""
|
|
263
|
+
Measure the euclidian distance between atoms.
|
|
264
|
+
|
|
265
|
+
Parameters
|
|
266
|
+
----------
|
|
267
|
+
atoms1, atoms2 : ndarray or Atom or AtomArray or AtomArrayStack
|
|
268
|
+
The atoms to measure the distances between.
|
|
269
|
+
The dimensions may vary.
|
|
270
|
+
Alternatively an ndarray containing the coordinates can be
|
|
271
|
+
provided.
|
|
272
|
+
Usual *NumPy* broadcasting rules apply.
|
|
273
|
+
box : ndarray, shape=(3,3) or shape=(m,3,3), optional
|
|
274
|
+
If this parameter is set, periodic boundary conditions are
|
|
275
|
+
taken into account (minimum-image convention), based on
|
|
276
|
+
the box vectors given with this parameter.
|
|
277
|
+
The shape *(m,3,3)* is only allowed, when the input coordinates
|
|
278
|
+
comprise multiple models.
|
|
279
|
+
|
|
280
|
+
Returns
|
|
281
|
+
-------
|
|
282
|
+
dist : float or ndarray
|
|
283
|
+
The atom distances.
|
|
284
|
+
The shape is equal to the shape of the input `atoms` with the
|
|
285
|
+
highest dimensionality minus the last axis.
|
|
286
|
+
|
|
287
|
+
See Also
|
|
288
|
+
--------
|
|
289
|
+
index_distance : The same calculation, but using atom indices.
|
|
290
|
+
"""
|
|
291
|
+
diff = displacement(atoms1, atoms2, box)
|
|
292
|
+
return np.sqrt(vector_dot(diff, diff))
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def index_distance(*args, **kwargs):
|
|
296
|
+
"""
|
|
297
|
+
index_distance(atoms, indices, periodic=False, box=None)
|
|
298
|
+
|
|
299
|
+
Measure the euclidian distance between pairs of atoms.
|
|
300
|
+
|
|
301
|
+
The pairs refer to indices of a given atom array, whose pairwise
|
|
302
|
+
distances should be calculated.
|
|
303
|
+
If an atom array stack is provided, the distances are calculated for
|
|
304
|
+
each frame/model.
|
|
305
|
+
In contrast to the :func:`distance()` function, this function is
|
|
306
|
+
able to take periodic boundary conditions into account.
|
|
307
|
+
|
|
308
|
+
Parameters
|
|
309
|
+
----------
|
|
310
|
+
atoms : AtomArray or AtomArrayStack or ndarray, shape=(n,3) or shape=(m,n,3)
|
|
311
|
+
The atoms the `indices` parameter refers to.
|
|
312
|
+
The pairwise distances are calculated for these pairs.
|
|
313
|
+
Alternatively, the atom coordinates can be directly provided as
|
|
314
|
+
:class:`ndarray`.
|
|
315
|
+
indices : ndarray, shape=(k,2)
|
|
316
|
+
Pairs of indices that point to `atoms`.
|
|
317
|
+
periodic : bool, optional
|
|
318
|
+
If set to true, periodic boundary conditions are taken into
|
|
319
|
+
account (minimum-image convention).
|
|
320
|
+
The `box` attribute of the `atoms` parameter is used for
|
|
321
|
+
calculation.
|
|
322
|
+
An alternative box can be provided via the `box` parameter.
|
|
323
|
+
By default, periodicity is ignored.
|
|
324
|
+
box : ndarray, shape=(3,3) or shape=(m,3,3), optional
|
|
325
|
+
If this parameter is set, the given box is used instead of the
|
|
326
|
+
`box` attribute of `atoms`.
|
|
327
|
+
|
|
328
|
+
Returns
|
|
329
|
+
-------
|
|
330
|
+
dist : ndarray, shape=(k,) or shape=(m,k)
|
|
331
|
+
The pairwise distances.
|
|
332
|
+
If `atoms` is an atom array stack, The distances are
|
|
333
|
+
calculated for each model.
|
|
334
|
+
|
|
335
|
+
Warnings
|
|
336
|
+
--------
|
|
337
|
+
In case `periodic` is set to true and if the box is not orthorhombic
|
|
338
|
+
(at least one angle deviates from 90 degrees),
|
|
339
|
+
the calculation requires approximately 8 times as long as in the
|
|
340
|
+
orthorhombic case.
|
|
341
|
+
Furthermore, it is not guaranteed, that the lowest-distance periodic
|
|
342
|
+
copy is found for non-orthorhombic boxes; this is especially true
|
|
343
|
+
for heavily skewed boxes.
|
|
344
|
+
|
|
345
|
+
See Also
|
|
346
|
+
--------
|
|
347
|
+
distance
|
|
348
|
+
"""
|
|
349
|
+
return _call_non_index_function(distance, 2, *args, **kwargs)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def angle(atoms1, atoms2, atoms3, box=None):
|
|
353
|
+
"""
|
|
354
|
+
Measure the angle between 3 atoms.
|
|
355
|
+
|
|
356
|
+
Parameters
|
|
357
|
+
----------
|
|
358
|
+
atoms1, atoms2, atoms3 : ndarray or Atom or AtomArray or AtomArrayStack
|
|
359
|
+
The atoms to measure the angle between. Alternatively an
|
|
360
|
+
ndarray containing the coordinates can be provided.
|
|
361
|
+
box : ndarray, shape=(3,3) or shape=(m,3,3), optional
|
|
362
|
+
If this parameter is set, periodic boundary conditions are
|
|
363
|
+
taken into account (minimum-image convention), based on
|
|
364
|
+
the box vectors given with this parameter.
|
|
365
|
+
The shape *(m,3,3)* is only allowed, when the input coordinates
|
|
366
|
+
comprise multiple models.
|
|
367
|
+
|
|
368
|
+
Returns
|
|
369
|
+
-------
|
|
370
|
+
angle : float or ndarray
|
|
371
|
+
The angle(s) between the atoms. The shape is equal to the shape
|
|
372
|
+
of the input `atoms` with the highest dimensionality minus the
|
|
373
|
+
last axis.
|
|
374
|
+
|
|
375
|
+
See Also
|
|
376
|
+
--------
|
|
377
|
+
index_angle : The same calculation, but using atom indices.
|
|
378
|
+
"""
|
|
379
|
+
v1 = displacement(atoms1, atoms2, box)
|
|
380
|
+
v2 = displacement(atoms3, atoms2, box)
|
|
381
|
+
norm_vector(v1)
|
|
382
|
+
norm_vector(v2)
|
|
383
|
+
return np.arccos(vector_dot(v1, v2))
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def index_angle(*args, **kwargs):
|
|
387
|
+
"""
|
|
388
|
+
index_angle(atoms, indices, periodic=False, box=None)
|
|
389
|
+
|
|
390
|
+
Measure the angle between triples of atoms.
|
|
391
|
+
|
|
392
|
+
The triples refer to indices of a given atom array, whose triplewise
|
|
393
|
+
angles should be calculated.
|
|
394
|
+
If an atom array stack is provided, the distances are calculated for
|
|
395
|
+
each frame/model.
|
|
396
|
+
|
|
397
|
+
Parameters
|
|
398
|
+
----------
|
|
399
|
+
atoms : AtomArray or AtomArrayStack or ndarray, shape=(n,3) or shape=(m,n,3)
|
|
400
|
+
The atoms the `indices` parameter refers to.
|
|
401
|
+
The triplewise distances are calculated for these pairs.
|
|
402
|
+
Alternatively, the atom coordinates can be directly provided as
|
|
403
|
+
:class:`ndarray`.
|
|
404
|
+
indices : ndarray, shape=(k,3)
|
|
405
|
+
Triples of indices that point to `atoms`.
|
|
406
|
+
periodic : bool, optional
|
|
407
|
+
If set to true, periodic boundary conditions are taken into
|
|
408
|
+
account (minimum-image convention).
|
|
409
|
+
The `box` attribute of the `atoms` parameter is used for
|
|
410
|
+
calculation.
|
|
411
|
+
An alternative box can be provided via the `box` parameter.
|
|
412
|
+
By default, periodicity is ignored.
|
|
413
|
+
box : ndarray, shape=(3,3) or shape=(m,3,3), optional
|
|
414
|
+
If this parameter is set, the given box is used instead of the
|
|
415
|
+
`box` attribute of `atoms`.
|
|
416
|
+
|
|
417
|
+
Returns
|
|
418
|
+
-------
|
|
419
|
+
angle : ndarray, shape=(k,) or shape=(m,k)
|
|
420
|
+
The triplewise angles.
|
|
421
|
+
If `atoms` is an atom array stack, The distances are
|
|
422
|
+
calculated for each model.
|
|
423
|
+
|
|
424
|
+
Warnings
|
|
425
|
+
--------
|
|
426
|
+
In case `periodic` is set to true and if the box is not orthorhombic
|
|
427
|
+
(at least one angle deviates from 90 degrees),
|
|
428
|
+
the calculation requires approximately 8 times as long as in the
|
|
429
|
+
orthorhombic case.
|
|
430
|
+
Furthermore, it is not guaranteed, that the lowest-distance periodic
|
|
431
|
+
copy is found for non-orthorhombic boxes; this is especially true
|
|
432
|
+
for heavily skewed boxes.
|
|
433
|
+
|
|
434
|
+
See Also
|
|
435
|
+
--------
|
|
436
|
+
angle
|
|
437
|
+
"""
|
|
438
|
+
return _call_non_index_function(angle, 3, *args, **kwargs)
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
def dihedral(atoms1, atoms2, atoms3, atoms4, box=None):
|
|
442
|
+
"""
|
|
443
|
+
Measure the dihedral angle between 4 atoms.
|
|
444
|
+
|
|
445
|
+
Parameters
|
|
446
|
+
----------
|
|
447
|
+
atoms1, atoms2, atoms3, atoms4 : ndarray or Atom or AtomArray or AtomArrayStack
|
|
448
|
+
The atoms to measure the dihedral angle between.
|
|
449
|
+
Alternatively an ndarray containing the coordinates can be
|
|
450
|
+
provided.
|
|
451
|
+
box : ndarray, shape=(3,3) or shape=(m,3,3), optional
|
|
452
|
+
If this parameter is set, periodic boundary conditions are
|
|
453
|
+
taken into account (minimum-image convention), based on
|
|
454
|
+
the box vectors given with this parameter.
|
|
455
|
+
The shape *(m,3,3)* is only allowed, when the input coordinates
|
|
456
|
+
comprise multiple models.
|
|
457
|
+
|
|
458
|
+
Returns
|
|
459
|
+
-------
|
|
460
|
+
dihed : float or ndarray
|
|
461
|
+
The dihedral angle(s) between the atoms. The shape is equal to
|
|
462
|
+
the shape of the input `atoms` with the highest dimensionality
|
|
463
|
+
minus the last axis.
|
|
464
|
+
|
|
465
|
+
See Also
|
|
466
|
+
--------
|
|
467
|
+
index_dihedral : The same calculation, but using atom indices.
|
|
468
|
+
dihedral_backbone : Calculate the dihedral angle along a peptide backbone.
|
|
469
|
+
"""
|
|
470
|
+
v1 = displacement(atoms1, atoms2, box)
|
|
471
|
+
v2 = displacement(atoms2, atoms3, box)
|
|
472
|
+
v3 = displacement(atoms3, atoms4, box)
|
|
473
|
+
norm_vector(v1)
|
|
474
|
+
norm_vector(v2)
|
|
475
|
+
norm_vector(v3)
|
|
476
|
+
|
|
477
|
+
n1 = np.cross(v1, v2)
|
|
478
|
+
n2 = np.cross(v2, v3)
|
|
479
|
+
|
|
480
|
+
# Calculation using atan2, to ensure the correct sign of the angle
|
|
481
|
+
x = vector_dot(n1, n2)
|
|
482
|
+
y = vector_dot(np.cross(n1, n2), v2)
|
|
483
|
+
return np.arctan2(y, x)
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
def index_dihedral(*args, **kwargs):
|
|
487
|
+
"""
|
|
488
|
+
index_dihedral(atoms, indices, periodic=False, box=None)
|
|
489
|
+
|
|
490
|
+
Measure the dihedral angle between quadruples of atoms.
|
|
491
|
+
|
|
492
|
+
The triples refer to indices of a given atom array, whose
|
|
493
|
+
quadruplewise dihedral angles should be calculated.
|
|
494
|
+
If an atom array stack is provided, the distances are calculated for
|
|
495
|
+
each frame/model.
|
|
496
|
+
|
|
497
|
+
Parameters
|
|
498
|
+
----------
|
|
499
|
+
atoms : AtomArray or AtomArrayStack or ndarray, shape=(n,3) or shape=(m,n,3)
|
|
500
|
+
The atoms the `indices` parameter refers to.
|
|
501
|
+
The quadruplewise dihedral angles are calculated for these
|
|
502
|
+
pairs.
|
|
503
|
+
Alternatively, the atom coordinates can be directly provided as
|
|
504
|
+
:class:`ndarray`.
|
|
505
|
+
indices : ndarray, shape=(k,4)
|
|
506
|
+
Quadruples of indices that point to `atoms`.
|
|
507
|
+
periodic : bool, optional
|
|
508
|
+
If set to true, periodic boundary conditions are taken into
|
|
509
|
+
account (minimum-image convention).
|
|
510
|
+
The `box` attribute of the `atoms` parameter is used for
|
|
511
|
+
calculation.
|
|
512
|
+
An alternative box can be provided via the `box` parameter.
|
|
513
|
+
By default, periodicity is ignored.
|
|
514
|
+
box : ndarray, shape=(3,3) or shape=(m,3,3), optional
|
|
515
|
+
If this parameter is set, the given box is used instead of the
|
|
516
|
+
`box` attribute of `atoms`.
|
|
517
|
+
|
|
518
|
+
Returns
|
|
519
|
+
-------
|
|
520
|
+
dihedral : ndarray, shape=(k,) or shape=(m,k)
|
|
521
|
+
The quadruplewise dihedral angles.
|
|
522
|
+
If `atoms` is an atom array stack, The distances are
|
|
523
|
+
calculated for each model.
|
|
524
|
+
|
|
525
|
+
Warnings
|
|
526
|
+
--------
|
|
527
|
+
In case `periodic` is set to true and if the box is not orthorhombic
|
|
528
|
+
(at least one angle deviates from 90 degrees),
|
|
529
|
+
the calculation requires approximately 8 times as long as in the
|
|
530
|
+
orthorhombic case.
|
|
531
|
+
Furthermore, it is not guaranteed, that the lowest-distance periodic
|
|
532
|
+
copy is found for non-orthorhombic boxes; this is especially true
|
|
533
|
+
for heavily skewed boxes.
|
|
534
|
+
|
|
535
|
+
See Also
|
|
536
|
+
--------
|
|
537
|
+
dihedral
|
|
538
|
+
dihedral_backbone
|
|
539
|
+
"""
|
|
540
|
+
return _call_non_index_function(dihedral, 4, *args, **kwargs)
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
def dihedral_backbone(atom_array):
|
|
544
|
+
"""
|
|
545
|
+
Measure the characteristic backbone dihedral angles of a chain.
|
|
546
|
+
|
|
547
|
+
Parameters
|
|
548
|
+
----------
|
|
549
|
+
atom_array : AtomArray or AtomArrayStack
|
|
550
|
+
The protein structure to measure the dihedral angles for.
|
|
551
|
+
For missing backbone atoms the corresponding angles are `NaN`.
|
|
552
|
+
|
|
553
|
+
Returns
|
|
554
|
+
-------
|
|
555
|
+
phi, psi, omega : ndarray, shape=(m,n) or shape=(n,), dtype=float
|
|
556
|
+
An array containing the 3 backbone dihedral angles for every CA atom.
|
|
557
|
+
`phi` is not defined at the N-terminus, `psi` and `omega` are not defined at the
|
|
558
|
+
C-terminus.
|
|
559
|
+
In these places the arrays have *NaN* values.
|
|
560
|
+
If an :class:`AtomArrayStack` is given, the output angles are 2-dimensional,
|
|
561
|
+
the first dimension corresponds to the model number.
|
|
562
|
+
"""
|
|
563
|
+
amino_acid_mask = filter_amino_acids(atom_array)
|
|
564
|
+
|
|
565
|
+
# Coordinates for dihedral angle calculation
|
|
566
|
+
coord_n, coord_ca, coord_c = coord_for_atom_name_per_residue(
|
|
567
|
+
atom_array,
|
|
568
|
+
("N", "CA", "C"),
|
|
569
|
+
amino_acid_mask,
|
|
570
|
+
)
|
|
571
|
+
n_residues = coord_n.shape[-2]
|
|
572
|
+
|
|
573
|
+
# Coordinates for dihedral angle calculation
|
|
574
|
+
# Dim 0: Model index (only for atom array stacks)
|
|
575
|
+
# Dim 1: Angle index
|
|
576
|
+
# Dim 2: X, Y, Z coordinates
|
|
577
|
+
# Dim 3: Atoms involved in dihedral angle
|
|
578
|
+
if isinstance(atom_array, AtomArray):
|
|
579
|
+
angle_coord_shape: tuple[int, ...] = (n_residues, 3, 4)
|
|
580
|
+
elif isinstance(atom_array, AtomArrayStack):
|
|
581
|
+
angle_coord_shape = (atom_array.stack_depth(), n_residues, 3, 4)
|
|
582
|
+
coord_for_phi = np.full(angle_coord_shape, np.nan, dtype=np.float32)
|
|
583
|
+
coord_for_psi = np.full(angle_coord_shape, np.nan, dtype=np.float32)
|
|
584
|
+
coord_for_omg = np.full(angle_coord_shape, np.nan, dtype=np.float32)
|
|
585
|
+
|
|
586
|
+
# fmt: off
|
|
587
|
+
coord_for_phi[..., 1:, :, 0] = coord_c[..., 0:-1, :]
|
|
588
|
+
coord_for_phi[..., 1:, :, 1] = coord_n[..., 1:, :]
|
|
589
|
+
coord_for_phi[..., 1:, :, 2] = coord_ca[..., 1:, :]
|
|
590
|
+
coord_for_phi[..., 1:, :, 3] = coord_c[..., 1:, :]
|
|
591
|
+
|
|
592
|
+
coord_for_psi[..., 0:-1, :, 0] = coord_n[..., 0:-1, :]
|
|
593
|
+
coord_for_psi[..., 0:-1, :, 1] = coord_ca[..., 0:-1, :]
|
|
594
|
+
coord_for_psi[..., 0:-1, :, 2] = coord_c[..., 0:-1, :]
|
|
595
|
+
coord_for_psi[..., 0:-1, :, 3] = coord_n[..., 1:, :]
|
|
596
|
+
|
|
597
|
+
coord_for_omg[..., 0:-1, :, 0] = coord_ca[..., 0:-1, :]
|
|
598
|
+
coord_for_omg[..., 0:-1, :, 1] = coord_c[..., 0:-1, :]
|
|
599
|
+
coord_for_omg[..., 0:-1, :, 2] = coord_n[..., 1:, :]
|
|
600
|
+
coord_for_omg[..., 0:-1, :, 3] = coord_ca[..., 1:, :]
|
|
601
|
+
# fmt: on
|
|
602
|
+
|
|
603
|
+
phi = dihedral(
|
|
604
|
+
coord_for_phi[..., 0],
|
|
605
|
+
coord_for_phi[..., 1],
|
|
606
|
+
coord_for_phi[..., 2],
|
|
607
|
+
coord_for_phi[..., 3],
|
|
608
|
+
)
|
|
609
|
+
psi = dihedral(
|
|
610
|
+
coord_for_psi[..., 0],
|
|
611
|
+
coord_for_psi[..., 1],
|
|
612
|
+
coord_for_psi[..., 2],
|
|
613
|
+
coord_for_psi[..., 3],
|
|
614
|
+
)
|
|
615
|
+
omg = dihedral(
|
|
616
|
+
coord_for_omg[..., 0],
|
|
617
|
+
coord_for_omg[..., 1],
|
|
618
|
+
coord_for_omg[..., 2],
|
|
619
|
+
coord_for_omg[..., 3],
|
|
620
|
+
)
|
|
621
|
+
|
|
622
|
+
return phi, psi, omg
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
def dihedral_side_chain(atoms):
|
|
626
|
+
r"""
|
|
627
|
+
Measure the side chain :math:`\chi` dihedral angles of amino acid residues.
|
|
628
|
+
|
|
629
|
+
Parameters
|
|
630
|
+
----------
|
|
631
|
+
atoms : AtomArray or AtomArrayStack
|
|
632
|
+
The protein structure to measure the side chain dihedral angles for.
|
|
633
|
+
|
|
634
|
+
Returns
|
|
635
|
+
-------
|
|
636
|
+
chi : ndarray, shape=(m, n, 4) or shape=(n, 4), dtype=float
|
|
637
|
+
An array containing the up to four side chain dihedral angles for every
|
|
638
|
+
amino acid residue.
|
|
639
|
+
Trailing :math:`\chi` angles that are not defined for an amino acid are filled
|
|
640
|
+
with :math:`NaN` values.
|
|
641
|
+
The same is True for all residues that are not canonical amino acids.
|
|
642
|
+
|
|
643
|
+
Notes
|
|
644
|
+
-----
|
|
645
|
+
By convention, the :math:`\chi_2` angle of leucine is defined using ``CD1``
|
|
646
|
+
instead of ``CD2``.
|
|
647
|
+
|
|
648
|
+
Examples
|
|
649
|
+
--------
|
|
650
|
+
|
|
651
|
+
>>> res_ids, res_names = get_residues(atom_array)
|
|
652
|
+
>>> dihedrals = dihedral_side_chain(atom_array)
|
|
653
|
+
>>> for res_id, res_name, dihedrals in zip(res_ids, res_names, dihedrals):
|
|
654
|
+
... print(f"{res_name.capitalize()}{res_id:<2d}:", dihedrals)
|
|
655
|
+
Asn1 : [-1.180 -0.066 nan nan]
|
|
656
|
+
Leu2 : [0.923 1.866 nan nan]
|
|
657
|
+
Tyr3 : [-2.593 -1.487 nan nan]
|
|
658
|
+
Ile4 : [-0.781 -0.972 nan nan]
|
|
659
|
+
Gln5 : [-2.557 1.410 -1.776 nan]
|
|
660
|
+
Trp6 : [3.117 1.372 nan nan]
|
|
661
|
+
Leu7 : [-1.33 3.08 nan nan]
|
|
662
|
+
Lys8 : [ 1.320 1.734 3.076 -2.022]
|
|
663
|
+
Asp9 : [-1.623 0.909 nan nan]
|
|
664
|
+
Gly10: [nan nan nan nan]
|
|
665
|
+
Gly11: [nan nan nan nan]
|
|
666
|
+
Pro12: [-0.331 0.539 nan nan]
|
|
667
|
+
Ser13: [-1.067 nan nan nan]
|
|
668
|
+
Ser14: [-2.514 nan nan nan]
|
|
669
|
+
Gly15: [nan nan nan nan]
|
|
670
|
+
Arg16: [ 1.032 -3.063 1.541 -1.568]
|
|
671
|
+
Pro17: [ 0.522 -0.601 nan nan]
|
|
672
|
+
Pro18: [ 0.475 -0.577 nan nan]
|
|
673
|
+
Pro19: [ 0.561 -0.602 nan nan]
|
|
674
|
+
Ser20: [-1.055 nan nan nan]
|
|
675
|
+
"""
|
|
676
|
+
is_multi_model = isinstance(atoms, AtomArrayStack)
|
|
677
|
+
|
|
678
|
+
chi_atoms = _all_chi_atoms()
|
|
679
|
+
res_names = atoms.res_name[get_residue_starts(atoms)]
|
|
680
|
+
chi_atom_coord = coord_for_atom_name_per_residue(
|
|
681
|
+
atoms, chi_atoms, filter_canonical_amino_acids(atoms)
|
|
682
|
+
)
|
|
683
|
+
chi_atoms_to_coord_index = {atom_name: i for i, atom_name in enumerate(chi_atoms)}
|
|
684
|
+
|
|
685
|
+
if is_multi_model:
|
|
686
|
+
shape = (atoms.stack_depth(), len(res_names), 4)
|
|
687
|
+
else:
|
|
688
|
+
shape = (len(res_names), 4)
|
|
689
|
+
chi_angles = np.full(shape, np.nan, dtype=np.float32)
|
|
690
|
+
for res_name, chi_atom_names_for_all_angles in _CHI_ATOMS.items():
|
|
691
|
+
res_mask = res_names == res_name
|
|
692
|
+
for chi_i, chi_atom_names in enumerate(chi_atom_names_for_all_angles):
|
|
693
|
+
dihedrals = dihedral(
|
|
694
|
+
chi_atom_coord[
|
|
695
|
+
chi_atoms_to_coord_index[chi_atom_names[0]], ..., res_mask, :
|
|
696
|
+
],
|
|
697
|
+
chi_atom_coord[
|
|
698
|
+
chi_atoms_to_coord_index[chi_atom_names[1]], ..., res_mask, :
|
|
699
|
+
],
|
|
700
|
+
chi_atom_coord[
|
|
701
|
+
chi_atoms_to_coord_index[chi_atom_names[2]], ..., res_mask, :
|
|
702
|
+
],
|
|
703
|
+
chi_atom_coord[
|
|
704
|
+
chi_atoms_to_coord_index[chi_atom_names[3]], ..., res_mask, :
|
|
705
|
+
],
|
|
706
|
+
)
|
|
707
|
+
if is_multi_model:
|
|
708
|
+
# Swap dimensions due to NumPy's behavior when using advanced indexing
|
|
709
|
+
# (https://numpy.org/devdocs/user/basics.indexing.html#combining-advanced-and-basic-indexing)
|
|
710
|
+
dihedrals = dihedrals.T
|
|
711
|
+
chi_angles[..., res_mask, chi_i] = dihedrals
|
|
712
|
+
return chi_angles
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
def centroid(atoms):
|
|
716
|
+
"""
|
|
717
|
+
Measure the centroid of a structure.
|
|
718
|
+
|
|
719
|
+
Parameters
|
|
720
|
+
----------
|
|
721
|
+
atoms : ndarray or AtomArray or AtomArrayStack
|
|
722
|
+
The structures to determine the centroid from.
|
|
723
|
+
Alternatively an ndarray containing the coordinates can be
|
|
724
|
+
provided.
|
|
725
|
+
|
|
726
|
+
Returns
|
|
727
|
+
-------
|
|
728
|
+
centroid : float or ndarray
|
|
729
|
+
The centroid of the structure(s). :class:`ndarray` is returned when
|
|
730
|
+
an :class:`AtomArrayStack` is given (centroid for each model).
|
|
731
|
+
"""
|
|
732
|
+
return np.mean(coord(atoms), axis=-2)
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
def _call_non_index_function(
|
|
736
|
+
function, expected_amount, atoms, indices, periodic=False, box=None
|
|
737
|
+
):
|
|
738
|
+
"""
|
|
739
|
+
Call an `xxx()` function based on the parameters given to a
|
|
740
|
+
`index_xxx()` function.
|
|
741
|
+
"""
|
|
742
|
+
if indices.shape[-1] != expected_amount:
|
|
743
|
+
raise ValueError(
|
|
744
|
+
f"Expected length {expected_amount} in the last dimension "
|
|
745
|
+
f"of the indices, but got length {indices.shape[-1]}"
|
|
746
|
+
)
|
|
747
|
+
coord_list = []
|
|
748
|
+
for i in range(expected_amount):
|
|
749
|
+
coord_list.append(coord(atoms)[..., indices[:, i], :])
|
|
750
|
+
if periodic:
|
|
751
|
+
if box is None:
|
|
752
|
+
if isinstance(atoms, (AtomArray, AtomArrayStack)):
|
|
753
|
+
box = atoms.box
|
|
754
|
+
else:
|
|
755
|
+
raise ValueError(
|
|
756
|
+
"If `atoms` are coordinates, the box must be set explicitly"
|
|
757
|
+
)
|
|
758
|
+
else:
|
|
759
|
+
box = None
|
|
760
|
+
return function(*coord_list, box)
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
def _displacement_orthogonal_box(fractions, box, disp):
|
|
764
|
+
"""
|
|
765
|
+
Fill in the PBC-aware displacement vector for non-PBC-aware
|
|
766
|
+
displacements given as fractions of given box vectors.
|
|
767
|
+
"""
|
|
768
|
+
# Fraction components are guaranteed to be positive
|
|
769
|
+
# Use fraction vector components with lower absolute
|
|
770
|
+
# -> new_vec[i] = vec[i] - 1 if vec[i] > 0.5 else vec[i]
|
|
771
|
+
fractions[fractions > 0.5] -= 1
|
|
772
|
+
disp[:] = fraction_to_coord(fractions, box)
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
def _displacement_triclinic_box(fractions, box, disp):
|
|
776
|
+
"""
|
|
777
|
+
Fill in the PBC-aware displacement vector for non-PBC-aware
|
|
778
|
+
displacements given as fractions of given box vectors.
|
|
779
|
+
"""
|
|
780
|
+
diffs = fraction_to_coord(fractions, box)
|
|
781
|
+
# Fraction components are guaranteed to be positive
|
|
782
|
+
# Test all 3 fraction vector components
|
|
783
|
+
# with positive and negative sign
|
|
784
|
+
# (i,j,k in {-1, 0})
|
|
785
|
+
# Hence, 8 periodic copies are tested
|
|
786
|
+
periodic_shift = []
|
|
787
|
+
for i in range(-1, 1):
|
|
788
|
+
for j in range(-1, 1):
|
|
789
|
+
for k in range(-1, 1):
|
|
790
|
+
x = i * box[0, 0] + j * box[1, 0] + k * box[2, 0]
|
|
791
|
+
y = i * box[0, 1] + j * box[1, 1] + k * box[2, 1]
|
|
792
|
+
z = i * box[0, 2] + j * box[1, 2] + k * box[2, 2]
|
|
793
|
+
periodic_shift.append([x, y, z])
|
|
794
|
+
periodic_shift = np.array(periodic_shift, dtype=disp.dtype)
|
|
795
|
+
# Create 8 periodically shifted variants for each atom
|
|
796
|
+
shifted_diffs = diffs[:, np.newaxis, :] + periodic_shift[np.newaxis, :, :]
|
|
797
|
+
# Find for each atom the periodically shifted variant with lowest
|
|
798
|
+
# distance
|
|
799
|
+
# Lowest squared distance -> lowest distance
|
|
800
|
+
sq_distance = vector_dot(shifted_diffs, shifted_diffs)
|
|
801
|
+
# for each given non-PBC-aware displacement find the PBC-aware
|
|
802
|
+
# displacement with the lowest distance
|
|
803
|
+
disp[:] = shifted_diffs[
|
|
804
|
+
np.arange(len(shifted_diffs)), np.argmin(sq_distance, axis=1)
|
|
805
|
+
]
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
@functools.cache
|
|
809
|
+
def _all_chi_atoms():
|
|
810
|
+
"""
|
|
811
|
+
Get the names of the atoms participating in any chi angle.
|
|
812
|
+
"""
|
|
813
|
+
atom_names = set()
|
|
814
|
+
for angles in _CHI_ATOMS.values():
|
|
815
|
+
for angle in angles:
|
|
816
|
+
atom_names.update(angle)
|
|
817
|
+
return sorted(atom_names)
|