scout-browser 4.80__py3-none-any.whl → 4.82.1__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/disease_terms.py +5 -2
- scout/adapter/mongo/query.py +23 -11
- scout/adapter/mongo/variant.py +2 -2
- scout/build/managed_variant.py +12 -1
- scout/build/variant/genotype.py +2 -0
- scout/build/variant/variant.py +5 -0
- scout/constants/__init__.py +1 -0
- scout/constants/clinvar.py +1 -1
- scout/constants/indexes.py +10 -0
- scout/constants/query_terms.py +3 -1
- scout/models/variant/variant.py +1 -0
- scout/parse/variant/frequency.py +56 -54
- scout/parse/variant/genotype.py +89 -15
- scout/parse/variant/transcript.py +17 -9
- scout/parse/variant/variant.py +12 -0
- scout/server/app.py +6 -3
- scout/server/blueprints/alignviewers/templates/alignviewers/utils.html +1 -1
- scout/server/blueprints/cases/controllers.py +2 -57
- scout/server/blueprints/cases/templates/cases/case_report.html +212 -190
- scout/server/blueprints/cases/templates/cases/chanjo2_form.html +47 -0
- scout/server/blueprints/cases/templates/cases/collapsible_actionbar.html +4 -4
- scout/server/blueprints/cases/templates/cases/gene_panel.html +17 -23
- scout/server/blueprints/cases/templates/cases/utils.html +3 -1
- scout/server/blueprints/cases/views.py +0 -22
- scout/server/blueprints/clinvar/controllers.py +3 -3
- scout/server/blueprints/clinvar/templates/clinvar/clinvar_submissions.html +29 -2
- scout/server/blueprints/clinvar/templates/clinvar/multistep_add_variant.html +36 -18
- scout/server/blueprints/clinvar/views.py +13 -1
- scout/server/blueprints/diagnoses/controllers.py +2 -0
- scout/server/blueprints/institutes/controllers.py +76 -38
- scout/server/blueprints/institutes/templates/overview/cases.html +54 -42
- scout/server/blueprints/managed_variants/templates/managed_variants/managed_variants.html +1 -1
- scout/server/blueprints/managed_variants/views.py +2 -4
- scout/server/blueprints/panels/templates/panels/panel.html +8 -7
- scout/server/blueprints/panels/templates/panels/panel_pdf_case_hits.html +2 -2
- scout/server/blueprints/panels/templates/panels/panel_pdf_simple.html +3 -3
- scout/server/blueprints/panels/views.py +2 -11
- scout/server/blueprints/phenotypes/templates/phenotypes/hpo_terms.html +3 -2
- scout/server/blueprints/variant/controllers.py +3 -2
- scout/server/blueprints/variant/templates/variant/components.html +1 -1
- scout/server/blueprints/variant/templates/variant/utils.html +3 -1
- scout/server/blueprints/variant/templates/variant/variant.html +20 -15
- scout/server/blueprints/variant/templates/variant/variant_details.html +78 -26
- scout/server/blueprints/variant/utils.py +9 -13
- scout/server/blueprints/variants/controllers.py +32 -3
- scout/server/blueprints/variants/forms.py +15 -1
- scout/server/blueprints/variants/templates/variants/components.html +55 -0
- scout/server/blueprints/variants/templates/variants/fusion-variants.html +3 -50
- scout/server/blueprints/variants/templates/variants/str-variants.html +8 -5
- scout/server/blueprints/variants/templates/variants/utils.html +57 -31
- scout/server/blueprints/variants/templates/variants/variants.html +1 -1
- scout/server/blueprints/variants/utils.py +7 -10
- scout/server/extensions/clinvar_extension.py +10 -2
- scout/server/templates/report_base.html +3 -3
- scout/server/templates/utils.html +2 -2
- {scout_browser-4.80.dist-info → scout_browser-4.82.1.dist-info}/METADATA +6 -5
- {scout_browser-4.80.dist-info → scout_browser-4.82.1.dist-info}/RECORD +62 -61
- {scout_browser-4.80.dist-info → scout_browser-4.82.1.dist-info}/LICENSE +0 -0
- {scout_browser-4.80.dist-info → scout_browser-4.82.1.dist-info}/WHEEL +0 -0
- {scout_browser-4.80.dist-info → scout_browser-4.82.1.dist-info}/entry_points.txt +0 -0
- {scout_browser-4.80.dist-info → scout_browser-4.82.1.dist-info}/top_level.txt +0 -0
@@ -153,7 +153,7 @@
|
|
153
153
|
{% if case.vcf_files.vcf_snv %}
|
154
154
|
<a href="{{ url_for('variants.variants', institute_id=case.owner, case_name=case.display_name, variant_type='research') }}">Research SNV and INDELs</a>
|
155
155
|
{% elif case.vcf_files.vcf_cancer %}
|
156
|
-
<a href="{{ url_for('variants.cancer_variants', institute_id=case.owner, case_name=case.display_name, variant_type='research') }}">
|
156
|
+
<a href="{{ url_for('variants.cancer_variants', institute_id=case.owner, case_name=case.display_name, variant_type='research') }}">Research Somatic Variants</a>
|
157
157
|
{% endif %}
|
158
158
|
{% else %}
|
159
159
|
{% if case.vcf_files.vcf_snv %}
|
@@ -192,6 +192,54 @@
|
|
192
192
|
</tr>
|
193
193
|
{% endmacro %}
|
194
194
|
|
195
|
+
{% macro sanger_to_be_validated(unevaluated, validated_by_others) %}
|
196
|
+
<div class="row container alert alert-info alert-dismissible" role="alert">
|
197
|
+
<div class="col-1">
|
198
|
+
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
199
|
+
</div>
|
200
|
+
<div class="col">
|
201
|
+
You have <strong>{{ unevaluated|length }}</strong> cases with Sanger validations to evaluate.
|
202
|
+
{% if validated_by_others == true %}
|
203
|
+
These variants have been validated by another user, but you ordered the Sanger sequencing. Adding your validation will silence this message.
|
204
|
+
{% endif %}
|
205
|
+
<!-- Button trigger modal -->
|
206
|
+
<button type="button" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#evaluateModal_validated{% if validated_by_others %}_by_others{% endif %}">
|
207
|
+
evaluate
|
208
|
+
</button>
|
209
|
+
</div>
|
210
|
+
|
211
|
+
<!-- Modal -->
|
212
|
+
<div class="modal fade" id="evaluateModal_validated{% if validated_by_others %}_by_others{% endif %}" tabindex="-1" role="dialog" aria-labelledby="sangerModalLabel" aria-hidden="true">
|
213
|
+
<div class="modal-dialog" role="document">
|
214
|
+
<div class="modal-content">
|
215
|
+
<div class="modal-header">
|
216
|
+
<h5 class="modal-title" id="sangerModalLabel">Sanger validations to evaluate:</h5>
|
217
|
+
</div>
|
218
|
+
<div class="modal-body">
|
219
|
+
<ul>
|
220
|
+
{% for uneval_obj in unevaluated %}
|
221
|
+
{% for case, var_list in uneval_obj.items() %}
|
222
|
+
<li>
|
223
|
+
Case <strong><a href="{{ url_for('cases.case', institute_id=institute._id, case_name=case) }}" target="_blank">{{case}}</a></strong> ---> <strong>{{var_list|length}}</strong> variants:
|
224
|
+
<ul>
|
225
|
+
{% for var in var_list %}
|
226
|
+
<li><a href="{{ url_for('variant.variant', institute_id=institute._id, case_name=case, variant_id=var) }}" target="_blank">{{var}}</a></li>
|
227
|
+
{% endfor %}
|
228
|
+
</ul>
|
229
|
+
</li>
|
230
|
+
{% endfor %}
|
231
|
+
{% endfor %}
|
232
|
+
</ul>
|
233
|
+
</div>
|
234
|
+
<div class="modal-footer">
|
235
|
+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
236
|
+
</div>
|
237
|
+
</div>
|
238
|
+
</div>
|
239
|
+
</div>
|
240
|
+
</div>
|
241
|
+
{% endmacro %}
|
242
|
+
|
195
243
|
{% block content_main %}
|
196
244
|
<div class="container-float">
|
197
245
|
<div class="row" id="body-row"> <!--sidebar and main container are on the same row-->
|
@@ -208,49 +256,13 @@
|
|
208
256
|
</div>
|
209
257
|
|
210
258
|
{% if sanger_unevaluated %}
|
211
|
-
|
212
|
-
|
213
|
-
{% if sanger_unevaluated|length > 1%}
|
214
|
-
You have <strong>{{ sanger_unevaluated|length }}</strong> cases with Sanger validations to evaluate!
|
215
|
-
{% else %}
|
216
|
-
You have <strong>1</strong> case with Sanger validations to evaluate!
|
217
|
-
{% endif %}
|
218
|
-
<!-- Button trigger modal -->
|
219
|
-
<button type="button" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#evaluateModal">
|
220
|
-
evaluate
|
221
|
-
</button>
|
259
|
+
{{ sanger_to_be_validated(sanger_unevaluated, false) }}
|
260
|
+
{% endif %}
|
222
261
|
|
223
|
-
|
224
|
-
|
225
|
-
<div class="modal-dialog" role="document">
|
226
|
-
<div class="modal-content">
|
227
|
-
<div class="modal-header">
|
228
|
-
<h5 class="modal-title" id="sangerModalLabel">Sanger validations to evaluate:</h5>
|
229
|
-
</div>
|
230
|
-
<div class="modal-body">
|
231
|
-
<ul>
|
232
|
-
{% for uneval_obj in sanger_unevaluated %}
|
233
|
-
{% for case, var_list in uneval_obj.items() %}
|
234
|
-
<li>
|
235
|
-
Case <strong><a href="{{ url_for('cases.case', institute_id=institute._id, case_name=case) }}" target="_blank">{{case}}</a></strong> ---> <strong>{{var_list|length}}</strong> variants:
|
236
|
-
<ul>
|
237
|
-
{% for var in var_list %}
|
238
|
-
<li><a href="{{ url_for('variant.variant', institute_id=institute._id, case_name=case, variant_id=var) }}" target="_blank">{{var}}</a></li>
|
239
|
-
{% endfor %}
|
240
|
-
</ul>
|
241
|
-
</li>
|
242
|
-
{% endfor %}
|
243
|
-
{% endfor %}
|
244
|
-
</ul>
|
245
|
-
</div>
|
246
|
-
<div class="modal-footer">
|
247
|
-
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
248
|
-
</div>
|
249
|
-
</div>
|
250
|
-
</div>
|
251
|
-
</div>
|
252
|
-
</div>
|
262
|
+
{% if sanger_validated_by_others %}
|
263
|
+
{{ sanger_to_be_validated(sanger_validated_by_others, true) }}
|
253
264
|
{% endif %}
|
265
|
+
|
254
266
|
<div>
|
255
267
|
{% set ordered_statuses = ['prioritized', 'inactive', 'active', 'archived', 'solved', 'ignored'] -%}
|
256
268
|
{% for status in ordered_statuses %}
|
@@ -184,7 +184,7 @@
|
|
184
184
|
<div class="col-sm-7 text-center">
|
185
185
|
<input type="file" name="csv_file" class="custom-file-input" required onchange="this.nextElementSibling.innerText = this.files[0].name">
|
186
186
|
<label class="custom-file-label" for="csv_file">Choose file</label><br>
|
187
|
-
<p class="help-block">How do I format my <a href="https://clinical-genomics.github.io/scout/user-guide/variants/#
|
187
|
+
<p class="help-block">How do I format my <a href="https://clinical-genomics.github.io/scout/user-guide/variants/#managed-variants-upload-file-format" rel="noopener" target="_blank">managed variants file</a>?</p>
|
188
188
|
</div>
|
189
189
|
<div class="col-sm-2 text-center">
|
190
190
|
<button type="submit" class="btn btn-secondary">Upload</button>
|
@@ -1,7 +1,6 @@
|
|
1
|
-
import datetime
|
2
1
|
import logging
|
3
2
|
|
4
|
-
from flask import Blueprint, flash, redirect, request
|
3
|
+
from flask import Blueprint, flash, redirect, request
|
5
4
|
from flask_login import current_user
|
6
5
|
|
7
6
|
from scout.server.extensions import store
|
@@ -29,12 +28,12 @@ def upload_managed_variants():
|
|
29
28
|
|
30
29
|
csv_file = request.files["csv_file"]
|
31
30
|
content = csv_file.stream.read()
|
32
|
-
lines = None
|
33
31
|
try:
|
34
32
|
if b"\n" in content:
|
35
33
|
lines = content.decode("utf-8-sig", "ignore").split("\n")
|
36
34
|
else:
|
37
35
|
lines = content.decode("windows-1252").split("\r")
|
36
|
+
|
38
37
|
except Exception as err:
|
39
38
|
flash(
|
40
39
|
"Something went wrong while parsing the panel CSV file! ({})".format(err),
|
@@ -42,7 +41,6 @@ def upload_managed_variants():
|
|
42
41
|
)
|
43
42
|
return redirect(request.referrer)
|
44
43
|
|
45
|
-
LOG.debug("Loading lines %s", lines)
|
46
44
|
result = controllers.upload_managed_variants(store, lines, institutes, current_user._id)
|
47
45
|
flash(
|
48
46
|
"In total {} new variants out of {} in file added".format(result[0], result[1]),
|
@@ -1,3 +1,4 @@
|
|
1
|
+
{% from "cases/chanjo2_form.html" import chanjo2_report_form %}
|
1
2
|
{% extends "layout.html" %}
|
2
3
|
|
3
4
|
{% block title %}
|
@@ -103,18 +104,18 @@
|
|
103
104
|
</span>
|
104
105
|
</li>
|
105
106
|
{% endif %}
|
106
|
-
{% if case and case.chanjo2_coverage %}
|
107
|
+
{% if case and case.chanjo2_coverage and panel.genes %}
|
107
108
|
<li class="list-group-item">
|
108
109
|
<label for="coverage_report">Coverage report (chanjo2)</label>
|
109
|
-
<
|
110
|
-
|
111
|
-
</
|
110
|
+
<span class="float-end">
|
111
|
+
{{ chanjo2_report_form(panel.institute, case, panel.name_and_version, 'report', panel.genes|map(attribute='hgnc_id')|join(','), case.display_name) }} <!--chanjo2 report-->
|
112
|
+
</span>
|
112
113
|
</li>
|
113
114
|
<li class="list-group-item">
|
114
115
|
<label for="coverage_report">Coverage overview (chanjo2)</label>
|
115
|
-
<
|
116
|
-
|
117
|
-
</
|
116
|
+
<span class="float-end">
|
117
|
+
{{ chanjo2_report_form(panel.institute, case, panel.name_and_version, 'overview', panel.genes|map(attribute='hgnc_id')|join(','), case.display_name) }} <!--chanjo2 genes overview -->
|
118
|
+
</span>
|
118
119
|
</li>
|
119
120
|
{% endif %}
|
120
121
|
<li class="list-group-item">
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<h4>Scout - Institute {{institute.display_name}} - case {{case.display_name}} - {{panel.name_and_version}}: panel extent report</h4> - created on: <strong>{{report_created_at}}</strong><br><br>
|
7
7
|
{{ hits_panel() }}
|
8
8
|
<br>[END OF REPORT]<br><br>
|
9
|
-
<a href="https://clinical-genomics.github.io/scout" target="_blank" rel="noopener">clinical-genomics.github.io/scout</a>
|
9
|
+
<a style="text-decoration:none;" href="https://clinical-genomics.github.io/scout" target="_blank" rel="noopener">clinical-genomics.github.io/scout</a>
|
10
10
|
</div>
|
11
11
|
{% endblock %}
|
12
12
|
|
@@ -21,7 +21,7 @@
|
|
21
21
|
Gene panel: <strong>{{panel.name_and_version}}</strong><br>
|
22
22
|
Last updated: <strong>{{ panel.date.strftime('%Y-%m-%d') }}</strong>
|
23
23
|
{% if case.outdated_panels and panel.panel_name in case.outdated_panels %}
|
24
|
-
<a><span class="badge rounded-pill
|
24
|
+
<a><span class="badge rounded-pill py-1 bg-warning" data-bs-toggle="popover" data-bs-placement="left" data-bs-html="true" data-bs-content="Panel version used in the analysis ({{panel.version}}) is outdated. Latest panel version is used in variants filtering.<br /><strong>Genes present in case panel and not in latest version</strong>: {{case.outdated_panels[panel.panel_name]['extra_genes']|join(', ') or '-'}}.<br /><strong>Genes present only in latest version</strong>: {{case.outdated_panels[panel.panel_name]['missing_genes']|join(', ') or '-'}}.">!</span></a>
|
25
25
|
{% endif %}<br>
|
26
26
|
Panel ID: {{ panel.panel_name }}<br>
|
27
27
|
Description: {{ panel.description }}<br>
|
@@ -6,14 +6,14 @@
|
|
6
6
|
<h4>Scout - Gene panel report</h4> - created on: <strong>{{report_created_at}}</strong><br><br>
|
7
7
|
{{ genes_panel() }}
|
8
8
|
[END OF REPORT]<br><br>
|
9
|
-
<a href="https://clinical-genomics.github.io/scout" target="_blank">clinical-genomics.github.io/scout</a>
|
9
|
+
<a style="text-decoration:none;" href="https://clinical-genomics.github.io/scout" target="_blank">clinical-genomics.github.io/scout</a>
|
10
10
|
</div>
|
11
11
|
{% endblock %}
|
12
12
|
|
13
13
|
{% macro genes_panel() %}
|
14
14
|
<div class="card border-dark mb-3">
|
15
15
|
<div class="card-header">
|
16
|
-
Panel: <a href="{{ url_for('panels.panel', panel_id=panel._id) }}">{{panel.name_and_version}}</a>
|
16
|
+
Panel: <a style="text-decoration:none;" href="{{ url_for('panels.panel', panel_id=panel._id) }}">{{panel.name_and_version}}</a>
|
17
17
|
</div>
|
18
18
|
<div class="card-body">
|
19
19
|
<table class="table table-sm">
|
@@ -58,7 +58,7 @@
|
|
58
58
|
<tr>
|
59
59
|
<td>{{loop.index}}</td>
|
60
60
|
<td>
|
61
|
-
<a href="https://www.genenames.org/cgi-bin/gene_symbol_report?hgnc_id={{gene.hgnc_id}}" target="_blank">{{gene.hgnc_id}}</a>
|
61
|
+
<a style="text-decoration:none;" href="https://www.genenames.org/cgi-bin/gene_symbol_report?hgnc_id={{gene.hgnc_id}}" target="_blank">{{gene.hgnc_id}}</a>
|
62
62
|
</td>
|
63
63
|
<td>{{ gene.symbol }}</td>
|
64
64
|
<td>{{ gene.disease_associated_transcripts|join(', ') }}</td>
|
@@ -3,18 +3,9 @@ import datetime
|
|
3
3
|
import json
|
4
4
|
import logging
|
5
5
|
|
6
|
-
from flask import
|
7
|
-
Blueprint,
|
8
|
-
Response,
|
9
|
-
escape,
|
10
|
-
flash,
|
11
|
-
redirect,
|
12
|
-
render_template,
|
13
|
-
request,
|
14
|
-
send_file,
|
15
|
-
url_for,
|
16
|
-
)
|
6
|
+
from flask import Blueprint, Response, flash, redirect, render_template, request, send_file, url_for
|
17
7
|
from flask_login import current_user
|
8
|
+
from markupsafe import escape
|
18
9
|
|
19
10
|
from scout.constants import DATE_DAY_FORMATTER
|
20
11
|
from scout.export.panel import export_gene_panels
|
@@ -21,7 +21,7 @@
|
|
21
21
|
<div class="row mt-3">
|
22
22
|
<div class="col-md-12">
|
23
23
|
<div class="card">
|
24
|
-
<div class="card-header">HPO terms</div>
|
24
|
+
<div class="card-header">Number of HPO terms present in the database:{{phenotypes|length}}</div>
|
25
25
|
<div class="card-body">
|
26
26
|
{% if phenotypes|length == 0 %}
|
27
27
|
The search didn't return any phenotype term
|
@@ -54,7 +54,8 @@
|
|
54
54
|
<script type="text/javascript">
|
55
55
|
$(document).ready(function() {
|
56
56
|
$('#phenotypes_table').DataTable( {
|
57
|
-
paging:
|
57
|
+
paging: true,
|
58
|
+
pageLength: 50,
|
58
59
|
dom: 'fBrtip',
|
59
60
|
buttons: [
|
60
61
|
{
|
@@ -3,8 +3,9 @@ import os
|
|
3
3
|
from typing import Dict, List, Optional
|
4
4
|
|
5
5
|
import requests
|
6
|
-
from flask import
|
6
|
+
from flask import abort, current_app, flash, url_for
|
7
7
|
from flask_login import current_user
|
8
|
+
from markupsafe import Markup
|
8
9
|
|
9
10
|
from scout.adapter import MongoAdapter
|
10
11
|
from scout.constants import (
|
@@ -238,7 +239,7 @@ def variant(
|
|
238
239
|
# The hierarchical call order is relevant: cases are used to populate variants
|
239
240
|
update_variant_case_panels(case_obj, variant_obj)
|
240
241
|
|
241
|
-
associate_variant_genes_with_case_panels(
|
242
|
+
associate_variant_genes_with_case_panels(case_obj, variant_obj)
|
242
243
|
|
243
244
|
# Provide basic info on alignment files availability for this case
|
244
245
|
case_has_alignments(case_obj)
|
@@ -241,7 +241,7 @@
|
|
241
241
|
<div class="card panel-default">
|
242
242
|
<div class="panel-heading">Compounds (top 20)</div>
|
243
243
|
<div class="card-body">
|
244
|
-
{{ compounds_table(institute, case, variant.compounds[:20]) }}
|
244
|
+
{{ compounds_table(institute, case, variant.compounds[:20], is_popover=false) }}
|
245
245
|
</div>
|
246
246
|
</div>
|
247
247
|
{% endmacro %}
|
@@ -131,7 +131,9 @@
|
|
131
131
|
<th>Variant</th>
|
132
132
|
<th>Gene</th>
|
133
133
|
<th>Type</th>
|
134
|
-
<th>Combined score
|
134
|
+
<th>Combined score
|
135
|
+
<span data-bs-toggle='tooltip' data-bs-title='Combined score is the sum of variants´s score and overlapping variant´s score'>?</span>
|
136
|
+
</th>
|
135
137
|
<th>Rank score</th>
|
136
138
|
<th>Length</th>
|
137
139
|
<th>Region</th>
|
@@ -5,7 +5,7 @@
|
|
5
5
|
{% from "variant/utils.html" import causative_button, genes_panel, modal_causative, overlapping_panel, pin_button, proteins_panel, transcripts_panel, custom_annotations %}
|
6
6
|
{% from "variant/tx_overview.html" import disease_associated, transcripts_overview %}
|
7
7
|
{% from "variant/gene_disease_relations.html" import autozygosity_panel, genemodels_panel, inheritance_panel, orpha_omim_phenotypes %}
|
8
|
-
{% from "variant/variant_details.html" import frequencies, gtcall_panel,
|
8
|
+
{% from "variant/variant_details.html" import conservations, frequencies, gtcall_panel, mappability, observations_panel, old_observations, severity_list, str_db_card %}
|
9
9
|
{% from "variant/components.html" import alignments, clinsig_table, compounds_panel, external_links, external_scripts, external_stylesheets, matching_variants, panel_classify, variant_scripts %}
|
10
10
|
{% from "variant/sanger.html" import modal_cancel_sanger, modal_sanger, sanger_button %}
|
11
11
|
{% from "variant/rank_score_results.html" import rankscore_panel %}
|
@@ -90,11 +90,15 @@
|
|
90
90
|
{{ panel_summary() }}
|
91
91
|
</div>
|
92
92
|
<div class="col-lg-4">
|
93
|
-
{
|
94
|
-
|
95
|
-
|
93
|
+
{% if str %}
|
94
|
+
{{ str_db_card(variant) }}
|
95
|
+
{% else %}
|
96
|
+
{{ frequencies(variant) }}
|
97
|
+
{% if config['LOQUSDB_SETTINGS'] %}
|
98
|
+
{{ observations_panel(variant, observations, case) }}
|
99
|
+
{% endif %}
|
100
|
+
{{ old_observations(variant) }}
|
96
101
|
{% endif %}
|
97
|
-
{{ old_observations(variant) }}
|
98
102
|
</div>
|
99
103
|
</div>
|
100
104
|
<div class="row">
|
@@ -227,8 +231,8 @@
|
|
227
231
|
<tr>
|
228
232
|
<td>
|
229
233
|
Position:
|
230
|
-
|
231
|
-
|
234
|
+
<strong>{{ variant.chromosome }}:<span class="text-muted">{{ variant.position }}</span></strong>
|
235
|
+
<button type="button" class="fa fa-copy btn-xs js-tooltip js-copy" style="background-color: Transparent;outline:none; border: none;" data-bs-toggle="tooltip" data-bs-placement="bottom" data-copy="{{ variant.chromosome }}:{{ variant.position }}" title="Copy to clipboard">
|
232
236
|
</button>
|
233
237
|
</td>
|
234
238
|
<td {% if not mei %}colspan="3"{% endif %}>
|
@@ -282,13 +286,12 @@
|
|
282
286
|
</strong></span>
|
283
287
|
</td>
|
284
288
|
</tr>
|
285
|
-
|
286
289
|
</tbody>
|
287
290
|
</table>
|
288
291
|
<table class="table table-bordered table-fixed table-sm">
|
289
292
|
<tbody class="border-top">
|
290
293
|
<tr>
|
291
|
-
<td>
|
294
|
+
<td {% if str %}colspan="2"{% endif %}>
|
292
295
|
Matches OMIM inhert.
|
293
296
|
{% if variant.is_matching_inheritance %}
|
294
297
|
<span class="badge bg-success float-end">Yes</span>
|
@@ -296,12 +299,14 @@
|
|
296
299
|
<div class="badge bg-warning float-end">No</div>
|
297
300
|
{% endif %}
|
298
301
|
</td>
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
{{ variant.frequency }}
|
303
|
-
|
304
|
-
|
302
|
+
{% if not str %}
|
303
|
+
<td>
|
304
|
+
Frequency
|
305
|
+
<div class="badge bg-{% if variant.frequency == 'common' %}danger{% elif variant.frequency == 'uncommon' %}warning{% else %}success{% endif %} float-end">
|
306
|
+
{{ variant.frequency }}
|
307
|
+
</div>
|
308
|
+
</td>
|
309
|
+
{% endif %}
|
305
310
|
</tr>
|
306
311
|
</tbody>
|
307
312
|
</table>
|
@@ -105,37 +105,89 @@
|
|
105
105
|
</div>
|
106
106
|
{% endmacro %}
|
107
107
|
|
108
|
-
{% macro
|
108
|
+
{% macro str_db_card(variant) %}
|
109
109
|
<div class="card panel-default">
|
110
|
-
<div class="panel-heading">
|
110
|
+
<div class="panel-heading">STR locus details</div>
|
111
111
|
<div class="card-body">
|
112
|
-
<table class="table">
|
112
|
+
<table class="table" aria-label="STR locus details">
|
113
113
|
<thead class="thead table-light">
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
114
|
+
<tr>
|
115
|
+
<th scope="col">Source</th>
|
116
|
+
<th scope="col">Value</th>
|
117
|
+
</tr>
|
118
|
+
</thead>
|
119
|
+
<tbody>
|
120
|
+
<tr><td>Normal max</td><td>{{ variant.str_normal_max }}</td></tr>
|
121
|
+
<tr><td>Pathologic min</td><td>{{ variant.str_pathologic_min }}</td><tr>
|
122
|
+
{% if variant.str_status == 'full_mutation' %}
|
123
|
+
<tr class="bg-danger">
|
124
|
+
{% elif variant.str_status == 'pre_mutation' %}
|
125
|
+
<tr class="bg-warning">
|
126
|
+
{% else %}
|
127
|
+
<tr>
|
128
|
+
{% endif %}
|
129
|
+
<td>Motif copies</td><td>{{ variant.str_mc }} <span class="badge bg-secondary text-white">{{ variant.str_status }}</span></td>
|
130
|
+
</tr>
|
131
|
+
<tr><td colspan=2> </td></tr>
|
132
|
+
{% if variant.str_swegen_mean %}
|
133
|
+
<tr><td>SweGen Z-score</td><td>
|
134
|
+
{% if variant.str_mc %}
|
135
|
+
{{ ((variant.str_mc - variant.str_swegen_mean ) / variant.str_swegen_std) | round(2) }}
|
136
|
+
{% endif %}
|
137
|
+
</td></tr>
|
138
|
+
<tr><td>SweGen mean</td><td>{{variant.str_swegen_mean|round(2)}}</td></tr>
|
139
|
+
<tr><td>SweGen std</td><td>{{variant.str_swegen_std|round(2)}}</td></tr>
|
140
|
+
<tr><td colspan=2> </td></tr>
|
141
|
+
{% endif %}
|
142
|
+
{% for gene in variant.genes %}
|
143
|
+
{% if gene.stripy_link %}
|
144
|
+
<tr><td>
|
145
|
+
<a href="{{ gene.str_gnomad_link }}" target="_blank" rel="noopener" referrerpolicy="no-referrer">gnomAD</a>
|
146
|
+
</td><td>{{ gene.hgnc_symbol }}</td></tr>
|
127
147
|
{% endif %}
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
{% else %}
|
133
|
-
-
|
148
|
+
{% if gene.stripy_link %}
|
149
|
+
<tr><td>
|
150
|
+
<a href="{{ gene.stripy_link }}" target="_blank" rel="noopener" referrerpolicy="no-referrer">STRipy</a>
|
151
|
+
</td><td>{{ gene.hgnc_symbol }}</td></tr>
|
134
152
|
{% endif %}
|
135
|
-
|
136
|
-
</
|
137
|
-
|
138
|
-
|
153
|
+
{% endfor %}
|
154
|
+
</tbody>
|
155
|
+
</table>
|
156
|
+
</div>
|
157
|
+
</div>
|
158
|
+
{% endmacro %}
|
159
|
+
|
160
|
+
{% macro frequencies(variant) %}
|
161
|
+
<div class="card panel-default">
|
162
|
+
<div class="panel-heading">Frequencies</div>
|
163
|
+
<div class="card-body">
|
164
|
+
<table class="table">
|
165
|
+
<thead class="thead table-light">
|
166
|
+
<tr>
|
167
|
+
<th scope="col">Source</th>
|
168
|
+
<th scope="col">Frequency</th>
|
169
|
+
</tr>
|
170
|
+
</thead>
|
171
|
+
<tbody>
|
172
|
+
{% for freq_name, value, link in variant.frequencies %}
|
173
|
+
<tr>
|
174
|
+
<td>
|
175
|
+
{% if link %}
|
176
|
+
<a href="{{ link }}" target="_blank" rel="noopener" referrerpolicy="no-referrer">{{ freq_name }}</a>
|
177
|
+
{% else %}
|
178
|
+
{{ freq_name }}
|
179
|
+
{% endif %}
|
180
|
+
</td>
|
181
|
+
<td>
|
182
|
+
{% if value %}
|
183
|
+
<span class="badge bg-secondary">{{ value|human_decimal }}</span>
|
184
|
+
{% else %}
|
185
|
+
-
|
186
|
+
{% endif %}
|
187
|
+
</td>
|
188
|
+
</tr>
|
189
|
+
{% endfor %}
|
190
|
+
</tbody>
|
139
191
|
</table>
|
140
192
|
</div>
|
141
193
|
</div>
|
@@ -175,15 +175,13 @@ def update_variant_case_panels(case_obj: dict, variant_obj: dict):
|
|
175
175
|
The case_obj should be up-to-date first. Call update_case_panels() as needed in context:
|
176
176
|
to save some resources we do not call it here for each variant.
|
177
177
|
"""
|
178
|
-
|
178
|
+
variant_obj["case_panels"] = []
|
179
179
|
variant_panel_names = variant_obj.get("panels") or []
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
if
|
184
|
-
|
185
|
-
|
186
|
-
variant_obj["case_panels"] = case_panel_objs
|
180
|
+
for latest_panel in case_obj.get("latest_panels") or []:
|
181
|
+
if latest_panel["panel_name"] not in variant_panel_names:
|
182
|
+
continue
|
183
|
+
if not set(latest_panel["hgnc_ids"]).isdisjoint(variant_obj["hgnc_ids"]):
|
184
|
+
variant_obj["case_panels"].append(latest_panel)
|
187
185
|
|
188
186
|
|
189
187
|
def get_extra_info(gene_panels: list) -> Dict[int, dict]:
|
@@ -660,17 +658,15 @@ def callers(variant_obj):
|
|
660
658
|
return list(calls)
|
661
659
|
|
662
660
|
|
663
|
-
def associate_variant_genes_with_case_panels(
|
661
|
+
def associate_variant_genes_with_case_panels(case_obj: Dict, variant_obj: Dict) -> None:
|
664
662
|
"""Add associated gene panels to each gene in variant object"""
|
665
663
|
|
666
664
|
genes = variant_obj.get("genes", [])
|
667
|
-
gene_panels = variant_obj.get("case_panels", [])
|
668
665
|
|
669
666
|
for gene in genes:
|
670
667
|
hgnc_id = gene["hgnc_id"]
|
671
668
|
matching_panels = []
|
672
|
-
for panel in
|
673
|
-
|
674
|
-
if hgnc_id in genes_on_panel:
|
669
|
+
for panel in case_obj.get("latest_panels", []):
|
670
|
+
if hgnc_id in panel["hgnc_ids"]:
|
675
671
|
matching_panels.append(panel["panel_name"])
|
676
672
|
gene["associated_gene_panels"] = matching_panels
|
@@ -51,6 +51,8 @@ from scout.server.utils import (
|
|
51
51
|
from .forms import FILTERSFORMCLASS, CancerSvFiltersForm, FusionFiltersForm, SvFiltersForm
|
52
52
|
from .utils import update_case_panels
|
53
53
|
|
54
|
+
NUM = re.compile(r"\d+")
|
55
|
+
|
54
56
|
LOG = logging.getLogger(__name__)
|
55
57
|
|
56
58
|
|
@@ -938,6 +940,10 @@ def parse_variant(
|
|
938
940
|
if not "end_chrom" in variant_obj:
|
939
941
|
variant_obj["end_chrom"] = variant_obj["chromosome"]
|
940
942
|
|
943
|
+
# common motif count for STR variants
|
944
|
+
|
945
|
+
variant_obj["str_mc"] = get_str_mc(variant_obj)
|
946
|
+
|
941
947
|
# variant level links shown on variants page
|
942
948
|
variant_obj["cosmic_links"] = cosmic_links(variant_obj)
|
943
949
|
variant_obj["str_source_link"] = str_source_link(variant_obj)
|
@@ -959,6 +965,31 @@ def parse_variant(
|
|
959
965
|
return variant_obj
|
960
966
|
|
961
967
|
|
968
|
+
def get_str_mc(variant_obj: dict) -> Optional[int]:
|
969
|
+
"""Return variant Short Tandem Repeat motif count, either as given by its ALT MC value
|
970
|
+
from the variant FORMAT field, or as a number given in the ALT on the form
|
971
|
+
'<STR123>'.
|
972
|
+
"""
|
973
|
+
|
974
|
+
alt_mc = None
|
975
|
+
if variant_obj["alternative"] == ".":
|
976
|
+
return alt_mc
|
977
|
+
|
978
|
+
for sample in variant_obj["samples"]:
|
979
|
+
if sample["genotype_call"] in ["./.", ".|", "0/0", "0|0"]:
|
980
|
+
continue
|
981
|
+
alt_mc = sample.get("alt_mc")
|
982
|
+
if alt_mc:
|
983
|
+
return alt_mc
|
984
|
+
|
985
|
+
alt_num = NUM.match(variant_obj["alternative"])
|
986
|
+
if alt_num:
|
987
|
+
alt_mc = int(alt_num)
|
988
|
+
return alt_mc
|
989
|
+
|
990
|
+
return None
|
991
|
+
|
992
|
+
|
962
993
|
def download_str_variants(case_obj, variant_objs):
|
963
994
|
"""Download filtered STR variants for a case to a CSV file
|
964
995
|
|
@@ -995,9 +1026,7 @@ def download_str_variants(case_obj, variant_objs):
|
|
995
1026
|
variant_line.append(
|
996
1027
|
variant.get("str_display_ru", variant.get("str_ru", ""))
|
997
1028
|
) # Reference repeat unit
|
998
|
-
variant_line.append(
|
999
|
-
variant.get("alternative", "").replace("STR", "").replace("<", "").replace(">", "")
|
1000
|
-
) # Estimated size
|
1029
|
+
variant_line.append(get_str_mc(variant) or ".") # Estimated size
|
1001
1030
|
variant_line.append(str(variant.get("str_ref", ""))) # Reference size
|
1002
1031
|
variant_line.append(str(variant.get("str_status", ""))) # Status
|
1003
1032
|
gt_cell = ""
|