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
@@ -514,12 +514,67 @@ MOSAICISM_OPTIONS = {
514
514
  }
515
515
 
516
516
  VARIANTS_TARGET_FROM_CATEGORY = {
517
- "sv": "variants.sv_variants",
518
517
  "cancer": "variants.cancer_variants",
519
518
  "cancer_sv": "variants.cancer_sv_variants",
519
+ "fusion": "variants.fusion_variants",
520
520
  "mei": "variants.mei_variants",
521
+ "outlier": "omics_variants.outliers",
521
522
  "snv": "variants.variants",
522
523
  "str": "variants.str_variants",
523
- "fusion": "variants.fusion_variants",
524
- "outlier": "omics_variants.outliers",
524
+ "sv": "variants.sv_variants",
525
+ }
526
+
527
+ _FREEBAYES = {"id": "freebayes", "name": "Freebayes"}
528
+ _GATK = {"id": "gatk", "name": "GATK"}
529
+ _MANTA = {"id": "manta", "name": "Manta"}
530
+ _TIDDIT = {"id": "tiddit", "name": "TIDDIT"}
531
+
532
+ CALLERS = {
533
+ "snv": [
534
+ {"id": "bcftools", "name": "Bcftools"},
535
+ {"id": "deepvariant", "name": "DeepVariant"},
536
+ _FREEBAYES,
537
+ _GATK,
538
+ {"id": "samtools", "name": "SAMtools"},
539
+ ],
540
+ "cancer": [
541
+ _FREEBAYES,
542
+ _GATK,
543
+ {"id": "mutect", "name": "MuTect"},
544
+ {"id": "pindel", "name": "Pindel"},
545
+ {"id": "tnscope", "name": "TNScope"},
546
+ {"id": "tnscope_umi", "name": "TNscope_UMI"},
547
+ {"id": "vardict", "name": "VarDict"},
548
+ ],
549
+ "cancer_sv": [
550
+ {"id": "ascat", "name": "ASCAT"},
551
+ {"id": "cnvkit", "name": "CNVkit"},
552
+ {"id": "dellysv", "name": "DellySV"},
553
+ {"id": "dellycnv", "name": "DellyCNV"},
554
+ _GATK,
555
+ {"id": "igh_dux4", "name": "IGH-DUX4 detection"},
556
+ _MANTA,
557
+ _TIDDIT,
558
+ ],
559
+ "mei": [{"id": "retroseq", "name": "RetroSeq"}],
560
+ "sv": [
561
+ {"id": "cnvnator", "name": "CNVnator"},
562
+ {"id": "cnvpytor", "name": "CNVpytor"},
563
+ {"id": "delly", "name": "Delly"},
564
+ _GATK,
565
+ {"id": "hificnv", "name": "HiFiCNV"},
566
+ _MANTA,
567
+ {"id": "severus", "name": "Severus"},
568
+ {"id": "sniffles", "name": "Sniffles"},
569
+ _TIDDIT,
570
+ ],
571
+ "str": [
572
+ {"id": "expansionhunter", "name": "ExpansionHunter"},
573
+ {"id": "trgt", "name": "TRGT"},
574
+ ],
575
+ "fusion": [
576
+ {"id": "arriba", "name": "Arriba"},
577
+ {"id": "fusioncatcher", "name": "FusionCatcher"},
578
+ {"id": "starfusion", "name": "STARfusion"},
579
+ ],
525
580
  }
scout/export/panel.py CHANGED
@@ -1,7 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import logging
3
+ from typing import List
3
4
 
5
+ from scout.adapter.mongo.base import MongoAdapter
4
6
  from scout.constants import CHROMOSOME_INTEGERS, CHROMOSOMES
7
+ from scout.constants.panels import EXPORT_PANEL_FIELDS
5
8
 
6
9
  LOG = logging.getLogger(__name__)
7
10
 
@@ -14,7 +17,6 @@ def export_panels(adapter, panels, versions=None, build="37"):
14
17
  Args:
15
18
  adapter(scout.adapter.MongoAdapter)
16
19
  panels(iterable(str)): Iterable with panel ids
