scout-browser 4.101.0__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.
Files changed (45) hide show
  1. scout/adapter/mongo/clinvar.py +7 -7
  2. scout/adapter/mongo/hgnc.py +7 -2
  3. scout/adapter/mongo/omics_variant.py +8 -0
  4. scout/adapter/mongo/variant_loader.py +6 -2
  5. scout/constants/__init__.py +1 -0
  6. scout/constants/igv_tracks.py +6 -2
  7. scout/constants/phenotype.py +1 -0
  8. scout/load/hpo.py +8 -2
  9. scout/server/blueprints/alignviewers/controllers.py +8 -6
  10. scout/server/blueprints/alignviewers/templates/alignviewers/igv_viewer.html +2 -0
  11. scout/server/blueprints/alignviewers/templates/alignviewers/utils.html +1 -1
  12. scout/server/blueprints/cases/controllers.py +56 -28
  13. scout/server/blueprints/cases/templates/cases/case_report.html +9 -88
  14. scout/server/blueprints/cases/templates/cases/matchmaker.html +1 -1
  15. scout/server/blueprints/cases/templates/cases/phenotype.html +1 -1
  16. scout/server/blueprints/cases/templates/cases/utils.html +26 -24
  17. scout/server/blueprints/cases/views.py +32 -33
  18. scout/server/blueprints/clinvar/controllers.py +3 -2
  19. scout/server/blueprints/diagnoses/controllers.py +4 -8
  20. scout/server/blueprints/diagnoses/templates/diagnoses/diagnoses.html +1 -1
  21. scout/server/blueprints/diagnoses/templates/diagnoses/disease_term.html +1 -1
  22. scout/server/blueprints/diagnoses/views.py +2 -2
  23. scout/server/blueprints/institutes/controllers.py +107 -73
  24. scout/server/blueprints/institutes/templates/overview/cases.html +1 -1
  25. scout/server/blueprints/login/controllers.py +2 -1
  26. scout/server/blueprints/login/views.py +5 -2
  27. scout/server/blueprints/omics_variants/views.py +2 -2
  28. scout/server/blueprints/phenotypes/controllers.py +15 -2
  29. scout/server/blueprints/phenotypes/templates/phenotypes/hpo_terms.html +1 -1
  30. scout/server/blueprints/variant/controllers.py +10 -11
  31. scout/server/blueprints/variant/templates/variant/utils.html +1 -1
  32. scout/server/blueprints/variant/templates/variant/variant_details.html +68 -60
  33. scout/server/blueprints/variant/utils.py +25 -0
  34. scout/server/blueprints/variants/controllers.py +11 -42
  35. scout/server/blueprints/variants/views.py +9 -8
  36. scout/server/config.py +3 -0
  37. scout/server/extensions/beacon_extension.py +7 -2
  38. scout/server/templates/bootstrap_global.html +11 -1
  39. scout/server/templates/layout.html +6 -1
  40. scout/server/utils.py +24 -3
  41. {scout_browser-4.101.0.dist-info → scout_browser-4.102.0.dist-info}/METADATA +1 -1
  42. {scout_browser-4.101.0.dist-info → scout_browser-4.102.0.dist-info}/RECORD +45 -45
  43. {scout_browser-4.101.0.dist-info → scout_browser-4.102.0.dist-info}/WHEEL +0 -0
  44. {scout_browser-4.101.0.dist-info → scout_browser-4.102.0.dist-info}/entry_points.txt +0 -0
  45. {scout_browser-4.101.0.dist-info → scout_browser-4.102.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,10 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import logging
3
+ import re
3
4
  from datetime import datetime
4
5
  from typing import List, Optional
5
6
 
6
7
  import pymongo
7
- from bson import ObjectId
8
8
  from bson.objectid import ObjectId
9
9
  from pymongo import ReturnDocument
10
10
 
@@ -393,14 +393,14 @@ class ClinVarHandler(object):
393
393
  self.clinvar_collection.delete_one({"_id": object_id})
394
394
 
395
395
  # in any case remove reference to it in the submission object 'case_data' list field
396
- self.clinvar_submission_collection.find_one_and_update(
397
- {"_id": ObjectId(submission_id)}, {"$pull": {"case_data": object_id}}
398
- )
399
396
 
400
397
  return self.clinvar_submission_collection.find_one_and_update(
401
- {"_id": submission_id},
402
- {"$set": {"updated_at": datetime.now()}},
403
- return_document=pymongo.ReturnDocument.AFTER,
398
+ {"_id": ObjectId(submission_id)},
399
+ {
400
+ "$set": {"updated_at": datetime.now()},
401
+ "$pull": {"case_data": {"$regex": f"^{re.escape(object_id)}"}},
402
+ },
403
+ return_document=ReturnDocument.AFTER,
404
404
  )
405
405
 
406
406
  def case_to_clinVars(self, case_id):
@@ -1,5 +1,5 @@
1
1
  import logging
2
- from typing import Dict, Set
2
+ from typing import Dict, Optional, Set
3
3
 
4
4
  import intervaltree
5
5
  from pymongo.errors import BulkWriteError, DuplicateKeyError
@@ -44,7 +44,9 @@ class GeneHandler(object):
44
44
 
45
45
  return result
46
46
 
47
- def hgnc_gene_caption(self, hgnc_identifier, build=None):
47
+ def hgnc_gene_caption(
48
+ self, hgnc_identifier: Optional[int] = None, build: Optional[str] = None
49
+ ) -> Optional[dict]:
48
50
  """Fetch the current hgnc gene symbol and similar caption info for a gene in a lightweight dict
49
51
  Avoid populating transcripts, exons etc that would be added on a full gene object. Use hgnc_gene() if
50
52
  you need to use those.
@@ -57,6 +59,9 @@ class GeneHandler(object):
57
59
  gene_caption(dict): light pymongo document with keys "hgnc_symbol", "description", "chromosome", "start", "end".
58
60
  """
59
61
 
62
+ if not hgnc_identifier:
63
+ return
64
+
60
65
  query = {"hgnc_id": int(hgnc_identifier)}
61
66
 
62
67
  if build in ["37", "38"]:
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ import os
2
3
  from typing import Dict, Iterable, List, Optional
3
4
 
4
5
  from pymongo import ASCENDING, DESCENDING
@@ -130,6 +131,13 @@ class OmicsVariantHandler:
130
131
 
131
132
  nr_inserted = 0
132
133
 
134
+ file_path = case_obj["omics_files"].get(file_type) if case_obj.get("omics_files") else None
135
+ if file_path is None or os.path.exists(file_path) is False:
136
+ LOG.warning(
137
+ f"File '{file_path}' not found on disk. Please update case {case_obj['_id']} with a valid file path for {file_type}."
138
+ )
139
+ return
140
+
133
141
  file_handle = open(case_obj["omics_files"].get(file_type), "r")
134
142
 
135
143
  for omics_info in parse_omics_file(file_handle, omics_file_type=omics_file_type):
@@ -642,7 +642,6 @@ class VariantLoader(object):
642
642
  Returns:
643
643
  nr_inserted(int)
644
644
  """
645
-
646
645
  institute_id = case_obj["owner"]
647
646
 
648
647
  nr_inserted = 0
@@ -659,9 +658,14 @@ class VariantLoader(object):
659
658
  continue
660
659
 
661
660
  LOG.info(f"Loading'{vcf_file_key}' variants")
662
- variant_file = case_obj["vcf_files"].get(vcf_file_key)
661
+ variant_file = (
662
+ case_obj["vcf_files"].get(vcf_file_key) if case_obj.get("vcf_files") else None
663
+ )
663
664
 
664
665
  if not variant_file or not self._has_variants_in_file(variant_file):
666
+ LOG.warning(
667
+ f"File '{variant_file}' not found on disk. Please update case {case_obj['_id']} with a valid file path for variant category: '{category}'."
668
+ )
665
669
  continue
666
670
 
667
671
  vcf_obj = VCF(variant_file)
@@ -78,6 +78,7 @@ from .indexes import ID_PROJECTION, INDEXES
78
78
  from .panels import PANELAPP_CONFIDENCE_EXCLUDE
79
79
  from .phenotype import (
80
80
  COHORT_TAGS,
81
+ HPO_LINK_URL,
81
82
  HPO_URL,
82
83
  HPOTERMS_URL,
83
84
  ORPHA_URLS,
@@ -4,11 +4,15 @@ HG19REF_URL = (
4
4
  )
5
5
  HG19REF_INDEX_URL = "https://s3.amazonaws.com/igv.broadinstitute.org/genomes/seq/1kg_v37/human_g1k_v37_decoy.fasta.fai"
6
6
  HG19CYTOBAND_URL = "https://raw.githubusercontent.com/Clinical-Genomics/reference-files/refs/heads/master/rare-disease/region/grch37_cytoband.bed"
7
- HG19ALIAS_URL = "https://igv.org/genomes/data/hg19/hg19_alias.tab"
7
+ HG19ALIAS_URL = (
8
+ "https://raw.githubusercontent.com/igvteam/igv-data/refs/heads/main/data/hg19/hg19_alias.tab"
9
+ )
8
10
 
9
11
  HG38REF_URL = "https://s3.amazonaws.com/igv.broadinstitute.org/genomes/seq/hg38/hg38.fa"
10
12
  HG38REF_INDEX_URL = "https://s3.amazonaws.com/igv.broadinstitute.org/genomes/seq/hg38/hg38.fa.fai"
11
- HG38ALIAS_URL = "https://igv.org/genomes/data/hg38/hg38_alias.tab"
13
+ HG38ALIAS_URL = (
14
+ "https://raw.githubusercontent.com/igvteam/igv-data/refs/heads/main/data/hg38/hg38_alias.tab"
15
+ )
12
16
  HG38CYTOBAND_URL = "https://igv-genepattern-org.s3.amazonaws.com/genomes/hg38/cytoBandIdeo.txt.gz"
13
17
 
14
18
  HG38GENES_URL = "https://hgdownload.soe.ucsc.edu/goldenPath/hg38/database/ncbiRefSeq.txt.gz"
@@ -2,6 +2,7 @@ HPO_URL = "http://purl.obolibrary.org/obo/hp/hpoa/{}"
2
2
  HPOTERMS_URL = (
3
3
  "https://raw.githubusercontent.com/obophenotype/human-phenotype-ontology/master/hp.obo"
4
4
  )
5
+ HPO_LINK_URL = "https://hpo.jax.org/browse/term/"
5
6
 
6
7
  ORPHA_URLS = {
7
8
  "orpha_to_hpo": "https://www.orphadata.com/data/xml/en_product4.xml",
scout/load/hpo.py CHANGED
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  from datetime import datetime
3
- from typing import Dict, Iterable, Optional
3
+ from typing import Iterable, Optional
4
4
 
5
5
  from click import progressbar
6
6
 
@@ -45,7 +45,13 @@ def load_hpo_terms(
45
45
  if not gene_info:
46
46
  continue
47
47
 
48
- hgnc_id = gene_info["true"]
48
+ if gene_info["true"] is not None:
49
+ hgnc_id = gene_info["true"]
50
+ elif len(gene_info["ids"]) == 1:
51
+ # unique aliases can be used
52
+ hgnc_id = list(gene_info["ids"])[0]
53
+ else:
54
+ continue
49
55
 
50
56
  if hpo_id not in hpo_terms:
51
57
  continue
@@ -8,7 +8,11 @@ from flask_login import current_user
8
8
 
9
9
  from scout.constants import CASE_SPECIFIC_TRACKS, HUMAN_REFERENCE, IGV_TRACKS
10
10
  from scout.server.extensions import config_igv_tracks, store
11
- from scout.server.utils import case_append_alignments, find_index
11
+ from scout.server.utils import (
12
+ case_append_alignments,
13
+ find_index,
14
+ get_case_genome_build,
15
+ )
12
16
  from scout.utils.ensembl_rest_clients import EnsemblRestApiClient
13
17
 
14
18
  LOG = logging.getLogger(__name__)
@@ -88,7 +92,8 @@ def make_igv_tracks(
88
92
  display_obj["locus"] = "chr{0}:{1}-{2}".format(chromosome, start, stop)
89
93
 
90
94
  # Set genome build for displaying alignments:
91
- if "38" in str(case_obj.get("genome_build", "37")) or chromosome == "M":
95
+
96
+ if get_case_genome_build(case_obj) == "38" or chromosome == "M":
92
97
  build = "38"
93
98
  else:
94
99
  build = "37"
@@ -137,10 +142,7 @@ def make_sashimi_tracks(
137
142
  """
138
143
 
139
144
  locus = "All"
140
-
141
- build = "38"
142
- if "37" in str(case_obj.get("rna_genome_build", "38")):
143
- build = "37"
145
+ build = "37" if "37" in str(case_obj.get("rna_genome_build", "38")) else "38"
144
146
 
145
147
  if variant_id:
146
148
  variant_obj = store.variant(document_id=variant_id)
@@ -35,6 +35,8 @@
35
35
  $(document).ready(function () {
36
36
  var div = $("#igvDiv")[0],
37
37
  options = {
38
+ loadDefaultGenomes: false,
39
+ genomeList: "https://raw.githubusercontent.com/igvteam/igv-data/main/genomes/web/genomes.json",
38
40
  showNavigation: true,
39
41
  showRuler: true,
40
42
  {% if display_center_guide %}
@@ -1,5 +1,5 @@
1
1
  {% macro igv_script() %}
2
2
  <link rel="shortcut icon" href="//igv.org/web/img/favicon.ico">
3
3
  <!-- IGV JS-->
4
- <script src="https://cdn.jsdelivr.net/npm/igv@3.2.0/dist/igv.min.js" integrity="sha512-MHnbGQeONlQXyEs6PgiW2bhwywJW5IwUnRKfQKrPaVSrzopctBTU1VtOiEXMf/ZPBk47eFimlVRxdff+sdsyAg==" crossorigin="anonymous"></script>
4
+ <script src="https://cdn.jsdelivr.net/npm/igv@3.3.0/dist/igv.min.js" integrity="sha512-U3drIflKJksG0+kiVuqYrQaI9SsloPhKfISeZr8bzVpO/oRFz7hE1vdJirvDyYIfv51CSucKJgcLAdupqitBcQ==" crossorigin="anonymous"></script>
5
5
  {% endmacro %}
@@ -22,6 +22,7 @@ from scout.constants import (
22
22
  CUSTOM_CASE_REPORTS,
23
23
  DATE_DAY_FORMATTER,
24
24
  GENOME_REGION,
25
+ HPO_LINK_URL,
25
26
  INHERITANCE_PALETTE,
26
27
  MITODEL_HEADER,
27
28
  MT_COV_STATS_HEADER,
@@ -66,6 +67,7 @@ from scout.server.utils import (
66
67
  case_has_mt_alignments,
67
68
  case_has_mtdna_report,
68
69
  case_has_rna_tracks,
70
+ get_case_genome_build,
69
71
  get_case_mito_chromosome,
70
72
  institute_and_case,
71
73
  )
@@ -157,7 +159,12 @@ def coverage_report_contents(base_url, institute_obj, case_obj):
157
159
  return html_body_content
158
160
 
159
161
 
160
- def _populate_case_groups(store, case_obj, case_groups, case_group_label):
162
+ def _populate_case_groups(
163
+ store: MongoAdapter,
164
+ case_obj: dict,
165
+ case_groups: Dict[str, List[str]],
166
+ case_group_label: Dict[str, str],
167
+ ):
161
168
  """Case groups allow display of information about user linked cases together on one case.
162
169
  Notably variantS lists show shared annotations and alignment views show all alignments
163
170
  available for the group.
@@ -178,20 +185,21 @@ def _populate_case_groups(store, case_obj, case_groups, case_group_label):
178
185
  case_group_label[group] = store.case_group_label(group)
179
186
 
180
187
 
181
- def _get_partial_causatives(store: MongoAdapter, case_obj: Dict) -> List[Dict]:
182
- """Return any partial causatives a case has, populated as causative objs.
183
- Args:
184
- store(adapter.MongoAdapter)
185
- case_obj(models.Case)
186
- Returns:
187
- partial(list(dict))
188
+ def _get_partial_causatives(store: MongoAdapter, institute_obj: dict, case_obj: dict) -> List[Dict]:
189
+ """Check for partial causatives and associated phenotypes.
190
+ Return any partial causatives a case has, populated as causative objs.
188
191
  """
189
192
 
190
193
  partial_causatives = []
191
194
  if case_obj.get("partial_causatives"):
192
195
  for var_id, values in case_obj["partial_causatives"].items():
196
+ variant_obj = store.variant(var_id)
197
+ if variant_obj:
198
+ decorated_variant_obj = _get_decorated_var(
199
+ store, var_obj=variant_obj, institute_obj=institute_obj, case_obj=case_obj
200
+ )
193
201
  causative_obj = {
194
- "variant": store.variant(var_id) or var_id,
202
+ "variant": decorated_variant_obj or var_id,
195
203
  "disease_terms": values.get("diagnosis_phenotypes"),
196
204
  "hpo_terms": values.get("phenotype_terms"),
197
205
  }
@@ -287,7 +295,7 @@ def bionano_case(store, institute_obj, case_obj) -> Dict:
287
295
  return data
288
296
 
289
297
 
290
- def sma_case(store, institute_obj, case_obj):
298
+ def sma_case(store: MongoAdapter, institute_obj: dict, case_obj: dict) -> dict:
291
299
  """Preprocess a case for tabular view, SMA."""
292
300
 
293
301
  _populate_case_individuals(case_obj)
@@ -299,11 +307,31 @@ def sma_case(store, institute_obj, case_obj):
299
307
  "case": case_obj,
300
308
  "comments": store.events(institute_obj, case=case_obj, comments=True),
301
309
  "events": _get_events(store, institute_obj, case_obj),
302
- "region": GENOME_REGION[case_obj.get("genome_build", "38")],
310
+ "region": GENOME_REGION[get_case_genome_build(case_obj)],
303
311
  }
304
312
  return data
305
313
 
306
314
 
315
+ def _get_suspects_or_causatives(
316
+ store: MongoAdapter, institute_obj: dict, case_obj: dict, kind: str = "suspects"
317
+ ) -> list:
318
+ """Fetch the variant objects for suspects and causatives and decorate them.
319
+ If no longer available, append variant_id instead."""
320
+
321
+ marked_vars = []
322
+ for variant_id in case_obj.get(kind, []):
323
+ variant_obj = store.variant(variant_id)
324
+ if variant_obj:
325
+ marked_vars.append(
326
+ _get_decorated_var(
327
+ store, var_obj=variant_obj, institute_obj=institute_obj, case_obj=case_obj
328
+ )
329
+ )
330
+ else:
331
+ marked_vars.append(variant_id)
332
+ return marked_vars
333
+
334
+
307
335
  def case(
308
336
  store: MongoAdapter, institute_obj: dict, case_obj: dict, hide_matching: bool = True
309
337
  ) -> dict:
@@ -331,22 +359,16 @@ def case(
331
359
  case_group_label = {}
332
360
  _populate_case_groups(store, case_obj, case_groups, case_group_label)
333
361
 
334
- # Fetch the variant objects for suspects and causatives
335
- suspects = [
336
- store.variant(variant_id) or variant_id for variant_id in case_obj.get("suspects", [])
337
- ]
362
+ suspects = _get_suspects_or_causatives(store, institute_obj, case_obj, "suspects")
338
363
  _populate_assessments(suspects)
339
- causatives = [
340
- store.variant(variant_id) or variant_id for variant_id in case_obj.get("causatives", [])
341
- ]
364
+
365
+ causatives = _get_suspects_or_causatives(store, institute_obj, case_obj, "causatives")
342
366
  _populate_assessments(causatives)
343
367
 
344
- # get evaluated variants
345
368
  evaluated_variants = store.evaluated_variants(case_obj["_id"], case_obj["owner"])
346
369
  _populate_assessments(evaluated_variants)
347
370
 
348
- # check for partial causatives and associated phenotypes
349
- partial_causatives = _get_partial_causatives(store, case_obj)
371
+ partial_causatives = _get_partial_causatives(store, institute_obj, case_obj)
350
372
  _populate_assessments(partial_causatives)
351
373
 
352
374
  case_obj["clinvar_variants"] = store.case_to_clinVars(case_obj["_id"])
@@ -367,9 +389,7 @@ def case(
367
389
  for hpo_term in itertools.chain(
368
390
  case_obj.get("phenotype_groups") or [], case_obj.get("phenotype_terms") or []
369
391
  ):
370
- hpo_term["hpo_link"] = "http://hpo.jax.org/app/browse/term/{}".format(
371
- hpo_term["phenotype_id"]
372
- )
392
+ hpo_term["hpo_link"] = f"{HPO_LINK_URL}{hpo_term['phenotype_id']}"
373
393
 
374
394
  _set_rank_model_links(case_obj)
375
395
 
@@ -471,7 +491,7 @@ def case(
471
491
  "tissue_types": SAMPLE_SOURCE,
472
492
  "report_types": CUSTOM_CASE_REPORTS,
473
493
  "mme_nodes": matchmaker.connected_nodes,
474
- "gens_info": gens.connection_settings(case_obj.get("genome_build")),
494
+ "gens_info": gens.connection_settings(get_case_genome_build(case_obj)),
475
495
  "display_rerunner": rerunner.connection_settings.get("display", False),
476
496
  "hide_matching": hide_matching,
477
497
  "audits": store.case_events_by_verb(
@@ -676,7 +696,9 @@ def case_report_variants(store: MongoAdapter, case_obj: dict, institute_obj: dic
676
696
  add_bayesian_acmg_classification(var_obj)
677
697
  add_bayesian_ccv_classification(var_obj)
678
698
  evaluated_variants_by_type[eval_category].append(
679
- _get_decorated_var(var_obj=var_obj, institute_obj=institute_obj, case_obj=case_obj)
699
+ _get_decorated_var(
700
+ store, var_obj=var_obj, institute_obj=institute_obj, case_obj=case_obj
701
+ )
680
702
  )
681
703
 
682
704
  for var_obj in store.evaluated_variants(
@@ -689,7 +711,9 @@ def case_report_variants(store: MongoAdapter, case_obj: dict, institute_obj: dic
689
711
  data["variants"] = evaluated_variants_by_type
690
712
 
691
713
 
692
- def _get_decorated_var(var_obj: dict, institute_obj: dict, case_obj: dict) -> dict:
714
+ def _get_decorated_var(
715
+ store: MongoAdapter, var_obj: dict, institute_obj: dict, case_obj: dict
716
+ ) -> dict:
693
717
  """Decorate a variant object for display using the variant controller"""
694
718
  return variant_decorator(
695
719
  store=store,
@@ -719,7 +743,9 @@ def _append_evaluated_variant_by_type(
719
743
  add_bayesian_ccv_classification(var_obj)
720
744
 
721
745
  evaluated_variants_by_type[eval_category].append(
722
- _get_decorated_var(var_obj=var_obj, institute_obj=institute_obj, case_obj=case_obj)
746
+ _get_decorated_var(
747
+ store, var_obj=var_obj, institute_obj=institute_obj, case_obj=case_obj
748
+ )
723
749
  )
724
750
 
725
751
 
@@ -765,6 +791,7 @@ def case_report_content(store: MongoAdapter, institute_obj: dict, case_obj: dict
765
791
  data["genetic_models"] = dict(GENETIC_MODELS)
766
792
  data["report_created_at"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
767
793
  data["current_scout_version"] = __version__
794
+ data["hpo_link_url"] = HPO_LINK_URL
768
795
 
769
796
  case_report_variants(store, case_obj, institute_obj, data)
770
797
 
@@ -1395,6 +1422,7 @@ def matchmaker_matches(request, institute_id, case_name):
1395
1422
  pat_matches = parse_matches(patient_id, server_resp["content"]["matches"])
1396
1423
  matches[patient_id] = pat_matches
1397
1424
 
1425
+ data["hpo_link_url"] = HPO_LINK_URL
1398
1426
  data["matches"] = matches
1399
1427
  return data
1400
1428
 
@@ -2,6 +2,8 @@
2
2
  {% from "utils.html" import comments_table, variant_related_comments_table %}
3
3
  {% from "variant/gene_disease_relations.html" import inheritance_badge %}
4
4
  {% from "variants/components.html" import fusion_variants_header, default_fusion_variant_cells %}
5
+ {% from "variant/variant_details.html" import frequencies_table, old_observations_table %}
6
+ {% from "variant/components.html" import clinsig_table %}
5
7
 
6
8
  {% extends "report_base.html" %}
7
9
 
@@ -192,7 +194,7 @@
192
194
  <ul>
193
195
  {% for pheno in case.phenotype_terms %}
194
196
  <li>
195
- {{pheno.feature}} - (<a style="text-decoration:none;" href="https://hpo.jax.org/app/browse/term/{{pheno.phenotype_id}}" target="_blank">{{pheno.phenotype_id}})</a>
197
+ {{pheno.feature}} - (<a style="text-decoration:none;" href="{{ hpo_link_url }}{{pheno.phenotype_id}}" target="_blank">{{pheno.phenotype_id}})</a>
196
198
  {% for feature_ind in pheno.individuals %} <!-- display eventual individual-level HPO terms -->
197
199
  {% for case_ind in case.individuals %}
198
200
  {% if feature_ind.individual_name == case_ind.display_name %}
@@ -588,78 +590,14 @@
588
590
  <table class="table table-sm">
589
591
  <tr>
590
592
  <td style="width:60%;">
591
- {{ genotype_table(variant) }}
593
+ {{ genotype_table(variant) }}<br>
594
+ {{ clinsig_table(variant) }}
592
595
  </td>
593
596
  <td style="width:3%"></td>
594
597
  <td>
595
- <table id="panel-table" class="table table-sm" style="background-color: transparent">
596
- <thead>
597
- <tr>
598
- <th>Pop. frequency
599
- {% if variant.frequency == 'common' %}
600
- <span class="badge bg-danger">{{variant.frequency}}</span>
601
- {% elif variant.frequency == 'uncommon' %}
602
- <span class="badge bg-warning text-dark">{{variant.frequency}}</span>
603
- {% else %}
604
- <span class="badge bg-success">{{variant.frequency}}</span>
605
- {% endif %}
606
- </th>
607
- <th>
608
- </th>
609
- </tr>
610
- </thead>
611
- <tbody>
612
- <tr>
613
- <td>
614
- {% if variant.dbsnp_id %}
615
- <a style="text-decoration:none;" href="{{ variant.thousandg_link }}" rel="noopener" target="_blank">1000G</a>
616
- {% else %}
617
- 1000G
618
- {% endif %}
619
- </td>
620
- <td>
621
- {% if variant.max_thousand_genomes_frequency %}
622
- {{ variant.max_thousand_genomes_frequency|human_decimal }} <small>(max)</small> |
623
- {% endif %}
624
- {{ variant.thousand_genomes_frequency|human_decimal if variant.thousand_genomes_frequency }}
625
- {% if not variant.max_thousand_genomes_frequency and not variant.thousand_genomes_frequency %}
626
- <span class="text-muted">Not annotated</span>
627
- {% endif %}
628
- </td>
629
- </tr>
630
- <tr>
631
- <td><a style="text-decoration:none;" title="Exome Aggregation Consortium" rel="noopener" target="_blank" href="{{ variant.exac_link }}">ExAC</a></td>
632
- <td>
633
- {% if variant.max_exac_frequency %}
634
- {{ variant.max_exac_frequency|human_decimal }} <small>(max)</small> |
635
- {% endif %}
636
- {{ variant.exac_frequency|human_decimal if variant.exac_frequency }}
637
- {% if not variant.max_exac_frequency and not variant.exac_frequency %}
638
- <span class="text-muted">Not annotated</span>
639
- {% endif %}
640
- </td>
641
- </tr>
642
- <tr>
643
- <td><a style="text-decoration:none;" title="genome Aggregation Database" rel="noopener" target="_blank" href="{{ variant.gnomad_link }}">gnomAD</a></td>
644
- <td>
645
- {% if 'gnomad_frequency' in variant%}
646
- {% if variant.max_gnomad_frequency %}
647
- {{ variant.max_gnomad_frequency|human_decimal }}
648
- <small>(max)</small> |
649
- {% endif %}
650
- {{ variant.gnomad_frequency|human_decimal if variant.gnomad_frequency }}
651
- {% else %}
652
- <span class="text-muted">Not annotated</span>
653
- {% endif %}
654
- </td>
655
- <td>
656
- </td>
657
- </tr>
658
- </tbody>
659
- </table>
598
+ {{ frequencies_table(variant) }}
599
+ {{ old_observations_table(variant) }}
660
600
  </td>
661
- </tr>
662
- </table>
663
601
  <table id="panel-table" class="table table-sm" style="background-color: transparent">
664
602
  <thead>
665
603
  <tr>
@@ -1074,25 +1012,8 @@
1074
1012
  </td>
1075
1013
  <td style="width:3%"></td>
1076
1014
  <td>
1077
- <table id="panel-table" class="table table-sm" style="background-color: transparent">
1078
- <thead>
1079
- <th colspan=2>Pop. frequency</th>
1080
- </thead>
1081
- <tbody>
1082
- {% for freq_name, value, link in variant.frequencies %}
1083
- <tr>
1084
- <td>{{ freq_name }}</td>
1085
- <td>
1086
- {% if value %}
1087
- <span class="badge bg-secondary">{{ value|human_decimal }}</span>
1088
- {% else %}
1089
- <span class="text-muted">Not annotated</span>
1090
- {% endif %}
1091
- </td>
1092
- </tr>
1093
- {% endfor %}
1094
- </tbody>
1095
- </table>
1015
+ {{ frequencies_table(variant) }}
1016
+ {{ old_observations_table(variant) }}
1096
1017
  </td>
1097
1018
  </tr>
1098
1019
  </table>
@@ -85,7 +85,7 @@
85
85
  <ul class="list-group list-group-flush">
86
86
  {% for hpo in case.mme_submission.features %}
87
87
  <li class="list-group-item">
88
- <a class="text-white" target="_blank" href="http://hpo.jax.org/app/browse/term/{{hpo.id}}">
88
+ <a class="text-white" target="_blank" href="{{hpo_link_url}}{{hpo.id}}">
89
89
  <span class="badge bg-sm bg-info">{{hpo.id}}</span>
90
90
  </a>{{hpo.label}}
91
91
  </li>
@@ -191,7 +191,7 @@
191
191
  {% endmacro %}
192
192
 
193
193
  {% macro hpo_panel(case, institute, config) %}
194
- {% set url = 'https://hpo.jax.org/app/' %}
194
+ {% set url = 'https://hpo.jax.org/' %}
195
195
  <div id="phenotypes_panel" class="panel-heading">
196
196
  <h6 class="mt-3"><span class="fa fa-stethoscope"></span>&nbsp;Phenotype terms (<a target="_blank" class="" href="{{ url }}" rel="noopener">HPO</a>)</h6>
197
197
  </div>
@@ -293,8 +293,18 @@
293
293
 
294
294
  {% if variant.category %}
295
295
  {% if variant.category in "str" %}
296
- {{ variant.str_repid }} {{ variant.alternative | replace("<", " ") | replace(">", "")}}
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", "str", "snv", "cancer") %}
343
- {% if variant.category == "cancer" %}
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
- {% else %}
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
- {{ pretty_variant(variant) }}
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
- {% if variant.category == "snv" %}
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="http://hpo.jax.org/app/browse/term/{{hpo.phenotype_id}}">
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 %}