# coding: utf-8
import collections.abc
import datetime
import os
import types
import typing

try:
    from typing import Literal
except ImportError:
    from typing_extensions import Literal  # type: ignore

from .easel import (
    Alphabet,
    Sequence,
    DigitalSequence,
    MSA,
    DigitalMSA,
    TextMSA,
    Randomness,
    VectorF,
    VectorU8,
    MatrixU8,
)

BIT_CUTOFFS = Literal["gathering", "trusted", "noise"]
SORT_KEY = Literal["key", "seqidx"]
ARCHITECTURE = Literal["fast", "hand"]
WEIGHTING = Literal["pb", "gsc", "blosum", "none", "given"]
EFFECTIVE = Literal["entropy", "exp", "clust", "none"]
PRIOR_SCHEME = Literal["laplace", "alphabet"]


class Alignment(collections.abc.Sized):
    domain: Domain
    def __len__(self) -> int: ...
    @property
    def hmm_accession(self) -> bytes: ...
    @property
    def hmm_from(self) -> int: ...
    @property
    def hmm_name(self) -> bytes: ...
    @property
    def hmm_sequence(self) -> str: ...
    @property
    def hmm_to(self) -> int: ...
    @property
    def target_from(self) -> int: ...
    @property
    def target_name(self) -> bytes: ...
    @property
    def target_sequence(self) -> str: ...
    @property
    def target_to(self) -> int: ...
    @property
    def identity_sequence(self) -> str: ...

class Background(object):
    def __init__(self, alphabet: Alphabet, uniform: bool = False) -> None: ...
    def __copy__(self) -> Background: ...
    @property
    def L(self) -> int: ...
    @L.setter
    def L(self, L: int) -> None: ...
    @property
    def residue_frequencies(self) -> VectorF: ...
    @property
    def transition_probability(self) -> float: ...
    @property
    def omega(self) -> float: ...
    @omega.setter
    def omega(self, omega: float) -> None: ...
    def copy(self) -> Background: ...

class Builder(object):
    alphabet: Alphabet
    randomness: Randomness
    architecture: ARCHITECTURE
    weighting: WEIGHTING
    effective_number: typing.Union[EFFECTIVE, int, float]
    prior_scheme: typing.Optional[PRIOR_SCHEME]
    popen: float
    pextend: float
    def __init__(
        self,
        alphabet: Alphabet,
        *,
        architecture: ARCHITECTURE = "fast",
        weighting: WEIGHTING = "pb",
        effective_number: typing.Union[EFFECTIVE, int, float] = "entropy",
        prior_scheme: typing.Optional[PRIOR_SCHEME] = "alphabet",
        symfrac: float = 0.5,
        fragthresh: float = 0.5,
        wid: float = 0.62,
        esigma: float = 45.0,
        eid: float = 0.62,
        EmL: int = 200,
        EmN: int = 200,
        EvL: int = 200,
        EvN: int = 200,
        EfL: int = 100,
        EfN: int = 200,
        Eft: float = 0.04,
        seed: int = 42,
        ere: typing.Optional[float] = None,
        popen: typing.Optional[float] = None,
        pextend: typing.Optional[float] = None,
    ) -> None: ...
    def __copy__(self) -> Builder: ...
    @property
    def seed(self) -> int: ...
    @seed.setter
    def seed(self, seed: int) -> None: ...
    def build(
        self,
        sequence: DigitalSequence,
        background: Background,
    ) -> typing.Tuple[HMM, Profile, OptimizedProfile]: ...
    def build_msa(
        self,
        msa: DigitalMSA,
        background: Background,
    ) -> typing.Tuple[HMM, Profile, OptimizedProfile]: ...
    def copy(self) -> Builder: ...

