scout-browser 4.101.0__py3-none-any.whl → 4.103.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scout/adapter/mongo/case.py +26 -122
- scout/adapter/mongo/clinvar.py +98 -32
- scout/adapter/mongo/event.py +0 -47
- scout/adapter/mongo/hgnc.py +7 -2
- scout/adapter/mongo/omics_variant.py +8 -0
- scout/adapter/mongo/variant_loader.py +12 -4
- scout/build/variant/variant.py +1 -0
- scout/commands/load/variants.py +1 -1
- scout/commands/update/user.py +87 -49
- scout/constants/__init__.py +4 -0
- scout/constants/clinvar.py +10 -0
- scout/constants/igv_tracks.py +6 -2
- scout/constants/phenotype.py +1 -0
- scout/constants/variant_tags.py +18 -0
- scout/demo/NIST.trgt.stranger.vcf.gz +0 -0
- scout/demo/NIST.trgt.stranger.vcf.gz.tbi +0 -0
- scout/demo/__init__.py +1 -0
- scout/load/hpo.py +8 -2
- scout/models/clinvar.py +86 -0
- scout/parse/variant/coordinates.py +5 -1
- scout/parse/variant/gene.py +5 -9
- scout/parse/variant/genotype.py +66 -42
- scout/parse/variant/variant.py +2 -0
- scout/server/app.py +71 -2
- scout/server/blueprints/alignviewers/controllers.py +8 -6
- scout/server/blueprints/alignviewers/templates/alignviewers/igv_viewer.html +4 -0
- scout/server/blueprints/alignviewers/templates/alignviewers/utils.html +1 -1
- scout/server/blueprints/cases/controllers.py +57 -29
- scout/server/blueprints/cases/templates/cases/case_report.html +28 -90
- scout/server/blueprints/cases/templates/cases/matchmaker.html +1 -1
- scout/server/blueprints/cases/templates/cases/phenotype.html +1 -1
- scout/server/blueprints/cases/templates/cases/utils.html +34 -53
- scout/server/blueprints/cases/views.py +32 -33
- scout/server/blueprints/clinvar/controllers.py +235 -54
- scout/server/blueprints/clinvar/form.py +38 -1
- scout/server/blueprints/clinvar/static/form_style.css +8 -1
- scout/server/blueprints/clinvar/templates/clinvar/clinvar_onc_submissions.html +200 -0
- scout/server/blueprints/clinvar/templates/clinvar/clinvar_submissions.html +3 -2
- scout/server/blueprints/clinvar/templates/clinvar/components.html +198 -0
- scout/server/blueprints/clinvar/templates/clinvar/multistep_add_onc_variant.html +187 -0
- scout/server/blueprints/clinvar/templates/clinvar/multistep_add_variant.html +9 -348
- scout/server/blueprints/clinvar/templates/clinvar/scripts.html +193 -0
- scout/server/blueprints/clinvar/views.py +90 -13
- scout/server/blueprints/diagnoses/controllers.py +4 -8
- scout/server/blueprints/diagnoses/templates/diagnoses/diagnoses.html +1 -1
- scout/server/blueprints/diagnoses/templates/diagnoses/disease_term.html +1 -1
- scout/server/blueprints/diagnoses/views.py +2 -2
- scout/server/blueprints/institutes/controllers.py +148 -75
- scout/server/blueprints/institutes/forms.py +1 -0
- scout/server/blueprints/institutes/templates/overview/cases.html +1 -1
- scout/server/blueprints/institutes/templates/overview/gene_variants.html +15 -6
- scout/server/blueprints/institutes/templates/overview/institute_sidebar.html +28 -2
- scout/server/blueprints/institutes/templates/overview/utils.html +1 -1
- scout/server/blueprints/institutes/views.py +17 -4
- scout/server/blueprints/login/controllers.py +2 -1
- scout/server/blueprints/login/views.py +5 -2
- scout/server/blueprints/mme/templates/mme/mme_submissions.html +2 -2
- scout/server/blueprints/omics_variants/templates/omics_variants/outliers.html +2 -2
- scout/server/blueprints/omics_variants/views.py +2 -2
- scout/server/blueprints/phenotypes/controllers.py +15 -2
- scout/server/blueprints/phenotypes/templates/phenotypes/hpo_terms.html +1 -1
- scout/server/blueprints/variant/controllers.py +11 -12
- scout/server/blueprints/variant/templates/variant/cancer-variant.html +2 -1
- scout/server/blueprints/variant/templates/variant/components.html +0 -1
- scout/server/blueprints/variant/templates/variant/sv-variant.html +2 -1
- scout/server/blueprints/variant/templates/variant/utils.html +1 -1
- scout/server/blueprints/variant/templates/variant/variant.html +2 -2
- scout/server/blueprints/variant/templates/variant/variant_details.html +100 -84
- scout/server/blueprints/variant/utils.py +25 -0
- scout/server/blueprints/variants/controllers.py +11 -42
- scout/server/blueprints/variants/templates/variants/cancer-variants.html +5 -3
- scout/server/blueprints/variants/templates/variants/str-variants.html +4 -1
- scout/server/blueprints/variants/templates/variants/sv-variants.html +3 -3
- scout/server/blueprints/variants/templates/variants/utils.html +4 -0
- scout/server/blueprints/variants/templates/variants/variants.html +4 -4
- scout/server/blueprints/variants/views.py +9 -8
- scout/server/config.py +3 -0
- scout/server/extensions/beacon_extension.py +7 -2
- scout/server/extensions/clinvar_extension.py +2 -2
- scout/server/templates/bootstrap_global.html +11 -1
- scout/server/templates/layout.html +6 -1
- scout/server/utils.py +24 -3
- {scout_browser-4.101.0.dist-info → scout_browser-4.103.0.dist-info}/METADATA +1 -1
- {scout_browser-4.101.0.dist-info → scout_browser-4.103.0.dist-info}/RECORD +87 -81
- {scout_browser-4.101.0.dist-info → scout_browser-4.103.0.dist-info}/WHEEL +0 -0
- {scout_browser-4.101.0.dist-info → scout_browser-4.103.0.dist-info}/entry_points.txt +0 -0
- {scout_browser-4.101.0.dist-info → scout_browser-4.103.0.dist-info}/licenses/LICENSE +0 -0
@@ -18,7 +18,12 @@ from scout.constants import (
|
|
18
18
|
)
|
19
19
|
from scout.server.blueprints.variants.controllers import update_form_hgnc_symbols
|
20
20
|
from scout.server.extensions import beacon, loqusdb, store
|
21
|
-
from scout.server.utils import
|
21
|
+
from scout.server.utils import (
|
22
|
+
institute_and_case,
|
23
|
+
jsonconverter,
|
24
|
+
templated,
|
25
|
+
user_institutes,
|
26
|
+
)
|
22
27
|
|
23
28
|
from . import controllers
|
24
29
|
from .forms import GeneVariantFiltersForm, InstituteForm
|
@@ -138,10 +143,18 @@ def gene_variants(institute_id):
|
|
138
143
|
|
139
144
|
data = {}
|
140
145
|
|
146
|
+
institute_choices = [
|
147
|
+
(inst["_id"], f"{inst['display_name']} ({inst['_id']})")
|
148
|
+
for inst in user_institutes(store, current_user)
|
149
|
+
]
|
150
|
+
form = GeneVariantFiltersForm()
|
151
|
+
form.institute.choices = institute_choices
|
152
|
+
users_institute_ids = [choice[0] for choice in institute_choices]
|
153
|
+
|
141
154
|
if request.method == "GET":
|
142
|
-
form
|
155
|
+
form.process(request.args)
|
143
156
|
else: # POST
|
144
|
-
form
|
157
|
+
form.process(request.form)
|
145
158
|
|
146
159
|
if form.variant_type.data == []:
|
147
160
|
form.variant_type.data = ["clinical"]
|
@@ -158,7 +171,7 @@ def gene_variants(institute_id):
|
|
158
171
|
|
159
172
|
variants_query = store.build_variant_query(
|
160
173
|
query=form.data,
|
161
|
-
institute_ids=[inst
|
174
|
+
institute_ids=[inst for inst in form.institute.data if inst in users_institute_ids],
|
162
175
|
category=category,
|
163
176
|
variant_type=variant_type,
|
164
177
|
) # This is the actual query dictionary, not the cursor with results
|
@@ -98,7 +98,7 @@ def google_login() -> Optional[Response]:
|
|
98
98
|
|
99
99
|
redirect_uri: str = url_for("login.authorized", _external=True)
|
100
100
|
try:
|
101
|
-
return oauth_client.google.authorize_redirect(redirect_uri)
|
101
|
+
return oauth_client.google.authorize_redirect(redirect_uri, prompt="select_account")
|
102
102
|
except Exception:
|
103
103
|
flash("An error has occurred while logging in user using Google OAuth", "warning")
|
104
104
|
return None
|
@@ -151,6 +151,7 @@ def perform_flask_login(user_dict: "LoginUser") -> Response:
|
|
151
151
|
|
152
152
|
def logout_oidc_user(session, provider: str):
|
153
153
|
"""Log out a user from an OIDC login provider-"""
|
154
|
+
|
154
155
|
logout_url = current_app.config[provider].get("logout_url")
|
155
156
|
if not logout_url or not session.get("token_response"):
|
156
157
|
return
|
@@ -13,7 +13,7 @@ from flask import (
|
|
13
13
|
session,
|
14
14
|
url_for,
|
15
15
|
)
|
16
|
-
from flask_login import
|
16
|
+
from flask_login import logout_user
|
17
17
|
|
18
18
|
from scout.server.extensions import login_manager, oauth_client, store
|
19
19
|
from scout.server.utils import public_endpoint
|
@@ -102,11 +102,14 @@ def authorized():
|
|
102
102
|
|
103
103
|
@login_bp.route("/logout")
|
104
104
|
def logout():
|
105
|
+
session.pop("email", None)
|
106
|
+
session.pop("name", None)
|
107
|
+
session.pop("locale", None)
|
108
|
+
session.pop("consent_given", None)
|
105
109
|
logout_user() # logs out user from scout
|
106
110
|
for provider in ["GOOGLE", "KEYCLOAK"]:
|
107
111
|
if current_app.config.get(provider):
|
108
112
|
controllers.logout_oidc_user(session, provider)
|
109
|
-
session.clear()
|
110
113
|
flash("you logged out", "success")
|
111
114
|
return redirect(url_for("public.index"))
|
112
115
|
|
@@ -60,7 +60,7 @@
|
|
60
60
|
{% set collapse_id = 'collapse-' + case._id %}
|
61
61
|
{% set max_chars = 300 %}
|
62
62
|
|
63
|
-
{% if case.synopsis|length > max_chars %}
|
63
|
+
{% if case.synopsis and case.synopsis|length > max_chars %}
|
64
64
|
<div>
|
65
65
|
{{ case.synopsis[:max_chars] }}…
|
66
66
|
</div>
|
@@ -80,7 +80,7 @@
|
|
80
80
|
</div>
|
81
81
|
</div>
|
82
82
|
{% else %}
|
83
|
-
{{ case.synopsis }}
|
83
|
+
{{ case.synopsis or 'NA' }}
|
84
84
|
{% endif %}
|
85
85
|
</td>
|
86
86
|
<td>{{ case.status }}</td>
|
@@ -100,8 +100,8 @@
|
|
100
100
|
<span data-bs-toggle="tooltip" data-bs-html="true" title='The ∆ψ-value, which is the difference between the actual observed ψ (intron Jaccard Index splice metric) and the expected ψ - see FRASER vignette for details.'>
|
101
101
|
{{ variant.delta_psi }} <a target="_blank" href="https://www.bioconductor.org/packages/devel/bioc/vignettes/FRASER/inst/doc/FRASER.pdf" rel="noopener noreferrer">Δψ</a></span>
|
102
102
|
{% else %}
|
103
|
-
<span data-bs-toggle="tooltip" data-bs-html="true" title='The log2 fold change - click to see OUTRIDER vignette for details.'>
|
104
|
-
{{ variant.l2fc }} <a target="_blank" href="https://www.bioconductor.org/packages/devel/bioc/vignettes/OUTRIDER/inst/doc/OUTRIDER.pdf" rel="noopener noreferrer">{% if variant.l2fc > 0 %}↑{% elif variant.l2fc < 0 %}↓{% endif %}</a></span>
|
103
|
+
<span data-bs-toggle="tooltip" data-bs-html="true" title='The log2 fold change (fold change) - click to see OUTRIDER vignette for details.'>
|
104
|
+
{{ variant.l2fc }} ({{variant.l2fc|l2fc_2_fc|round(2)}}x) <a target="_blank" href="https://www.bioconductor.org/packages/devel/bioc/vignettes/OUTRIDER/inst/doc/OUTRIDER.pdf" rel="noopener noreferrer">{% if variant.l2fc > 0 %}↑{% elif variant.l2fc < 0 %}↓{% endif %}</a></span>
|
105
105
|
{% endif %}
|
106
106
|
</td>
|
107
107
|
<td>
|
@@ -17,7 +17,7 @@ from scout.server.blueprints.variants.controllers import (
|
|
17
17
|
)
|
18
18
|
from scout.server.blueprints.variants.forms import OutlierFiltersForm
|
19
19
|
from scout.server.extensions import store
|
20
|
-
from scout.server.utils import institute_and_case, templated
|
20
|
+
from scout.server.utils import get_case_genome_build, institute_and_case, templated
|
21
21
|
|
22
22
|
from . import controllers
|
23
23
|
|
@@ -71,7 +71,7 @@ def outliers(institute_id, case_name):
|
|
71
71
|
# Populate chromosome select choices
|
72
72
|
populate_chrom_choices(form, case_obj)
|
73
73
|
|
74
|
-
genome_build =
|
74
|
+
genome_build = get_case_genome_build(case_obj)
|
75
75
|
cytobands = store.cytoband_by_chrom(genome_build)
|
76
76
|
|
77
77
|
update_form_hgnc_symbols(store, case_obj, form)
|
@@ -1,7 +1,17 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
+
from typing import Optional
|
3
4
|
|
4
|
-
|
5
|
+
from scout.adapter import MongoAdapter
|
6
|
+
from scout.constants import HPO_LINK_URL
|
7
|
+
|
8
|
+
|
9
|
+
def hpo_terms(
|
10
|
+
store: MongoAdapter,
|
11
|
+
query: Optional[str] = None,
|
12
|
+
limit: Optional[str] = None,
|
13
|
+
page: Optional[str] = None,
|
14
|
+
) -> dict:
|
5
15
|
"""Retrieves a list of HPO terms from scout database
|
6
16
|
|
7
17
|
Args:
|
@@ -29,4 +39,7 @@ def hpo_terms(store, query=None, limit=None, page=None):
|
|
29
39
|
hpo_phenotypes["phenotypes"] = list(store.hpo_terms(query=query, limit=limit, skip=skip))
|
30
40
|
else:
|
31
41
|
hpo_phenotypes["phenotypes"] = list(store.hpo_terms(limit=limit, skip=skip))
|
32
|
-
|
42
|
+
|
43
|
+
data = hpo_phenotypes
|
44
|
+
data["hpo_link_url"] = HPO_LINK_URL
|
45
|
+
return data
|
@@ -34,7 +34,7 @@
|
|
34
34
|
</thead>
|
35
35
|
{% for pheno in phenotypes %}
|
36
36
|
<tr>
|
37
|
-
<td><a href="
|
37
|
+
<td><a href="{{hpo_link_url}}{{pheno.hpo_id}}" referrerpolicy="no-referrer" target="_blank">{{ pheno.hpo_id }}</a></td>
|
38
38
|
<td><span class="text-body">{{ pheno.description }}</span></td>
|
39
39
|
<td><span class="text-body">{{pheno.genes|length}}</span></td>
|
40
40
|
</tr>
|
@@ -28,6 +28,7 @@ from scout.constants import (
|
|
28
28
|
VERBS_MAP,
|
29
29
|
)
|
30
30
|
from scout.server.blueprints.variant.utils import (
|
31
|
+
get_str_mc,
|
31
32
|
update_representative_gene,
|
32
33
|
update_variant_case_panels,
|
33
34
|
)
|
@@ -40,6 +41,7 @@ from scout.server.utils import (
|
|
40
41
|
case_has_chanjo_coverage,
|
41
42
|
case_has_mt_alignments,
|
42
43
|
case_has_rna_tracks,
|
44
|
+
get_case_genome_build,
|
43
45
|
user_institutes,
|
44
46
|
variant_institute_and_case,
|
45
47
|
)
|
@@ -232,9 +234,7 @@ def variant(
|
|
232
234
|
|
233
235
|
variant_id = variant_obj["variant_id"]
|
234
236
|
|
235
|
-
genome_build =
|
236
|
-
if genome_build not in ["37", "38"]:
|
237
|
-
genome_build = "37"
|
237
|
+
genome_build = get_case_genome_build(case_obj)
|
238
238
|
|
239
239
|
# is variant located on the mitochondria
|
240
240
|
variant_obj["is_mitochondrial"] = any(
|
@@ -314,6 +314,9 @@ def variant(
|
|
314
314
|
|
315
315
|
variant_obj["end_position"] = end_position(variant_obj)
|
316
316
|
|
317
|
+
# common motif count for STR variants
|
318
|
+
variant_obj["str_mc"] = get_str_mc(variant_obj)
|
319
|
+
|
317
320
|
# Add general variant links
|
318
321
|
variant_obj.update(get_variant_links(institute_obj, variant_obj, int(genome_build)))
|
319
322
|
variant_obj["frequencies"] = frequencies(variant_obj)
|
@@ -362,7 +365,7 @@ def variant(
|
|
362
365
|
ccv_evaluation(store, evaluation_obj)
|
363
366
|
ccv_evaluations.append(evaluation_obj)
|
364
367
|
|
365
|
-
case_clinvars = store.
|
368
|
+
case_clinvars = store.case_to_clinvars(case_obj.get("display_name"))
|
366
369
|
|
367
370
|
if variant_id in case_clinvars:
|
368
371
|
variant_obj["clinvar_clinsig"] = case_clinvars.get(variant_id)["clinsig"]
|
@@ -425,9 +428,7 @@ def get_gene_has_full_coverage(institute_obj, case_obj, variant_obj) -> Dict[int
|
|
425
428
|
if not case_obj.get("chanjo2_coverage"):
|
426
429
|
return {}
|
427
430
|
|
428
|
-
genome_build =
|
429
|
-
if genome_build not in ["37", "38"]:
|
430
|
-
genome_build = "37"
|
431
|
+
genome_build = get_case_genome_build(case_obj)
|
431
432
|
|
432
433
|
gene_has_full_coverage: dict = {
|
433
434
|
hgnc_id: chanjo2.get_gene_complete_coverage(
|
@@ -436,7 +437,7 @@ def get_gene_has_full_coverage(institute_obj, case_obj, variant_obj) -> Dict[int
|
|
436
437
|
individuals=case_obj.get("individuals"),
|
437
438
|
build=genome_build,
|
438
439
|
)
|
439
|
-
for hgnc_id in [gene.get("hgnc_id") for gene in variant_obj.get("genes")]
|
440
|
+
for hgnc_id in [gene.get("hgnc_id") for gene in variant_obj.get("genes", [])]
|
440
441
|
}
|
441
442
|
return gene_has_full_coverage
|
442
443
|
|
@@ -555,7 +556,7 @@ def observations(store: MongoAdapter, loqusdb: LoqusDB, variant_obj: dict) -> Di
|
|
555
556
|
f"Could not find a Loqus instance with id:{loqus_id}",
|
556
557
|
"warning",
|
557
558
|
)
|
558
|
-
obs_data[loqus_id]
|
559
|
+
obs_data[loqus_id] = {"observations": "N/A"}
|
559
560
|
continue
|
560
561
|
|
561
562
|
if obs_data[loqus_id] == {}: # Variant was not found
|
@@ -656,9 +657,7 @@ def variant_acmg(store: MongoAdapter, institute_id: str, case_name: str, variant
|
|
656
657
|
store, variant_obj, institute_id, case_name
|
657
658
|
)
|
658
659
|
|
659
|
-
genome_build =
|
660
|
-
if genome_build not in ["37", "38"]:
|
661
|
-
genome_build = "37"
|
660
|
+
genome_build = get_case_genome_build(case_obj)
|
662
661
|
|
663
662
|
add_gene_info(store, variant_obj, genome_build=genome_build)
|
664
663
|
|
@@ -8,6 +8,7 @@
|
|
8
8
|
{% from "variant/sanger.html" import modal_cancel_sanger, modal_sanger, sanger_button %}
|
9
9
|
{% from "variant/gene_disease_relations.html" import orpha_omim_phenotypes %}
|
10
10
|
{% from "variant/rank_score_results.html" import rankscore_panel %}
|
11
|
+
{% from "variants/utils.html" import variant_rank_score %}
|
11
12
|
|
12
13
|
{% block title %}
|
13
14
|
{{ super() }} - {{ institute.display_name }} - {{ case.display_name }} - {{ variant.display_name }}
|
@@ -282,7 +283,7 @@
|
|
282
283
|
<strong>{{ variant.alternative }}</strong>
|
283
284
|
{%- endif -%}
|
284
285
|
</li>
|
285
|
-
<li class="list-group-item">Rank score: <span class="font-weight-bold">{{ variant
|
286
|
+
<li class="list-group-item">Rank score: <span class="font-weight-bold">{{ variant_rank_score(variant) }}</span>
|
286
287
|
</li>
|
287
288
|
<li class="list-group-item">
|
288
289
|
{{ clinsig_table(variant) }}
|
@@ -1,7 +1,6 @@
|
|
1
1
|
{% from "cases/chanjo2_form.html" import chanjo2_report_form %}
|
2
2
|
{% from "variant/buttons.html" import variant_tag_button, variant_tier_button, dismiss_variant_button, mosaic_variant_button %}
|
3
3
|
{% from "variants/utils.html" import compounds_table %}
|
4
|
-
{% from "variant/variant_details.html" import severity_list %}
|
5
4
|
{% from "variant/buttons.html" import reviewer_button, splice_junctions_button %}
|
6
5
|
{% from "variant/utils.html" import igv_track_selection %}
|
7
6
|
|
@@ -7,6 +7,7 @@
|
|
7
7
|
{% from "variant/gene_disease_relations.html" import orpha_omim_phenotypes %}
|
8
8
|
{% from "variant/variant_details.html" import frequencies, gtcall_panel, observations_panel %}
|
9
9
|
{% from "variant/buttons.html" import dismiss_variant_button, splice_junctions_button, variant_tag_button %}
|
10
|
+
{% from "variants/utils.html" import variant_rank_score %}
|
10
11
|
|
11
12
|
{% block title %}
|
12
13
|
{{ super() }} - {{ institute.display_name }} - {{ case.display_name }} - {{ variant.display_name }}
|
@@ -174,7 +175,7 @@
|
|
174
175
|
<li class="list-group-item">Rank <span class="badge rounded-pill bg-secondary float-end">{{ variant.variant_rank }}</span></li>
|
175
176
|
<li class="list-group-item">
|
176
177
|
Rank score
|
177
|
-
<span class="badge rounded-pill bg-secondary float-end">{{
|
178
|
+
<span class="badge rounded-pill bg-secondary float-end">{{variant_rank_score(variant)}}</span>
|
178
179
|
</li>
|
179
180
|
|
180
181
|
<li class="list-group-item">
|
@@ -396,7 +396,7 @@
|
|
396
396
|
<div class="col-1">
|
397
397
|
<!--Define build variable to be used in the UCSC link-->
|
398
398
|
{% set build = "hg19" %}
|
399
|
-
{% if case.genome_build == 38 or variant.chromosome == "MT" %}
|
399
|
+
{% if case.genome_build == "38" or variant.chromosome == "MT" %}
|
400
400
|
{% set build = "hg38" %}
|
401
401
|
{% endif %}
|
402
402
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
{% extends "layout.html" %}
|
2
2
|
{% from "variant/buttons.html" import database_buttons %}
|
3
3
|
{% from "utils.html" import activity_panel, comments_panel, pedigree_panel %}
|
4
|
-
{% from "variants/utils.html" import compounds_table %}
|
4
|
+
{% from "variants/utils.html" import compounds_table, variant_rank_score %}
|
5
5
|
{% from "variant/utils.html" import causative_button, genes_panel, modal_causative, overlapping_panel, pin_button, proteins_panel, transcripts_panel, custom_annotations, gene_panels %}
|
6
6
|
{% from "variant/tx_overview.html" import disease_associated, transcripts_overview %}
|
7
7
|
{% from "variant/gene_disease_relations.html" import autozygosity_panel, genemodels_panel, inheritance_panel, orpha_omim_phenotypes %}
|
@@ -263,7 +263,7 @@
|
|
263
263
|
</td>
|
264
264
|
<td>
|
265
265
|
Rank score
|
266
|
-
<span><strong>{{
|
266
|
+
<span><strong>{{variant_rank_score(variant)}}</strong></span>
|
267
267
|
</td>
|
268
268
|
<td>
|
269
269
|
CADD score
|
@@ -19,7 +19,7 @@
|
|
19
19
|
{% elif variant.category == "sv" %}
|
20
20
|
<th rowspan="2" colspan="1" title="SV caller specific quality score. Note different scales for different callers.">SV quality</th>
|
21
21
|
{% elif variant.category == "str" %}
|
22
|
-
<th rowspan="2" colspan="1">
|
22
|
+
<th rowspan="2" colspan="1">Expansion support</th>
|
23
23
|
{% else %}
|
24
24
|
{% if variant.chromosome in ["MT","M"] %}
|
25
25
|
<th rowspan="2" colspan="1" title="Variant Allele Frequency.">Variant Allele Frequency (VAF)</th>
|
@@ -54,7 +54,8 @@
|
|
54
54
|
|
55
55
|
{% if variant.category == "snv" and variant.chromosome in ["MT","M"] %}
|
56
56
|
<td>
|
57
|
-
{
|
57
|
+
{# Using number == number as a test for NaN value numbers here. Given that they exist, NaN values are the only time a number is not considered equal to itself. #}
|
58
|
+
{% if sample.alt_frequency and sample.alt_frequency != -1 and sample.alt_frequency == sample.alt_frequency %}
|
58
59
|
{{ (100*sample.alt_frequency)|round(2) }}%
|
59
60
|
{% else %}
|
60
61
|
N/A
|
@@ -80,7 +81,7 @@
|
|
80
81
|
<small>N/A</small>
|
81
82
|
{% endif %} (<small>VQ</small>
|
82
83
|
{% if variant.quality not in ["None", None, "-1", -1] %}
|
83
|
-
{{variant.quality}}
|
84
|
+
{{variant.quality|round(1)}}
|
84
85
|
{% else %}
|
85
86
|
<small>N/A</small>
|
86
87
|
{% endif%})
|
@@ -164,38 +165,42 @@
|
|
164
165
|
</div>
|
165
166
|
{% endmacro %}
|
166
167
|
|
168
|
+
{% macro frequencies_table(variant) %}
|
169
|
+
<table class="table table-sm align-middle mb-1" style="font-size: 0.875rem;">
|
170
|
+
<thead class="table-light">
|
171
|
+
<tr>
|
172
|
+
<th scope="col" class="py-1 px-2">Source</th>
|
173
|
+
<th scope="col" class="py-1 px-2">Frequency</th>
|
174
|
+
</tr>
|
175
|
+
</thead>
|
176
|
+
<tbody>
|
177
|
+
{% for freq_name, value, link in variant.frequencies %}
|
178
|
+
<tr>
|
179
|
+
<td class="py-1 px-2">
|
180
|
+
{% if link %}
|
181
|
+
<a href="{{ link }}" target="_blank" rel="noopener" referrerpolicy="no-referrer">{{ freq_name }}</a>
|
182
|
+
{% else %}
|
183
|
+
{{ freq_name }}
|
184
|
+
{% endif %}
|
185
|
+
</td>
|
186
|
+
<td class="py-1 px-2">
|
187
|
+
{% if value %}
|
188
|
+
<span class="badge bg-secondary" style="font-size: 0.75rem;">{{ value|human_decimal }}</span>
|
189
|
+
{% else %}
|
190
|
+
-
|
191
|
+
{% endif %}
|
192
|
+
</td>
|
193
|
+
</tr>
|
194
|
+
{% endfor %}
|
195
|
+
</tbody>
|
196
|
+
</table>
|
197
|
+
{% endmacro %}
|
198
|
+
|
167
199
|
{% macro frequencies(variant) %}
|
168
200
|
<div class="card panel-default">
|
169
201
|
<div class="panel-heading">Frequencies</div>
|
170
202
|
<div class="card-body">
|
171
|
-
|
172
|
-
<thead class="thead table-light">
|
173
|
-
<tr>
|
174
|
-
<th scope="col">Source</th>
|
175
|
-
<th scope="col">Frequency</th>
|
176
|
-
</tr>
|
177
|
-
</thead>
|
178
|
-
<tbody>
|
179
|
-
{% for freq_name, value, link in variant.frequencies %}
|
180
|
-
<tr>
|
181
|
-
<td>
|
182
|
-
{% if link %}
|
183
|
-
<a href="{{ link }}" target="_blank" rel="noopener" referrerpolicy="no-referrer">{{ freq_name }}</a>
|
184
|
-
{% else %}
|
185
|
-
{{ freq_name }}
|
186
|
-
{% endif %}
|
187
|
-
</td>
|
188
|
-
<td>
|
189
|
-
{% if value %}
|
190
|
-
<span class="badge bg-secondary">{{ value|human_decimal }}</span>
|
191
|
-
{% else %}
|
192
|
-
-
|
193
|
-
{% endif %}
|
194
|
-
</td>
|
195
|
-
</tr>
|
196
|
-
{% endfor %}
|
197
|
-
</tbody>
|
198
|
-
</table>
|
203
|
+
{{ frequencies_table(variant) }}
|
199
204
|
</div>
|
200
205
|
</div>
|
201
206
|
{% endmacro %}
|
@@ -282,6 +287,41 @@
|
|
282
287
|
</div>
|
283
288
|
{% endmacro %}
|
284
289
|
|
290
|
+
{% macro old_observations_table(variant) %}
|
291
|
+
<table class="table">
|
292
|
+
<thead class="thead table-light">
|
293
|
+
<tr>
|
294
|
+
<th scope="col">Local archive</th>
|
295
|
+
<th scope="col">Nr obs.</th>
|
296
|
+
<th scope="col">Nr homo.</th>
|
297
|
+
<th scope="col">Frequency</th>
|
298
|
+
</tr>
|
299
|
+
</thead>
|
300
|
+
<tbody>
|
301
|
+
<tr>
|
302
|
+
<td>RD</td>
|
303
|
+
<td>{{ variant.local_obs_old|default('N/A') }}</td>
|
304
|
+
<td>{{ variant.local_obs_hom_old|default('N/A') }}</td>
|
305
|
+
<td>{% if variant.local_obs_old_freq %} {{variant.local_obs_old_freq|round(6)}} {% elif variant.local_obs_old_nr_cases and variant.local_obs_old %} {{ (variant.local_obs_old/variant.local_obs_old_nr_cases)|round(5) }} {% elif variant.local_obs_old_nr_cases %} 0 / {{variant.local_obs_old_nr_cases}} {% else %} N/A {% endif %}</td>
|
306
|
+
</tr>
|
307
|
+
{% if variant.category in ['cancer', 'cancer_sv'] %}
|
308
|
+
<tr>
|
309
|
+
<td>Cancer Germline</td>
|
310
|
+
<td>{{ variant.local_obs_cancer_germline_old|default('N/A') }}</td>
|
311
|
+
<td>{{ variant.local_obs_cancer_germline_hom_old|default('N/A') }}</td>
|
312
|
+
<td>{% if variant.local_obs_cancer_germline_old_freq %} {{variant.local_obs_cancer_germline_old_freq|round(6)}} {% elif variant.local_obs_cancer_germline_old_nr_cases and variant.local_obs_cancer_germline_old %} {{ (variant.local_obs_cancer_germline_old/variant.local_obs_cancer_germline_old_nr_cases)|round(5) }} {% elif variant.local_obs_cancer_germline_old_nr_cases %} 0 / {{variant.local_obs_cancer_germline_old_nr_cases}} {% else %} N/A {% endif %}</td>
|
313
|
+
</tr>
|
314
|
+
<tr>
|
315
|
+
<td>Cancer Somatic</td>
|
316
|
+
<td>{{ variant.local_obs_cancer_somatic_old|default('N/A') }}</td>
|
317
|
+
<td>{{ variant.local_obs_cancer_somatic_hom_old|default('N/A') }}</td>
|
318
|
+
<td>{% if variant.local_obs_cancer_somatic_old_freq %} {{variant.local_obs_cancer_somatic_old_freq|round(6)}} {% elif variant.local_obs_cancer_somatic_old_nr_cases and variant.local_obs_cancer_somatic_old %} {{ (variant.local_obs_cancer_somatic_old/variant.local_obs_cancer_somatic_old_nr_cases)|round(5) }} {% elif variant.local_obs_cancer_somatic_old_nr_cases %} 0 / {{variant.local_obs_cancer_somatic_old_nr_cases}} {% else %} N/A {% endif %}</td>
|
319
|
+
</tr>
|
320
|
+
{% endif %}
|
321
|
+
</tbody>
|
322
|
+
</table>
|
323
|
+
{% endmacro %}
|
324
|
+
|
285
325
|
{% macro old_observations(variant, obs_date) %}
|
286
326
|
{% if "SHOW_OBSERVED_VARIANT_ARCHIVE" in config and config["SHOW_OBSERVED_VARIANT_ARCHIVE"] == true %}
|
287
327
|
<div class="card panel-default">
|
@@ -289,38 +329,7 @@
|
|
289
329
|
<a href="https://github.com/moonso/loqusdb" target="_blank" data-bs-toggle="tooltip" title="Local observations annotated from an archive copy of the loqusdb local frequency database. Only variants above a quality threshold are included, and each case is included only once. {% if variant.local_obs_old_desc %} {{variant.local_obs_old_desc}} {% endif %}">Local observations (archive {{ obs_date or variant.local_obs_old_date or "version"}})</a>
|
290
330
|
</div>
|
291
331
|
<div class="card-body">
|
292
|
-
|
293
|
-
<thead class="thead table-light">
|
294
|
-
<tr>
|
295
|
-
<th scope="col">Archive</th>
|
296
|
-
<th scope="col">Nr obs.</th>
|
297
|
-
<th scope="col">Nr homo.</th>
|
298
|
-
<th scope="col">Frequency</th>
|
299
|
-
</tr>
|
300
|
-
</thead>
|
301
|
-
<tbody>
|
302
|
-
<tr>
|
303
|
-
<td>RD</td>
|
304
|
-
<td>{{ variant.local_obs_old|default('N/A') }}</td>
|
305
|
-
<td>{{ variant.local_obs_hom_old|default('N/A') }}</td>
|
306
|
-
<td>{% if variant.local_obs_old_freq %} {{variant.local_obs_old_freq|round(6)}} {% elif variant.local_obs_old_nr_cases and variant.local_obs_old %} {{ (variant.local_obs_old/variant.local_obs_old_nr_cases)|round(5) }} {% elif variant.local_obs_old_nr_cases %} 0 / {{variant.local_obs_old_nr_cases}} {% else %} N/A {% endif %}</td>
|
307
|
-
</tr>
|
308
|
-
{% if variant.category in ['cancer', 'cancer_sv'] %}
|
309
|
-
<tr>
|
310
|
-
<td>Cancer Germline</td>
|
311
|
-
<td>{{ variant.local_obs_cancer_germline_old|default('N/A') }}</td>
|
312
|
-
<td>{{ variant.local_obs_cancer_germline_hom_old|default('N/A') }}</td>
|
313
|
-
<td>{% if variant.local_obs_cancer_germline_old_freq %} {{variant.local_obs_cancer_germline_old_freq|round(6)}} {% elif variant.local_obs_cancer_germline_old_nr_cases and variant.local_obs_cancer_germline_old %} {{ (variant.local_obs_cancer_germline_old/variant.local_obs_cancer_germline_old_nr_cases)|round(5) }} {% elif variant.local_obs_cancer_germline_old_nr_cases %} 0 / {{variant.local_obs_cancer_germline_old_nr_cases}} {% else %} N/A {% endif %}</td>
|
314
|
-
</tr>
|
315
|
-
<tr>
|
316
|
-
<td>Cancer Somatic</td>
|
317
|
-
<td>{{ variant.local_obs_cancer_somatic_old|default('N/A') }}</td>
|
318
|
-
<td>{{ variant.local_obs_cancer_somatic_hom_old|default('N/A') }}</td>
|
319
|
-
<td>{% if variant.local_obs_cancer_somatic_old_freq %} {{variant.local_obs_cancer_somatic_old_freq|round(6)}} {% elif variant.local_obs_cancer_somatic_old_nr_cases and variant.local_obs_cancer_somatic_old %} {{ (variant.local_obs_cancer_somatic_old/variant.local_obs_cancer_somatic_old_nr_cases)|round(5) }} {% elif variant.local_obs_cancer_somatic_old_nr_cases %} 0 / {{variant.local_obs_cancer_somatic_old_nr_cases}} {% else %} N/A {% endif %}</td>
|
320
|
-
</tr>
|
321
|
-
{% endif %}
|
322
|
-
</tbody>
|
323
|
-
</table>
|
332
|
+
{{ old_observations_table(variant) }}
|
324
333
|
</div>
|
325
334
|
</div>
|
326
335
|
{% endif %}
|
@@ -344,13 +353,15 @@
|
|
344
353
|
<li class="list-group-item">
|
345
354
|
<a href="https://sites.google.com/site/revelgenomics/about" target="_blank" data-bs-toggle="tooltip"
|
346
355
|
title="An ensemble score based on 13 individual scores for predicting the pathogenicity of missense variants. Scores range from 0 to 1. The larger the score the more likely the SNP has damaging effect">REVEL score</a>
|
347
|
-
|
348
|
-
|
349
|
-
|
356
|
+
{% if variant.revel and variant.revel != "-" %}
|
357
|
+
<span class="badge float-end bg-{{variant.revel|get_label_or_color_by_score('revel', 'color')}}" data-bs-toggle="tooltip" title="{{variant.revel|get_label_or_color_by_score('revel', 'label')}}">
|
358
|
+
{{ variant.revel }}
|
359
|
+
</span>
|
350
360
|
{% else %}
|
351
|
-
|
361
|
+
<span class="float-end">
|
362
|
+
{{ "-" }}
|
363
|
+
</span>
|
352
364
|
{% endif %}
|
353
|
-
</span>
|
354
365
|
</li>
|
355
366
|
<li class="list-group-item">
|
356
367
|
<a href="http://database.liulab.science/dbNSFP" target="_blank" data-bs-toggle="tooltip"
|
@@ -378,23 +389,28 @@
|
|
378
389
|
<span class="float-end">{{ variant.spidex|spidex_human if variant.spidex else none|spidex_human }}</span>
|
379
390
|
</li>
|
380
391
|
<li class="list-group-item">
|
392
|
+
{% set spliceai_highest = variant.spliceai_scores | spliceai_max %}
|
381
393
|
<a href="{{ variant.spliceai_link }}" target="_blank" rel="noopener">SpliceAI</a> <a href="https://github.com/Illumina/SpliceAI" target="_blank" rel="noopener">DS max</a>
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
{%
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
394
|
+
{% if spliceai_highest %}
|
395
|
+
<span class="badge bg-{{ spliceai_highest | get_label_or_color_by_score('spliceai', 'color') }} float-end" data-bs-toggle="tooltip" data-bs-html="true" data-bs-placement="bottom"
|
396
|
+
title="<strong>
|
397
|
+
{% for entry in variant.spliceai_scores %}
|
398
|
+
{% if entry is not none %}
|
399
|
+
SpliceAI highest delta score {{ entry }} </strong> at position {{ variant.spliceai_positions[loop.index0]}} relative to this variant. {{ spliceai_highest | get_label_or_color_by_score('spliceai', 'label')}} according to Walker et al 2023.
|
400
|
+
{% if variant.spliceai_predictions[loop.index0] %}
|
401
|
+
<br>All scores and positions(relative to variant):<br>
|
402
|
+
{{ variant.spliceai_predictions[loop.index0] }} <br>
|
403
|
+
{% endif %}
|
404
|
+
<br>
|
405
|
+
{% else %}
|
406
|
+
No SpliceAI positions annotated for this variant.
|
407
|
+
{% endif %}
|
408
|
+
{% endfor %}
|
409
|
+
">
|
410
|
+
{{ variant.spliceai_scores|join(', ') }}
|
411
|
+
{% else %}
|
412
|
+
<span class="float-end">{{ "-" }}
|
413
|
+
{% endif %}
|
398
414
|
</span>
|
399
415
|
</li>
|
400
416
|
</ul>
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import logging
|
2
|
+
import re
|
2
3
|
from typing import Dict, List, Optional, Tuple
|
3
4
|
|
4
5
|
from scout.adapter import MongoAdapter
|
@@ -683,3 +684,27 @@ def associate_variant_genes_with_case_panels(case_obj: Dict, variant_obj: Dict)
|
|
683
684
|
geneid_gene[hgnc_id]["associated_gene_panels"] = matching_panels
|
684
685
|
|
685
686
|
variant_obj["genes"] = list(geneid_gene.values())
|
687
|
+
|
688
|
+
|
689
|
+
def get_str_mc(variant_obj: dict) -> Optional[int]:
|
690
|
+
"""Return variant Short Tandem Repeat motif count, either as given by its ALT MC value
|
691
|
+
from the variant FORMAT field, or as a number given in the ALT on the form
|
692
|
+
'<STR123>'.
|
693
|
+
"""
|
694
|
+
NUM = re.compile(r"\d+")
|
695
|
+
|
696
|
+
alt_mc = None
|
697
|
+
if variant_obj["alternative"] == ".":
|
698
|
+
return alt_mc
|
699
|
+
|
700
|
+
for sample in variant_obj["samples"]:
|
701
|
+
if sample["genotype_call"] in ["./.", ".|", "0/0", "0|0"]:
|
702
|
+
continue
|
703
|
+
alt_mc = sample.get("alt_mc")
|
704
|
+
if alt_mc:
|
705
|
+
return alt_mc
|
706
|
+
|
707
|
+
alt_num = NUM.search(variant_obj["alternative"])
|
708
|
+
if alt_num:
|
709
|
+
alt_mc = int(alt_num.group())
|
710
|
+
return alt_mc
|