scout-browser 4.92__py3-none-any.whl → 4.95.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.
Files changed (82) hide show
  1. scout/adapter/mongo/base.py +3 -0
  2. scout/adapter/mongo/case.py +27 -2
  3. scout/adapter/mongo/ccv.py +131 -0
  4. scout/adapter/mongo/hgnc.py +5 -1
  5. scout/adapter/mongo/managed_variant.py +4 -2
  6. scout/adapter/mongo/query.py +91 -54
  7. scout/adapter/mongo/variant.py +17 -11
  8. scout/adapter/mongo/variant_events.py +45 -1
  9. scout/build/ccv.py +59 -0
  10. scout/build/panel.py +1 -1
  11. scout/commands/export/export_command.py +0 -0
  12. scout/commands/load/base.py +0 -0
  13. scout/commands/load/user.py +0 -0
  14. scout/commands/serve.py +2 -1
  15. scout/commands/update/disease.py +0 -0
  16. scout/commands/update/genes.py +0 -0
  17. scout/commands/wipe_database.py +0 -0
  18. scout/constants/__init__.py +2 -0
  19. scout/constants/case_tags.py +2 -0
  20. scout/constants/ccv.py +244 -0
  21. scout/constants/gene_tags.py +22 -12
  22. scout/demo/643594.config.yaml +2 -2
  23. scout/demo/643594.research.mei.vcf.gz +0 -0
  24. scout/demo/643594.research.mei.vcf.gz.tbi +0 -0
  25. scout/demo/images/custom_images/1300x1000.jpg +0 -0
  26. scout/load/panelapp.py +8 -12
  27. scout/models/ccv_evaluation.py +26 -0
  28. scout/models/variant/variant.py +1 -0
  29. scout/parse/omim.py +5 -6
  30. scout/parse/panelapp.py +16 -42
  31. scout/parse/variant/compound.py +20 -21
  32. scout/parse/variant/gene.py +0 -0
  33. scout/parse/variant/genotype.py +0 -0
  34. scout/resources/custom_igv_tracks/mane.bb +0 -0
  35. scout/server/blueprints/cases/controllers.py +48 -0
  36. scout/server/blueprints/cases/templates/cases/case_report.html +61 -1
  37. scout/server/blueprints/cases/templates/cases/collapsible_actionbar.html +2 -2
  38. scout/server/blueprints/cases/templates/cases/index.html +0 -2
  39. scout/server/blueprints/cases/views.py +5 -5
  40. scout/server/blueprints/clinvar/controllers.py +4 -5
  41. scout/server/blueprints/institutes/controllers.py +129 -67
  42. scout/server/blueprints/institutes/forms.py +5 -2
  43. scout/server/blueprints/institutes/templates/overview/cases.html +6 -0
  44. scout/server/blueprints/institutes/templates/overview/causatives.html +1 -1
  45. scout/server/blueprints/institutes/templates/overview/utils.html +18 -6
  46. scout/server/blueprints/institutes/templates/overview/verified.html +1 -1
  47. scout/server/blueprints/institutes/views.py +4 -0
  48. scout/server/blueprints/managed_variants/forms.py +17 -2
  49. scout/server/blueprints/managed_variants/templates/managed_variants/managed_variants.html +2 -2
  50. scout/server/blueprints/panels/controllers.py +5 -6
  51. scout/server/blueprints/panels/templates/panels/panel.html +5 -5
  52. scout/server/blueprints/variant/controllers.py +148 -1
  53. scout/server/blueprints/variant/templates/variant/cancer-variant.html +1 -1
  54. scout/server/blueprints/variant/templates/variant/ccv.html +183 -0
  55. scout/server/blueprints/variant/templates/variant/components.html +86 -5
  56. scout/server/blueprints/variant/templates/variant/sv-variant.html +2 -2
  57. scout/server/blueprints/variant/templates/variant/tx_overview.html +3 -3
  58. scout/server/blueprints/variant/templates/variant/variant.html +1 -1
  59. scout/server/blueprints/variant/templates/variant/variant_details.html +29 -11
  60. scout/server/blueprints/variant/utils.py +21 -1
  61. scout/server/blueprints/variant/views.py +115 -5
  62. scout/server/blueprints/variants/controllers.py +31 -0
  63. scout/server/blueprints/variants/forms.py +33 -5
  64. scout/server/blueprints/variants/templates/variants/cancer-sv-variants.html +4 -18
  65. scout/server/blueprints/variants/templates/variants/cancer-variants.html +4 -13
  66. scout/server/blueprints/variants/templates/variants/components.html +77 -73
  67. scout/server/blueprints/variants/templates/variants/indicators.html +11 -0
  68. scout/server/blueprints/variants/templates/variants/sv-variants.html +2 -2
  69. scout/server/links.py +1 -1
  70. scout/server/static/custom_images.js +19 -2
  71. scout/utils/acmg.py +0 -1
  72. scout/utils/ccv.py +193 -0
  73. scout/utils/link.py +4 -3
  74. scout/utils/md5.py +0 -0
  75. {scout_browser-4.92.dist-info → scout_browser-4.95.0.dist-info}/METADATA +67 -45
  76. {scout_browser-4.92.dist-info → scout_browser-4.95.0.dist-info}/RECORD +70 -65
  77. {scout_browser-4.92.dist-info → scout_browser-4.95.0.dist-info}/WHEEL +1 -2
  78. scout/__version__.py +0 -1
  79. scout/demo/images/custom_images/640x480_two.jpg +0 -0
  80. scout_browser-4.92.dist-info/top_level.txt +0 -1
  81. {scout_browser-4.92.dist-info → scout_browser-4.95.0.dist-info}/entry_points.txt +0 -0
  82. {scout_browser-4.92.dist-info → scout_browser-4.95.0.dist-info/licenses}/LICENSE +0 -0
