scout-browser 4.84__py3-none-any.whl → 4.86__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/__version__.py +1 -1
- scout/adapter/mongo/base.py +17 -14
- scout/adapter/mongo/case.py +20 -1
- scout/adapter/mongo/cytoband.py +13 -0
- scout/adapter/mongo/filter.py +36 -1
- scout/adapter/mongo/hgnc.py +1 -1
- scout/adapter/mongo/omics_variant.py +145 -0
- scout/adapter/mongo/query.py +13 -3
- scout/adapter/mongo/variant.py +10 -4
- scout/build/case.py +5 -0
- scout/build/variant/variant.py +1 -0
- scout/commands/update/genes.py +9 -13
- scout/constants/__init__.py +3 -1
- scout/constants/case_tags.py +1 -0
- scout/constants/clinvar.py +1 -1
- scout/constants/file_types.py +31 -0
- scout/constants/filters.py +4 -0
- scout/constants/indexes.py +30 -13
- scout/constants/variant_tags.py +3 -0
- scout/demo/643594.clinical.mei.vcf.gz +0 -0
- scout/demo/643594.clinical.mei.vcf.gz.tbi +0 -0
- scout/demo/643594.config.yaml +4 -0
- scout/demo/drop/fraser_top_hits_clinical.tsv +5 -0
- scout/demo/drop/outrider_top_hits_clinical.tsv +10 -0
- scout/load/hgnc_gene.py +39 -6
- scout/load/setup.py +4 -4
- scout/models/case/case_loading_models.py +25 -2
- scout/models/omics_variant.py +227 -0
- scout/parse/hgnc.py +1 -0
- scout/parse/omics_variant/__init__.py +11 -0
- scout/parse/omics_variant/drop.py +19 -0
- scout/parse/variant/callers.py +6 -3
- scout/parse/variant/frequency.py +10 -2
- scout/parse/variant/transcript.py +1 -1
- scout/parse/variant/variant.py +10 -4
- scout/server/app.py +4 -1
- scout/server/blueprints/alignviewers/controllers.py +35 -24
- scout/server/blueprints/alignviewers/templates/alignviewers/igv_sashimi_viewer.html +19 -15
- scout/server/blueprints/alignviewers/templates/alignviewers/igv_viewer.html +45 -5
- scout/server/blueprints/alignviewers/templates/alignviewers/utils.html +1 -1
- scout/server/blueprints/alignviewers/views.py +10 -2
- scout/server/blueprints/cases/controllers.py +18 -1
- scout/server/blueprints/cases/templates/cases/case.html +28 -10
- scout/server/blueprints/cases/templates/cases/case_report.html +2 -17
- scout/server/blueprints/cases/templates/cases/collapsible_actionbar.html +1 -1
- scout/server/blueprints/cases/templates/cases/gene_panel.html +27 -41
- scout/server/blueprints/cases/templates/cases/phenotype.html +8 -5
- scout/server/blueprints/cases/templates/cases/utils.html +27 -4
- scout/server/blueprints/clinvar/controllers.py +9 -3
- scout/server/blueprints/dashboard/controllers.py +44 -13
- scout/server/blueprints/dashboard/static/charts.js +46 -36
- scout/server/blueprints/dashboard/templates/dashboard/dashboard_general.html +2 -2
- scout/server/blueprints/institutes/forms.py +2 -0
- scout/server/blueprints/institutes/templates/overview/cases.html +6 -4
- scout/server/blueprints/institutes/templates/overview/gene_variants.html +40 -27
- scout/server/blueprints/institutes/templates/overview/institute_sidebar.html +1 -1
- scout/server/blueprints/institutes/views.py +5 -12
- scout/server/blueprints/omics_variants/__init__.py +1 -0
- scout/server/blueprints/omics_variants/controllers.py +122 -0
- scout/server/blueprints/omics_variants/templates/omics_variants/outliers.html +262 -0
- scout/server/blueprints/omics_variants/views.py +106 -0
- scout/server/blueprints/panels/controllers.py +1 -7
- scout/server/blueprints/panels/templates/panels/panels.html +12 -4
- scout/server/blueprints/panels/views.py +9 -11
- scout/server/blueprints/variant/templates/variant/buttons.html +7 -2
- scout/server/blueprints/variant/templates/variant/str-variant-reviewer.html +1 -1
- scout/server/blueprints/variant/templates/variant/utils.html +1 -1
- scout/server/blueprints/variant/utils.py +54 -103
- scout/server/blueprints/variant/views.py +1 -0
- scout/server/blueprints/variants/controllers.py +1 -4
- scout/server/blueprints/variants/forms.py +42 -0
- scout/server/blueprints/variants/templates/variants/utils.html +8 -4
- scout/server/blueprints/variants/views.py +28 -7
- scout/server/config.py +4 -0
- scout/server/extensions/clinvar_extension.py +7 -7
- scout/server/links.py +2 -2
- scout/server/templates/bootstrap_global.html +1 -4
- scout/server/templates/utils.html +4 -4
- scout/server/utils.py +4 -1
- {scout_browser-4.84.dist-info → scout_browser-4.86.dist-info}/METADATA +11 -11
- {scout_browser-4.84.dist-info → scout_browser-4.86.dist-info}/RECORD +85 -75
- {scout_browser-4.84.dist-info → scout_browser-4.86.dist-info}/WHEEL +1 -1
- {scout_browser-4.84.dist-info → scout_browser-4.86.dist-info}/LICENSE +0 -0
- {scout_browser-4.84.dist-info → scout_browser-4.86.dist-info}/entry_points.txt +0 -0
- {scout_browser-4.84.dist-info → scout_browser-4.86.dist-info}/top_level.txt +0 -0
@@ -100,7 +100,7 @@
|
|
100
100
|
<div class="col-3">Show tracks:</div>
|
101
101
|
<div class="col-6">
|
102
102
|
<select name="user_tracks" class="selectpicker" data-width="90%" data-style="btn-secondary" multiple>
|
103
|
-
{% for track in igv_tracks %}
|
103
|
+
{% for track in igv_tracks|sort %}
|
104
104
|
<!--pre-select option if user has saved it in preferences or select all options if user has no preferences yet-->
|
105
105
|
<option value="{{ track }}" {{ "selected" if current_user.igv_tracks and track in current_user.igv_tracks or current_user.igv_tracks is not defined }}>{{ track }}</option>
|
106
106
|
{% endfor %}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import logging
|
2
|
-
from typing import Dict, List, Optional
|
2
|
+
from typing import Dict, List, Optional, Tuple
|
3
3
|
|
4
4
|
from scout.adapter import MongoAdapter
|
5
5
|
from scout.constants import ACMG_COMPLETE_MAP, CALLERS, CLINSIG_MAP, SO_TERMS
|
@@ -333,122 +333,72 @@ def predictions(genes):
|
|
333
333
|
return data
|
334
334
|
|
335
335
|
|
336
|
-
def frequencies(variant_obj):
|
337
|
-
"""
|
338
|
-
|
339
|
-
This function converts the raw annotations to something better to visualize.
|
340
|
-
GnomAD is mandatory and will always be shown.
|
336
|
+
def frequencies(variant_obj: dict) -> list[Tuple]:
|
337
|
+
"""Convert raw annotations to a more visual format with frequencies.
|
341
338
|
|
342
339
|
Args:
|
343
340
|
variant_obj(scout.models.Variant)
|
344
341
|
|
345
342
|
Returns:
|
346
|
-
|
343
|
+
list of tuple: A list of frequencies to display.
|
347
344
|
"""
|
348
345
|
is_mitochondrial_variant = variant_obj.get("chromosome") == "MT"
|
346
|
+
category = variant_obj["category"]
|
347
|
+
|
348
|
+
# Define frequency mappings for each category
|
349
|
+
frequency_mappings = {
|
350
|
+
"sv": {
|
351
|
+
"gnomad_frequency": ("GnomAD", variant_obj.get("gnomad_sv_link")),
|
352
|
+
"clingen_cgh_benign": ("ClinGen CGH (benign)", None),
|
353
|
+
"clingen_cgh_pathogenic": ("ClinGen CGH (pathogenic)", None),
|
354
|
+
"clingen_ngi": ("ClinGen NGI", None),
|
355
|
+
"clingen_mip": ("ClinGen MIP", None),
|
356
|
+
"swegen": ("SweGen", None),
|
357
|
+
"decipher": ("Decipher", None),
|
358
|
+
"thousand_genomes_frequency": ("1000G", None),
|
359
|
+
"thousand_genomes_frequency_left": ("1000G(left)", None),
|
360
|
+
"thousand_genomes_frequency_right": ("1000G(right)", None),
|
361
|
+
"colorsdb_af": ("CoLoRSdb", None),
|
362
|
+
},
|
363
|
+
"mei": {
|
364
|
+
"swegen_alu": ("SweGen ALU", None),
|
365
|
+
"swegen_herv": ("SweGen HERV", None),
|
366
|
+
"swegen_l1": ("SweGen L1", None),
|
367
|
+
"swegen_sva": ("SweGen SVA", None),
|
368
|
+
"swegen_mei_max": ("SweGen MEI(max)", None),
|
369
|
+
},
|
370
|
+
"snv": {
|
371
|
+
"gnomad_frequency": ("GnomAD", variant_obj.get("gnomad_link")),
|
372
|
+
"thousand_genomes_frequency": ("1000G", variant_obj.get("thousandg_link")),
|
373
|
+
"max_thousand_genomes_frequency": ("1000G(max)", variant_obj.get("thousandg_link")),
|
374
|
+
"exac_frequency": ("ExAC", variant_obj.get("exac_link")),
|
375
|
+
"max_exac_frequency": ("ExAC(max)", variant_obj.get("exac_link")),
|
376
|
+
"swegen": ("SweGen", variant_obj.get("swegen_link")),
|
377
|
+
"gnomad_mt_homoplasmic_frequency": (
|
378
|
+
"GnomAD MT, homoplasmic",
|
379
|
+
variant_obj.get("gnomad_link"),
|
380
|
+
),
|
381
|
+
"gnomad_mt_heteroplasmic_frequency": (
|
382
|
+
"GnomAD MT, heteroplasmic",
|
383
|
+
variant_obj.get("gnomad_link"),
|
384
|
+
),
|
385
|
+
"colorsdb_af": ("CoLoRSdb", None),
|
386
|
+
},
|
387
|
+
}
|
388
|
+
|
389
|
+
# Select the appropriate frequency dictionary
|
390
|
+
freqs = frequency_mappings.get(category, frequency_mappings["snv"])
|
349
391
|
|
350
|
-
if variant_obj["category"] == "sv":
|
351
|
-
freqs = {
|
352
|
-
"gnomad_frequency": {
|
353
|
-
"display_name": "GnomAD",
|
354
|
-
"link": variant_obj.get("gnomad_sv_link"),
|
355
|
-
},
|
356
|
-
"clingen_cgh_benign": {
|
357
|
-
"display_name": "ClinGen CGH (benign)",
|
358
|
-
"link": None,
|
359
|
-
},
|
360
|
-
"clingen_cgh_pathogenic": {
|
361
|
-
"display_name": "ClinGen CGH (pathogenic)",
|
362
|
-
"link": None,
|
363
|
-
},
|
364
|
-
"clingen_ngi": {"display_name": "ClinGen NGI", "link": None},
|
365
|
-
"clingen_mip": {"display_name": "ClinGen MIP", "link": None},
|
366
|
-
"swegen": {"display_name": "SweGen", "link": None},
|
367
|
-
"decipher": {"display_name": "Decipher", "link": None},
|
368
|
-
"thousand_genomes_frequency": {"display_name": "1000G", "link": None},
|
369
|
-
"thousand_genomes_frequency_left": {
|
370
|
-
"display_name": "1000G(left)",
|
371
|
-
"link": None,
|
372
|
-
},
|
373
|
-
"thousand_genomes_frequency_right": {
|
374
|
-
"display_name": "1000G(right)",
|
375
|
-
"link": None,
|
376
|
-
},
|
377
|
-
}
|
378
|
-
elif variant_obj["category"] == "mei":
|
379
|
-
freqs = {
|
380
|
-
"swegen_alu": {
|
381
|
-
"display_name": "SweGen ALU",
|
382
|
-
"link": None,
|
383
|
-
},
|
384
|
-
"swegen_herv": {
|
385
|
-
"display_name": "SweGen HERV",
|
386
|
-
"link": None,
|
387
|
-
},
|
388
|
-
"swegen_l1": {
|
389
|
-
"display_name": "SweGen L1",
|
390
|
-
"link": None,
|
391
|
-
},
|
392
|
-
"swegen_sva": {
|
393
|
-
"display_name": "SweGen SVA",
|
394
|
-
"link": None,
|
395
|
-
},
|
396
|
-
"swegen_mei_max": {
|
397
|
-
"display_name": "SweGen MEI(max)",
|
398
|
-
"link": None,
|
399
|
-
},
|
400
|
-
}
|
401
|
-
else:
|
402
|
-
freqs = {
|
403
|
-
"gnomad_frequency": {
|
404
|
-
"display_name": "GnomAD",
|
405
|
-
"link": variant_obj.get("gnomad_link"),
|
406
|
-
},
|
407
|
-
"thousand_genomes_frequency": {
|
408
|
-
"display_name": "1000G",
|
409
|
-
"link": variant_obj.get("thousandg_link"),
|
410
|
-
},
|
411
|
-
"max_thousand_genomes_frequency": {
|
412
|
-
"display_name": "1000G(max)",
|
413
|
-
"link": variant_obj.get("thousandg_link"),
|
414
|
-
},
|
415
|
-
"exac_frequency": {
|
416
|
-
"display_name": "ExAC",
|
417
|
-
"link": variant_obj.get("exac_link"),
|
418
|
-
},
|
419
|
-
"max_exac_frequency": {
|
420
|
-
"display_name": "ExAC(max)",
|
421
|
-
"link": variant_obj.get("exac_link"),
|
422
|
-
},
|
423
|
-
"swegen": {
|
424
|
-
"display_name": "SweGen",
|
425
|
-
"link": variant_obj.get("swegen_link"),
|
426
|
-
},
|
427
|
-
"gnomad_mt_homoplasmic_frequency": {
|
428
|
-
"display_name": "GnomAD MT, homoplasmic",
|
429
|
-
"link": variant_obj.get("gnomad_link"),
|
430
|
-
},
|
431
|
-
"gnomad_mt_heteroplasmic_frequency": {
|
432
|
-
"display_name": "GnomAD MT, heteroplasmic",
|
433
|
-
"link": variant_obj.get("gnomad_link"),
|
434
|
-
},
|
435
|
-
}
|
436
392
|
frequency_list = []
|
437
|
-
for freq_key in freqs:
|
438
|
-
display_name = freqs[freq_key]["display_name"]
|
393
|
+
for freq_key, (display_name, link) in freqs.items():
|
439
394
|
value = variant_obj.get(freq_key)
|
440
|
-
|
441
|
-
# Always add gnomad for non-mitochondrial variants
|
395
|
+
|
442
396
|
if freq_key == "gnomad_frequency":
|
443
397
|
if is_mitochondrial_variant:
|
444
398
|
continue
|
445
|
-
|
446
|
-
if not value:
|
447
|
-
value = variant_obj.get("exac_frequency")
|
448
|
-
value = value or "NA"
|
399
|
+
value = value or variant_obj.get("exac_frequency") or "NA"
|
449
400
|
|
450
|
-
|
451
|
-
elif freq_key.startswith("gnomad_mt_") and is_mitochondrial_variant:
|
401
|
+
if freq_key.startswith("gnomad_mt_") and is_mitochondrial_variant:
|
452
402
|
value = value or "NA"
|
453
403
|
|
454
404
|
if value:
|
@@ -474,6 +424,7 @@ def frequency(variant_obj):
|
|
474
424
|
variant_obj.get("gnomad_frequency") or 0,
|
475
425
|
variant_obj.get("gnomad_mt_homoplasmic_frequency") or 0,
|
476
426
|
variant_obj.get("swegen_mei_max") or 0,
|
427
|
+
variant_obj.get("colorsdb_af") or 0,
|
477
428
|
)
|
478
429
|
|
479
430
|
if most_common_frequency > 0.05:
|
@@ -1496,9 +1496,6 @@ def populate_filters_form(store, institute_obj, case_obj, user_obj, category, re
|
|
1496
1496
|
Returns:
|
1497
1497
|
form: FiltersForm
|
1498
1498
|
"""
|
1499
|
-
form = None
|
1500
|
-
clinical_filter_panels = []
|
1501
|
-
|
1502
1499
|
default_panels = []
|
1503
1500
|
for panel in case_obj.get("panels", []):
|
1504
1501
|
if panel.get("is_default"):
|
@@ -1520,7 +1517,7 @@ def populate_filters_form(store, institute_obj, case_obj, user_obj, category, re
|
|
1520
1517
|
}
|
1521
1518
|
)
|
1522
1519
|
clinical_filter = MultiDict(clinical_filter_dict)
|
1523
|
-
elif category in ("sv", "cancer", "cancer_sv", "mei"):
|
1520
|
+
elif category in ("sv", "cancer", "cancer_sv", "mei", "outlier"):
|
1524
1521
|
clinical_filter_dict = FiltersFormClass.clinical_filter_base
|
1525
1522
|
clinical_filter_dict.update(
|
1526
1523
|
{
|
@@ -23,10 +23,12 @@ from scout.constants import (
|
|
23
23
|
CLINICAL_FILTER_BASE,
|
24
24
|
CLINICAL_FILTER_BASE_CANCER,
|
25
25
|
CLINICAL_FILTER_BASE_MEI,
|
26
|
+
CLINICAL_FILTER_BASE_OUTLIER,
|
26
27
|
CLINICAL_FILTER_BASE_SV,
|
27
28
|
CLINSIG_MAP,
|
28
29
|
FEATURE_TYPES,
|
29
30
|
GENETIC_MODELS,
|
31
|
+
OUTLIER_TYPES,
|
30
32
|
SO_TERMS,
|
31
33
|
SPIDEX_LEVELS,
|
32
34
|
SV_TYPES,
|
@@ -39,6 +41,7 @@ CLINSIG_OPTIONS = list(CLINSIG_MAP.items())
|
|
39
41
|
FUNC_ANNOTATIONS = [(term, term.replace("_", " ")) for term in SO_TERMS]
|
40
42
|
REGION_ANNOTATIONS = [(term, term.replace("_", " ")) for term in FEATURE_TYPES]
|
41
43
|
SV_TYPE_CHOICES = [(term, term.replace("_", " ").upper()) for term in SV_TYPES]
|
44
|
+
OUTLIER_TYPE_CHOICES = [(term, term.replace("_", " ").upper()) for term in OUTLIER_TYPES]
|
42
45
|
SPIDEX_CHOICES = [(term, term.replace("_", " ")) for term in SPIDEX_LEVELS]
|
43
46
|
FUSION_CALLER_CHOICES = [(term.get("id"), term.get("name")) for term in CALLERS.get("fusion")]
|
44
47
|
|
@@ -236,6 +239,44 @@ class FusionFiltersForm(VariantFiltersForm):
|
|
236
239
|
fusion_caller = SelectMultipleField("Fusion Caller", choices=FUSION_CALLER_CHOICES, default=[])
|
237
240
|
|
238
241
|
|
242
|
+
class OutlierFiltersForm(FlaskForm):
|
243
|
+
variant_type = HiddenField(default="clinical")
|
244
|
+
|
245
|
+
gene_panels = NonValidatingSelectMultipleField(choices=[])
|
246
|
+
gene_panels_exclude = BooleanField("Exclude genes")
|
247
|
+
hgnc_symbols = TagListField("HGNC Symbols/Ids (case sensitive)")
|
248
|
+
|
249
|
+
svtype = SelectMultipleField("Type", choices=OUTLIER_TYPE_CHOICES)
|
250
|
+
|
251
|
+
filters = NonValidatingSelectField(choices=[], validators=[validators.Optional()])
|
252
|
+
filter_display_name = StringField(default="")
|
253
|
+
save_filter = SubmitField(label="Save filter")
|
254
|
+
load_filter = SubmitField(label="Load filter")
|
255
|
+
lock_filter = SubmitField(label="Lock filter")
|
256
|
+
delete_filter = SubmitField(label="Delete filter")
|
257
|
+
audit_filter = SubmitField(label="Audit filter")
|
258
|
+
clinical_filter = SubmitField(label="Clinical filter")
|
259
|
+
|
260
|
+
chrom_pos = StringField(
|
261
|
+
"Chromosome position",
|
262
|
+
[validators.Optional()],
|
263
|
+
render_kw={"placeholder": "<chr>:<start pos>-<end pos>[optional +/-<span>]"},
|
264
|
+
)
|
265
|
+
|
266
|
+
chrom = NonValidatingSelectMultipleField("Chromosome", choices=[], default="")
|
267
|
+
start = IntegerField("Start position", [validators.Optional()])
|
268
|
+
end = IntegerField("End position", [validators.Optional()])
|
269
|
+
cytoband_start = NonValidatingSelectField("Cytoband start", choices=[])
|
270
|
+
cytoband_end = NonValidatingSelectField("Cytoband end", choices=[])
|
271
|
+
|
272
|
+
filter_variants = SubmitField(label="Filter variants")
|
273
|
+
export = SubmitField(label="Filter and export")
|
274
|
+
|
275
|
+
clinical_filter_base = CLINICAL_FILTER_BASE_OUTLIER
|
276
|
+
|
277
|
+
show_unaffected = BooleanField("Show also variants present only in unaffected", default=False)
|
278
|
+
|
279
|
+
|
239
280
|
FILTERSFORMCLASS = {
|
240
281
|
"snv": FiltersForm,
|
241
282
|
"str": StrFiltersForm,
|
@@ -244,4 +285,5 @@ FILTERSFORMCLASS = {
|
|
244
285
|
"cancer": CancerFiltersForm,
|
245
286
|
"mei": MeiFiltersForm,
|
246
287
|
"fusion": FusionFiltersForm,
|
288
|
+
"outlier": OutlierFiltersForm,
|
247
289
|
}
|
@@ -30,13 +30,17 @@
|
|
30
30
|
|
31
31
|
var the_form = document.forms['filters_form'];
|
32
32
|
|
33
|
-
document.getElementById('hide_dismissed')
|
33
|
+
var hide_dismissed = document.getElementById('hide_dismissed');
|
34
|
+
if (hide_dismissed) {
|
35
|
+
hide_dismissed.onchange = function() {
|
34
36
|
the_form.submit();
|
35
|
-
}
|
37
|
+
}}
|
36
38
|
|
37
|
-
document.getElementById('show_unaffected')
|
39
|
+
var show_unaffected =document.getElementById('show_unaffected');
|
40
|
+
if (show_unaffected) {
|
41
|
+
show_unaffected.onchange = function() {
|
38
42
|
the_form.submit();
|
39
|
-
}
|
43
|
+
}}
|
40
44
|
|
41
45
|
function resetPage(){
|
42
46
|
document.getElementById('page').value = "1";
|
@@ -137,7 +137,9 @@ def variants(institute_id, case_name):
|
|
137
137
|
variants_query = store.variants(
|
138
138
|
case_obj["_id"], query=form.data, category=category, build=genome_build
|
139
139
|
)
|
140
|
-
result_size = store.count_variants(
|
140
|
+
result_size = store.count_variants(
|
141
|
+
case_obj["_id"], form.data, None, category, build=genome_build
|
142
|
+
)
|
141
143
|
|
142
144
|
if request.form.get("export"):
|
143
145
|
return controllers.download_variants(store, case_obj, variants_query)
|
@@ -236,7 +238,7 @@ def str_variants(institute_id, case_name):
|
|
236
238
|
]
|
237
239
|
)
|
238
240
|
|
239
|
-
result_size = store.count_variants(case_obj["_id"], query, None, category)
|
241
|
+
result_size = store.count_variants(case_obj["_id"], query, None, category, build=genome_build)
|
240
242
|
|
241
243
|
if request.form.get("export"):
|
242
244
|
return controllers.download_str_variants(case_obj, variants_query)
|
@@ -312,7 +314,9 @@ def sv_variants(institute_id, case_name):
|
|
312
314
|
case_obj["_id"], category=category, query=form.data, build=genome_build
|
313
315
|
)
|
314
316
|
|
315
|
-
result_size = store.count_variants(
|
317
|
+
result_size = store.count_variants(
|
318
|
+
case_obj["_id"], form.data, None, category, build=genome_build
|
319
|
+
)
|
316
320
|
|
317
321
|
# if variants should be exported
|
318
322
|
if request.form.get("export"):
|
@@ -406,7 +410,9 @@ def mei_variants(institute_id, case_name):
|
|
406
410
|
case_obj["_id"], category=category, query=form.data, build=genome_build
|
407
411
|
)
|
408
412
|
|
409
|
-
result_size = store.count_variants(
|
413
|
+
result_size = store.count_variants(
|
414
|
+
case_obj["_id"], form.data, None, category, build=genome_build
|
415
|
+
)
|
410
416
|
|
411
417
|
# if variants should be exported
|
412
418
|
if request.form.get("export"):
|
@@ -515,7 +521,9 @@ def cancer_variants(institute_id, case_name):
|
|
515
521
|
variants_query = store.variants(
|
516
522
|
case_obj["_id"], category="cancer", query=form.data, build=genome_build
|
517
523
|
)
|
518
|
-
result_size = store.count_variants(
|
524
|
+
result_size = store.count_variants(
|
525
|
+
case_obj["_id"], form.data, None, category, build=genome_build
|
526
|
+
)
|
519
527
|
|
520
528
|
if request.form.get("export"):
|
521
529
|
return controllers.download_variants(store, case_obj, variants_query)
|
@@ -596,7 +604,9 @@ def cancer_sv_variants(institute_id, case_name):
|
|
596
604
|
case_obj["_id"], category=category, query=form.data, build=genome_build
|
597
605
|
)
|
598
606
|
|
599
|
-
result_size = store.count_variants(
|
607
|
+
result_size = store.count_variants(
|
608
|
+
case_obj["_id"], form.data, None, category, build=genome_build
|
609
|
+
)
|
600
610
|
|
601
611
|
# if variants should be exported
|
602
612
|
if request.form.get("export"):
|
@@ -681,7 +691,9 @@ def fusion_variants(institute_id, case_name):
|
|
681
691
|
case_obj["_id"], category=category, query=form.data, build=genome_build
|
682
692
|
)
|
683
693
|
|
684
|
-
result_size = store.count_variants(
|
694
|
+
result_size = store.count_variants(
|
695
|
+
case_obj["_id"], form.data, None, category, build=genome_build
|
696
|
+
)
|
685
697
|
|
686
698
|
# if variants should be exported
|
687
699
|
if request.form.get("export"):
|
@@ -765,3 +777,12 @@ def toggle_show_dismiss_block():
|
|
765
777
|
"""Endpoint to toggle the show dismiss block session variable."""
|
766
778
|
session["show_dismiss_block"] = not session.get("show_dismiss_block")
|
767
779
|
return f"Toggled to {session['show_dismiss_block']}"
|
780
|
+
|
781
|
+
|
782
|
+
@variants_bp.route("/variants/un-audit_filter", methods=["GET"])
|
783
|
+
def unaudit_filter():
|
784
|
+
"""Un-audit an audited filter."""
|
785
|
+
store.unaudit_filter(
|
786
|
+
audit_id=request.args.get("audit_id"), user_obj=store.user(current_user.email)
|
787
|
+
)
|
788
|
+
return redirect(request.referrer)
|
scout/server/config.py
CHANGED
@@ -64,6 +64,10 @@ ACCREDITATION_BADGE = "swedac-1926-iso17025.png"
|
|
64
64
|
# BEACON_URL = "http://localhost:6000/apiv1.0"
|
65
65
|
# BEACON_TOKEN = "DEMO"
|
66
66
|
|
67
|
+
# ClinVar API URL
|
68
|
+
# An alternative URL that will be used to send ClinVar submissions to. Just uncomment the line below to use the test API
|
69
|
+
# CLINVAR_API_URL = "https://submit.ncbi.nlm.nih.gov/apitest/v1/submissions/"
|
70
|
+
|
67
71
|
# connection details for LoqusDB MongoDB database
|
68
72
|
# Example with 2 instances of LoqusDB, one using a binary file and one instance connected via REST API
|
69
73
|
# When multiple instances are available, admin users can modify which one is in use for a given institute from the admin settings page
|
@@ -4,7 +4,7 @@ import logging
|
|
4
4
|
import requests
|
5
5
|
from flask import flash
|
6
6
|
|
7
|
-
from scout.constants.clinvar import
|
7
|
+
from scout.constants.clinvar import CLINVAR_API_URL_DEFAULT, PRECLINVAR_URL
|
8
8
|
|
9
9
|
LOG = logging.getLogger(__name__)
|
10
10
|
|
@@ -15,9 +15,9 @@ class ClinVarApi:
|
|
15
15
|
the ClinVar submission schema (https://www.ncbi.nlm.nih.gov/clinvar/docs/api_http/) and if valid, can be directly submitted to ClinVar.
|
16
16
|
"""
|
17
17
|
|
18
|
-
def
|
18
|
+
def init_app(self, app):
|
19
19
|
self.convert_service = "/".join([PRECLINVAR_URL, "csv_2_json"])
|
20
|
-
self.
|
20
|
+
self.submit_service_url = app.config.get("CLINVAR_API_URL") or CLINVAR_API_URL_DEFAULT
|
21
21
|
|
22
22
|
def set_header(self, api_key) -> dict:
|
23
23
|
"""Creates a header to be submitted a in a POST rquest to the CLinVar API
|
@@ -71,16 +71,16 @@ class ClinVarApi:
|
|
71
71
|
"actions": [{"type": "AddData", "targetDb": "clinvar", "data": {"content": json_data}}]
|
72
72
|
}
|
73
73
|
try:
|
74
|
-
resp = requests.post(self.
|
75
|
-
return resp.status_code, resp
|
74
|
+
resp = requests.post(self.submit_service_url, data=json.dumps(data), headers=header)
|
75
|
+
return self.submit_service_url, resp.status_code, resp
|
76
76
|
|
77
77
|
except Exception as ex:
|
78
|
-
return None, ex
|
78
|
+
return self.submit_service_url, None, ex
|
79
79
|
|
80
80
|
def show_submission_status(self, submission_id: str, api_key=None):
|
81
81
|
"""Retrieve the status of a ClinVar submission using the https://submit.ncbi.nlm.nih.gov/api/v1/submissions/SUBnnnnnn/actions/ endpoint."""
|
82
82
|
|
83
83
|
header: dict = self.set_header(api_key)
|
84
|
-
actions_url = f"{
|
84
|
+
actions_url = f"{self.submit_service_url}{submission_id}/actions/"
|
85
85
|
actions_resp: requests.models.Response = requests.get(actions_url, headers=header)
|
86
86
|
flash(f"Response from ClinVar: {actions_resp.json()}", "primary")
|
scout/server/links.py
CHANGED
@@ -563,9 +563,9 @@ def decipher_link(variant_obj, build=37):
|
|
563
563
|
def exac_link(variant_obj):
|
564
564
|
"""Compose link to ExAC website for a variant position."""
|
565
565
|
url_template = (
|
566
|
-
"https://
|
566
|
+
"https://gnomad.broadinstitute.org/variant/"
|
567
567
|
"{this[chromosome]}-{this[position]}-{this[reference]}"
|
568
|
-
"-{this[alternative]}"
|
568
|
+
"-{this[alternative]}?dataset=exac"
|
569
569
|
)
|
570
570
|
return url_template.format(this=variant_obj)
|
571
571
|
|
@@ -10,16 +10,13 @@
|
|
10
10
|
|
11
11
|
{% block css %}
|
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
|
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/
|
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
|
{% endblock %}
|
16
16
|
|
17
17
|
{% block css_style %}
|
18
18
|
{% endblock %}
|
19
19
|
|
20
|
-
<!-- Adding support for Font Awesome icons version 6 -->
|
21
|
-
<script src="https://kit.fontawesome.com/bff7dad824.js" integrity="sha512-+ohxkrmvsgaa299uNunuNiobFRMBGoAVR3t/fpqBmZdObzKnfBMKVyIqxrXtHMZDrwQS73ZuOVj8hUqxoJt+Ww==" crossorigin="anonymous"></script>
|
22
|
-
|
23
20
|
<style>
|
24
21
|
|
25
22
|
.spinner {
|
@@ -12,7 +12,7 @@
|
|
12
12
|
<td>
|
13
13
|
<small>
|
14
14
|
<strong> {{ comment.user_name }} </strong>
|
15
|
-
on {{ comment.created_at.
|
15
|
+
on {{ comment.created_at.strftime('%y-%m-%d %H:%M') }}
|
16
16
|
{% if comment.level == 'global' %}
|
17
17
|
<span class='badge bg-info text-white'>GLOBAL</span>
|
18
18
|
{% endif %}
|
@@ -134,7 +134,7 @@
|
|
134
134
|
<form method="POST" action="{{ url_for('cases.events', institute_id=institute._id, case_name=case.display_name, event_id=comment._id,_anchor='comments') }}">
|
135
135
|
<small>
|
136
136
|
<strong>{{ comment.user_name }}</strong>
|
137
|
-
on {{ comment.created_at.
|
137
|
+
on {{ comment.created_at.strftime('%y-%m-%d %H:%M') }}
|
138
138
|
{% if comment.level == 'global' %}
|
139
139
|
<span class="badge bg-info">GLOBAL</span>
|
140
140
|
{% endif %}
|
@@ -145,7 +145,7 @@
|
|
145
145
|
<span class='badge bg-secondary'>edited</span>
|
146
146
|
{% endif %}
|
147
147
|
{% if comment.user_id == current_user.email %}
|
148
|
-
<button class="btn btn-link btn-sm" type="submit" name="remove"><i class="fa fa-
|
148
|
+
<button class="btn btn-link btn-sm" type="submit" name="remove"><i class="fa fa-times"></i></button>
|
149
149
|
<button class="btn btn-link btn-sm" type="button" data-bs-toggle="modal" data-bs-target="#editComment_{{index}}"><i class="fa fa-edit"></i></button>
|
150
150
|
{% endif %}
|
151
151
|
</small>
|
@@ -208,7 +208,7 @@
|
|
208
208
|
({{ event.hpo_term }})
|
209
209
|
{%- endif %}
|
210
210
|
{%-if event.individuals %}, individuals: {{event.individuals|join(', ')}}{% endif %}
|
211
|
-
at <span class="timestamp">{{ event.created_at.
|
211
|
+
at <span class="timestamp">{{ event.created_at.strftime('%y-%m-%d %H:%M') }}</span>
|
212
212
|
</li>
|
213
213
|
{% else %}
|
214
214
|
<li class="list-group-item">No activity yet</li>
|
scout/server/utils.py
CHANGED
@@ -269,7 +269,8 @@ def case_has_mt_alignments(case_obj: dict):
|
|
269
269
|
|
270
270
|
|
271
271
|
def case_has_rna_tracks(case_obj: Dict) -> bool:
|
272
|
-
"""Returns True if one
|
272
|
+
"""Returns True if one or more individuals of the case contain RNA-seq data
|
273
|
+
Add this info to the case obj dict.
|
273
274
|
|
274
275
|
Args:
|
275
276
|
case_obj(dict)
|
@@ -277,10 +278,12 @@ def case_has_rna_tracks(case_obj: Dict) -> bool:
|
|
277
278
|
True or False (bool)
|
278
279
|
"""
|
279
280
|
# Display junctions track if available for any of the individuals
|
281
|
+
case_obj["has_rna_tracks"] = False
|
280
282
|
for ind in case_obj.get("individuals", []):
|
281
283
|
# RNA can have three different aln track files
|
282
284
|
for path_name in ["splice_junctions_bed", "rna_coverage_bigwig", "rna_alignment_path"]:
|
283
285
|
if _check_path_name(ind, path_name):
|
286
|
+
case_obj["has_rna_tracks"] = True
|
284
287
|
return True
|
285
288
|
return False
|
286
289
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: scout-browser
|
3
|
-
Version: 4.
|
3
|
+
Version: 4.86
|
4
4
|
Summary: Clinical DNA variant visualizer and browser.
|
5
5
|
Home-page: https://github.com/Clinical-Genomics/scout
|
6
6
|
Author: Måns Magnusson
|
@@ -15,8 +15,8 @@ Classifier: Topic :: Software Development :: Libraries
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.6
|
16
16
|
Description-Content-Type: text/markdown
|
17
17
|
License-File: LICENSE
|
18
|
-
Requires-Dist: werkzeug
|
19
|
-
Requires-Dist: Flask
|
18
|
+
Requires-Dist: werkzeug
|
19
|
+
Requires-Dist: Flask>=2.0
|
20
20
|
Requires-Dist: Flask-Bootstrap
|
21
21
|
Requires-Dist: Flask-CORS
|
22
22
|
Requires-Dist: path.py
|
@@ -26,9 +26,9 @@ Requires-Dist: Flask-WTF
|
|
26
26
|
Requires-Dist: Flask-Mail
|
27
27
|
Requires-Dist: coloredlogs
|
28
28
|
Requires-Dist: query-phenomizer
|
29
|
-
Requires-Dist: Flask-Babel
|
30
|
-
Requires-Dist: livereload
|
31
|
-
Requires-Dist: tornado
|
29
|
+
Requires-Dist: Flask-Babel>=3
|
30
|
+
Requires-Dist: livereload>=2.7
|
31
|
+
Requires-Dist: tornado>=6.4.1
|
32
32
|
Requires-Dist: python-dateutil
|
33
33
|
Requires-Dist: pymongo
|
34
34
|
Requires-Dist: pathlib
|
@@ -47,14 +47,14 @@ Requires-Dist: flask-ldapconn
|
|
47
47
|
Requires-Dist: cyvcf2
|
48
48
|
Requires-Dist: configobj
|
49
49
|
Requires-Dist: ped-parser
|
50
|
-
Requires-Dist: pydantic
|
51
|
-
Requires-Dist: PyYaml
|
52
|
-
Requires-Dist: intervaltree
|
50
|
+
Requires-Dist: pydantic>=2
|
51
|
+
Requires-Dist: PyYaml>=5.1
|
52
|
+
Requires-Dist: intervaltree==3.0.2
|
53
53
|
Requires-Dist: anytree
|
54
54
|
Requires-Dist: tabulate
|
55
55
|
Provides-Extra: coverage
|
56
|
-
Requires-Dist: chanjo-report
|
57
|
-
Requires-Dist: pymysql
|
56
|
+
Requires-Dist: chanjo-report; extra == "coverage"
|
57
|
+
Requires-Dist: pymysql; extra == "coverage"
|
58
58
|
|
59
59
|
|
60
60
|
<p align="center">
|