scout-browser 4.101.0__py3-none-any.whl → 4.102.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/clinvar.py +7 -7
- scout/adapter/mongo/hgnc.py +7 -2
- scout/adapter/mongo/omics_variant.py +8 -0
- scout/adapter/mongo/variant_loader.py +6 -2
- scout/constants/__init__.py +1 -0
- scout/constants/igv_tracks.py +6 -2
- scout/constants/phenotype.py +1 -0
- scout/load/hpo.py +8 -2
- scout/server/blueprints/alignviewers/controllers.py +8 -6
- scout/server/blueprints/alignviewers/templates/alignviewers/igv_viewer.html +2 -0
- scout/server/blueprints/alignviewers/templates/alignviewers/utils.html +1 -1
- scout/server/blueprints/cases/controllers.py +56 -28
- scout/server/blueprints/cases/templates/cases/case_report.html +9 -88
- 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 +26 -24
- scout/server/blueprints/cases/views.py +32 -33
- scout/server/blueprints/clinvar/controllers.py +3 -2
- 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 +107 -73
- scout/server/blueprints/institutes/templates/overview/cases.html +1 -1
- scout/server/blueprints/login/controllers.py +2 -1
- scout/server/blueprints/login/views.py +5 -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 +10 -11
- scout/server/blueprints/variant/templates/variant/utils.html +1 -1
- scout/server/blueprints/variant/templates/variant/variant_details.html +68 -60
- scout/server/blueprints/variant/utils.py +25 -0
- scout/server/blueprints/variants/controllers.py +11 -42
- scout/server/blueprints/variants/views.py +9 -8
- scout/server/config.py +3 -0
- scout/server/extensions/beacon_extension.py +7 -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.102.0.dist-info}/METADATA +1 -1
- {scout_browser-4.101.0.dist-info → scout_browser-4.102.0.dist-info}/RECORD +45 -45
- {scout_browser-4.101.0.dist-info → scout_browser-4.102.0.dist-info}/WHEEL +0 -0
- {scout_browser-4.101.0.dist-info → scout_browser-4.102.0.dist-info}/entry_points.txt +0 -0
- {scout_browser-4.101.0.dist-info → scout_browser-4.102.0.dist-info}/licenses/LICENSE +0 -0
@@ -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
|
|
@@ -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)
|
@@ -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
|
|
@@ -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
|
|
@@ -164,38 +164,42 @@
|
|
164
164
|
</div>
|
165
165
|
{% endmacro %}
|
166
166
|
|
167
|
+
{% macro frequencies_table(variant) %}
|
168
|
+
<table class="table table-sm align-middle mb-1" style="font-size: 0.875rem;">
|
169
|
+
<thead class="table-light">
|
170
|
+
<tr>
|
171
|
+
<th scope="col" class="py-1 px-2">Source</th>
|
172
|
+
<th scope="col" class="py-1 px-2">Frequency</th>
|
173
|
+
</tr>
|
174
|
+
</thead>
|
175
|
+
<tbody>
|
176
|
+
{% for freq_name, value, link in variant.frequencies %}
|
177
|
+
<tr>
|
178
|
+
<td class="py-1 px-2">
|
179
|
+
{% if link %}
|
180
|
+
<a href="{{ link }}" target="_blank" rel="noopener" referrerpolicy="no-referrer">{{ freq_name }}</a>
|
181
|
+
{% else %}
|
182
|
+
{{ freq_name }}
|
183
|
+
{% endif %}
|
184
|
+
</td>
|
185
|
+
<td class="py-1 px-2">
|
186
|
+
{% if value %}
|
187
|
+
<span class="badge bg-secondary" style="font-size: 0.75rem;">{{ value|human_decimal }}</span>
|
188
|
+
{% else %}
|
189
|
+
-
|
190
|
+
{% endif %}
|
191
|
+
</td>
|
192
|
+
</tr>
|
193
|
+
{% endfor %}
|
194
|
+
</tbody>
|
195
|
+
</table>
|
196
|
+
{% endmacro %}
|
197
|
+
|
167
198
|
{% macro frequencies(variant) %}
|
168
199
|
<div class="card panel-default">
|
169
200
|
<div class="panel-heading">Frequencies</div>
|
170
201
|
<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>
|
202
|
+
{{ frequencies_table(variant) }}
|
199
203
|
</div>
|
200
204
|
</div>
|
201
205
|
{% endmacro %}
|
@@ -282,6 +286,41 @@
|
|
282
286
|
</div>
|
283
287
|
{% endmacro %}
|
284
288
|
|
289
|
+
{% macro old_observations_table(variant) %}
|
290
|
+
<table class="table">
|
291
|
+
<thead class="thead table-light">
|
292
|
+
<tr>
|
293
|
+
<th scope="col">Local archive</th>
|
294
|
+
<th scope="col">Nr obs.</th>
|
295
|
+
<th scope="col">Nr homo.</th>
|
296
|
+
<th scope="col">Frequency</th>
|
297
|
+
</tr>
|
298
|
+
</thead>
|
299
|
+
<tbody>
|
300
|
+
<tr>
|
301
|
+
<td>RD</td>
|
302
|
+
<td>{{ variant.local_obs_old|default('N/A') }}</td>
|
303
|
+
<td>{{ variant.local_obs_hom_old|default('N/A') }}</td>
|
304
|
+
<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>
|
305
|
+
</tr>
|
306
|
+
{% if variant.category in ['cancer', 'cancer_sv'] %}
|
307
|
+
<tr>
|
308
|
+
<td>Cancer Germline</td>
|
309
|
+
<td>{{ variant.local_obs_cancer_germline_old|default('N/A') }}</td>
|
310
|
+
<td>{{ variant.local_obs_cancer_germline_hom_old|default('N/A') }}</td>
|
311
|
+
<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>
|
312
|
+
</tr>
|
313
|
+
<tr>
|
314
|
+
<td>Cancer Somatic</td>
|
315
|
+
<td>{{ variant.local_obs_cancer_somatic_old|default('N/A') }}</td>
|
316
|
+
<td>{{ variant.local_obs_cancer_somatic_hom_old|default('N/A') }}</td>
|
317
|
+
<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>
|
318
|
+
</tr>
|
319
|
+
{% endif %}
|
320
|
+
</tbody>
|
321
|
+
</table>
|
322
|
+
{% endmacro %}
|
323
|
+
|
285
324
|
{% macro old_observations(variant, obs_date) %}
|
286
325
|
{% if "SHOW_OBSERVED_VARIANT_ARCHIVE" in config and config["SHOW_OBSERVED_VARIANT_ARCHIVE"] == true %}
|
287
326
|
<div class="card panel-default">
|
@@ -289,38 +328,7 @@
|
|
289
328
|
<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
329
|
</div>
|
291
330
|
<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>
|
331
|
+
{{ old_observations_table(variant) }}
|
324
332
|
</div>
|
325
333
|
</div>
|
326
334
|
{% endif %}
|
@@ -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
|
@@ -35,6 +35,7 @@ from scout.server.blueprints.variant.utils import (
|
|
35
35
|
clinsig_human,
|
36
36
|
get_callers,
|
37
37
|
get_filters,
|
38
|
+
get_str_mc,
|
38
39
|
predictions,
|
39
40
|
update_representative_gene,
|
40
41
|
update_variant_case_panels,
|
@@ -45,6 +46,7 @@ from scout.server.links import add_gene_links, cosmic_links, str_source_link
|
|
45
46
|
from scout.server.utils import (
|
46
47
|
case_has_alignments,
|
47
48
|
case_has_mt_alignments,
|
49
|
+
get_case_genome_build,
|
48
50
|
institute_and_case,
|
49
51
|
user_institutes,
|
50
52
|
)
|
@@ -57,8 +59,6 @@ from .forms import (
|
|
57
59
|
)
|
58
60
|
from .utils import update_case_panels
|
59
61
|
|
60
|
-
NUM = re.compile(r"\d+")
|
61
|
-
|
62
62
|
LOG = logging.getLogger(__name__)
|
63
63
|
|
64
64
|
|
@@ -106,7 +106,7 @@ def populate_persistent_filters_choices(
|
|
106
106
|
def populate_chrom_choices(form, case_obj):
|
107
107
|
"""Populate the option of the chromosome select according to the case genome build"""
|
108
108
|
# Populate chromosome choices
|
109
|
-
chromosomes = CHROMOSOMES if
|
109
|
+
chromosomes = CHROMOSOMES if get_case_genome_build(case_obj) == "37" else CHROMOSOMES_38
|
110
110
|
form.chrom.choices = [(chrom, chrom) for chrom in chromosomes]
|
111
111
|
|
112
112
|
|
@@ -139,9 +139,7 @@ def variants(
|
|
139
139
|
more_variants = variant_count > (skip_count + per_page)
|
140
140
|
variant_res = variants_query.skip(skip_count).limit(per_page)
|
141
141
|
|
142
|
-
genome_build =
|
143
|
-
if genome_build not in ["37", "38"]:
|
144
|
-
genome_build = "37"
|
142
|
+
genome_build = get_case_genome_build(case_obj)
|
145
143
|
|
146
144
|
case_dismissed_vars = store.case_dismissed_variants(institute_obj, case_obj)
|
147
145
|
|
@@ -237,9 +235,7 @@ def sv_variants(store, institute_obj, case_obj, variants_query, variant_count, p
|
|
237
235
|
|
238
236
|
more_variants = variant_count > (skip_count + per_page)
|
239
237
|
variants = []
|
240
|
-
genome_build =
|
241
|
-
if genome_build not in ["37", "38"]:
|
242
|
-
genome_build = "37"
|
238
|
+
genome_build = get_case_genome_build(case_obj)
|
243
239
|
|
244
240
|
case_dismissed_vars = store.case_dismissed_variants(institute_obj, case_obj)
|
245
241
|
|
@@ -285,9 +281,7 @@ def mei_variants(
|
|
285
281
|
|
286
282
|
more_variants = variant_count > (skip_count + per_page)
|
287
283
|
variants = []
|
288
|
-
genome_build =
|
289
|
-
if genome_build not in ["37", "38"]:
|
290
|
-
genome_build = "37"
|
284
|
+
genome_build = get_case_genome_build(case_obj)
|
291
285
|
|
292
286
|
case_dismissed_vars = store.case_dismissed_variants(institute_obj, case_obj)
|
293
287
|
|
@@ -353,9 +347,7 @@ def fusion_variants(
|
|
353
347
|
|
354
348
|
more_variants = variant_count > (skip_count + per_page)
|
355
349
|
variants = []
|
356
|
-
genome_build =
|
357
|
-
if genome_build not in ["37", "38"]:
|
358
|
-
genome_build = "38"
|
350
|
+
genome_build = get_case_genome_build(case_obj)
|
359
351
|
|
360
352
|
case_dismissed_vars = store.case_dismissed_variants(institute_obj, case_obj)
|
361
353
|
|
@@ -997,28 +989,6 @@ def parse_variant(
|
|
997
989
|
return variant_obj
|
998
990
|
|
999
991
|
|
1000
|
-
def get_str_mc(variant_obj: dict) -> Optional[int]:
|
1001
|
-
"""Return variant Short Tandem Repeat motif count, either as given by its ALT MC value
|
1002
|
-
from the variant FORMAT field, or as a number given in the ALT on the form
|
1003
|
-
'<STR123>'.
|
1004
|
-
"""
|
1005
|
-
alt_mc = None
|
1006
|
-
if variant_obj["alternative"] == ".":
|
1007
|
-
return alt_mc
|
1008
|
-
|
1009
|
-
for sample in variant_obj["samples"]:
|
1010
|
-
if sample["genotype_call"] in ["./.", ".|", "0/0", "0|0"]:
|
1011
|
-
continue
|
1012
|
-
alt_mc = sample.get("alt_mc")
|
1013
|
-
if alt_mc:
|
1014
|
-
return alt_mc
|
1015
|
-
|
1016
|
-
alt_num = NUM.search(variant_obj["alternative"])
|
1017
|
-
if alt_num:
|
1018
|
-
alt_mc = int(alt_num.group())
|
1019
|
-
return alt_mc
|
1020
|
-
|
1021
|
-
|
1022
992
|
def download_str_variants(case_obj, variant_objs):
|
1023
993
|
"""Download filtered STR variants for a case to a CSV file
|
1024
994
|
|
@@ -1502,7 +1472,9 @@ def upload_panel(store, institute_id, case_name, stream):
|
|
1502
1472
|
hgnc_symbols = set()
|
1503
1473
|
for raw_symbol in raw_symbols:
|
1504
1474
|
matching_genes = list(
|
1505
|
-
store.gene_by_symbol_or_aliases(
|
1475
|
+
store.gene_by_symbol_or_aliases(
|
1476
|
+
symbol=raw_symbol, build=get_case_genome_build(case_obj)
|
1477
|
+
)
|
1506
1478
|
)
|
1507
1479
|
if not matching_genes:
|
1508
1480
|
flash("HGNC symbol not found: {}".format(raw_symbol), "warning")
|
@@ -1983,10 +1955,7 @@ def update_form_hgnc_symbols(store, case_obj, form):
|
|
1983
1955
|
genome_build = None
|
1984
1956
|
case_obj = case_obj or {}
|
1985
1957
|
|
1986
|
-
|
1987
|
-
if build in str(case_obj.get("genome_build", "")):
|
1988
|
-
genome_build = build
|
1989
|
-
break
|
1958
|
+
genome_build = get_case_genome_build(case_obj)
|
1990
1959
|
|
1991
1960
|
# retrieve current symbols from form
|
1992
1961
|
if form.hgnc_symbols.data:
|
@@ -19,7 +19,7 @@ from scout.constants import (
|
|
19
19
|
SEVERE_SO_TERMS_SV,
|
20
20
|
)
|
21
21
|
from scout.server.extensions import store
|
22
|
-
from scout.server.utils import institute_and_case, templated
|
22
|
+
from scout.server.utils import get_case_genome_build, institute_and_case, templated
|
23
23
|
|
24
24
|
from . import controllers
|
25
25
|
from .forms import (
|
@@ -129,7 +129,7 @@ def variants(institute_id, case_name):
|
|
129
129
|
|
130
130
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
131
131
|
|
132
|
-
genome_build =
|
132
|
+
genome_build = get_case_genome_build(case_obj)
|
133
133
|
cytobands = store.cytoband_by_chrom(genome_build)
|
134
134
|
|
135
135
|
variants_query = store.variants(
|
@@ -220,7 +220,7 @@ def str_variants(institute_id, case_name):
|
|
220
220
|
|
221
221
|
controllers.activate_case(store, institute_obj, case_obj, current_user)
|
222
222
|
|
223
|
-
genome_build =
|
223
|
+
genome_build = get_case_genome_build(case_obj)
|
224
224
|
cytobands = store.cytoband_by_chrom(genome_build)
|
225
225
|
|
226
226
|
query = form.data
|
@@ -231,6 +231,7 @@ def str_variants(institute_id, case_name):
|
|
231
231
|
).sort(
|
232
232
|
[
|
233
233
|
("str_repid", pymongo.ASCENDING),
|
234
|
+
("str_trid", pymongo.ASCENDING),
|
234
235
|
("chromosome", pymongo.ASCENDING),
|
235
236
|
("position", pymongo.ASCENDING),
|
236
237
|
]
|
@@ -302,7 +303,7 @@ def sv_variants(institute_id, case_name):
|
|
302
303
|
# Populate custom soft filters
|
303
304
|
controllers.populate_institute_soft_filters(form=form, institute_obj=institute_obj)
|
304
305
|
|
305
|
-
genome_build =
|
306
|
+
genome_build = get_case_genome_build(case_obj)
|
306
307
|
cytobands = store.cytoband_by_chrom(genome_build)
|
307
308
|
|
308
309
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
@@ -397,7 +398,7 @@ def mei_variants(institute_id, case_name):
|
|
397
398
|
# populate available panel choices
|
398
399
|
form.gene_panels.choices = controllers.gene_panel_choices(store, institute_obj, case_obj)
|
399
400
|
|
400
|
-
genome_build =
|
401
|
+
genome_build = get_case_genome_build(case_obj)
|
401
402
|
cytobands = store.cytoband_by_chrom(genome_build)
|
402
403
|
|
403
404
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
@@ -509,7 +510,7 @@ def cancer_variants(institute_id, case_name):
|
|
509
510
|
|
510
511
|
form.gene_panels.choices = controllers.gene_panel_choices(store, institute_obj, case_obj)
|
511
512
|
|
512
|
-
genome_build =
|
513
|
+
genome_build = get_case_genome_build(case_obj)
|
513
514
|
cytobands = store.cytoband_by_chrom(genome_build)
|
514
515
|
|
515
516
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
@@ -587,7 +588,7 @@ def cancer_sv_variants(institute_id, case_name):
|
|
587
588
|
# Populate custom soft filters
|
588
589
|
controllers.populate_institute_soft_filters(form=form, institute_obj=institute_obj)
|
589
590
|
|
590
|
-
genome_build =
|
591
|
+
genome_build = get_case_genome_build(case_obj)
|
591
592
|
cytobands = store.cytoband_by_chrom(genome_build)
|
592
593
|
|
593
594
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
@@ -671,7 +672,7 @@ def fusion_variants(institute_id, case_name):
|
|
671
672
|
# Populate custom soft filters
|
672
673
|
controllers.populate_institute_soft_filters(form=form, institute_obj=institute_obj)
|
673
674
|
|
674
|
-
genome_build =
|
675
|
+
genome_build = get_case_genome_build(case_obj)
|
675
676
|
cytobands = store.cytoband_by_chrom(genome_build)
|
676
677
|
|
677
678
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
scout/server/config.py
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
SECRET_KEY = "this is not secret..."
|
3
3
|
REMEMBER_COOKIE_NAME = "scout_remember_me" # Prevent session timeout when user closes browser
|
4
|
+
# INSTANCE_NAME = "Development" # Name will be displayed on the top navigation menu
|
5
|
+
# INSTANCE_COLOR = "#800000" # Color of the top navigation menu
|
6
|
+
|
4
7
|
# SESSION_TIMEOUT_MINUTES = 60 # Minutes of inactivity before session times out
|
5
8
|
|
6
9
|
# MONGO_URI = "mongodb://127.0.0.1:27011,127.0.0.1:27012,127.0.0.1:27013/?replicaSet=rs0&readPreference=primary"
|
@@ -8,7 +8,12 @@ import logging
|
|
8
8
|
from flask import flash, url_for
|
9
9
|
from flask_login import current_user
|
10
10
|
|
11
|
-
from scout.utils
|
11
|
+
from scout.server.utils import get_case_genome_build
|
12
|
+
from scout.utils.scout_requests import (
|
13
|
+
delete_request_json,
|
14
|
+
get_request_json,
|
15
|
+
post_request_json,
|
16
|
+
)
|
12
17
|
|
13
18
|
LOG = logging.getLogger(__name__)
|
14
19
|
DATASET_BUILDS = ["GRCh37", "GRCh38"]
|
@@ -58,7 +63,7 @@ class Beacon:
|
|
58
63
|
data(dict): a dictionary with base info to be used as json data in beacon add request (lacks path to VCF file to extract variants from)
|
59
64
|
"""
|
60
65
|
# Initialize key/values to be sent in request:
|
61
|
-
assembly = "GRCh38" if
|
66
|
+
assembly = "GRCh38" if get_case_genome_build(case_obj) == "38" else "GRCh37"
|
62
67
|
dataset_id = "_".join([case_obj["owner"], case_obj.get("build", assembly)])
|
63
68
|
|
64
69
|
samples = []
|
@@ -12,7 +12,17 @@
|
|
12
12
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-dark-5@1.1.3/dist/css/bootstrap-dark.min.css" integrity="sha384-pZAJcuaxKZEGkzXV5bYqUcSwBfMZPdQS/+JXdYOu9ScyZJMnGHD5Xi6HVHfZuULH" crossorigin="anonymous">
|
13
13
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
14
14
|
<link rel="stylesheet" href="{{ url_for('static', filename='bs_styles.css') }}">
|
15
|
-
|
15
|
+
|
16
|
+
{% if config.INSTANCE_COLOR %}
|
17
|
+
<style>
|
18
|
+
/* Override Scout's bg-primary with color set on app config, if available */
|
19
|
+
nav.navbar.bg-primary {
|
20
|
+
background-color: {{ config.INSTANCE_COLOR }} !important;
|
21
|
+
}
|
22
|
+
</style>
|
23
|
+
{% endif %}
|
24
|
+
|
25
|
+
{% endblock %}
|
16
26
|
|
17
27
|
{% block css_style %}
|
18
28
|
{% endblock %}
|
@@ -18,9 +18,14 @@
|
|
18
18
|
|
19
19
|
{% block navbar %}
|
20
20
|
<nav class="navbar navbar-expand-lg nav-pills navbar-dark bg-primary sticky-top" >
|
21
|
-
<div class="container-fluid
|
21
|
+
<div class="container-fluid rounded-bottom">
|
22
22
|
<a class="navbar-brand" href="{{ url_for('cases.index') }}">
|
23
23
|
<img src="{{ url_for('public.static', filename='scout-logo.png') }}" width="30" height="30" class="d-inline-block align-top text-white" alt="">Scout</a>
|
24
|
+
{% if config.INSTANCE_NAME %}
|
25
|
+
<span class="badge bg-light text-dark">
|
26
|
+
{{ config.INSTANCE_NAME }}
|
27
|
+
</span>
|
28
|
+
{% endif %}
|
24
29
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
25
30
|
<span class="navbar-toggler-icon"></span>
|
26
31
|
</button>
|