@@ -161,94 +161,84 @@
161
161
 
162
162
  {% macro gene_cell(variant, inherit_palette) %}
163
163
  <div class="align-items-center">
164
- {% if variant.category == "cancer" or variant.category == "sv_cancer" %}
165
- <a data-bs-toggle="tooltip" data-bs-html="true" title="
164
+
165
+ {% macro gene_tooltip(gene) %}
166
+ <div>
166
167
  <div>
168
+ <strong>{{ gene.hgnc_symbol }}</strong>: {{ gene.description }}
169
+ </div>
170
+ {% if gene.inheritance %}
167
171
  <div>
168
- <strong>{{ variant.first_rep_gene.hgnc_symbol }}</strong>: {{ variant.first_rep_gene.description }}
172
+ <strong>Models</strong>: {{ gene.inheritance|join(',') }}
169
173
  </div>
170
- {% if variant.first_rep_gene.inheritance %}
171
- <div>
172
- <strong>Models</strong>: {{ variant.first_rep_gene.inheritance|join(',') }}
173
- </div>
174
- {% endif %}
175
- {% if variant.first_rep_gene.phenotypes %}
174
+ {% endif %}
175
+ {% if gene.phenotypes %}
176
176
  <div><strong>OMIM disease</strong>
177
- {% for disease in variant.first_rep_gene.phenotypes %}
178
- <div>
179
- {{ disease.description }}
180
- </div>
177
+ {% for disease in gene.phenotypes %}
178
+ <div>{{ disease.description }}</div>
181
179
  {% endfor %}
182
180
  </div>
183
181
  {% endif %}
184
- </div>"
185
- {% if variant.first_rep_gene %}
186
- href="{{ url_for('genes.gene', hgnc_id=variant.first_rep_gene.hgnc_id) }}"
187
- {% endif %}>
188
- {{ variant.first_rep_gene.hgnc_symbol or variant.first_rep_gene.hgnc_id }}
189
- {% if variant.secondary_gene %}
190
- <span class="text-muted">
191
- ({{ variant.second_rep_gene.hgnc_symbol or variant.second_rep_gene.hgnc_id }})
192
- </span>
193
- {% endif %}
182
+ </div>
183
+ {% endmacro %}
184
+
185
+ {% macro gene_link(gene) %}
186
+ <a
187
+ data-bs-toggle="tooltip"
188
+ data-bs-html="true"
189
+ title="{{ gene_tooltip(gene) }}"
190
+ href="{{ url_for('genes.gene', hgnc_id=gene.hgnc_id) }}"
191
+ >
192
+ {{ gene.hgnc_symbol or gene.hgnc_id }}
194
193
  </a>
194
+ {% endmacro %}
195
+
196
+ {% macro panel_badge(variant, gene_id=0) %}
197
+
198
+ {% set matching_panels = [] %}
199
+ {% for panel in variant.case_panels|rejectattr('removed')|list %}
200
+ {% if gene_id in panel.hgnc_ids %}
201
+ {% set _ = matching_panels.append(panel) %}
202
+ {% endif %}
203
+ {% endfor %}
195
204
 
