scout-browser 4.100.2__py3-none-any.whl → 4.102.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scout/adapter/mongo/case.py +20 -6
- scout/adapter/mongo/clinvar.py +7 -7
- scout/adapter/mongo/hgnc.py +7 -2
- scout/adapter/mongo/omics_variant.py +8 -0
- scout/adapter/mongo/variant_loader.py +6 -2
- scout/constants/__init__.py +1 -0
- scout/constants/file_types.py +1 -1
- scout/constants/igv_tracks.py +6 -2
- scout/constants/phenotype.py +1 -0
- scout/load/hpo.py +8 -2
- scout/server/blueprints/alignviewers/controllers.py +8 -6
- scout/server/blueprints/alignviewers/templates/alignviewers/igv_viewer.html +2 -0
- scout/server/blueprints/alignviewers/templates/alignviewers/utils.html +1 -1
- scout/server/blueprints/cases/controllers.py +56 -28
- scout/server/blueprints/cases/templates/cases/case_report.html +9 -88
- scout/server/blueprints/cases/templates/cases/matchmaker.html +1 -1
- scout/server/blueprints/cases/templates/cases/phenotype.html +1 -1
- scout/server/blueprints/cases/templates/cases/utils.html +27 -25
- scout/server/blueprints/cases/views.py +32 -33
- scout/server/blueprints/clinvar/controllers.py +18 -23
- scout/server/blueprints/clinvar/templates/clinvar/multistep_add_variant.html +0 -2
- scout/server/blueprints/diagnoses/controllers.py +4 -8
- scout/server/blueprints/diagnoses/templates/diagnoses/diagnoses.html +1 -1
- scout/server/blueprints/diagnoses/templates/diagnoses/disease_term.html +1 -1
- scout/server/blueprints/diagnoses/views.py +2 -2
- scout/server/blueprints/institutes/controllers.py +107 -73
- scout/server/blueprints/institutes/templates/overview/cases.html +8 -7
- scout/server/blueprints/login/controllers.py +2 -1
- scout/server/blueprints/login/views.py +5 -2
- scout/server/blueprints/omics_variants/views.py +2 -2
- scout/server/blueprints/panels/views.py +11 -2
- scout/server/blueprints/phenotypes/controllers.py +15 -2
- scout/server/blueprints/phenotypes/templates/phenotypes/hpo_terms.html +1 -1
- scout/server/blueprints/variant/controllers.py +10 -11
- scout/server/blueprints/variant/templates/variant/utils.html +1 -1
- scout/server/blueprints/variant/templates/variant/variant_details.html +68 -60
- scout/server/blueprints/variant/utils.py +25 -0
- scout/server/blueprints/variants/controllers.py +11 -42
- scout/server/blueprints/variants/templates/variants/cancer-variants.html +3 -3
- scout/server/blueprints/variants/templates/variants/indicators.html +18 -15
- scout/server/blueprints/variants/templates/variants/utils.html +1 -1
- scout/server/blueprints/variants/views.py +9 -8
- scout/server/config.py +3 -0
- scout/server/extensions/beacon_extension.py +7 -2
- scout/server/templates/bootstrap_global.html +11 -1
- scout/server/templates/layout.html +6 -1
- scout/server/utils.py +24 -3
- {scout_browser-4.100.2.dist-info → scout_browser-4.102.0.dist-info}/METADATA +1 -1
- {scout_browser-4.100.2.dist-info → scout_browser-4.102.0.dist-info}/RECORD +52 -52
- {scout_browser-4.100.2.dist-info → scout_browser-4.102.0.dist-info}/WHEEL +0 -0
- {scout_browser-4.100.2.dist-info → scout_browser-4.102.0.dist-info}/entry_points.txt +0 -0
- {scout_browser-4.100.2.dist-info → scout_browser-4.102.0.dist-info}/licenses/LICENSE +0 -0
@@ -293,8 +293,18 @@
|
|
293
293
|
|
294
294
|
{% if variant.category %}
|
295
295
|
{% if variant.category in "str" %}
|
296
|
-
{
|
297
|
-
|
296
|
+
{% if variant.str_repid %}
|
297
|
+
{{ variant.str_repid }}
|
298
|
+
{% elif variant.str_trid %}
|
299
|
+
{{ variant.str_trid }}
|
300
|
+
{% else %}
|
301
|
+
{% for gene in variant.genes %} {{ gene.symbol }} {% endfor %}
|
302
|
+
{% endif %}
|
303
|
+
{% if variant.str_mc %}
|
304
|
+
STR{{ variant.str_mc }}
|
305
|
+
{% else %}
|
306
|
+
{{ variant.alternative|truncate(20,True) }}
|
307
|
+
{% endif %}
|
298
308
|
{% elif variant.category in ("snv", "cancer") %}
|
299
309
|
{% set display_genes = [] %}
|
300
310
|
{% for gene in variant.genes %}
|
@@ -339,18 +349,24 @@
|
|
339
349
|
{% macro pretty_link_variant(variant, case) %}
|
340
350
|
{# Returns human readable links to the corresponding variant page #}
|
341
351
|
|
342
|
-
{% if variant.category in ("mei", "
|
343
|
-
{
|
344
|
-
<a href='{{ url_for('variant.cancer_variant',
|
352
|
+
{% if variant.category in ("mei", "snv") %}
|
353
|
+
<a href='{{ url_for('variant.variant',
|
345
354
|
institute_id=variant.institute,
|
346
355
|
case_name=case.display_name,
|
347
356
|
variant_id=variant._id) }}' target='_blank'>
|
348
|
-
|
357
|
+
{% elif variant.category == "str" %}
|
349
358
|
<a href='{{ url_for('variant.variant',
|
359
|
+
institute_id=variant.institute,
|
360
|
+
case_name=case.display_name,
|
361
|
+
variant_id=variant._id) }}'
|
362
|
+
data-bs-toggle='tooltip'
|
363
|
+
title='{{ variant.alternative | replace("<", " ") | replace(">", "")}}'
|
364
|
+
target='_blank'>
|
365
|
+
{% elif variant.category == "cancer" %}
|
366
|
+
<a href='{{ url_for('variant.cancer_variant',
|
350
367
|
institute_id=variant.institute,
|
351
368
|
case_name=case.display_name,
|
352
369
|
variant_id=variant._id) }}' target='_blank'>
|
353
|
-
{% endif %}
|
354
370
|
{% elif variant.category == "outlier" %}
|
355
371
|
<a href='{{ url_for('omics_variants.outliers',
|
356
372
|
institute_id=variant.institute, case_name=case.display_name) }}' target='_blank'>
|
@@ -360,7 +376,7 @@
|
|
360
376
|
case_name=case.display_name,
|
361
377
|
variant_id=variant._id) }}' target='_blank'>
|
362
378
|
{% endif %}
|
363
|
-
|
379
|
+
{{ pretty_variant(variant) }}
|
364
380
|
</a>
|
365
381
|
{% endmacro %}
|
366
382
|
|
@@ -442,21 +458,7 @@
|
|
442
458
|
<div class="row">
|
443
459
|
<div class="col">
|
444
460
|
<i class="far fa-check-circle"></i>
|
445
|
-
{
|
446
|
-
<a href="{{ url_for('variant.variant',
|
447
|
-
institute_id=variant.institute,
|
448
|
-
case_name=case.display_name,
|
449
|
-
variant_id=variant._id) }}">
|
450
|
-
{{ variant.hgnc_symbols|join(', ') }} (partial causative)
|
451
|
-
{% else %}
|
452
|
-
<a href="{{ url_for('variant.sv_variant',
|
453
|
-
institute_id=variant.institute,
|
454
|
-
case_name=case.display_name,
|
455
|
-
variant_id=variant._id) }}">
|
456
|
-
{{ variant.sub_category|upper }}({{ variant.chromosome }}{{ variant.cytoband_start }}-{{ variant.chromosome }}{{ variant.cytoband_end }})
|
457
|
-
(partial causative)
|
458
|
-
{% endif %}
|
459
|
-
</a>
|
461
|
+
{{ pretty_link_variant(variant, case) }} (partial causative)
|
460
462
|
</div>
|
461
463
|
<div class="col-2" style="width:fit-content;">
|
462
464
|
{{ remove_form(url_for('cases.mark_causative',
|
@@ -495,7 +497,7 @@
|
|
495
497
|
</div>
|
496
498
|
<div class="col-8">
|
497
499
|
{% for hpo in variant_phenotypes.hpo_terms %}
|
498
|
-
<a target="_blank" href="
|
500
|
+
<a target="_blank" href="https://hpo.jax.org/browse/term/{{hpo.phenotype_id}}">
|
499
501
|
<span class="badge badge-sm bg-info">{{hpo.phenotype_id}}</span>
|
500
502
|
</a>
|
501
503
|
{% else %}
|
@@ -627,7 +629,7 @@
|
|
627
629
|
(included in ClinVar submission)
|
628
630
|
{% elif variant.category in ('cancer', 'cancer_sv') %}
|
629
631
|
<button data-bs-toggle='tooltip' data-bs-placement="bottom" title="Submission of somatic variants from Scout is temporarily suspended. We are working to harmonize submissions with changes introduced by ClinVar for this variant category." disabled >Add to ClinVar submission</button>
|
630
|
-
{%
|
632
|
+
{% elif variant.category in ('snv', 'sv') %}
|
631
633
|
<button type="submit" name="var_id" value="{{variant._id}}" class="btn btn-secondary btn-sm" style="float: right;">Add to ClinVar submission</button>
|
632
634
|
{% endif %}
|
633
635
|
</form>
|
@@ -36,6 +36,7 @@ from scout.server.utils import (
|
|
36
36
|
html_to_pdf_file,
|
37
37
|
institute_and_case,
|
38
38
|
jsonconverter,
|
39
|
+
safe_redirect_back,
|
39
40
|
templated,
|
40
41
|
user_cases,
|
41
42
|
user_institutes,
|
@@ -148,7 +149,7 @@ def beacon_add_variants(institute_id, case_name):
|
|
148
149
|
store, institute_id, case_name
|
149
150
|
) # This function checks if user has permissions to access the case
|
150
151
|
beacon.add_variants(store, case_obj, request.form)
|
151
|
-
return
|
152
|
+
return safe_redirect_back(request)
|
152
153
|
|
153
154
|
|
154
155
|
@cases_bp.route("/beacon_remove_variants/<institute_id>/<case_name>", methods=["GET"])
|
@@ -158,7 +159,7 @@ def beacon_remove_variants(institute_id, case_name):
|
|
158
159
|
store, institute_id, case_name
|
159
160
|
) # This function checks if user has permissions to access the case
|
160
161
|
beacon.remove_variants(store, institute_id, case_obj)
|
161
|
-
return
|
162
|
+
return safe_redirect_back(request)
|
162
163
|
|
163
164
|
|
164
165
|
@cases_bp.route("/<institute_id>/<case_name>/mme_matches", methods=["GET", "POST"])
|
@@ -175,7 +176,7 @@ def matchmaker_match(institute_id, case_name, target):
|
|
175
176
|
"""Starts an internal match or a match against one or all MME external nodes"""
|
176
177
|
institute_obj, case_obj = institute_and_case(store, institute_id, case_name)
|
177
178
|
match_results = controllers.matchmaker_match(request, target, institute_id, case_name)
|
178
|
-
return
|
179
|
+
return safe_redirect_back(request)
|
179
180
|
|
180
181
|
|
181
182
|
@cases_bp.route("/<institute_id>/<case_name>/mme_add", methods=["POST"])
|
@@ -183,7 +184,7 @@ def matchmaker_add(institute_id, case_name):
|
|
183
184
|
"""Add or update a case in MatchMaker"""
|
184
185
|
# Call matchmaker_delete controller to add a patient to MatchMaker
|
185
186
|
controllers.matchmaker_add(request, institute_id, case_name)
|
186
|
-
return
|
187
|
+
return safe_redirect_back(request)
|
187
188
|
|
188
189
|
|
189
190
|
@cases_bp.route("/<institute_id>/<case_name>/mme_delete", methods=["POST"])
|
@@ -191,7 +192,7 @@ def matchmaker_delete(institute_id, case_name):
|
|
191
192
|
"""Remove a case from MatchMaker"""
|
192
193
|
# Call matchmaker_delete controller to delete a patient from MatchMaker
|
193
194
|
controllers.matchmaker_delete(request, institute_id, case_name)
|
194
|
-
return
|
195
|
+
return safe_redirect_back(request)
|
195
196
|
|
196
197
|
|
197
198
|
@cases_bp.route("/<institute_id>/<case_name>/individuals", methods=["POST"])
|
@@ -212,7 +213,7 @@ def update_individual(institute_id, case_name):
|
|
212
213
|
age=age,
|
213
214
|
tissue=tissue,
|
214
215
|
)
|
215
|
-
return
|
216
|
+
return safe_redirect_back(request)
|
216
217
|
|
217
218
|
|
218
219
|
@cases_bp.route("/<institute_id>/<case_name>/samples", methods=["POST"])
|
@@ -237,7 +238,7 @@ def update_cancer_sample(institute_id, case_name):
|
|
237
238
|
tumor_type=tumor_type,
|
238
239
|
tumor_purity=tumor_purity,
|
239
240
|
)
|
240
|
-
return
|
241
|
+
return safe_redirect_back(request)
|
241
242
|
|
242
243
|
|
243
244
|
@cases_bp.route("/<institute_id>/<case_name>/synopsis", methods=["POST"])
|
@@ -247,7 +248,7 @@ def case_synopsis(institute_id, case_name):
|
|
247
248
|
user_obj = store.user(current_user.email)
|
248
249
|
new_synopsis = request.form.get("synopsis")
|
249
250
|
controllers.update_synopsis(store, institute_obj, case_obj, user_obj, new_synopsis)
|
250
|
-
return
|
251
|
+
return safe_redirect_back(request)
|
251
252
|
|
252
253
|
|
253
254
|
@cases_bp.route("/api/v1/<institute_id>/<case_name>/case_report", methods=["GET"])
|
@@ -344,7 +345,7 @@ def mt_report(institute_id, case_name):
|
|
344
345
|
shutil.rmtree(temp_excel_dir)
|
345
346
|
|
346
347
|
flash("No MT report excel file could be exported for this sample", "warning")
|
347
|
-
return
|
348
|
+
return safe_redirect_back(request)
|
348
349
|
|
349
350
|
|
350
351
|
@cases_bp.route("/<institute_id>/<case_name>/diagnose", methods=["POST"])
|
@@ -366,7 +367,7 @@ def case_diagnosis(institute_id, case_name):
|
|
366
367
|
affected_inds=affected_inds,
|
367
368
|
remove=True if request.args.get("remove") == "yes" else False,
|
368
369
|
)
|
369
|
-
return
|
370
|
+
return safe_redirect_back(request, "#".join([link, "disease_assign"]))
|
370
371
|
|
371
372
|
|
372
373
|
@cases_bp.route("/<institute_id>/<case_name>/phenotypes", methods=["POST"])
|
@@ -414,7 +415,7 @@ def phenotypes(institute_id, case_name, phenotype_id=None):
|
|
414
415
|
)
|
415
416
|
return redirect(case_url)
|
416
417
|
|
417
|
-
return
|
418
|
+
return safe_redirect_back(request, "#".join([case_url, "phenotypes_panel"]))
|
418
419
|
|
419
420
|
|
420
421
|
@cases_bp.route("/<institute_id>/<case_name>/phenotype_export", methods=["POST"])
|
@@ -526,7 +527,7 @@ def phenotypes_actions(institute_id, case_name):
|
|
526
527
|
hgnc_ids = [result[0] for result in results if result[1] >= hpo_count]
|
527
528
|
store.update_dynamic_gene_list(case_obj, hgnc_ids=hgnc_ids, phenotype_ids=hpo_ids)
|
528
529
|
|
529
|
-
return
|
530
|
+
return safe_redirect_back(request, "#".join([case_url, "phenotypes_panel"]))
|
530
531
|
|
531
532
|
|
532
533
|
@cases_bp.route("/<institute_id>/<case_name>/events", methods=["POST"])
|
@@ -567,7 +568,7 @@ def events(institute_id, case_name, event_id=None):
|
|
567
568
|
# create a case comment
|
568
569
|
store.comment(institute_obj, case_obj, user_obj, link, content=content)
|
569
570
|
|
570
|
-
return
|
571
|
+
return safe_redirect_back(request)
|
571
572
|
|
572
573
|
|
573
574
|
@cases_bp.route("/<institute_id>/<case_name>/status", methods=["POST"])
|
@@ -588,7 +589,7 @@ def status(institute_id, case_name):
|
|
588
589
|
if tags or case_obj.get("tags") and tags != case_obj.get("tags"):
|
589
590
|
store.tag_case(institute_obj, case_obj, user_obj, tags, link)
|
590
591
|
|
591
|
-
return
|
592
|
+
return safe_redirect_back(request)
|
592
593
|
|
593
594
|
|
594
595
|
@cases_bp.route("/<institute_id>/<case_name>/assign", methods=["POST"])
|
@@ -605,7 +606,7 @@ def assign(institute_id, case_name, user_id=None, inactivate=False):
|
|
605
606
|
store.unassign(institute_obj, case_obj, user_obj, link, inactivate)
|
606
607
|
else:
|
607
608
|
store.assign(institute_obj, case_obj, user_obj, link)
|
608
|
-
return
|
609
|
+
return safe_redirect_back(request)
|
609
610
|
|
610
611
|
|
611
612
|
@cases_bp.route("/api/v1/cases", defaults={"institute_id": None})
|
@@ -688,7 +689,7 @@ def pin_variant(institute_id, case_name, variant_id):
|
|
688
689
|
store.pin_variant(institute_obj, case_obj, user_obj, link, variant_obj)
|
689
690
|
elif request.form["action"] == "DELETE":
|
690
691
|
store.unpin_variant(institute_obj, case_obj, user_obj, link, variant_obj)
|
691
|
-
return
|
692
|
+
return safe_redirect_back(request, request.referrer or link)
|
692
693
|
|
693
694
|
|
694
695
|
@cases_bp.route("/<institute_id>/<case_name>/<variant_id>/validate", methods=["POST"])
|
@@ -705,7 +706,7 @@ def mark_validation(institute_id, case_name, variant_id):
|
|
705
706
|
variant_id=variant_id,
|
706
707
|
)
|
707
708
|
store.validate(institute_obj, case_obj, user_obj, link, variant_obj, validate_type)
|
708
|
-
return
|
709
|
+
return safe_redirect_back(request, request.referrer or link)
|
709
710
|
|
710
711
|
|
711
712
|
@cases_bp.route(
|
@@ -748,8 +749,7 @@ def mark_causative(institute_id, case_name, variant_id, partial_causative=False)
|
|
748
749
|
store.unmark_causative(institute_obj, case_obj, user_obj, link, variant_obj)
|
749
750
|
|
750
751
|
# send the user back to the case that was marked as solved
|
751
|
-
|
752
|
-
return redirect(request.referrer)
|
752
|
+
return safe_redirect_back(request)
|
753
753
|
|
754
754
|
|
755
755
|
@cases_bp.route("/<institute_id>/<case_name>/check-case", methods=["POST"])
|
@@ -761,7 +761,7 @@ def check_case(institute_id, case_name):
|
|
761
761
|
store.case_collection.find_one_and_update(
|
762
762
|
{"_id": case_obj["_id"]}, {"$set": {"needs_check": False}}
|
763
763
|
)
|
764
|
-
return
|
764
|
+
return safe_redirect_back(request)
|
765
765
|
|
766
766
|
|
767
767
|
@cases_bp.route("/<institute_id>/<case_name>/report/<report_type>")
|
@@ -835,7 +835,7 @@ def share(institute_id, case_name):
|
|
835
835
|
except ValueError as ex:
|
836
836
|
flash(str(ex), "warning")
|
837
837
|
|
838
|
-
return
|
838
|
+
return safe_redirect_back(request)
|
839
839
|
|
840
840
|
|
841
841
|
@cases_bp.route("/<institute_id>/<case_name>/update_rerun_status")
|
@@ -846,7 +846,7 @@ def update_rerun_status(institute_id, case_name):
|
|
846
846
|
link = url_for("cases.case", institute_id=institute_id, case_name=case_name)
|
847
847
|
|
848
848
|
store.update_rerun_status(institute_obj, case_obj, user_obj, link)
|
849
|
-
return
|
849
|
+
return safe_redirect_back(request, link)
|
850
850
|
|
851
851
|
|
852
852
|
@cases_bp.route("/<institute_id>/<case_name>/monitor", methods=["POST"])
|
@@ -860,7 +860,7 @@ def rerun_monitor(institute_id, case_name):
|
|
860
860
|
else:
|
861
861
|
store.unmonitor(institute_obj, case_obj, user_obj, link)
|
862
862
|
|
863
|
-
return
|
863
|
+
return safe_redirect_back(request)
|
864
864
|
|
865
865
|
|
866
866
|
@cases_bp.route("/<institute_id>/<case_name>/reanalysis", methods=["POST"])
|
@@ -876,7 +876,7 @@ def reanalysis(institute_id, case_name):
|
|
876
876
|
LOG.error(msg)
|
877
877
|
flash(msg, "danger")
|
878
878
|
|
879
|
-
return
|
879
|
+
return safe_redirect_back(request)
|
880
880
|
|
881
881
|
|
882
882
|
@cases_bp.route("/<institute_id>/<case_name>/research", methods=["POST"])
|
@@ -886,7 +886,7 @@ def research(institute_id, case_name):
|
|
886
886
|
user_obj = store.user(current_user.email)
|
887
887
|
link = url_for(".case", institute_id=institute_id, case_name=case_name)
|
888
888
|
store.open_research(institute_obj, case_obj, user_obj, link)
|
889
|
-
return
|
889
|
+
return safe_redirect_back(request)
|
890
890
|
|
891
891
|
|
892
892
|
@cases_bp.route("/<institute_id>/<case_name>/reset_research", methods=["GET"])
|
@@ -895,7 +895,7 @@ def reset_research(institute_id, case_name):
|
|
895
895
|
user_obj = store.user(current_user.email)
|
896
896
|
link = url_for(".case", institute_id=institute_id, case_name=case_name)
|
897
897
|
store.reset_research(institute_obj, case_obj, user_obj, link)
|
898
|
-
return
|
898
|
+
return safe_redirect_back(request)
|
899
899
|
|
900
900
|
|
901
901
|
@cases_bp.route("/<institute_id>/<case_name>/cohorts", methods=["POST"])
|
@@ -909,7 +909,7 @@ def cohorts(institute_id, case_name):
|
|
909
909
|
store.remove_cohort(institute_obj, case_obj, user_obj, link, cohort_tag)
|
910
910
|
else:
|
911
911
|
store.add_cohort(institute_obj, case_obj, user_obj, link, cohort_tag)
|
912
|
-
return
|
912
|
+
return safe_redirect_back(request, "#".join([request.referrer, "cohorts"]))
|
913
913
|
|
914
914
|
|
915
915
|
@cases_bp.route("/<institute_id>/<case_name>/default-panels", methods=["POST"])
|
@@ -917,7 +917,7 @@ def default_panels(institute_id, case_name):
|
|
917
917
|
"""Update default panels for a case."""
|
918
918
|
panel_ids = request.form.getlist("panel_ids")
|
919
919
|
controllers.update_default_panels(store, current_user, institute_id, case_name, panel_ids)
|
920
|
-
return
|
920
|
+
return safe_redirect_back(request)
|
921
921
|
|
922
922
|
|
923
923
|
@cases_bp.route("/<institute_id>/<case_name>/update-clinical-filter-hpo", methods=["POST"])
|
@@ -928,7 +928,7 @@ def update_clinical_filter_hpo(institute_id, case_name):
|
|
928
928
|
controllers.update_clinical_filter_hpo(
|
929
929
|
store, current_user, institute_obj, case_obj, hpo_clinical_filter
|
930
930
|
)
|
931
|
-
return
|
931
|
+
return safe_redirect_back(request)
|
932
932
|
|
933
933
|
|
934
934
|
@cases_bp.route("/<institute_id>/<case_name>/add_case_group", methods=["GET", "POST"])
|
@@ -943,8 +943,7 @@ def add_case_group(institute_id, case_name):
|
|
943
943
|
case_name = request.form.get("other_case_name")
|
944
944
|
|
945
945
|
controllers.add_case_group(store, current_user, institute_id, case_name, group_id)
|
946
|
-
|
947
|
-
return redirect(request.referrer + "#case_groups")
|
946
|
+
return safe_redirect_back(request, request.referrer + "#case_groups")
|
948
947
|
|
949
948
|
|
950
949
|
@cases_bp.route("/<institute_id>/<case_name>/<case_group>/remove_case_group", methods=["GET"])
|
@@ -952,7 +951,7 @@ def remove_case_group(institute_id, case_name, case_group):
|
|
952
951
|
"""Unbind a case group from a case. Remove the group if it is no longer in use."""
|
953
952
|
controllers.remove_case_group(store, current_user, institute_id, case_name, case_group)
|
954
953
|
|
955
|
-
return
|
954
|
+
return safe_redirect_back(request, request.referrer + "#case_groups")
|
956
955
|
|
957
956
|
|
958
957
|
@cases_bp.route("/<case_group>/case_group_update_label", methods=["POST"])
|
@@ -962,7 +961,7 @@ def case_group_update_label(case_group):
|
|
962
961
|
|
963
962
|
controllers.case_group_update_label(store, case_group, label)
|
964
963
|
|
965
|
-
return
|
964
|
+
return safe_redirect_back(request, request.referrer + "#case_groups")
|
966
965
|
|
967
966
|
|
968
967
|
@cases_bp.route("/<institute_id>/<case_name>/download-hpo-genes/<category>", methods=["GET"])
|
@@ -19,6 +19,7 @@ from scout.constants.variant_tags import MANUAL_RANK_OPTIONS
|
|
19
19
|
from scout.models.clinvar import clinvar_variant
|
20
20
|
from scout.server.blueprints.variant.utils import add_gene_info
|
21
21
|
from scout.server.extensions import clinvar_api, store
|
22
|
+
from scout.server.utils import get_case_genome_build
|
22
23
|
from scout.utils.hgvs import validate_hgvs
|
23
24
|
from scout.utils.scout_requests import fetch_refseq_version
|
24
25
|
|
@@ -30,7 +31,7 @@ LOG = logging.getLogger(__name__)
|
|
30
31
|
def _get_var_tx_hgvs(case_obj: dict, variant_obj: dict) -> List[Tuple[str, str]]:
|
31
32
|
"""Retrieve all transcripts / HGVS for a given variant."""
|
32
33
|
|
33
|
-
build =
|
34
|
+
build = get_case_genome_build(case_obj)
|
34
35
|
tx_hgvs_list = [("", "Do not specify")]
|
35
36
|
case_has_build_37 = "37" in case_obj.get("genome_build", "37")
|
36
37
|
|
@@ -40,33 +41,27 @@ def _get_var_tx_hgvs(case_obj: dict, variant_obj: dict) -> List[Tuple[str, str]]
|
|
40
41
|
transcripts = gene.get("transcripts", [])
|
41
42
|
|
42
43
|
for tx in transcripts:
|
43
|
-
|
44
44
|
refseq_id = tx.get("refseq_id")
|
45
45
|
coding_seq_name = tx.get("coding_sequence_name")
|
46
46
|
if not (refseq_id and coding_seq_name):
|
47
47
|
continue # Skip transcripts missing required fields
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
)
|
65
|
-
|
66
|
-
label = f"{hgvs_simple}{'_validated_' if validated else ''}{'_mane-select_' if refseq_is_mane_select else ''}{'_mane-plus-clinical_' if refseq_is_mane_plus_clinical else ''}"
|
67
|
-
|
49
|
+
if case_has_build_37:
|
50
|
+
for refseq in tx.get("refseq_identifiers", []):
|
51
|
+
refseq_version = fetch_refseq_version(refseq)
|
52
|
+
hgvs_simple = f"{refseq_version}:{coding_seq_name}"
|
53
|
+
validated = validate_hgvs(build, hgvs_simple)
|
54
|
+
label = f"{hgvs_simple}{'_validated_' if validated else ''}"
|
55
|
+
tx_hgvs_list.append((hgvs_simple, label))
|
56
|
+
|
57
|
+
else: # build 38, collect only MANE Select or MANE Plus Clinical
|
58
|
+
mane_select = tx.get("mane_select_transcript")
|
59
|
+
mane_plus_clinical = tx.get("mane_plus_clinical_transcript")
|
60
|
+
if mane_select is None and mane_plus_clinical is None:
|
61
|
+
continue
|
62
|
+
hgvs_simple = f"{mane_select or mane_plus_clinical}:{coding_seq_name}"
|
63
|
+
label = f"{hgvs_simple}{'_mane-select_' if mane_select else ''}{'_mane-plus-clinical_' if mane_plus_clinical else ''}"
|
68
64
|
tx_hgvs_list.append((hgvs_simple, label))
|
69
|
-
|
70
65
|
return tx_hgvs_list
|
71
66
|
|
72
67
|
|
@@ -405,7 +400,7 @@ def json_api_submission(submission_id):
|
|
405
400
|
|
406
401
|
# Retrieve genome build for the case submitted
|
407
402
|
case_obj = store.case(case_id=variant_data[0].get("case_id")) or {"genome_build": 37}
|
408
|
-
extra_params["assembly"] = "GRCh37" if "37" in
|
403
|
+
extra_params["assembly"] = "GRCh37" if "37" in get_case_genome_build(case_obj) else "GRCh38"
|
409
404
|
|
410
405
|
def _write_file(afile, header, lines): # Write temp CSV file
|
411
406
|
writes = csv.writer(afile, delimiter=",", quoting=csv.QUOTE_ALL)
|
@@ -154,8 +154,6 @@
|
|
154
154
|
{% endfor %}
|
155
155
|
</table>
|
156
156
|
|
157
|
-
<span class="text-danger">HGVS validation is performed only for variants in build GRCh37 or MANE Select and MANE Plus Clinical transcripts. For any other available HGVS present in this list, manual validation can be performed using the VariantValidator link above.</span>
|
158
|
-
|
159
157
|
<br><br>
|
160
158
|
<!-- dbSNP identifier -->
|
161
159
|
{{variant_data.var_form.variations_ids.label(class="fw-bold, text-dark")}}
|
@@ -1,16 +1,13 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
from scout.adapter import MongoAdapter
|
4
|
+
from scout.constants import HPO_LINK_URL
|
4
5
|
from scout.server.links import disease_link
|
5
6
|
|
6
7
|
|
7
|
-
def disease_entry(store, disease_id) -> dict:
|
8
|
+
def disease_entry(store: MongoAdapter, disease_id: str) -> dict:
|
8
9
|
"""Retrieve specific info for a disease term
|
9
10
|
|
10
|
-
Args:
|
11
|
-
store(obj): an adapter to the scout database
|
12
|
-
disease_id(str): a disease_id
|
13
|
-
|
14
11
|
Returns:
|
15
12
|
disease_obj(obj): a disease term containing description and genes
|
16
13
|
"""
|
@@ -21,6 +18,7 @@ def disease_entry(store, disease_id) -> dict:
|
|
21
18
|
store.hpo_term(hpo_id) for hpo_id in disease_obj.get("hpo_terms", [])
|
22
19
|
]
|
23
20
|
disease_obj["disease_link"] = disease_link(disease_id=disease_obj["disease_id"])
|
21
|
+
disease_obj["hpo_link_url"] = HPO_LINK_URL
|
24
22
|
return disease_obj
|
25
23
|
|
26
24
|
|
@@ -43,6 +41,4 @@ def disease_terms(store: MongoAdapter, query: str, source: str) -> dict:
|
|
43
41
|
)
|
44
42
|
disease.update({"genes": gene_ids_symbols})
|
45
43
|
|
46
|
-
|
47
|
-
|
48
|
-
return data
|
44
|
+
return {"terms": list(disease_data)}
|
@@ -95,7 +95,7 @@
|
|
95
95
|
</td>
|
96
96
|
<td id="hpo-container">
|
97
97
|
<span class="text-body">
|
98
|
-
<a id="hpo-link" class="badge bg-secondary text-white m-1" href="
|
98
|
+
<a id="hpo-link" class="badge bg-secondary text-white m-1" href="{{hpo_link_url}}{{term}}" target="_blank" rel="noopener" ></a>
|
99
99
|
</span>
|
100
100
|
</td>
|
101
101
|
</tr>
|
@@ -47,7 +47,7 @@
|
|
47
47
|
<ul class="list-group list-group-flush">
|
48
48
|
{% for pheno in hpo_complete %}
|
49
49
|
<li class="list-group-item">
|
50
|
-
<a href="
|
50
|
+
<a href="{{hpo_link_url}}{{pheno.hpo_id}}" target="_blank">{{ pheno.hpo_id }}</a>
|
51
51
|
{{pheno.description}}
|
52
52
|
</li>
|
53
53
|
{% else %}
|
@@ -2,6 +2,7 @@ from typing import Union
|
|
2
2
|
|
3
3
|
from flask import Blueprint, jsonify, request
|
4
4
|
|
5
|
+
from scout.constants import HPO_LINK_URL
|
5
6
|
from scout.server.extensions import store
|
6
7
|
from scout.server.utils import public_endpoint, templated
|
7
8
|
|
@@ -30,8 +31,7 @@ def diagnosis(disease_id):
|
|
30
31
|
def count_diagnoses():
|
31
32
|
"""Display the diagnosis counts for each coding system available in database"""
|
32
33
|
|
33
|
-
|
34
|
-
return data
|
34
|
+
return {"counts": store.disease_terminology_count(), "hpo_link_url": HPO_LINK_URL}
|
35
35
|
|
36
36
|
|
37
37
|
@omim_bp.route("/api/v1/diagnoses")
|