scout-browser 4.89.1__py3-none-any.whl → 4.90__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.
Files changed (51) hide show
  1. scout/__version__.py +1 -1
  2. scout/adapter/mongo/hgnc.py +1 -1
  3. scout/adapter/mongo/panel.py +21 -58
  4. scout/adapter/mongo/query.py +9 -0
  5. scout/build/panel.py +36 -72
  6. scout/constants/__init__.py +28 -45
  7. scout/constants/acmg.py +76 -16
  8. scout/constants/gene_tags.py +4 -2
  9. scout/constants/panels.py +11 -0
  10. scout/constants/query_terms.py +1 -0
  11. scout/constants/variant_tags.py +58 -3
  12. scout/export/panel.py +30 -33
  13. scout/parse/panel.py +55 -51
  14. scout/server/blueprints/alignviewers/views.py +3 -0
  15. scout/server/blueprints/cases/controllers.py +4 -0
  16. scout/server/blueprints/cases/templates/cases/case_sma.html +14 -6
  17. scout/server/blueprints/cases/templates/cases/collapsible_actionbar.html +10 -2
  18. scout/server/blueprints/cases/templates/cases/matchmaker.html +12 -7
  19. scout/server/blueprints/institutes/controllers.py +11 -4
  20. scout/server/blueprints/institutes/templates/overview/causatives.html +1 -1
  21. scout/server/blueprints/institutes/templates/overview/gene_variants.html +3 -5
  22. scout/server/blueprints/institutes/templates/overview/utils.html +2 -2
  23. scout/server/blueprints/institutes/templates/overview/verified.html +1 -1
  24. scout/server/blueprints/institutes/views.py +22 -6
  25. scout/server/blueprints/omics_variants/templates/omics_variants/outliers.html +1 -1
  26. scout/server/blueprints/omics_variants/views.py +2 -0
  27. scout/server/blueprints/panels/controllers.py +8 -16
  28. scout/server/blueprints/panels/templates/panels/gene-edit.html +2 -2
  29. scout/server/blueprints/panels/templates/panels/panel.html +21 -13
  30. scout/server/blueprints/panels/templates/panels/panel_pdf_simple.html +25 -18
  31. scout/server/blueprints/panels/views.py +9 -6
  32. scout/server/blueprints/variant/templates/variant/acmg.html +28 -24
  33. scout/server/blueprints/variant/templates/variant/gene_disease_relations.html +1 -3
  34. scout/server/blueprints/variant/templates/variant/utils.html +1 -1
  35. scout/server/blueprints/variant/utils.py +1 -0
  36. scout/server/blueprints/variant/views.py +5 -2
  37. scout/server/blueprints/variants/templates/variants/cancer-sv-variants.html +7 -11
  38. scout/server/blueprints/variants/templates/variants/components.html +55 -38
  39. scout/server/blueprints/variants/templates/variants/mei-variants.html +2 -6
  40. scout/server/blueprints/variants/templates/variants/str-variants.html +8 -2
  41. scout/server/blueprints/variants/templates/variants/sv-variants.html +4 -8
  42. scout/server/blueprints/variants/templates/variants/variants.html +23 -18
  43. scout/server/blueprints/variants/views.py +6 -0
  44. scout/utils/acmg.py +155 -28
  45. scout/utils/scout_requests.py +8 -13
  46. {scout_browser-4.89.1.dist-info → scout_browser-4.90.dist-info}/METADATA +1 -1
  47. {scout_browser-4.89.1.dist-info → scout_browser-4.90.dist-info}/RECORD +51 -50
  48. {scout_browser-4.89.1.dist-info → scout_browser-4.90.dist-info}/LICENSE +0 -0
  49. {scout_browser-4.89.1.dist-info → scout_browser-4.90.dist-info}/WHEEL +0 -0
  50. {scout_browser-4.89.1.dist-info → scout_browser-4.90.dist-info}/entry_points.txt +0 -0
  51. {scout_browser-4.89.1.dist-info → scout_browser-4.90.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,6 @@
1
- {% macro variant_gene_symbols_cell(variant) %}
1
+ {% from "variant/gene_disease_relations.html" import inheritance_badge %}
2
+
3
+ {% macro variant_gene_symbols_cell(variant, inherit_palette) %}
2
4
  <div class="d-flex justify-content-between align-items-center">
3
5
  <div>
4
6
  {% if variant.hgnc_symbols|length >= 5 %}
@@ -16,7 +18,30 @@
16
18
  {% if variant.hgnc_symbols %}
17
19
  <span class="badge bg-secondary mr-3 text-white">{{ variant.hgnc_symbols|length }}</span>
18
20
  {% endif %}
19
- <span class="text-body">{{variant.hgnc_symbols|sort|join(", ")}}</span>
21
+ {% for gene in variant.genes %}
22
+ <a data-bs-toggle="tooltip" data-bs-html="true" title="
23
+ <div>
24
+ <div>
25
+ <strong>{{ gene.hgnc_symbol }}</strong>: {{ gene.description }}
26
+ </div>
27
+ {% if gene.inheritance %}
28
+ <div>
29
+ <strong>Models</strong>: {{ gene.inheritance|join(',') }}
30
+ </div>
31
+ {% endif %}
32
+ {% if gene.phenotypes %}
33
+ <div><strong>OMIM disease</strong>
34
+ {% for disease in gene.phenotypes %}
35
+ <div>
36
+ {{ disease.description }}
37
+ </div>
38
+ {% endfor %}
39
+ </div>
40
+ {% endif %}
41
+ </div>"
42
+ href="{{ url_for('genes.gene', hgnc_id=gene.hgnc_id) }}">{{ gene.hgnc_symbol or gene.hgnc_id }}
43
+ {% for model in gene.inheritance %} {{ inheritance_badge(model,inherit_palette) }}{% endfor %}</a>
44
+ {% endfor %}
20
45
  </div>
21
46
  {% endif %}
22
47
  </div>
@@ -38,8 +63,8 @@
38
63
  <th id="frame_status" style="width:8%" title="Frame status of the fusion">Frame Status</th>
39
64
  <th id="transcripts" style="width:8%" title="Transcript ID">Transcript ID</th>
40
65
  <th id="exons" style="width:4%" title="Exon Number">Exon Number</th>
41
- <th id="brealpoints" style="width:4%" title="Breakpoints">Breakpoints</th>
42
- <th id="oriantation" style="width:4%" title="Orientation">Orientation</th>
66
+ <th id="breakpoints" style="width:4%" title="Breakpoints">Breakpoints</th>
67
+ <th id="orientation" style="width:4%" title="Orientation">Orientation</th>
43
68
  </tr>
44
69
  </thead>
45
70
  {% endmacro %}
@@ -100,10 +125,20 @@
100
125
 
101
126
  {% macro variant_funct_anno_cell(variant) %}
102
127
  <div class="d-flex justify-content-between align-items-center">
103
- <div>
104
- {% if variant.category == "fusion" %}
105
- {{ variant.frame_status|lower if variant.frame_status else "-" }}
128
+ <div data-bs-toggle="tooltip" data-bs-html="true" title="<div class='text-start'>
129
+ {% if variant.functional_annotations|length >= 5 %}
130
+ Regional annotations<br>
131
+ {% if variant.missing_data %}[first 30 genes]{% endif %}
132
+ {% for annotation in variant.region_annotations|sort %}
133
+ {{ annotation }}<br>
134
+ {% endfor %}
106
135
  {% else %}
136
+ {{ variant.region_annotations|sort|join(', ') }}
137
+ {% endif %}
138
+ </div>">
139
+ {% if variant.category == "fusion" %}
140
+ {{ variant.frame_status|lower if variant.frame_status else "-" }}
141
+ {% else %}
107
142
  {% if variant.functional_annotations|length >= 5 %}
108
143
  <a class="mr-3" data-bs-toggle="collapse" href="#_functanno_{{variant._id}}" role="button" aria-expanded="false" aria-controls="_{{variant._id}}">{% if variant.missing_data %}[first 30 genes]{% else %}[...]{% endif %}</a>
109
144
  <div class="collapse" id="_functanno_{{variant._id}}">
@@ -123,26 +158,8 @@
123
158
  </div>
124
159
  {% endmacro %}
125
160
 
126
- {% macro variant_region_anno_cell(variant) %}
127
- <div class="d-flex justify-content-between align-items-center">
128
- <div>
129
- {% if variant.functional_annotations|length >= 5 %}
130
- <a class="mr-3" data-bs-toggle="collapse" href="#_regionanno_{{variant._id}}" role="button" aria-expanded="false" aria-controls="_{{variant._id}}">{% if variant.missing_data %}[first 30 genes]{% else %}[...]{% endif %}</a>
131
- <div class="collapse" id="_regionanno_{{variant._id}}">
132
- {% for annotation in variant.region_annotations|sort %}
133
- {{ annotation }}<br>
134
- {% endfor %}
135
- </div>
136
- {% else %}
137
- <div>
138
- {{ variant.region_annotations|sort|join(", ") }}
139
- </div>
140
- {% endif %}
141
- </div>
142
- </div>
143
- {% endmacro %}
144
161
 
145
- {% macro gene_cell(variant) %}
162
+ {% macro gene_cell(variant, inherit_palette) %}
146
163
  <div class="align-items-center">
147
164
  {% if variant.category == "cancer" or variant.category == "sv_cancer" %}
148
165
  <a data-bs-toggle="tooltip" data-bs-html="true" title="
@@ -191,7 +208,9 @@
191
208
  </a>
192
209
  {% endif %}
193
210
  {% else %}
211
+ {% set panel_count = variant.case_panels|rejectattr('removed')|list|count %}
194
212
  {% for gene in variant.genes %}
213
+ <div>
195
214
  <a data-bs-toggle="tooltip" data-bs-html="true" title="
196
215
  <div>
197
216
  <div>
@@ -213,12 +232,8 @@
213
232
  {% endif %}
214
233
  </div>"
215
234
  href="{{ url_for('genes.gene', hgnc_id=gene.hgnc_id) }}">{{ gene.hgnc_symbol or gene.hgnc_id }}
216
- </a>
217
- {% endfor %}
218
-
219
-
220
- {% set panel_count = variant.case_panels|rejectattr('removed')|list|count %}
221
- {% if panel_count > 0 %}
235
+ {% for model in gene.inheritance %} {{ inheritance_badge(model,inherit_palette) }}{% endfor %}</a>
236
+ {% if panel_count > 0 %}
222
237
  <a
223
238
  class="badge bg-secondary text-white"
224
239
  data-bs-toggle="popover"
@@ -229,7 +244,10 @@
229
244
  {% endfor %}"
230
245
  title="Overlapping gene panels">{{panel_count}}
231
246
  </a>
232
- {% endif %}
247
+ {% endif %}
248
+ </div>
249
+ {% endfor %}
250
+
233
251
  {% endif %}
234
252
  </div>
235
253
  {% endmacro %}
@@ -272,21 +290,20 @@
272
290
  ">
273
291
  {% if variant.clinsig_human %}
274
292
  <span class="badge bg-secondary">ClinVar</span>
275
- <br>
276
293
  {% endif%}
277
294
  {% if variant.cosmic_ids %}
278
295
  <span class="badge bg-secondary">COSMIC</span>
279
- <br>
296
+
280
297
  {% endif %}
281
298
  {% if variant.mitomap_associated_diseases %}
282
299
  <span class="badge bg-secondary">MITOMAP</span>
283
- <br>
284
300
  {% endif %}
285
301
  {% if variant.clingen_cgh_pathogenic %}
286
- <span class="badge bg-secondary">CGH Pathogenic</span><br>
302
+ <span class="badge bg-secondary">CGH Pathogenic</span>
287
303
  {% endif %}
288
304
  {% if variant.local_obs_old or variant.local_obs_cancer_germline_old or variant.local_obs_cancer_somatic_old %}
289
- <span class="badge bg-secondary">Local</span>
305
+ <span class="badge bg-secondary">Local {% if variant.category in ['snv', 'sv'] %}<span class="badge bg-dark text-white">
306
+ {{ variant.local_obs_old or 0 }}</span>{% endif %}</span>
290
307
  <br>
291
308
  {% endif %}
292
309
  </div>
@@ -1,6 +1,6 @@
1
1
  {% extends "layout.html" %}
2
2
  {% from "variants/utils.html" import mei_filters, cell_rank, pagination_footer, pagination_hidden_div, dismiss_variants_block, filter_form_footer, filter_script_main, update_stash_filter_button_status %}
3
- {% from "variants/components.html" import external_scripts, external_stylesheets, frequency_cell_general, variant_gene_symbols_cell, variant_funct_anno_cell, variant_region_anno_cell %}
3
+ {% from "variants/components.html" import external_scripts, external_stylesheets, frequency_cell_general, variant_gene_symbols_cell, variant_funct_anno_cell %}
4
4
 
5
5
  {% block title %}
6
6
  {{ super() }} - {{ institute.display_name }} - {{ case.display_name }} - Mobile Element Insertion variants
@@ -65,7 +65,6 @@ onsubmit="return validateForm()">
65
65
  <th style="width:9%">Start loc</th>
66
66
  <th>Frequency</th>
67
67
  <th>Gene(s)</th>
68
- <th>Region</th>
69
68
  <th>Function</th>
70
69
  </tr>
71
70
  </thead>
@@ -109,10 +108,7 @@ onsubmit="return validateForm()">
109
108
  {{ frequency_cell_general(variant) }}
110
109
  </td>
111
110
  <td>
112
- {{ variant_gene_symbols_cell(variant) }}
113
- </td>
114
- <td style="word-wrap:break-word;">
115
- {{ variant_region_anno_cell(variant) }}
111
+ {{ variant_gene_symbols_cell(variant, inherit_palette) }}
116
112
  </td>
117
113
  <td style="word-wrap:break-word;">
118
114
  {{ variant_funct_anno_cell(variant) }}
@@ -1,10 +1,11 @@
1
1
  {% extends "layout.html" %}
2
2
  {% from "utils.html" import comments_table, pedigree_panel %}
3
- {% from "variants/components.html" import external_scripts, external_stylesheets, gene_cell, frequency_cell_general %}
4
3
  {% from "variant/buttons.html" import reviewer_button%}
5
-
4
+ {% from "variant/gene_disease_relations.html" import inheritance_badge %}
5
+ {% from "variants/components.html" import external_scripts, external_stylesheets, frequency_cell_general %}
6
6
  {% from "variants/utils.html" import cell_rank, dismiss_variants_block, filter_form_footer, update_stash_filter_button_status, pagination_footer, pagination_hidden_div, str_filters, filter_script_main %}
7
7
 
8
+
8
9
  {% block title %}
9
10
  {{ super() }} - {{ institute.display_name }} - {{ case.display_name }} - STR variants
10
11
  {% endblock %}
@@ -239,6 +240,11 @@
239
240
  {% for gene in variant.genes %} {{ gene.symbol }} {% endfor %} {% endif %}
240
241
  </a>
241
242
  {% for gene in variant.genes %}
243
+ {% if variant.str_disease %}
244
+ {{ inheritance_badge(variant.str_inheritance_mode,inherit_palette) }}
245
+ {% else %}
246
+ {% for model in gene.inheritance %} {{ inheritance_badge(model,inherit_palette) }} {% endfor %}
247
+ {% endif %}
242
248
  <span class="badge bg-secondary"><a href="{{ gene.stripy_link }}" class="text-white" referrerpolicy="no-referrer" rel="noopener" target="_blank">S</a></span>
243
249
  <span class="badge bg-secondary"><a href="{{ gene.gnomad_str_link }}" class="text-white" referrerpolicy="no-referrer" rel="noopener" target="_blank">G</a></span>
244
250
  {% endfor %}
@@ -1,6 +1,6 @@
1
1
  {% extends "layout.html" %}
2
2
  {% from "variants/utils.html" import sv_filters, cell_rank, pagination_footer, pagination_hidden_div, dismiss_variants_block, filter_form_footer, filter_script_main, update_stash_filter_button_status %}
3
- {% from "variants/components.html" import external_scripts, external_stylesheets, frequency_cell_general, observed_cell_general, variant_gene_symbols_cell, variant_funct_anno_cell, variant_region_anno_cell %}
3
+ {% from "variants/components.html" import external_scripts, external_stylesheets, frequency_cell_general, observed_cell_general, variant_gene_symbols_cell, variant_funct_anno_cell %}
4
4
 
5
5
  {% block title %}
6
6
  {{ super() }} - {{ institute.display_name }} - {{ case.display_name }} - SV variants
@@ -67,13 +67,12 @@ onsubmit="return validateForm()">
67
67
  <th>Pop Freq</th>
68
68
  <th>Observed</th>
69
69
  <th>Gene(s)</th>
70
- <th>Region</th>
71
70
  <th>Function</th>
72
71
  </tr>
73
72
  </thead>
74
73
  <tbody>
75
74
  {% for variant in variants %}
76
- {{ variant_row(variant) }}
75
+ {{ variant_row(variant, inherit_palette) }}
77
76
  {% else %}
78
77
  <tr>
79
78
  <td colspan="11">No matching variants</td>
@@ -90,7 +89,7 @@ onsubmit="return validateForm()">
90
89
  </div>
91
90
  {% endblock %}
92
91
 
93
- {% macro variant_row(variant) %}
92
+ {% macro variant_row(variant, inherit_palette) %}
94
93
  {% if variant.dismiss_variant %}
95
94
  <tr class="dismiss">
96
95
  {% elif 'causatives' in case and variant._id in case.causatives %}
@@ -114,10 +113,7 @@ onsubmit="return validateForm()">
114
113
  </td>
115
114
  <td>{{observed_cell_general(variant)}}</td>
116
115
  <td>
117
- {{ variant_gene_symbols_cell(variant) }}
118
- </td>
119
- <td style="word-wrap:break-word;">
120
- {{ variant_region_anno_cell(variant) }}
116
+ {{ variant_gene_symbols_cell(variant, inherit_palette) }}
121
117
  </td>
122
118
  <td style="word-wrap:break-word;">
123
119
  {{ variant_funct_anno_cell(variant) }}
@@ -56,16 +56,15 @@
56
56
  <tr>
57
57
  <th style="width:2%"></th>
58
58
  <th style="width:12%" title="Rank position">Rank</th>
59
- <th style="width:4%" title="Rank score">Score</th>
59
+ <th style="width:5%" title="Rank score">Score</th>
60
60
  <th style="width:4%" title="Chromosome">Chr.</th>
61
- <th style="width:8%" title="HGNC symbols">Gene</th>
62
- <th style="width:4%" title="Pop Freq">Pop Freq</th>
63
- <th style="width:6%" title="Observed database matches">Observed</th>
61
+ <th style="width:12%" title="HGNC symbols">Gene</th>
62
+ <th style="width:6%" title="Pop Freq">Pop Freq</th>
63
+ <th style="width:10%" title="Observed database matches">Observed</th>
64
64
  <th style="width:5%" title="CADD score">CADD</th>
65
- <th style="width:8%" title="Gene region annotation">Gene annotation</th>
66
- <th style="width:17%" title="Functional annotation">Func. annotation</th>
67
- <th style="width:17%" title="Inheritance models">Inheritance model</th>
68
- <th style="width:8%" title="Overlapping">Overlapping</th>
65
+ <th style="width:18%" title="Functional annotation">Function</th>
66
+ <th style="width:14%" title="Inheritance models">Inheritance model</th>
67
+ <th style="width:14%" title="Overlapping">Overlap</th>
69
68
  </tr>
70
69
  </thead>
71
70
  <tbody>
@@ -86,26 +85,19 @@
86
85
  {{ mark_heteroplasmic_mt(case.individuals, variant.samples) }}
87
86
  {% endif %}
88
87
  </td>
89
- <td>{{ gene_cell(variant) }}</td>
88
+ <td>{{ gene_cell(variant, inherit_palette) }}</td>
90
89
  <td class="text-start">{{ frequency_cell_general(variant) }}</td>
91
90
  <td class="text-start">{{ observed_cell_general(variant) }}</td>
92
91
  <td class="text-end">{{ cell_cadd(variant) }}</td>
93
92
  <td>
94
- {% for annotation in variant.region_annotations %}
95
- <div>{{ annotation }}</div>
96
- {% endfor %}
97
- </td>
98
- <td>
99
- {% for annotation in variant.functional_annotations %}
100
- <div>{{ annotation }}</div>
101
- {% endfor %}
93
+ {{ functional_annotation_cell(variant) }}
102
94
  </td>
103
95
  <td>{{ cell_models(variant) }}</td>
104
96
  <td>{{ overlapping_cell(variant) }}</td>
105
97
  </tr>
106
98
  {% else %}
107
99
  <tr>
108
- <td colspan="10">
100
+ <td colspan="9">
109
101
  No matching variants
110
102
  </td>
111
103
  </tr>
@@ -121,6 +113,19 @@
121
113
  </div>
122
114
  {% endblock %}
123
115
 
116
+ {% macro functional_annotation_cell(variant) %}
117
+ <div data-bs-toggle="tooltip" data-bs-html="true" title="
118
+ <div>
119
+ {% for annotation in variant.region_annotations %}
120
+ {{ annotation }}</br>
121
+ {% endfor %}
122
+ </div>">
123
+ {% for annotation in variant.functional_annotations %}
124
+ <div>{{ annotation }}</div>
125
+ {% endfor %}
126
+ </div>
127
+ {% endmacro %}
128
+
124
129
  {% macro cell_cadd(variant) %}
125
130
  <div data-bs-toggle="tooltip" data-bs-placement="left" data-bs-html="true" title="
126
131
  <div class='text-start'>
@@ -13,6 +13,7 @@ from scout.constants import (
13
13
  CANCER_TIER_OPTIONS,
14
14
  DISMISS_VARIANT_OPTIONS,
15
15
  GENETIC_MODELS_PALETTE,
16
+ INHERITANCE_PALETTE,
16
17
  MANUAL_RANK_OPTIONS,
17
18
  SEVERE_SO_TERMS,
18
19
  SEVERE_SO_TERMS_SV,
@@ -163,6 +164,7 @@ def variants(institute_id, case_name):
163
164
  filters=available_filters,
164
165
  form=form,
165
166
  genetic_models_palette=GENETIC_MODELS_PALETTE,
167
+ inherit_palette=INHERITANCE_PALETTE,
166
168
  institute=institute_obj,
167
169
  manual_rank_options=MANUAL_RANK_OPTIONS,
168
170
  page=page,
@@ -254,6 +256,7 @@ def str_variants(institute_id, case_name):
254
256
  expand_search=controllers.get_expand_search(request.form),
255
257
  filters=available_filters,
256
258
  form=form,
259
+ inherit_palette=INHERITANCE_PALETTE,
257
260
  institute=institute_obj,
258
261
  manual_rank_options=MANUAL_RANK_OPTIONS,
259
262
  page=page,
@@ -333,6 +336,7 @@ def sv_variants(institute_id, case_name):
333
336
  expand_search=controllers.get_expand_search(request.form),
334
337
  filters=available_filters,
335
338
  form=form,
339
+ inherit_palette=INHERITANCE_PALETTE,
336
340
  institute=institute_obj,
337
341
  manual_rank_options=MANUAL_RANK_OPTIONS,
338
342
  page=page,
@@ -429,6 +433,7 @@ def mei_variants(institute_id, case_name):
429
433
  expand_search=controllers.get_expand_search(request.form),
430
434
  filters=available_filters,
431
435
  form=form,
436
+ inherit_palette=INHERITANCE_PALETTE,
432
437
  institute=institute_obj,
433
438
  manual_rank_options=MANUAL_RANK_OPTIONS,
434
439
  page=page,
@@ -627,6 +632,7 @@ def cancer_sv_variants(institute_id, case_name):
627
632
  expand_search=controllers.get_expand_search(request.form),
628
633
  filters=available_filters,
629
634
  form=form,
635
+ inherit_palette=INHERITANCE_PALETTE,
630
636
  institute=institute_obj,
631
637
  manual_rank_options=MANUAL_RANK_OPTIONS,
632
638
  page=page,
scout/utils/acmg.py CHANGED
@@ -1,4 +1,12 @@
1
1
  # coding=UTF-8
2
+
3
+
4
+ from typing import Optional
5
+
6
+ from scout.constants import ACMG_COMPLETE_MAP
7
+ from scout.constants.acmg import ACMG_POTENTIAL_CONFLICTS
8
+
9
+
2
10
  def is_pathogenic(pvs, ps_terms, pm_terms, pp_terms):
3
11
  """Check if the criterias for Pathogenic is fullfilled
4
12
 
@@ -157,38 +165,31 @@ def is_likely_benign(bs_terms, bp_terms):
157
165
  return False
158
166
 
159
167
 
160
- def get_acmg(acmg_terms):
161
- """Use the algorithm described in ACMG paper to get a ACMG calssification
162
-
163
- Modifying strength of a term is possible by adding a string describing its new level: "PP1_Strong" or
164
- "PVS1_Moderate".
165
-
166
- If no terms return None
167
-
168
- Args:
169
- acmg_terms(set(str)): A collection of prediction terms
170
-
171
- Returns:
172
- prediction(str): in ['uncertain_significance','benign','likely_benign',
173
- 'likely_pathogenic','pathogenic']
174
-
168
+ def get_acmg_criteria(acmg_terms: set) -> tuple:
175
169
  """
176
- if not acmg_terms:
177
- return None
178
- prediction = "uncertain_significance"
179
- # This variable indicates if Pathogenecity Very Strong exists
170
+ Given a set of ACMG evidence criteria terms, that may be strength modified with suffixes.
171
+ For each term,
172
+ first, Strength modified criteria suffixes should count towards their modified score.
173
+ then, we need to see if we match any of the two stand-alone terms. If so, set their respective booleans.
174
+ finally, check remaining prefixes if no suffix match or stand-alone criteria match
175
+
176
+ Return a tuple with
177
+ pvs: This variable indicates if Pathogenicity Very Strong exists
178
+ ps_terms: Collection of terms with Pathogenicity Strong
179
+ pm_terms: Collection of terms with Pathogenicity moderate
180
+ pp_terms: Collection of terms with Pathogenicity supporting
181
+ ba: This variable indicates if Benign impact stand-alone exists
182
+ bs_terms: Collection of terms with Benign evidence Strong
183
+ bp_terms: Collection of terms with supporting Benign evidence
184
+ """
185
+
180
186
  pvs = False
181
- # Collection of terms with Pathogenecity Strong
182
187
  ps_terms = []
183
- # Collection of terms with Pathogenecity moderate
184
188
  pm_terms = []
185
- # Collection of terms with Pathogenecity supporting
186
189
  pp_terms = []
187
- # This variable indicates if Benign impact stand-alone exists
190
+
188
191
  ba = False
189
- # Collection of terms with Benign evidence Strong
190
192
  bs_terms = []
191
- # Collection of terms with supporting Benign evidence
192
193
  bp_terms = []
193
194
 
194
195
  suffix_map = {
@@ -212,20 +213,51 @@ def get_acmg(acmg_terms):
212
213
  if term.startswith(prefix):
213
214
  term_list.append(term)
214
215
  break
216
+ else:
217
+ continue
215
218
  break
216
219
  else:
217
- # Do we match any of the two standalone terms
218
220
  if term.startswith("PVS"):
219
221
  pvs = True
220
222
  elif term.startswith("BA"):
221
223
  ba = True
222
- else: # Check remaining prefixes if no suffix match or standalone criteria match
224
+ else:
223
225
  for prefix, term_list in prefix_map.items():
224
226
  if term.startswith(prefix):
225
227
  term_list.append(term)
226
228
  break
227
229
 
228
- # We need to start by checking for Pathogenecity
230
+ return (pvs, ps_terms, pm_terms, pp_terms, ba, bs_terms, bp_terms)
231
+
232
+
233
+ def get_acmg(acmg_terms: set) -> Optional[str]:
234
+ """Use the algorithm described in ACMG paper (Richards 2015) to get a ACMG classification
235
+
236
+ Modifying strength of a term is possible by adding a string describing its new level: "PP1_Strong" or
237
+ "PVS1_Moderate".
238
+
239
+ BA is considered fully Stand Alone.
240
+
241
+ If no terms return None
242
+
243
+ Args:
244
+ acmg_terms(set(str)): A collection of prediction terms
245
+
246
+ Returns:
247
+ prediction(str): in ['uncertain_significance','benign','likely_benign',
248
+ 'likely_pathogenic','pathogenic']
249
+
250
+ """
251
+ if not acmg_terms:
252
+ return None
253
+
254
+ (pvs, ps_terms, pm_terms, pp_terms, ba, bs_terms, bp_terms) = get_acmg_criteria(acmg_terms)
255
+
256
+ if ba:
257
+ return "benign"
258
+
259
+ prediction = "uncertain_significance"
260
+
229
261
  pathogenic = is_pathogenic(pvs, ps_terms, pm_terms, pp_terms)
230
262
  likely_pathogenic = is_likely_pathogenic(pvs, ps_terms, pm_terms, pp_terms)
231
263
  benign = is_benign(ba, bs_terms)
@@ -245,3 +277,98 @@ def get_acmg(acmg_terms):
245
277
  prediction = "likely_benign"
246
278
 
247
279
  return prediction
280
+
281
+
282
+ def get_acmg_temperature(acmg_terms: set) -> Optional[dict]:
283
+ """
284
+ Use the algorithm described in Tavtigian 2020 to classifiy variants.
285
+
286
+ PVS 8 points, S 4, M 2, P 1.
287
+ This gives:
288
+
289
+ P > 10
290
+ LP 6 < p < 9
291
+ VUS 0 < p < 5
292
+ LB -1 < p < -6
293
+ B < -7
294
+
295
+ If no terms return None
296
+
297
+ Args:
298
+ acmg_terms(set(str)): A collection of prediction terms
299
+
300
+ Returns:
301
+ dict:
302
+ temperature:
303
+ (points, temperature, point_classification)
304
+
305
+ """
306
+ TEMPERATURE_STRINGS = {
307
+ -1: {"label": "B/LB", "color": "success", "icon": "fa-times"},
308
+ 0: {"label": "Ice cold", "color": "info", "icon": "fa-icicles"},
309
+ 1: {"label": "Cold", "color": "info", "icon": "fa-snowman"},
310
+ 2: {"label": "Cold", "color": "info", "icon": "fa-snowflake"},
311
+ 3: {"label": "Tepid", "color": "yellow", "icon": "fa-temperature-half"},
312
+ 4: {"label": "Warm", "color": "orange", "icon": "fa-mug-hot"},
313
+ 5: {"label": "Hot", "color": "red", "icon": "fa-pepper-hot"},
314
+ 6: {"label": "LP/P", "color": "danger", "icon": "fa-stethoscope"},
315
+ }
316
+
317
+ if not acmg_terms:
318
+ return {}
319
+
320
+ (pvs, ps_terms, pm_terms, pp_terms, ba, bs_terms, bp_terms) = get_acmg_criteria(acmg_terms)
321
+
322
+ if ba:
323
+ points = -8
324
+ else:
325
+ points = (
326
+ 8 * pvs
327
+ + 4 * len(ps_terms)
328
+ + 2 * len(pm_terms)
329
+ + len(pp_terms)
330
+ - 4 * len(bs_terms)
331
+ - len(bp_terms)
332
+ )
333
+
334
+ if points <= -7:
335
+ point_classification = "benign"
336
+ temperature_icon = TEMPERATURE_STRINGS[-1].get("icon")
337
+ elif points <= -1:
338
+ point_classification = "likely_benign"
339
+ temperature_icon = TEMPERATURE_STRINGS[-1].get("icon")
340
+ elif points <= 5:
341
+ point_classification = "uncertain_significance"
342
+ elif points <= 9:
343
+ point_classification = "likely_pathogenic"
344
+ temperature_icon = TEMPERATURE_STRINGS[6].get("icon")
345
+ elif points >= 10:
346
+ point_classification = "pathogenic"
347
+ temperature_icon = TEMPERATURE_STRINGS[6].get("icon")
348
+
349
+ temperature_class = ACMG_COMPLETE_MAP[point_classification].get("color")
350
+ temperature = ACMG_COMPLETE_MAP[point_classification].get("label")
351
+
352
+ if point_classification == "uncertain_significance":
353
+ temperature_class = TEMPERATURE_STRINGS[points].get("color")
354
+ temperature = TEMPERATURE_STRINGS[points].get("label")
355
+ temperature_icon = TEMPERATURE_STRINGS[points].get("icon")
356
+
357
+ return {
358
+ "points": points,
359
+ "temperature": temperature,
360
+ "temperature_class": temperature_class,
361
+ "temperature_icon": temperature_icon,
362
+ "point_classification": ACMG_COMPLETE_MAP[point_classification].get("short"),
363
+ }
364
+
365
+
366
+ def get_acmg_conflicts(acmg_terms: set) -> list:
367
+ """Check potential conflict paris, return list of reference strings."""
368
+
369
+ conflicts = []
370
+ for t1, t2, reference in ACMG_POTENTIAL_CONFLICTS:
371
+ if t1 in acmg_terms and t2 in acmg_terms:
372
+ conflicts.append(reference)
373
+
374
+ return conflicts
@@ -3,7 +3,7 @@
3
3
  import logging
4
4
  import urllib.request
5
5
  import zlib
6
- from typing import Dict
6
+ from typing import Dict, List
7
7
  from urllib.error import HTTPError
8
8
 
9
9
  import requests
@@ -134,7 +134,7 @@ def fetch_resource(url, json=False):
134
134
  """
135
135
  if url.startswith("ftp"):
136
136
  # requests do not handle ftp
137
- response = urllib.request.urlopen(url, timeout=TIMEOUT)
137
+ response = urllib.request.urlopen(url, timeout=TIMEOUT) # nosec
138
138
  if isinstance(response, Exception):
139
139
  raise response
140
140
  data = response.read().decode("utf-8")
@@ -307,20 +307,15 @@ def fetch_orpha_files() -> Dict:
307
307
  return orpha_files
308
308
 
309
309
 
310
- def fetch_hgnc():
311
- """Fetch the hgnc genes file from
312
- ftp://ftp.ebi.ac.uk/pub/databases/genenames/new/tsv/hgnc_complete_set.txt
313
-
314
- Returns:
315
- hgnc_gene_lines(list(str))
310
+ def fetch_hgnc() -> List[str]:
311
+ """Fetch the hgnc genes names file from
312
+ https://storage.googleapis.com/public-download-files/hgnc/tsv/tsv/hgnc_complete_set.txt
316
313
  """
317
- file_name = "hgnc_complete_set.txt"
318
- url = "ftp://ftp.ebi.ac.uk/pub/databases/genenames/new/tsv/{0}".format(file_name)
319
- LOG.info("Fetching HGNC genes from %s", url)
320
314
 
321
- hgnc_lines = fetch_resource(url)
315
+ url = "https://storage.googleapis.com/public-download-files/hgnc/tsv/tsv/hgnc_complete_set.txt"
316
+ LOG.info("Fetching HGNC genes from %s", url)
322
317
 
323
- return hgnc_lines
318
+ return fetch_resource(url)
324
319
 
325
320
 
326
321
  def fetch_constraint():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scout-browser
3
- Version: 4.89.1
3
+ Version: 4.90
4
4
  Summary: Clinical DNA variant visualizer and browser.
5
5
  Home-page: https://github.com/Clinical-Genomics/scout
6
6
  Author: Måns Magnusson