biotite 0.41.1__cp312-cp312-macosx_10_16_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of biotite might be problematic. Click here for more details.
- biotite/__init__.py +19 -0
- biotite/application/__init__.py +43 -0
- biotite/application/application.py +265 -0
- biotite/application/autodock/__init__.py +12 -0
- biotite/application/autodock/app.py +505 -0
- biotite/application/blast/__init__.py +14 -0
- biotite/application/blast/alignment.py +83 -0
- biotite/application/blast/webapp.py +421 -0
- biotite/application/clustalo/__init__.py +12 -0
- biotite/application/clustalo/app.py +238 -0
- biotite/application/dssp/__init__.py +12 -0
- biotite/application/dssp/app.py +152 -0
- biotite/application/localapp.py +306 -0
- biotite/application/mafft/__init__.py +12 -0
- biotite/application/mafft/app.py +122 -0
- biotite/application/msaapp.py +374 -0
- biotite/application/muscle/__init__.py +13 -0
- biotite/application/muscle/app3.py +254 -0
- biotite/application/muscle/app5.py +171 -0
- biotite/application/sra/__init__.py +18 -0
- biotite/application/sra/app.py +456 -0
- biotite/application/tantan/__init__.py +12 -0
- biotite/application/tantan/app.py +222 -0
- biotite/application/util.py +59 -0
- biotite/application/viennarna/__init__.py +18 -0
- biotite/application/viennarna/rnaalifold.py +304 -0
- biotite/application/viennarna/rnafold.py +269 -0
- biotite/application/viennarna/rnaplot.py +187 -0
- biotite/application/viennarna/util.py +72 -0
- biotite/application/webapp.py +77 -0
- biotite/copyable.py +71 -0
- biotite/database/__init__.py +23 -0
- biotite/database/entrez/__init__.py +15 -0
- biotite/database/entrez/check.py +61 -0
- biotite/database/entrez/dbnames.py +89 -0
- biotite/database/entrez/download.py +223 -0
- biotite/database/entrez/key.py +44 -0
- biotite/database/entrez/query.py +223 -0
- biotite/database/error.py +15 -0
- biotite/database/pubchem/__init__.py +21 -0
- biotite/database/pubchem/download.py +260 -0
- biotite/database/pubchem/error.py +20 -0
- biotite/database/pubchem/query.py +827 -0
- biotite/database/pubchem/throttle.py +99 -0
- biotite/database/rcsb/__init__.py +13 -0
- biotite/database/rcsb/download.py +167 -0
- biotite/database/rcsb/query.py +959 -0
- biotite/database/uniprot/__init__.py +13 -0
- biotite/database/uniprot/check.py +32 -0
- biotite/database/uniprot/download.py +134 -0
- biotite/database/uniprot/query.py +209 -0
- biotite/file.py +251 -0
- biotite/sequence/__init__.py +73 -0
- biotite/sequence/align/__init__.py +49 -0
- biotite/sequence/align/alignment.py +658 -0
- biotite/sequence/align/banded.cpython-312-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-312-darwin.so +0 -0
- biotite/sequence/align/kmeralphabet.pyx +574 -0
- biotite/sequence/align/kmersimilarity.cpython-312-darwin.so +0 -0
- biotite/sequence/align/kmersimilarity.pyx +233 -0
- biotite/sequence/align/kmertable.cpython-312-darwin.so +0 -0
- biotite/sequence/align/kmertable.pyx +3400 -0
- biotite/sequence/align/localgapped.cpython-312-darwin.so +0 -0
- biotite/sequence/align/localgapped.pyx +892 -0
- biotite/sequence/align/localungapped.cpython-312-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-312-darwin.so +0 -0
- biotite/sequence/align/multiple.pyx +620 -0
- biotite/sequence/align/pairwise.cpython-312-darwin.so +0 -0
- biotite/sequence/align/pairwise.pyx +587 -0
- biotite/sequence/align/permutation.cpython-312-darwin.so +0 -0
- biotite/sequence/align/permutation.pyx +305 -0
- biotite/sequence/align/primes.txt +821 -0
- biotite/sequence/align/selector.cpython-312-darwin.so +0 -0
- biotite/sequence/align/selector.pyx +956 -0
- biotite/sequence/align/statistics.py +265 -0
- biotite/sequence/align/tracetable.cpython-312-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-312-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-312-darwin.so +0 -0
- biotite/sequence/phylo/nj.pyx +221 -0
- biotite/sequence/phylo/tree.cpython-312-darwin.so +0 -0
- biotite/sequence/phylo/tree.pyx +1169 -0
- biotite/sequence/phylo/upgma.cpython-312-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-312-darwin.so +0 -0
- biotite/structure/bonds.pyx +1933 -0
- biotite/structure/box.py +592 -0
- biotite/structure/celllist.cpython-312-darwin.so +0 -0
- biotite/structure/celllist.pyx +849 -0
- biotite/structure/chains.py +298 -0
- biotite/structure/charges.cpython-312-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-312-darwin.so +0 -0
- biotite/structure/io/mmtf/convertarray.pyx +341 -0
- biotite/structure/io/mmtf/convertfile.cpython-312-darwin.so +0 -0
- biotite/structure/io/mmtf/convertfile.pyx +501 -0
- biotite/structure/io/mmtf/decode.cpython-312-darwin.so +0 -0
- biotite/structure/io/mmtf/decode.pyx +152 -0
- biotite/structure/io/mmtf/encode.cpython-312-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-312-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-312-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-312-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
biotite/structure/box.py
ADDED
|
@@ -0,0 +1,592 @@
|
|
|
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
|
+
Functions related to working with the simulation box or unit cell
|
|
7
|
+
of a structure
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
__name__ = "biotite.structure"
|
|
11
|
+
__author__ = "Patrick Kunzmann"
|
|
12
|
+
__all__ = ["vectors_from_unitcell", "unitcell_from_vectors", "box_volume",
|
|
13
|
+
"repeat_box", "repeat_box_coord", "move_inside_box",
|
|
14
|
+
"remove_pbc", "remove_pbc_from_coord",
|
|
15
|
+
"coord_to_fraction", "fraction_to_coord", "is_orthogonal"]
|
|
16
|
+
|
|
17
|
+
from collections.abc import Iterable
|
|
18
|
+
from numbers import Integral
|
|
19
|
+
import numpy as np
|
|
20
|
+
import numpy.linalg as linalg
|
|
21
|
+
from .util import vector_dot
|
|
22
|
+
from .atoms import repeat
|
|
23
|
+
from .molecules import get_molecule_masks
|
|
24
|
+
from .chains import get_chain_masks, get_chain_starts
|
|
25
|
+
from .error import BadStructureError
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def vectors_from_unitcell(len_a, len_b, len_c, alpha, beta, gamma):
|
|
29
|
+
"""
|
|
30
|
+
Calculate the three vectors spanning a box from the unit cell
|
|
31
|
+
lengths and angles.
|
|
32
|
+
|
|
33
|
+
The return value of this function are the three box vectors as
|
|
34
|
+
required for the :attr:`box` attribute in atom arrays and stacks.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
len_a, len_b, len_c : float
|
|
39
|
+
The lengths of the three box/unit cell vectors *a*, *b* and *c*.
|
|
40
|
+
alpha, beta, gamma:
|
|
41
|
+
The angles between the box vectors in radians.
|
|
42
|
+
*alpha* is the angle between *b* and *c*,
|
|
43
|
+
*beta* between *a* and *c*, *gamma* between *a* and *b*
|
|
44
|
+
|
|
45
|
+
Returns
|
|
46
|
+
-------
|
|
47
|
+
box : ndarray, dtype=float, shape=(3,3)
|
|
48
|
+
The three box vectors.
|
|
49
|
+
The vector components are in the last dimension.
|
|
50
|
+
The value can be directly used as :attr:`box` attribute in an
|
|
51
|
+
atom array.
|
|
52
|
+
|
|
53
|
+
See also
|
|
54
|
+
--------
|
|
55
|
+
unitcell_from_vectors
|
|
56
|
+
"""
|
|
57
|
+
a_x = len_a
|
|
58
|
+
b_x = len_b * np.cos(gamma)
|
|
59
|
+
b_y = len_b * np.sin(gamma)
|
|
60
|
+
c_x = len_c * np.cos(beta)
|
|
61
|
+
c_y = len_c * (np.cos(alpha) - np.cos(beta)*np.cos(gamma)) / np.sin(gamma)
|
|
62
|
+
c_z = np.sqrt(len_c*len_c - c_x*c_x - c_y*c_y)
|
|
63
|
+
box = np.array([
|
|
64
|
+
[a_x, 0, 0],
|
|
65
|
+
[b_x, b_y, 0],
|
|
66
|
+
[c_x, c_y, c_z]
|
|
67
|
+
], dtype=np.float32)
|
|
68
|
+
|
|
69
|
+
# Fix numerical errors, as values, that are actually 0,
|
|
70
|
+
# might not be calculated as such
|
|
71
|
+
tol = 1e-4 * (len_a + len_b + len_c)
|
|
72
|
+
box[np.abs(box) < tol] = 0
|
|
73
|
+
|
|
74
|
+
return box
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def unitcell_from_vectors(box):
|
|
78
|
+
"""
|
|
79
|
+
Get the unit cell lengths and angles from box vectors.
|
|
80
|
+
|
|
81
|
+
This is the reverse operation of :func:`vectors_from_unitcell()`.
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
box : ndarray, shape=(3,3)
|
|
86
|
+
The box vectors
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
-------
|
|
90
|
+
len_a, len_b, len_c : float
|
|
91
|
+
The lengths of the three box/unit cell vectors *a*, *b* and *c*.
|
|
92
|
+
alpha, beta, gamma : float
|
|
93
|
+
The angles between the box vectors in radians.
|
|
94
|
+
|
|
95
|
+
See also
|
|
96
|
+
--------
|
|
97
|
+
vectors_from_unitcell
|
|
98
|
+
"""
|
|
99
|
+
a = box[0]
|
|
100
|
+
b = box[1]
|
|
101
|
+
c = box[2]
|
|
102
|
+
len_a = linalg.norm(a)
|
|
103
|
+
len_b = linalg.norm(b)
|
|
104
|
+
len_c = linalg.norm(c)
|
|
105
|
+
alpha = np.arccos(np.dot(b, c) / (len_b * len_c))
|
|
106
|
+
beta = np.arccos(np.dot(a, c) / (len_a * len_c))
|
|
107
|
+
gamma = np.arccos(np.dot(a, b) / (len_a * len_b))
|
|
108
|
+
return len_a, len_b, len_c, alpha, beta, gamma
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def box_volume(box):
|
|
112
|
+
"""
|
|
113
|
+
Get the volume of one ore multiple boxes.
|
|
114
|
+
|
|
115
|
+
Parameters
|
|
116
|
+
----------
|
|
117
|
+
box : ndarray, shape=(3,3) or shape=(m,3,3)
|
|
118
|
+
One or multiple boxes to get the volume for.
|
|
119
|
+
|
|
120
|
+
Returns
|
|
121
|
+
-------
|
|
122
|
+
volume : float or ndarray, shape=(m,)
|
|
123
|
+
"""
|
|
124
|
+
# Using the triple product
|
|
125
|
+
return np.abs(linalg.det(box))
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def repeat_box(atoms, amount=1):
|
|
129
|
+
r"""
|
|
130
|
+
Repeat the atoms in a box by duplicating and placing them in
|
|
131
|
+
adjacent boxes.
|
|
132
|
+
|
|
133
|
+
The output atom array (stack) contains the original atoms (central
|
|
134
|
+
box) and duplicates of them in the given amount of adjacent boxes.
|
|
135
|
+
The coordinates of the duplicate atoms are translated accordingly
|
|
136
|
+
by the box coordinates.
|
|
137
|
+
|
|
138
|
+
Parameters
|
|
139
|
+
----------
|
|
140
|
+
atoms : AtomArray or AtomArrayStack
|
|
141
|
+
The atoms to be repeated.
|
|
142
|
+
If `atoms` is a :class:`AtomArrayStack`, the atoms are repeated
|
|
143
|
+
for each model, according to the box of each model.
|
|
144
|
+
amount : int, optional
|
|
145
|
+
The amount of boxes that are created in each direction of the
|
|
146
|
+
central box.
|
|
147
|
+
Hence, the total amount of boxes is
|
|
148
|
+
:math:`(1 + 2 \cdot \text{amount}) ^ 3`.
|
|
149
|
+
By default, one box is created in each direction, totalling in
|
|
150
|
+
27 boxes.
|
|
151
|
+
|
|
152
|
+
Returns
|
|
153
|
+
-------
|
|
154
|
+
repeated : AtomArray or AtomArrayStack
|
|
155
|
+
The repeated atoms.
|
|
156
|
+
Includes the original atoms (central box) in the beginning of
|
|
157
|
+
the atom array (stack).
|
|
158
|
+
indices : ndarray, dtype=int, shape=(n,3)
|
|
159
|
+
Indices to the atoms in the original atom array (stack).
|
|
160
|
+
Equal to
|
|
161
|
+
``numpy.tile(np.arange(atoms.array_length()), (1 + 2 * amount) ** 3)``.
|
|
162
|
+
|
|
163
|
+
See also
|
|
164
|
+
--------
|
|
165
|
+
repeat_box_coord
|
|
166
|
+
|
|
167
|
+
Examples
|
|
168
|
+
--------
|
|
169
|
+
|
|
170
|
+
>>> array = AtomArray(length=2)
|
|
171
|
+
>>> array.coord = np.array([[1,5,3], [-1,2,5]], dtype=float)
|
|
172
|
+
>>> array.box = np.array([[10,0,0], [0,10,0], [0,0,10]], dtype=float)
|
|
173
|
+
>>> repeated, indices = repeat_box(array)
|
|
174
|
+
>>> print(repeated.coord)
|
|
175
|
+
[[ 1. 5. 3.]
|
|
176
|
+
[ -1. 2. 5.]
|
|
177
|
+
[ -9. -5. -7.]
|
|
178
|
+
[-11. -8. -5.]
|
|
179
|
+
[ -9. -5. 3.]
|
|
180
|
+
[-11. -8. 5.]
|
|
181
|
+
[ -9. -5. 13.]
|
|
182
|
+
[-11. -8. 15.]
|
|
183
|
+
[ -9. 5. -7.]
|
|
184
|
+
[-11. 2. -5.]
|
|
185
|
+
[ -9. 5. 3.]
|
|
186
|
+
[-11. 2. 5.]
|
|
187
|
+
[ -9. 5. 13.]
|
|
188
|
+
[-11. 2. 15.]
|
|
189
|
+
[ -9. 15. -7.]
|
|
190
|
+
[-11. 12. -5.]
|
|
191
|
+
[ -9. 15. 3.]
|
|
192
|
+
[-11. 12. 5.]
|
|
193
|
+
[ -9. 15. 13.]
|
|
194
|
+
[-11. 12. 15.]
|
|
195
|
+
[ 1. -5. -7.]
|
|
196
|
+
[ -1. -8. -5.]
|
|
197
|
+
[ 1. -5. 3.]
|
|
198
|
+
[ -1. -8. 5.]
|
|
199
|
+
[ 1. -5. 13.]
|
|
200
|
+
[ -1. -8. 15.]
|
|
201
|
+
[ 1. 5. -7.]
|
|
202
|
+
[ -1. 2. -5.]
|
|
203
|
+
[ 1. 5. 13.]
|
|
204
|
+
[ -1. 2. 15.]
|
|
205
|
+
[ 1. 15. -7.]
|
|
206
|
+
[ -1. 12. -5.]
|
|
207
|
+
[ 1. 15. 3.]
|
|
208
|
+
[ -1. 12. 5.]
|
|
209
|
+
[ 1. 15. 13.]
|
|
210
|
+
[ -1. 12. 15.]
|
|
211
|
+
[ 11. -5. -7.]
|
|
212
|
+
[ 9. -8. -5.]
|
|
213
|
+
[ 11. -5. 3.]
|
|
214
|
+
[ 9. -8. 5.]
|
|
215
|
+
[ 11. -5. 13.]
|
|
216
|
+
[ 9. -8. 15.]
|
|
217
|
+
[ 11. 5. -7.]
|
|
218
|
+
[ 9. 2. -5.]
|
|
219
|
+
[ 11. 5. 3.]
|
|
220
|
+
[ 9. 2. 5.]
|
|
221
|
+
[ 11. 5. 13.]
|
|
222
|
+
[ 9. 2. 15.]
|
|
223
|
+
[ 11. 15. -7.]
|
|
224
|
+
[ 9. 12. -5.]
|
|
225
|
+
[ 11. 15. 3.]
|
|
226
|
+
[ 9. 12. 5.]
|
|
227
|
+
[ 11. 15. 13.]
|
|
228
|
+
[ 9. 12. 15.]]
|
|
229
|
+
>>> print(indices)
|
|
230
|
+
[0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
|
|
231
|
+
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]
|
|
232
|
+
"""
|
|
233
|
+
if atoms.box is None:
|
|
234
|
+
raise BadStructureError("Structure has no box")
|
|
235
|
+
|
|
236
|
+
repeat_coord, indices = repeat_box_coord(atoms.coord, atoms.box)
|
|
237
|
+
# Unroll repeated coordinates for input to 'repeat()'
|
|
238
|
+
if repeat_coord.ndim == 2:
|
|
239
|
+
repeat_coord = repeat_coord.reshape(-1, atoms.array_length(), 3)
|
|
240
|
+
else: # ndim == 3
|
|
241
|
+
repeat_coord = repeat_coord.reshape(
|
|
242
|
+
atoms.stack_depth(), -1, atoms.array_length(), 3
|
|
243
|
+
)
|
|
244
|
+
repeat_coord = np.swapaxes(repeat_coord, 0, 1)
|
|
245
|
+
return repeat(atoms, repeat_coord), indices
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def repeat_box_coord(coord, box, amount=1):
|
|
249
|
+
r"""
|
|
250
|
+
Similar to :func:`repeat_box()`, repeat the coordinates in a box by
|
|
251
|
+
duplicating and placing them in adjacent boxes.
|
|
252
|
+
|
|
253
|
+
Parameters
|
|
254
|
+
----------
|
|
255
|
+
coord : ndarray, dtype=float, shape=(n,3) or shape=(m,n,3)
|
|
256
|
+
The coordinates to be repeated.
|
|
257
|
+
box : ndarray, dtype=float, shape=(3,3) or shape=(m,3,3)
|
|
258
|
+
The reference box.
|
|
259
|
+
If only one box is provided, i.e. the shape is *(3,3)*,
|
|
260
|
+
the box is used for all models *m*, if the coordinates shape
|
|
261
|
+
is *(m,n,3)*.
|
|
262
|
+
amount : int, optional
|
|
263
|
+
The amount of boxes that are created in each direction of the
|
|
264
|
+
central box.
|
|
265
|
+
Hence, the total amount of boxes is
|
|
266
|
+
:math:`(1 + 2 \cdot \text{amount}) ^ 3`.
|
|
267
|
+
By default, one box is created in each direction, totalling in
|
|
268
|
+
27 boxes.
|
|
269
|
+
|
|
270
|
+
Returns
|
|
271
|
+
-------
|
|
272
|
+
repeated : ndarray, dtype=float, shape=(p,3) or shape=(m,p,3)
|
|
273
|
+
The repeated coordinates, with the same dimension as the input
|
|
274
|
+
`coord`.
|
|
275
|
+
Includes the original coordinates (central box) in the beginning
|
|
276
|
+
of the array.
|
|
277
|
+
indices : ndarray, dtype=int, shape=(p,3)
|
|
278
|
+
Indices to the coordinates in the original array.
|
|
279
|
+
Equal to
|
|
280
|
+
``numpy.tile(np.arange(coord.shape[-2]), (1 + 2 * amount) ** 3)``.
|
|
281
|
+
"""
|
|
282
|
+
if not isinstance(amount, Integral):
|
|
283
|
+
raise TypeError("The amount must be an integer")
|
|
284
|
+
# List of numpy arrays for each box repeat
|
|
285
|
+
coords_for_boxes = [coord]
|
|
286
|
+
for i in range(-amount, amount+1):
|
|
287
|
+
for j in range(-amount, amount+1):
|
|
288
|
+
for k in range(-amount, amount+1):
|
|
289
|
+
# Omit the central box
|
|
290
|
+
if i != 0 or j != 0 or k != 0:
|
|
291
|
+
temp_coord = coord.copy()
|
|
292
|
+
# Shift coordinates to adjacent box/unit cell
|
|
293
|
+
translation_vec = np.sum(
|
|
294
|
+
box * np.array([i,j,k])[:, np.newaxis],
|
|
295
|
+
axis=-2
|
|
296
|
+
)
|
|
297
|
+
# 'newaxis' to perform same translation on all
|
|
298
|
+
# atoms for each model
|
|
299
|
+
temp_coord += translation_vec[..., np.newaxis, :]
|
|
300
|
+
coords_for_boxes.append(temp_coord)
|
|
301
|
+
return (
|
|
302
|
+
np.concatenate(coords_for_boxes, axis=-2),
|
|
303
|
+
np.tile(np.arange(coord.shape[-2]), (1 + 2 * amount) ** 3)
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def move_inside_box(coord, box):
|
|
308
|
+
r"""
|
|
309
|
+
Move all coordinates into the given box, with the box vectors
|
|
310
|
+
originating at *(0,0,0)*.
|
|
311
|
+
|
|
312
|
+
Coordinates are outside the box, when they cannot be represented by
|
|
313
|
+
a linear combination of the box vectors with scalar factors
|
|
314
|
+
:math:`0 \le a_i \le 1`.
|
|
315
|
+
In this case the affected coordinates are translated by the box
|
|
316
|
+
vectors, so that they are inside the box.
|
|
317
|
+
|
|
318
|
+
Parameters
|
|
319
|
+
----------
|
|
320
|
+
coord : ndarray, dtype=float, shape=(n,3) or shape=(m,n,3)
|
|
321
|
+
The coordinates for one or multiple models.
|
|
322
|
+
box : ndarray, dtype=float, shape=(3,3) or shape=(m,3,3)
|
|
323
|
+
The box(es) for one or multiple models.
|
|
324
|
+
When `coord` is given for multiple models, :attr:`box` must be
|
|
325
|
+
given for multiple models as well.
|
|
326
|
+
|
|
327
|
+
Returns
|
|
328
|
+
-------
|
|
329
|
+
moved_coord : ndarray, dtype=float, shape=(n,3) or shape=(m,n,3)
|
|
330
|
+
The moved coordinates.
|
|
331
|
+
Has the same shape is the input `coord`.
|
|
332
|
+
|
|
333
|
+
Examples
|
|
334
|
+
--------
|
|
335
|
+
|
|
336
|
+
>>> box = np.array([[10,0,0], [0,10,0], [0,0,10]], dtype=float)
|
|
337
|
+
>>> inside_coord = [ 1, 2, 3]
|
|
338
|
+
>>> outside_coord = [ 1, 22, 54]
|
|
339
|
+
>>> other_outside_coord = [-4, 8, 6]
|
|
340
|
+
>>> coord = np.stack([inside_coord, outside_coord, other_outside_coord])
|
|
341
|
+
>>> print(coord)
|
|
342
|
+
[[ 1 2 3]
|
|
343
|
+
[ 1 22 54]
|
|
344
|
+
[-4 8 6]]
|
|
345
|
+
>>> moved_coord = move_inside_box(coord, box)
|
|
346
|
+
>>> print(moved_coord.astype(int))
|
|
347
|
+
[[1 2 3]
|
|
348
|
+
[1 2 4]
|
|
349
|
+
[6 8 6]]
|
|
350
|
+
"""
|
|
351
|
+
fractions = coord_to_fraction(coord, box)
|
|
352
|
+
fractions_rem = fractions % 1
|
|
353
|
+
return fraction_to_coord(fractions_rem, box)
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def remove_pbc(atoms, selection=None):
|
|
357
|
+
"""
|
|
358
|
+
Remove segmentation caused by periodic boundary conditions from each
|
|
359
|
+
molecule in the given structure.
|
|
360
|
+
|
|
361
|
+
In this process the centroid of each molecule is moved into the
|
|
362
|
+
dimensions of the box.
|
|
363
|
+
To determine the molecules the structure is required to have an
|
|
364
|
+
associated `BondList`.
|
|
365
|
+
Otherwise segmentation removal is performed on a per-chain basis.
|
|
366
|
+
|
|
367
|
+
Parameters
|
|
368
|
+
----------
|
|
369
|
+
atoms : AtomArray, shape=(n,) or AtomArrayStack, shape=(m,n)
|
|
370
|
+
The potentially segmented structure.
|
|
371
|
+
The :attr:`box` attribute must be set in the structure.
|
|
372
|
+
An associated :attr:`bonds` attribute is recommended.
|
|
373
|
+
selection : ndarray, dtype=bool, shape=(n,)
|
|
374
|
+
Specifies which parts of `atoms` are sanitized, i.e the
|
|
375
|
+
segmentation is removed.
|
|
376
|
+
|
|
377
|
+
Returns
|
|
378
|
+
-------
|
|
379
|
+
sanitized_atoms : AtomArray or AtomArrayStack
|
|
380
|
+
The input structure with removed segmentation over periodic
|
|
381
|
+
boundaries.
|
|
382
|
+
|
|
383
|
+
See also
|
|
384
|
+
--------
|
|
385
|
+
remove_pbc_from_coord
|
|
386
|
+
|
|
387
|
+
Notes
|
|
388
|
+
-----
|
|
389
|
+
This function ensures that adjacent atoms in the input
|
|
390
|
+
:class:`AtomArray`/:class:`AtomArrayStack` are spatially close to
|
|
391
|
+
each other, i.e. their distance to each other is be smaller than the
|
|
392
|
+
half box size.
|
|
393
|
+
"""
|
|
394
|
+
# Avoid circular import
|
|
395
|
+
from .geometry import centroid
|
|
396
|
+
|
|
397
|
+
if atoms.box is None:
|
|
398
|
+
raise BadStructureError(
|
|
399
|
+
"The 'box' attribute must be set in the structure"
|
|
400
|
+
)
|
|
401
|
+
new_atoms = atoms.copy()
|
|
402
|
+
|
|
403
|
+
if atoms.bonds is not None:
|
|
404
|
+
molecule_masks = get_molecule_masks(atoms)
|
|
405
|
+
else:
|
|
406
|
+
molecule_masks = get_chain_masks(atoms, get_chain_starts(atoms))
|
|
407
|
+
|
|
408
|
+
for mask in molecule_masks:
|
|
409
|
+
if selection is not None:
|
|
410
|
+
mask &= selection
|
|
411
|
+
# Remove segmentation in molecule
|
|
412
|
+
new_atoms.coord[..., mask, :] = remove_pbc_from_coord(
|
|
413
|
+
new_atoms.coord[..., mask, :], atoms.box
|
|
414
|
+
)
|
|
415
|
+
# Put center of molecule into box
|
|
416
|
+
center = centroid(new_atoms.coord[..., mask, :])[..., np.newaxis, :]
|
|
417
|
+
center_in_box = move_inside_box(
|
|
418
|
+
center, new_atoms.box
|
|
419
|
+
)
|
|
420
|
+
new_atoms.coord[..., mask, :] += (center_in_box - center)
|
|
421
|
+
|
|
422
|
+
return new_atoms
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def remove_pbc_from_coord(coord, box):
|
|
426
|
+
"""
|
|
427
|
+
Remove segmentation caused by periodic boundary conditions from
|
|
428
|
+
given coordinates.
|
|
429
|
+
|
|
430
|
+
In this process the first coordinate is taken as origin and
|
|
431
|
+
is moved inside the box.
|
|
432
|
+
All other coordinates are assembled relative to the origin by using
|
|
433
|
+
the displacement coordinates in adjacent array positions.
|
|
434
|
+
Basically, this function performs the reverse action of
|
|
435
|
+
:func:`move_inside_box()`.
|
|
436
|
+
|
|
437
|
+
Parameters
|
|
438
|
+
----------
|
|
439
|
+
coord : ndarray, dtype=float, shape=(m,n,3) or shape=(n,3)
|
|
440
|
+
The coordinates of the potentially segmented structure.
|
|
441
|
+
box : ndarray, dtype=float, shape=(m,3,3) or shape=(3,3)
|
|
442
|
+
The simulation box or unit cell that is used as periodic
|
|
443
|
+
boundary.
|
|
444
|
+
The amount of dimensions must fit the `coord` parameter.
|
|
445
|
+
|
|
446
|
+
Returns
|
|
447
|
+
-------
|
|
448
|
+
sanitized_coord : ndarray, dtype=float, shape=(m,n,3) or shape=(n,3)
|
|
449
|
+
The reassembled coordinates.
|
|
450
|
+
|
|
451
|
+
See also
|
|
452
|
+
--------
|
|
453
|
+
remove_pbc_from_coord
|
|
454
|
+
move_inside_box
|
|
455
|
+
|
|
456
|
+
Notes
|
|
457
|
+
-----
|
|
458
|
+
This function solves a common problem from MD simulation output:
|
|
459
|
+
When atoms move over the periodic boundary, they reappear on the
|
|
460
|
+
other side of the box, segmenting the structure.
|
|
461
|
+
This function reassembles the given coordinates, removing the
|
|
462
|
+
segmentation.
|
|
463
|
+
"""
|
|
464
|
+
|
|
465
|
+
# Import in function to avoid circular import
|
|
466
|
+
from .geometry import index_displacement
|
|
467
|
+
# Get the PBC-sanitized displacements of all coordinates
|
|
468
|
+
# to the respective next coordinate
|
|
469
|
+
index_pairs = np.stack(
|
|
470
|
+
[
|
|
471
|
+
np.arange(0, coord.shape[-2] - 1),
|
|
472
|
+
np.arange(1, coord.shape[-2] )
|
|
473
|
+
],
|
|
474
|
+
axis=1
|
|
475
|
+
)
|
|
476
|
+
neighbour_disp = index_displacement(
|
|
477
|
+
coord, index_pairs, box=box, periodic=True
|
|
478
|
+
)
|
|
479
|
+
# Get the PBC-sanitized displacements of all but the first
|
|
480
|
+
# coordinates to (0,0,0)
|
|
481
|
+
absolute_disp = np.cumsum(neighbour_disp, axis=-2)
|
|
482
|
+
# The first coordinate should be inside the box
|
|
483
|
+
base_coord = move_inside_box(coord[..., 0:1, :], box)
|
|
484
|
+
# The new coordinates are obtained by adding the displacements
|
|
485
|
+
# to the new origin
|
|
486
|
+
sanitized_coord = np.zeros(coord.shape, coord.dtype)
|
|
487
|
+
sanitized_coord[..., 0:1, :] = base_coord
|
|
488
|
+
sanitized_coord[..., 1:, :] = base_coord + absolute_disp
|
|
489
|
+
return sanitized_coord
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
def coord_to_fraction(coord, box):
|
|
493
|
+
"""
|
|
494
|
+
Transform coordinates to fractions of box vectors.
|
|
495
|
+
|
|
496
|
+
Parameters
|
|
497
|
+
----------
|
|
498
|
+
coord : ndarray, dtype=float, shape=(n,3) or shape=(m,n,3)
|
|
499
|
+
The coordinates for one or multiple models.
|
|
500
|
+
box : ndarray, dtype=float, shape=(3,3) or shape=(m,3,3)
|
|
501
|
+
The box(es) for one or multiple models.
|
|
502
|
+
When `coord` is given for multiple models, :attr:`box` must be
|
|
503
|
+
given for multiple models as well.
|
|
504
|
+
|
|
505
|
+
Returns
|
|
506
|
+
-------
|
|
507
|
+
fraction : ndarray, dtype=float, shape=(n,3) or shape=(m,n,3)
|
|
508
|
+
The fractions of the box vectors.
|
|
509
|
+
|
|
510
|
+
See also
|
|
511
|
+
--------
|
|
512
|
+
fraction_to_coord
|
|
513
|
+
|
|
514
|
+
Examples
|
|
515
|
+
--------
|
|
516
|
+
|
|
517
|
+
>>> box = np.array([[5,0,0], [0,5,0], [0,5,5]], dtype=float)
|
|
518
|
+
>>> coord = np.array(
|
|
519
|
+
... [[1,1,1], [10,0,0], [0,0,10], [-5,2,1]],
|
|
520
|
+
... dtype=float
|
|
521
|
+
... )
|
|
522
|
+
>>> print(coord)
|
|
523
|
+
[[ 1. 1. 1.]
|
|
524
|
+
[10. 0. 0.]
|
|
525
|
+
[ 0. 0. 10.]
|
|
526
|
+
[-5. 2. 1.]]
|
|
527
|
+
>>> fractions = coord_to_fraction(coord, box)
|
|
528
|
+
>>> print(fractions)
|
|
529
|
+
[[ 0.2 0.0 0.2]
|
|
530
|
+
[ 2.0 0.0 0.0]
|
|
531
|
+
[ 0.0 -2.0 2.0]
|
|
532
|
+
[-1.0 0.2 0.2]]
|
|
533
|
+
"""
|
|
534
|
+
return np.matmul(coord, linalg.inv(box))
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
def fraction_to_coord(fraction, box):
|
|
538
|
+
"""
|
|
539
|
+
Transform fractions of box vectors to coordinates.
|
|
540
|
+
|
|
541
|
+
This is the reverse operation of :func:`coord_to_fraction()`.
|
|
542
|
+
|
|
543
|
+
Parameters
|
|
544
|
+
----------
|
|
545
|
+
fraction : ndarray, dtype=float, shape=(n,3) or shape=(m,n,3)
|
|
546
|
+
The fractions of the box vectors for one or multiple models.
|
|
547
|
+
box : ndarray, dtype=float, shape=(3,3) or shape=(m,3,3)
|
|
548
|
+
The box(es) for one or multiple models.
|
|
549
|
+
When `coord` is given for multiple models, :attr:`box` must be
|
|
550
|
+
given for multiple models as well.
|
|
551
|
+
|
|
552
|
+
Returns
|
|
553
|
+
-------
|
|
554
|
+
coord : ndarray, dtype=float, shape=(n,3) or shape=(m,n,3)
|
|
555
|
+
The coordinates.
|
|
556
|
+
|
|
557
|
+
See also
|
|
558
|
+
--------
|
|
559
|
+
coord_to_fraction
|
|
560
|
+
"""
|
|
561
|
+
return np.matmul(fraction, box)
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
def is_orthogonal(box):
|
|
565
|
+
"""
|
|
566
|
+
Check, whether a box or multiple boxes is/are orthogonal.
|
|
567
|
+
|
|
568
|
+
A box is orthogonal when the dot product of all box vectors with
|
|
569
|
+
each other is 0.
|
|
570
|
+
|
|
571
|
+
Parameters
|
|
572
|
+
----------
|
|
573
|
+
box : ndarray, dtype=float, shape=(3,3) or shape=(m,3,3)
|
|
574
|
+
A single box or multiple boxes.
|
|
575
|
+
|
|
576
|
+
Returns
|
|
577
|
+
-------
|
|
578
|
+
is_orthgonal : bool or ndarray, shape=(m,), dtype=bool
|
|
579
|
+
True, if the box vectors are orthogonal, false otherwise
|
|
580
|
+
|
|
581
|
+
Notes
|
|
582
|
+
-----
|
|
583
|
+
Due to possible numerical errors, this function also evaluates two
|
|
584
|
+
vectors as orthogonal, when their dot product is not exactly zero,
|
|
585
|
+
but it is within a small tolerance (:math:`10^{-6}`).
|
|
586
|
+
"""
|
|
587
|
+
# Fix numerical errors, as values, that are actually 0,
|
|
588
|
+
# might not be calculated as such
|
|
589
|
+
tol = 1e-6
|
|
590
|
+
return (np.abs(vector_dot(box[..., 0, :], box[..., 1, :])) < tol) & \
|
|
591
|
+
(np.abs(vector_dot(box[..., 0, :], box[..., 2, :])) < tol) & \
|
|
592
|
+
(np.abs(vector_dot(box[..., 1, :], box[..., 2, :])) < tol)
|
|
Binary file
|