Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PM4 and BP3 rules for VCEPs #177

Merged
merged 5 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"type": "debugpy",
"request": "launch",
"module": "src.cli",
"args": ["NM_000038.6(APC):c.2476T>G", "--genome-release", "grch38"],
"args": ["NM_000314.7(PTEN):c.1133_1136del", "--genome-release", "grch38"],
"console": "integratedTerminal"
},
{
Expand Down
31 changes: 31 additions & 0 deletions src/criteria/auto_pm4_bp3.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,20 @@ def is_inframe_delins(var_data: AutoACMGData) -> bool:
return True
return False

def _bp3_not_applicable(self, seqvar: SeqVar, var_data: AutoACMGData) -> bool:
"""
Check if BP3 is not applicable for the variant.

Args:
var_data (AutoACMGData): The variant information.

Returns:
bool: True if BP3 is not applicable, False otherwise.
"""
if seqvar.chrom == "MT":
return True
return False

def verify_pm4bp3(self, seqvar: SeqVar, var_data: AutoACMGData) -> Tuple[Optional[PM4BP3], str]:
"""Predicts PM4 and BP3 criteria for the provided sequence variant.

Expand Down Expand Up @@ -182,6 +196,23 @@ def predict_pm4bp3(
bp3_pred = AutoACMGPrediction.Failed
pm4_strength = AutoACMGStrength.PathogenicModerate
bp3_strength = AutoACMGStrength.BenignSupporting

# BP3 is not applicable for some VCEPs
if self._bp3_not_applicable(seqvar, var_data):
return (
AutoACMGCriteria(
name="PM4",
prediction=pm4_pred,
strength=pm4_strength,
summary=comment,
),
AutoACMGCriteria(
name="BP3",
prediction=AutoACMGPrediction.NotApplicable,
strength=bp3_strength,
summary="BP3 is not applicable for the gene.",
),
)
return (
AutoACMGCriteria(
name="PM4",
Expand Down
16 changes: 16 additions & 0 deletions src/defs/auto_acmg.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from enum import auto
from typing import Dict, List, Optional

from pydantic import BaseModel, ConfigDict

from src.defs.annonars_variant import GnomadExomes, GnomadMtDna
from src.defs.core import AutoAcmgBaseEnum, AutoAcmgBaseModel
from src.defs.mehari import Exon, TranscriptGene, TranscriptSeqvar
Expand Down Expand Up @@ -428,3 +430,17 @@ class AutoACMGResult(AutoAcmgBaseModel):
data: AutoACMGData = AutoACMGData()
# ; ACMG criteria prediction
criteria: AutoACMGCriteriaResult = AutoACMGCriteriaResult()


class VcepSpec(BaseModel):
#: Identifier, e.g., "GN002"
identifier: str
#: Version, e.g., "2.0.0"
version: str
#: Title of the VCEP specification, e.g., "ClinGen Cardiomyopathy Expert Panel Specifications
#: to the ACMG/AMP Variant Interpretation Guidelines for MYH7".
title: Optional[str] = None

model_config = ConfigDict(
frozen=True,
)
2 changes: 1 addition & 1 deletion src/vcep/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from src.vcep.glaucoma import GlaucomaPredictor
from src.vcep.hbopc import HBOPCPredictor
from src.vcep.hearing_loss import HearingLossPredictor
from src.vcep.hhtp import HHTPredictor
from src.vcep.hht import HHTPredictor
from src.vcep.insight_colorectal_cancer import InsightColorectalCancerPredictor
from src.vcep.leber_congenital_amaurosis import LeberCongenitalAmaurosisPredictor
from src.vcep.lysosomal_diseases import LysosomalDiseasesPredictor
Expand Down
20 changes: 19 additions & 1 deletion src/vcep/acadvl.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,26 @@
Link: https://cspec.genome.network/cspec/ui/svi/doc/GN021
"""

from typing import Tuple

from loguru import logger

from src.criteria.default_predictor import DefaultPredictor
from src.defs.auto_acmg import AutoACMGCriteria, AutoACMGData, AutoACMGPrediction, AutoACMGStrength
from src.defs.auto_acmg import (
AutoACMGCriteria,
AutoACMGData,
AutoACMGPrediction,
AutoACMGStrength,
VcepSpec,
)
from src.defs.seqvar import SeqVar

#: VCEP specification for ACADVL.
SPEC: VcepSpec = VcepSpec(
identifier="GN021",
version="1.0.0",
)

PM1_CLUSTER = [
(214, 223), # Nucleotide and substrate binding
(249, 251), # Nucleotide and substrate binding
Expand Down Expand Up @@ -44,3 +58,7 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri
strength=AutoACMGStrength.PathogenicModerate,
summary="Variant does not fall within any critical region for ACADVL. PM1 is not met.",
)

def _bp3_not_applicable(self, seqvar: SeqVar, var_data: AutoACMGData) -> bool:
"""Override BP3 to be not applicable for ACADVL."""
return True
20 changes: 20 additions & 0 deletions src/vcep/brain_malformations.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,26 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri
else:
return super().predict_pm1(seqvar, var_data)

def predict_pm4bp3(
self, seqvar: SeqVar, var_data: AutoACMGData
) -> Tuple[AutoACMGCriteria, AutoACMGCriteria]:
"""Override predict_pm4bp3 to include VCEP-specific logic for brain malformations VCEP."""
logger.info("Predict PM4 and BP3")
return (
AutoACMGCriteria(
name="PM4",
prediction=AutoACMGPrediction.NotApplicable,
strength=AutoACMGStrength.PathogenicModerate,
summary="PM4 is not applicable for the brain malformations VCEP.",
),
AutoACMGCriteria(
name="BP3",
prediction=AutoACMGPrediction.NotApplicable,
strength=AutoACMGStrength.BenignSupporting,
summary="BP3 is not applicable for the brain malformations VCEP.",
),
)

def predict_bp7(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteria:
"""Change the PhyloP100 score threshold for BP7."""
var_data.thresholds.phyloP100 = 0.1
Expand Down
6 changes: 6 additions & 0 deletions src/vcep/cardiomyopathy.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
https://cspec.genome.network/cspec/ui/svi/doc/GN103
"""

from typing import Tuple

from loguru import logger

from src.criteria.default_predictor import DefaultPredictor
Expand Down Expand Up @@ -99,6 +101,10 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri

return super().predict_pm1(seqvar, var_data)

def _bp3_not_applicable(self, seqvar: SeqVar, var_data: AutoACMGData) -> bool:
"""Override BP3 for Cardiomyopathy."""
return True

def predict_bp7(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteria:
"""Override donor and acceptor positions for Cardiomyopathy VCEP."""
var_data.thresholds.bp7_donor = 7
Expand Down
32 changes: 32 additions & 0 deletions src/vcep/cdh1.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
Link: https://cspec.genome.network/cspec/ui/svi/doc/GN007
"""

from typing import Tuple

from loguru import logger

from src.criteria.default_predictor import DefaultPredictor
Expand All @@ -24,6 +26,36 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri
summary="PM1 is not applicable for CDH1.",
)

def predict_pm4bp3(
self, seqvar: SeqVar, var_data: AutoACMGData
) -> Tuple[AutoACMGCriteria, AutoACMGCriteria]:
"""Override predict_pm4bp3 to include VCEP-specific logic for CDH1."""
logger.info("Predict PM4 and BP3")
pred, comment = super().verify_pm4bp3(seqvar, var_data)
if pred:
pm4 = (
AutoACMGPrediction.Met
if pred.PM4
else (AutoACMGPrediction.NotMet if pred.PM4 is False else AutoACMGPrediction.Failed)
)
else:
pm4 = AutoACMGPrediction.Failed
comment = "PM4 could not be verified."
return (
AutoACMGCriteria(
name="PM4",
prediction=pm4,
strength=AutoACMGStrength.PathogenicSupporting,
summary=comment,
),
AutoACMGCriteria(
name="BP3",
prediction=AutoACMGPrediction.NotApplicable,
strength=AutoACMGStrength.BenignSupporting,
summary="BP3 is not applicable for CDH1.",
),
)

def predict_bp7(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteria:
"""Override donor and acceptor positions for CDH1 VCEP."""
var_data.thresholds.bp7_donor = 7
Expand Down
6 changes: 6 additions & 0 deletions src/vcep/cerebral_creatine_deficiency_syndromes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
https://cspec.genome.network/cspec/ui/svi/doc/GN027
"""

from typing import Tuple

from src.criteria.default_predictor import DefaultPredictor
from src.defs.auto_acmg import AutoACMGCriteria, AutoACMGData, AutoACMGPrediction, AutoACMGStrength
from src.defs.seqvar import SeqVar
Expand All @@ -29,6 +31,10 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri
summary="PM1 is not applicable for Cerebral Creatine Deficiency Syndromes.",
)

def _bp3_not_applicable(self, seqvar: SeqVar, var_data: AutoACMGData) -> bool:
"""Override _bp3_not_applicable for Cerebral Creatine Deficiency Syndromes."""
return True

def predict_bp7(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteria:
"""Override donor and acceptor positions for Cerebral Creatine Deficiency Syndromes VCEP."""
if var_data.hgnc_id == "HGNC:4136":
Expand Down
6 changes: 5 additions & 1 deletion src/vcep/coagulation_factor_deficiency.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
https://cspec.genome.network/cspec/ui/svi/doc/GN080
"""

from typing import Dict, List
from typing import Dict, List, Tuple

from loguru import logger

Expand Down Expand Up @@ -133,6 +133,10 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri
summary=f"Variant does not meet the PM1 criteria for {var_data.hgnc_id}.",
)

def _bp3_not_applicable(self, seqvar: SeqVar, var_data: AutoACMGData) -> bool:
"""Override BP3 for Coagulation Factor Deficiency."""
return True

def predict_bp7(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteria:
"""Change the spliceAI and phyloP threshold for BP7."""
if var_data.hgnc_id == "HGNC:3546":
Expand Down
4 changes: 4 additions & 0 deletions src/vcep/congenital_myopathies.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,7 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri
strength=AutoACMGStrength.PathogenicModerate,
summary="Variant does not fall within a critical domain.",
)

def _bp3_not_applicable(self, seqvar: SeqVar, var_data: AutoACMGData) -> bool:
"""Override BP3 for congenital myopathies."""
return True
4 changes: 4 additions & 0 deletions src/vcep/dicer1.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri
summary="Variant does not affect a critical domain for DICER1.",
)