196
- {% set panel_count = variant.case_panels|rejectattr('removed')|list|length %}
197
- {% if panel_count > 0%}
198
- <a
199
- class="badge bg-secondary text-white"
200
- data-bs-toggle="popover"
201
- data-bs-html="true"
202
- data-bs-trigger="hover click"
203
- title="Overlapping gene panels"
204
- data-bs-content="{% for panel in variant.case_panels|sort(attribute='panel_name',case_sensitive=False)|rejectattr('removed') %}
205
- {{ panel.panel_name|safe }}<br>
206
- {% endfor %}"
207
- >{{panel_count}}
208
- </a>
205
+ {% set panel_count = matching_panels|length %}
206
+ <a
207
+ class="badge bg-secondary text-white"
208
+ data-bs-toggle="popover"
209
+ data-bs-html="true"
210
+ data-bs-trigger="hover click"
211
+ title="Overlapping gene panels"
212
+ data-bs-content="{% for panel in matching_panels %}
213
+ {{ panel.panel_name|safe }}<br>
214
+ {% else %} No ovelapping gene panels {% endfor %}"
215
+ >{{ panel_count }}</a>
216
+ {% endmacro %}
217
+
218
+ {% if variant.category in ["cancer", "sv_cancer"] %}
219
+ {% if variant.first_rep_gene %}
220
+ {{ gene_link(variant.first_rep_gene) }}
221
+ {% endif %}
222
+ {% if variant.secondary_gene %}
223
+ <span class="text-muted">
224
+ ({{ variant.second_rep_gene.hgnc_symbol or variant.second_rep_gene.hgnc_id }})
225
+ </span>
226
+ {% endif %}
227
+ {% if variant.first_rep_gene or variant.second_rep_gene %}
228
+ {{ panel_badge(variant, variant.first_rep_gene.hgnc_id or variant.second_rep_gene.hgnc_id) }}
209
229
  {% endif %}
210
230
  {% else %}
211
- {% set panel_count = variant.case_panels|rejectattr('removed')|list|count %}
212
231
  {% for gene in variant.genes %}
213
232
  <div>
214
- <a data-bs-toggle="tooltip" data-bs-html="true" title="
215
- <div>
216
- <div>
217
- <strong>{{ gene.hgnc_symbol }}</strong>: {{ gene.description }}
218
- </div>
219
- {% if gene.inheritance %}
220
- <div>
221
- <strong>Models</strong>: {{ gene.inheritance|join(',') }}
222
- </div>
223
- {% endif %}
224
- {% if gene.phenotypes %}
225
- <div><strong>OMIM disease</strong>
226
- {% for disease in gene.phenotypes %}
227
- <div>
228
- {{ disease.description }}
229
- </div>
230
- {% endfor %}
231
- </div>
232
- {% endif %}
233
- </div>"
234
- href="{{ url_for('genes.gene', hgnc_id=gene.hgnc_id) }}">{{ gene.hgnc_symbol or gene.hgnc_id }}
235
- {% for model in gene.inheritance %} {{ inheritance_badge(model,inherit_palette) }}{% endfor %}</a>
236
- {% if panel_count > 0 %}
237
- <a
238
- class="badge bg-secondary text-white"
239
- data-bs-toggle="popover"
240
- data-bs-html="true"
241
- data-bs-trigger="hover click"
242
- data-bs-content="{% for panel in variant.case_panels|sort(attribute='panel_name',case_sensitive=False)|rejectattr('removed') %}
243
- {{ panel.panel_name|safe }}<br>
244
- {% endfor %}"
245
- title="Overlapping gene panels">{{panel_count}}
246
- </a>
247
- {% endif %}
248
- </div>
233
+ {{ gene_link(gene) }}
234
+ {% for model in gene.inheritance %}
235
+ {{ inheritance_badge(model, inherit_palette) }}
236
+ {% endfor %}
237
+ {{ panel_badge(variant, gene.hgnc_id) }}
238
+ </div>
249
239
  {% endfor %}
250
-
251
240
  {% endif %}
241
+
252
242
  </div>
253
243
  {% endmacro %}
254
244
 
@@ -413,3 +403,17 @@
413
403
  <script src="https://cdn.datatables.net/1.12.0/js/jquery.dataTables.min.js" integrity="sha512-fu0WiDG5xqtX2iWk7cp17Q9so54SC+5lk/z/glzwlKFdEOwGG6piUseP2Sik9hlvlmyOJ0lKXRSuv1ltdVk9Jg==" referrerpolicy="no-referrer" crossorigin="anonymous"></script>
