Source code for dnaerys._enums

"""Enum types mirroring the Dnaerys proto enums, with string alias resolution.

All 12 ``IntEnum`` classes correspond 1:1 to the proto enums defined in
``dnaerys.proto`` (R1.20.0).  The ``UNSPECIFIED = 0`` sentinel from each proto
enum is deliberately excluded — it has no meaning in client code and would
pollute autocompletion.

Integer values match the proto exactly, so enum members can be passed directly
wherever the gRPC stub expects an integer enum value.
"""

from __future__ import annotations

import enum
from typing import TypeVar

__all__ = [
    "Chromosome",
    "RefAssembly",
    "VariantType",
    "FeatureType",
    "BioType",
    "Consequence",
    "Impact",
    "SIFT",
    "PolyPhen",
    "ClinSignificance",
    "AlphaMissense",
    "KinshipDegree",
    "resolve_chromosome",
    "resolve_enum",
    "resolve_assembly",
]

E = TypeVar("E", bound=enum.IntEnum)


# ---------------------------------------------------------------------------
# Enum definitions — values match dnaerys.proto R1.20.0 exactly
# ---------------------------------------------------------------------------


[docs] class Chromosome(enum.IntEnum): """Human chromosome identifiers. 25 members: autosomes 1–22, sex chromosomes X and Y, and mitochondrial DNA. Integer values match the proto ``Chromosome`` enum (``CHR1`` = 1 … ``CHRMT`` = 25). ``CHROMOSOME_UNSPECIFIED`` (0) is excluded. """ CHR1 = 1 CHR2 = 2 CHR3 = 3 CHR4 = 4 CHR5 = 5 CHR6 = 6 CHR7 = 7 CHR8 = 8 CHR9 = 9 CHR10 = 10 CHR11 = 11 CHR12 = 12 CHR13 = 13 CHR14 = 14 CHR15 = 15 CHR16 = 16 CHR17 = 17 CHR18 = 18 CHR19 = 19 CHR20 = 20 CHR21 = 21 CHR22 = 22 CHRX = 23 CHRY = 24 CHRMT = 25
[docs] class RefAssembly(enum.IntEnum): """Reference genome assembly versions. ``GRCh37`` (hg19) and ``GRCh38`` (hg38). The Dnaerys server defaults to GRCh38 when the assembly is unspecified. """ GRCh37 = 1 GRCh38 = 2
[docs] class VariantType(enum.IntEnum): """Sequence Ontology variant class terms. 34 members corresponding to the proto ``VariantType`` enum. See https://asia.ensembl.org/info/genome/variation/prediction/classification.html#classes """ SNV = 1 INSERTION = 2 DELETION = 3 INDEL = 4 SUBSTITUTION = 5 INVERSION = 6 TRANSLOCATION = 7 DUPLICATION = 8 ALU_INSERTION = 9 COMPLEX_STRUCTURAL_ALTERATION = 10 COMPLEX_SUBSTITUTION = 11 COPY_NUMBER_GAIN = 12 COPY_NUMBER_LOSS = 13 COPY_NUMBER_VARIATION = 14 INTERCHROMOSOMAL_BREAKPOINT = 15 INTERCHROMOSOMAL_TRANSLOCATION = 16 INTRACHROMOSOMAL_BREAKPOINT = 17 INTRACHROMOSOMAL_TRANSLOCATION = 18 LOSS_OF_HETEROZYGOSITY = 19 MOBILE_ELEMENT_DELETION = 20 MOBILE_ELEMENT_INSERTION = 21 NOVEL_SEQUENCE_INSERTION = 22 SHORT_TANDEM_REPEAT_VARIATION = 23 TANDEM_DUPLICATION = 24 PROBE = 25 ALU_DELETION = 26 HERV_DELETION = 27 HERV_INSERTION = 28 LINE1_DELETION = 29 LINE1_INSERTION = 30 SVA_DELETION = 31 SVA_INSERTION = 32 COMPLEX_CHROMOSOMAL_REARRANGEMENT = 33 SEQUENCE_ALTERATION = 34
[docs] class FeatureType(enum.IntEnum): """VEP feature types. 3 members: ``TRANSCRIPT``, ``REGULATORYFEATURE``, ``MOTIFFEATURE``. """ TRANSCRIPT = 1 REGULATORYFEATURE = 2 MOTIFFEATURE = 3
[docs] class BioType(enum.IntEnum): """VEP biotypes for transcripts and regulatory features. 47 members corresponding to the proto ``BioType`` enum. See https://asia.ensembl.org/info/genome/genebuild/biotypes.html """ PROCESSED_TRANSCRIPT = 1 LNCRNA = 2 ANTISENSE = 3 MACRO_LNCRNA = 4 NON_CODING = 5 RETAINED_INTRON = 6 SENSE_INTRONIC = 7 SENSE_OVERLAPPING = 8 LINCRNA = 9 NCRNA = 10 MIRNA = 11 MISCRNA = 12 PIRNA = 13 RRNA = 14 SIRNA = 15 SNRNA = 16 SNORNA = 17 TRNA = 18 VAULTRNA = 19 PROTEIN_CODING = 20 PSEUDOGENE = 21 IG_PSEUDOGENE = 22 POLYMORPHIC_PSEUDOGENE = 23 PROCESSED_PSEUDOGENE = 24 TRANSCRIBED_PSEUDOGENE = 25 TRANSLATED_PSEUDOGENE = 26 UNITARY_PSEUDOGENE = 27 UNPROCESSED_PSEUDOGENE = 28 READTHROUGH = 29 STOP_CODON_READTHROUGH = 30 TEC = 31 TR_GENE = 32 TR_C_GENE = 33 TR_D_GENE = 34 TR_J_GENE = 35 TR_V_GENE = 36 IG_GENE = 37 IG_C_GENE = 38 IG_D_GENE = 39 IG_J_GENE = 40 IG_V_GENE = 41 NONSENSE_MEDIATED_DECAY = 42 PROMOTER = 43 PROMOTER_FLANKING_REGION = 44 ENHANCER = 45 CTCF_BINDING_SITE = 46 OPEN_CHROMATIN_REGION = 47
[docs] class Consequence(enum.IntEnum): """Sequence Ontology variant consequence terms. 41 members corresponding to the proto ``Consequence`` enum. See https://asia.ensembl.org/info/genome/variation/prediction/predicted_data.html#consequences """ TRANSCRIPT_ABLATION = 1 SPLICE_ACCEPTOR_VARIANT = 2 SPLICE_DONOR_VARIANT = 3 STOP_GAINED = 4 FRAMESHIFT_VARIANT = 5 STOP_LOST = 6 START_LOST = 7 TRANSCRIPT_AMPLIFICATION = 8 INFRAME_INSERTION = 9 INFRAME_DELETION = 10 MISSENSE_VARIANT = 11 PROTEIN_ALTERING_VARIANT = 12 SPLICE_REGION_VARIANT = 13 INCOMPLETE_TERMINAL_CODON_VARIANT = 14 START_RETAINED_VARIANT = 15 STOP_RETAINED_VARIANT = 16 SYNONYMOUS_VARIANT = 17 CODING_SEQUENCE_VARIANT = 18 MATURE_MIRNA_VARIANT = 19 FIVE_PRIME_UTR_VARIANT = 20 THREE_PRIME_UTR_VARIANT = 21 NON_CODING_TRANSCRIPT_EXON_VARIANT = 22 INTRON_VARIANT = 23 NMD_TRANSCRIPT_VARIANT = 24 NON_CODING_TRANSCRIPT_VARIANT = 25 UPSTREAM_GENE_VARIANT = 26 DOWNSTREAM_GENE_VARIANT = 27 TFBS_ABLATION = 28 TFBS_AMPLIFICATION = 29 TF_BINDING_SITE_VARIANT = 30 REGULATORY_REGION_ABLATION = 31 REGULATORY_REGION_AMPLIFICATION = 32 FEATURE_ELONGATION = 33 REGULATORY_REGION_VARIANT = 34 FEATURE_TRUNCATION = 35 INTERGENIC_VARIANT = 36 SPLICE_POLYPYRIMIDINE_TRACT_VARIANT = 37 SPLICE_DONOR_5TH_BASE_VARIANT = 38 SPLICE_DONOR_REGION_VARIANT = 39 CODING_TRANSCRIPT_VARIANT = 40 SEQUENCE_VARIANT = 41
[docs] class Impact(enum.IntEnum): """VEP impact severity levels. 4 members ordered from most to least severe: ``HIGH``, ``MODERATE``, ``LOW``, ``MODIFIER``. """ HIGH = 1 MODERATE = 2 LOW = 3 MODIFIER = 4
[docs] class SIFT(enum.IntEnum): """SIFT prediction terms for amino acid substitution impact. See https://sift.bii.a-star.edu.sg/ """ TOLERATED = 1 DELETERIOUS = 2
[docs] class PolyPhen(enum.IntEnum): """PolyPhen-2 prediction terms for amino acid substitution impact.""" BENIGN = 1 POSSIBLY_DAMAGING = 2 PROBABLY_DAMAGING = 3 UNKNOWN = 4
[docs] class ClinSignificance(enum.IntEnum): """ClinVar clinical significance categories. 19 members corresponding to the proto ``ClinSignificance`` enum. See https://www.ncbi.nlm.nih.gov/clinvar/docs/clinsig/ """ CLNSIG_BENIGN = 1 LIKELY_BENIGN = 2 UNCERTAIN_SIGNIFICANCE = 3 LIKELY_PATHOGENIC = 4 PATHOGENIC = 5 DRUG_RESPONSE = 6 ASSOCIATION = 7 RISK_FACTOR = 8 PROTECTIVE = 9 AFFECTS = 10 CONFERS_SENSITIVITY = 11 CONFLICTING_INTERPRETATIONS = 12 NOT_PROVIDED = 13 OTHER = 14 LIKELY_PATHOGENIC_LOW_PENETRANCE = 15 PATHOGENIC_LOW_PENETRANCE = 16 UNCERTAIN_RISK_ALLELE = 17 LIKELY_RISK_ALLELE = 18 ESTABLISHED_RISK_ALLELE = 19
[docs] class AlphaMissense(enum.IntEnum): """AlphaMissense pathogenicity classification. See https://www.science.org/doi/10.1126/science.adg7492 Thresholds: ``AM_LIKELY_BENIGN`` (score < 0.34), ``AM_LIKELY_PATHOGENIC`` (score > 0.564), ``AM_AMBIGUOUS`` (otherwise). """ AM_LIKELY_BENIGN = 1 AM_LIKELY_PATHOGENIC = 2 AM_AMBIGUOUS = 3
[docs] class KinshipDegree(enum.IntEnum): """Kinship relatedness degree classifications. Based on the KING robust kinship estimator phi_bwf thresholds: ``TWINS_MONOZYGOTIC`` (> 0.354), ``FIRST_DEGREE`` (0.177–0.354), ``SECOND_DEGREE`` (0.0884–0.177), ``THIRD_DEGREE`` (0.0442–0.0884), ``UNRELATED`` (< 0.0442). See https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3025716 """ TWINS_MONOZYGOTIC = 1 FIRST_DEGREE = 2 SECOND_DEGREE = 3 THIRD_DEGREE = 4 UNRELATED = 5
# --------------------------------------------------------------------------- # Chromosome alias lookup — explicit dict, no fuzzy matching # --------------------------------------------------------------------------- def _build_chromosome_aliases() -> dict[str, Chromosome]: """Build a case-insensitive alias dict for chromosome resolution. All keys are stored lowercase. The following alias forms are supported for each chromosome: Autosomes 1–22: ``"chr1"``, ``"chr_1"``, ``"1"`` → ``Chromosome.CHR1`` Sex chromosomes: ``"chrx"``, ``"chr_x"``, ``"x"`` → ``Chromosome.CHRX`` ``"chry"``, ``"chr_y"``, ``"y"`` → ``Chromosome.CHRY`` Mitochondrial: ``"chrmt"``, ``"chr_mt"``, ``"mt"`` → ``Chromosome.CHRMT`` """ aliases: dict[str, Chromosome] = {} # Autosomes 1–22 for i in range(1, 23): member = Chromosome(i) aliases[str(i)] = member aliases[f"chr{i}"] = member aliases[f"chr_{i}"] = member # Sex chromosomes aliases["x"] = Chromosome.CHRX aliases["chrx"] = Chromosome.CHRX aliases["chr_x"] = Chromosome.CHRX aliases["y"] = Chromosome.CHRY aliases["chry"] = Chromosome.CHRY aliases["chr_y"] = Chromosome.CHRY # Mitochondrial aliases["mt"] = Chromosome.CHRMT aliases["chrmt"] = Chromosome.CHRMT aliases["chr_mt"] = Chromosome.CHRMT return aliases _CHROMOSOME_ALIASES: dict[str, Chromosome] = _build_chromosome_aliases() # --------------------------------------------------------------------------- # Resolution functions # ---------------------------------------------------------------------------
[docs] def resolve_chromosome(value: Chromosome | str | int) -> Chromosome: """Resolve a chromosome identifier to a ``Chromosome`` enum member. Parameters ---------- value : Chromosome | str | int Accepts: - A ``Chromosome`` enum member (returned as-is). - An integer 1–25 (converted via ``Chromosome(value)``). - A string alias (case-insensitive): ``"chr1"`` / ``"CHR_1"`` / ``"1"`` for autosomes, ``"chrX"`` / ``"X"`` for sex chromosomes, ``"chrMT"`` / ``"MT"`` for mitochondrial DNA. Returns ------- Chromosome The resolved enum member. Raises ------ ValueError If *value* is a string that does not match any known alias. TypeError If *value* is neither a ``Chromosome``, ``str``, nor ``int``. """ if isinstance(value, Chromosome): return value if isinstance(value, int): return Chromosome(value) if isinstance(value, str): result = _CHROMOSOME_ALIASES.get(value.lower()) if result is not None: return result valid = sorted(_CHROMOSOME_ALIASES.keys()) raise ValueError( f"Unknown chromosome {value!r}. " f"Valid inputs: {', '.join(valid)}" ) raise TypeError( f"Expected Chromosome, str, or int, got {type(value).__name__}" )
[docs] def resolve_enum(enum_cls: type[E], value: E | str) -> E: """Resolve a string to an enum member by exact name (case-insensitive). Parameters ---------- enum_cls : type[IntEnum] The target enum class. value : IntEnum | str Either an existing member of *enum_cls* (returned as-is) or a string matching a member name case-insensitively. Returns ------- IntEnum The resolved enum member. Raises ------ ValueError If *value* is a string that does not match any member name in *enum_cls*. The error message lists all valid member names. """ if isinstance(value, enum_cls): return value if isinstance(value, str): upper = value.upper() for member in enum_cls: if member.name == upper: return member valid_names = [m.name for m in enum_cls] raise ValueError( f"Unknown {enum_cls.__name__} value {value!r}. " f"Valid values: {', '.join(valid_names)}" ) raise TypeError( f"Expected {enum_cls.__name__} or str, got {type(value).__name__}" )
[docs] def resolve_assembly(value: RefAssembly | str) -> RefAssembly: """Resolve a reference assembly identifier to a ``RefAssembly`` enum member. Parameters ---------- value : RefAssembly | str Accepts a ``RefAssembly`` member or a string: ``"GRCh37"``, ``"GRCh38"`` (case-insensitive). Returns ------- RefAssembly The resolved enum member. Raises ------ ValueError If *value* is a string that does not match a known assembly name. """ if isinstance(value, RefAssembly): return value if isinstance(value, str): upper = value.upper() for member in RefAssembly: if member.name.upper() == upper: return member valid_names = [m.name for m in RefAssembly] raise ValueError( f"Unknown assembly {value!r}. " f"Valid values: {', '.join(valid_names)}" ) raise TypeError( f"Expected RefAssembly or str, got {type(value).__name__}" )