17
- bed(bool): If lines should be bed formated
18
20
  """
19
21
  if versions and (len(versions) != len(panels)):
20
22
  raise SyntaxError("If version specify for each panel")
@@ -111,28 +113,30 @@ def export_panels(adapter, panels, versions=None, build="37"):
111
113
  yield gene_line
112
114
 
113
115
 
114
- def export_gene_panels(adapter, panels, version=None):
116
+ def set_export_fields(panels: list[str]) -> list[tuple]:
117
+ """Set the field that should be exported for one panel or a list of panels."""
118
+
119
+ if len(panels) == 1:
120
+ return EXPORT_PANEL_FIELDS
121
+
122
+ # if more than one panel is exported (from the CLI) - export only HGNC and symbol
123
+ return EXPORT_PANEL_FIELDS[:2]
124
+
125
+
126
+ def export_gene_panels(adapter: MongoAdapter, panels: List[str], version: float = None):
115
127
  """Export the genes of a gene panel
116
128
 
117
129
  Takes a list of gene panel names and return the lines of the gene panels.
118
130
  Unlike export_panels this function only export the genes and extra information,
119
131
  not the coordinates.
120
132
 
121
- Args:
122
- adapter(MongoAdapter)
123
- panels(list(str))
124
- version(float): Version number, only works when one panel
125
-
126
133
  Yields:
127
134
  gene panel lines
128
135
  """
136
+
129
137
  if version and len(panels) > 1:
130
138
  raise SyntaxError("Version only possible with one panel")
131
139
 
132
- bed_string = "{0}\t{1}\t{2}\t{3}\t{4}\t{5}"
133
-
134
- headers = []
135
-
136
140
  # Dictionary with hgnc ids as keys and panel gene information as value.
137
141
  panel_geneobjs = dict()
138
142
 
@@ -141,29 +145,22 @@ def export_gene_panels(adapter, panels, version=None):
141
145
  if not panel_obj:
142
146
  LOG.warning("Panel %s could not be found", panel_id)
143
147
  continue
148
+ panel_geneobjs.update({gene["hgnc_id"]: gene for gene in panel_obj.get("genes", [])})
144
149
 
145
- for gene_obj in panel_obj["genes"]:
146
- panel_geneobjs[gene_obj["hgnc_id"]] = gene_obj
147
-
148
- if len(panel_geneobjs) == 0:
150
+ if not panel_geneobjs:
149
151
  return
150
152
 
151
- headers.append(
152
- "#hgnc_id\thgnc_symbol\tdisease_associated_transcripts\t"
153
- "reduced_penetrance\tmosaicism\tdatabase_entry_version"
154
- )
155
-
156
- for header in headers:
157
- yield header
153
+ header = []
154
+ header.append("\t".join(fields[0] for fields in EXPORT_PANEL_FIELDS))
155
+ yield from header
158
156
 
159
- for hgnc_id in panel_geneobjs:
160
- gene_obj = panel_geneobjs[hgnc_id]
161
- gene_line = bed_string.format(
162
- gene_obj["hgnc_id"],
163
- gene_obj["symbol"],
164
- ",".join(gene_obj.get("disease_associated_transcripts", [])),
165
- gene_obj.get("reduced_penetrance", ""),
166
- gene_obj.get("mosaicism", ""),
167
- gene_obj.get("database_entry_version", ""),
168
- )
169
- yield gene_line
157
+ for gene_obj in panel_geneobjs.values():
158
+ gene_line_fields = [
159
+ (
160
+ ",".join(gene_obj.get(gene_key, ""))
161
+ if isinstance(gene_obj.get(gene_key), list)
162
+ else str(gene_obj.get(gene_key, ""))
163
+ )
164
+ for _, gene_key in set_export_fields(panels=panels)
165
+ ]
166
+ yield "\t".join(gene_line_fields)
scout/parse/panel.py CHANGED
@@ -85,72 +85,63 @@ def get_hgnc_identifier(gene_info, id_type="hgnc_id"):
85
85
  return None
86
86
 
87
87
 
88
- def parse_gene(gene_info):
89
- """Parse a gene line with information from a panel file
88
+ def parse_gene(gene_info: dict) -> dict:
89
+ """Parse a gene line with information from a panel file."""
90
+
91
+ def get_alias_keys_value(alias_keys: list[str]) -> List[str]:
92
+ """Collect list of strings from the alias keys present in gene_info."""
93
+ return [
94
+ item.strip()
95
+ for alias_key in alias_keys
96
+ if alias_key in gene_info
97
+ for item in gene_info[alias_key].strip('"').split(",")
98
+ if item
99
+ ]
90
100
 