414
404
  <script src="https://cdn.datatables.net/1.12.0/js/dataTables.bootstrap5.min.js" integrity="sha512-nfoMMJ2SPcUdaoGdaRVA1XZpBVyDGhKQ/DCedW2k93MTRphPVXgaDoYV1M/AJQLCiw/cl2Nbf9pbISGqIEQRmQ==" referrerpolicy="no-referrer" crossorigin="anonymous"></script>
415
405
  {% endmacro %}
406
+
407
+ {% macro allele_cell(allele) %}
408
+ {% if 'alt_freq' in allele %}
409
+ {% if allele.alt_freq == -1 %}
410
+ <span class="text-body">.</span>
411
+ {% else %}
412
+ <span class="text-body"><b>{{ allele.alt_freq|round(4) }}</b></span>
413
+ {% endif %}
414
+ <br>
415
+ <small class="text-body">{% if 'alt_depth' in allele and allele.alt_depth >= 0 %}{{ allele.alt_depth }}{% else %}.{% endif %}|{% if 'ref_depth' in allele and allele.ref_depth >= 0 %}{{ allele.ref_depth }}{% else %}.{% endif %}</small>
416
+ {% else %}
417
+ <span class="text-body">N/A</span>
418
+ {% endif %}
419
+ {% endmacro %}
@@ -74,6 +74,17 @@
74
74
  {% endif %}
75
75
  {% endmacro %}
76
76
 
77
+ {% macro ccv_evaluations_badge(variant) %}
78
+ {% if variant.ccv_evaluations %}
79
+ {% for evaluation in (variant.ccv_evaluations or []) %}
80
+ <span class="badge bg-secondary" style="margin-left:1px" data-bs-toggle="tooltip" data-bs-placement="right"
81
+ title="Previously classified as {{ evaluation.ccv_classification.label }}">
82
+ {{ evaluation.ccv_classification.short }}
83
+ </span>
84
+ {% endfor %}
85
+ {% endif %}
86
+ {% endmacro %}
87
+
77
88
  {% macro dismissals_badge(variant) %}
78
89
  {% if variant.dismissals %}
79
90
  <span class="badge bg-secondary" style="margin-left:1px" data-bs-toggle="tooltip" data-bs-html="true" data-bs-placement="top"
@@ -108,8 +108,8 @@ onsubmit="return validateForm()">
108
108
  </td>
109
109
  <td>{{ variant.sub_category|upper }}</td>
110
110
  <td>{{ variant.chromosome if variant.chromosome == variant.end_chrom else variant.chromosome+'-'+variant.end_chrom }}</td>
111
- <td><span style="white-space: nowrap;">{{ variant.position|human_longint|safe }}</span></td>
112
- <td><span style="white-space: nowrap;">{{ 'inf' if variant.end == 100000000000 else variant.end|human_longint|safe }}</span></td>
111
+ <td>{% if variant.chromosome != variant.end_chrom %}<span class="text-body"></span><b>{{ variant.chromosome }}</b>:</span>{% endif %}<span style="white-space: nowrap;">{{ variant.position|human_longint|safe }}</span></td>
112
+ <td>{% if variant.chromosome != variant.end_chrom %}<span class="text-body"><b>{{ variant.end_chrom }}</b>:</span>{% endif %}<span style="white-space: nowrap;">{{ 'inf' if variant.end == 100000000000 else variant.end|human_longint|safe }}</span></td>
113
113
  <td class="text-end"><span style="white-space: nowrap;">{{ '-' if variant.length == 100000000000 else variant.length|human_longint|safe}}</span></td>
114
114
  <td>
115
115
  {{ frequency_cell_general(variant) }}
scout/server/links.py CHANGED
@@ -714,7 +714,7 @@ def ucsc_link(variant_obj, build=None):
714
714
  )
715
715
  if build == 38:
716
716
  url_template = (
717
- "http://genome.ucsc.edu/cgi-bin/hgTracks?db=hg20&"
717
+ "http://genome.ucsc.edu/cgi-bin/hgTracks?db=hg38&"
718
718
  "position=chr{this[chromosome]}:{this[position]}"
719
719
  "-{this[position]}&dgv=pack&knownGene=pack&omimGene=pack"
720
720
  )
