biotite 0.41.1__cp310-cp310-macosx_10_16_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 +19 -0
- biotite/application/__init__.py +43 -0
- biotite/application/application.py +265 -0
- biotite/application/autodock/__init__.py +12 -0
- biotite/application/autodock/app.py +505 -0
- biotite/application/blast/__init__.py +14 -0
- biotite/application/blast/alignment.py +83 -0
- biotite/application/blast/webapp.py +421 -0
- biotite/application/clustalo/__init__.py +12 -0
- biotite/application/clustalo/app.py +238 -0
- biotite/application/dssp/__init__.py +12 -0
- biotite/application/dssp/app.py +152 -0
- biotite/application/localapp.py +306 -0
- biotite/application/mafft/__init__.py +12 -0
- biotite/application/mafft/app.py +122 -0
- biotite/application/msaapp.py +374 -0
- biotite/application/muscle/__init__.py +13 -0
- biotite/application/muscle/app3.py +254 -0
- biotite/application/muscle/app5.py +171 -0
- biotite/application/sra/__init__.py +18 -0
- biotite/application/sra/app.py +456 -0
- biotite/application/tantan/__init__.py +12 -0
- biotite/application/tantan/app.py +222 -0
- biotite/application/util.py +59 -0
- biotite/application/viennarna/__init__.py +18 -0
- biotite/application/viennarna/rnaalifold.py +304 -0
- biotite/application/viennarna/rnafold.py +269 -0
- biotite/application/viennarna/rnaplot.py +187 -0
- biotite/application/viennarna/util.py +72 -0
- biotite/application/webapp.py +77 -0
- biotite/copyable.py +71 -0
- biotite/database/__init__.py +23 -0
- biotite/database/entrez/__init__.py +15 -0
- biotite/database/entrez/check.py +61 -0
- biotite/database/entrez/dbnames.py +89 -0
- biotite/database/entrez/download.py +223 -0
- biotite/database/entrez/key.py +44 -0
- biotite/database/entrez/query.py +223 -0
- biotite/database/error.py +15 -0
- biotite/database/pubchem/__init__.py +21 -0
- biotite/database/pubchem/download.py +260 -0
- biotite/database/pubchem/error.py +20 -0
- biotite/database/pubchem/query.py +827 -0
- biotite/database/pubchem/throttle.py +99 -0
- biotite/database/rcsb/__init__.py +13 -0
- biotite/database/rcsb/download.py +167 -0
- biotite/database/rcsb/query.py +959 -0
- biotite/database/uniprot/__init__.py +13 -0
- biotite/database/uniprot/check.py +32 -0
- biotite/database/uniprot/download.py +134 -0
- biotite/database/uniprot/query.py +209 -0
- biotite/file.py +251 -0
- biotite/sequence/__init__.py +73 -0
- biotite/sequence/align/__init__.py +49 -0
- biotite/sequence/align/alignment.py +658 -0
- biotite/sequence/align/banded.cpython-310-darwin.so +0 -0
- biotite/sequence/align/banded.pyx +652 -0
- biotite/sequence/align/buckets.py +69 -0
- biotite/sequence/align/cigar.py +434 -0
- biotite/sequence/align/kmeralphabet.cpython-310-darwin.so +0 -0
- biotite/sequence/align/kmeralphabet.pyx +574 -0
- biotite/sequence/align/kmersimilarity.cpython-310-darwin.so +0 -0
- biotite/sequence/align/kmersimilarity.pyx +233 -0
- biotite/sequence/align/kmertable.cpython-310-darwin.so +0 -0
- biotite/sequence/align/kmertable.pyx +3400 -0
- biotite/sequence/align/localgapped.cpython-310-darwin.so +0 -0
- biotite/sequence/align/localgapped.pyx +892 -0
- biotite/sequence/align/localungapped.cpython-310-darwin.so +0 -0
- biotite/sequence/align/localungapped.pyx +279 -0
- biotite/sequence/align/matrix.py +405 -0
- biotite/sequence/align/matrix_data/BLOSUM100.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM30.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM35.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM40.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM45.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM50.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM50_13p.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM50_14.3.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM50_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM55.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM60.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM62.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM62_13p.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM62_14.3.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM62_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/BLOSUM65.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM70.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM75.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM80.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM85.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUM90.mat +31 -0
- biotite/sequence/align/matrix_data/BLOSUMN.mat +31 -0
- biotite/sequence/align/matrix_data/CorBLOSUM49_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/CorBLOSUM57_13p.mat +25 -0
- biotite/sequence/align/matrix_data/CorBLOSUM57_14.3.mat +25 -0
- biotite/sequence/align/matrix_data/CorBLOSUM61_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/CorBLOSUM66_13p.mat +25 -0
- biotite/sequence/align/matrix_data/CorBLOSUM67_14.3.mat +25 -0
- biotite/sequence/align/matrix_data/DAYHOFF.mat +32 -0
- biotite/sequence/align/matrix_data/GONNET.mat +26 -0
- biotite/sequence/align/matrix_data/IDENTITY.mat +25 -0
- biotite/sequence/align/matrix_data/MATCH.mat +25 -0
- biotite/sequence/align/matrix_data/NUC.mat +25 -0
- biotite/sequence/align/matrix_data/PAM10.mat +34 -0
- biotite/sequence/align/matrix_data/PAM100.mat +34 -0
- biotite/sequence/align/matrix_data/PAM110.mat +34 -0
- biotite/sequence/align/matrix_data/PAM120.mat +34 -0
- biotite/sequence/align/matrix_data/PAM130.mat +34 -0
- biotite/sequence/align/matrix_data/PAM140.mat +34 -0
- biotite/sequence/align/matrix_data/PAM150.mat +34 -0
- biotite/sequence/align/matrix_data/PAM160.mat +34 -0
- biotite/sequence/align/matrix_data/PAM170.mat +34 -0
- biotite/sequence/align/matrix_data/PAM180.mat +34 -0
- biotite/sequence/align/matrix_data/PAM190.mat +34 -0
- biotite/sequence/align/matrix_data/PAM20.mat +34 -0
- biotite/sequence/align/matrix_data/PAM200.mat +34 -0
- biotite/sequence/align/matrix_data/PAM210.mat +34 -0
- biotite/sequence/align/matrix_data/PAM220.mat +34 -0
- biotite/sequence/align/matrix_data/PAM230.mat +34 -0
- biotite/sequence/align/matrix_data/PAM240.mat +34 -0
- biotite/sequence/align/matrix_data/PAM250.mat +34 -0
- biotite/sequence/align/matrix_data/PAM260.mat +34 -0
- biotite/sequence/align/matrix_data/PAM270.mat +34 -0
- biotite/sequence/align/matrix_data/PAM280.mat +34 -0
- biotite/sequence/align/matrix_data/PAM290.mat +34 -0
- biotite/sequence/align/matrix_data/PAM30.mat +34 -0
- biotite/sequence/align/matrix_data/PAM300.mat +34 -0
- biotite/sequence/align/matrix_data/PAM310.mat +34 -0
- biotite/sequence/align/matrix_data/PAM320.mat +34 -0
- biotite/sequence/align/matrix_data/PAM330.mat +34 -0
- biotite/sequence/align/matrix_data/PAM340.mat +34 -0
- biotite/sequence/align/matrix_data/PAM350.mat +34 -0
- biotite/sequence/align/matrix_data/PAM360.mat +34 -0
- biotite/sequence/align/matrix_data/PAM370.mat +34 -0
- biotite/sequence/align/matrix_data/PAM380.mat +34 -0
- biotite/sequence/align/matrix_data/PAM390.mat +34 -0
- biotite/sequence/align/matrix_data/PAM40.mat +34 -0
- biotite/sequence/align/matrix_data/PAM400.mat +34 -0
- biotite/sequence/align/matrix_data/PAM410.mat +34 -0
- biotite/sequence/align/matrix_data/PAM420.mat +34 -0
- biotite/sequence/align/matrix_data/PAM430.mat +34 -0
- biotite/sequence/align/matrix_data/PAM440.mat +34 -0
- biotite/sequence/align/matrix_data/PAM450.mat +34 -0
- biotite/sequence/align/matrix_data/PAM460.mat +34 -0
- biotite/sequence/align/matrix_data/PAM470.mat +34 -0
- biotite/sequence/align/matrix_data/PAM480.mat +34 -0
- biotite/sequence/align/matrix_data/PAM490.mat +34 -0
- biotite/sequence/align/matrix_data/PAM50.mat +34 -0
- biotite/sequence/align/matrix_data/PAM500.mat +34 -0
- biotite/sequence/align/matrix_data/PAM60.mat +34 -0
- biotite/sequence/align/matrix_data/PAM70.mat +34 -0
- biotite/sequence/align/matrix_data/PAM80.mat +34 -0
- biotite/sequence/align/matrix_data/PAM90.mat +34 -0
- biotite/sequence/align/matrix_data/RBLOSUM52_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/RBLOSUM59_13p.mat +25 -0
- biotite/sequence/align/matrix_data/RBLOSUM59_14.3.mat +25 -0
- biotite/sequence/align/matrix_data/RBLOSUM64_5.0.mat +25 -0
- biotite/sequence/align/matrix_data/RBLOSUM69_13p.mat +25 -0
- biotite/sequence/align/matrix_data/RBLOSUM69_14.3.mat +25 -0
- biotite/sequence/align/multiple.cpython-310-darwin.so +0 -0
- biotite/sequence/align/multiple.pyx +620 -0
- biotite/sequence/align/pairwise.cpython-310-darwin.so +0 -0
- biotite/sequence/align/pairwise.pyx +587 -0
- biotite/sequence/align/permutation.cpython-310-darwin.so +0 -0
- biotite/sequence/align/permutation.pyx +305 -0
- biotite/sequence/align/primes.txt +821 -0
- biotite/sequence/align/selector.cpython-310-darwin.so +0 -0
- biotite/sequence/align/selector.pyx +956 -0
- biotite/sequence/align/statistics.py +265 -0
- biotite/sequence/align/tracetable.cpython-310-darwin.so +0 -0
- biotite/sequence/align/tracetable.pxd +64 -0
- biotite/sequence/align/tracetable.pyx +370 -0
- biotite/sequence/alphabet.py +566 -0
- biotite/sequence/annotation.py +829 -0
- biotite/sequence/codec.cpython-310-darwin.so +0 -0
- biotite/sequence/codec.pyx +155 -0
- biotite/sequence/codon.py +466 -0
- biotite/sequence/codon_tables.txt +202 -0
- biotite/sequence/graphics/__init__.py +33 -0
- biotite/sequence/graphics/alignment.py +1034 -0
- biotite/sequence/graphics/color_schemes/autumn.json +51 -0
- biotite/sequence/graphics/color_schemes/blossom.json +51 -0
- biotite/sequence/graphics/color_schemes/clustalx_dna.json +11 -0
- biotite/sequence/graphics/color_schemes/clustalx_protein.json +28 -0
- biotite/sequence/graphics/color_schemes/flower.json +51 -0
- biotite/sequence/graphics/color_schemes/jalview_buried.json +31 -0
- biotite/sequence/graphics/color_schemes/jalview_hydrophobicity.json +31 -0
- biotite/sequence/graphics/color_schemes/jalview_prop_helix.json +31 -0
- biotite/sequence/graphics/color_schemes/jalview_prop_strand.json +31 -0
- biotite/sequence/graphics/color_schemes/jalview_prop_turn.json +31 -0
- biotite/sequence/graphics/color_schemes/jalview_taylor.json +28 -0
- biotite/sequence/graphics/color_schemes/jalview_zappo.json +28 -0
- biotite/sequence/graphics/color_schemes/ocean.json +51 -0
- biotite/sequence/graphics/color_schemes/pb_flower.json +39 -0
- biotite/sequence/graphics/color_schemes/rainbow_dna.json +11 -0
- biotite/sequence/graphics/color_schemes/rainbow_protein.json +30 -0
- biotite/sequence/graphics/color_schemes/spring.json +51 -0
- biotite/sequence/graphics/color_schemes/sunset.json +51 -0
- biotite/sequence/graphics/color_schemes/wither.json +51 -0
- biotite/sequence/graphics/colorschemes.py +139 -0
- biotite/sequence/graphics/dendrogram.py +184 -0
- biotite/sequence/graphics/features.py +510 -0
- biotite/sequence/graphics/logo.py +110 -0
- biotite/sequence/graphics/plasmid.py +661 -0
- biotite/sequence/io/__init__.py +12 -0
- biotite/sequence/io/fasta/__init__.py +22 -0
- biotite/sequence/io/fasta/convert.py +273 -0
- biotite/sequence/io/fasta/file.py +278 -0
- biotite/sequence/io/fastq/__init__.py +19 -0
- biotite/sequence/io/fastq/convert.py +120 -0
- biotite/sequence/io/fastq/file.py +551 -0
- biotite/sequence/io/genbank/__init__.py +17 -0
- biotite/sequence/io/genbank/annotation.py +277 -0
- biotite/sequence/io/genbank/file.py +575 -0
- biotite/sequence/io/genbank/metadata.py +324 -0
- biotite/sequence/io/genbank/sequence.py +172 -0
- biotite/sequence/io/general.py +192 -0
- biotite/sequence/io/gff/__init__.py +26 -0
- biotite/sequence/io/gff/convert.py +133 -0
- biotite/sequence/io/gff/file.py +434 -0
- biotite/sequence/phylo/__init__.py +36 -0
- biotite/sequence/phylo/nj.cpython-310-darwin.so +0 -0
- biotite/sequence/phylo/nj.pyx +221 -0
- biotite/sequence/phylo/tree.cpython-310-darwin.so +0 -0
- biotite/sequence/phylo/tree.pyx +1169 -0
- biotite/sequence/phylo/upgma.cpython-310-darwin.so +0 -0
- biotite/sequence/phylo/upgma.pyx +164 -0
- biotite/sequence/profile.py +456 -0
- biotite/sequence/search.py +116 -0
- biotite/sequence/seqtypes.py +556 -0
- biotite/sequence/sequence.py +374 -0
- biotite/structure/__init__.py +132 -0
- biotite/structure/atoms.py +1455 -0
- biotite/structure/basepairs.py +1415 -0
- biotite/structure/bonds.cpython-310-darwin.so +0 -0
- biotite/structure/bonds.pyx +1933 -0
- biotite/structure/box.py +592 -0
- biotite/structure/celllist.cpython-310-darwin.so +0 -0
- biotite/structure/celllist.pyx +849 -0
- biotite/structure/chains.py +298 -0
- biotite/structure/charges.cpython-310-darwin.so +0 -0
- biotite/structure/charges.pyx +520 -0
- biotite/structure/compare.py +274 -0
- biotite/structure/density.py +114 -0
- biotite/structure/dotbracket.py +216 -0
- biotite/structure/error.py +31 -0
- biotite/structure/filter.py +585 -0
- biotite/structure/geometry.py +697 -0
- biotite/structure/graphics/__init__.py +13 -0
- biotite/structure/graphics/atoms.py +226 -0
- biotite/structure/graphics/rna.py +282 -0
- biotite/structure/hbond.py +409 -0
- biotite/structure/info/__init__.py +25 -0
- biotite/structure/info/atom_masses.json +121 -0
- biotite/structure/info/atoms.py +82 -0
- biotite/structure/info/bonds.py +145 -0
- biotite/structure/info/ccd/README.rst +8 -0
- biotite/structure/info/ccd/amino_acids.txt +1663 -0
- biotite/structure/info/ccd/carbohydrates.txt +1135 -0
- biotite/structure/info/ccd/components.bcif +0 -0
- biotite/structure/info/ccd/nucleotides.txt +798 -0
- biotite/structure/info/ccd.py +95 -0
- biotite/structure/info/groups.py +90 -0
- biotite/structure/info/masses.py +123 -0
- biotite/structure/info/misc.py +144 -0
- biotite/structure/info/radii.py +197 -0
- biotite/structure/info/standardize.py +196 -0
- biotite/structure/integrity.py +268 -0
- biotite/structure/io/__init__.py +30 -0
- biotite/structure/io/ctab.py +72 -0
- biotite/structure/io/dcd/__init__.py +13 -0
- biotite/structure/io/dcd/file.py +65 -0
- biotite/structure/io/general.py +257 -0
- biotite/structure/io/gro/__init__.py +14 -0
- biotite/structure/io/gro/file.py +343 -0
- biotite/structure/io/mmtf/__init__.py +21 -0
- biotite/structure/io/mmtf/assembly.py +214 -0
- biotite/structure/io/mmtf/convertarray.cpython-310-darwin.so +0 -0
- biotite/structure/io/mmtf/convertarray.pyx +341 -0
- biotite/structure/io/mmtf/convertfile.cpython-310-darwin.so +0 -0
- biotite/structure/io/mmtf/convertfile.pyx +501 -0
- biotite/structure/io/mmtf/decode.cpython-310-darwin.so +0 -0
- biotite/structure/io/mmtf/decode.pyx +152 -0
- biotite/structure/io/mmtf/encode.cpython-310-darwin.so +0 -0
- biotite/structure/io/mmtf/encode.pyx +183 -0
- biotite/structure/io/mmtf/file.py +233 -0
- biotite/structure/io/mol/__init__.py +20 -0
- biotite/structure/io/mol/convert.py +115 -0
- biotite/structure/io/mol/ctab.py +414 -0
- biotite/structure/io/mol/header.py +116 -0
- biotite/structure/io/mol/mol.py +193 -0
- biotite/structure/io/mol/sdf.py +916 -0
- biotite/structure/io/netcdf/__init__.py +13 -0
- biotite/structure/io/netcdf/file.py +63 -0
- biotite/structure/io/npz/__init__.py +20 -0
- biotite/structure/io/npz/file.py +152 -0
- biotite/structure/io/pdb/__init__.py +20 -0
- biotite/structure/io/pdb/convert.py +293 -0
- biotite/structure/io/pdb/file.py +1240 -0
- biotite/structure/io/pdb/hybrid36.cpython-310-darwin.so +0 -0
- biotite/structure/io/pdb/hybrid36.pyx +242 -0
- biotite/structure/io/pdbqt/__init__.py +15 -0
- biotite/structure/io/pdbqt/convert.py +107 -0
- biotite/structure/io/pdbqt/file.py +640 -0
- biotite/structure/io/pdbx/__init__.py +23 -0
- biotite/structure/io/pdbx/bcif.py +648 -0
- biotite/structure/io/pdbx/cif.py +1032 -0
- biotite/structure/io/pdbx/component.py +246 -0
- biotite/structure/io/pdbx/convert.py +1597 -0
- biotite/structure/io/pdbx/encoding.cpython-310-darwin.so +0 -0
- biotite/structure/io/pdbx/encoding.pyx +950 -0
- biotite/structure/io/pdbx/legacy.py +267 -0
- biotite/structure/io/tng/__init__.py +13 -0
- biotite/structure/io/tng/file.py +46 -0
- biotite/structure/io/trajfile.py +710 -0
- biotite/structure/io/trr/__init__.py +13 -0
- biotite/structure/io/trr/file.py +46 -0
- biotite/structure/io/xtc/__init__.py +13 -0
- biotite/structure/io/xtc/file.py +46 -0
- biotite/structure/mechanics.py +75 -0
- biotite/structure/molecules.py +353 -0
- biotite/structure/pseudoknots.py +642 -0
- biotite/structure/rdf.py +243 -0
- biotite/structure/repair.py +253 -0
- biotite/structure/residues.py +562 -0
- biotite/structure/resutil.py +178 -0
- biotite/structure/sasa.cpython-310-darwin.so +0 -0
- biotite/structure/sasa.pyx +322 -0
- biotite/structure/sequence.py +112 -0
- biotite/structure/sse.py +327 -0
- biotite/structure/superimpose.py +727 -0
- biotite/structure/transform.py +504 -0
- biotite/structure/util.py +98 -0
- biotite/temp.py +86 -0
- biotite/version.py +16 -0
- biotite/visualize.py +251 -0
- biotite-0.41.1.dist-info/METADATA +187 -0
- biotite-0.41.1.dist-info/RECORD +340 -0
- biotite-0.41.1.dist-info/WHEEL +4 -0
- biotite-0.41.1.dist-info/licenses/LICENSE.rst +30 -0
|
@@ -0,0 +1,504 @@
|
|
|
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 different transformations#
|
|
7
|
+
that can be applied on structures.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
__name__ = "biotite.structure"
|
|
11
|
+
__author__ = "Patrick Kunzmann", "Claude J. Rogers"
|
|
12
|
+
__all__ = ["translate", "rotate", "rotate_centered", "rotate_about_axis",
|
|
13
|
+
"orient_principal_components", "align_vectors"]
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
from .geometry import centroid
|
|
17
|
+
from .error import BadStructureError
|
|
18
|
+
from .atoms import Atom, AtomArray, AtomArrayStack, coord
|
|
19
|
+
from .util import norm_vector, vector_dot, matrix_rotate
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def translate(atoms, vector):
|
|
23
|
+
"""
|
|
24
|
+
Translate the given atoms or coordinates by a given vector.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
29
|
+
The atoms of which the coordinates are transformed.
|
|
30
|
+
The coordinates can be directly provided as :class:`ndarray`.
|
|
31
|
+
vector: array-like, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
32
|
+
The translation vector :math:`(x, y, z)`.
|
|
33
|
+
|
|
34
|
+
Returns
|
|
35
|
+
-------
|
|
36
|
+
transformed : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
37
|
+
A copy of the input atoms or coordinates, translated by the
|
|
38
|
+
given vector.
|
|
39
|
+
"""
|
|
40
|
+
positions = coord(atoms).copy()
|
|
41
|
+
vector = np.asarray(vector)
|
|
42
|
+
|
|
43
|
+
if vector.shape[-1] != 3:
|
|
44
|
+
raise ValueError("Translation vector must contain 3 coordinates")
|
|
45
|
+
positions += vector
|
|
46
|
+
return _put_back(atoms, positions)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def rotate(atoms, angles):
|
|
50
|
+
"""
|
|
51
|
+
Rotate the given atoms or coordinates about the *x*, *y* and *z*
|
|
52
|
+
axes by given angles.
|
|
53
|
+
|
|
54
|
+
The rotations are centered at the origin and are performed
|
|
55
|
+
sequentially in the order *x*, *y*, *z*.
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
60
|
+
The atoms of which the coordinates are transformed.
|
|
61
|
+
The coordinates can be directly provided as :class:`ndarray`.
|
|
62
|
+
angles: array-like, length=3
|
|
63
|
+
The rotation angles in radians around *x*, *y* and *z*.
|
|
64
|
+
|
|
65
|
+
Returns
|
|
66
|
+
-------
|
|
67
|
+
transformed : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
68
|
+
A copy of the input atoms or coordinates, rotated by the given
|
|
69
|
+
angles.
|
|
70
|
+
|
|
71
|
+
See Also
|
|
72
|
+
--------
|
|
73
|
+
rotate_centered
|
|
74
|
+
rotate_about_axis
|
|
75
|
+
|
|
76
|
+
Examples
|
|
77
|
+
--------
|
|
78
|
+
Rotation about the *z*-axis by 90 degrees:
|
|
79
|
+
|
|
80
|
+
>>> position = np.array([2.0, 0.0, 0.0])
|
|
81
|
+
>>> rotated = rotate(position, angles=(0, 0, 0.5*np.pi))
|
|
82
|
+
>>> print(rotated)
|
|
83
|
+
[1.225e-16 2.000e+00 0.000e+00]
|
|
84
|
+
"""
|
|
85
|
+
from numpy import sin, cos
|
|
86
|
+
|
|
87
|
+
# Check if "angles" contains 3 angles for all dimensions
|
|
88
|
+
if len(angles) != 3:
|
|
89
|
+
raise ValueError("Translation vector must be container of length 3")
|
|
90
|
+
# Create rotation matrices for all 3 dimensions
|
|
91
|
+
rot_x = np.array([[ 1, 0, 0 ],
|
|
92
|
+
[ 0, cos(angles[0]), -sin(angles[0]) ],
|
|
93
|
+
[ 0, sin(angles[0]), cos(angles[0]) ]])
|
|
94
|
+
|
|
95
|
+
rot_y = np.array([[ cos(angles[1]), 0, sin(angles[1]) ],
|
|
96
|
+
[ 0, 1, 0 ],
|
|
97
|
+
[ -sin(angles[1]), 0, cos(angles[1]) ]])
|
|
98
|
+
|
|
99
|
+
rot_z = np.array([[ cos(angles[2]), -sin(angles[2]), 0 ],
|
|
100
|
+
[ sin(angles[2]), cos(angles[2]), 0 ],
|
|
101
|
+
[ 0, 0, 1 ]])
|
|
102
|
+
|
|
103
|
+
positions = coord(atoms).copy()
|
|
104
|
+
positions = matrix_rotate(positions, rot_z @ rot_y @ rot_x)
|
|
105
|
+
|
|
106
|
+
return _put_back(atoms, positions)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def rotate_centered(atoms, angles):
|
|
110
|
+
"""
|
|
111
|
+
Rotate the given atoms or coordinates about the *x*, *y* and *z*
|
|
112
|
+
axes by given angles.
|
|
113
|
+
|
|
114
|
+
The rotations are centered at the centroid of the corresponding
|
|
115
|
+
structure and are performed sequentially in the order *x*, *y*, *z*.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
120
|
+
The atoms of which the coordinates are transformed.
|
|
121
|
+
The coordinates can be directly provided as :class:`ndarray`.
|
|
122
|
+
angles: array-like, length=3
|
|
123
|
+
The rotation angles in radians around axes *x*, *y* and *z*.
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
transformed : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
128
|
+
A copy of the input atoms or coordinates, rotated by the given
|
|
129
|
+
angles.
|
|
130
|
+
|
|
131
|
+
See Also
|
|
132
|
+
--------
|
|
133
|
+
rotate
|
|
134
|
+
rotate_about_axis
|
|
135
|
+
"""
|
|
136
|
+
if len(coord(atoms).shape) == 1:
|
|
137
|
+
# Single value -> centered rotation does not change coordinates
|
|
138
|
+
return atoms.copy()
|
|
139
|
+
|
|
140
|
+
# Rotation around centroid requires moving centroid to origin
|
|
141
|
+
center = coord(centroid(atoms))
|
|
142
|
+
# 'centroid()' removes the second last dimesion
|
|
143
|
+
# -> add dimension again to ensure correct translation
|
|
144
|
+
center = center[..., np.newaxis, :]
|
|
145
|
+
translated = translate(atoms, -center)
|
|
146
|
+
rotated = rotate(translated, angles)
|
|
147
|
+
translated_back = translate(rotated, center)
|
|
148
|
+
return translated_back
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def rotate_about_axis(atoms, axis, angle, support=None):
|
|
152
|
+
"""
|
|
153
|
+
Rotate the given atoms or coordinates about a given axis by a given
|
|
154
|
+
angle.
|
|
155
|
+
|
|
156
|
+
Parameters
|
|
157
|
+
----------
|
|
158
|
+
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
159
|
+
The atoms of which the coordinates are transformed.
|
|
160
|
+
The coordinates can be directly provided as :class:`ndarray`.
|
|
161
|
+
axis : array-like, length=3
|
|
162
|
+
A vector representing the direction of the rotation axis.
|
|
163
|
+
The length of the vector is irrelevant.
|
|
164
|
+
angle : float
|
|
165
|
+
The rotation angle in radians.
|
|
166
|
+
support : array-like, length=3, optional
|
|
167
|
+
An optional support vector for the rotation axis, i.e. the
|
|
168
|
+
center of the rotation.
|
|
169
|
+
By default, the center of the rotation is at *(0,0,0)*.
|
|
170
|
+
|
|
171
|
+
Returns
|
|
172
|
+
-------
|
|
173
|
+
transformed : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
174
|
+
A copy of the input atoms or coordinates, rotated about the
|
|
175
|
+
given axis.
|
|
176
|
+
|
|
177
|
+
See Also
|
|
178
|
+
--------
|
|
179
|
+
rotate
|
|
180
|
+
rotate_centered
|
|
181
|
+
|
|
182
|
+
Examples
|
|
183
|
+
--------
|
|
184
|
+
Rotation about a custom axis on the *y*-*z*-plane by 90 degrees:
|
|
185
|
+
|
|
186
|
+
>>> position = np.array([2.0, 0.0, 0.0])
|
|
187
|
+
>>> axis = [0.0, 1.0, 1.0]
|
|
188
|
+
>>> rotated = rotate_about_axis(position, axis, angle=0.5*np.pi)
|
|
189
|
+
>>> print(rotated)
|
|
190
|
+
[ 1.225e-16 1.414e+00 -1.414e+00]
|
|
191
|
+
"""
|
|
192
|
+
positions = coord(atoms).copy()
|
|
193
|
+
if support is not None:
|
|
194
|
+
# Transform coordinates
|
|
195
|
+
# so that the axis support vector is at (0,0,0)
|
|
196
|
+
positions -= np.asarray(support)
|
|
197
|
+
|
|
198
|
+
# Normalize axis
|
|
199
|
+
axis = np.asarray(axis, dtype=np.float32).copy()
|
|
200
|
+
if np.linalg.norm(axis) == 0:
|
|
201
|
+
raise ValueError("Length of the rotation axis is 0")
|
|
202
|
+
norm_vector(axis)
|
|
203
|
+
# Save some interim values, that are used repeatedly in the
|
|
204
|
+
# rotation matrix, for clarity and to save computation time
|
|
205
|
+
sin_a = np.sin(angle)
|
|
206
|
+
cos_a = np.cos(angle)
|
|
207
|
+
icos_a = 1 - cos_a
|
|
208
|
+
x = axis[...,0]
|
|
209
|
+
y = axis[...,1]
|
|
210
|
+
z = axis[...,2]
|
|
211
|
+
# Rotation matrix is taken from
|
|
212
|
+
# https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
|
|
213
|
+
rot_matrix = np.array([
|
|
214
|
+
[ cos_a + icos_a*x**2, icos_a*x*y - z*sin_a, icos_a*x*z + y*sin_a],
|
|
215
|
+
[icos_a*x*y + z*sin_a, cos_a + icos_a*y**2, icos_a*y*z - x*sin_a],
|
|
216
|
+
[icos_a*x*z - y*sin_a, icos_a*y*z + x*sin_a, cos_a + icos_a*z**2]
|
|
217
|
+
])
|
|
218
|
+
|
|
219
|
+
# For proper rotation reshape into a maximum of 2 dimensions
|
|
220
|
+
orig_ndim = positions.ndim
|
|
221
|
+
if orig_ndim > 2:
|
|
222
|
+
orig_shape = positions.shape
|
|
223
|
+
positions = positions.reshape(-1, 3)
|
|
224
|
+
# Apply rotation
|
|
225
|
+
positions = np.dot(rot_matrix, positions.T).T
|
|
226
|
+
# Reshape back into original shape
|
|
227
|
+
if orig_ndim > 2:
|
|
228
|
+
positions = positions.reshape(*orig_shape)
|
|
229
|
+
|
|
230
|
+
if support is not None:
|
|
231
|
+
# Transform coordinates back to original support vector position
|
|
232
|
+
positions += np.asarray(support)
|
|
233
|
+
|
|
234
|
+
return _put_back(atoms, positions)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def orient_principal_components(atoms, order=None):
|
|
238
|
+
"""
|
|
239
|
+
Translate and rotate the atoms to be centered at the origin with
|
|
240
|
+
the principal axes aligned to the Cartesian axes, as specified by
|
|
241
|
+
the `order` parameter. By default, x, y, z.
|
|
242
|
+
|
|
243
|
+
By default, the resulting coordinates have the highest variance in
|
|
244
|
+
the x-axis and the lowest variance on the z-axis. Setting the `order`
|
|
245
|
+
parameter will change the direction of the highest variance.
|
|
246
|
+
For example, ``order=(2, 1, 0)`` results in highest variance along the
|
|
247
|
+
z-axis and lowest along the x-axis.
|
|
248
|
+
|
|
249
|
+
Parameters
|
|
250
|
+
----------
|
|
251
|
+
atoms : AtomArray or ndarray, shape=(n,3)
|
|
252
|
+
The atoms of which the coordinates are transformed.
|
|
253
|
+
The coordinates can be directly provided as :class:`ndarray`.
|
|
254
|
+
order : array-like, length=3
|
|
255
|
+
The order of decreasing variance. Setting `order` to ``(2, 0, 1)``
|
|
256
|
+
results in highest variance along the y-axis and lowest along
|
|
257
|
+
the x-axis. Default = ``(0, 1, 2)``.
|
|
258
|
+
|
|
259
|
+
Returns
|
|
260
|
+
-------
|
|
261
|
+
AtomArray or ndarray, shape=(n,3)
|
|
262
|
+
The atoms with coordinates centered at the orgin and aligned with
|
|
263
|
+
xyz axes.
|
|
264
|
+
|
|
265
|
+
See Also
|
|
266
|
+
--------
|
|
267
|
+
rotate_centered
|
|
268
|
+
rotate_about_axis
|
|
269
|
+
|
|
270
|
+
Examples
|
|
271
|
+
--------
|
|
272
|
+
Align principal components to xyz axes (default), or specify the order
|
|
273
|
+
of variance.
|
|
274
|
+
|
|
275
|
+
>>> print("original variance =", atom_array.coord.var(axis=0))
|
|
276
|
+
original variance = [26.517 20.009 9.325]
|
|
277
|
+
>>> moved = orient_principal_components(atom_array)
|
|
278
|
+
>>> print("moved variance =", moved.coord.var(axis=0))
|
|
279
|
+
moved variance = [28.906 18.495 8.450]
|
|
280
|
+
>>> # Note the increase in variance along the x-axis
|
|
281
|
+
>>> # Specifying the order keyword changes the orientation
|
|
282
|
+
>>> moved_z = orient_principal_components(atom_array, order=(2, 1, 0))
|
|
283
|
+
>>> print("moved (zyx) variance =", moved_z.coord.var(axis=0))
|
|
284
|
+
moved (zyx) variance = [ 8.450 18.495 28.906]
|
|
285
|
+
"""
|
|
286
|
+
# Check user input
|
|
287
|
+
coords = coord(atoms)
|
|
288
|
+
if coords.ndim != 2:
|
|
289
|
+
raise ValueError(f"Expected input shape of (n, 3), got {coords.shape}.")
|
|
290
|
+
row, col = coords.shape
|
|
291
|
+
if (row < 3) or (col != 3):
|
|
292
|
+
raise ValueError(
|
|
293
|
+
f"Expected at least 3 entries, {row} given,"
|
|
294
|
+
f" and 3 dimensions, {col} given."
|
|
295
|
+
)
|
|
296
|
+
if order is None:
|
|
297
|
+
order = np.array([0, 1, 2])
|
|
298
|
+
else:
|
|
299
|
+
order = np.asarray(order, dtype=int)
|
|
300
|
+
if order.shape != (3,):
|
|
301
|
+
raise ValueError(
|
|
302
|
+
f"Expected order to have shape (3,), not {order.shape}"
|
|
303
|
+
)
|
|
304
|
+
if not (np.sort(order) == np.arange(3)).all():
|
|
305
|
+
raise ValueError("Expected order to contain [0, 1, 2].")
|
|
306
|
+
|
|
307
|
+
# place centroid of the atoms at the origin
|
|
308
|
+
centered = coords - coords.mean(axis=0)
|
|
309
|
+
|
|
310
|
+
# iterate a few times to ensure the ideal rotation has been applied
|
|
311
|
+
identity = np.eye(3)
|
|
312
|
+
MAX_ITER = 50
|
|
313
|
+
for _ in range(MAX_ITER):
|
|
314
|
+
# PCA, W is the component matrix, s ~ explained variance
|
|
315
|
+
_, sigma, components = np.linalg.svd(centered)
|
|
316
|
+
|
|
317
|
+
# sort 1st, 2nd, 3rd pca compontents along x, y, z
|
|
318
|
+
idx = sigma.argsort()[::-1][order]
|
|
319
|
+
ident = np.eye(3)[:, idx]
|
|
320
|
+
|
|
321
|
+
# Run the Kabsch algorithm to orient principal components
|
|
322
|
+
# along the x, y, z axes
|
|
323
|
+
v, _, wt = np.linalg.svd(components.T @ ident)
|
|
324
|
+
|
|
325
|
+
if np.linalg.det(v) * np.linalg.det(wt) < -0:
|
|
326
|
+
v[:, -1] *= -1
|
|
327
|
+
# Calculate rotation matrix
|
|
328
|
+
rotation = v @ wt
|
|
329
|
+
if np.isclose(rotation, identity, atol=1e-5).all():
|
|
330
|
+
break
|
|
331
|
+
# Apply rotation, keep molecule centered on the origin
|
|
332
|
+
centered = centered @ rotation
|
|
333
|
+
return _put_back(atoms, centered)
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def align_vectors(atoms, origin_direction, target_direction,
|
|
337
|
+
origin_position=None, target_position=None):
|
|
338
|
+
"""
|
|
339
|
+
Apply a transformation to atoms or coordinates, that would transfer
|
|
340
|
+
a origin vector to a target vector.
|
|
341
|
+
|
|
342
|
+
At first the transformation (translation and rotation), that is
|
|
343
|
+
necessary to align the origin vector to the target vector is
|
|
344
|
+
calculated.
|
|
345
|
+
This means, that the application of the transformation on the
|
|
346
|
+
origin vector would give the target vector.
|
|
347
|
+
Then the same transformation is applied to the given
|
|
348
|
+
atoms/coordinates.
|
|
349
|
+
|
|
350
|
+
Parameters
|
|
351
|
+
----------
|
|
352
|
+
atoms : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
353
|
+
The atoms of which the coordinates are transformed.
|
|
354
|
+
The coordinates can be directly provided as :class:`ndarray`.
|
|
355
|
+
origin_direction, target_direction : array-like, length=3
|
|
356
|
+
The vectors representing the direction of the origin or target,
|
|
357
|
+
respectively.
|
|
358
|
+
The length of the vectors is irrelevant.
|
|
359
|
+
origin_position, target_position : array-like, length=3, optional
|
|
360
|
+
Optional support vectors for the origin or target, respectively.
|
|
361
|
+
By default, origin and target start at *(0,0,0)*.
|
|
362
|
+
|
|
363
|
+
Returns
|
|
364
|
+
-------
|
|
365
|
+
transformed : Atom or AtomArray or AtomArrayStack or ndarray, shape=(3,) or shape=(n,3) or shape=(m,n,3)
|
|
366
|
+
A copy of the input atoms or coordinates with the applied
|
|
367
|
+
transformation.
|
|
368
|
+
|
|
369
|
+
See Also
|
|
370
|
+
--------
|
|
371
|
+
rotate
|
|
372
|
+
rotate_centered
|
|
373
|
+
|
|
374
|
+
Examples
|
|
375
|
+
--------
|
|
376
|
+
Align two different residues at their CA-CB bond, i.e. the CA and CB
|
|
377
|
+
position of both residues should be equal:
|
|
378
|
+
|
|
379
|
+
>>> first_residue = atom_array[atom_array.res_id == 1]
|
|
380
|
+
>>> second_residue = atom_array[atom_array.res_id == 2]
|
|
381
|
+
>>> first_residue_ca = first_residue[first_residue.atom_name == "CA"]
|
|
382
|
+
>>> first_residue_cb = first_residue[first_residue.atom_name == "CB"]
|
|
383
|
+
>>> second_residue_ca = second_residue[second_residue.atom_name == "CA"]
|
|
384
|
+
>>> second_residue_cb = second_residue[second_residue.atom_name == "CB"]
|
|
385
|
+
>>> first_residue = align_vectors(
|
|
386
|
+
... first_residue,
|
|
387
|
+
... origin_direction = first_residue_cb.coord - first_residue_ca.coord,
|
|
388
|
+
... target_direction = second_residue_cb.coord - second_residue_ca.coord,
|
|
389
|
+
... origin_position = first_residue_ca.coord,
|
|
390
|
+
... target_position = second_residue_ca.coord
|
|
391
|
+
... )
|
|
392
|
+
>>> # The CA and CB coordinates of both residues are now almost equal
|
|
393
|
+
>>> print(first_residue)
|
|
394
|
+
A 1 ASN N N -5.549 3.788 -1.125
|
|
395
|
+
A 1 ASN CA C -4.923 4.002 -2.452
|
|
396
|
+
A 1 ASN C C -3.877 2.949 -2.808
|
|
397
|
+
A 1 ASN O O -4.051 2.292 -3.825
|
|
398
|
+
A 1 ASN CB C -4.413 5.445 -2.618
|
|
399
|
+
A 1 ASN CG C -5.593 6.413 -2.670
|
|
400
|
+
A 1 ASN OD1 O -6.738 5.988 -2.651
|
|
401
|
+
A 1 ASN ND2 N -5.362 7.711 -2.695
|
|
402
|
+
A 1 ASN H1 H -5.854 2.830 -1.023
|
|
403
|
+
A 1 ASN H2 H -4.902 4.017 -0.382
|
|
404
|
+
A 1 ASN H3 H -6.357 4.397 -1.047
|
|
405
|
+
A 1 ASN HA H -5.711 3.870 -3.198
|
|
406
|
+
A 1 ASN HB2 H -3.781 5.697 -1.788
|
|
407
|
+
A 1 ASN HB3 H -3.860 5.526 -3.556
|
|
408
|
+
A 1 ASN HD21 H -4.440 8.115 -2.680
|
|
409
|
+
A 1 ASN HD22 H -6.190 8.284 -2.750
|
|
410
|
+
>>> print(second_residue)
|
|
411
|
+
A 2 LEU N N -6.379 4.031 -2.228
|
|
412
|
+
A 2 LEU CA C -4.923 4.002 -2.452
|
|
413
|
+
A 2 LEU C C -4.136 3.187 -1.404
|
|
414
|
+
A 2 LEU O O -3.391 2.274 -1.760
|
|
415
|
+
A 2 LEU CB C -4.411 5.450 -2.619
|
|
416
|
+
A 2 LEU CG C -4.795 6.450 -1.495
|
|
417
|
+
A 2 LEU CD1 C -3.612 6.803 -0.599
|
|
418
|
+
A 2 LEU CD2 C -5.351 7.748 -2.084
|
|
419
|
+
A 2 LEU H H -6.821 4.923 -2.394
|
|
420
|
+
A 2 LEU HA H -4.750 3.494 -3.403
|
|
421
|
+
A 2 LEU HB2 H -3.340 5.414 -2.672
|
|
422
|
+
A 2 LEU HB3 H -4.813 5.817 -3.564
|
|
423
|
+
A 2 LEU HG H -5.568 6.022 -0.858
|
|
424
|
+
A 2 LEU HD11 H -3.207 5.905 -0.146
|
|
425
|
+
A 2 LEU HD12 H -2.841 7.304 -1.183
|
|
426
|
+
A 2 LEU HD13 H -3.929 7.477 0.197
|
|
427
|
+
A 2 LEU HD21 H -4.607 8.209 -2.736
|
|
428
|
+
A 2 LEU HD22 H -6.255 7.544 -2.657
|
|
429
|
+
A 2 LEU HD23 H -5.592 8.445 -1.281
|
|
430
|
+
"""
|
|
431
|
+
origin_direction = np.asarray(
|
|
432
|
+
origin_direction, dtype=np.float32
|
|
433
|
+
).squeeze()
|
|
434
|
+
target_direction = np.asarray(
|
|
435
|
+
target_direction, dtype=np.float32
|
|
436
|
+
).squeeze()
|
|
437
|
+
# check that original and target direction are vectors of shape (3,)
|
|
438
|
+
if origin_direction.shape != (3,):
|
|
439
|
+
raise ValueError(
|
|
440
|
+
f"Expected origin vector to have shape (3,), "
|
|
441
|
+
f"got {origin_direction.shape}"
|
|
442
|
+
)
|
|
443
|
+
if target_direction.shape != (3,):
|
|
444
|
+
raise ValueError(
|
|
445
|
+
f"Expected target vector to have shape (3,), "
|
|
446
|
+
f"got {target_direction.shape}"
|
|
447
|
+
)
|
|
448
|
+
if np.linalg.norm(origin_direction) == 0:
|
|
449
|
+
raise ValueError("Length of the origin vector is 0")
|
|
450
|
+
if np.linalg.norm(target_direction) == 0:
|
|
451
|
+
raise ValueError("Length of the target vector is 0")
|
|
452
|
+
if origin_position is not None:
|
|
453
|
+
origin_position = np.asarray(origin_position, dtype=np.float32)
|
|
454
|
+
if target_position is not None:
|
|
455
|
+
target_position = np.asarray(target_position, dtype=np.float32)
|
|
456
|
+
|
|
457
|
+
positions = coord(atoms).copy()
|
|
458
|
+
if origin_position is not None:
|
|
459
|
+
# Transform coordinates
|
|
460
|
+
# so that the position of the origin vector is at (0,0,0)
|
|
461
|
+
positions -= origin_position
|
|
462
|
+
|
|
463
|
+
# Normalize direction vectors
|
|
464
|
+
origin_direction = origin_direction.copy()
|
|
465
|
+
norm_vector(origin_direction)
|
|
466
|
+
target_direction = target_direction.copy()
|
|
467
|
+
norm_vector(target_direction)
|
|
468
|
+
# Formula is taken from
|
|
469
|
+
# https://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d/476311#476311
|
|
470
|
+
vx, vy, vz = np.cross(origin_direction, target_direction)
|
|
471
|
+
v_c = np.array([
|
|
472
|
+
[ 0, -vz, vy],
|
|
473
|
+
[ vz, 0, -vx],
|
|
474
|
+
[-vy, vx, 0]
|
|
475
|
+
], dtype=float)
|
|
476
|
+
cos_a = vector_dot(origin_direction, target_direction)
|
|
477
|
+
if np.all(cos_a == -1):
|
|
478
|
+
raise ValueError(
|
|
479
|
+
"Direction vectors are point into opposite directions, "
|
|
480
|
+
"cannot calculate rotation matrix"
|
|
481
|
+
)
|
|
482
|
+
rot_matrix = np.identity(3) + v_c + (v_c @ v_c) / (1 + cos_a)
|
|
483
|
+
|
|
484
|
+
positions = matrix_rotate(positions, rot_matrix)
|
|
485
|
+
|
|
486
|
+
if target_position is not None:
|
|
487
|
+
# Transform coordinates to position of the target vector
|
|
488
|
+
positions += target_position
|
|
489
|
+
|
|
490
|
+
return _put_back(atoms, positions)
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def _put_back(input_atoms, transformed):
|
|
494
|
+
"""
|
|
495
|
+
Put the altered coordinates back into the :class:`Atom`,
|
|
496
|
+
:class:`AtomArray` or :class:`AtomArrayStack`, if the input was one
|
|
497
|
+
of these types.
|
|
498
|
+
"""
|
|
499
|
+
if isinstance(input_atoms, (Atom, AtomArray, AtomArrayStack)):
|
|
500
|
+
moved_atoms = input_atoms.copy()
|
|
501
|
+
moved_atoms.coord = transformed
|
|
502
|
+
return moved_atoms
|
|
503
|
+
else:
|
|
504
|
+
return transformed
|
|
@@ -0,0 +1,98 @@
|
|
|
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
|
+
Utility functions for in internal use in `Bio.Structure` package
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__name__ = "biotite.structure"
|
|
10
|
+
__author__ = "Patrick Kunzmann"
|
|
11
|
+
__all__ = ["vector_dot", "norm_vector", "distance", "matrix_rotate"]
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
from .atoms import Atom, array
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def vector_dot(v1,v2):
|
|
18
|
+
"""
|
|
19
|
+
Calculate vector dot product of two vectors.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
v1,v2 : ndarray
|
|
24
|
+
The arrays to calculate the product from.
|
|
25
|
+
The vectors are represented by the last axis.
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
product : float or ndarray
|
|
30
|
+
Scalar product over the last dimension of the arrays.
|
|
31
|
+
"""
|
|
32
|
+
return (v1*v2).sum(axis=-1)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def norm_vector(v):
|
|
36
|
+
"""
|
|
37
|
+
Normalise a vector.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
v : ndarray
|
|
42
|
+
The array containg the vector(s).
|
|
43
|
+
The vectors are represented by the last axis.
|
|
44
|
+
"""
|
|
45
|
+
factor = np.linalg.norm(v, axis=-1)
|
|
46
|
+
if isinstance(factor, np.ndarray):
|
|
47
|
+
v /= factor[..., np.newaxis]
|
|
48
|
+
else:
|
|
49
|
+
v /= factor
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def distance(v1,v2):
|
|
53
|
+
"""
|
|
54
|
+
Calculate the distance between two position vectors.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
v1,v2 : ndarray
|
|
59
|
+
The arrays to calculate the product from.
|
|
60
|
+
The vectors are represented by the last axis.
|
|
61
|
+
|
|
62
|
+
Returns
|
|
63
|
+
-------
|
|
64
|
+
product : float or ndarray
|
|
65
|
+
Vector distance over the last dimension of the array.
|
|
66
|
+
"""
|
|
67
|
+
dif = v1 - v2
|
|
68
|
+
return np.sqrt((dif*dif).sum(axis=-1))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def matrix_rotate(v, matrix):
|
|
72
|
+
"""
|
|
73
|
+
Perform a rotation using a rotation matrix.
|
|
74
|
+
|
|
75
|
+
Parameters
|
|
76
|
+
----------
|
|
77
|
+
v : ndarray
|
|
78
|
+
The coordinates to rotate.
|
|
79
|
+
matrix : ndarray
|
|
80
|
+
The rotation matrix.
|
|
81
|
+
|
|
82
|
+
Returns
|
|
83
|
+
-------
|
|
84
|
+
rotated : ndarray
|
|
85
|
+
The rotated coordinates.
|
|
86
|
+
"""
|
|
87
|
+
# For proper rotation reshape into a maximum of 2 dimensions
|
|
88
|
+
orig_ndim = v.ndim
|
|
89
|
+
if orig_ndim > 2:
|
|
90
|
+
orig_shape = v.shape
|
|
91
|
+
v = v.reshape(-1, 3)
|
|
92
|
+
# Apply rotation
|
|
93
|
+
v = np.dot(matrix, v.T).T
|
|
94
|
+
# Reshape back into original shape
|
|
95
|
+
if orig_ndim > 2:
|
|
96
|
+
v = v.reshape(*orig_shape)
|
|
97
|
+
return v
|
|
98
|
+
|
biotite/temp.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
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"
|
|
6
|
+
__author__ = "Patrick Kunzmann"
|
|
7
|
+
__all__ = ["temp_file", "temp_dir"]
|
|
8
|
+
|
|
9
|
+
import shutil
|
|
10
|
+
import atexit
|
|
11
|
+
import os
|
|
12
|
+
import tempfile
|
|
13
|
+
import warnings
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
_temp_dir = ""
|
|
17
|
+
|
|
18
|
+
def _create_temp_dir():
|
|
19
|
+
global _temp_dir
|
|
20
|
+
if _temp_dir == "":
|
|
21
|
+
cwd = os.getcwd()
|
|
22
|
+
_temp_dir = os.path.join(cwd, ".biotitetemp")
|
|
23
|
+
if not os.path.isdir(_temp_dir):
|
|
24
|
+
os.makedirs(_temp_dir)
|
|
25
|
+
atexit.register(_delete_temp)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _delete_temp():
|
|
29
|
+
global _temp_dir
|
|
30
|
+
# Condition only for savety reasons
|
|
31
|
+
if ".biotitetemp" in _temp_dir:
|
|
32
|
+
shutil.rmtree(_temp_dir)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def temp_file(suffix=""):
|
|
36
|
+
"""
|
|
37
|
+
Get a file path to a temporary file.
|
|
38
|
+
|
|
39
|
+
All temporary files will be deleted after script execution.
|
|
40
|
+
|
|
41
|
+
DEPRECATED: Please use the :mod:`tempfile` module from the
|
|
42
|
+
standard library.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
suffix : str
|
|
47
|
+
Suffix of the file.
|
|
48
|
+
By default no suffix will be appended.
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
temp_file_name : str
|
|
53
|
+
a file name in the temporary directory.
|
|
54
|
+
"""
|
|
55
|
+
global _temp_dir
|
|
56
|
+
warnings.warn(
|
|
57
|
+
"Please use the :mod:`tempfile` module from the standard library",
|
|
58
|
+
DeprecationWarning
|
|
59
|
+
)
|
|
60
|
+
_create_temp_dir()
|
|
61
|
+
if suffix != "" and not suffix.startswith("."):
|
|
62
|
+
suffix = "." + suffix
|
|
63
|
+
return tempfile.mktemp(suffix=suffix, dir=_temp_dir)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def temp_dir():
|
|
67
|
+
"""
|
|
68
|
+
Get the temporary directory path.
|
|
69
|
+
|
|
70
|
+
The temporary directory will be deleted after script execution.
|
|
71
|
+
|
|
72
|
+
DEPRECATED: Please use the :mod:`tempfile` module from the
|
|
73
|
+
standard library.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
temp_dir : str
|
|
78
|
+
Path of the temporary directory.
|
|
79
|
+
"""
|
|
80
|
+
global _temp_dir
|
|
81
|
+
warnings.warn(
|
|
82
|
+
"Please use the :mod:`tempfile` module from the standard library",
|
|
83
|
+
DeprecationWarning
|
|
84
|
+
)
|
|
85
|
+
_create_temp_dir()
|
|
86
|
+
return _temp_dir
|
biotite/version.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# file generated by setuptools_scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
TYPE_CHECKING = False
|
|
4
|
+
if TYPE_CHECKING:
|
|
5
|
+
from typing import Tuple, Union
|
|
6
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
7
|
+
else:
|
|
8
|
+
VERSION_TUPLE = object
|
|
9
|
+
|
|
10
|
+
version: str
|
|
11
|
+
__version__: str
|
|
12
|
+
__version_tuple__: VERSION_TUPLE
|
|
13
|
+
version_tuple: VERSION_TUPLE
|
|
14
|
+
|
|
15
|
+
__version__ = version = '0.41.1'
|
|
16
|
+
__version_tuple__ = version_tuple = (0, 41, 1)
|