91
- Args:
92
- gene_info(dict): dictionary with gene info
93
-
94
- Returns:
95
- gene(dict): A dictionary with the gene information
96
- {
97
- 'hgnc_id': int,
98
- 'hgnc_symbol': str,
99
- 'disease_associated_transcripts': list(str),
100
- 'inheritance_models': list(str),
101
- 'mosaicism': bool,
102
- 'reduced_penetrance': bool,
103
- 'database_entry_version': str,
104
- }
105
-
106
- """
107
101
  gene = {}
108
102
 
103
+ # Parse hgnc_id and handle errors
109
104
  hgnc_id = get_hgnc_identifier(gene_info, id_type="hgnc_id")
110
105
  if hgnc_id is not None:
111
106
  try:
112
107
  hgnc_id = int(hgnc_id)
113
108
  except ValueError:
114
- raise SyntaxError("Invalid hgnc id: {0}".format(hgnc_id))
109
+ raise SyntaxError(f"Invalid hgnc id: {hgnc_id}")
115
110
 
116
111
  gene["hgnc_id"] = hgnc_id
117
-
118
112
  gene["hgnc_symbol"] = get_hgnc_identifier(gene_info, id_type="hgnc_symbol")
119
113
  gene["identifier"] = hgnc_id or gene["hgnc_symbol"]
120
114
 
121
- # Disease associated transcripts is a ','-separated list of
122
- # manually curated transcripts
123
- transcripts = ""
124
- for field in PANEL_GENE_INFO_TRANSCRIPTS:
125
- if field not in gene_info:
126
- continue
127
- transcripts = gene_info[field].strip('"')
128
-
129
- gene["transcripts"] = [
130
- transcript.strip() for transcript in transcripts.split(",") if transcript
131
- ]
132
-
133
- # Genetic disease models is a ','-separated list of manually curated
134
- # inheritance patterns that are followed for a gene
135
- models = ""
136
- for field in PANEL_GENE_INFO_MODELS:
137
- if field not in gene_info:
138
- continue
139
- models = gene_info[field].strip().strip('"')
115
+ # Add list values from alias keys
116
+ gene.update(
117
+ {
118
+ "disease_associated_transcripts": get_alias_keys_value(PANEL_GENE_INFO_TRANSCRIPTS),
119
+ "inheritance_models": get_alias_keys_value(PANEL_GENE_INFO_MODELS),
120
+ "custom_inheritance_models": get_alias_keys_value(["custom_inheritance_models"]),
121
+ }
122
+ )
140
123
 
141
- # Collect whichever model provided by the user.
142
- # Then populate inheritance_models and custom_inheritance_models on gene build step
143
- gene["inheritance_models"] = [model.strip() for model in models.split(",") if model != ""]
124
+ # Remove empty keys
125
+ gene = {k: v for k, v in gene.items() if v}
144
126
 
145
- # If a gene is known to be associated with mosaicism this is annotated
146
- gene["mosaicism"] = bool(gene_info.get("mosaicism"))
127
+ # Add boolean flags if they are True
128
+ gene.update(
129
+ {
130
+ key: True
131
+ for key in ["mosaicism", "reduced_penetrance"]
132
+ if gene_info.get(key) and gene_info.get(key) != ""
133
+ }
134
+ )
147
135
 
148
- # If a gene is known to have reduced penetrance this is annotated
149
- gene["reduced_penetrance"] = bool(gene_info.get("reduced_penetrance"))
136
+ # Add optional fields
137
+ gene.update(
138
+ {
139
+ key: gene_info[key]
140
+ for key in ["database_entry_version", "comment"]
141
+ if gene_info.get(key) and gene_info.get(key) != ""
142
+ }
143
+ )
150
144
 
151
- # The database entry version is a way to track when a a gene was added or
152
- # modified, optional
153
- gene["database_entry_version"] = gene_info.get("database_entry_version")
154
145
  return gene
155
146
 
156
147
 
@@ -383,7 +374,7 @@ def parse_panel_app_panel(
383
374
  return gene_panel
384
375
 
385
376
 
386
- def get_omim_panel_genes(genemap2_lines, mim2gene_lines, alias_genes):
377
+ def get_omim_panel_genes(genemap2_lines: list, mim2gene_lines: list, alias_genes: dict):
387
378
  """Return all genes that should be included in the OMIM-AUTO panel
