scout-browser 4.99.0__py3-none-any.whl → 4.100.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 +30 -15
- scout/adapter/mongo/clinvar.py +23 -31
- scout/adapter/mongo/event.py +14 -4
- scout/adapter/mongo/omics_variant.py +14 -1
- scout/adapter/mongo/query.py +24 -1
- scout/adapter/mongo/variant.py +37 -19
- scout/adapter/mongo/variant_loader.py +159 -176
- scout/build/individual.py +3 -1
- scout/commands/download/ensembl.py +1 -2
- scout/commands/load/research.py +2 -3
- scout/commands/update/individual.py +1 -0
- scout/constants/__init__.py +7 -2
- scout/constants/igv_tracks.py +4 -3
- scout/constants/indexes.py +5 -4
- scout/constants/query_terms.py +1 -0
- scout/models/case/case.py +1 -0
- scout/models/case/case_loading_models.py +3 -1
- scout/parse/ensembl.py +8 -3
- scout/server/app.py +6 -0
- scout/server/blueprints/alignviewers/templates/alignviewers/igv_viewer.html +10 -0
- scout/server/blueprints/cases/controllers.py +9 -3
- scout/server/blueprints/cases/templates/cases/case_report.html +25 -13
- scout/server/blueprints/cases/templates/cases/chanjo2_form.html +1 -1
- scout/server/blueprints/cases/templates/cases/collapsible_actionbar.html +1 -1
- scout/server/blueprints/cases/templates/cases/gene_panel.html +1 -1
- scout/server/blueprints/cases/templates/cases/utils.html +19 -0
- scout/server/blueprints/clinvar/controllers.py +5 -1
- scout/server/blueprints/clinvar/templates/clinvar/clinvar_submissions.html +34 -12
- scout/server/blueprints/clinvar/templates/clinvar/multistep_add_variant.html +1 -1
- scout/server/blueprints/diagnoses/static/diagnoses.js +8 -1
- scout/server/blueprints/institutes/static/variants_list_scripts.js +9 -1
- scout/server/blueprints/institutes/templates/overview/institute_sidebar.html +9 -1
- scout/server/blueprints/mme/__init__.py +1 -0
- scout/server/blueprints/mme/controllers.py +18 -0
- scout/server/blueprints/mme/templates/mme/mme_submissions.html +153 -0
- scout/server/blueprints/mme/views.py +34 -0
- scout/server/blueprints/panels/templates/panels/panel.html +19 -6
- scout/server/blueprints/phenotypes/templates/phenotypes/hpo_terms.html +8 -1
- scout/server/blueprints/variant/controllers.py +19 -10
- scout/server/blueprints/variant/templates/variant/acmg.html +9 -0
- scout/server/blueprints/variant/templates/variant/cancer-variant.html +1 -1
- scout/server/blueprints/variant/templates/variant/components.html +19 -16
- scout/server/blueprints/variant/templates/variant/sv-variant.html +2 -2
- scout/server/blueprints/variant/templates/variant/utils.html +20 -8
- scout/server/blueprints/variant/templates/variant/variant.html +42 -1
- scout/server/blueprints/variant/views.py +12 -0
- scout/server/blueprints/variants/controllers.py +17 -9
- scout/server/blueprints/variants/forms.py +8 -3
- scout/server/blueprints/variants/templates/variants/components.html +8 -2
- scout/server/blueprints/variants/templates/variants/indicators.html +11 -13
- scout/server/blueprints/variants/templates/variants/utils.html +28 -23
- scout/server/extensions/bionano_extension.py +0 -1
- scout/server/extensions/chanjo2_extension.py +54 -13
- scout/server/links.py +15 -0
- scout/server/static/bs_styles.css +34 -6
- scout/server/templates/utils.html +9 -10
- scout/server/utils.py +18 -0
- scout/utils/ensembl_biomart_clients.py +1 -0
- scout/utils/scout_requests.py +1 -3
- {scout_browser-4.99.0.dist-info → scout_browser-4.100.0.dist-info}/METADATA +1 -1
- {scout_browser-4.99.0.dist-info → scout_browser-4.100.0.dist-info}/RECORD +64 -60
- {scout_browser-4.99.0.dist-info → scout_browser-4.100.0.dist-info}/WHEEL +0 -0
- {scout_browser-4.99.0.dist-info → scout_browser-4.100.0.dist-info}/entry_points.txt +0 -0
- {scout_browser-4.99.0.dist-info → scout_browser-4.100.0.dist-info}/licenses/LICENSE +0 -0
@@ -10,12 +10,25 @@
|
|
10
10
|
<li class="nav-item">
|
11
11
|
<a class="nav-link" href="{{ url_for('cases.index') }}">Institutes</a>
|
12
12
|
</li>
|
13
|
-
|
14
|
-
<
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
{% if case %}
|
14
|
+
<li class="nav-item">
|
15
|
+
<a class="nav-link" href="{{ url_for('overview.cases', institute_id=institute._id) }}">
|
16
|
+
{{ institute.display_name }}
|
17
|
+
</a>
|
18
|
+
</li>
|
19
|
+
<li class="nav-item d-flex align-items-center">
|
20
|
+
<a class="nav-link" href="{{ url_for('cases.case', institute_id=institute._id, case_name=case.display_name) }}">
|
21
|
+
{{ case.display_name }}
|
22
|
+
</a>
|
23
|
+
</li>
|
24
|
+
{% else %}
|
25
|
+
<li class="nav-item">
|
26
|
+
<a class="nav-link" href="{{ url_for('panels.panels') }}">Gene Panels</a>
|
27
|
+
</li>
|
28
|
+
{% endif %}
|
29
|
+
<li class="nav-item active d-flex align-items-center">
|
30
|
+
<span class="navbar-text">{{ panel.display_name }} {{ panel.version }}</span>
|
31
|
+
</li>
|
19
32
|
{% endblock %}
|
20
33
|
|
21
34
|
{% block content_main %}
|
@@ -367,11 +367,13 @@ def variant(
|
|
367
367
|
if variant_id in case_clinvars:
|
368
368
|
variant_obj["clinvar_clinsig"] = case_clinvars.get(variant_id)["clinsig"]
|
369
369
|
|
370
|
-
|
370
|
+
overlapping_variants, overlapping_outliers = [], []
|
371
371
|
if get_overlapping:
|
372
|
-
|
372
|
+
overlapping_variants, overlapping_outliers = map(list, store.hgnc_overlapping(variant_obj))
|
373
|
+
|
374
|
+
for var in overlapping_variants:
|
373
375
|
var.update(predictions(var.get("genes", [])))
|
374
|
-
|
376
|
+
|
375
377
|
variant_obj["end_chrom"] = variant_obj.get("end_chrom", variant_obj["chromosome"])
|
376
378
|
|
377
379
|
dismiss_options = DISMISS_VARIANT_OPTIONS
|
@@ -395,7 +397,8 @@ def variant(
|
|
395
397
|
"causatives": other_causatives,
|
396
398
|
"managed_variant": managed_variant,
|
397
399
|
"events": events,
|
398
|
-
"overlapping_vars":
|
400
|
+
"overlapping_vars": overlapping_variants,
|
401
|
+
"overlapping_outliers": overlapping_outliers,
|
399
402
|
"manual_rank_options": MANUAL_RANK_OPTIONS,
|
400
403
|
"cancer_tier_options": CANCER_TIER_OPTIONS,
|
401
404
|
"dismiss_variant_options": dismiss_options,
|
@@ -406,9 +409,6 @@ def variant(
|
|
406
409
|
"inherit_palette": INHERITANCE_PALETTE,
|
407
410
|
"igv_tracks": get_igv_tracks("38" if variant_obj["is_mitochondrial"] else genome_build),
|
408
411
|
"has_rna_tracks": case_has_rna_tracks(case_obj),
|
409
|
-
"gene_has_full_coverage": get_gene_has_full_coverage(
|
410
|
-
institute_obj, case_obj, variant_obj, genome_build
|
411
|
-
),
|
412
412
|
"gens_info": gens.connection_settings(genome_build),
|
413
413
|
"evaluations": evaluations,
|
414
414
|
"ccv_evaluations": ccv_evaluations,
|
@@ -416,16 +416,19 @@ def variant(
|
|
416
416
|
}
|
417
417
|
|
418
418
|
|
419
|
-
def get_gene_has_full_coverage(
|
420
|
-
institute_obj, case_obj, variant_obj, genome_build
|
421
|
-
) -> Dict[int, bool]:
|
419
|
+
def get_gene_has_full_coverage(institute_obj, case_obj, variant_obj) -> Dict[int, bool]:
|
422
420
|
"""
|
423
421
|
Query chanjo2, if configured and d4 files are available for this case,
|
424
422
|
for coverage completeness on the genes touching this variant.
|
425
423
|
"""
|
424
|
+
case_has_chanjo2_coverage(case_obj)
|
426
425
|
if not case_obj.get("chanjo2_coverage"):
|
427
426
|
return {}
|
428
427
|
|
428
|
+
genome_build = str(case_obj.get("genome_build", "37"))
|
429
|
+
if genome_build not in ["37", "38"]:
|
430
|
+
genome_build = "37"
|
431
|
+
|
429
432
|
gene_has_full_coverage: dict = {
|
430
433
|
hgnc_id: chanjo2.get_gene_complete_coverage(
|
431
434
|
hgnc_id=hgnc_id,
|
@@ -653,6 +656,12 @@ def variant_acmg(store: MongoAdapter, institute_id: str, case_name: str, variant
|
|
653
656
|
store, variant_obj, institute_id, case_name
|
654
657
|
)
|
655
658
|
|
659
|
+
genome_build = str(case_obj.get("genome_build", "37"))
|
660
|
+
if genome_build not in ["37", "38"]:
|
661
|
+
genome_build = "37"
|
662
|
+
|
663
|
+
add_gene_info(store, variant_obj, genome_build=genome_build)
|
664
|
+
|
656
665
|
return dict(
|
657
666
|
institute=institute_obj,
|
658
667
|
case=case_obj,
|
@@ -105,6 +105,15 @@
|
|
105
105
|
</div>
|
106
106
|
{% endfor %}
|
107
107
|
</div>
|
108
|
+
<!-- external links -->
|
109
|
+
<div class="card panel-default mt-3">
|
110
|
+
<div class="card-body">
|
111
|
+
Search ClinGen Criteria Specifications (CSPEC):
|
112
|
+
{% for gene in variant.genes %}
|
113
|
+
<a href="{{ gene.cspec_link }}" class="btn btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank">{{ gene.common.hgnc_symbol if gene.common else gene.hgnc_id }}</a>
|
114
|
+
{% endfor %}
|
115
|
+
</div>
|
116
|
+
</div>
|
108
117
|
<!-- classification preview in the footer-->
|
109
118
|
<div class="mt-3 fixed-bottom bg-light border">
|
110
119
|
<div class="row">
|
@@ -104,7 +104,7 @@
|
|
104
104
|
</div>
|
105
105
|
|
106
106
|
<div class="row">
|
107
|
-
<div class="col-12">{{ overlapping_panel(variant, overlapping_vars, case, institute) }}</div>
|
107
|
+
<div class="col-12">{{ overlapping_panel(variant, overlapping_vars, overlapping_outliers, case, institute) }}</div>
|
108
108
|
{% if rank_score_results %}
|
109
109
|
<div class="col-12">{{ rankscore_panel(rank_score_results) }}</div>
|
110
110
|
{% endif %}
|
@@ -132,27 +132,31 @@
|
|
132
132
|
</div>
|
133
133
|
{% endif %}
|
134
134
|
{% for gene in variant.genes %}
|
135
|
-
<div class="
|
135
|
+
<div class="ms-1">
|
136
136
|
{% if gene.alamut_link %}
|
137
137
|
<a href="{{ gene.alamut_link }}" class="btn btn-sm btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank" data-bs-toggle="tooltip" title="Alamut Visual (Plus) - Open variant - with gene transcript c. coordinate">Alamut {{ gene.common.hgnc_symbol if gene.common else gene.hgnc_id }} c.</a>
|
138
138
|
{% endif %}
|
139
139
|
</div>
|
140
140
|
{% endfor %}
|
141
|
-
{{ gene_coverage(institute, variant, case, config) }}
|
142
141
|
</li>
|
143
142
|
<li class="list-group-item">
|
144
143
|
<div>
|
145
144
|
{{ igv_track_selection(igv_tracks, current_user) }}
|
146
145
|
</div>
|
147
146
|
</li>
|
147
|
+
{% if (case.chanjo_coverage and config.chanjo_report) or case.chanjo2_coverage %}
|
148
|
+
<li class="list-group-item d-flex justify-content-between">
|
149
|
+
{{ gene_coverage(institute, variant, case, config) }}
|
150
|
+
</li>
|
151
|
+
{% endif %}
|
148
152
|
</ul>
|
149
153
|
{% endmacro %}
|
150
154
|
|
151
155
|
{% macro gene_coverage(institute, variant, case, config) %}
|
152
156
|
{% if case.chanjo_coverage and config.chanjo_report %}
|
153
|
-
<div class="d-flex flex-wrap ms-1">
|
157
|
+
<div class="d-flex flex-wrap ms-1" data-bs-toggle="tooltip" title="Chanjo coverage reports">
|
154
158
|
{% for gene in variant.genes %}
|
155
|
-
<a class="btn btn-sm btn-secondary text-white" rel="noopener noreferrer" target="_blank" href="{{ url_for('report.gene', gene_id=gene.hgnc_id, sample_id=variant.samples|map(attribute='sample_id')|list) }}"
|
159
|
+
<a class="btn btn-sm btn-secondary text-white" rel="noopener noreferrer" target="_blank" href="{{ url_for('report.gene', gene_id=gene.hgnc_id, sample_id=variant.samples|map(attribute='sample_id')|list) }}">
|
156
160
|
Gene coverage: {{ gene.common.hgnc_symbol if gene.common else gene.hgnc_id }}
|
157
161
|
</a>
|
158
162
|
{% endfor %}
|
@@ -160,14 +164,12 @@
|
|
160
164
|
{% endif %}
|
161
165
|
{% if case.chanjo2_coverage %}
|
162
166
|
<div class="d-flex flex-wrap ms-1" data-bs-toggle="tooltip" title="Chanjo2 coverage reports">
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
<span class="
|
167
|
-
|
168
|
-
|
169
|
-
{% endif %}
|
170
|
-
{% endfor %}
|
167
|
+
{% for gene in variant.genes %}
|
168
|
+
<div class="btn-group" style="display:flex">
|
169
|
+
{{ chanjo2_report_form(institute, case, gene.hgnc_symbol if gene.hgnc_symbol else gene.hgnc_id, 'overview', gene.hgnc_id, "Gene coverage " ~ (gene.hgnc_symbol if gene.hgnc_symbol else gene.hgnc_id), "btn btn-sm btn-secondary text-white") }} <!--chanjo2 genes overview -->
|
170
|
+
<span class="btn complete-coverage-indicator align-items-center btn-info text-white btn-sm" style="display:flex" id="coverage-indicator-{{gene.hgnc_id}}-button" data-bs-toggle="tooltip" data-bs-placement="bottom" data-loading-text="Checking completeness..." title="Checking completeness..."><span style="display:flex" id="coverage-indicator-{{gene.hgnc_id}}-icon" class='align-self-center blink_me fa-solid fa-circle-question'></span><span style="display:flex" id="coverage-indicator-{{gene.hgnc_id}}-text" class='align-self-center'>Checking</span></span>
|
171
|
+
</div>
|
172
|
+
{% endfor %}
|
171
173
|
</div>
|
172
174
|
{% endif %}
|
173
175
|
{% endmacro %}
|
@@ -338,8 +340,8 @@
|
|
338
340
|
<div class="card-body mt-1 ms-3 mb-1" style="padding: 0;">
|
339
341
|
Matching manually ranked variants:
|
340
342
|
{% for manual_rank, manual_rank_info in matching_manual_ranked.items() %}
|
341
|
-
<a style="padding: 0;" class="btn btn-{{manual_rank_info.label_class}} btn-small" data-bs-toggle="collapse" href="#collapse_mr{{manual_rank}}" role="button" aria-expanded="false" aria-controls="
|
342
|
-
{{manual_rank_info.label}} ({{manual_rank_info.links|length}}x)
|
343
|
+
<a style="padding: 0;" class="btn btn-{{manual_rank_info.label_class}} btn-small" data-bs-toggle="collapse" href="#collapse_mr{{manual_rank}}" role="button" aria-expanded="false" aria-controls="#collapse_mr{{manual_rank}}">
|
344
|
+
<span class="collapse-button-icon me-1"></span>{{manual_rank_info.label}} ({{manual_rank_info.links|length}}x)
|
343
345
|
</a>
|
344
346
|
<div class="collapse" id="collapse_mr{{manual_rank}}">
|
345
347
|
<div>
|
@@ -360,8 +362,8 @@
|
|
360
362
|
<div class="card-body mt-1 ms-3 mb-1" style="padding: 0;">
|
361
363
|
Matching tiered:
|
362
364
|
{% for tier, tiered_info in matching_tiered.items() %}
|
363
|
-
<a style="padding: 0;" class="btn btn-{{tiered_info.
|
364
|
-
{{tier}} ({{tiered_info.links|length}}x)
|
365
|
+
<a style="padding: 0;" class="btn btn-{{tiered_info.label_class}} btn-xs" data-bs-toggle="collapse" href="#collapse_{{tier}}" aria-expanded="false" aria-controls="collapse_{{tier}}">
|
366
|
+
<span class="collapse-button-icon me-1"></span>{{tier}} ({{tiered_info.links|length}}x)
|
365
367
|
</a>
|
366
368
|
<div class="collapse" id="collapse_{{tier}}">
|
367
369
|
<div>
|
@@ -431,6 +433,7 @@
|
|
431
433
|
<a href="{{ gene.oncokb_link }}" class="btn btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank">OncoKB</a>
|
432
434
|
<a href="{{ gene.civic_link }}" class="btn btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank">CIViC</a>
|
433
435
|
<a href="{{ gene.ckb_link }}" class="btn btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank">CKB</a>
|
436
|
+
<a href="{{ gene.cancer_hotspots_link }}" class="btn btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank">Cancer Hotspots</a>
|
434
437
|
{% endif %}
|
435
438
|
{% if str %}
|
436
439
|
<a href="{{ gene.stripy_link }}" class="btn btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank">STRipy</a>
|
@@ -74,7 +74,7 @@
|
|
74
74
|
{% if variant.category == "cancer_sv" %}
|
75
75
|
{{matching_variants(managed_variant, causatives, variant.matching_tiered) }}
|
76
76
|
{% else %}
|
77
|
-
{{matching_variants(managed_variant, causatives) }}
|
77
|
+
{{matching_variants(managed_variant, causatives, variant.matching_ranked) }}
|
78
78
|
{% endif %}
|
79
79
|
</div>
|
80
80
|
</div>
|
@@ -122,7 +122,7 @@
|
|
122
122
|
</div>
|
123
123
|
|
124
124
|
<div class="row">
|
125
|
-
<div class="col-12">{{ overlapping_panel(variant, overlapping_vars, case, institute) }}</div>
|
125
|
+
<div class="col-12">{{ overlapping_panel(variant, overlapping_vars, overlapping_outliers, case, institute) }}</div>
|
126
126
|
</div>
|
127
127
|
|
128
128
|
<div class="mt-3 row">
|
@@ -116,7 +116,7 @@
|
|
116
116
|
</div>
|
117
117
|
{% endmacro %}
|
118
118
|
|
119
|
-
{% macro overlapping_panel(variant, overlapping_vars, case, institute) %}
|
119
|
+
{% macro overlapping_panel(variant, overlapping_vars, overlapping_outliers, case, institute) %}
|
120
120
|
<div class="card panel-default">
|
121
121
|
{% if variant.category != "snv" %}
|
122
122
|
<div class="panel-heading">Gene overlapping variants</div>
|
@@ -141,27 +141,39 @@
|
|
141
141
|
</tr>
|
142
142
|
</thead>
|
143
143
|
<tbody>
|
144
|
-
{% for overlapping_variant in overlapping_vars %}
|
144
|
+
{% for overlapping_variant in overlapping_vars + overlapping_outliers %}
|
145
145
|
<tr>
|
146
146
|
<td>
|
147
147
|
{% if overlapping_variant.category in ("sv", "cancer_sv") %}
|
148
148
|
<a href="{{url_for('variant.sv_variant', institute_id=institute._id,
|
149
149
|
case_name=case.display_name, variant_id=overlapping_variant._id)}}" target="_blank">
|
150
|
-
{{ overlapping_variant.display_name|truncate(
|
150
|
+
{{ overlapping_variant.display_name|truncate(50, True) }}
|
151
151
|
</a>
|
152
|
-
{%
|
152
|
+
{% elif overlapping_variant.category == "outlier" %}
|
153
|
+
{{ overlapping_variant.display_name|truncate(50, True) }}
|
154
|
+
{% else %}
|
153
155
|
<a href="{{url_for('variant.variant', institute_id=institute._id,
|
154
156
|
case_name=case.display_name, variant_id=overlapping_variant._id)}}" target="_blank">
|
155
|
-
{{ overlapping_variant.display_name|truncate(
|
157
|
+
{{ overlapping_variant.display_name|truncate(50, True) }}
|
156
158
|
</a>
|
157
159
|
{% endif %}
|
158
160
|
</td>
|
159
161
|
<td>{{ overlapping_variant.hgnc_symbols|join(', ')|truncate(40, True) }}</td>
|
160
162
|
<td>{{ overlapping_variant.sub_category|upper }}</td>
|
161
|
-
|
162
|
-
|
163
|
+
{% if overlapping_variant.rank_score %}
|
164
|
+
<td class="text-end">{{ variant.rank_score + overlapping_variant.rank_score }}</td>
|
165
|
+
<td class="text-end">{{ overlapping_variant.rank_score }}</td>
|
166
|
+
{% else %}
|
167
|
+
<td class="text-end">-</td><td class="text-end">-</td>
|
168
|
+
{% endif %}
|
169
|
+
|
163
170
|
<td class="text-end">{{ overlapping_variant.length }}</td>
|
164
|
-
<td>
|
171
|
+
<td>
|
172
|
+
{{ overlapping_variant.region_annotations|join(', ')|truncate(40, True) }}
|
173
|
+
{% if overlapping_variant.sub_category == "splicing" %}
|
174
|
+
{{ overlapping_variant.potential_impact }} - fs {{ overlapping_variant.causes_frameshift }}
|
175
|
+
{% endif %}
|
176
|
+
</td>
|
165
177
|
<td>{{ overlapping_variant.functional_annotations|join(', ')|truncate(40, True) }}</td>
|
166
178
|
</tr>
|
167
179
|
{% else %}
|
@@ -152,7 +152,7 @@
|
|
152
152
|
{% endif %}
|
153
153
|
{{ rankscore_panel(rank_score_results) }}
|
154
154
|
<div class="row">
|
155
|
-
<div class="col-12">{{ overlapping_panel(variant, overlapping_vars, case, institute) }}</div>
|
155
|
+
<div class="col-12">{{ overlapping_panel(variant, overlapping_vars, overlapping_outliers, case, institute) }}</div>
|
156
156
|
</div>
|
157
157
|
<div class="mt-3 row">
|
158
158
|
<div class="col-12">
|
@@ -432,5 +432,46 @@
|
|
432
432
|
set_scrolly_table('proteins_panel_table')
|
433
433
|
set_scrolly_table('transcripts_panel_table')
|
434
434
|
|
435
|
+
function update_gene_has_full_coverage() {
|
436
|
+
$.getJSON('{{ url_for("variant.gene_has_full_coverage", institute_id=institute._id, case_name=case.display_name, variant_id=variant._id) }}', function (data) {
|
437
|
+
if($.isEmptyObject(data.gene_has_full_coverage)) {
|
438
|
+
const complete_coverage_indicator_elements = document.getElementsByClassName("complete-coverage-indicator");
|
439
|
+
for(let complete_coverage_indicator of complete_coverage_indicator_elements) {
|
440
|
+
complete_coverage_indicator.style.display = "none"
|
441
|
+
}
|
442
|
+
}
|
443
|
+
for (const [hgnc_id, has_complete_coverage] of Object.entries(data.gene_has_full_coverage)) {
|
444
|
+
// reset the temp color for the outer span and icon of the inner span
|
445
|
+
console.log()
|
446
|
+
var coverage_indicator_button = document.getElementById('coverage-indicator-'+hgnc_id+'-button');
|
447
|
+
var coverage_indicator_icon = document.getElementById('coverage-indicator-'+hgnc_id+'-icon');
|
448
|
+
var coverage_indicator_text = document.getElementById('coverage-indicator-'+hgnc_id+'-text');
|
449
|
+
|
450
|
+
// this is the outer, button span
|
451
|
+
coverage_indicator_button.classList.remove('btn-info');
|
452
|
+
// this is the inner, icon span
|
453
|
+
coverage_indicator_icon.classList.remove('blink_me','fa-circle-question');
|
454
|
+
|
455
|
+
if (has_complete_coverage) {
|
456
|
+
coverage_indicator_button.classList.add('btn-success');
|
457
|
+
coverage_indicator_button.setAttribute('data-bs-original-title', "Chanjo2 coverage is at 100% completeness.");
|
458
|
+
coverage_indicator_icon.classList.add('fa-circle-check');
|
459
|
+
coverage_indicator_text.textContent = "Complete"
|
460
|
+
} else {
|
461
|
+
coverage_indicator_button.classList.add('btn-warning');
|
462
|
+
coverage_indicator_button.setAttribute('data-bs-original-title', "Note that Chanjo2 coverage is below 100% completeness.");
|
463
|
+
coverage_indicator_icon.classList.add('fa-triangle-exclamation');
|
464
|
+
coverage_indicator_text.textContent = "Incomplete"
|
465
|
+
}
|
466
|
+
}
|
467
|
+
}).fail(function() {
|
468
|
+
const complete_coverage_indicator_elements = document.getElementsByClassName("complete-coverage-indicator");
|
469
|
+
for(let complete_coverage_indicator of complete_coverage_indicator_elements) {
|
470
|
+
complete_coverage_indicator.style.display = "none"
|
471
|
+
}
|
472
|
+
});
|
473
|
+
};
|
474
|
+
|
475
|
+
$( window ).on( "load", function() { update_gene_has_full_coverage(); })
|
435
476
|
</script>
|
436
477
|
{% endblock %}
|
@@ -28,6 +28,7 @@ from scout.server.blueprints.variant.controllers import (
|
|
28
28
|
)
|
29
29
|
from scout.server.blueprints.variant.controllers import evaluation as evaluation_controller
|
30
30
|
from scout.server.blueprints.variant.controllers import (
|
31
|
+
get_gene_has_full_coverage,
|
31
32
|
observations,
|
32
33
|
str_variant_reviewer,
|
33
34
|
)
|
@@ -423,6 +424,17 @@ def acmg():
|
|
423
424
|
return jsonify({"classification": classification, "conflicts": acmg_conflicts, **acmg_bayesian})
|
424
425
|
|
425
426
|
|
427
|
+
@variant_bp.route("/api/v1/gene_has_full_coverage/<institute_id>/<case_name>/<variant_id>/")
|
428
|
+
def gene_has_full_coverage(institute_id, case_name, variant_id):
|
429
|
+
"""Check if gene has full coverage using chanjo2 endpoint"""
|
430
|
+
institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
|
431
|
+
variant_obj = store.variant(variant_id)
|
432
|
+
|
433
|
+
return jsonify(
|
434
|
+
{"gene_has_full_coverage": get_gene_has_full_coverage(institute_obj, case_obj, variant_obj)}
|
435
|
+
)
|
436
|
+
|
437
|
+
|
426
438
|
@variant_bp.route("/ccv_evaluations/<evaluation_id>", methods=["GET", "POST"])
|
427
439
|
@templated("variant/ccv.html")
|
428
440
|
def ccv_evaluation(evaluation_id):
|
@@ -49,7 +49,12 @@ from scout.server.utils import (
|
|
49
49
|
user_institutes,
|
50
50
|
)
|
51
51
|
|
52
|
-
from .forms import
|
52
|
+
from .forms import (
|
53
|
+
FILTERSFORMCLASS,
|
54
|
+
CancerSvFiltersForm,
|
55
|
+
FusionFiltersForm,
|
56
|
+
SvFiltersForm,
|
57
|
+
)
|
53
58
|
from .utils import update_case_panels
|
54
59
|
|
55
60
|
NUM = re.compile(r"\d+")
|
@@ -111,6 +116,13 @@ def populate_institute_soft_filters(form, institute_obj):
|
|
111
116
|
form.institute_soft_filters.data = ",".join(institute_obj["soft_filters"])
|
112
117
|
|
113
118
|
|
119
|
+
def set_overlapping_variants(variant_obj: dict):
|
120
|
+
"""Define DNA or WTS variants that are overlapping with a gene of a variant."""
|
121
|
+
overlapping_variants, overlapping_outliers = store.hgnc_overlapping(variant_obj)
|
122
|
+
variant_obj["overlapping"] = list(overlapping_variants) or None
|
123
|
+
variant_obj["overlapping_outliers"] = list(overlapping_outliers) or None
|
124
|
+
|
125
|
+
|
114
126
|
def variants(
|
115
127
|
store,
|
116
128
|
institute_obj,
|
@@ -137,8 +149,7 @@ def variants(
|
|
137
149
|
|
138
150
|
variants = []
|
139
151
|
for variant_obj in variant_res:
|
140
|
-
|
141
|
-
variant_obj["overlapping"] = overlapping_svs or None
|
152
|
+
set_overlapping_variants(variant_obj)
|
142
153
|
|
143
154
|
evaluations = []
|
144
155
|
is_research = variant_obj["variant_type"] == "research"
|
@@ -233,8 +244,7 @@ def sv_variants(store, institute_obj, case_obj, variants_query, variant_count, p
|
|
233
244
|
case_dismissed_vars = store.case_dismissed_variants(institute_obj, case_obj)
|
234
245
|
|
235
246
|
for variant_obj in variants_query.skip(skip_count).limit(per_page):
|
236
|
-
|
237
|
-
variant_obj["overlapping"] = overlapping_svs or None
|
247
|
+
set_overlapping_variants(variant_obj)
|
238
248
|
|
239
249
|
# show previous classifications for research variants
|
240
250
|
clinical_var_obj = variant_obj
|
@@ -282,8 +292,7 @@ def mei_variants(
|
|
282
292
|
case_dismissed_vars = store.case_dismissed_variants(institute_obj, case_obj)
|
283
293
|
|
284
294
|
for variant_obj in variants_query.skip(skip_count).limit(per_page):
|
285
|
-
|
286
|
-
variant_obj["overlapping"] = overlapping or None
|
295
|
+
set_overlapping_variants(variant_obj)
|
287
296
|
|
288
297
|
# show previous classifications for research variants
|
289
298
|
clinical_var_obj = variant_obj
|
@@ -1454,8 +1463,7 @@ def cancer_variants(store, institute_id, case_name, variants_query, variant_coun
|
|
1454
1463
|
variant_obj["second_rep_gene"] = secondary_gene
|
1455
1464
|
variant_obj["clinical_assessments"] = get_manual_assessments(variant_obj)
|
1456
1465
|
|
1457
|
-
|
1458
|
-
variant_obj["overlapping"] = overlapping or None
|
1466
|
+
set_overlapping_variants(variant_obj)
|
1459
1467
|
|
1460
1468
|
evaluations = []
|
1461
1469
|
# Get previous ClinGen-CGC-VIGG evaluations of the variant from other cases
|
@@ -28,6 +28,7 @@ from scout.constants import (
|
|
28
28
|
CLINSIG_MAP,
|
29
29
|
FEATURE_TYPES,
|
30
30
|
GENETIC_MODELS,
|
31
|
+
ONC_CLNSIG,
|
31
32
|
OUTLIER_TYPES,
|
32
33
|
SO_TERMS,
|
33
34
|
SPIDEX_LEVELS,
|
@@ -38,6 +39,7 @@ from scout.constants import (
|
|
38
39
|
LOG = logging.getLogger(__name__)
|
39
40
|
|
40
41
|
CLINSIG_OPTIONS = list(CLINSIG_MAP.items())
|
42
|
+
ONC_CLNSIG_OPTIONS = [(term.lower().replace(" ", "_"), term) for term in ONC_CLNSIG]
|
41
43
|
FUNC_ANNOTATIONS = [(term, term.replace("_", " ")) for term in SO_TERMS]
|
42
44
|
REGION_ANNOTATIONS = [(term, term.replace("_", " ")) for term in FEATURE_TYPES]
|
43
45
|
SV_TYPE_CHOICES = [(term, term.replace("_", " ").upper()) for term in SV_TYPES]
|
@@ -112,8 +114,9 @@ class VariantFiltersForm(FlaskForm):
|
|
112
114
|
compound_rank_score = IntegerField("Compound rank score")
|
113
115
|
compound_follow_filter = BooleanField("Compounds follow filter")
|
114
116
|
cadd_inclusive = BooleanField("CADD inclusive")
|
115
|
-
clinsig = NonValidatingSelectMultipleField("ClinVar
|
117
|
+
clinsig = NonValidatingSelectMultipleField("ClinVar significance", choices=CLINSIG_OPTIONS)
|
116
118
|
clinsig_exclude = BooleanField("Exclude")
|
119
|
+
clinvar_tag = BooleanField("ClinVar hits only")
|
117
120
|
prioritise_clinvar = BooleanField("Prioritise ClinVar")
|
118
121
|
|
119
122
|
gnomad_frequency = BetterDecimalField("gnomadAF", validators=[validators.Optional()])
|
@@ -183,7 +186,6 @@ class FiltersForm(VariantFiltersForm):
|
|
183
186
|
spidex_human = SelectMultipleField("SPIDEX", choices=SPIDEX_CHOICES)
|
184
187
|
|
185
188
|
clinical_filter = SubmitField(label="Clinical filter")
|
186
|
-
clinvar_tag = BooleanField("ClinVar hits only")
|
187
189
|
|
188
190
|
# polymorphic constant base for clinical filter
|
189
191
|
clinical_filter_base = CLINICAL_FILTER_BASE
|
@@ -196,8 +198,11 @@ class CancerFiltersForm(VariantFiltersForm):
|
|
196
198
|
alt_count = IntegerField("Min alt count", validators=[validators.Optional()])
|
197
199
|
control_frequency = BetterDecimalField("Normal alt AF <", validators=[validators.Optional()])
|
198
200
|
tumor_frequency = BetterDecimalField("Tumor alt AF >", validators=[validators.Optional()])
|
199
|
-
clinvar_tag = BooleanField("ClinVar hits only")
|
200
201
|
cosmic_tag = BooleanField("Cosmic hits")
|
202
|
+
clinsig_onc = NonValidatingSelectMultipleField(
|
203
|
+
"ClinVar oncogenicity", choices=ONC_CLNSIG_OPTIONS
|
204
|
+
)
|
205
|
+
clinsig_onc_exclude = BooleanField("Exclude")
|
201
206
|
mvl_tag = BooleanField("Managed Variants hits")
|
202
207
|
local_obs_cancer_somatic_old = IntegerField(
|
203
208
|
"Local somatic obs. (archive)", validators=[validators.Optional()]
|
@@ -440,10 +440,16 @@
|
|
440
440
|
data-bs-html="true" data-bs-trigger="hover click"
|
441
441
|
{% if variant.category == "SNV" %}
|
442
442
|
data-bs-content="<div>Gene overlapping non-SNVs</div>
|
443
|
-
{{ overlapping_tooltip_table(institute, case, variant.overlapping[:20]) }}">Gene overlapping</a>
|
443
|
+
{{ overlapping_tooltip_table(institute, case, variant.overlapping[:20]) }}">Gene overlapping (DNA)</a>
|
444
444
|
{% else %}
|
445
445
|
data-bs-content="<div>Gene overlapping variants</div>
|
446
|
-
{{ overlapping_tooltip_table(institute, case, variant.overlapping[:40]) }}">Gene overlapping</a>
|
446
|
+
{{ overlapping_tooltip_table(institute, case, variant.overlapping[:40]) }}">Gene overlapping (DNA)</a>
|
447
447
|
{% endif %}
|
448
448
|
{% endif %}
|
449
|
+
|
450
|
+
{% if variant.overlapping_outliers %}
|
451
|
+
<a href="#" class="badge bg-success text-white" data-bs-toggle="popover" data-bs-placement="left"
|
452
|
+
data-bs-html="true" data-bs-trigger="hover click" data-bs-content="<div>Gene overlapping WTS outliers</div>
|
453
|
+
{{ overlapping_tooltip_table(institute, case, variant.overlapping_outliers[:40]) }}">Gene overlapping (WTS)</a>
|
454
|
+
{% endif %}
|
449
455
|
{% endmacro %}
|
@@ -41,25 +41,23 @@
|
|
41
41
|
|
42
42
|
{% macro other_tiered_variants(variant) %}
|
43
43
|
{% if variant.matching_tiered %}
|
44
|
-
<span class="
|
45
|
-
|
44
|
+
<span class="badge bg-dark" data-bs-toggle="popover" data-bs-html="true" data-bs-trigger="hover click"
|
45
|
+
data-bs-title="Previously <b>T</b>iered as"
|
46
|
+
data-bs-content="
|
46
47
|
{% for tier, tiered_info in variant.matching_tiered.items() %}
|
47
|
-
<span class='badge bg-{{tiered_info.
|
48
|
-
{% endfor %}
|
49
|
-
"
|
50
|
-
data-original-title="Previously tiered as">T</span>
|
48
|
+
<span class='badge bg-{{tiered_info.label_class}}'>{{tier}} ({{tiered_info.links|length}}x)</span>
|
49
|
+
{% endfor %}">T</span>
|
51
50
|
{% endif %} <!-- end of if variant.matching_tiered -->
|
52
51
|
{% endmacro %}
|
53
52
|
|
54
53
|
{% macro matching_manual_rank(variant) %}
|
55
54
|
{% if variant.matching_ranked %}
|
56
|
-
<span class="
|
57
|
-
data-bs-
|
55
|
+
<span class="badge bg-dark" data-bs-toggle="popover" data-bs-html="true" data-bs-trigger="hover click"
|
56
|
+
data-bs-title="Previously <b>M</b>anually ranked as"
|
57
|
+
data-bs-content="
|
58
58
|
{% for manual_rank, manual_rank_info in variant.matching_ranked.items() %}
|
59
|
-
<div>{{manual_rank_info.label}} - {{manual_rank_info.description}} ({{manual_rank_info.links|length}}x)</div>
|
60
|
-
{% endfor %}
|
61
|
-
"
|
62
|
-
data-original-title="Previously ranked as">M</span>
|
59
|
+
<div><span class='badge bg-{{ manual_rank_info.label_class }}'>{{manual_rank_info.label}}</span> - {{manual_rank_info.description}} ({{manual_rank_info.links|length}}x)</div>
|
60
|
+
{% endfor %}">M</span>
|
63
61
|
{% endif %}
|
64
62
|
{% endmacro %}
|
65
63
|
|
@@ -120,7 +118,7 @@
|
|
120
118
|
{% macro group_assessments_badge(variant) %}
|
121
119
|
{% if variant.group_assessments %}
|
122
120
|
{% for assessment in (variant.group_assessments or []) %}
|
123
|
-
<span class="badge bg-{{ assessment.display_class }}" data-bs-html="true" data-bs-toggle="tooltip" data-bs-placement="right"
|
121
|
+
<span class="badge bg-{{ assessment.display_class }}<b>" data-bs-html="true" data-bs-toggle="tooltip" data-bs-placement="right"
|
124
122
|
title="Cohort {{ assessment.title }}">
|
125
123
|
{{ assessment.label }}</span>
|
126
124
|
{% endfor %}
|