scout-browser 4.95.0__py3-none-any.whl → 4.97.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 (99) hide show
  1. scout/adapter/mongo/case.py +75 -70
  2. scout/adapter/mongo/filter.py +28 -11
  3. scout/adapter/mongo/institute.py +2 -0
  4. scout/adapter/mongo/omics_variant.py +20 -5
  5. scout/adapter/mongo/query.py +104 -95
  6. scout/adapter/mongo/variant.py +0 -5
  7. scout/adapter/mongo/variant_loader.py +10 -12
  8. scout/build/case.py +3 -1
  9. scout/build/individual.py +3 -11
  10. scout/commands/delete/delete_command.py +87 -49
  11. scout/commands/load/research.py +4 -4
  12. scout/commands/load/variants.py +25 -8
  13. scout/commands/setup/setup_scout.py +1 -1
  14. scout/commands/update/case.py +12 -0
  15. scout/commands/update/individual.py +1 -2
  16. scout/constants/__init__.py +7 -2
  17. scout/constants/acmg.py +25 -18
  18. scout/constants/file_types.py +68 -119
  19. scout/constants/filters.py +2 -1
  20. scout/constants/gene_tags.py +3 -3
  21. scout/constants/igv_tracks.py +7 -11
  22. scout/constants/query_terms.py +2 -2
  23. scout/demo/643594.config.yaml +6 -0
  24. scout/demo/643594.peddy.ped +1 -1
  25. scout/demo/643594.somalier.ancestry.tsv +4 -0
  26. scout/demo/643594.somalier.pairs.tsv +4 -0
  27. scout/demo/643594.somalier.samples.tsv +4 -0
  28. scout/demo/cancer.load_config.yaml +2 -3
  29. scout/demo/resources/__init__.py +1 -1
  30. scout/demo/resources/gnomad.v4.1.constraint_metrics_reduced.tsv +3755 -0
  31. scout/demo/rnafusion.load_config.yaml +1 -0
  32. scout/exceptions/database.py +1 -1
  33. scout/load/all.py +8 -16
  34. scout/models/case/case.py +1 -0
  35. scout/models/case/case_loading_models.py +15 -5
  36. scout/models/managed_variant.py +3 -3
  37. scout/models/omics_variant.py +3 -3
  38. scout/parse/case.py +113 -5
  39. scout/parse/pedqc.py +127 -0
  40. scout/parse/variant/frequency.py +9 -6
  41. scout/parse/variant/variant.py +71 -39
  42. scout/server/app.py +14 -0
  43. scout/server/blueprints/alignviewers/controllers.py +2 -0
  44. scout/server/blueprints/alignviewers/templates/alignviewers/igv_viewer.html +3 -0
  45. scout/server/blueprints/alignviewers/templates/alignviewers/utils.html +1 -1
  46. scout/server/blueprints/cases/controllers.py +25 -3
  47. scout/server/blueprints/cases/templates/cases/case.html +3 -0
  48. scout/server/blueprints/cases/templates/cases/case_report.html +28 -2
  49. scout/server/blueprints/cases/templates/cases/chanjo2_form.html +2 -2
  50. scout/server/blueprints/cases/templates/cases/collapsible_actionbar.html +12 -0
  51. scout/server/blueprints/cases/templates/cases/gene_panel.html +9 -3
  52. scout/server/blueprints/cases/templates/cases/individuals_table.html +4 -1
  53. scout/server/blueprints/cases/templates/cases/utils.html +23 -19
  54. scout/server/blueprints/cases/views.py +5 -9
  55. scout/server/blueprints/clinvar/controllers.py +12 -11
  56. scout/server/blueprints/clinvar/templates/clinvar/clinvar_submissions.html +10 -14
  57. scout/server/blueprints/clinvar/templates/clinvar/multistep_add_variant.html +15 -7
  58. scout/server/blueprints/clinvar/views.py +18 -31
  59. scout/server/blueprints/institutes/controllers.py +20 -1
  60. scout/server/blueprints/institutes/forms.py +5 -1
  61. scout/server/blueprints/institutes/templates/overview/institute_settings.html +7 -0
  62. scout/server/blueprints/institutes/templates/overview/utils.html +20 -1
  63. scout/server/blueprints/omics_variants/templates/omics_variants/outliers.html +9 -2
  64. scout/server/blueprints/omics_variants/views.py +8 -10
  65. scout/server/blueprints/variant/controllers.py +30 -1
  66. scout/server/blueprints/variant/templates/variant/cancer-variant.html +21 -5
  67. scout/server/blueprints/variant/templates/variant/components.html +26 -9
  68. scout/server/blueprints/variant/templates/variant/variant.html +4 -2
  69. scout/server/blueprints/variant/templates/variant/variant_details.html +1 -1
  70. scout/server/blueprints/variant/utils.py +2 -0
  71. scout/server/blueprints/variant/views.py +10 -3
  72. scout/server/blueprints/variants/controllers.py +29 -3
  73. scout/server/blueprints/variants/forms.py +37 -10
  74. scout/server/blueprints/variants/templates/variants/cancer-variants.html +5 -4
  75. scout/server/blueprints/variants/templates/variants/components.html +12 -10
  76. scout/server/blueprints/variants/templates/variants/str-variants.html +13 -9
  77. scout/server/blueprints/variants/templates/variants/utils.html +59 -36
  78. scout/server/blueprints/variants/views.py +45 -60
  79. scout/server/extensions/beacon_extension.py +1 -1
  80. scout/server/extensions/bionano_extension.py +5 -5
  81. scout/server/extensions/chanjo2_extension.py +40 -1
  82. scout/server/extensions/chanjo_extension.py +1 -1
  83. scout/server/extensions/clinvar_extension.py +56 -2
  84. scout/server/extensions/matchmaker_extension.py +1 -1
  85. scout/server/links.py +0 -14
  86. scout/server/static/bs_styles.css +2 -0
  87. scout/server/templates/layout.html +1 -0
  88. scout/server/utils.py +5 -0
  89. scout/utils/acmg.py +5 -5
  90. scout/utils/ensembl_biomart_clients.py +2 -11
  91. scout/utils/scout_requests.py +1 -1
  92. {scout_browser-4.95.0.dist-info → scout_browser-4.97.0.dist-info}/METADATA +1 -1
  93. {scout_browser-4.95.0.dist-info → scout_browser-4.97.0.dist-info}/RECORD +96 -94
  94. scout/demo/resources/gnomad.v4.0.constraint_metrics_reduced.tsv +0 -3755
  95. scout/parse/peddy.py +0 -149
  96. scout/utils/sort.py +0 -21
  97. {scout_browser-4.95.0.dist-info → scout_browser-4.97.0.dist-info}/WHEEL +0 -0
  98. {scout_browser-4.95.0.dist-info → scout_browser-4.97.0.dist-info}/entry_points.txt +0 -0
  99. {scout_browser-4.95.0.dist-info → scout_browser-4.97.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,15 +1,17 @@
1
1
  import logging
2
+ from typing import List, Optional, Tuple
2
3
 
3
4
  import click
4
5
  from flask import current_app, url_for
5
6
  from flask.cli import with_appcontext
6
7
 
7
- from scout.constants import CASE_STATUSES
8
+ from scout.adapter.mongo import MongoAdapter
9
+ from scout.constants import ANALYSIS_TYPES, CASE_STATUSES, VARIANTS_TARGET_FROM_CATEGORY
8
10
  from scout.server.extensions import store
9
11
 
10
12
  LOG = logging.getLogger(__name__)
11
13
 
12
- BYTES_IN_ONE_GIGABYTE = 1073741824 # (1024*1024*1024)
14
+ BYTES_IN_ONE_GIGABYTE = 1073741824
13
15
  DELETE_VARIANTS_HEADER = [
14
16
  "Case n.",
15
17
  "Ncases",
@@ -23,8 +25,55 @@ DELETE_VARIANTS_HEADER = [
23
25
  "Total variants",
24
26
  "Removed variants",
25
27
  ]
28
+ VARIANT_CATEGORIES = list(VARIANTS_TARGET_FROM_CATEGORY.keys())
26
29
 
27
- VARIANT_CATEGORIES = ["mei", "snv", "sv", "cancer", "cancer_sv", "str"]
30
+
31
+ def _set_keep_ctg(keep_ctg: Tuple[str], rm_ctg: Tuple[str]) -> List[str]:
32
+ """Define the categories of variants that should not be removed."""
33
+ if keep_ctg and rm_ctg:
34
+ raise click.UsageError("Please use either '--keep-ctg' or '--rm-ctg', not both.")
35
+ if keep_ctg:
36
+ return list(keep_ctg)
37
+ if rm_ctg:
38
+ return list(set(VARIANT_CATEGORIES).difference(set(rm_ctg)))
39
+ return []
40
+
41
+
42
+ def get_case_ids(case_file: Optional[str], case_id: List[str]) -> List[str]:
43
+ """Fetch the _id of the cases to remove variants from."""
44
+ if case_file and case_id:
45
+ click.echo(
46
+ "You should specify either case ID (multiple times if needed) or the path to a text file containing a list of case IDs (one per line)."
47
+ )
48
+ return []
49
+ return (
50
+ [line.strip() for line in open(case_file).readlines() if line.strip()]
51
+ if case_file
52
+ else list(case_id)
53
+ )
54
+
55
+
56
+ def handle_delete_variants(
57
+ store: MongoAdapter, keep_ctg: List[str], dry_run: bool, variants_query: dict
58
+ ) -> Tuple[int]:
59
+ """Handle variant removal for a case or count how many variants would be removed if it's a simulation.."""
60
+
61
+ if dry_run:
62
+ remove_n_variants = store.variant_collection.count_documents(variants_query)
63
+ remove_n_omics_variants = (
64
+ store.omics_variant_collection.count_documents(variants_query)
65
+ if "outlier" not in keep_ctg
66
+ else 0
67
+ )
68
+ else:
69
+ remove_n_variants = store.variant_collection.delete_many(variants_query).deleted_count
70
+ remove_n_omics_variants = (
71
+ store.omics_variant_collection.delete_many(variants_query).deleted_count
72
+ if "outlier" not in keep_ctg
73
+ else 0
74
+ )
75
+
76
+ return remove_n_variants, remove_n_omics_variants
28
77
 
29
78
 
30
79
  @click.command("variants", short_help="Delete variants for one or more cases")
@@ -47,18 +96,25 @@ VARIANT_CATEGORIES = ["mei", "snv", "sv", "cancer", "cancer_sv", "str"]
47
96
  @click.option("--older-than", type=click.INT, default=0, help="Older than (months)")
48
97
  @click.option(
49
98
  "--analysis-type",
50
- type=click.Choice(["wgs", "wes", "panel"]),
99
+ type=click.Choice(ANALYSIS_TYPES),
51
100
  multiple=True,
52
101
  help="Type of analysis",
53
102
  )
54
103
  @click.option("--rank-threshold", type=click.INT, default=5, help="With rank threshold lower than")
55
104
  @click.option("--variants-threshold", type=click.INT, help="With more variants than")
105
+ @click.option(
106
+ "--rm-ctg",
107
+ type=click.Choice(VARIANT_CATEGORIES),
108
+ multiple=True,
109
+ required=False,
110
+ help="Remove only the following categories",
111
+ )
56
112
  @click.option(
57
113
  "--keep-ctg",
58
114
  type=click.Choice(VARIANT_CATEGORIES),
59
115
  multiple=True,
60
116
  required=False,
61
- help="Do not delete one of more variant categories",
117
+ help="Keep the following categories",
62
118
  )
63
119
  @click.option(
64
120
  "--dry-run",
@@ -68,43 +124,38 @@ VARIANT_CATEGORIES = ["mei", "snv", "sv", "cancer", "cancer_sv", "str"]
68
124
  @with_appcontext
69
125
  def variants(
70
126
  user: str,
71
- case_id: list,
127
+ case_id: tuple,
72
128
  case_file: str,
73
129
  institute: str,
74
- status: list,
130
+ status: tuple,
75
131
  older_than: int,
76
- analysis_type: list,
132
+ analysis_type: tuple,
77
133
  rank_threshold: int,
78
134
  variants_threshold: int,
79
- keep_ctg: list,
135
+ rm_ctg: tuple,
136
+ keep_ctg: tuple,
80
137
  dry_run: bool,
81
138
  ) -> None:
82
139
  """Delete variants for one or more cases"""
83
140
 
84
- if case_file and case_id:
85
- click.echo(
86
- "You should specify either case ID (multiple times if needed) or the path to a text file containing a list of case IDs (one per line)."
87
- )
88
- return
89
-
90
141
  user_obj = store.user(user)
91
142
  if user_obj is None:
92
143
  click.echo(f"Could not find a user with email '{user}' in database")
93
144
  return
94
145
 
146
+ case_ids = get_case_ids(case_file=case_file, case_id=case_id)
147
+
95
148
  total_deleted = 0
96
- items_name = "deleted variants"
149
+
97
150
  if dry_run:
98
151
  click.echo("--------------- DRY RUN COMMAND ---------------")
99
152
  items_name = "estimated deleted variants"
100
153
  else:
101
154
  click.confirm("Variants are going to be deleted from database. Continue?", abort=True)
102
-
103
- if case_file:
104
- case_id = [line.strip() for line in open(case_file).readlines() if line.strip()]
155
+ items_name = "deleted variants"
105
156
 
106
157
  case_query = store.build_case_query(
107
- case_ids=case_id,
158
+ case_ids=case_ids,
108
159
  institute_id=institute,
109
160
  status=status,
110
161
  older_than=older_than,
@@ -120,10 +171,15 @@ def variants(
120
171
  f"Rank-score threshold:{rank_threshold}, case n. variants threshold:{variants_threshold}."
121
172
  )
122
173
  click.echo("\t".join(DELETE_VARIANTS_HEADER))
174
+ keep_ctg = _set_keep_ctg(keep_ctg=keep_ctg, rm_ctg=rm_ctg)
175
+
123
176
  for nr, case in enumerate(cases, 1):
177
+
124
178
  case_id = case["_id"]
125
179
  institute_id = case["owner"]
126
- case_n_variants = store.variant_collection.count_documents({"case_id": case_id})
180
+ case_n_variants = store.variant_collection.count_documents(
181
+ {"case_id": case_id}
182
+ ) + store.omics_variant_collection.count_documents({"case_id": case_id})
127
183
  # Skip case if user provided a number of variants to keep and this number is less than total number of case variants
128
184
  if variants_threshold and case_n_variants < variants_threshold:
129
185
  continue
@@ -136,36 +192,15 @@ def variants(
136
192
  variants_to_keep = (
137
193
  case.get("suspects", []) + case.get("causatives", []) + evaluated_not_dismissed or []
138
194
  )
139
- variants_query = store.delete_variants_query(
195
+
196
+ variants_query: dict = store.delete_variants_query(
140
197
  case_id, variants_to_keep, rank_threshold, keep_ctg
141
198
  )
142
199
 
143
- if dry_run:
144
- # Just print how many variants would be removed for this case
145
- remove_n_variants = store.variant_collection.count_documents(variants_query)
146
- total_deleted += remove_n_variants
147
- click.echo(
148
- "\t".join(
149
- [
150
- str(nr),
151
- str(n_cases),
152
- case["owner"],
153
- case["display_name"],
154
- case_id,
155
- case.get("track", ""),
156
- str(case["analysis_date"]),
157
- case.get("status", ""),
158
- str(case.get("is_research", "")),
159
- str(case_n_variants),
160
- str(remove_n_variants),
161
- ]
162
- )
163
- )
164
- continue
165
-
166
- # delete variants specified by variants_query
167
- result = store.variant_collection.delete_many(variants_query)
168
- total_deleted += result.deleted_count
200
+ remove_n_variants, remove_n_omics_variants = handle_delete_variants(
201
+ store=store, keep_ctg=keep_ctg, dry_run=dry_run, variants_query=variants_query
202
+ )
203
+ total_deleted += remove_n_variants + remove_n_omics_variants
169
204
  click.echo(
170
205
  "\t".join(
171
206
  [
@@ -179,11 +214,14 @@ def variants(
179
214
  case.get("status", ""),
180
215
  str(case.get("is_research", "")),
181
216
  str(case_n_variants),
182
- str(result.deleted_count),
217
+ str(remove_n_variants + remove_n_omics_variants),
183
218
  ]
184
219
  )
185
220
  )
186
221
 
222
+ if dry_run: # Do not create an associated event
223
+ continue
224
+
187
225
  # Create event in database
188
226
  institute_obj = store.institute(case["owner"])
189
227
  with current_app.test_request_context("/cases"):
@@ -7,7 +7,7 @@ import click
7
7
  from flask.cli import with_appcontext
8
8
 
9
9
  from scout.adapter import MongoAdapter
10
- from scout.constants import FILE_TYPE_MAP
10
+ from scout.constants import ORDERED_FILE_TYPE_MAP
11
11
  from scout.server.extensions import store
12
12
 
13
13
  LOG = logging.getLogger(__name__)
@@ -93,8 +93,8 @@ def research(case_id, institute, force):
93
93
  LOG.warning("research not requested, use '--force'")
94
94
  continue
95
95
 
96
- for file_type in FILE_TYPE_MAP:
97
- if FILE_TYPE_MAP[file_type]["variant_type"] != "research":
96
+ for file_type in ORDERED_FILE_TYPE_MAP:
97
+ if ORDERED_FILE_TYPE_MAP[file_type]["variant_type"] != "research":
98
98
  continue
99
99
 
100
100
  if case_obj["vcf_files"].get(file_type):
@@ -106,7 +106,7 @@ def research(case_id, institute, force):
106
106
  adapter=adapter,
107
107
  case_obj=case_obj,
108
108
  variant_type="research",
109
- category=FILE_TYPE_MAP[file_type]["category"],
109
+ category=ORDERED_FILE_TYPE_MAP[file_type]["category"],
110
110
  rank_treshold=default_threshold,
111
111
  )
112
112
 
@@ -1,10 +1,11 @@
1
1
  import logging
2
- from typing import Dict, List, Optional
2
+ from typing import Dict, List
3
3
 
4
4
  import click
5
5
  from flask.cli import with_appcontext
6
6
 
7
- from scout.constants import OMICS_FILE_TYPE_MAP
7
+ from scout.adapter.mongo import MongoAdapter
8
+ from scout.constants import ORDERED_OMICS_FILE_TYPE_MAP
8
9
  from scout.server.extensions import store
9
10
 
10
11
  LOG = logging.getLogger(__name__)
@@ -24,6 +25,7 @@ LOG = logging.getLogger(__name__)
24
25
  @click.option("--mei", is_flag=True, help="Upload clinical MEI variants")
25
26
  @click.option("--mei-research", is_flag=True, help="Upload research MEI variants")
26
27
  @click.option("--outlier", is_flag=True, help="Upload clinical OMICS outlier variants")
28
+ @click.option("--outlier-research", is_flag=True, help="Upload research OMICS outlier variants")
27
29
  @click.option("--sv", is_flag=True, help="Upload clinical structural variants")
28
30
  @click.option("--sv-research", is_flag=True, help="Upload research structural variants")
29
31
  @click.option("--snv", is_flag=True, help="Upload clinical SNV variants")
@@ -57,6 +59,7 @@ def variants(
57
59
  mei,
58
60
  mei_research,
59
61
  outlier,
62
+ outlier_research,
60
63
  sv,
61
64
  sv_research,
62
65
  snv,
@@ -118,6 +121,11 @@ def variants(
118
121
  "variant_type": "clinical",
119
122
  "upload": outlier,
120
123
  },
124
+ {
125
+ "category": "outlier",
126
+ "variant_type": "research",
127
+ "upload": outlier_research,
128
+ },
121
129
  ]
122
130
 
123
131
  gene_obj = None
@@ -137,6 +145,14 @@ def variants(
137
145
  if keep_actions: # collect all variants with user actions for this case
138
146
  old_evaluated_variants = list(adapter.evaluated_variants(case_id, institute_id))
139
147
 
148
+ def check_research(adapter: MongoAdapter, case_obj: dict, variant_type: str, force: bool):
149
+ if variant_type == "research":
150
+ if not (force or case_obj["research_requested"]):
151
+ LOG.warning("research not requested, use '--force'")
152
+ raise click.Abort()
153
+ case_obj["is_research"] = True
154
+ adapter.update_case(case_obj=case_obj)
155
+
140
156
  def load_variant_files(
141
157
  case_obj: dict, files: List[Dict], rank_threshold: int, force: bool
142
158
  ) -> int:
@@ -150,10 +166,8 @@ def variants(
150
166
  continue
151
167
 
152
168
  i += 1
153
- if variant_type == "research":
154
- if not (force or case_obj["research_requested"]):
155
- LOG.warning("research not requested, use '--force'")
156
- raise click.Abort()
169
+
170
+ check_research(adapter, case_obj, variant_type, force)
157
171
 
158
172
  LOG.info(
159
173
  "Delete {0} {1} variants for case {2}".format(
@@ -201,6 +215,9 @@ def variants(
201
215
  continue
202
216
 
203
217
  i += 1
218
+
219
+ check_research(adapter, case_obj, variant_type, force)
220
+
204
221
  LOG.info(
205
222
  "Delete {0} {1} OMICS variants for case {2}".format(
206
223
  variant_type, category, case_obj["_id"]
@@ -211,7 +228,8 @@ def variants(
211
228
  case_id=case_obj["_id"], variant_type=variant_type, category=category
212
229
  )
213
230
 
214
- for file_type, omics_file_type in OMICS_FILE_TYPE_MAP.items():
231
+ for file_type, omics_file_type in ORDERED_OMICS_FILE_TYPE_MAP.items():
232
+
215
233
  if (
216
234
  omics_file_type["variant_type"] != variant_type
217
235
  or omics_file_type["category"] != category
@@ -237,7 +255,6 @@ def variants(
237
255
  adapter.case_variants_count(
238
256
  case_obj["_id"], institute_id, force_update_case=True
239
257
  )
240
-
241
258
  except Exception as e:
242
259
  LOG.warning(e)
243
260
  raise click.Abort()
@@ -186,7 +186,7 @@ def database(
186
186
  resource_files["genemap_path"] = str(path.resolve())
187
187
  if path.stem == "hgnc":
188
188
  resource_files["hgnc_path"] = str(path.resolve())
189
- if path.stem == "gnomad.v4.0.constraint_metrics":
189
+ if path.stem == "gnomad.v4.1.constraint_metrics":
190
190
  resource_files["constraint_path"] = str(path.resolve())
191
191
  if path.stem == "ensembl_genes_37":
192
192
  resource_files["genes37_path"] = str(path.resolve())
@@ -21,10 +21,18 @@ LOG = logging.getLogger(__name__)
21
21
  "--fraser",
22
22
  help="Path to clinical WTS OMICS outlier FRASER TSV file to be added - NB variants are NOT loaded",
23
23
  )
24
+ @click.option(
25
+ "--fraser-research",
26
+ help="Path to research WTS OMICS outlier FRASER TSV file to be added - NB variants are NOT loaded",
27
+ )
24
28
  @click.option(
25
29
  "--outrider",
26
30
  help="Path to clinical WTS OMICS outlier OUTRIDER TSV file to be added - NB variants are NOT loaded",
27
31
  )
32
+ @click.option(
33
+ "--outrider-research",
34
+ help="Path to research WTS OMICS outlier OUTRIDER TSV file to be added - NB variants are NOT loaded",
35
+ )
28
36
  @click.option(
29
37
  "--rna-genome-build",
30
38
  type=click.Choice(["37", "38"]),
@@ -100,7 +108,9 @@ def case(
100
108
  institute,
101
109
  collaborator,
102
110
  fraser,
111
+ fraser_research,
103
112
  outrider,
113
+ outrider_research,
104
114
  vcf,
105
115
  vcf_sv,
106
116
  vcf_str,
@@ -166,7 +176,9 @@ def case(
166
176
 
167
177
  for key_name, key in [
168
178
  ("fraser", fraser),
179
+ ("fraser_research", fraser_research),
169
180
  ("outrider", outrider),
181
+ ("outrider_research", outrider_research),
170
182
  ]:
171
183
  if key is None:
172
184
  continue
@@ -1,5 +1,4 @@
1
- """Code for updating information on individuals
2
- """
1
+ """Code for updating information on individuals"""
3
2
 
4
3
  from pathlib import Path
5
4
 
@@ -45,7 +45,7 @@ from .disease_parsing import (
45
45
  MIMNR_PATTERN,
46
46
  OMIM_STATUS_MAP,
47
47
  )
48
- from .file_types import FILE_TYPE_MAP, OMICS_FILE_TYPE_MAP
48
+ from .file_types import ORDERED_FILE_TYPE_MAP, ORDERED_OMICS_FILE_TYPE_MAP
49
49
  from .filters import (
50
50
  CLINICAL_FILTER_BASE,
51
51
  CLINICAL_FILTER_BASE_CANCER,
@@ -64,7 +64,12 @@ from .gene_tags import (
64
64
  PANEL_GENE_INFO_TRANSCRIPTS,
65
65
  UPDATE_GENES_RESOURCES,
66
66
  )
67
- from .igv_tracks import CASE_SPECIFIC_TRACKS, HUMAN_REFERENCE, IGV_TRACKS, USER_DEFAULT_TRACKS
67
+ from .igv_tracks import (
68
+ CASE_SPECIFIC_TRACKS,
69
+ HUMAN_REFERENCE,
70
+ IGV_TRACKS,
71
+ USER_DEFAULT_TRACKS,
72
+ )
68
73
  from .indexes import ID_PROJECTION, INDEXES
69
74
  from .panels import PANELAPP_CONFIDENCE_EXCLUDE
70
75
  from .phenotype import (
scout/constants/acmg.py CHANGED
@@ -309,48 +309,55 @@ ACMG_CRITERIA["benign impact"] = OrderedDict(
309
309
 
310
310
  ACMG_POTENTIAL_CONFLICTS = [
311
311
  (
312
- "PVS1",
313
- "PM4",
312
+ {"PVS1", "PM4"},
314
313
  "Use of PVS1 and PM4 together risks double-counting evidence (Tayoun et al 2019).",
315
314
  ),
316
315
  (
317
- "PVS1",
318
- "PM1",
316
+ {"PVS1", "PM1"},
319
317
  "Use of PVS1 and PM1 together is not recommended (Durkie et al 2024).",
320
318
  ),
321
319
  (
322
- "PVS1",
323
- "PP2",
320
+ {"PVS1", "PP2"},
324
321
  "Use of PVS1 and PP2 together is not recommended (Durkie et al 2024).",
325
322
  ),
326
323
  (
327
- "PVS1",
328
- "PS3",
324
+ {"PVS1", "PS3"},
329
325
  "Note that for RNA PS3 should only be taken with PVS1 for well established functional assays, not splicing alone (Walker 2023).",
330
326
  ),
331
327
  (
332
- "PS1",
333
- "PM4",
328
+ {"PS1", "PM4"},
334
329
  "Use of PS1 and PM4 together is not recommended (Durkie et al 2024).",
335
330
  ),
336
331
  (
337
- "PS1",
338
- "PM5",
332
+ {"PS1", "PM5"},
339
333
  "Use of PS1 and PM5 together conflicts with original definition (Richards et al 2015).",
340
334
  ),
341
335
  (
342
- "PS1",
343
- "PP3",
336
+ {"PS1", "PP3"},
344
337
  "Use of PS1 and PP3 together risks double-counting evidence (Tayoun et al 2019).",
345
338
  ),
346
339
  (
347
- "PS2",
348
- "PM6",
340
+ {"PS2", "PM6"},
349
341
  "Use of PS2 and PM6 together conflicts with original definition (Richards et al 2015).",
350
342
  ),
351
343
  (
352
- "PM1",
353
- "PP2",
344
+ {"PM1", "PP2"},
354
345
  "Avoid double-counting evidence for constraints in both PM1 and PP2 (Durkie et al 2024).",
355
346
  ),
347
+ (
348
+ {"PP1", "PP4"},
349
+ "When applying phenotype specificity and segregation data together, a point-system is available from ClinGen SVI (Biesecker et al 2024).",
350
+ ),
351
+ (
352
+ {"BS4", "PP4"},
353
+ "When applying phenotype specificity and segregation data together, a point-system is available from ClinGen SVI (Biesecker et al 2024).",
354
+ ),
355
+ (
356
+ {"PS2", "PP4"},
357
+ "Consider using PS2 without the PP4 criterion, based on the SVI Recommendation for de novo Criteria (PS2 & PM6).",
358
+ ),
359
+ (
360
+ {"PM6", "PP4"},
361
+ "Consider using PM6 without the PP4 criterion, based on the SVI Recommendation for de novo Criteria (PS2 & PM6).",
362
+ ),
356
363
  ]