from typing import List, Optional, Tuple

class FKmer:
    def __init__(
        self, seqs: List[bytes], end: int, counts: Optional[List[float]] = None
    ) -> None: ...
    def starts(self) -> List[int]: ...
    @property
    def end(self) -> int: ...
    def counts(self) -> Optional[List[float]]: ...
    def len(self) -> List[int]: ...
    def num_seqs(self) -> int: ...
    def seqs(self) -> List[str]: ...
    def seqs_bytes(self) -> List[bytes]: ...
    def region(self) -> Tuple[int, int]: ...
    def to_bed(self, chrom: str, amplicon_prefix: str, pool: int) -> str: ...
    def remap(self, end: int) -> None: ...
    def gc(self) -> List[float]: ...
    def counts_sum(self) -> Optional[float]: ...

class RKmer:
    def __init__(
        self, seqs: List[bytes], start: int, counts: Optional[List[float]] = None
    ) -> None: ...
    def seqs(self) -> List[str]: ...
    @property
    def start(self) -> int: ...
    def counts(self) -> Optional[List[float]]: ...
    def ends(self) -> List[int]: ...
    def lens(self) -> List[int]: ...
    def num_seqs(self) -> int: ...
    def seqs_bytes(self) -> List[bytes]: ...
    def region(self) -> Tuple[int, int]: ...
    def to_bed(self, chrom: str, amplicon_prefix: str, pool: int) -> str: ...
    def remap(self, start: int) -> None: ...
    def gc(self) -> List[float]: ...
    def counts_sum(self) -> Optional[float]: ...

class Digester:
    def __init__(self, msa_path: str, ncores: int, remap: bool) -> None: ...
    def create_seq_slice(self) -> List[bytes]: ...
    def digest(
        self,
        findexes: Optional[List[int]] = None,
        rindexes: Optional[List[int]] = None,
        primer_len_min: Optional[int] = None,
        primer_len_max: Optional[int] = None,
        primer_gc_max: Optional[float] = None,
        primer_gc_min: Optional[float] = None,
        primer_tm_max: Optional[float] = None,
        primer_tm_min: Optional[float] = None,
        primer_annealing_prop: Optional[float] = None,
        primer_annealing_diff: Optional[float] = None,
        annealing_temp_c: Optional[float] = None,
        max_walk: Optional[int] = None,
        max_homopolymers: Optional[int] = None,
        min_freq: Optional[float] = None,
        ignore_n: Optional[bool] = None,
        dimerscore: Optional[float] = None,
        thermo_check: bool = False,
    ) -> Tuple[List[FKmer], List[RKmer], List[str]]: ...
    @property
    def _seq_array(self) -> List[bytes]: ...
    @property
    def _mapping_array(self) -> List[Optional[int]]: ...
    @property
    def _ref_to_msa_array(self) -> List[int]: ...

def digest_seq(
    msa_path: str,
    ncores: int,
    remap: bool,
    findexes: Optional[List[int]] = None,
    rindexes: Optional[List[int]] = None,
    primer_len_min: Optional[int] = None,
    primer_len_max: Optional[int] = None,
    primer_gc_max: Optional[float] = None,
    primer_gc_min: Optional[float] = None,
    primer_tm_max: Optional[float] = None,
    primer_tm_min: Optional[float] = None,
    primer_annealing_prop: Optional[float] = None,
    primer_annealing_diff: Optional[float] = None,
    annealing_temp_c: Optional[float] = None,
    max_walk: Optional[int] = None,
    max_homopolymers: Optional[int] = None,
    min_freq: Optional[float] = None,
    ignore_n: Optional[bool] = None,
    dimerscore: Optional[float] = None,
    thermo_check: Optional[bool] = None,
) -> Tuple[List[FKmer], List[RKmer], List[str]]: ...
def do_seqs_interact(seq1: bytes, seq2: bytes, t: float) -> bool: ...
def do_pool_interact(seqs1: List[bytes], seqs2: List[bytes], t: float) -> bool: ...
def calc_at_offset_py(seq1: str, seq2: str, offset: int) -> float: ...
def calc_annealing(
    sequence: str,
    dna_nm: float,
    k_mm: float,
    divalent_conc: float,
    dntp_conc: float,
    dmso_conc: float,
    dmso_fact: float,
    formamide_conc: float,
    annealing_temp_c: float,
) -> float: ...
def generate_primerpairs_py(
    fkmers: List[FKmer],
    rkmers: List[RKmer],
    t: float,
    amplicon_size_min: int,
    amplicon_size_max: int,
) -> List[Tuple[FKmer, RKmer]]: ...
