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

Fix #4906 - warn on potentially conflicting ACMG terms. #4932

Merged
merged 8 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ About changelog [here](https://keepachangelog.com/en/1.0.0/)
- Link to chanjo2 MANE coverage overview on case page and panel page
- More SVI recommendation links on the ACMG page
- IGV buttons for SMN CN page
- Warnings on ACMG classifications for potentially conflicting classification pairs
### Changed
- Variants query backend allows rank_score filtering
- Added script to tabulate causatives clinical filter rank
Expand Down
50 changes: 49 additions & 1 deletion scout/constants/acmg.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@
(
"BP7",
{
"short": "(not in use)",
"short": "Synonymous, no splice impact",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m going to guess that was from before we had splice prediction in the pipe.

dnil marked this conversation as resolved.
Show resolved Hide resolved
"description": "A synonymous variant for which splicing prediction algorithms predict no impact to the splice consensus sequence nor the creation of a new splice site",
},
),
Expand All @@ -306,3 +306,51 @@
),
]
)

ACMG_POTENTIAL_CONFLICTS = [
(
"PVS1",
"PM4",
"Use of PVS1 and PM4 together risks double-counting evidence (Tayoun et al 2019).",
),
(
"PVS1",
"PM1",
"Use of PVS1 and PM1 together is not recommended (Durkie et al 2024).",
),
(
"PVS1",
"PP2",
"Use of PVS1 and PP2 together is not recommended (Durkie et al 2024).",
),
(
"PVS1",
"PS3",
"Note that for RNA PS3 should only be taken with PVS1 for well established functional assays, not splicing alone (Walker 2023).",
),
(
"PS1",
"PM4",
"Use of PS1 and PM4 together is not recommended (Durkie et al 2024).",
),
(
"PS1",
"PM5",
"Use of PS1 and PM5 together conflicts with original definition (Richards et al 2015).",
),
(
"PS1",
"PP3",
"Use of PS1 and PP3 together risks double-counting evidence (Tayoun et al 2019).",
),
(
"PS2",
"PM6",
"Use of PS2 and PM6 together conflicts with original definition (Richards et al 2015).",
),
(
"PM1",
"PP2",
"Avoid double-counting evidence for constraints in both PM1 and PP2 (Durkie et al 2024).",
),
]
23 changes: 14 additions & 9 deletions scout/server/blueprints/variant/templates/variant/acmg.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,7 @@ <h4>
{% elif not evaluation %}
<button class="btn btn-primary form-control">Submit</button>
{% endif %}
<!-- classification preview in the footer-->
<div class="mt-3 fixed-bottom bg-light border">
<div class="text-center">
{% for option in ACMG_OPTIONS %}
<a id="acmg-{{ option.code }}" class="btn acmg-preview">{{ option.label }}</a>
{% endfor %}
</div>
</div>
<div id="conflicts_div" class="bg-warning"></div>
</div>
</div>

Expand Down Expand Up @@ -108,6 +101,14 @@ <h4>Evidence of {{ category }}</h4>
</div>
{% endfor %}
</div>
<!-- classification preview in the footer-->
<div class="mt-3 fixed-bottom bg-light border">
<div class="text-center">
{% for option in ACMG_OPTIONS %}
<a id="acmg-{{ option.code }}" class="btn acmg-preview">{{ option.label }}</a>
{% endfor %}
</div>
</div>
</form>
</div>
{% endblock %}
Expand Down Expand Up @@ -166,12 +167,16 @@ <h5>Likely Pathogenic</h5>
return 'criterion=' + elem.value
});


$.getJSON('/api/v1/acmg?' + criteria.toArray().join('&'), function(data) {
// reset the selection
$('.acmg-preview').removeClass('btn-primary');
// add new selection
$('#acmg-' + data.classification).addClass('btn-primary');

// Update any classification conflicts
var conflicts_div = document.getElementById("conflicts_div");
conflicts_div.innerHTML = data.conflicts.join("<br>");

});
}
</script>
Expand Down
5 changes: 3 additions & 2 deletions scout/server/blueprints/variant/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
)
from scout.server.extensions import loqusdb, store
from scout.server.utils import institute_and_case, public_endpoint, templated
from scout.utils.acmg import get_acmg
from scout.utils.acmg import get_acmg, get_acmg_conflicts
from scout.utils.ensembl_rest_clients import EnsemblRestApiClient

LOG = logging.getLogger(__name__)
Expand Down Expand Up @@ -347,7 +347,8 @@ def acmg():
"""Calculate an ACMG classification from submitted criteria."""
criteria = request.args.getlist("criterion")
classification = get_acmg(criteria)
return jsonify(dict(classification=classification))
acmg_conflicts = get_acmg_conflicts(criteria)
return jsonify({"classification": classification, "conflicts": acmg_conflicts})


@variant_bp.route(
Expand Down
16 changes: 16 additions & 0 deletions scout/utils/acmg.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# coding=UTF-8
from flask import flash
dnil marked this conversation as resolved.
Show resolved Hide resolved

from scout.constants.acmg import ACMG_POTENTIAL_CONFLICTS


def is_pathogenic(pvs, ps_terms, pm_terms, pp_terms):
"""Check if the criterias for Pathogenic is fullfilled

Expand Down Expand Up @@ -249,3 +254,14 @@ def get_acmg(acmg_terms):
prediction = "likely_benign"

return prediction


def get_acmg_conflicts(acmg_terms: set) -> list:
"""Check potential conflict paris, return list of reference strings."""

conflicts = []
for t1, t2, reference in ACMG_POTENTIAL_CONFLICTS:
if t1 in acmg_terms and t2 in acmg_terms:
conflicts.append(reference)

return conflicts
7 changes: 7 additions & 0 deletions tests/utils/test_acmg.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from scout.utils.acmg import (
get_acmg,
get_acmg_conflicts,
is_benign,
is_likely_benign,
is_likely_pathogenic,
Expand Down Expand Up @@ -433,3 +434,9 @@ def test_acmg_benign_moderate():
acmg_terms = {"BP1_Moderate", "BS1"}
res = get_acmg(acmg_terms)
assert res == "likely_benign"


def test_acmg_conflicts():
acmg_terms = {"PVS1", "PM4"}
conflicts = get_acmg_conflicts(acmg_terms)
assert len(conflicts) == 1
Loading