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,561 @@
|
|
|
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
|
+
import warnings
|
|
6
|
+
from numbers import Integral
|
|
7
|
+
import numpy as np
|
|
8
|
+
from biotite.sequence.align.alignment import get_codes
|
|
9
|
+
from biotite.sequence.alphabet import LetterAlphabet
|
|
10
|
+
from biotite.sequence.seqtypes import (
|
|
11
|
+
GeneralSequence,
|
|
12
|
+
NucleotideSequence,
|
|
13
|
+
ProteinSequence,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__name__ = "biotite.sequence"
|
|
17
|
+
__author__ = "Maximilian Greil"
|
|
18
|
+
__all__ = ["SequenceProfile"]
|
|
19
|
+
|
|
20
|
+
# Abbreviations
|
|
21
|
+
_NUC_DNA_ALPH = NucleotideSequence.alphabet_unamb
|
|
22
|
+
_NUC_RNA_ALPH = LetterAlphabet(["A", "C", "G", "U"])
|
|
23
|
+
_PROT_ALPH = ProteinSequence.alphabet
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _determine_common_alphabet(alphabets):
|
|
27
|
+
"""
|
|
28
|
+
Determine the common alphabet from a list of alphabets, that
|
|
29
|
+
extends all alphabets.
|
|
30
|
+
"""
|
|
31
|
+
common_alphabet = alphabets[0]
|
|
32
|
+
for alphabet in alphabets[1:]:
|
|
33
|
+
if not common_alphabet.extends(alphabet):
|
|
34
|
+
if alphabet.extends(common_alphabet):
|
|
35
|
+
common_alphabet = alphabet
|
|
36
|
+
else:
|
|
37
|
+
raise ValueError(
|
|
38
|
+
"There is no common alphabet that extends all alphabets"
|
|
39
|
+
)
|
|
40
|
+
return common_alphabet
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _codes_to_iupac(frequency, codes, maxes, row):
|
|
44
|
+
"""
|
|
45
|
+
Returns IUPAC code for a row of 'symbols' with none, one or
|
|
46
|
+
multiple maximum positions.
|
|
47
|
+
"""
|
|
48
|
+
if np.sum(frequency) == 0:
|
|
49
|
+
raise ValueError(
|
|
50
|
+
f"There is an empty column in the 'symbols' frequency table. "
|
|
51
|
+
f"This doesn't make sense in context of an alignment. "
|
|
52
|
+
f"Please check the 'symbols' frequency table in row {row}."
|
|
53
|
+
)
|
|
54
|
+
key = tuple(np.where(frequency == maxes)[0])
|
|
55
|
+
return codes[key]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class SequenceProfile(object):
|
|
59
|
+
"""
|
|
60
|
+
A :class:`SequenceProfile` object stores information about a
|
|
61
|
+
sequence profile of aligned sequences.
|
|
62
|
+
It is possible to calculate and return its consensus sequence.
|
|
63
|
+
|
|
64
|
+
This class saves the position frequency matrix
|
|
65
|
+
(position count matrix) 'symbols' of the occurrences of each
|
|
66
|
+
alphabet symbol at each position.
|
|
67
|
+
It also saves the number of gaps at each position in the array
|
|
68
|
+
'gaps'.
|
|
69
|
+
|
|
70
|
+
With :meth:`from_alignment()` a :class:`SequenceProfile` object can
|
|
71
|
+
be created from an indefinite number of aligned sequences.
|
|
72
|
+
|
|
73
|
+
With :meth:`probability_matrix()` the position probability matrix
|
|
74
|
+
can be created based on 'symbols' and a pseudocount.
|
|
75
|
+
|
|
76
|
+
With :meth:`log_odds_matrix()` the position weight matrix can
|
|
77
|
+
be created based on the before calculated position probability
|
|
78
|
+
matrix and the background frequencies.
|
|
79
|
+
|
|
80
|
+
With :meth:`sequence_probability_from_matrix()` the probability of a
|
|
81
|
+
sequence can be calculated based on the before calculated position
|
|
82
|
+
probability matrix of this instance of object SequenceProfile.
|
|
83
|
+
|
|
84
|
+
With :meth:`sequence_score_from_matrix()` the score of a sequence
|
|
85
|
+
can be calculated based on the before calculated position weight
|
|
86
|
+
matrix of this instance of object SequenceProfile.
|
|
87
|
+
|
|
88
|
+
All attributes of this class are publicly accessible.
|
|
89
|
+
|
|
90
|
+
Parameters
|
|
91
|
+
----------
|
|
92
|
+
symbols : ndarray, dtype=int, shape=(n,k)
|
|
93
|
+
This matrix simply saves for each position how often absolutely
|
|
94
|
+
each symbol is present.
|
|
95
|
+
gaps : ndarray, dtype=int, shape=n
|
|
96
|
+
Array which indicates the number of gaps at each position.
|
|
97
|
+
alphabet : Alphabet, length=k
|
|
98
|
+
Alphabet of sequences of sequence profile.
|
|
99
|
+
|
|
100
|
+
Attributes
|
|
101
|
+
----------
|
|
102
|
+
symbols : ndarray, dtype=int, shape=(n,k)
|
|
103
|
+
This matrix simply saves for each position how often absolutely
|
|
104
|
+
each symbol is present.
|
|
105
|
+
gaps : ndarray, dtype=int, shape=n
|
|
106
|
+
Array which indicates the number of gaps at each position.
|
|
107
|
+
alphabet : Alphabet, length=k
|
|
108
|
+
Alphabet of sequences of sequence profile
|
|
109
|
+
|
|
110
|
+
Examples
|
|
111
|
+
--------
|
|
112
|
+
|
|
113
|
+
Create a profile from a multiple sequence alignment:
|
|
114
|
+
|
|
115
|
+
>>> sequences = [
|
|
116
|
+
... NucleotideSequence("CGCTCATTC"),
|
|
117
|
+
... NucleotideSequence("CGCTATTC"),
|
|
118
|
+
... NucleotideSequence("CCCTCAATC"),
|
|
119
|
+
... ]
|
|
120
|
+
>>> msa, _, _, _ = align_multiple(
|
|
121
|
+
... sequences, SubstitutionMatrix.std_nucleotide_matrix(), gap_penalty=-5
|
|
122
|
+
... )
|
|
123
|
+
>>> print(msa)
|
|
124
|
+
CGCTCATTC
|
|
125
|
+
CGCT-ATTC
|
|
126
|
+
CCCTCAATC
|
|
127
|
+
>>> profile = SequenceProfile.from_alignment(msa)
|
|
128
|
+
>>> print(profile)
|
|
129
|
+
A C G T
|
|
130
|
+
0 0 3 0 0
|
|
131
|
+
1 0 1 2 0
|
|
132
|
+
2 0 3 0 0
|
|
133
|
+
3 0 0 0 3
|
|
134
|
+
4 0 2 0 0
|
|
135
|
+
5 3 0 0 0
|
|
136
|
+
6 1 0 0 2
|
|
137
|
+
7 0 0 0 3
|
|
138
|
+
8 0 3 0 0
|
|
139
|
+
>>> print(profile.gaps)
|
|
140
|
+
[0 0 0 0 1 0 0 0 0]
|
|
141
|
+
|
|
142
|
+
Slice the profile (masks and index arrays are also supported):
|
|
143
|
+
|
|
144
|
+
>>> print(profile[2:])
|
|
145
|
+
A C G T
|
|
146
|
+
0 0 3 0 0
|
|
147
|
+
1 0 0 0 3
|
|
148
|
+
2 0 2 0 0
|
|
149
|
+
3 3 0 0 0
|
|
150
|
+
4 1 0 0 2
|
|
151
|
+
5 0 0 0 3
|
|
152
|
+
6 0 3 0 0
|
|
153
|
+
|
|
154
|
+
Use the profile to compute the position probability matrix:
|
|
155
|
+
|
|
156
|
+
>>> print(profile.probability_matrix())
|
|
157
|
+
[[0.000 1.000 0.000 0.000]
|
|
158
|
+
[0.000 0.333 0.667 0.000]
|
|
159
|
+
[0.000 1.000 0.000 0.000]
|
|
160
|
+
[0.000 0.000 0.000 1.000]
|
|
161
|
+
[0.000 1.000 0.000 0.000]
|
|
162
|
+
[1.000 0.000 0.000 0.000]
|
|
163
|
+
[0.333 0.000 0.000 0.667]
|
|
164
|
+
[0.000 0.000 0.000 1.000]
|
|
165
|
+
[0.000 1.000 0.000 0.000]]
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
def __init__(self, symbols, gaps, alphabet):
|
|
169
|
+
self._symbols = symbols
|
|
170
|
+
self._gaps = gaps
|
|
171
|
+
self._alphabet = alphabet
|
|
172
|
+
|
|
173
|
+
if len(alphabet) != symbols.shape[1]:
|
|
174
|
+
raise ValueError(
|
|
175
|
+
f"The given alphabet doesn't have the same length "
|
|
176
|
+
f"({len(alphabet)}) as the number of columns "
|
|
177
|
+
f"({symbols.shape[1]}) in the 'symbols' frequency table."
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
if gaps.shape[0] != symbols.shape[0]:
|
|
181
|
+
raise ValueError(
|
|
182
|
+
f"The given 'gaps' position matrix doesn't have the same "
|
|
183
|
+
f"length ({gaps.shape[0]}) as the 'symbols' "
|
|
184
|
+
f"frequency table ({symbols.shape[0]})"
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
@property
|
|
188
|
+
def symbols(self):
|
|
189
|
+
return self._symbols
|
|
190
|
+
|
|
191
|
+
@property
|
|
192
|
+
def gaps(self):
|
|
193
|
+
return self._gaps
|
|
194
|
+
|
|
195
|
+
@property
|
|
196
|
+
def alphabet(self):
|
|
197
|
+
return self._alphabet
|
|
198
|
+
|
|
199
|
+
@symbols.setter
|
|
200
|
+
def symbols(self, new_symbols):
|
|
201
|
+
if not new_symbols.shape == self.symbols.shape:
|
|
202
|
+
raise ValueError(
|
|
203
|
+
f"New ndarray 'symbols' must be of same shape "
|
|
204
|
+
f"{self.symbols.shape} as the old one"
|
|
205
|
+
)
|
|
206
|
+
self._symbols = new_symbols
|
|
207
|
+
|
|
208
|
+
@gaps.setter
|
|
209
|
+
def gaps(self, new_gaps):
|
|
210
|
+
if not new_gaps.shape == self.gaps.shape:
|
|
211
|
+
raise ValueError(
|
|
212
|
+
f"New ndarray 'gaps' must be of same shape "
|
|
213
|
+
f"{self.gaps.shape} as the old one"
|
|
214
|
+
)
|
|
215
|
+
self._gaps = new_gaps
|
|
216
|
+
|
|
217
|
+
def __str__(self):
|
|
218
|
+
# Add an additional row and column for the position and symbol indicators
|
|
219
|
+
print_matrix = np.full(
|
|
220
|
+
(self.symbols.shape[0] + 1, self.symbols.shape[1] + 1), "", dtype=object
|
|
221
|
+
)
|
|
222
|
+
print_matrix[1:, 1:] = self.symbols.astype(str)
|
|
223
|
+
print_matrix[0, 1:] = [str(sym) for sym in self.alphabet]
|
|
224
|
+
print_matrix[1:, 0] = [str(i) for i in range(self.symbols.shape[0])]
|
|
225
|
+
max_len = len(max(print_matrix.flatten(), key=len))
|
|
226
|
+
return "\n".join(
|
|
227
|
+
[
|
|
228
|
+
" ".join([str(cell).rjust(max_len) for cell in row])
|
|
229
|
+
for row in print_matrix
|
|
230
|
+
]
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
def __repr__(self):
|
|
234
|
+
return (
|
|
235
|
+
f"SequenceProfile(np.{np.array_repr(self.symbols)}, "
|
|
236
|
+
f"np.{np.array_repr(self.gaps)}, Alphabet({self.alphabet}))"
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
def __eq__(self, item):
|
|
240
|
+
if not isinstance(item, SequenceProfile):
|
|
241
|
+
return False
|
|
242
|
+
if not np.array_equal(self.symbols, item.symbols):
|
|
243
|
+
return False
|
|
244
|
+
if not np.array_equal(self.gaps, item.gaps):
|
|
245
|
+
return False
|
|
246
|
+
if not self.alphabet == item.alphabet:
|
|
247
|
+
return False
|
|
248
|
+
return True
|
|
249
|
+
|
|
250
|
+
@staticmethod
|
|
251
|
+
def from_alignment(alignment, alphabet=None):
|
|
252
|
+
"""
|
|
253
|
+
Get an object of :class:`SequenceProfile` from an object of
|
|
254
|
+
:class:`Alignment`.
|
|
255
|
+
|
|
256
|
+
Based on the sequences of the alignment, the SequenceProfile
|
|
257
|
+
parameters symbols and gaps are calculated.
|
|
258
|
+
|
|
259
|
+
Parameters
|
|
260
|
+
----------
|
|
261
|
+
alignment : Alignment
|
|
262
|
+
An Alignment object to create the SequenceProfile object
|
|
263
|
+
from.
|
|
264
|
+
alphabet : bool
|
|
265
|
+
This alphabet will be used when creating the SequenceProfile
|
|
266
|
+
object. If no alphabet is selected, the alphabet for this
|
|
267
|
+
:class:`SequenceProfile`.
|
|
268
|
+
object will be calculated from the sequences of object
|
|
269
|
+
Alignment.
|
|
270
|
+
|
|
271
|
+
Returns
|
|
272
|
+
-------
|
|
273
|
+
profile: SequenceProfile
|
|
274
|
+
The created :class:`SequenceProfile` object.
|
|
275
|
+
"""
|
|
276
|
+
sequences = get_codes(alignment)
|
|
277
|
+
if alphabet is None:
|
|
278
|
+
alphabet = _determine_common_alphabet(
|
|
279
|
+
[seq.alphabet for seq in alignment.sequences]
|
|
280
|
+
)
|
|
281
|
+
else:
|
|
282
|
+
for alph in (seq.alphabet for seq in alignment.sequences):
|
|
283
|
+
if not alphabet.extends(alph):
|
|
284
|
+
raise ValueError(
|
|
285
|
+
"The given alphabet is incompatible with a least one "
|
|
286
|
+
"alphabet of the given sequences"
|
|
287
|
+
)
|
|
288
|
+
symbols = np.zeros((len(sequences[0]), len(alphabet)), dtype=int)
|
|
289
|
+
gaps = np.zeros(len(sequences[0]), dtype=int)
|
|
290
|
+
sequences = np.transpose(sequences)
|
|
291
|
+
for i in range(len(sequences)):
|
|
292
|
+
row = np.where(sequences[i,] == -1, len(alphabet), sequences[i,])
|
|
293
|
+
count = np.bincount(row, minlength=len(alphabet) + 1)
|
|
294
|
+
symbols[i,] = count[0 : len(alphabet)]
|
|
295
|
+
gaps[i] = count[-1]
|
|
296
|
+
return SequenceProfile(symbols, gaps, alphabet)
|
|
297
|
+
|
|
298
|
+
def to_consensus(self, as_general=False):
|
|
299
|
+
"""
|
|
300
|
+
Get the consensus sequence for this SequenceProfile object.
|
|
301
|
+
|
|
302
|
+
Parameters
|
|
303
|
+
----------
|
|
304
|
+
as_general : bool
|
|
305
|
+
If true, returns consensus sequence as GeneralSequence
|
|
306
|
+
object.
|
|
307
|
+
Otherwise, the consensus sequence object type is chosen
|
|
308
|
+
based on the alphabet of this SequenceProfile object.
|
|
309
|
+
|
|
310
|
+
Returns
|
|
311
|
+
-------
|
|
312
|
+
consensus: Sequence
|
|
313
|
+
The calculated consensus sequence.
|
|
314
|
+
"""
|
|
315
|
+
# https://en.wikipedia.org/wiki/International_Union_of_Pure_and_Applied_Chemistry#Amino_acid_and_nucleotide_base_codes
|
|
316
|
+
if as_general:
|
|
317
|
+
return self._general_to_consensus()
|
|
318
|
+
elif self.alphabet == _NUC_DNA_ALPH:
|
|
319
|
+
return NucleotideSequence(self._dna_to_consensus())
|
|
320
|
+
elif self.alphabet == _NUC_RNA_ALPH:
|
|
321
|
+
return NucleotideSequence(self._rna_to_consensus())
|
|
322
|
+
elif self.alphabet == _PROT_ALPH:
|
|
323
|
+
return self._prot_to_consensus()
|
|
324
|
+
return self._general_to_consensus()
|
|
325
|
+
|
|
326
|
+
def _dna_to_consensus(self):
|
|
327
|
+
codes = {
|
|
328
|
+
(0,): "A",
|
|
329
|
+
(1,): "C",
|
|
330
|
+
(2,): "G",
|
|
331
|
+
(3,): "T",
|
|
332
|
+
(0, 2): "R",
|
|
333
|
+
(1, 3): "Y",
|
|
334
|
+
(1, 2): "S",
|
|
335
|
+
(0, 3): "W",
|
|
336
|
+
(2, 3): "K",
|
|
337
|
+
(0, 1): "M",
|
|
338
|
+
(1, 2, 3): "B",
|
|
339
|
+
(0, 2, 3): "D",
|
|
340
|
+
(0, 1, 3): "H",
|
|
341
|
+
(0, 1, 2): "V",
|
|
342
|
+
(0, 1, 2, 3): "N",
|
|
343
|
+
}
|
|
344
|
+
consensus = ""
|
|
345
|
+
maxes = np.max(self.symbols, axis=1)
|
|
346
|
+
for i in range(len(self.symbols)):
|
|
347
|
+
consensus += _codes_to_iupac(self.symbols[i, :], codes, maxes[i], i)
|
|
348
|
+
return consensus
|
|
349
|
+
|
|
350
|
+
def _rna_to_consensus(self):
|
|
351
|
+
codes = {
|
|
352
|
+
(0,): "A",
|
|
353
|
+
(1,): "C",
|
|
354
|
+
(2,): "G",
|
|
355
|
+
(3,): "U",
|
|
356
|
+
(0, 2): "R",
|
|
357
|
+
(1, 3): "Y",
|
|
358
|
+
(1, 2): "S",
|
|
359
|
+
(0, 3): "W",
|
|
360
|
+
(2, 3): "K",
|
|
361
|
+
(0, 1): "M",
|
|
362
|
+
(1, 2, 3): "B",
|
|
363
|
+
(0, 2, 3): "D",
|
|
364
|
+
(0, 1, 3): "H",
|
|
365
|
+
(0, 1, 2): "V",
|
|
366
|
+
(0, 1, 2, 3): "N",
|
|
367
|
+
}
|
|
368
|
+
consensus = ""
|
|
369
|
+
maxes = np.max(self.symbols, axis=1)
|
|
370
|
+
for i in range(len(self.symbols)):
|
|
371
|
+
consensus += _codes_to_iupac(self.symbols[i, :], codes, maxes[i], i)
|
|
372
|
+
return consensus
|
|
373
|
+
|
|
374
|
+
def _prot_to_consensus(self):
|
|
375
|
+
"""
|
|
376
|
+
In case there is more than one symbol with the same maximal
|
|
377
|
+
occurrences, the alphabetically sorted first symbol will be
|
|
378
|
+
taken for the consensus sequence.
|
|
379
|
+
"""
|
|
380
|
+
consensus = ProteinSequence()
|
|
381
|
+
consensus.code = np.argmax(self.symbols, axis=1)
|
|
382
|
+
consensus.code = np.where(
|
|
383
|
+
np.sum(self.symbols, axis=1) == 0, 23, consensus.code
|
|
384
|
+
) # _PROT_ALPH[23] = 'X'
|
|
385
|
+
return consensus
|
|
386
|
+
|
|
387
|
+
def _general_to_consensus(self):
|
|
388
|
+
"""
|
|
389
|
+
In case there is more than one symbol with the same maximal
|
|
390
|
+
occurrences, the alphabetically sorted first symbol will be
|
|
391
|
+
taken for the consensus sequence.
|
|
392
|
+
In case the sum of occurrences of all symbols at a position is
|
|
393
|
+
zero, the alphabetically sorted first symbol will be taken for
|
|
394
|
+
the consensus sequence.
|
|
395
|
+
"""
|
|
396
|
+
consensus = GeneralSequence(self.alphabet)
|
|
397
|
+
consensus.code = np.argmax(self.symbols, axis=1)
|
|
398
|
+
return consensus
|
|
399
|
+
|
|
400
|
+
def probability_matrix(self, pseudocount=0):
|
|
401
|
+
r"""
|
|
402
|
+
Calculate the position probability matrix (PPM) based on
|
|
403
|
+
'symbols' and the given pseudocount.
|
|
404
|
+
This new matrix has the same shape as 'symbols'.
|
|
405
|
+
|
|
406
|
+
.. math::
|
|
407
|
+
|
|
408
|
+
P(S) = \frac {C_S + \frac{c_p}{k}} {\sum_{i} C_i + c_p}
|
|
409
|
+
|
|
410
|
+
:math:`S`: The symbol.
|
|
411
|
+
|
|
412
|
+
:math:`C_S`: The count of symbol :math:`S` at the sequence
|
|
413
|
+
position.
|
|
414
|
+
|
|
415
|
+
:math:`c_p`: The pseudocount.
|
|
416
|
+
|
|
417
|
+
:math:`k`: Length of the alphabet.
|
|
418
|
+
|
|
419
|
+
Parameters
|
|
420
|
+
----------
|
|
421
|
+
pseudocount : int, optional
|
|
422
|
+
Amount added to the number of observed cases in order to
|
|
423
|
+
change the expected probability of the PPM.
|
|
424
|
+
|
|
425
|
+
Returns
|
|
426
|
+
-------
|
|
427
|
+
ppm : ndarray, dtype=float, shape=(n,k)
|
|
428
|
+
The calculated the position probability matrix.
|
|
429
|
+
"""
|
|
430
|
+
if pseudocount < 0:
|
|
431
|
+
raise ValueError("Pseudocount can not be smaller than zero.")
|
|
432
|
+
return (self.symbols + pseudocount / self.symbols.shape[1]) / (
|
|
433
|
+
np.sum(self.symbols, axis=1)[:, np.newaxis] + pseudocount
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
def log_odds_matrix(self, background_frequencies=None, pseudocount=0):
|
|
437
|
+
r"""
|
|
438
|
+
Calculate the position weight matrix (PWM) based on the
|
|
439
|
+
position probability matrix (PPM) (with given pseudocount) and
|
|
440
|
+
background_frequencies.
|
|
441
|
+
This new matrix has the same shape as 'symbols'.
|
|
442
|
+
|
|
443
|
+
.. math::
|
|
444
|
+
|
|
445
|
+
W(S) = \log_2 \left( \frac{P(S)}{B_S} \right)
|
|
446
|
+
|
|
447
|
+
:math:`S`: The symbol.
|
|
448
|
+
|
|
449
|
+
:math:`P(S)`: The probability of symbol :math:`S` at the
|
|
450
|
+
sequence position.
|
|
451
|
+
|
|
452
|
+
:math:`c_p`: The background frequency of symbol :math:`S`.
|
|
453
|
+
|
|
454
|
+
Parameters
|
|
455
|
+
----------
|
|
456
|
+
background_frequencies : ndarray, shape=(k,), dtype=float, optional
|
|
457
|
+
The background frequencies for each symbol in the alphabet.
|
|
458
|
+
By default, a uniform distribution is assumed.
|
|
459
|
+
pseudocount : int, optional
|
|
460
|
+
Amount added to the number of observed cases in order to change
|
|
461
|
+
the expected probability of the PPM.
|
|
462
|
+
|
|
463
|
+
Returns
|
|
464
|
+
-------
|
|
465
|
+
pwm : ndarray, dtype=float, shape=(n,k)
|
|
466
|
+
The calculated the position weight matrix.
|
|
467
|
+
"""
|
|
468
|
+
if background_frequencies is None:
|
|
469
|
+
background_frequencies = 1 / len(self.alphabet)
|
|
470
|
+
ppm = self.probability_matrix(pseudocount=pseudocount)
|
|
471
|
+
# Catch warning that appears, if a symbol is missing at any
|
|
472
|
+
# position in the profile
|
|
473
|
+
with warnings.catch_warnings():
|
|
474
|
+
warnings.filterwarnings("ignore", category=RuntimeWarning)
|
|
475
|
+
return np.log2(ppm / background_frequencies)
|
|
476
|
+
|
|
477
|
+
def sequence_probability(self, sequence, pseudocount=0):
|
|
478
|
+
r"""
|
|
479
|
+
Calculate probability of a sequence based on the
|
|
480
|
+
position probability matrix (PPM).
|
|
481
|
+
|
|
482
|
+
The sequence probability is the product of the probability of
|
|
483
|
+
the respective symbol over all sequence positions.
|
|
484
|
+
|
|
485
|
+
Parameters
|
|
486
|
+
----------
|
|
487
|
+
sequence : Sequence
|
|
488
|
+
The input sequence.
|
|
489
|
+
pseudocount : int, optional
|
|
490
|
+
Amount added to the number of observed cases in order to change
|
|
491
|
+
the expected probability of the PPM.
|
|
492
|
+
|
|
493
|
+
Returns
|
|
494
|
+
-------
|
|
495
|
+
probability : float
|
|
496
|
+
The calculated probability for the input sequence based on
|
|
497
|
+
the PPM.
|
|
498
|
+
"""
|
|
499
|
+
ppm = self.probability_matrix(pseudocount=pseudocount)
|
|
500
|
+
if len(sequence) != len(ppm):
|
|
501
|
+
raise ValueError(
|
|
502
|
+
f"The given sequence has a different length ({len(sequence)}) than "
|
|
503
|
+
f"the position probability matrix ({len(ppm)})."
|
|
504
|
+
)
|
|
505
|
+
if not ppm.shape == self.symbols.shape:
|
|
506
|
+
raise ValueError(
|
|
507
|
+
f"Position probability matrix {ppm.shape} must be of same shape "
|
|
508
|
+
f"as 'symbols' {self.symbols.shape}"
|
|
509
|
+
)
|
|
510
|
+
return np.prod(ppm[np.arange(len(sequence)), sequence.code])
|
|
511
|
+
|
|
512
|
+
def sequence_score(self, sequence, background_frequencies=None, pseudocount=0):
|
|
513
|
+
"""
|
|
514
|
+
Calculate score of a sequence based on the
|
|
515
|
+
position weight matrix (PWM).
|
|
516
|
+
|
|
517
|
+
The score is the sum of weights (log-odds scores) of
|
|
518
|
+
the respective symbol over all sequence positions.
|
|
519
|
+
|
|
520
|
+
Parameters
|
|
521
|
+
----------
|
|
522
|
+
sequence : Sequence
|
|
523
|
+
The input sequence.
|
|
524
|
+
background_frequencies : ndarray, shape=(k,), dtype=float, optional
|
|
525
|
+
The background frequencies for each symbol in the alphabet.
|
|
526
|
+
By default a uniform distribution is assumed.
|
|
527
|
+
pseudocount : int, optional
|
|
528
|
+
Amount added to the number of observed cases in order to change
|
|
529
|
+
the expected probability of the PPM.
|
|
530
|
+
|
|
531
|
+
Returns
|
|
532
|
+
-------
|
|
533
|
+
score : float
|
|
534
|
+
The calculated score for the input sequence based on
|
|
535
|
+
the PWM.
|
|
536
|
+
"""
|
|
537
|
+
if background_frequencies is None:
|
|
538
|
+
background_frequencies = 1 / len(self.alphabet)
|
|
539
|
+
pwm = self.log_odds_matrix(
|
|
540
|
+
background_frequencies=background_frequencies, pseudocount=pseudocount
|
|
541
|
+
)
|
|
542
|
+
if len(sequence) != len(pwm):
|
|
543
|
+
raise ValueError(
|
|
544
|
+
f"The given sequence has a different length ({len(sequence)}) than "
|
|
545
|
+
f"the position weight matrix ({len(pwm)})."
|
|
546
|
+
)
|
|
547
|
+
if not pwm.shape == self.symbols.shape:
|
|
548
|
+
raise ValueError(
|
|
549
|
+
f"Position weight matrix {pwm.shape} must be of same shape "
|
|
550
|
+
f"as 'symbols' {self.symbols.shape}"
|
|
551
|
+
)
|
|
552
|
+
return np.sum(pwm[np.arange(len(sequence)), sequence.code])
|
|
553
|
+
|
|
554
|
+
def __getitem__(self, index):
|
|
555
|
+
if isinstance(index, Integral):
|
|
556
|
+
# Do not allow to collapse dimensions
|
|
557
|
+
index = slice(index, index + 1)
|
|
558
|
+
return SequenceProfile(self.symbols[index], self.gaps[index], self.alphabet)
|
|
559
|
+
|
|
560
|
+
def __len__(self):
|
|
561
|
+
return len(self.symbols)
|
|
@@ -0,0 +1,117 @@
|
|
|
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.sequence"
|
|
6
|
+
__author__ = "Patrick Kunzmann"
|
|
7
|
+
__all__ = ["find_subsequence", "find_symbol", "find_symbol_first", "find_symbol_last"]
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def find_subsequence(sequence, query):
|
|
13
|
+
"""
|
|
14
|
+
Find a subsequence in a sequence.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
sequence : Sequence
|
|
19
|
+
The sequence to find the subsequence in.
|
|
20
|
+
query : Sequence
|
|
21
|
+
The potential subsequence. Its alphabet must extend the
|
|
22
|
+
`sequence` alphabet.
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
match_indices : ndarray
|
|
27
|
+
The starting indices in `sequence`, where `query` has been
|
|
28
|
+
found. The array is empty if no match has been found.
|
|
29
|
+
|
|
30
|
+
Raises
|
|
31
|
+
------
|
|
32
|
+
ValueError
|
|
33
|
+
If the `query` alphabet does not extend the `sequence` alphabet.
|
|
34
|
+
|
|
35
|
+
Examples
|
|
36
|
+
--------
|
|
37
|
+
|
|
38
|
+
>>> main_seq = NucleotideSequence("ACTGAATGA")
|
|
39
|
+
>>> sub_seq = NucleotideSequence("TGA")
|
|
40
|
+
>>> print(find_subsequence(main_seq, sub_seq))
|
|
41
|
+
[2 6]
|
|
42
|
+
"""
|
|
43
|
+
if not sequence.get_alphabet().extends(query.get_alphabet()):
|
|
44
|
+
raise ValueError("The sequences alphabets are not equal")
|
|
45
|
+
match_indices = []
|
|
46
|
+
frame_size = len(query)
|
|
47
|
+
for i in range(len(sequence) - frame_size + 1):
|
|
48
|
+
sub_seq_code = sequence.code[i : i + frame_size]
|
|
49
|
+
if np.array_equal(query.code, sub_seq_code):
|
|
50
|
+
match_indices.append(i)
|
|
51
|
+
return np.array(match_indices)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def find_symbol(sequence, symbol):
|
|
55
|
+
"""
|
|
56
|
+
Find a symbol in a sequence.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
sequence : Sequence
|
|
61
|
+
The sequence to find the symbol in.
|
|
62
|
+
symbol : object
|
|
63
|
+
The symbol to be found in `sequence`.
|
|
64
|
+
|
|
65
|
+
Returns
|
|
66
|
+
-------
|
|
67
|
+
match_indices : ndarray
|
|
68
|
+
The indices in `sequence`, where `symbol` has been found.
|
|
69
|
+
"""
|
|
70
|
+
code = sequence.get_alphabet().encode(symbol)
|
|
71
|
+
return np.where(sequence.code == code)[0]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def find_symbol_first(sequence, symbol):
|
|
75
|
+
"""
|
|
76
|
+
Find first occurence of a symbol in a sequence.
|
|
77
|
+
|
|
78
|
+
Parameters
|
|
79
|
+
----------
|
|
80
|
+
sequence : Sequence
|
|
81
|
+
The sequence to find the symbol in.
|
|
82
|
+
symbol : object
|
|
83
|
+
The symbol to be found in `sequence`.
|
|
84
|
+
|
|
85
|
+
Returns
|
|
86
|
+
-------
|
|
87
|
+
first_index : int
|
|
88
|
+
The first index of `symbol` in `sequence`. If `symbol` is not in
|
|
89
|
+
`sequence`, -1 is returned.
|
|
90
|
+
"""
|
|
91
|
+
match_i = find_symbol(sequence, symbol)
|
|
92
|
+
if len(match_i) == 0:
|
|
93
|
+
return -1
|
|
94
|
+
return np.min(match_i)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def find_symbol_last(sequence, symbol):
|
|
98
|
+
"""
|
|
99
|
+
Find last occurence of a symbol in a sequence.
|
|
100
|
+
|
|
101
|
+
Parameters
|
|
102
|
+
----------
|
|
103
|
+
sequence : Sequence
|
|
104
|
+
The sequence to find the symbol in.
|
|
105
|
+
symbol : object
|
|
106
|
+
The symbol to be found in `sequence`.
|
|
107
|
+
|
|
108
|
+
Returns
|
|
109
|
+
-------
|
|
110
|
+
flast_index : int
|
|
111
|
+
The last index of `symbol` in `sequence`. If `symbol` is not in
|
|
112
|
+
`sequence`, -1 is returned.
|
|
113
|
+
"""
|
|
114
|
+
match_i = find_symbol(sequence, symbol)
|
|
115
|
+
if len(match_i) == 0:
|
|
116
|
+
return -1
|
|
117
|
+
return np.max(match_i)
|