Skip to content

Commit

Permalink
add strucvar dcision tree (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
gromdimon authored Apr 15, 2024
1 parent 1100975 commit 4749544
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 18 deletions.
6 changes: 3 additions & 3 deletions src/seqvar_pvs1.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
from src.defs.seqvar import SeqVar


class SeqVarPVS1Helpers:
"""Helper methods for PVS1 criteria for transcript."""
class SeqVarPVS1Helper:
"""Helper methods for PVS1 criteria for sequence variants."""

@staticmethod
def _get_pHGVS_termination(pHGVS: str) -> int:
Expand Down Expand Up @@ -352,7 +352,7 @@ def _choose_transcript(
return seqvar_transcript, gene_transcript


class SeqVarPVS1(SeqVarPVS1Helpers):
class SeqVarPVS1(SeqVarPVS1Helper):
"""PVS1 criteria for transcript."""

def __init__(self, seqvar: SeqVar):
Expand Down
142 changes: 132 additions & 10 deletions src/strucvar_pvs1.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,66 @@
"""PVS1 criteria for Structural Variants (StrucVar)."""

import typer

from src.defs.autopvs1 import PVS1Prediction, PVS1PredictionStrucVarPath
from src.defs.strucvar import StrucVar, StrucVarType


class StrucVarPVS1:
class StrucVarPVS1Helper:
"""Helper methods for PVS1 criteria for structural variants."""

@staticmethod
def _full_gene_deletion() -> bool:
"""Check if the variant is a full gene deletion."""
return False

@staticmethod
def _deletion_disrupts_rf() -> bool:
"""Check if the single or multiple exon deletion disrupts the reading frame."""
return False

@staticmethod
def _undergo_nmd() -> bool:
"""Check if the deletion is expected to undergo NMD."""
return False

@staticmethod
def _in_biologically_relevant_transcript() -> bool:
"""Check if the deletion is in a biologically relevant transcript."""
return False

@staticmethod
def _critical4protein_function() -> bool:
"""Check if the deletion is critical for protein function."""
return False

@staticmethod
def _lof_is_frequent_in_population() -> bool:
"""Check if loss-of-function is frequent in the population."""
return False

@staticmethod
def _lof_removes_more_then_10_percent_of_protein() -> bool:
"""Check if the loss-of-function removes more than 10% of the protein."""
return False

@staticmethod
def _proven_in_tandem() -> bool:
"""Check if the duplication is proven in tandem."""
return False

@staticmethod
def _presumed_in_tandem() -> bool:
"""Check if the duplication is presumed in tandem."""
return False

@staticmethod
def _duplication_disrupts_rf() -> bool:
"""Check if the duplication disrupts the reading frame."""
return False


class StrucVarPVS1(StrucVarPVS1Helper):
"""PVS1 prediction for structural variants."""

def __init__(self, variant: StrucVar):
Expand All @@ -14,21 +70,87 @@ def __init__(self, variant: StrucVar):

def initialize(self):
"""Initialize the PVS1 prediction."""
if self.variant.sv_type == StrucVarType.DEL:
self.prediction_path = PVS1PredictionStrucVarPath.DEL1
elif self.variant.sv_type == StrucVarType.DUP:
self.prediction_path = PVS1PredictionStrucVarPath.DUP1
pass

def verify_PVS1(self):
"""Verify PVS1 prediction."""
if self.variant.sv_type == StrucVarType.DEL:
self.prediction = PVS1Prediction.PVS1
if self._full_gene_deletion():
self.prediction = PVS1Prediction.PVS1
self.prediction_path = PVS1PredictionStrucVarPath.DEL1
elif self._deletion_disrupts_rf() and self._undergo_nmd():
if self._in_biologically_relevant_transcript():
self.prediction = PVS1Prediction.PVS1
self.prediction_path = PVS1PredictionStrucVarPath.DEL2
else:
self.prediction = PVS1Prediction.NotPVS1
self.prediction_path = PVS1PredictionStrucVarPath.DEL3
elif self._deletion_disrupts_rf() and not self._undergo_nmd():
if self._critical4protein_function():
self.prediction = PVS1Prediction.PVS1_Strong
self.prediction_path = PVS1PredictionStrucVarPath.DEL4
else:
if (
self._lof_is_frequent_in_population()
or not self._in_biologically_relevant_transcript()
):
self.prediction = PVS1Prediction.NotPVS1
self.prediction_path = PVS1PredictionStrucVarPath.DEL5
else:
if self._lof_removes_more_then_10_percent_of_protein():
self.prediction = PVS1Prediction.PVS1_Strong
self.prediction_path = PVS1PredictionStrucVarPath.DEL6
else:
self.prediction = PVS1Prediction.PVS1_Moderate
self.prediction_path = PVS1PredictionStrucVarPath.DEL7
else:
if self._critical4protein_function():
self.prediction = PVS1Prediction.PVS1_Strong
self.prediction_path = PVS1PredictionStrucVarPath.DEL8
else:
if (
self._lof_is_frequent_in_population()
or not self._in_biologically_relevant_transcript()
):
self.prediction = PVS1Prediction.NotPVS1
self.prediction_path = PVS1PredictionStrucVarPath.DEL5
else:
if self._lof_removes_more_then_10_percent_of_protein():
self.prediction = PVS1Prediction.PVS1_Strong
self.prediction_path = PVS1PredictionStrucVarPath.DEL6
else:
self.prediction = PVS1Prediction.PVS1_Moderate
self.prediction_path = PVS1PredictionStrucVarPath.DEL7

elif self.variant.sv_type == StrucVarType.DUP:
self.prediction = PVS1Prediction.PVS1
if self._proven_in_tandem():
if self._duplication_disrupts_rf() and self._undergo_nmd():
self.prediction = PVS1Prediction.PVS1
self.prediction_path = PVS1PredictionStrucVarPath.DUP1
else:
self.prediction = PVS1Prediction.NotPVS1
self.prediction_path = PVS1PredictionStrucVarPath.DUP2
elif self._presumed_in_tandem():
if self._duplication_disrupts_rf() and self._undergo_nmd():
self.prediction = PVS1Prediction.PVS1_Strong
self.prediction_path = PVS1PredictionStrucVarPath.DUP3
else:
self.prediction = PVS1Prediction.NotPVS1
self.prediction_path = PVS1PredictionStrucVarPath.DUP2

else:
self.prediction = PVS1Prediction.NotPVS1
self.prediction_path = PVS1PredictionStrucVarPath.DUP4

else:
self.prediction = PVS1Prediction.NotPVS1
self.prediction_path = PVS1PredictionStrucVarPath.NotSet
typer.secho(
f"Invalid structural variant. Ensure the structural variant type is either DEL or DUP.",
err=True,
fg=typer.colors.RED,
)

def get_prediction(self) -> tuple[PVS1Prediction, PVS1PredictionStrucVarPath]:
"""Get the PVS1 prediction."""
return self.prediction, self.prediction_path

def __repr__(self):
return f"{self.variant.user_repr} - {self.prediction.name}"
10 changes: 5 additions & 5 deletions tests/test_seqvar_pvs1.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from src.defs.genome_builds import GenomeRelease
from src.defs.mehari import GeneTranscripts, TranscriptsSeqVar
from src.defs.seqvar import SeqVar
from src.seqvar_pvs1 import SeqVarPVS1, SeqVarPVS1Helpers, SeqVarTranscriptsHelper
from src.seqvar_pvs1 import SeqVarPVS1, SeqVarPVS1Helper, SeqVarTranscriptsHelper
from tests.utils import get_json_object


Expand Down Expand Up @@ -70,7 +70,7 @@ def __init__(self, altStartI, altEndI, altCdsStartI=None, altCdsEndI=None, cigar
)
def test_get_pHGVS_termination(pHGVS, expected_termination):
"""Test the _get_pHGVS_termination method."""
termination = SeqVarPVS1Helpers._get_pHGVS_termination(pHGVS)
termination = SeqVarPVS1Helper._get_pHGVS_termination(pHGVS)
assert termination == expected_termination, f"Failed for pHGVS: {pHGVS}"


Expand All @@ -92,7 +92,7 @@ def test_get_pHGVS_termination(pHGVS, expected_termination):
)
def test_undergo_nmd(exons, pHGVS, hgnc_id, expected_result):
"""Test the _undergo_nmd method."""
result = SeqVarPVS1Helpers()._undergo_nmd(exons, pHGVS, hgnc_id)
result = SeqVarPVS1Helper()._undergo_nmd(exons, pHGVS, hgnc_id)
assert result == expected_result, f"Failed for hgnc_id: {hgnc_id}, pHGVS: {pHGVS}"


Expand All @@ -110,7 +110,7 @@ def test_undergo_nmd(exons, pHGVS, hgnc_id, expected_result):
)
def test_in_biologically_relevant_transcript(transcript_tags, expected_result):
"""Test the _in_biologically_relevant_transcript method."""
result = SeqVarPVS1Helpers._in_biologically_relevant_transcript(transcript_tags)
result = SeqVarPVS1Helper._in_biologically_relevant_transcript(transcript_tags)
assert result == expected_result, f"Failed for transcript_tags: {transcript_tags}"


Expand Down Expand Up @@ -142,7 +142,7 @@ def test_lof_is_frequent_in_population():
)
def test_lof_removes_more_then_10_percent_of_protein(exons, pHGVS, expected_result):
"""Test the _lof_removes_more_then_10_percent_of_protein method."""
result = SeqVarPVS1Helpers._lof_removes_more_then_10_percent_of_protein(pHGVS, exons)
result = SeqVarPVS1Helper._lof_removes_more_then_10_percent_of_protein(pHGVS, exons)
assert (
result == expected_result
), f"Expected {expected_result} for pHGVS: {pHGVS} with exon lengths: {[exon.altEndI - exon.altStartI for exon in exons]}"
Expand Down

0 comments on commit 4749544

Please sign in to comment.