scout-browser 4.79.1__py3-none-any.whl → 4.81__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/variant.py +2 -2
- scout/constants/__init__.py +3 -0
- scout/constants/clinvar.py +3 -0
- scout/constants/indexes.py +14 -12
- scout/constants/variants_export.py +11 -0
- scout/models/case/case_loading_models.py +45 -23
- scout/models/clinvar.py +1 -0
- scout/parse/variant/variant.py +27 -23
- scout/server/blueprints/api/views.py +12 -0
- scout/server/blueprints/cases/controllers.py +72 -6
- scout/server/blueprints/cases/templates/cases/case.html +1 -22
- scout/server/blueprints/cases/templates/cases/case_bionano.html +2 -0
- scout/server/blueprints/cases/templates/cases/case_report.html +135 -129
- scout/server/blueprints/cases/templates/cases/case_sma.html +2 -0
- scout/server/blueprints/cases/templates/cases/collapsible_actionbar.html +12 -2
- scout/server/blueprints/cases/templates/cases/gene_panel.html +45 -22
- scout/server/blueprints/cases/templates/cases/utils.html +52 -14
- scout/server/blueprints/cases/views.py +22 -0
- scout/server/blueprints/clinvar/controllers.py +2 -0
- scout/server/blueprints/clinvar/form.py +5 -0
- scout/server/blueprints/clinvar/templates/clinvar/multistep_add_variant.html +30 -5
- scout/server/blueprints/diagnoses/templates/diagnoses/diagnoses.html +1 -1
- scout/server/blueprints/institutes/static/select2_darktheme.css +62 -0
- scout/server/blueprints/institutes/templates/overview/institute_settings.html +1 -1
- scout/server/blueprints/panels/templates/panels/panel.html +15 -1
- 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 +5 -1
- scout/server/blueprints/variant/controllers.py +5 -2
- scout/server/blueprints/variant/templates/variant/variant_details.html +32 -20
- scout/server/blueprints/variants/controllers.py +179 -93
- scout/server/blueprints/variants/templates/variants/components.html +5 -4
- scout/server/blueprints/variants/templates/variants/fusion-variants.html +1 -1
- scout/server/blueprints/variants/views.py +30 -15
- scout/server/config.py +3 -0
- scout/server/templates/report_base.html +3 -3
- scout/server/templates/utils.html +68 -38
- scout/server/utils.py +25 -3
- {scout_browser-4.79.1.dist-info → scout_browser-4.81.dist-info}/METADATA +1 -1
- {scout_browser-4.79.1.dist-info → scout_browser-4.81.dist-info}/RECORD +45 -45
- scout/server/blueprints/cases/templates/cases/clinvar.html +0 -48
- {scout_browser-4.79.1.dist-info → scout_browser-4.81.dist-info}/LICENSE +0 -0
- {scout_browser-4.79.1.dist-info → scout_browser-4.81.dist-info}/WHEEL +0 -0
- {scout_browser-4.79.1.dist-info → scout_browser-4.81.dist-info}/entry_points.txt +0 -0
- {scout_browser-4.79.1.dist-info → scout_browser-4.81.dist-info}/top_level.txt +0 -0
@@ -145,7 +145,7 @@
|
|
145
145
|
<div class="card panel-default">
|
146
146
|
<div class="panel-heading d-flex justify-content-between">
|
147
147
|
<a href="https://github.com/moonso/loqusdb" target="_blank">Local observations</a>
|
148
|
-
<span data-bs-toggle="tooltip" title="Nr of observations is the total number of
|
148
|
+
<span data-bs-toggle="tooltip" title="Nr of observations is the total number of cases where the variant occurs in the loqusdb instance. Names of collaborator cases are shown.">?</span>
|
149
149
|
</div>
|
150
150
|
<div class="card-body">
|
151
151
|
<table class="table">
|
@@ -165,27 +165,39 @@
|
|
165
165
|
<td>{{ obs.homozygote|default('N/A') }}</td>
|
166
166
|
<td>{{ obs.total|default('N/A') }}</td>
|
167
167
|
</tr>
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
168
|
+
{% if obs.cases or obs.observations == 1 %}
|
169
|
+
<tr>
|
170
|
+
<td colspan="4">
|
171
|
+
{% if obs.observations == 1 %}
|
172
|
+
{% if obs.case_match == True %}
|
173
|
+
Observed only in this case
|
174
|
+
<span id="case_match_tooltip" data-bs-toggle='tooltip' title="Subsequent analysis of the same individual or multiple occurrences within the same family will usually not result in an increased observation count, even if performed by different institutes.">
|
175
|
+
<i class="mx-1 fas fa-info-circle"></i>
|
176
|
+
</span>
|
177
|
+
{% elif obs.case_match == False %}
|
178
|
+
Observed in one other case
|
179
|
+
<span id="case_mismatch_tooltip" data-bs-toggle='tooltip' title="Low sequencing quality for the variant or previous loqusdb upload of data from the same individuals may prevent the current case from occurring in loqusdb">
|
180
|
+
<i class="mx-1 fas fa-info-circle"></i>
|
181
|
+
</span>
|
182
|
+
{% endif %}
|
183
|
+
{% endif %}
|
184
|
+
{% for data in obs.cases %}
|
185
|
+
{% if data.variant and data.variant.category == "snv"%}
|
186
|
+
<a class="badge rounded-pill bg-light text-dark" target="_blank" href="{{ url_for('variant.variant', institute_id=data.case.owner, case_name=data.case.display_name, variant_id=data.variant._id) }}">{{ data.case.display_name }}</a>
|
187
|
+
{% elif data.variant and data.variant.category == "sv"%}
|
188
|
+
<a class="badge rounded-pill bg-light text-dark" target="_blank" href="{{ url_for('variant.sv_variant', institute_id=data.case.owner, case_name=data.case.display_name, variant_id=data.variant._id) }}">{{ data.case.display_name }}</a>
|
189
|
+
{% else %}
|
190
|
+
<span data-bs-toggle="tooltip" title="Missing link, this might be caused by variants not loaded after a rerun or inexact SV matching.">
|
177
191
|
<span class="ml-3 badge rounded-pill bg-light text-dark">{{ data.case.display_name }}</span>
|
178
|
-
|
179
|
-
{% endfor %}
|
180
|
-
{% if obs.cases|length > 10 %}
|
181
|
-
+ more
|
192
|
+
</span>
|
182
193
|
{% endif %}
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
194
|
+
{% endfor %}
|
195
|
+
{% if obs.cases|length > 10 %}
|
196
|
+
+ more
|
197
|
+
{% endif %}
|
198
|
+
</td>
|
199
|
+
</tr>
|
200
|
+
{% endif %}
|
189
201
|
{% endfor %}
|
190
202
|
</tbody>
|
191
203
|
</table>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import decimal
|
2
2
|
import logging
|
3
3
|
import re
|
4
|
-
from typing import Any, Dict
|
4
|
+
from typing import Any, Dict, List, Optional
|
5
5
|
|
6
6
|
import bson
|
7
7
|
from flask import Response, flash, session, url_for
|
@@ -16,20 +16,22 @@ from scout.adapter import MongoAdapter
|
|
16
16
|
from scout.constants import (
|
17
17
|
ACMG_COMPLETE_MAP,
|
18
18
|
ACMG_MAP,
|
19
|
+
CANCER_EXPORT_HEADER,
|
19
20
|
CANCER_SPECIFIC_VARIANT_DISMISS_OPTIONS,
|
20
21
|
CANCER_TIER_OPTIONS,
|
21
22
|
CHROMOSOMES,
|
22
23
|
CHROMOSOMES_38,
|
23
24
|
CLINSIG_MAP,
|
24
25
|
DISMISS_VARIANT_OPTIONS,
|
26
|
+
EXPORT_HEADER,
|
25
27
|
EXPORTED_VARIANTS_LIMIT,
|
28
|
+
FUSION_EXPORT_HEADER,
|
26
29
|
MANUAL_RANK_OPTIONS,
|
27
30
|
MOSAICISM_OPTIONS,
|
28
31
|
SPIDEX_HUMAN,
|
29
32
|
VARIANT_FILTERS,
|
30
33
|
VARIANTS_TARGET_FROM_CATEGORY,
|
31
34
|
)
|
32
|
-
from scout.constants.variants_export import CANCER_EXPORT_HEADER, EXPORT_HEADER
|
33
35
|
from scout.server.blueprints.variant.utils import (
|
34
36
|
callers,
|
35
37
|
clinsig_human,
|
@@ -331,17 +333,17 @@ def fusion_variants(
|
|
331
333
|
if clinical_var_obj is not None:
|
332
334
|
variant_obj["clinical_assessments"] = get_manual_assessments(clinical_var_obj)
|
333
335
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
case_dismissed_vars=case_dismissed_vars,
|
342
|
-
)
|
336
|
+
parsed_variant = parse_variant(
|
337
|
+
store,
|
338
|
+
institute_obj,
|
339
|
+
case_obj,
|
340
|
+
variant_obj,
|
341
|
+
genome_build=genome_build,
|
342
|
+
case_dismissed_vars=case_dismissed_vars,
|
343
343
|
)
|
344
344
|
|
345
|
+
variants.append(parsed_variant)
|
346
|
+
|
345
347
|
return {"variants": variants, "more_variants": more_variants}
|
346
348
|
|
347
349
|
|
@@ -958,7 +960,7 @@ def parse_variant(
|
|
958
960
|
|
959
961
|
|
960
962
|
def download_str_variants(case_obj, variant_objs):
|
961
|
-
"""Download filtered STR variants for a case to
|
963
|
+
"""Download filtered STR variants for a case to a CSV file
|
962
964
|
|
963
965
|
Args:
|
964
966
|
case_obj(dict)
|
@@ -1024,21 +1026,17 @@ def download_str_variants(case_obj, variant_objs):
|
|
1024
1026
|
)
|
1025
1027
|
|
1026
1028
|
|
1027
|
-
def download_variants(
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1031
|
-
store(adapter.MongoAdapter)
|
1032
|
-
case_obj(dict)
|
1033
|
-
variant_objs(PyMongo cursor)
|
1029
|
+
def download_variants(
|
1030
|
+
store: MongoAdapter, case_obj: dict, variant_objs: CursorType, category: Optional[str] = None
|
1031
|
+
) -> Response:
|
1032
|
+
"""Download filtered variants for a case to a CSV file
|
1034
1033
|
|
1035
1034
|
Returns:
|
1036
1035
|
an HTTP response containing a csv file
|
1037
1036
|
"""
|
1038
|
-
document_header = variants_export_header(case_obj)
|
1039
|
-
export_lines = []
|
1037
|
+
document_header = variants_export_header(case_obj, category)
|
1040
1038
|
export_lines = variant_export_lines(
|
1041
|
-
store, case_obj, variant_objs.limit(EXPORTED_VARIANTS_LIMIT)
|
1039
|
+
store, case_obj, variant_objs.limit(EXPORTED_VARIANTS_LIMIT), category
|
1042
1040
|
)
|
1043
1041
|
|
1044
1042
|
def generate(header, lines):
|
@@ -1060,85 +1058,168 @@ def download_variants(store, case_obj, variant_objs):
|
|
1060
1058
|
)
|
1061
1059
|
|
1062
1060
|
|
1063
|
-
def
|
1061
|
+
def variant_export_lines_common(store: MongoAdapter, variant: dict, case_obj: dict) -> list:
|
1062
|
+
"""
|
1063
|
+
Get common variant info to be exported. Returns a list to be merged into a string
|
1064
|
+
in suitable export format.
|
1065
|
+
"""
|
1066
|
+
variant_line = []
|
1067
|
+
position = variant["position"]
|
1068
|
+
change = variant["reference"] + ">" + variant["alternative"]
|
1069
|
+
variant_line.append(variant.get("rank_score", "N/A"))
|
1070
|
+
variant_line.append(variant["chromosome"])
|
1071
|
+
variant_line.append(position)
|
1072
|
+
variant_line.append(change)
|
1073
|
+
variant_line.append("_".join([str(position), change]))
|
1074
|
+
|
1075
|
+
gene_list: List[dict] = variant.get("genes", [])
|
1076
|
+
|
1077
|
+
if gene_list:
|
1078
|
+
gene_info = variant_export_genes_info(store, gene_list, case_obj.get("genome_build"))
|
1079
|
+
variant_line += gene_info
|
1080
|
+
else:
|
1081
|
+
empty_col = 0
|
1082
|
+
while empty_col < 5:
|
1083
|
+
variant_line.append(
|
1084
|
+
"-"
|
1085
|
+
) # empty HGNC id, empty gene name, two empty transcripts columns, and consequence
|
1086
|
+
empty_col += 1
|
1087
|
+
|
1088
|
+
if variant.get("cadd_score"):
|
1089
|
+
variant_line.append(round(variant["cadd_score"], 2))
|
1090
|
+
else:
|
1091
|
+
variant_line.append("N/A")
|
1092
|
+
|
1093
|
+
if variant.get("gnomad_frequency"):
|
1094
|
+
variant_line.append(round(variant["gnomad_frequency"], 5))
|
1095
|
+
else:
|
1096
|
+
variant_line.append("N/A")
|
1097
|
+
|
1098
|
+
return variant_line
|
1099
|
+
|
1100
|
+
|
1101
|
+
def get_fusion_variant_field(variant: dict, field: str) -> str:
|
1102
|
+
"""Get fusion variant fields that could be from multiple fusion partners.
|
1103
|
+
Split if comma separated, and join with 'or' sign, so as not to interfere with csv file generation.
|
1104
|
+
Avoid empty values and use "N/A" instead.
|
1105
|
+
"""
|
1106
|
+
value = variant.get(field, "N/A")
|
1107
|
+
if "," in value:
|
1108
|
+
value = value.split(",")
|
1109
|
+
if isinstance(value, list):
|
1110
|
+
value = " | ".join(value)
|
1111
|
+
if value is None or value == []:
|
1112
|
+
value = "N/A"
|
1113
|
+
return value
|
1114
|
+
|
1115
|
+
|
1116
|
+
def get_fusion_exons(variant: dict) -> str:
|
1117
|
+
"""Get RNAfusion specific variant exons for all genes/transcripts listed. Join with pipe 'or' character."""
|
1118
|
+
exon = ""
|
1119
|
+
for gene in variant.get("genes", []):
|
1120
|
+
for transcript in gene.get("transcripts", []):
|
1121
|
+
if bool(transcript.get("exon")):
|
1122
|
+
if exon:
|
1123
|
+
exon = exon + " | "
|
1124
|
+
exon = exon + transcript["exon"]
|
1125
|
+
|
1126
|
+
return exon
|
1127
|
+
|
1128
|
+
|
1129
|
+
def variant_export_lines_fusion(variant: dict, case_obj: dict) -> list:
|
1130
|
+
"""Get RNAfusion specific variant info to be exported. Returns a list to be merged into a string
|
1131
|
+
in suitable export format.
|
1132
|
+
"""
|
1133
|
+
variant_line = []
|
1134
|
+
|
1135
|
+
for field in ["fusion_genes", "orientation", "frame_status", "found_db"]:
|
1136
|
+
variant_line.append(get_fusion_variant_field(variant, field))
|
1137
|
+
|
1138
|
+
variant_line.append(get_fusion_exons(variant))
|
1139
|
+
|
1140
|
+
variant_gts = variant["samples"] # list of coverage and gt calls for case samples
|
1141
|
+
for individual in case_obj["individuals"]:
|
1142
|
+
for variant_gt in variant_gts:
|
1143
|
+
if individual["individual_id"] != variant_gt["sample_id"]:
|
1144
|
+
continue
|
1145
|
+
variant_line.append(variant_gt.get("read_depth", "N/A"))
|
1146
|
+
variant_line.append(variant_gt.get("split_read", "N/A"))
|
1147
|
+
variant_line.append(variant_gt.get("ffpm", "N/A"))
|
1148
|
+
|
1149
|
+
return variant_line
|
1150
|
+
|
1151
|
+
|
1152
|
+
def variant_export_lines_cancer(variant: dict) -> list:
|
1153
|
+
"""
|
1154
|
+
Get cancer specific variant info to be exported. Returns a list to be merged into a string
|
1155
|
+
in suitable export format.
|
1156
|
+
"""
|
1157
|
+
variant_line = []
|
1158
|
+
|
1159
|
+
# Add cancer and normal VAFs
|
1160
|
+
for sample in ["tumor", "normal"]:
|
1161
|
+
allele = variant.get(sample)
|
1162
|
+
if not allele:
|
1163
|
+
variant_line.append("-")
|
1164
|
+
continue
|
1165
|
+
alt_freq = round(allele.get("alt_freq", 0), 4)
|
1166
|
+
alt_depth = allele.get("alt_depth")
|
1167
|
+
ref_depth = allele.get("ref_depth")
|
1168
|
+
|
1169
|
+
vaf_sample = f"{alt_freq} ({alt_depth}|{ref_depth})"
|
1170
|
+
variant_line.append(vaf_sample)
|
1171
|
+
|
1172
|
+
# ADD eventual COSMIC ID
|
1173
|
+
cosmic_ids = variant.get("cosmic_ids") or ["-"]
|
1174
|
+
variant_line.append(" | ".join(cosmic_ids))
|
1175
|
+
|
1176
|
+
return variant_line
|
1177
|
+
|
1178
|
+
|
1179
|
+
def variant_export_lines_rare(variant: dict, case_obj: dict) -> list:
|
1180
|
+
"""
|
1181
|
+
Get generic rare disease variant info to be exported. Returns a list to be merged into a string
|
1182
|
+
in suitable export format.
|
1183
|
+
"""
|
1184
|
+
variant_line = []
|
1185
|
+
|
1186
|
+
variant_gts = variant["samples"] # list of coverage and gt calls for case samples
|
1187
|
+
for individual in case_obj["individuals"]:
|
1188
|
+
for variant_gt in variant_gts:
|
1189
|
+
if individual["individual_id"] != variant_gt["sample_id"]:
|
1190
|
+
continue
|
1191
|
+
|
1192
|
+
variant_line.append(variant_gt["genotype_call"])
|
1193
|
+
# gather coverage info
|
1194
|
+
variant_line.append(variant_gt["allele_depths"][0]) # AD reference
|
1195
|
+
variant_line.append(variant_gt["allele_depths"][1]) # AD alternate
|
1196
|
+
# gather genotype quality info
|
1197
|
+
variant_line.append(variant_gt["genotype_quality"])
|
1198
|
+
|
1199
|
+
return variant_line
|
1200
|
+
|
1201
|
+
|
1202
|
+
def variant_export_lines(
|
1203
|
+
store: MongoAdapter, case_obj: dict, variants_query: CursorType, category: Optional[str] = None
|
1204
|
+
) -> List[str]:
|
1064
1205
|
"""Get variants info to be exported to file, one list (line) per variant.
|
1065
|
-
|
1066
|
-
store(scout.adapter.MongoAdapter)
|
1067
|
-
case_obj(scout.models.Case)
|
1068
|
-
variants_query: a list of variant objects, each one is a dictionary
|
1206
|
+
|
1069
1207
|
Returns:
|
1070
1208
|
export_variants: a list of strings. Each string of the list corresponding to the fields
|
1071
|
-
of a variant to be exported to file, separated by comma
|
1209
|
+
of a variant to be exported to file, separated by comma.
|
1072
1210
|
"""
|
1073
1211
|
|
1074
1212
|
export_variants = []
|
1075
1213
|
|
1076
1214
|
for variant in variants_query:
|
1077
|
-
variant_line =
|
1078
|
-
position = variant["position"]
|
1079
|
-
change = variant["reference"] + ">" + variant["alternative"]
|
1080
|
-
variant_line.append(variant.get("rank_score", "N/A"))
|
1081
|
-
variant_line.append(variant["chromosome"])
|
1082
|
-
variant_line.append(position)
|
1083
|
-
variant_line.append(change)
|
1084
|
-
variant_line.append("_".join([str(position), change]))
|
1085
|
-
|
1086
|
-
# gather gene info:
|
1087
|
-
gene_list = variant.get("genes") # this is a list of gene objects
|
1088
|
-
|
1089
|
-
# if variant is in genes
|
1090
|
-
if gene_list:
|
1091
|
-
gene_info = variant_export_genes_info(store, gene_list, case_obj.get("genome_build"))
|
1092
|
-
variant_line += gene_info
|
1093
|
-
else:
|
1094
|
-
empty_col = 0
|
1095
|
-
while empty_col < 4:
|
1096
|
-
variant_line.append(
|
1097
|
-
"-"
|
1098
|
-
) # empty HGNC id, empty gene name and empty transcripts columns
|
1099
|
-
empty_col += 1
|
1100
|
-
|
1101
|
-
if variant.get("cadd_score"):
|
1102
|
-
variant_line.append(round(variant["cadd_score"], 2))
|
1103
|
-
else:
|
1104
|
-
variant_line.append("N/A")
|
1105
|
-
|
1106
|
-
if variant.get("gnomad_frequency"):
|
1107
|
-
variant_line.append(round(variant["gnomad_frequency"], 5))
|
1108
|
-
else:
|
1109
|
-
variant_line.append("N/A")
|
1110
|
-
|
1111
|
-
if case_obj.get("track") == "cancer":
|
1112
|
-
# Add cancer and normal VAFs
|
1113
|
-
for sample in ["tumor", "normal"]:
|
1114
|
-
allele = variant.get(sample)
|
1115
|
-
if not allele:
|
1116
|
-
variant_line.append("-")
|
1117
|
-
continue
|
1118
|
-
alt_freq = round(allele.get("alt_freq", 0), 4)
|
1119
|
-
alt_depth = allele.get("alt_depth")
|
1120
|
-
ref_depth = allele.get("ref_depth")
|
1121
|
-
|
1122
|
-
vaf_sample = f"{alt_freq} ({alt_depth}|{ref_depth})"
|
1123
|
-
variant_line.append(vaf_sample)
|
1124
|
-
|
1125
|
-
# ADD eventual COSMIC ID
|
1126
|
-
cosmic_ids = variant.get("cosmic_ids") or ["-"]
|
1127
|
-
variant_line.append(" | ".join(cosmic_ids))
|
1215
|
+
variant_line = variant_export_lines_common(store, variant, case_obj)
|
1128
1216
|
|
1217
|
+
if category == "fusion":
|
1218
|
+
variant_line.extend(variant_export_lines_fusion(variant, case_obj))
|
1219
|
+
elif case_obj.get("track") == "cancer":
|
1220
|
+
variant_line.extend(variant_export_lines_cancer(variant))
|
1129
1221
|
else:
|
1130
|
-
|
1131
|
-
for individual in case_obj["individuals"]:
|
1132
|
-
for variant_gt in variant_gts:
|
1133
|
-
if individual["individual_id"] != variant_gt["sample_id"]:
|
1134
|
-
continue
|
1135
|
-
|
1136
|
-
variant_line.append(variant_gt["genotype_call"])
|
1137
|
-
# gather coverage info
|
1138
|
-
variant_line.append(variant_gt["allele_depths"][0]) # AD reference
|
1139
|
-
variant_line.append(variant_gt["allele_depths"][1]) # AD alternate
|
1140
|
-
# gather genotype quality info
|
1141
|
-
variant_line.append(variant_gt["genotype_quality"])
|
1222
|
+
variant_line.extend(variant_export_lines_rare(variant, case_obj))
|
1142
1223
|
|
1143
1224
|
variant_line = [str(i) for i in variant_line]
|
1144
1225
|
export_variants.append(",".join(variant_line))
|
@@ -1224,16 +1305,20 @@ def variant_export_genes_info(store, gene_list, genome_build="37"):
|
|
1224
1305
|
return gene_info
|
1225
1306
|
|
1226
1307
|
|
1227
|
-
def variants_export_header(case_obj):
|
1308
|
+
def variants_export_header(case_obj: dict, category: str = "snv") -> List[str]:
|
1228
1309
|
"""Returns a header for the CSV file with the filtered variants to be exported.
|
1229
1310
|
Args:
|
1230
1311
|
case_obj(scout.models.Case)
|
1312
|
+
category: Variant category to prepare export for e.g. "fusion"
|
1231
1313
|
Returns:
|
1232
1314
|
header: includes the fields defined in scout.constants.variants_export EXPORT_HEADER
|
1233
1315
|
+ AD_reference, AD_alternate, GT_quality for each sample analysed for a case
|
1234
1316
|
"""
|
1317
|
+
|
1235
1318
|
header = []
|
1236
|
-
if
|
1319
|
+
if category == "fusion":
|
1320
|
+
header = header + FUSION_EXPORT_HEADER
|
1321
|
+
elif case_obj.get("track") == "cancer":
|
1237
1322
|
header = header + CANCER_EXPORT_HEADER
|
1238
1323
|
else:
|
1239
1324
|
header = header + EXPORT_HEADER
|
@@ -1244,6 +1329,7 @@ def variants_export_header(case_obj):
|
|
1244
1329
|
header.append("AD_reference_" + display_name) # Add AD reference field for a sample
|
1245
1330
|
header.append("AD_alternate_" + display_name) # Add AD alternate field for a sample
|
1246
1331
|
header.append("GT_quality_" + display_name) # Add Genotype quality field for a sample
|
1332
|
+
|
1247
1333
|
return header
|
1248
1334
|
|
1249
1335
|
|
@@ -34,11 +34,12 @@
|
|
34
34
|
href="{{ url_for('genes.gene', hgnc_id=gene.hgnc_id) }}">{{ gene.hgnc_symbol or gene.hgnc_id }}
|
35
35
|
</a> <br>
|
36
36
|
{% endfor %}
|
37
|
-
{% else %}
|
38
|
-
{% for symbol in variant.fusion_genes %}
|
39
|
-
{{ symbol }} <br>
|
40
|
-
{% endfor %}
|
41
37
|
{% endif %}
|
38
|
+
{% for symbol in variant.fusion_genes %}
|
39
|
+
{% if symbol not in variant.hgnc_symbols %}
|
40
|
+
{{ symbol }} <br>
|
41
|
+
{% endif %}
|
42
|
+
{% endfor %}
|
42
43
|
</div>
|
43
44
|
{% endmacro %}
|
44
45
|
|
@@ -127,7 +127,7 @@ onsubmit="return validateForm()">
|
|
127
127
|
{% if variant.genes %}
|
128
128
|
{% for gene in variant.genes %}
|
129
129
|
{% for transcript in gene.transcripts %}
|
130
|
-
<div>{{ transcript.exon|int }} </div>
|
130
|
+
<div>{% if "exon" in transcript %}{{ transcript.exon|int }}{% endif %} </div>
|
131
131
|
{% endfor %}
|
132
132
|
{% endfor %}
|
133
133
|
{% endif %}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""Views for the variants"""
|
2
|
+
|
2
3
|
import io
|
3
4
|
import logging
|
4
5
|
|
@@ -122,7 +123,6 @@ def variants(institute_id, case_name):
|
|
122
123
|
return redirect(request.referrer)
|
123
124
|
|
124
125
|
hgnc_symbols_set = set(form.hgnc_symbols.data)
|
125
|
-
LOG.debug("Symbols prior to upload: {0}".format(hgnc_symbols_set))
|
126
126
|
new_hgnc_symbols = controllers.upload_panel(store, institute_id, case_name, stream)
|
127
127
|
hgnc_symbols_set.update(new_hgnc_symbols)
|
128
128
|
form.hgnc_symbols.data = hgnc_symbols_set
|
@@ -131,9 +131,12 @@ def variants(institute_id, case_name):
|
|
131
131
|
|
132
132
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
133
133
|
|
134
|
-
|
134
|
+
genome_build = "38" if "38" in str(case_obj.get("genome_build", "37")) else "37"
|
135
|
+
cytobands = store.cytoband_by_chrom(genome_build)
|
135
136
|
|
136
|
-
variants_query = store.variants(
|
137
|
+
variants_query = store.variants(
|
138
|
+
case_obj["_id"], query=form.data, category=category, build=genome_build
|
139
|
+
)
|
137
140
|
result_size = store.count_variants(case_obj["_id"], form.data, None, category)
|
138
141
|
|
139
142
|
if request.form.get("export"):
|
@@ -217,12 +220,15 @@ def str_variants(institute_id, case_name):
|
|
217
220
|
|
218
221
|
controllers.activate_case(store, institute_obj, case_obj, current_user)
|
219
222
|
|
220
|
-
|
223
|
+
genome_build = "38" if "38" in str(case_obj.get("genome_build", "37")) else "37"
|
224
|
+
cytobands = store.cytoband_by_chrom(genome_build)
|
221
225
|
|
222
226
|
query = form.data
|
223
227
|
query["variant_type"] = variant_type
|
224
228
|
|
225
|
-
variants_query = store.variants(
|
229
|
+
variants_query = store.variants(
|
230
|
+
case_obj["_id"], category=category, query=query, build=genome_build
|
231
|
+
).sort(
|
226
232
|
[
|
227
233
|
("str_repid", pymongo.ASCENDING),
|
228
234
|
("chromosome", pymongo.ASCENDING),
|
@@ -297,12 +303,14 @@ def sv_variants(institute_id, case_name):
|
|
297
303
|
# Populate chromosome select choices
|
298
304
|
controllers.populate_chrom_choices(form, case_obj)
|
299
305
|
|
300
|
-
genome_build = "38" if "38" in str(case_obj.get("genome_build")) else "37"
|
306
|
+
genome_build = "38" if "38" in str(case_obj.get("genome_build", "37")) else "37"
|
301
307
|
cytobands = store.cytoband_by_chrom(genome_build)
|
302
308
|
|
303
309
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
304
310
|
|
305
|
-
variants_query = store.variants(
|
311
|
+
variants_query = store.variants(
|
312
|
+
case_obj["_id"], category=category, query=form.data, build=genome_build
|
313
|
+
)
|
306
314
|
|
307
315
|
result_size = store.count_variants(case_obj["_id"], form.data, None, category)
|
308
316
|
|
@@ -389,12 +397,14 @@ def mei_variants(institute_id, case_name):
|
|
389
397
|
# populate available panel choices
|
390
398
|
form.gene_panels.choices = controllers.gene_panel_choices(store, institute_obj, case_obj)
|
391
399
|
|
392
|
-
genome_build = "38" if "38" in str(case_obj.get("genome_build")) else "37"
|
400
|
+
genome_build = "38" if "38" in str(case_obj.get("genome_build", "37")) else "37"
|
393
401
|
cytobands = store.cytoband_by_chrom(genome_build)
|
394
402
|
|
395
403
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
396
404
|
|
397
|
-
variants_query = store.variants(
|
405
|
+
variants_query = store.variants(
|
406
|
+
case_obj["_id"], category=category, query=form.data, build=genome_build
|
407
|
+
)
|
398
408
|
|
399
409
|
result_size = store.count_variants(case_obj["_id"], form.data, None, category)
|
400
410
|
|
@@ -496,7 +506,8 @@ def cancer_variants(institute_id, case_name):
|
|
496
506
|
controllers.populate_chrom_choices(form, case_obj)
|
497
507
|
|
498
508
|
form.gene_panels.choices = controllers.gene_panel_choices(store, institute_obj, case_obj)
|
499
|
-
|
509
|
+
|
510
|
+
genome_build = "38" if "38" in str(case_obj.get("genome_build", "37")) else "37"
|
500
511
|
cytobands = store.cytoband_by_chrom(genome_build)
|
501
512
|
|
502
513
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
@@ -576,12 +587,14 @@ def cancer_sv_variants(institute_id, case_name):
|
|
576
587
|
# Populate chromosome select choices
|
577
588
|
controllers.populate_chrom_choices(form, case_obj)
|
578
589
|
|
579
|
-
genome_build = "38" if "38" in str(case_obj.get("genome_build")) else "37"
|
590
|
+
genome_build = "38" if "38" in str(case_obj.get("genome_build", "37")) else "37"
|
580
591
|
cytobands = store.cytoband_by_chrom(genome_build)
|
581
592
|
|
582
593
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
583
594
|
|
584
|
-
variants_query = store.variants(
|
595
|
+
variants_query = store.variants(
|
596
|
+
case_obj["_id"], category=category, query=form.data, build=genome_build
|
597
|
+
)
|
585
598
|
|
586
599
|
result_size = store.count_variants(case_obj["_id"], form.data, None, category)
|
587
600
|
|
@@ -659,18 +672,20 @@ def fusion_variants(institute_id, case_name):
|
|
659
672
|
# Populate chromosome select choices
|
660
673
|
controllers.populate_chrom_choices(form, case_obj)
|
661
674
|
|
662
|
-
genome_build = "38"
|
675
|
+
genome_build = "38" if "38" in str(case_obj.get("genome_build", "37")) else "37"
|
663
676
|
cytobands = store.cytoband_by_chrom(genome_build)
|
664
677
|
|
665
678
|
controllers.update_form_hgnc_symbols(store, case_obj, form)
|
666
679
|
|
667
|
-
variants_query = store.variants(
|
680
|
+
variants_query = store.variants(
|
681
|
+
case_obj["_id"], category=category, query=form.data, build=genome_build
|
682
|
+
)
|
668
683
|
|
669
684
|
result_size = store.count_variants(case_obj["_id"], form.data, None, category)
|
670
685
|
|
671
686
|
# if variants should be exported
|
672
687
|
if request.form.get("export"):
|
673
|
-
return controllers.download_variants(store, case_obj, variants_query)
|
688
|
+
return controllers.download_variants(store, case_obj, variants_query, category=category)
|
674
689
|
|
675
690
|
data = controllers.fusion_variants(
|
676
691
|
store, institute_obj, case_obj, variants_query, result_size, page
|
scout/server/config.py
CHANGED
@@ -41,6 +41,9 @@ ACCREDITATION_BADGE = "swedac-1926-iso17025.png"
|
|
41
41
|
# Chanjo database connection string - used by chanjo report to create coverage reports
|
42
42
|
# SQLALCHEMY_DATABASE_URI = "mysql+pymysql://test_user:test_passwordw@127.0.0.1:3306/chanjo"
|
43
43
|
|
44
|
+
# URL to an instance of Chanjo2, for generating coverage report
|
45
|
+
# CHANJO2_URL = "http://chanjo2-stage.scilifelab.se"
|
46
|
+
|
44
47
|
# Configure gens service
|
45
48
|
# GENS_HOST = "127.0.0.1"
|
46
49
|
# GENS_PORT = 5000
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
5
5
|
|
6
6
|
{% block css %}
|
7
|
-
|
7
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
8
8
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
9
9
|
<style>
|
10
10
|
tr.light-grey td{
|
@@ -22,8 +22,8 @@
|
|
22
22
|
{% endblock %}
|
23
23
|
|
24
24
|
{% block scripts %}
|
25
|
-
|
26
|
-
<script src="https://
|
25
|
+
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
|
26
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
|
27
27
|
{% endblock %}
|
28
28
|
</body>
|
29
29
|
</html>
|