class Cutoffs(object):
    def __init__(self, owner: typing.Union[Profile, HMM]) -> None: ...
    def __copy__(self) -> Cutoffs: ...
    def __str__(self) -> str: ...
    def __eq__(self, other: object) -> bool: ...
    @property
    def gathering(self) -> typing.Optional[typing.Tuple[float, float]]: ...
    @gathering.setter
    def gathering(self, gathering: typing.Optional[typing.Tuple[float, float]]) -> None: ...
    @gathering.deleter
    def gathering(self) -> None: ...
    @property
    def gathering1(self) -> typing.Optional[float]: ...
    @property
    def gathering2(self) -> typing.Optional[float]: ...
    @property
    def trusted(self) -> typing.Optional[typing.Tuple[float, float]]: ...
    @trusted.setter
    def trusted(self, trusted: typing.Optional[typing.Tuple[float, float]]) -> None: ...
    @trusted.deleter
    def trusted(self) -> None: ...
    @property
    def trusted1(self) -> typing.Optional[float]: ...
    @property
    def trusted2(self) -> typing.Optional[float]: ...
    @property
    def noise(self) -> typing.Optional[typing.Tuple[float, float]]: ...
    @noise.setter
    def noise(self, noise: typing.Optional[typing.Tuple[float, float]]) -> None: ...
    @noise.deleter
    def noise(self) -> None: ...
    @property
    def noise1(self) -> typing.Optional[float]: ...
    @property
    def noise2(self) -> typing.Optional[float]: ...
    def gathering_available(self) -> bool: ...
    def trusted_available(self) -> bool: ...
    def noise_available(self) -> bool: ...
    def as_vector(self) -> VectorF: ...

class Domain(object):
    alignment: Alignment
    hit: Hit
    @property
    def env_from(self) -> int: ...
    @property
    def env_to(self) -> int: ...
    @property
    def score(self) -> float: ...
    @property
    def bias(self) -> float: ...
    @property
    def correction(self) -> float: ...
    @property
    def envelope_score(self) -> float: ...
    @property
    def c_evalue(self) -> float: ...
    @property
    def i_evalue(self) -> float: ...
    @property
    def pvalue(self) -> float: ...

class Domains(typing.Sequence[Domain]):
    hit: Hit
    def __len__(self) -> int: ...
    @typing.overload
    def __getitem__(self, index: int) -> Domain: ...
    @typing.overload
    def __getitem__(self, index: slice) -> typing.Sequence[Domain]: ...

class EvalueParameters:
    def __init__(self, owner: typing.Union[Profile, HMM]) -> None: ...
    def __copy__(self) -> EvalueParameters: ...
    def __str__(self) -> str: ...
    def __eq__(self, other: object) -> bool: ...
    @property
    def m_mu(self) -> typing.Optional[float]: ...
    @m_mu.setter
    def m_mu(self, m: typing.Optional[float]) -> None: ...
    @property
    def m_lambda(self) -> typing.Optional[float]: ...
    @m_lambda.setter
    def m_lambda(self, l: typing.Optional[float]) -> None: ...
    @property
    def v_mu(self) -> typing.Optional[float]: ...
    @v_mu.setter
    def v_mu(self, m: typing.Optional[float]) -> None: ...
    @property
    def v_lambda(self) -> typing.Optional[float]: ...
    @v_lambda.setter
    def v_lambda(self, l: typing.Optional[float]) -> None: ...
    @property
    def f_tau(self) -> typing.Optional[float]: ...
    @f_tau.setter
    def f_tau(self, t: typing.Optional[float]) -> None: ...
    @property
    def f_lambda(self) -> typing.Optional[float]: ...
    @f_lambda.setter
    def f_lambda(self, l: typing.Optional[float]) -> None: ...
    def as_vector(self) -> VectorF: ...

class Hit(object):
    hits: TopHits
    @property
    def name(self) -> bytes: ...
    @property
    def accession(self) -> bytes: ...
    @property
    def description(self) -> bytes: ...
    @property
    def score(self) -> float: ...
    @property
    def pre_score(self) -> float: ...
    @property
    def sum_score(self) -> float: ...
    @property
    def bias(self) -> float: ...
    @property
    def evalue(self) -> float: ...
    @property
    def pvalue(self) -> float: ...
    @property
    def domains(self) -> Domains: ...
    @property
    def best_domain(self) -> Domain: ...
    def is_included(self) -> bool: ...
    def is_reported(self) -> bool: ...
    def is_new(self) -> bool: ...
    def is_dropped(self) -> bool: ...
    def is_duplicate(self) -> bool: ...