@@ -1,3 +1,11 @@
1
+ const imgMaxWidth = window.innerWidth*0.7;
2
+ const imgMaxHeight = window.innerHeight*0.7;
3
+
4
+ function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
5
+ let ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
6
+ return [srcWidth*ratio, srcHeight*ratio];
7
+ }
8
+
1
9
  /**
2
10
  * This function fetches an image from disk and displays it in a specified div
3
11
  * @param {string} imageUrl - The URL of the image to fetch
@@ -9,15 +17,24 @@
9
17
  .then(blob => {
10
18
  const img = document.createElement("img");
11
19
  img.src = URL.createObjectURL(blob);
20
+ if (width > imgMaxWidth || height > imgMaxHeight) {
21
+ const resized_pixels = calculateAspectRatioFit(width, height, imgMaxWidth, imgMaxHeight);
22
+ width = resized_pixels[0];
23
+ height = resized_pixels[1];
24
+ }
12
25
  if (width) {
13
26
  img.style.width = width+'px';
14
27
  }
15
28
  if (height) {
16
29
  img.style.height = height+'px';
17
30
  }
18
- // Display the image in the specified div
31
+ // Add the image to a link and add the link to the div
32
+ const link = document.createElement('a');
33
+ link.appendChild(img);
34
+ link.href = img.src;
35
+ link.setAttribute('target', "_blank");
19
36
  const div = document.getElementById(divId);
20
- div.appendChild(img);
37
+ div.appendChild(link);
21
38
  })
22
39
  .catch(error => console.error(error));
23
40
  }
scout/utils/acmg.py CHANGED
@@ -1,6 +1,5 @@
1
1
  # coding=UTF-8
2
2
 
3
-
4
3
  from typing import Optional
5
4
 
6
5
  from scout.constants import ACMG_COMPLETE_MAP
scout/utils/ccv.py ADDED
@@ -0,0 +1,193 @@
1
+ # coding=UTF-8
2
+ from typing import Optional
3
+
4
+ from scout.constants.ccv import CCV_COMPLETE_MAP, CCV_POTENTIAL_CONFLICTS
5
+
6
+
7
+ def get_ccv_points(ccv_terms: set) -> int:
8
+ """
9
+ Use the algorithm described in Clingen-CGC-VIGG classification paper (Horak 2022)
10
+ Given a set of CCV evidence criteria terms
11
+ for each term,
12
+ check prefixes if no suffix match or stand-alone criteria match
13
+
14
+ O positive, SB negative.
15
+ VS 8 points, S 4, M 2, P 1.
16
+
17
+ If no terms return None
18
+
19
+ Args:
20
+ ccv_terms(set(str)): A collection of prediction terms
21
+ Returns:
22
+ points(int):"""
23
+
24
+ ovs_terms = []
25
+ os_terms = []
26
+ om_terms = []
27
+ op_terms = []
28
+ sbvs_terms = []
29
+ sbs_terms = []
30
+ sbm_terms = []
31
+ sbp_terms = []
32
+
33
+ prefix_map = {
34
+ "OVS": ovs_terms,
35
+ "OS": os_terms,
36
+ "OM": om_terms,
37
+ "OP": op_terms,
38
+ "SBVS": sbvs_terms,
39
+ "SBS": sbs_terms,
40
+ "SBM": sbm_terms,
41
+ "SBP": sbp_terms,
42
+ }
43
+
44
+ suffix_map = {
45
+ "_Strong": {"O": os_terms, "SB": sbs_terms},
46
+ "_Moderate": {"O": om_terms, "SB": sbm_terms},
47
+ "_Supporting": {"O": op_terms, "SB": sbp_terms},
48
+ }
49
+
50
+ for term in ccv_terms:
51
+ for suffix, prefix_dict in suffix_map.items():
52
+ if term.endswith(suffix):
53
+ for prefix, term_list in prefix_dict.items():
54
+ if term.startswith(prefix):
55
+ term_list.append(term)
56
+ break
57
+ else:
58
+ continue
59
+ break
60
+ else:
61
+ for prefix, term_list in prefix_map.items():
62
+ if term.startswith(prefix):
63
+ term_list.append(term)
64
+ break
65
+ points = (
66
+ 8 * len(ovs_terms)
67
+ + 4 * len(os_terms)
68
+ + 2 * len(om_terms)
69
+ + len(op_terms)
70
+ - 8 * len(sbvs_terms)
71
+ - 4 * len(sbs_terms)
72
+ - 2 * len(sbm_terms)
73
+ - len(sbp_terms)
74
+ )
75
+ return points
76
+
77
+
78
+ def get_ccv(ccv_terms: set) -> Optional[str]:
79
+ """Use the algorithm described in Clingen-CGC-VIGG classification paper (Horak 2022)
80
+
81
+ If no terms return None
82
+
83
+ O >= 10
84
+ OP 6 <= p <= 9
85
+ VUS 0 <= p <= 5
86
+ LB -1 <= p <= -6
87
+ B <= -7
88
+
89
+ Args:
90
+ ccv_terms(set(str)): A collection of prediction terms
91
+
92
+ Returns:
93
+ prediction(str): in ['uncertain_significance','benign','likely_benign',
94
+ 'likely_oncogenic','oncogenic']
95
+
96
+ """
97
+ if not ccv_terms:
98
+ return None
99
+
100
+ points = get_ccv_points(ccv_terms)
101
+
102
+ if points <= -7:
103
+ prediction = "benign"
104
+ elif points <= -1:
105
+ prediction = "likely_benign"
106
+ elif points <= 5:
107
+ prediction = "uncertain_significance"
108
+ elif points <= 9:
109
+ prediction = "likely_oncogenic"
110
+ elif points >= 10:
111
+ prediction = "oncogenic"
112
+
113
+ return prediction
114
+
115
+
116
+ def get_ccv_temperature(ccv_terms: set) -> Optional[dict]:
117
+ """
118
+ Use the algorithm described in Clingen-CGC-VIGG classification paper (Horak 2022)
119
+
120
+ O >= 10
121
+ OP 6 <= p <= 9
122
+ VUS 0 <= p <= 5
123
+ LB -1 <= p <= -6
124
+ B <= -7
125
+
126
+ If no terms return None
127
+
128
+ Args:
129
+ ccv_terms(set(str)): A collection of prediction terms
130
+
131
+ Returns:
132
+ dict:
133
+ temperature:
134
+ (points, temperature, point_classification)
135
+
136
+ """
137
+ TEMPERATURE_STRINGS = {
138
+ -1: {"label": "B/LB", "color": "success", "icon": "fa-times"},
139
+ 0: {"label": "Ice cold", "color": "info", "icon": "fa-icicles"},
140
+ 1: {"label": "Cold", "color": "info", "icon": "fa-snowman"},
141
+ 2: {"label": "Cold", "color": "info", "icon": "fa-snowflake"},
142
+ 3: {"label": "Tepid", "color": "yellow", "icon": "fa-temperature-half"},
143
+ 4: {"label": "Warm", "color": "orange", "icon": "fa-mug-hot"},
144
+ 5: {"label": "Hot", "color": "red", "icon": "fa-pepper-hot"},
145
+ 6: {"label": "LO/O", "color": "danger", "icon": "fa-stethoscope"},
146
+ }
147
+
148
+ if not ccv_terms:
149
+ return {}
150
+
151
+ points = get_ccv_points(ccv_terms)
152
+
153
+ if points <= -7:
154
+ point_classification = "benign"
155
+ temperature_icon = TEMPERATURE_STRINGS[-1].get("icon")
156
+ elif points <= -1:
157
+ point_classification = "likely_benign"
158
+ temperature_icon = TEMPERATURE_STRINGS[-1].get("icon")
159
+ elif points <= 5:
160
+ point_classification = "uncertain_significance"
161
+ elif points <= 9:
162
+ point_classification = "likely_oncogenic"
163
+ temperature_icon = TEMPERATURE_STRINGS[6].get("icon")
164
+ elif points >= 10:
165
+ point_classification = "oncogenic"
166
+ temperature_icon = TEMPERATURE_STRINGS[6].get("icon")
167
+
168
+ temperature_class = CCV_COMPLETE_MAP[point_classification].get("color")
169
+ temperature = CCV_COMPLETE_MAP[point_classification].get("label")
170
+
171
+ if point_classification == "uncertain_significance":
172
+ temperature_class = TEMPERATURE_STRINGS[points].get("color")
173
+ temperature = TEMPERATURE_STRINGS[points].get("label")
174
+ temperature_icon = TEMPERATURE_STRINGS[points].get("icon")
175
+
176
+ return {
177
+ "points": points,
178
+ "temperature": temperature,
179
+ "temperature_class": temperature_class,
180
+ "temperature_icon": temperature_icon,
181
+ "point_classification": CCV_COMPLETE_MAP[point_classification].get("short"),
182
+ }
183
+
184
+
185
+ def get_ccv_conflicts(ccv_terms: set) -> list:
186
+ """Check potential conflict paris, return list of reference strings."""
187
+
188
+ conflicts = []
189
+ for t1, t2, reference in CCV_POTENTIAL_CONFLICTS:
190
+ if t1 in ccv_terms and t2 in ccv_terms:
191
+ conflicts.append(reference)
192
+
193
+ return conflicts
scout/utils/link.py CHANGED
@@ -36,15 +36,16 @@ def genes_by_alias(hgnc_genes):
36
36
  hgnc_symbol = gene["hgnc_symbol"]
37
37
 
38
38
  for alias in gene["previous_symbols"]:
39
+ alias = alias.upper()
39
40
  true_id = None
40
41
  if alias == hgnc_symbol:
41
42
  true_id = hgnc_id
42
43
  if alias in alias_genes:
43
- alias_genes[alias.upper()]["ids"].add(hgnc_id)
44
+ alias_genes[alias]["ids"].add(hgnc_id)
44
45
  if true_id:
45
- alias_genes[alias.upper()]["true"] = hgnc_id
46
+ alias_genes[alias]["true"] = hgnc_id
46
47
  else:
47
- alias_genes[alias.upper()] = {"true": true_id, "ids": set([hgnc_id])}
48
+ alias_genes[alias] = {"true": true_id, "ids": set([hgnc_id])}
48
49
 
49
50
  return alias_genes
50
51
 
scout/utils/md5.py CHANGED
File without changes
@@ -1,61 +1,76 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: scout-browser
3
- Version: 4.92
4
- Summary: Clinical DNA variant visualizer and browser.
5
- Home-page: https://github.com/Clinical-Genomics/scout
6
- Author: Måns Magnusson
7
- Author-email: mans.magnusson@scilifelab.se
3
+ Version: 4.95.0
4
+ Summary: Clinical DNA variant visualizer and browser
5
+ Project-URL: Repository, https://github.com/Clinical-Genomics/scout
6
+ Project-URL: Changelog, https://github.com/Clinical-Genomics/scout/blob/main/CHANGELOG.md
7
+ Project-URL: Documentation, https://clinical-genomics.github.io/scout/
8
+ Project-URL: Bug Tracker, https://github.com/Clinical-Genomics/scout/issues
9
+ Project-URL: Issues, https://github.com/Clinical-Genomics/scout/issues
10
+ Author-email: Chiara Rasi <chiara.rasi@scilifelab.se>, Daniel Nilsson <daniel.nilsson@ki.se>, Robin Andeer <robin.andeer@gmail.com>, Mans Magnuson <monsunas@gmail.com>
11
+ License: MIT License
12
+ License-File: LICENSE
13
+ Keywords: acmg,beacon,cancer,clingen-cgc-vicc,clinvar,cnv,coverage,dna,fusion,genome visualisation,lrs,matchmaker exchange,ogm,outliers,panel,panelapp,phenopacket,rna,sma,snv,str,sv,variant ranking,variant triage,variants,vcf,wes,wgs,wts
14
+ Classifier: Development Status :: 5 - Production/Stable
8
15
  Classifier: Environment :: Web Environment
9
16
  Classifier: Intended Audience :: Developers
10
- Classifier: License :: OSI Approved :: BSD License
11
- Classifier: Operating System :: OS Independent
17
+ Classifier: Intended Audience :: Science/Research
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Operating System :: MacOS :: MacOS X
20
+ Classifier: Operating System :: Unix
12
21
  Classifier: Programming Language :: Python
22
+ Classifier: Programming Language :: Python :: 3.9
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Programming Language :: Python :: 3.13
27
+ Classifier: Programming Language :: Python :: Implementation :: CPython
13
28
  Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
14
- Classifier: Topic :: Software Development :: Libraries
15
- Classifier: Programming Language :: Python :: 3.6
16
- Description-Content-Type: text/markdown
17
- License-File: LICENSE
18
- Requires-Dist: werkzeug
19
- Requires-Dist: Flask>=2.0
20
- Requires-Dist: Flask-Bootstrap
21
- Requires-Dist: Flask-CORS
22
- Requires-Dist: path.py
23
- Requires-Dist: markdown
24
- Requires-Dist: WTForms
25
- Requires-Dist: Flask-WTF
26
- Requires-Dist: Flask-Mail
27
- Requires-Dist: coloredlogs
28
- Requires-Dist: query-phenomizer
29
- Requires-Dist: Flask-Babel>=3
30
- Requires-Dist: livereload>=2.7
31
- Requires-Dist: tornado>=6.4.1
32
- Requires-Dist: python-dateutil
33
- Requires-Dist: pymongo
34
- Requires-Dist: pathlib
35
- Requires-Dist: pdfkit
36
- Requires-Dist: phenopackets
37
- Requires-Dist: xlsxwriter
29
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
30
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
31
+ Requires-Python: >=3.9
32
+ Requires-Dist: anytree
33
+ Requires-Dist: authlib
34
+ Requires-Dist: cairosvg
38
35
  Requires-Dist: click
36
+ Requires-Dist: coloredlogs
37
+ Requires-Dist: configobj
39
38
  Requires-Dist: cryptography
39
+ Requires-Dist: cyvcf2
40
40
  Requires-Dist: defusedxml
41
- Requires-Dist: svglib
42
- Requires-Dist: cairosvg
43
- Requires-Dist: importlib-resources
44
- Requires-Dist: authlib
45
- Requires-Dist: flask-login
41
+ Requires-Dist: flask-babel>=3
42
+ Requires-Dist: flask-bootstrap
43
+ Requires-Dist: flask-cors
46
44
  Requires-Dist: flask-ldapconn
47
- Requires-Dist: cyvcf2
48
- Requires-Dist: configobj
45
+ Requires-Dist: flask-login
46
+ Requires-Dist: flask-mail
47
+ Requires-Dist: flask-wtf
48
+ Requires-Dist: flask>=2.0
49
+ Requires-Dist: importlib-resources
50
+ Requires-Dist: intervaltree==3.0.2
51
+ Requires-Dist: livereload>=2.7
52
+ Requires-Dist: markdown
53
+ Requires-Dist: path-py
54
+ Requires-Dist: pathlib
55
+ Requires-Dist: pdfkit
49
56
  Requires-Dist: ped-parser
57
+ Requires-Dist: phenopackets
50
58
  Requires-Dist: pydantic>=2
51
- Requires-Dist: PyYaml>=5.1
52
- Requires-Dist: intervaltree==3.0.2
53
- Requires-Dist: anytree
59
+ Requires-Dist: pymongo
60
+ Requires-Dist: python-dateutil
61
+ Requires-Dist: pyyaml>=5.1
62
+ Requires-Dist: query-phenomizer
63
+ Requires-Dist: svglib
54
64
  Requires-Dist: tabulate
65
+ Requires-Dist: tornado>=6.4.1
66
+ Requires-Dist: werkzeug
67
+ Requires-Dist: wtforms
68
+ Requires-Dist: xlsxwriter
55
69
  Provides-Extra: coverage
56
- Requires-Dist: chanjo-report; extra == "coverage"
57
- Requires-Dist: pymysql; extra == "coverage"
58
-
70
+ Requires-Dist: chanjo-report; extra == 'coverage'
71
+ Requires-Dist: pymysql; extra == 'coverage'
72
+ Requires-Dist: python-dateutil; extra == 'coverage'
73
+ Description-Content-Type: text/markdown
59
74
 
60
75
  <p align="center">
61
76
  <a href="https://Clinical-Genomics.github.io/scout/">
@@ -126,6 +141,13 @@ cd scout
126
141
  pip install --editable .
127
142
  ```
128
143
 
144
+ Scout is configured to use `uv` if you like; either run, install, install as a tool or
145
+ ```
146
+ uv sync --frozen
147
+ uv run scout
148
+ ```
149
+
150
+
129
151
  Scout PDF reports are created using [Flask-WeasyPrint](https://pythonhosted.org/Flask-WeasyPrint/). This library requires external dependencies which need be installed separately (namely Cairo and Pango). See platform-specific instructions for Linux, macOS and Windows available on the WeasyPrint installation [pages](https://doc.courtbouillon.org/weasyprint/stable/first_steps.html#installation).
130
152
 
131
153
  <b>NB</b>: in order to convert HTML reports into PDF reports, we have recently switched from the WeasyPrint lib to [python-pdfkit](https://github.com/JazzCore/python-pdfkit). For this reason, when upgrading to a Scout version >4.47, you need to install an additional [wkhtmltopdf system library](https://wkhtmltopdf.org/).