biotite 1.5.0__cp313-cp313-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-313-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-313-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/kmeralphabet.pyx +595 -0
- biotite/sequence/align/kmersimilarity.cpython-313-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/kmersimilarity.pyx +233 -0
- biotite/sequence/align/kmertable.cpython-313-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/kmertable.pyx +3411 -0
- biotite/sequence/align/localgapped.cpython-313-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/localgapped.pyx +892 -0
- biotite/sequence/align/localungapped.cpython-313-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-313-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/multiple.pyx +619 -0
- biotite/sequence/align/pairwise.cpython-313-x86_64-linux-gnu.so +0 -0
- biotite/sequence/align/pairwise.pyx +585 -0
- biotite/sequence/align/permutation.cpython-313-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-313-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-313-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-313-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-313-x86_64-linux-gnu.so +0 -0
- biotite/sequence/phylo/nj.pyx +221 -0
- biotite/sequence/phylo/tree.cpython-313-x86_64-linux-gnu.so +0 -0
- biotite/sequence/phylo/tree.pyx +1169 -0
- biotite/sequence/phylo/upgma.cpython-313-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-313-x86_64-linux-gnu.so +0 -0
- biotite/structure/bonds.pyx +2036 -0
- biotite/structure/box.py +724 -0
- biotite/structure/celllist.cpython-313-x86_64-linux-gnu.so +0 -0
- biotite/structure/celllist.pyx +864 -0
- biotite/structure/chains.py +310 -0
- biotite/structure/charges.cpython-313-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-313-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-313-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-313-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,160 @@
|
|
|
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__ = [
|
|
12
|
+
"vector_dot",
|
|
13
|
+
"norm_vector",
|
|
14
|
+
"distance",
|
|
15
|
+
"matrix_rotate",
|
|
16
|
+
"coord_for_atom_name_per_residue",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
import numpy as np
|
|
20
|
+
from biotite.structure.atoms import AtomArrayStack
|
|
21
|
+
from biotite.structure.residues import (
|
|
22
|
+
get_atom_name_indices,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def vector_dot(v1, v2):
|
|
27
|
+
"""
|
|
28
|
+
Calculate vector dot product of two vectors.
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
v1, v2 : ndarray
|
|
33
|
+
The arrays to calculate the product from.
|
|
34
|
+
The vectors are represented by the last axis.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
product : float or ndarray
|
|
39
|
+
Scalar product over the last dimension of the arrays.
|
|
40
|
+
"""
|
|
41
|
+
return (v1 * v2).sum(axis=-1)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def norm_vector(v):
|
|
45
|
+
"""
|
|
46
|
+
Normalise a vector.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
v : ndarray
|
|
51
|
+
The array containg the vector(s).
|
|
52
|
+
The vectors are represented by the last axis.
|
|
53
|
+
"""
|
|
54
|
+
factor = np.linalg.norm(v, axis=-1)
|
|
55
|
+
if isinstance(factor, np.ndarray):
|
|
56
|
+
v /= factor[..., np.newaxis]
|
|
57
|
+
else:
|
|
58
|
+
v /= factor
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def distance(v1, v2):
|
|
62
|
+
"""
|
|
63
|
+
Calculate the distance between two position vectors.
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
v1, v2 : ndarray
|
|
68
|
+
The arrays to calculate the product from.
|
|
69
|
+
The vectors are represented by the last axis.
|
|
70
|
+
|
|
71
|
+
Returns
|
|
72
|
+
-------
|
|
73
|
+
product : float or ndarray
|
|
74
|
+
Vector distance over the last dimension of the array.
|
|
75
|
+
"""
|
|
76
|
+
dif = v1 - v2
|
|
77
|
+
return np.sqrt((dif * dif).sum(axis=-1))
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def matrix_rotate(v, matrix):
|
|
81
|
+
"""
|
|
82
|
+
Perform a rotation using a rotation matrix.
|
|
83
|
+
|
|
84
|
+
Parameters
|
|
85
|
+
----------
|
|
86
|
+
v : ndarray
|
|
87
|
+
The coordinates to rotate.
|
|
88
|
+
matrix : ndarray
|
|
89
|
+
The rotation matrix.
|
|
90
|
+
|
|
91
|
+
Returns
|
|
92
|
+
-------
|
|
93
|
+
rotated : ndarray
|
|
94
|
+
The rotated coordinates.
|
|
95
|
+
"""
|
|
96
|
+
# For proper rotation reshape into a maximum of 2 dimensions
|
|
97
|
+
orig_ndim = v.ndim
|
|
98
|
+
if orig_ndim > 2:
|
|
99
|
+
orig_shape = v.shape
|
|
100
|
+
v = v.reshape(-1, 3)
|
|
101
|
+
# Apply rotation
|
|
102
|
+
v = np.dot(matrix, v.T).T
|
|
103
|
+
# Reshape back into original shape
|
|
104
|
+
if orig_ndim > 2:
|
|
105
|
+
v = v.reshape(*orig_shape)
|
|
106
|
+
return v
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def coord_for_atom_name_per_residue(atoms, atom_names, mask=None):
|
|
110
|
+
"""
|
|
111
|
+
Get the coordinates of a specific atom for every residue.
|
|
112
|
+
|
|
113
|
+
If a residue does not contain the specified atom, the coordinates are `NaN`.
|
|
114
|
+
If a residue contains multiple atoms with the specified name, an exception is
|
|
115
|
+
raised.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
atoms : AtomArray, shape=(n,) or AtomArrayStack, shape=(m,n)
|
|
120
|
+
The atom array or stack to get the residue-wise coordinates from.
|
|
121
|
+
atom_names : list of str, length=k
|
|
122
|
+
The atom names to get the coordinates for.
|
|
123
|
+
mask : ndarray, shape=(n,), dtype=bool, optional
|
|
124
|
+
A boolean mask to further select valid atoms from `atoms`.
|
|
125
|
+
|
|
126
|
+
Returns
|
|
127
|
+
-------
|
|
128
|
+
coord: ndarray, shape=(k, m, r, 3) or shape=(k, r, 3)
|
|
129
|
+
The coordinates of the specified atom for each residue.
|
|
130
|
+
"""
|
|
131
|
+
atom_name_indices = get_atom_name_indices(atoms, atom_names)
|
|
132
|
+
|
|
133
|
+
is_multi_model = isinstance(atoms, AtomArrayStack)
|
|
134
|
+
if is_multi_model:
|
|
135
|
+
coord = np.full(
|
|
136
|
+
(len(atom_names), atoms.stack_depth(), atom_name_indices.shape[0], 3),
|
|
137
|
+
np.nan,
|
|
138
|
+
dtype=np.float32,
|
|
139
|
+
)
|
|
140
|
+
else:
|
|
141
|
+
coord = np.full(
|
|
142
|
+
(len(atom_names), atom_name_indices.shape[0], 3),
|
|
143
|
+
np.nan,
|
|
144
|
+
dtype=np.float32,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
for atom_name_i, atom_indices in enumerate(atom_name_indices.T):
|
|
148
|
+
valid_mask = atom_indices != -1
|
|
149
|
+
if mask is not None:
|
|
150
|
+
valid_mask &= mask[atom_indices]
|
|
151
|
+
coord_for_atom_name = atoms.coord[..., atom_indices[valid_mask], :]
|
|
152
|
+
if is_multi_model:
|
|
153
|
+
# Swap dimensions due to NumPy's behavior when using advanced indexing
|
|
154
|
+
# (https://numpy.org/devdocs/user/basics.indexing.html#combining-advanced-and-basic-indexing)
|
|
155
|
+
coord[atom_name_i, ..., valid_mask, :] = coord_for_atom_name.transpose(
|
|
156
|
+
1, 0, 2
|
|
157
|
+
)
|
|
158
|
+
else:
|
|
159
|
+
coord[atom_name_i, valid_mask, :] = coord_for_atom_name
|
|
160
|
+
return coord
|
biotite/version.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
TYPE_CHECKING = False
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import Union
|
|
17
|
+
|
|
18
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
20
|
+
else:
|
|
21
|
+
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
23
|
+
|
|
24
|
+
version: str
|
|
25
|
+
__version__: str
|
|
26
|
+
__version_tuple__: VERSION_TUPLE
|
|
27
|
+
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
30
|
+
|
|
31
|
+
__version__ = version = '1.5.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 5, 0)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = None
|
biotite/visualize.py
ADDED
|
@@ -0,0 +1,375 @@
|
|
|
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__ = ["colors", "plot_scaled_text", "set_font_size_in_coord", "AdaptiveFancyArrow"]
|
|
8
|
+
|
|
9
|
+
import warnings
|
|
10
|
+
from collections import OrderedDict
|
|
11
|
+
import numpy as np
|
|
12
|
+
from numpy.linalg import norm
|
|
13
|
+
|
|
14
|
+
_FONT_PROPERTY_KEYS = ["family", "style", "variant", "weight", "stretch", "size"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Biotite themed colors
|
|
18
|
+
colors = OrderedDict(
|
|
19
|
+
[
|
|
20
|
+
("brightorange", "#ffb569ff"),
|
|
21
|
+
("lightorange", "#ff982dff"),
|
|
22
|
+
("orange", "#ff8405ff"),
|
|
23
|
+
("dimorange", "#dc7000ff"),
|
|
24
|
+
("darkorange", "#b45c00ff"),
|
|
25
|
+
("brightgreen", "#98e97fff"),
|
|
26
|
+
("lightgreen", "#6fe04cff"),
|
|
27
|
+
("green", "#52da2aff"),
|
|
28
|
+
("dimgreen", "#45bc20ff"),
|
|
29
|
+
("darkgreen", "#389a1aff"),
|
|
30
|
+
]
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def plot_scaled_text(
|
|
35
|
+
axes, text, x, y, width=None, height=None, mode="unlocked", **kwargs
|
|
36
|
+
):
|
|
37
|
+
"""
|
|
38
|
+
Create a :class:`matplotlib.textpath.TextPath`, whose text size is given in
|
|
39
|
+
coordinates instead of font size.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
axes : Axes
|
|
44
|
+
The axes to draw the text on.
|
|
45
|
+
text : str
|
|
46
|
+
The text to be drawn.
|
|
47
|
+
x, y : float
|
|
48
|
+
The lower left position of the text.
|
|
49
|
+
width, height : float, optional
|
|
50
|
+
The width/height `text` should have in its reference coordinate system.
|
|
51
|
+
At least one value must be supplied.
|
|
52
|
+
mode : {'proportional', 'unlocked', 'maximum', 'minimum'}, optional
|
|
53
|
+
Defines how the text size is scaled.
|
|
54
|
+
The scaling mode:
|
|
55
|
+
|
|
56
|
+
- *proportional* - The width and height are scaled by the
|
|
57
|
+
same extent.
|
|
58
|
+
Either `width` or `height` must be set for this mode.
|
|
59
|
+
- *unlocked* - The width and the height are scaled by
|
|
60
|
+
different extents, changing the aspect ratio of the text.
|
|
61
|
+
Both `width` and `height` must be set for this mode.
|
|
62
|
+
- *maximum* - The width and the height are scaled by
|
|
63
|
+
the same extent, so that they are at maximum as large
|
|
64
|
+
as the supplied `width`/`height`.
|
|
65
|
+
Both `width` and `height` must be set for this mode.
|
|
66
|
+
- *minimum* - The width and the height are scaled by
|
|
67
|
+
the same extent, so that they are at minimum as large
|
|
68
|
+
as the supplied `width`/`height`.
|
|
69
|
+
Both `width` and `height` must be set for this mode.
|
|
70
|
+
|
|
71
|
+
**kwargs
|
|
72
|
+
Additional parameters for the :class:`matplotlib.font_manager.FontProperties`
|
|
73
|
+
of the text or the created :class:`matplotlib.patches.PathPatch`.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
patch : matplotlib.patches.PathPatch
|
|
78
|
+
The patch that represents the text.
|
|
79
|
+
"""
|
|
80
|
+
from matplotlib.patches import PathPatch
|
|
81
|
+
from matplotlib.textpath import TextPath
|
|
82
|
+
from matplotlib.transforms import Affine2D
|
|
83
|
+
|
|
84
|
+
# The larger the size, the more there is an offset at the x-axis
|
|
85
|
+
# -> Keep font size small to reduce this error to a minimum
|
|
86
|
+
# The size is transformed to the desired size afterwards anyway
|
|
87
|
+
font_property_kwargs = {
|
|
88
|
+
key: kwargs.pop(key) for key in _FONT_PROPERTY_KEYS if key in kwargs
|
|
89
|
+
}
|
|
90
|
+
path = TextPath((x, y), text, size=1e-3, prop=font_property_kwargs)
|
|
91
|
+
bbox = path.get_extents()
|
|
92
|
+
|
|
93
|
+
if mode == "proportional":
|
|
94
|
+
if width is None:
|
|
95
|
+
# Proportional scaling based on height
|
|
96
|
+
scale_y = height / bbox.height
|
|
97
|
+
scale_x = scale_y
|
|
98
|
+
elif height is None:
|
|
99
|
+
# Proportional scaling based on width
|
|
100
|
+
scale_x = width / bbox.width
|
|
101
|
+
scale_y = scale_x
|
|
102
|
+
else:
|
|
103
|
+
raise ValueError(
|
|
104
|
+
"width or height are mutually exclusive in 'proportional' mode"
|
|
105
|
+
)
|
|
106
|
+
elif mode == "unlocked":
|
|
107
|
+
scale_x = width / bbox.width
|
|
108
|
+
scale_y = height / bbox.height
|
|
109
|
+
elif mode == "minimum":
|
|
110
|
+
scale_x = width / bbox.width
|
|
111
|
+
scale_y = height / bbox.height
|
|
112
|
+
scale = max(scale_x, scale_y)
|
|
113
|
+
scale_x, scale_y = scale, scale
|
|
114
|
+
elif mode == "maximum":
|
|
115
|
+
scale_x = width / bbox.width
|
|
116
|
+
scale_y = height / bbox.height
|
|
117
|
+
scale = min(scale_x, scale_y)
|
|
118
|
+
scale_x, scale_y = scale, scale
|
|
119
|
+
|
|
120
|
+
path = (
|
|
121
|
+
Affine2D()
|
|
122
|
+
.translate(-bbox.x0, -bbox.y0)
|
|
123
|
+
.scale(scale_x, scale_y)
|
|
124
|
+
.translate(bbox.x0, bbox.y0)
|
|
125
|
+
.transform_path(path)
|
|
126
|
+
)
|
|
127
|
+
patch = PathPatch(path, **kwargs)
|
|
128
|
+
axes.add_patch(patch)
|
|
129
|
+
|
|
130
|
+
return patch
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def set_font_size_in_coord(text, width=None, height=None, mode="unlocked"):
|
|
134
|
+
"""
|
|
135
|
+
Specifiy the font size of an existing `Text` object in coordinates
|
|
136
|
+
of the object's reference coordiante system.
|
|
137
|
+
|
|
138
|
+
Instead of having the font size fixed in 'pt', the size of the text
|
|
139
|
+
scales to the specied width/height and adapts to changes in the
|
|
140
|
+
plot's width/height.
|
|
141
|
+
The scaling can be proportional or non-proportional, depending
|
|
142
|
+
the `mode`.
|
|
143
|
+
|
|
144
|
+
DEPRECATED: Use :func:`plot_scaled_text()` instead.
|
|
145
|
+
|
|
146
|
+
Parameters
|
|
147
|
+
----------
|
|
148
|
+
text : Text:
|
|
149
|
+
The matplotlib `Text` to be scaled.
|
|
150
|
+
width, height : float, optional
|
|
151
|
+
The new width/height of `text` in its
|
|
152
|
+
reference coordinate system.
|
|
153
|
+
At least one value must be supplied.
|
|
154
|
+
mode : {'proportional', 'unlocked', 'maximum', 'minimum'}, optional
|
|
155
|
+
The scaling mode:
|
|
156
|
+
|
|
157
|
+
- *proportional* - The width and height are scaled by the
|
|
158
|
+
same extent.
|
|
159
|
+
Either `width` or `height` must be set for this mode.
|
|
160
|
+
- *unlocked* - The width and the height are scaled by
|
|
161
|
+
different extents, changing the aspect ratio.
|
|
162
|
+
Both `width` and `height` must be set for this mode.
|
|
163
|
+
- *maximum* - The width and the height are scaled by
|
|
164
|
+
the same extent, so that they are at maximum as large
|
|
165
|
+
as the supplied `width`/`height`.
|
|
166
|
+
Both `width` and `height` must be set for this mode.
|
|
167
|
+
- *minimum* - The width and the height are scaled by
|
|
168
|
+
the same extent, so that they are at minimum as large
|
|
169
|
+
as the supplied `width`/`height`.
|
|
170
|
+
Both `width` and `height` must be set for this mode.
|
|
171
|
+
|
|
172
|
+
Notes
|
|
173
|
+
-----
|
|
174
|
+
This function uses the :func:`get_window_extent()` method of the
|
|
175
|
+
:class:`Text` object.
|
|
176
|
+
According to experience, this function does not give the the exact
|
|
177
|
+
visual boundaries of the text.
|
|
178
|
+
Consequently, the scaled text might be slightly smaller or larger
|
|
179
|
+
than the specified width/height.
|
|
180
|
+
This behavior is not equal for all initial font sizes (in 'pt'),
|
|
181
|
+
the boundaries for an initial size of 1 'pt' seem to be most exact.
|
|
182
|
+
"""
|
|
183
|
+
from matplotlib.patheffects import AbstractPathEffect
|
|
184
|
+
from matplotlib.transforms import Affine2D, Bbox
|
|
185
|
+
|
|
186
|
+
class TextScaler(AbstractPathEffect):
|
|
187
|
+
def __init__(self, text, width, height, mode):
|
|
188
|
+
self._text = text
|
|
189
|
+
self._mode = mode
|
|
190
|
+
self._width = width
|
|
191
|
+
self._height = height
|
|
192
|
+
|
|
193
|
+
def draw_path(self, renderer, gc, tpath, affine, rgbFace=None): # noqa: N803
|
|
194
|
+
ax = self._text.axes
|
|
195
|
+
try:
|
|
196
|
+
renderer = ax.get_figure().canvas.get_renderer()
|
|
197
|
+
except Exception:
|
|
198
|
+
# Use cached renderer for backends, where
|
|
199
|
+
# `get_renderer()` is not available
|
|
200
|
+
# Based on the strategy from `Text.get_window_extent()`
|
|
201
|
+
renderer = ax.get_figure()._cachedRenderer
|
|
202
|
+
if renderer is None:
|
|
203
|
+
raise
|
|
204
|
+
bbox = text.get_window_extent(renderer)
|
|
205
|
+
bbox = Bbox(ax.transData.inverted().transform(bbox))
|
|
206
|
+
|
|
207
|
+
if self._mode == "proportional":
|
|
208
|
+
if self._width is None:
|
|
209
|
+
# Proportional scaling based on height
|
|
210
|
+
scale_y = self._height / bbox.height
|
|
211
|
+
scale_x = scale_y
|
|
212
|
+
elif self._height is None:
|
|
213
|
+
# Proportional scaling based on width
|
|
214
|
+
scale_x = self._width / bbox.width
|
|
215
|
+
scale_y = scale_x
|
|
216
|
+
elif self._mode == "unlocked":
|
|
217
|
+
scale_x = self._width / bbox.width
|
|
218
|
+
scale_y = self._height / bbox.height
|
|
219
|
+
elif self._mode == "minimum":
|
|
220
|
+
scale_x = self._width / bbox.width
|
|
221
|
+
scale_y = self._height / bbox.height
|
|
222
|
+
scale = max(scale_x, scale_y)
|
|
223
|
+
scale_x, scale_y = scale, scale
|
|
224
|
+
elif self._mode == "maximum":
|
|
225
|
+
scale_x = self._width / bbox.width
|
|
226
|
+
scale_y = self._height / bbox.height
|
|
227
|
+
scale = min(scale_x, scale_y)
|
|
228
|
+
scale_x, scale_y = scale, scale
|
|
229
|
+
|
|
230
|
+
affine = Affine2D().scale(scale_x, scale_y) + affine
|
|
231
|
+
renderer.draw_path(gc, tpath, affine, rgbFace)
|
|
232
|
+
|
|
233
|
+
warnings.warn(
|
|
234
|
+
"Deprecated, use 'biotite.graphics.text.plot_scaled_text()' instead.",
|
|
235
|
+
DeprecationWarning,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
if mode in ["unlocked", "minimum", "maximum"]:
|
|
239
|
+
if width is None or height is None:
|
|
240
|
+
raise TypeError(f"Width and height must be set in '{mode}' mode")
|
|
241
|
+
elif mode == "proportional":
|
|
242
|
+
if not (width is None and height is not None) or not (
|
|
243
|
+
height is None and width is not None
|
|
244
|
+
):
|
|
245
|
+
raise TypeError(f"Either width or height must be set in '{mode}' mode")
|
|
246
|
+
else:
|
|
247
|
+
raise ValueError(f"Unknown mode '{mode}'")
|
|
248
|
+
text.set_path_effects([TextScaler(text, width, height, mode)])
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
try:
|
|
252
|
+
# Only create this class when matplotlib is installed
|
|
253
|
+
from matplotlib.patches import FancyArrow
|
|
254
|
+
from matplotlib.transforms import Bbox
|
|
255
|
+
|
|
256
|
+
class AdaptiveFancyArrow(FancyArrow):
|
|
257
|
+
"""
|
|
258
|
+
A `FancyArrow` with fixed head shape.
|
|
259
|
+
|
|
260
|
+
The length of the head is proportional to the width of the head
|
|
261
|
+
in display coordinates.
|
|
262
|
+
If the head length is longer than the length of the entire
|
|
263
|
+
arrow, the head length is limited to the arrow length.
|
|
264
|
+
|
|
265
|
+
Parameters
|
|
266
|
+
----------
|
|
267
|
+
x,y : float
|
|
268
|
+
The arrow's start position.
|
|
269
|
+
dx, dy : float
|
|
270
|
+
The arrow's direction vector, inclduing the arrow head.
|
|
271
|
+
tail_width, head_width : float
|
|
272
|
+
The width of the arrow's tail and head in its reference
|
|
273
|
+
coordinate system
|
|
274
|
+
head_ratio : float, optional
|
|
275
|
+
The length of the arrow head as faction of the arrow width
|
|
276
|
+
(display coordinates).
|
|
277
|
+
draw_head: bool, optional
|
|
278
|
+
If false, the arrow has no head. The result is a rectangle.
|
|
279
|
+
shape : str, optional
|
|
280
|
+
The `shape` parameter in the constructor of `FancyArrow`.
|
|
281
|
+
**kwargs
|
|
282
|
+
Other parameters that are used in the constructor of
|
|
283
|
+
`FancyArrow`.
|
|
284
|
+
"""
|
|
285
|
+
|
|
286
|
+
def __init__(
|
|
287
|
+
self,
|
|
288
|
+
x,
|
|
289
|
+
y,
|
|
290
|
+
dx,
|
|
291
|
+
dy,
|
|
292
|
+
tail_width,
|
|
293
|
+
head_width,
|
|
294
|
+
head_ratio,
|
|
295
|
+
draw_head=True,
|
|
296
|
+
shape="full",
|
|
297
|
+
**kwargs,
|
|
298
|
+
):
|
|
299
|
+
self._x = x
|
|
300
|
+
self._y = y
|
|
301
|
+
self._dx = dx
|
|
302
|
+
self._dy = dy
|
|
303
|
+
self._tail_width = tail_width
|
|
304
|
+
self._head_width = head_width
|
|
305
|
+
self._head_ratio = head_ratio
|
|
306
|
+
self._draw_head = draw_head
|
|
307
|
+
self._shape = shape
|
|
308
|
+
self._kwargs = kwargs
|
|
309
|
+
if not draw_head:
|
|
310
|
+
head_width = tail_width
|
|
311
|
+
super().__init__(
|
|
312
|
+
x,
|
|
313
|
+
y,
|
|
314
|
+
dx,
|
|
315
|
+
dy,
|
|
316
|
+
width=tail_width,
|
|
317
|
+
head_width=head_width,
|
|
318
|
+
overhang=0,
|
|
319
|
+
shape=shape,
|
|
320
|
+
length_includes_head=True,
|
|
321
|
+
**kwargs,
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
def draw(self, renderer):
|
|
325
|
+
arrow_box = Bbox([(0, 0), (0, self._head_width)])
|
|
326
|
+
arrow_box_display = self.axes.transData.transform_bbox(arrow_box)
|
|
327
|
+
head_length_display = np.abs(arrow_box_display.height * self._head_ratio)
|
|
328
|
+
arrow_box_display.x1 = arrow_box_display.x0 + head_length_display
|
|
329
|
+
# Transfrom back to data coordinates for plotting
|
|
330
|
+
arrow_box = self.axes.transData.inverted().transform_bbox(arrow_box_display)
|
|
331
|
+
head_length = arrow_box.width
|
|
332
|
+
arrow_length = norm((self._dx, self._dy))
|
|
333
|
+
if head_length > arrow_length:
|
|
334
|
+
# If the head would be longer than the entire arrow,
|
|
335
|
+
# only draw the arrow head with reduced length
|
|
336
|
+
head_length = arrow_length
|
|
337
|
+
if not self._draw_head:
|
|
338
|
+
head_length = 0
|
|
339
|
+
|
|
340
|
+
# Renew the arrow's properties
|
|
341
|
+
super().__init__(
|
|
342
|
+
self._x,
|
|
343
|
+
self._y,
|
|
344
|
+
self._dx,
|
|
345
|
+
self._dy,
|
|
346
|
+
width=self._tail_width,
|
|
347
|
+
head_width=self._head_width,
|
|
348
|
+
overhang=0,
|
|
349
|
+
shape=self._shape,
|
|
350
|
+
head_length=head_length,
|
|
351
|
+
length_includes_head=True,
|
|
352
|
+
axes=self.axes,
|
|
353
|
+
transform=self.get_transform(),
|
|
354
|
+
**self._kwargs,
|
|
355
|
+
)
|
|
356
|
+
self.set_clip_path(self.axes.patch)
|
|
357
|
+
super().draw(renderer)
|
|
358
|
+
|
|
359
|
+
# Override to replace docstring
|
|
360
|
+
# Removes warning:
|
|
361
|
+
# unknown document: /tutorials/intermediate/constrainedlayout_guide
|
|
362
|
+
def get_in_layout(self):
|
|
363
|
+
""" """
|
|
364
|
+
return super().get_in_layout()
|
|
365
|
+
|
|
366
|
+
def set_in_layout(self, in_layout):
|
|
367
|
+
""" """
|
|
368
|
+
return super().set_in_layout(in_layout)
|
|
369
|
+
|
|
370
|
+
except ImportError:
|
|
371
|
+
# Dummy class that propagates a meaningful error,
|
|
372
|
+
# i.e. that Matplotlib is not installed
|
|
373
|
+
class AdaptiveFancyArrow:
|
|
374
|
+
def __init__(*args, **kwargs):
|
|
375
|
+
raise ModuleNotFoundError("No module named 'matplotlib'")
|