class HMM(object):
    alphabet: Alphabet
    evalue_parameters: EvalueParameters
    cutoffs: Cutoffs
    def __init__(self, M: int, alphabet: Alphabet) -> None: ...
    def __eq__(self, other: object) -> bool: ...
    def __copy__(self) -> HMM: ...
    def __sizeof__(self) -> int: ...
    def __getstate__(self) -> typing.Dict[str, object]: ...
    def __setstate__(self, state: typing.Dict[str, object]) -> None: ...
    @property
    def M(self) -> int: ...
    @property
    def name(self) -> typing.Optional[bytes]: ...
    @name.setter
    def name(self, names: typing.Optional[bytes]) -> None: ...
    @property
    def accession(self) -> typing.Optional[bytes]: ...
    @accession.setter
    def accession(self, accession: typing.Optional[bytes]) -> None: ...
    @property
    def checksum(self) -> typing.Optional[int]: ...
    @property
    def composition(self) -> typing.Optional[VectorF]: ...
    @property
    def description(self) -> typing.Optional[bytes]: ...
    @description.setter
    def description(self, description: typing.Optional[bytes]) -> None: ...
    @property
    def consensus(self) -> typing.Optional[str]: ...
    @property
    def consensus_structure(self) -> typing.Optional[str]: ...
    @property
    def consensus_accessibility(self) -> typing.Optional[str]: ...
    @property
    def command_line(self) -> typing.Optional[str]: ...
    @command_line.setter
    def command_line(self, cli: typing.Optional[str]) -> None: ...
    @property
    def nseq(self) -> typing.Optional[int]: ...
    @property
    def nseq_effective(self) -> typing.Optional[int]: ...
    @property
    def creation_time(self) -> typing.Optional[datetime.datetime]: ...
    @creation_time.setter
    def creation_time(self, ctime: typing.Optional[datetime.datetime]) -> None: ...
    def copy(self) -> HMM: ...
    def write(self, fh: typing.BinaryIO, binary: bool = False) -> None: ...
    def zero(self) -> None: ...
    def renormalize(self) -> None: ...
    def scale(self, scale: float, exponential: bool = False) -> None: ...
    def set_composition(self) -> None: ...

class HMMFile(typing.ContextManager[HMMFile], typing.Iterator[HMM]):
    def __init__(
        self,
        file: typing.Union[typing.AnyStr, os.PathLike[typing.AnyStr], typing.BinaryIO],
        db: bool = True
    ) -> None: ...
    def __enter__(self) -> HMMFile: ...
    def __exit__(
        self,
        exc_type: typing.Optional[typing.Type[BaseException]],
        exc_value: typing.Optional[BaseException],
        traceback: typing.Optional[types.TracebackType],
    ) -> bool: ...
    def __iter__(self) -> HMMFile: ...
    def __next__(self) -> HMM: ...
    def close(self) -> None: ...

class OptimizedProfile(object):
    alphabet: Alphabet
    offsets: _Offsets
    def __init__(self, M: int, abc: Alphabet) -> None: ...
    def __copy__(self) -> OptimizedProfile: ...
    def is_local(self) -> bool: ...
    def copy(self) -> OptimizedProfile: ...
    @property
    def M(self) -> int: ...
    @property
    def L(self) -> int: ...
    @L.setter
    def L(self, L: int) -> None: ...
    @property
    def tbm(self) -> int: ...
    @property
    def tec(self) -> int: ...
    @property
    def tjb(self) -> int: ...
    @property
    def base(self) -> int: ...
    @property
    def bias(self) -> int: ...
    @property
    def sbv(self) -> MatrixU8: ...
    @property
    def rbv(self) -> MatrixU8: ...
    def write(self, fh_filter: typing.BinaryIO, fh_profile: typing.BinaryIO) -> None: ...