def _bp3_not_applicable(self, seqvar: SeqVar, var_data: AutoACMGData) -> bool:
"""Override BP3 to be not applicable for DICER1."""
return True

def predict_bp7(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteria:
"""Override donor and acceptor positions for DICER1 VCEP."""
var_data.thresholds.bp7_donor = 7
Expand Down
20 changes: 20 additions & 0 deletions src/vcep/enigma.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri

return super().predict_pm1(seqvar, var_data)

def predict_pm4bp3(
self, seqvar: SeqVar, var_data: AutoACMGData
) -> Tuple[AutoACMGCriteria, AutoACMGCriteria]:
"""Override predict_pm4bp3 to include VCEP-specific logic for ENIGMA BRCA1 and BRCA2."""
logger.info("Predict PM4 and BP3")
return (
AutoACMGCriteria(
name="PM4",
prediction=AutoACMGPrediction.NotApplicable,
strength=AutoACMGStrength.PathogenicModerate,
summary="PM4 is not applicable for the ENIGMA VCEP.",
),
AutoACMGCriteria(
name="BP3",
prediction=AutoACMGPrediction.NotApplicable,
strength=AutoACMGStrength.BenignSupporting,
summary="BP3 is not applicable for the ENIGMA VCEP.",
),
)

def _in_important_domain(self, var_data: AutoACMGData) -> bool:
"""Check if the variant is in an important domain."""
for start, end in BP7_IMPORTANT_DOMAINS.get(var_data.hgnc_id, []):
Expand Down
4 changes: 4 additions & 0 deletions src/vcep/familial_hypercholesterolemia.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,7 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri
strength=AutoACMGStrength.PathogenicModerate,
summary=f"Variant does not meet the PM1 criteria for LDLR.",
)

