Skip to content

Commit

Permalink
PM4 and BP3 rules for VCEPs (#177)
Browse files Browse the repository at this point in the history
* PM4 and BP3 rules for VCEPs

* Unit tests

* fix integ test for PM4

* PTEN unit test

* formatting
  • Loading branch information
gromdimon authored Aug 28, 2024
1 parent 116f0e4 commit e371aea
Show file tree
Hide file tree
Showing 59 changed files with 1,238 additions and 25 deletions.
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

0 comments on commit e371aea

Please sign in to comment.