Source code for tidymut.core.codon
# tidymut/core/codon_table.py
from __future__ import annotations
from collections.abc import Collection
from typing import TYPE_CHECKING
from .constants import (
STANDARD_GENETIC_CODE_DNA,
STANDARD_START_CODONS_DNA,
STANDARD_GENETIC_CODE_RNA,
STANDARD_START_CODONS_RNA,
)
if TYPE_CHECKING:
from typing import Dict, List, Literal, Optional
__all__ = ["CodonTable"]
def __dir__() -> List[str]:
return __all__
[docs]
class CodonTable:
"""codon table used to translate codons to amino acids"""
def __init__(
self,
name: str,
codon_map: Dict[str, str],
start_codons: Optional[Collection[str]] = None,
stop_codons: Optional[Collection[str]] = None,
):
self.name = name
self.codon_map = {k.upper(): v for k, v in codon_map.items()}
# auto detect stop codons
if stop_codons is None:
self.stop_codons = [
codon for codon, aa in self.codon_map.items() if aa == "*"
]
else:
self.stop_codons = set([c.upper() for c in stop_codons])
# set start codons
if start_codons is None:
self.start_codons = STANDARD_START_CODONS_DNA
else:
self.start_codons = set([c.upper() for c in start_codons])
[docs]
def translate_codon(self, codon: str) -> str:
"""translate single codon to corresponding amino acid"""
return self.codon_map.get(codon.upper(), "X")
[docs]
def is_stop_codon(self, codon: str) -> bool:
"""check if codon is a stop codon"""
return codon.upper() in self.stop_codons
[docs]
def is_start_codon(self, codon: str) -> bool:
"""check if codon is a start codon"""
return codon.upper() in self.start_codons
[docs]
@classmethod
def get_standard_table(
cls, seq_type: Literal["DNA", "RNA"] = "DNA"
) -> "CodonTable":
"""get standard codon table (NCBI standard)"""
if seq_type == "DNA":
return cls("Standard", STANDARD_GENETIC_CODE_DNA, STANDARD_START_CODONS_DNA)
elif seq_type == "RNA":
return cls("Standard", STANDARD_GENETIC_CODE_RNA, STANDARD_START_CODONS_RNA)
else:
raise ValueError("Invalid sequence type")
[docs]
@classmethod
def get_table_by_name(
cls, name: str, seq_type: Literal["DNA", "RNA"] = "DNA"
) -> "CodonTable":
"""get codon table by name"""
return {
"Standard": cls.get_standard_table(seq_type),
# TODO: add more tables here
}[name]