def _bp3_not_applicable(self, seqvar: SeqVar, var_data: AutoACMGData) -> bool:
"""Override BP3 for Familial Hypercholesterolemia."""
return True
4 changes: 4 additions & 0 deletions src/vcep/fbn1.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,7 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri
strength=AutoACMGStrength.PathogenicModerate,
summary=f"Variant does not meet the PM1 criteria for FBN1.",
)

def _bp3_not_applicable(self, seqvar: SeqVar, var_data: AutoACMGData) -> bool:
"""Override BP3 for FBN1."""
return True
4 changes: 4 additions & 0 deletions src/vcep/glaucoma.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri
summary="PM1 is not applicable for MYOC.",
)

def _bp3_not_applicable(self, seqvar: SeqVar, var_data: AutoACMGData) -> bool:
"""Override _bp3_not_applicable for Glaucoma VCEP."""
return True

def _is_conserved(self, var_data: AutoACMGData) -> bool:
"""
Predict if the variant is conserved.
Expand Down
54 changes: 54 additions & 0 deletions src/vcep/hbopc.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
https://cspec.genome.network/cspec/ui/svi/doc/GN077
"""

from typing import Tuple

from loguru import logger

from src.criteria.default_predictor import DefaultPredictor
Expand Down Expand Up @@ -37,6 +39,58 @@ def predict_pm1(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteri

return super().predict_pm1(seqvar, var_data)

def predict_pm4bp3(
self, seqvar: SeqVar, var_data: AutoACMGData
) -> Tuple[AutoACMGCriteria, AutoACMGCriteria]:
"""Override predict_pm4bp3 to include VCEP-specific logic for CDH1."""
logger.info("Predict PM4 and BP3")

if var_data.hgnc_id == "HGNC:795":
pred, comment = self.verify_pm4bp3(seqvar, var_data)
if pred:
pm4 = (
AutoACMGPrediction.Met
if pred.PM4
else (
AutoACMGPrediction.NotMet
if pred.PM4 is False
else AutoACMGPrediction.Failed
)
)
else:
pm4 = AutoACMGPrediction.Failed
comment = "PM4 could not be verified."
return (
AutoACMGCriteria(
name="PM4",
prediction=pm4,
strength=AutoACMGStrength.PathogenicSupporting,
summary=comment,
),
AutoACMGCriteria(
name="BP3",
prediction=AutoACMGPrediction.NotApplicable,
strength=AutoACMGStrength.BenignSupporting,
summary="BP3 is not applicable for ATM.",
),
)
elif var_data.hgnc_id == "HGNC:26144":
return (
AutoACMGCriteria(
name="PM4",
prediction=AutoACMGPrediction.NotApplicable,
strength=AutoACMGStrength.PathogenicSupporting,
summary="PM4 is not applicable for PALB2.",
),
AutoACMGCriteria(
name="BP3",
prediction=AutoACMGPrediction.NotApplicable,
strength=AutoACMGStrength.BenignSupporting,
summary="BP3 is not applicable for PALB2.",
),
)
return super().predict_pm4bp3(seqvar, var_data)

def predict_bp7(self, seqvar: SeqVar, var_data: AutoACMGData) -> AutoACMGCriteria:
"""Override donor and acceptor positions for ATM and PALB2."""
if var_data.hgnc_id == "HGNC:26144":
Expand Down
Loading
Loading