388
379
  Return the hgnc symbols
389
380
 
@@ -424,6 +415,19 @@ def get_omim_panel_genes(genemap2_lines, mim2gene_lines, alias_genes):
424
415
  break
425
416
 
426
417
  if hgnc_id_info:
427
- yield {"hgnc_id": hgnc_id_info["true"], "hgnc_symbol": hgnc_symbol}
418
+ if hgnc_id_info["true"]:
419
+ hgnc_id = hgnc_id_info["true"]
420
+ elif len(hgnc_id_info.get("ids", ())) == 1:
421
+ hgnc_id = list(hgnc_id_info["ids"])[0]
422
+ LOG.warning(
423
+ "Gene symbol %s does not exist: using an apparently unique alias for hgnc_id %s",
424
+ hgnc_symbol,
425
+ hgnc_id,
426
+ )
427
+ else:
428
+ LOG.warning(
429
+ "Gene symbol %s does not exist, and as an alias it is not unique", hgnc_symbol
430
+ )
431
+ yield {"hgnc_id": hgnc_id, "hgnc_symbol": hgnc_symbol}
428
432
  else:
429
433
  LOG.warning("Gene symbol %s does not exist", hgnc_symbol)
@@ -127,6 +127,9 @@ def sashimi_igv(
127
127
  @alignviewers_bp.route(
128
128
  "/<institute_id>/<case_name>/<variant_id>/<chrom>/<start>/<stop>/igv", methods=["GET"]
129
129
  ) # from SV variant page, where you have to pass breakpoints coordinates
130
+ @alignviewers_bp.route(
131
+ "/<institute_id>/<case_name>/<chrom>/<start>/<stop>/igv", methods=["GET"]
132
+ ) # from SMN variant page
130
133
  def igv(
131
134
  institute_id: str,
132
135
  case_name: str,
@@ -20,6 +20,7 @@ from scout.constants import (
20
20
  CASE_TAGS,
21
21
  CUSTOM_CASE_REPORTS,
22
22
  DATE_DAY_FORMATTER,
23
+ GENOME_REGION,
23
24
  INHERITANCE_PALETTE,
24
25
  MITODEL_HEADER,
25
26
  MT_COV_STATS_HEADER,
@@ -282,11 +283,14 @@ def sma_case(store, institute_obj, case_obj):
282
283
 
283
284
  _populate_case_individuals(case_obj)
284
285
 
286
+ case_has_alignments(case_obj)
287
+
285
288
  data = {
286
289
  "institute": institute_obj,
287
290
  "case": case_obj,
288
291
  "comments": store.events(institute_obj, case=case_obj, comments=True),
289
292
  "events": _get_events(store, institute_obj, case_obj),
293
+ "region": GENOME_REGION[case_obj.get("genome_build", "38")],
290
294
  }
291
295
  return data
292
296
 
@@ -50,7 +50,7 @@
50
50
  </div>
51
51
  </div> <!-- end of div class row -->
52
52
 
53
- <div class="d-flex">
53
+ <span class="d-flex">
54
54
  {% if case.vcf_files.vcf_snv %}
55
55
  <span class="me-3">
56
56
  <form action="{{url_for('variants.variants', institute_id=institute._id, case_name=case.display_name) }}">
@@ -61,11 +61,19 @@
61
61
  </span>
62
62
  {% endif %}
63
63
  {% if case.vcf_files.vcf_sv %}
64
- <form action="{{url_for('variants.sv_variants', institute_id=institute._id, case_name=case.display_name) }}">
65
- <input type="hidden" id="hgnc_symbols" name="hgnc_symbols" value="SMN1, SMN2"></input>
66
- <input type="hidden" id="gene_panels" name="gene_panels" value="['']"></input>
67
- <button type="submit" class="btn btn-secondary btn-sm" target="_blank" rel="noopener" data-bs-toggle="tooltip" title="Structural variants view filtered for the genes SMN1 and SMN2">SVs</button></span>
68
- </form>
64
+ <span class="me-3">
65
+ <form action="{{url_for('variants.sv_variants', institute_id=institute._id, case_name=case.display_name) }}">
66
+ <input type="hidden" id="hgnc_symbols" name="hgnc_symbols" value="SMN1, SMN2"></input>
67
+ <input type="hidden" id="gene_panels" name="gene_panels" value="['']"></input>
68
+ <button type="submit" class="btn btn-secondary btn-sm" target="_blank" rel="noopener" data-bs-toggle="tooltip" title="Structural variants view filtered for the genes SMN1 and SMN2">SVs</button></span>
69
+ </form>
70
+ </span>
71
+ {% endif %}
72
+ {% if case.bam_files %}
73
+ <span class="me-3"><a class="btn btn-secondary btn-sm text-white" href="{{url_for('alignviewers.igv', institute_id=case['owner'], case_name=case['display_name'], chrom=region['smn1']['chrom'], start=region['smn1']['start'], stop=region['smn1']['end'] )}}" target="_blank">IGV viewer SMN1</a></span>
74
+ <span class="me-3"><a class="btn btn-secondary btn-sm text-white" href="{{url_for('alignviewers.igv', institute_id=case['owner'], case_name=case['display_name'], chrom=region['smn2']['chrom'], start=region['smn2']['start'], stop=region['smn2']['end'] )}}" target="_blank">IGV viewer SMN2</a></span>
75
+ {% else %}
76
+ <span class="me-3 text-muted">BAM file(s) missing</span>
69
77
  {% endif %}
70
78
  </div>
71
79
 
@@ -90,16 +90,24 @@
90
90
  <div href="#" class="bg-dark list-group-item text-white">
91
91
  <div class="d-flex flex-row flex-fill bd-highlight">
92
92
  <span class="menu-collapsed">Coverage (chanjo2)</span>
93
- {{ chanjo2_report_form(institute, case, case.panel_names|join(', '), 'report', case.default_genes|join(','), "<span class='fa fa-link'></span>"|safe ) }} <!--chanjo2 report-->
93
+ {{ chanjo2_report_form(institute, case, case.panel_names|join(', '), 'report', case.default_genes|join(','), "<span class='fa fa-link' style='cursor: pointer;'></span>"|safe ) }} <!--chanjo2 report-->
94
94
  </div>
95
95
  </div>
96
+ {% if "38" in case.genome_build %}
97
+ <div href="#" class="bg-dark list-group-item text-white">
98
+ <div class="d-flex flex-row flex-fill bd-highlight">
99
+ <span class="menu-collapsed">MANE Coverage (chanjo2)</span>
100
+ {{ chanjo2_report_form(institute, case, case.panel_names|join(', '), 'mane_overview', case.default_genes|join(','), "<span class='fa fa-link' style='cursor: pointer;'></span>"|safe ) }} <!--chanjo2 MANE overview-->
101
+ </div>
102
+ </div>
103
+ {% endif %}
96
104
  {% endif %}
97
105
  {% if case.chanjo_coverage %}
98
106
  <div href="#" class="bg-dark list-group-item text-white">
99
107
  <div class="d-flex flex-row flex-fill bd-highlight">
100
108
  <span class="menu-collapsed">Coverage</span>
101
109
  <form method="POST" id="coverage_html" target="_blank" rel="noopener" action="{{ url_for('report.report', sample_id=case.individual_ids, level=institute.coverage_cutoff, panel_name=case.panel_names|join(', ')) }}">
102
- <input type="hidden" name="gene_ids" value="{{ case.default_genes|join(',') }}"></input>
110
+ <input type="hidden" name="gene_ids" value="{{ case.default_genes|join(',') }}"/>
103
111
  <a href="javascript:;" onclick="document.getElementById('coverage_html').submit();">
104
112
  <span class="fa fa-link"></span></a>
105
113
  </form>
@@ -155,8 +155,13 @@
155
155
  <div class="card">
156
156
  <div class="card-header" id="heading_{{match_obj.match_oid}}">
157
157
  <h2 class="mb-0">
158
- <button class="btn btn-link collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#div_{{match_obj.match_oid}}" aria-expanded="false" aria-controls="collapseTwo">
158
+ <button class="btn btn-link collapsed" type="button" {% if match_obj.patients|length == 0 %} disabled {% endif %} data-bs-toggle="collapse" data-bs-target="#div_{{match_obj.match_oid}}" aria-expanded="false" aria-controls="collapseTwo">
159
159
  Match {{match_obj.match_date.strftime('%Y-%m-%d %H:%M')}}
160
+ {% if match_obj.patients %}
161
+ <span class="badge rounded-pill bg-success ms-3">matches: {{match_obj.patients|length}}</span>
162
+ {% else %}
163
+ <span class="badge rounded-pill bg-secondary ms-3">No matches available</span>
164
+ {% endif %}
160
165
  </button>
161
166
  </h2>
162
167
  </div>
@@ -177,14 +182,14 @@
177
182
  {% for match_result in match_obj.patients %}
178
183
  <tr class="{{ loop.cycle('odd', 'even') }}">
179
184
  <td style="width: 5%" class="border-bottom-0"><span class="badge bg-primary rounded-pill">{{match_result.score.patient|round(4)}}</td>
180
- <td style="width: 10%">{{match_result.node.label}}</td>
181
- <td style="width: 15%">
185
+ <td style="width: 10%" class="text-body"><strong>{{match_result.node.label}}</strong></td>
186
+ <td style="width: 15%" class="text-body">
182
187
  {% if "http" in match_result.patient_id %}
183
188
  <a href="{{match_result.patient_id}}" target="_blank">link</a>
184
189
  {% else %}
185
190
  <strong>{{match_result.patient_id}}</strong></td>
186
191
  {% endif %}
187
- <td style="width: 20%" class="text-break">
192
+ <td style="width: 20%" class="text-break text-body">
188
193
  {{match_result.patient.contact.name}}<br>
189
194
  {% if "http" in match_result.patient.contact.href %}
190
195
  <a href="{{match_result.patient.contact.href}}" target="_blank">contact link</a>
@@ -198,7 +203,7 @@
198
203
  <br>{{match_result.patient.contact.email|replace("mailto:","")}}
199
204
  {% endif %}
200
205
  </td>
201
- <td style="width: 35%">
206
+ <td style="width: 35%" class="text-body">
202
207
  {% for feature in match_result.patient.features %}
203
208
  <span data-bs-toggle="tooltip" title="{{feature.label or 'description not available'}}" class="badge bg-info">{{feature.label}}({{feature.id}})</span>
204
209
  {% else %}
@@ -219,10 +224,10 @@
219
224
  {% if match_result.patient.genomicFeatures%}
220
225
  <tr class="{{ loop.cycle('odd', 'even') }}">
221
226
  <td class="border-top-0"></td>
222
- <td style="width: 20%"><strong>Gene/Variants:</strong></td>
227
+ <td style="width: 20%" class="text-body"><strong>Gene/Variants:</strong></td>
223
228
  <td colspan="5">
224
229
  {% for g_feat in match_result.patient.genomicFeatures %}
225
- <div style="display: flex;">
230
+ <div style="display: flex;" class="text-body">
226
231
  <div style="margin-left: 20px;"><strong>{{loop.index}}</strong></div>
227
232
  <ul>
228
233
  <li><strong>{{ g_feat.gene._geneName}}</strong>
@@ -10,7 +10,13 @@ from pymongo.cursor import Cursor
10
10
  from werkzeug.datastructures import Headers, MultiDict
11
11
 
12
12
  from scout.adapter.mongo.base import MongoAdapter
13
- from scout.constants import CASE_STATUSES, DATE_DAY_FORMATTER, ID_PROJECTION, PHENOTYPE_GROUPS
13
+ from scout.constants import (
14
+ CASE_STATUSES,
15
+ DATE_DAY_FORMATTER,
16
+ ID_PROJECTION,
17
+ PHENOTYPE_GROUPS,
18
+ VARIANTS_TARGET_FROM_CATEGORY,
19
+ )
14
20
  from scout.server.blueprints.variant.utils import predictions, update_representative_gene
15
21
  from scout.server.extensions import beacon, store
16
22
  from scout.server.utils import institute_and_case, user_institutes
@@ -434,7 +440,7 @@ def cases(store, request, institute_id):
434
440
  data["institute"] = institute_obj
435
441
 
436
442
  name_query = request.form
437
- limit = int(request.args.get("search_limit")) if request.args.get("search_limit") else 100
443
+ limit = int(request.form.get("search_limit")) if request.form.get("search_limit") else 100
438
444
 
439
445
  data["form"] = CaseFilterForm(request.form)
440
446
 
@@ -669,7 +675,7 @@ def export_gene_variants(
669
675
  variant_line.append(variant.get("display_name")) # Position
670
676
  variant_line.append(str(variant.get("rank_score", ""))) # Score
671
677
  variant_genes = [
672
- gene.get("hgnc_symbol", gene.get("hgnc_id")) for gene in variant.get("genes", [])
678
+ gene.get("hgnc_symbol", str(gene.get("hgnc_id"))) for gene in variant.get("genes", [])
673
679
  ]
674
680
  variant_line.append(" | ".join(variant_genes)) # Genes
675
681
 
@@ -736,7 +742,8 @@ def gene_variants(store, pymongo_cursor, variant_count, page=1, per_page=50):
736
742
  def filters(store, institute_id):
737
743
  """Retrieve all filters for an institute"""
738
744
  filters = []
739
- categories = ["cancer", "snv", "str", "sv"]
745
+
746
+ categories = VARIANTS_TARGET_FROM_CATEGORY.keys()
740
747
  for category in categories:
741
748
  category_filters = store.filters(institute_id, category)
742
749
  filters.extend(category_filters)
@@ -29,7 +29,7 @@
29
29
  <div class="container-float">
30
30
  <div class="row" id="body-row"> <!--sidebar and main container are on the same row-->
31
31
  <div class="col-12">
32
- {{ variant_list_content(institute, causatives, acmg_map, callers) }}
32
+ {{ variant_list_content(institute, causatives, acmg_map, callers, inherit_palette) }}
33
33
  </div>
34
34
  </div> <!-- end of div id body-row -->
35
35
  </div>
@@ -1,5 +1,5 @@
1
1
  {% extends "layout.html" %}
2
- {% from "variants/components.html" import frequency_cell_general, variant_funct_anno_cell, variant_gene_symbols_cell, variant_region_anno_cell %}
2
+ {% from "variants/components.html" import frequency_cell_general, variant_funct_anno_cell, variant_gene_symbols_cell %}
3
3
  {% from "utils.html" import comments_table %}
4
4
  {% from "overview/institute_sidebar.html" import institute_actionbar %}
5
5
  {% from "variants/utils.html" import pagination_footer, pagination_hidden_div %}
@@ -43,7 +43,6 @@
43
43
  <th scope="col">Gene</th>
44
44
  <th scope="col">Pop Freq</th>
45
45
  <th scope="col">CADD</th>
46
- <th scope="col">Region</th>
47
46
  <th scope="col">Function</th>
48
47
  </tr>
49
48
  </thead>
@@ -56,16 +55,15 @@
56
55
  {% endif %}
57
56
  <td class="align-middle">{{ cell_rank(variant) }}</td>
58
57
  <td class="align-middle">{{ pretty_link_no_gene(variant) }} </td>
59
- <td class="align-middle">{{ variant_gene_symbols_cell(variant) }}</td>
58
+ <td class="align-middle">{{ variant_gene_symbols_cell(variant, inherit_palette) }}</td>
60
59
  <td class="align-middle">{{ frequency_cell_general(variant) }}</td>
61
60
  <td class="align-middle">{{ cell_cadd(variant) }}</td>
62
- <td class="align-middle">{{ variant_region_anno_cell(variant) }}</td>
63
61
  <td class="align-middle">{{ variant_funct_anno_cell(variant) }}</td>
64
62
  </tr>
65
63
  {% endfor %}
66
64
  {% if form.hgnc_symbols.data == [] %}
67
65
  <tr>
68
- <td colspan=7>
66
+ <td colspan=6>
69
67
  No variants to display
70
68
  </td>
71
69
  </tr>
@@ -311,7 +311,7 @@
311
311
  {% endmacro %}
312
312
 
313
313
 
314
- {% macro variant_list_content(institute, variants, acmg_map, callers) %}
314
+ {% macro variant_list_content(institute, variants, acmg_map, callers, inherit_palette) %}
315
315
  <div class="card mt-3">
316
316
  <div class="card-body overflow-auto">
317
317
  <table id="variants_table" class="table display table-sm">
@@ -348,7 +348,7 @@
348
348
  {% if variant.category == "fusion" %}
349
349
  {{ fusion_variant_gene_symbols_cell(variant) }}
350
350
  {% else %}
351
- {{ variant_gene_symbols_cell(variant) }}
351
+ {{ variant_gene_symbols_cell(variant, inherit_palette) }}
352
352
  {% endif %}
353
353
  </td>
354
354
  <td><!-- Variant link -->
@@ -58,7 +58,7 @@
58
58
  {{validated_chart()}}
59
59
  </div>
60
60
  <div class="row">
61
- <div class="col-12">{{ variant_list_content(institute, verified, acmg_map, callers) }}</div>
61
+ <div class="col-12">{{ variant_list_content(institute, verified, acmg_map, callers, inherit_palette) }}</div>
62
62
  </div>
63
63
  </div>
64
64
  </div>
@@ -6,7 +6,14 @@ from flask import Blueprint, flash, jsonify, redirect, render_template, request
6
6
  from flask_login import current_user
7
7
  from pymongo import DESCENDING
8
8
 
9
- from scout.constants import ACMG_COMPLETE_MAP, ACMG_MAP, CALLERS, VERBS_ICONS_MAP, VERBS_MAP
9
+ from scout.constants import (
10
+ ACMG_COMPLETE_MAP,
11
+ ACMG_MAP,
12
+ CALLERS,
13
+ INHERITANCE_PALETTE,
14
+ VERBS_ICONS_MAP,
15
+ VERBS_MAP,
16
+ )
10
17
  from scout.server.blueprints.variants.controllers import update_form_hgnc_symbols
11
18
  from scout.server.extensions import beacon, loqusdb, store
12
19
  from scout.server.utils import institute_and_case, jsonconverter, templated, user_institutes
@@ -63,11 +70,12 @@ def verified(institute_id):
63
70
  verified_vars = controllers.verified_vars(institute_id)
64
71
  verified_stats = controllers.verified_stats(institute_id, verified_vars)
65
72
  return dict(
73
+ acmg_map={key: ACMG_COMPLETE_MAP[value] for key, value in ACMG_MAP.items()},
74
+ callers=CALLERS,
75
+ inherit_palette=INHERITANCE_PALETTE,
66
76
  institute=institute_obj,
67
77
  verified=verified_vars,
68
78
  verified_stats=verified_stats,
69
- acmg_map={key: ACMG_COMPLETE_MAP[value] for key, value in ACMG_MAP.items()},
70
- callers=CALLERS,
71
79
  )
72
80
 
73
81
 
@@ -76,10 +84,11 @@ def verified(institute_id):
76
84
  def causatives(institute_id):
77
85
  institute_obj = institute_and_case(store, institute_id)
78
86
  return dict(
79
- institute=institute_obj,
80
- causatives=controllers.causatives(institute_obj, request),
81
87
  acmg_map={key: ACMG_COMPLETE_MAP[value] for key, value in ACMG_MAP.items()},
82
88
  callers=CALLERS,
89
+ causatives=controllers.causatives(institute_obj, request),
90
+ institute=institute_obj,
91
+ inherit_palette=INHERITANCE_PALETTE,
83
92
  )
84
93
 
85
94
 
@@ -168,7 +177,14 @@ def gene_variants(institute_id):
168
177
  store, results, result_size, page
169
178
  ) # decorated variant results, max 50 in a page
170
179
 
171
- return dict(institute=institute_obj, form=form, page=page, result_size=result_size, **data)
180
+ return dict(
181
+ institute=institute_obj,
182
+ form=form,
183
+ inherit_palette=INHERITANCE_PALETTE,
184
+ page=page,
185
+ result_size=result_size,
186
+ **data,
187
+ )
172
188
 
173
189
 
174
190
  # MOST OF THE CONTENT OF THIS ENDPOINT WILL BE REMOVED AND INCLUDED INTO THE BEACON EXTENSION UNDER SERVER/EXTENSIONS