class _Offsets(object):
    def __init__(self, owner: typing.Union[Profile, OptimizedProfile]) -> None: ...
    def __copy__(self) -> _Offsets: ...
    @property
    def model(self) -> typing.Optional[int]: ...
    @model.setter
    def model(self, model: typing.Optional[int]) -> None: ...
    @property
    def filter(self) -> typing.Optional[int]: ...
    @filter.setter
    def filter(self, filter: typing.Optional[int]) -> None: ...
    @property
    def profile(self) -> typing.Optional[int]: ...
    @profile.setter
    def profile(self, profile: typing.Optional[int]) -> None: ...

class Pipeline(object):
    M_HINT: typing.ClassVar[int] = 100
    L_HINT: typing.ClassVar[int] = 100
    LONG_TARGETS: typing.ClassVar[bool] = False
    alphabet: Alphabet
    background: Background
    profile: typing.Optional[Profile]
    randomness: Randomness
    def __init__(
        self,
        alphabet: Alphabet,
        background: typing.Optional[Background] = None,
        *,
        bias_filter: bool = True,
        report_e: float = 10.0,
        null2: bool = True,
        seed: typing.Optional[int] = None,
        Z: typing.Optional[float] = None,
        domZ: typing.Optional[float] = None,
        F1: float = 0.02,
        F2: float = 1e-3,
        F3: float = 1e-5,
        E: float = 10.0,
        T: typing.Optional[float] = None,
        domE: float = 10.0,
        domT: typing.Optional[float] = None,
        incE: float = 0.01,
        incT: typing.Optional[float] = None,
        incdomE: float = 0.01,
        incdomT: typing.Optional[float] = None,
        bit_cutoffs: typing.Optional[BIT_CUTOFFS] = None,
    ) -> None: ...
    @property
    def Z(self) -> typing.Optional[float]: ...
    @Z.setter
    def Z(self, Z: typing.Optional[float]) -> None: ...
    @property
    def domZ(self) -> typing.Optional[float]: ...
    @domZ.setter
    def domZ(self, domZ: typing.Optional[float]) -> None: ...
    @property
    def null2(self) -> bool: ...
    @null2.setter
    def null2(self, null2: bool) -> None: ...
    @property
    def bias_filter(self) -> bool: ...
    @bias_filter.setter
    def bias_filter(self, bias_filter: bool) -> None: ...
    @property
    def F1(self) -> float: ...
    @F1.setter
    def F1(self, F1: float) -> None: ...
    @property
    def F2(self) -> float: ...
    @F2.setter
    def F2(self, F2: float) -> None: ...
    @property
    def F3(self) -> float: ...
    @F3.setter
    def F3(self, F3: float) -> None: ...
    @property
    def E(self) -> float: ...
    @E.setter
    def E(self, E: float) -> None: ...
    @property
    def T(self) -> typing.Optional[float]: ...
    @T.setter
    def T(self, T: typing.Optional[float]) -> None: ...
    @property
    def domE(self) -> float: ...
    @domE.setter
    def domE(self, domE: float) -> None: ...
    @property
    def domT(self) -> typing.Optional[float]: ...
    @domT.setter
    def domT(self, domT: typing.Optional[float]) -> None: ...
    @property
    def incE(self) -> float: ...
    @incE.setter
    def incE(self, incE: float) -> None: ...
    @property
    def incT(self) -> typing.Optional[float]: ...
    @incT.setter
    def incT(self, incT: typing.Optional[float]) -> None: ...
    @property
    def incdomE(self) -> float: ...
    @incdomE.setter
    def incdomE(self, incdomE: float) -> None: ...
    @property
    def incdomT(self) -> typing.Optional[float]: ...
    @incdomT.setter
    def incdomT(self, incdomT: typing.Optional[float]) -> None: ...
    @property
    def bit_cutoffs(self) -> typing.Optional[BIT_CUTOFFS]: ...
    @bit_cutoffs.setter
    def bit_cutoffs(self, bit_cutoffs: typing.Optional[BIT_CUTOFFS]) -> None: ...
    def clear(self) -> None: ...
    def search_hmm(
        self,
        query: HMM,
        sequences: typing.Iterable[DigitalSequence],
    ) -> TopHits: ...
    def search_msa(
        self,
        query: DigitalMSA,
        sequences: typing.Iterable[DigitalSequence],
        builder: typing.Optional[Builder] = None,
    ) -> TopHits: ...
    def search_seq(
        self,
        query: DigitalSequence,
        sequences: typing.Iterable[DigitalSequence],
        builder: typing.Optional[Builder] = None,
    ) -> TopHits: ...
    def scan_hmm(
        self,
        query: DigitalSequence,
        hmms: typing.Iterable[HMM],
    ) -> TopHits: ...

class Profile(object):
    alphabet: Alphabet
    evalue_parameters: EvalueParameters
    offsets: _Offsets
    cutoffs: Cutoffs
    def __init__(self, M: int, alphabet: Alphabet) -> None: ...
    def __copy__(self) -> Profile: ...
    @property
    def M(self) -> int: ...
    @property
    def name(self) -> typing.Optional[bytes]: ...
    @property
    def accession(self) -> typing.Optional[bytes]: ...
    @property
    def description(self) -> typing.Optional[bytes]: ...
    @property
    def consensus(self) -> typing.Optional[str]: ...
    @property
    def consensus_structure(self) -> typing.Optional[str]: ...
    def clear(self) -> None: ...
    def configure(
        self,
        hmm: HMM,
        background: Background,
        L: int,
        multihit: bool = True,
        local: bool = True,
    ) -> None: ...
    def copy(self) -> Profile: ...
    def is_local(self) -> bool: ...
    def is_multihit(self) -> bool: ...
    def optimized(self) -> OptimizedProfile: ...

class TopHits(typing.Sequence[Hit]):
    Z: float
    domZ: float
    long_targets: bool
    def __init__(self) -> None: ...
    def __bool__(self) -> bool: ...
    def __len__(self) -> int: ...
    @typing.overload
    def __getitem__(self, index: int) -> Hit: ...
    @typing.overload
    def __getitem__(self, index: slice) -> typing.Sequence[Hit]: ...
    def __iadd__(self, other: TopHits) -> TopHits: ...
    def sort(self, by: SORT_KEY = "key") -> None: ...
    def is_sorted(self, by: SORT_KEY = "key") -> bool: ...
    def to_msa(
        self,
        alphabet: Alphabet,
        trim: bool = False,
        digitize: bool = False,
        all_consensus_cols: bool = False
    ) -> MSA: ...

class Trace(object):
    def __eq__(self, other: object) -> bool: ...
    @property
    def M(self) -> int: ...
    @property
    def L(self) -> int: ...
    @property
    def posterior_probabilities(self) -> VectorF: ...
    def expected_accuracy(self) -> float: ...

class Traces(typing.Sequence[Trace]):
    def __init__(self) -> None: ...
    def __eq__(self, other: object) -> bool: ...
    def __len__(self) -> int: ...
    @typing.overload
    def __getitem__(self, index: int) -> Trace: ...
    @typing.overload
    def __getitem__(self, index: slice) -> typing.Sequence[Trace]: ...

class TraceAligner(object):
    def __init__(self) -> None: ...
    def compute_traces(
        self,
        hmm: HMM,
        sequences: typing.Iterable[DigitalSequence],
    ) -> Traces: ...
    def align_traces(
        self,
        hmm: HMM,
        sequences: typing.Iterable[DigitalSequence],
        traces: Traces,
        trim: bool = False,
        digitize: bool = False,
        all_consensus_cols: bool = False,
    ) -> MSA: ...
