scout-browser 4.82.2__py3-none-any.whl → 4.84__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 (87) hide show
  1. scout/__version__.py +1 -1
  2. scout/adapter/client.py +1 -0
  3. scout/adapter/mongo/base.py +0 -1
  4. scout/adapter/mongo/case.py +19 -37
  5. scout/adapter/mongo/case_events.py +98 -2
  6. scout/adapter/mongo/hgnc.py +39 -22
  7. scout/adapter/mongo/institute.py +3 -9
  8. scout/adapter/mongo/panel.py +2 -1
  9. scout/adapter/mongo/variant.py +12 -2
  10. scout/adapter/mongo/variant_loader.py +156 -141
  11. scout/build/genes/hgnc_gene.py +5 -134
  12. scout/commands/base.py +1 -0
  13. scout/commands/download/ensembl.py +1 -0
  14. scout/commands/download/everything.py +1 -0
  15. scout/commands/download/exac.py +1 -0
  16. scout/commands/download/hgnc.py +1 -0
  17. scout/commands/download/hpo.py +1 -0
  18. scout/commands/download/omim.py +1 -0
  19. scout/commands/export/database.py +1 -0
  20. scout/commands/load/panel.py +1 -0
  21. scout/commands/load/report.py +1 -0
  22. scout/commands/update/case.py +10 -10
  23. scout/commands/update/individual.py +6 -1
  24. scout/commands/update/omim.py +1 -0
  25. scout/commands/update/panelapp.py +1 -0
  26. scout/constants/file_types.py +86 -13
  27. scout/export/exon.py +1 -0
  28. scout/load/__init__.py +0 -1
  29. scout/load/all.py +8 -5
  30. scout/load/hgnc_gene.py +1 -1
  31. scout/load/panel.py +8 -4
  32. scout/load/setup.py +1 -0
  33. scout/models/case/case_loading_models.py +6 -16
  34. scout/models/hgnc_map.py +50 -87
  35. scout/models/phenotype_term.py +3 -3
  36. scout/parse/case.py +0 -1
  37. scout/parse/disease_terms.py +1 -0
  38. scout/parse/omim.py +1 -0
  39. scout/parse/orpha.py +1 -0
  40. scout/parse/panel.py +40 -15
  41. scout/parse/variant/conservation.py +1 -0
  42. scout/resources/__init__.py +3 -0
  43. scout/server/app.py +4 -50
  44. scout/server/blueprints/alignviewers/controllers.py +15 -17
  45. scout/server/blueprints/alignviewers/templates/alignviewers/igv_viewer.html +13 -3
  46. scout/server/blueprints/alignviewers/views.py +10 -15
  47. scout/server/blueprints/cases/controllers.py +70 -73
  48. scout/server/blueprints/cases/templates/cases/case.html +94 -71
  49. scout/server/blueprints/cases/templates/cases/collapsible_actionbar.html +1 -1
  50. scout/server/blueprints/cases/templates/cases/phenotype.html +8 -6
  51. scout/server/blueprints/cases/templates/cases/utils.html +3 -3
  52. scout/server/blueprints/cases/views.py +8 -6
  53. scout/server/blueprints/panels/forms.py +1 -0
  54. scout/server/blueprints/variant/controllers.py +14 -19
  55. scout/server/blueprints/variant/templates/variant/acmg.html +25 -16
  56. scout/server/blueprints/variant/templates/variant/components.html +11 -6
  57. scout/server/blueprints/variant/views.py +5 -2
  58. scout/server/blueprints/variants/controllers.py +12 -28
  59. scout/server/blueprints/variants/views.py +1 -1
  60. scout/server/config.py +16 -4
  61. scout/server/extensions/__init__.py +4 -2
  62. scout/server/extensions/beacon_extension.py +1 -0
  63. scout/server/extensions/bionano_extension.py +1 -0
  64. scout/server/extensions/chanjo_extension.py +59 -0
  65. scout/server/extensions/gens_extension.py +1 -0
  66. scout/server/extensions/ldap_extension.py +5 -3
  67. scout/server/extensions/loqus_extension.py +16 -14
  68. scout/server/extensions/matchmaker_extension.py +1 -0
  69. scout/server/extensions/mongo_extension.py +1 -0
  70. scout/server/extensions/phenopacket_extension.py +1 -0
  71. scout/server/extensions/rerunner_extension.py +1 -0
  72. scout/server/links.py +4 -4
  73. scout/server/static/bs_styles.css +20 -2
  74. scout/server/utils.py +16 -2
  75. scout/utils/acmg.py +33 -20
  76. scout/utils/ensembl_rest_clients.py +1 -0
  77. scout/utils/scout_requests.py +1 -0
  78. scout/utils/sort.py +21 -0
  79. scout/utils/track_resources.py +70 -0
  80. {scout_browser-4.82.2.dist-info → scout_browser-4.84.dist-info}/METADATA +2 -5
  81. {scout_browser-4.82.2.dist-info → scout_browser-4.84.dist-info}/RECORD +85 -84
  82. {scout_browser-4.82.2.dist-info → scout_browser-4.84.dist-info}/WHEEL +1 -1
  83. {scout_browser-4.82.2.dist-info → scout_browser-4.84.dist-info}/entry_points.txt +0 -1
  84. scout/load/case.py +0 -36
  85. scout/utils/cloud_resources.py +0 -61
  86. {scout_browser-4.82.2.dist-info → scout_browser-4.84.dist-info}/LICENSE +0 -0
  87. {scout_browser-4.82.2.dist-info → scout_browser-4.84.dist-info}/top_level.txt +0 -0
@@ -27,12 +27,12 @@ from scout.parse.variant.headers import (
27
27
  from scout.parse.variant.ids import parse_simple_id
28
28
  from scout.parse.variant.managed_variant import parse_managed_variant_id
29
29
  from scout.parse.variant.rank_score import parse_rank_score
30
+ from scout.utils.sort import get_load_priority
30
31
 
31
32
  LOG = logging.getLogger(__name__)
32
33
 
33
34
 
34
35
  class VariantLoader(object):
35
-
36
36
  """Methods to handle variant loading in the mongo adapter"""
37
37
 
38
38
  def update_variant(self, variant_obj):
@@ -201,87 +201,88 @@ class VariantLoader(object):
201
201
  """
202
202
 
203
203
  case_id = case_obj["_id"]
204
- # Possible categories 'snv', 'sv', 'str', 'cancer', 'cancer_sv':
205
- categories = set()
206
- # Possible variant types 'clinical', 'research':
207
- variant_types = set()
208
-
209
- for file_type in FILE_TYPE_MAP:
210
- if case_obj.get("vcf_files", {}).get(file_type):
211
- categories.add(FILE_TYPE_MAP[file_type]["category"])
212
- variant_types.add(FILE_TYPE_MAP[file_type]["variant_type"])
204
+ # Possible categories 'snv', 'sv', 'str', 'cancer', 'cancer_sv'. Sort according to load order to ensure Cancer SNVs before
205
+ # Cancer SVs, in particular, and keep a consistent variant_id collision resolution order.
206
+ # Possible variant types are 'clinical', 'research'.
207
+ load_variants = {
208
+ (FILE_TYPE_MAP[file_type]["variant_type"], FILE_TYPE_MAP[file_type]["category"])
209
+ for file_type in FILE_TYPE_MAP
210
+ if case_obj.get("vcf_files", {}).get(file_type)
211
+ }
213
212
 
214
213
  coding_intervals = self.get_coding_intervals(build=build)
215
214
  # Loop over all intervals
216
215
  for chrom in CHROMOSOMES:
217
216
  intervals = coding_intervals.get(chrom, IntervalTree())
218
- for var_type in variant_types:
219
- for category in categories:
220
- LOG.info(
221
- "Updating compounds on chromosome:{0}, type:{1}, category:{2} for case:{3}".format(
222
- chrom, var_type, category, case_id
223
- )
217
+ for var_type, category in sorted(
218
+ list(load_variants),
219
+ key=lambda tup: get_load_priority(variant_type=tup[0], category=tup[1]),
220
+ ):
221
+ LOG.info(
222
+ "Updating compounds on chromosome:{0}, type:{1}, category:{2} for case:{3}".format(
223
+ chrom, var_type, category, case_id
224
224
  )
225
+ )
225
226
 
226
- # Fetch all variants from a chromosome
227
- query = {"variant_type": var_type, "chrom": chrom}
227
+ # Fetch all variants from a chromosome
228
+ query = {"variant_type": var_type, "chrom": chrom}
228
229
 
229
- # Get all variants from the database of the specific type
230
- variant_objs = self.variants(
231
- case_id=case_id,
232
- query=query,
233
- category=category,
234
- nr_of_variants=-1,
235
- sort_key="position",
236
- )
230
+ # Get all variants from the database of the specific type
231
+ variant_objs = self.variants(
232
+ case_id=case_id,
233
+ query=query,
234
+ category=category,
235
+ nr_of_variants=-1,
236
+ sort_key="position",
237
+ )
237
238
 
238
- # Initiate a bulk
239
- bulk = {}
240
- current_region = None
241
- special = False
239
+ # Initiate a bulk
240
+ bulk = {}
241
+ current_region = None
242
+ special = False
242
243
 
243
- # Loop over the variants and check if they are in a coding region
244
- for var_obj in variant_objs:
245
- var_id = var_obj["_id"]
246
- var_chrom = var_obj["chromosome"]
247
- var_start = var_obj["position"]
248
- var_end = var_obj["end"] + 1
244
+ # Loop over the variants and check if they are in a coding region
245
+ for var_obj in variant_objs:
246
+ var_id = var_obj["_id"]
247
+ var_chrom = var_obj["chromosome"]
248
+ var_start = var_obj["position"]
249
+ var_end = var_obj["end"] + 1
249
250
 
250
- update_bulk = True
251
- new_region = None
251
+ update_bulk = True
252
+ new_region = None
252
253
 
253
- # Check if the variant is in a coding region
254
- genomic_regions = coding_intervals.get(var_chrom, IntervalTree()).overlap(
255
- var_start, var_end
256
- )
254
+ # Check if the variant is in a coding region
255
+ genomic_regions = coding_intervals.get(var_chrom, IntervalTree()).overlap(
256
+ var_start, var_end
257
+ )
257
258
 
258
- # If the variant is in a coding region
259
- if genomic_regions:
260
- # We know there is data here so get the interval id
261
- new_region = genomic_regions.pop().data
259
+ # If the variant is in a coding region
260
+ if genomic_regions:
261
+ # We know there is data here so get the interval id
262
+ new_region = genomic_regions.pop().data
262
263
 
263
- if new_region and (new_region == current_region):
264
- # If the variant is in the same region as previous
265
- # we add it to the same bulk
266
- update_bulk = False
264
+ if new_region and (new_region == current_region):
265
+ # If the variant is in the same region as previous
266
+ # we add it to the same bulk
267
+ update_bulk = False
267
268
 
268
- current_region = new_region
269
+ current_region = new_region
269
270
 
270
- # If the variant is not in a current region we update the compounds
271
- # from the previous region, if any. Otherwise continue
272
- if update_bulk and bulk:
273
- self.update_compounds(bulk)
274
- self.update_mongo_compound_variants(bulk)
275
- bulk = {}
271
+ # If the variant is not in a current region we update the compounds
272
+ # from the previous region, if any. Otherwise continue
273
+ if update_bulk and bulk:
274
+ self.update_compounds(bulk)
275
+ self.update_mongo_compound_variants(bulk)
276
+ bulk = {}
276
277
 
277
- if new_region:
278
- bulk[var_id] = var_obj
278
+ if new_region:
279
+ bulk[var_id] = var_obj
279
280
 
280
- if not bulk:
281
- continue
281
+ if not bulk:
282
+ continue
282
283
 
283
- self.update_compounds(bulk)
284
- self.update_mongo_compound_variants(bulk)
284
+ self.update_compounds(bulk)
285
+ self.update_mongo_compound_variants(bulk)
285
286
 
286
287
  LOG.info("All compounds updated")
287
288
 
@@ -363,6 +364,9 @@ class VariantLoader(object):
363
364
  sample_info=None,
364
365
  custom_images=None,
365
366
  local_archive_info=None,
367
+ gene_to_panels=None,
368
+ hgncid_to_gene=None,
369
+ genomic_intervals=None,
366
370
  ):
367
371
  """Perform the loading of variants
368
372
 
@@ -389,10 +393,6 @@ class VariantLoader(object):
389
393
  nr_inserted(int)
390
394
  """
391
395
  build = build or "37"
392
- genes = [gene_obj for gene_obj in self.all_genes(build=build)]
393
- gene_to_panels = self.gene_to_panels(case_obj)
394
- hgncid_to_gene = self.hgncid_to_gene(genes=genes, build=build)
395
- genomic_intervals = self.get_coding_intervals(genes=genes, build=build)
396
396
 
397
397
  LOG.info("Start inserting {0} {1} variants into database".format(variant_type, category))
398
398
  start_insertion = datetime.now()
@@ -611,6 +611,16 @@ class VariantLoader(object):
611
611
  is not None
612
612
  )
613
613
 
614
+ def _has_variants_in_file(self, variant_file: str) -> bool:
615
+ """Check if variant file has any variants."""
616
+ try:
617
+ vcf_obj = VCF(variant_file)
618
+ var = next(vcf_obj)
619
+ return True
620
+ except StopIteration as err:
621
+ LOG.warning("Variant file %s does not include any variants", variant_file)
622
+ return False
623
+
614
624
  def load_variants(
615
625
  self,
616
626
  case_obj,
@@ -649,7 +659,7 @@ class VariantLoader(object):
649
659
 
650
660
  nr_inserted = 0
651
661
 
652
- variant_file = None
662
+ variant_files = []
653
663
  for vcf_file_key in FILE_TYPE_MAP.keys():
654
664
  if FILE_TYPE_MAP[vcf_file_key]["variant_type"] != variant_type:
655
665
  continue
@@ -658,85 +668,90 @@ class VariantLoader(object):
658
668
 
659
669
  LOG.debug("Attempt to load %s %s VCF.", variant_type, category.upper())
660
670
  variant_file = case_obj["vcf_files"].get(vcf_file_key)
671
+ if variant_file:
672
+ variant_files.append(variant_file)
661
673
 
662
- if not variant_file:
674
+ if not variant_files:
663
675
  raise SyntaxError(
664
- "VCF file {} {} does not seem to exist".format(category, variant_type)
676
+ "VCF files for {} {} does not seem to exist".format(category, variant_type)
665
677
  )
666
678
 
667
- # Check if there are any variants in file
668
- try:
679
+ gene_to_panels = self.gene_to_panels(case_obj)
680
+ genes = [gene_obj for gene_obj in self.all_genes(build=build)]
681
+ hgncid_to_gene = self.hgncid_to_gene(genes=genes, build=build)
682
+ genomic_intervals = self.get_coding_intervals(genes=genes, build=build)
683
+
684
+ for variant_file in variant_files:
685
+ if not self._has_variants_in_file(variant_file):
686
+ continue
687
+
669
688
  vcf_obj = VCF(variant_file)
670
- var = next(vcf_obj)
671
- except StopIteration as err:
672
- LOG.warning("Variant file %s does not include any variants", variant_file)
673
- return nr_inserted
674
- # We need to reload the file
675
- vcf_obj = VCF(variant_file)
676
-
677
- # Parse the neccessary headers from vcf file
678
- rank_results_header = parse_rank_results_header(vcf_obj)
679
-
680
- local_archive_info = parse_local_archive_header(vcf_obj)
681
-
682
- vep_header = parse_vep_header(vcf_obj)
683
- if vep_header:
684
- LOG.info("Found VEP header %s", "|".join(vep_header))
685
-
686
- # This is a dictionary to tell where ind are in vcf
687
- individual_positions = {}
688
- for i, ind in enumerate(vcf_obj.samples):
689
- individual_positions[ind] = i
690
-
691
- # Dictionary for cancer analysis
692
- sample_info = {}
693
- if category in ("cancer", "cancer_sv"):
694
- for ind in case_obj["individuals"]:
695
- if ind["phenotype"] == 2:
696
- sample_info[ind["individual_id"]] = "case"
697
- else:
698
- sample_info[ind["individual_id"]] = "control"
699
-
700
- # Check if a region scould be uploaded
701
- region = ""
702
- if gene_obj:
703
- chrom = gene_obj["chromosome"]
704
- # Add same padding as VEP
705
- start = max(gene_obj["start"] - 5000, 0)
706
- end = gene_obj["end"] + 5000
707
- if chrom:
708
- # We want to load all variants in the region regardless of rank score
709
- rank_threshold = rank_threshold or -1000
710
- if not (start and end):
711
- raise SyntaxError("Specify chrom start and end")
712
- region = "{0}:{1}-{2}".format(chrom, start, end)
713
- else:
714
- rank_threshold = rank_threshold or 0
715
-
716
- variants = vcf_obj(region)
717
689
 
718
- try:
719
- nr_inserted = self._load_variants(
720
- variants=variants,
721
- variant_type=variant_type,
722
- case_obj=case_obj,
723
- individual_positions=individual_positions,
724
- rank_threshold=rank_threshold,
725
- institute_id=institute_id,
726
- build=build,
727
- rank_results_header=rank_results_header,
728
- vep_header=vep_header,
729
- category=category,
730
- sample_info=sample_info,
731
- custom_images=custom_images,
732
- local_archive_info=local_archive_info,
733
- )
734
- except Exception as error:
735
- LOG.exception("unexpected error")
736
- LOG.warning("Deleting inserted variants")
737
- self.delete_variants(case_obj["_id"], variant_type)
738
- raise error
690
+ # Parse the necessary headers from vcf file
691
+ rank_results_header = parse_rank_results_header(vcf_obj)
692
+
693
+ local_archive_info = parse_local_archive_header(vcf_obj)
694
+
695
+ vep_header = parse_vep_header(vcf_obj)
696
+ if vep_header:
697
+ LOG.debug("Found VEP header %s", "|".join(vep_header))
698
+
699
+ # This is a dictionary to tell where ind are in vcf
700
+ individual_positions = {ind: i for i, ind in enumerate(vcf_obj.samples)}
701
+
702
+ # Dictionary for cancer analysis
703
+ sample_info = {}
704
+ if category in ("cancer", "cancer_sv"):
705
+ for ind in case_obj["individuals"]:
706
+ if ind["phenotype"] == 2:
707
+ sample_info[ind["individual_id"]] = "case"
708
+ else:
709
+ sample_info[ind["individual_id"]] = "control"
710
+
711
+ # Check if a region should be uploaded
712
+ region = ""
713
+ if gene_obj:
714
+ chrom = gene_obj["chromosome"]
715
+ # Add same padding as VEP
716
+ start = max(gene_obj["start"] - 5000, 0)
717
+ end = gene_obj["end"] + 5000
718
+ if chrom:
719
+ # We want to load all variants in the region regardless of rank score
720
+ rank_threshold = rank_threshold or -1000
721
+ if not (start and end):
722
+ raise SyntaxError("Specify chrom start and end")
723
+ region = "{0}:{1}-{2}".format(chrom, start, end)
724
+ else:
725
+ rank_threshold = rank_threshold or 0
726
+
727
+ variants = vcf_obj(region)
739
728
 
740
- self.update_variant_rank(case_obj, variant_type, category=category)
729
+ try:
730
+ nr_inserted = self._load_variants(
731
+ variants=variants,
732
+ variant_type=variant_type,
733
+ case_obj=case_obj,
734
+ individual_positions=individual_positions,
735
+ rank_threshold=rank_threshold,
736
+ institute_id=institute_id,
737
+ build=build,
738
+ rank_results_header=rank_results_header,
739
+ vep_header=vep_header,
740
+ category=category,
741
+ sample_info=sample_info,
742
+ custom_images=custom_images,
743
+ local_archive_info=local_archive_info,
744
+ gene_to_panels=gene_to_panels,
745
+ hgncid_to_gene=hgncid_to_gene,
746
+ genomic_intervals=genomic_intervals,
747
+ )
748
+ except Exception as error:
749
+ LOG.exception("unexpected error")
750
+ LOG.warning("Deleting inserted variants")
751
+ self.delete_variants(case_obj["_id"], variant_type)
752
+ raise error
753
+
754
+ if nr_inserted:
755
+ self.update_variant_rank(case_obj, variant_type, category=category)
741
756
 
742
757
  return nr_inserted
@@ -1,6 +1,5 @@
1
1
  import logging
2
2
 
3
- from scout.constants import GENE_CONSTRAINT_LABELS
4
3
  from scout.models.hgnc_map import HgncGene
5
4
 
6
5
  LOG = logging.getLogger(__name__)
@@ -16,137 +15,9 @@ def build_phenotype(phenotype_info):
16
15
  return phenotype_obj
17
16
 
18
17
 
19
- def build_hgnc_gene(gene_info, build="37"):
20
- """Build a hgnc_gene object
18
+ def build_hgnc_gene(gene_info: dict, build: bool = "37") -> dict:
19
+ """Build a HGNC gene object"""
21
20
 
22
- Args:
23
- gene_info(dict): Gene information
24
-
25
- Returns:
26
- gene_obj(dict)
27
-
28
- {
29
- '_id': ObjectId(),
30
- # This is the hgnc id, required:
31
- 'hgnc_id': int,
32
- # The primary symbol, required
33
- 'hgnc_symbol': str,
34
- 'ensembl_id': str, # required
35
- 'build': str, # '37' or '38', defaults to '37', required
36
-
37
- 'chromosome': str, # required
38
- 'start': int, # required
39
- 'end': int, # required
40
-
41
- 'description': str, # Gene description
42
- 'aliases': list(), # Gene symbol aliases, includes hgnc_symbol, str
43
- 'entrez_id': int,
44
- 'omim_id': int,
45
- 'pli_score': float,
46
- 'primary_transcripts': list(), # List of refseq transcripts (str)
47
- 'ucsc_id': str,
48
- 'uniprot_ids': list(), # List of str
49
- 'vega_id': str,
50
- 'transcripts': list(), # List of hgnc_transcript
51
-
52
- # Inheritance information
53
- 'inheritance_models': list(), # List of model names
54
- 'incomplete_penetrance': bool, # Acquired from HPO
55
-
56
- # Phenotype information
57
- 'phenotypes': list(), # List of dictionaries with phenotype information
58
- }
59
- """
60
- try:
61
- hgnc_id = int(gene_info["hgnc_id"])
62
- except KeyError as err:
63
- raise KeyError("Gene has to have a hgnc_id")
64
- except ValueError as err:
65
- raise ValueError("hgnc_id has to be integer")
66
-
67
- try:
68
- hgnc_symbol = gene_info["hgnc_symbol"]
69
- except KeyError as err:
70
- raise KeyError("Gene has to have a hgnc_symbol")
71
-
72
- try:
73
- ensembl_id = gene_info["ensembl_gene_id"]
74
- except KeyError as err:
75
- raise KeyError("Gene has to have a ensembl_id")
76
-
77
- try:
78
- chromosome = gene_info["chromosome"]
79
- except KeyError as err:
80
- raise KeyError("Gene has to have a chromosome")
81
-
82
- try:
83
- start = int(gene_info["start"])
84
- except KeyError as err:
85
- raise KeyError("Gene has to have a start position")
86
- except TypeError as err:
87
- raise TypeError("Gene start has to be a integer")
88
-
89
- try:
90
- end = int(gene_info["end"])
91
- except KeyError as err:
92
- raise KeyError("Gene has to have a end position")
93
- except TypeError as err:
94
- raise TypeError("Gene end has to be a integer")
95
-
96
- gene_obj = HgncGene(
97
- hgnc_id=hgnc_id,
98
- hgnc_symbol=hgnc_symbol,
99
- ensembl_id=ensembl_id,
100
- chrom=chromosome,
101
- start=start,
102
- end=end,
103
- build=build,
104
- )
105
-
106
- if gene_info.get("description"):
107
- gene_obj["description"] = gene_info["description"]
108
- # LOG.debug("Adding info %s", gene_info['description'])
109
-
110
- if gene_info.get("previous_symbols"):
111
- gene_obj["aliases"] = gene_info["previous_symbols"]
112
-
113
- if gene_info.get("entrez_id"):
114
- gene_obj["entrez_id"] = int(gene_info["entrez_id"])
115
-
116
- if gene_info.get("omim_id"):
117
- gene_obj["omim_id"] = int(gene_info["omim_id"])
118
-
119
- for constraint in GENE_CONSTRAINT_LABELS.keys():
120
- if gene_info.get(constraint):
121
- gene_obj[constraint] = float(gene_info[constraint])
122
-
123
- if gene_info.get("ref_seq"):
124
- gene_obj["primary_transcripts"] = gene_info["ref_seq"]
125
-
126
- if gene_info.get("ucsc_id"):
127
- gene_obj["ucsc_id"] = gene_info["ucsc_id"]
128
-
129
- if gene_info.get("uniprot_ids"):
130
- gene_obj["uniprot_ids"] = gene_info["uniprot_ids"]
131
-
132
- if gene_info.get("vega_id"):
133
- gene_obj["vega_id"] = gene_info["vega_id"]
134
-
135
- if gene_info.get("incomplete_penetrance"):
136
- gene_obj["incomplete_penetrance"] = True
137
-
138
- if gene_info.get("inheritance_models"):
139
- gene_obj["inheritance_models"] = gene_info["inheritance_models"]
140
-
141
- phenotype_objs = []
142
- for phenotype_info in gene_info.get("phenotypes", []):
143
- phenotype_objs.append(build_phenotype(phenotype_info))
144
-
145
- if phenotype_objs:
146
- gene_obj["phenotypes"] = phenotype_objs
147
-
148
- for key in list(gene_obj):
149
- if gene_obj[key] is None:
150
- gene_obj.pop(key)
151
-
152
- return gene_obj
21
+ gene_info["build"] = build
22
+ hgnc_gene = HgncGene(**gene_info)
23
+ return hgnc_gene.model_dump(exclude_none=True)
scout/commands/base.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Code for CLI base"""
2
+
2
3
  import logging
3
4
  import pathlib
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Code for handling downloading of ensembl files used by scout from CLI"""
2
+
2
3
  import logging
3
4
  import pathlib
4
5
  from typing import List, Optional
@@ -1,6 +1,7 @@
1
1
  """Code for handling downloading Download all necessary resources for scout used by scout from
2
2
  CLI
3
3
  """
4
+
4
5
  import logging
5
6
  import pathlib
6
7
 
@@ -1,4 +1,5 @@
1
1
  """Code for handling downloading of the ExAC genes file used by scout from CLI"""
2
+
2
3
  import logging
3
4
  import pathlib
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Code for handling downloading of HPO files used by scout from CLI"""
2
+
2
3
  import logging
3
4
  import pathlib
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Code for handling downloading of HPO files used by scout from CLI"""
2
+
2
3
  import logging
3
4
  import pathlib
4
5
 
@@ -1,4 +1,5 @@
1
1
  """Code for handling downloading of HPO files used by scout from CLI"""
2
+
2
3
  import logging
3
4
  from pathlib import Path
4
5
  from typing import Dict
@@ -3,6 +3,7 @@
3
3
  Since the variants collection is very large this dump will be optional.
4
4
 
5
5
  """
6
+
6
7
  import logging
7
8
  import subprocess
8
9
  from subprocess import CalledProcessError
@@ -1,4 +1,5 @@
1
1
  """Code for scout load panel CLI functionality"""
2
+
2
3
  import logging
3
4
 
4
5
  import click
@@ -1,4 +1,5 @@
1
1
  """Code for updating reports"""
2
+
2
3
  import logging
3
4
 
4
5
  import click
@@ -94,7 +94,6 @@ def case(
94
94
  """
95
95
  Update a case in the database
96
96
  """
97
- adapter = store
98
97
 
99
98
  if not case_id:
100
99
  if not (case_name and institute):
@@ -104,7 +103,7 @@ def case(
104
103
  raise click.Abort()
105
104
 
106
105
  # Check if the case exists
107
- case_obj = adapter.case(case_id=case_id, institute_id=institute, display_name=case_name)
106
+ case_obj = store.case(case_id=case_id, institute_id=institute, display_name=case_name)
108
107
 
109
108
  if not case_obj:
110
109
  LOG.warning("Case %s could not be found", case_id)
@@ -112,7 +111,7 @@ def case(
112
111
 
113
112
  case_changed = False
114
113
  if collaborator:
115
- if not adapter.institute(collaborator):
114
+ if not store.institute(collaborator):
116
115
  LOG.warning("Institute %s could not be found", collaborator)
117
116
  return
118
117
  if not collaborator in case_obj["collaborators"]:
@@ -139,7 +138,8 @@ def case(
139
138
  case_changed = True
140
139
 
141
140
  if case_changed:
142
- adapter.update_case(case_obj)
141
+ institute_obj = store.institute(case_obj["owner"])
142
+ store.update_case_cli(case_obj, institute_obj)
143
143
 
144
144
  if reupload_sv:
145
145
  LOG.info("Set needs_check to True for case %s", case_id)
@@ -151,7 +151,7 @@ def case(
151
151
  if vcf_sv:
152
152
  updates["vcf_files.vcf_sv_research"] = vcf_sv_research
153
153
 
154
- updated_case = adapter.case_collection.find_one_and_update(
154
+ updated_case = store.case_collection.find_one_and_update(
155
155
  {"_id": case_id},
156
156
  {"$set": updates},
157
157
  return_document=pymongo.ReturnDocument.AFTER,
@@ -159,8 +159,8 @@ def case(
159
159
  rankscore_treshold = rankscore_treshold or updated_case.get("rank_score_threshold", 5)
160
160
  # Delete and reload the clinical SV variants
161
161
  if updated_case["vcf_files"].get("vcf_sv"):
162
- adapter.delete_variants(case_id, variant_type="clinical", category="sv")
163
- adapter.load_variants(
162
+ store.delete_variants(case_id, variant_type="clinical", category="sv")
163
+ store.load_variants(
164
164
  updated_case,
165
165
  variant_type="clinical",
166
166
  category="sv",
@@ -168,13 +168,13 @@ def case(
168
168
  )
169
169
  # Delete and reload research SV variants
170
170
  if updated_case["vcf_files"].get("vcf_sv_research"):
171
- adapter.delete_variants(case_id, variant_type="research", category="sv")
171
+ store.delete_variants(case_id, variant_type="research", category="sv")
172
172
  if updated_case.get("is_research"):
173
- adapter.load_variants(
173
+ store.load_variants(
174
174
  updated_case,
175
175
  variant_type="research",
176
176
  category="sv",
177
177
  rank_threshold=int(rankscore_treshold),
178
178
  )
179
179
  # Update case variants count
180
- adapter.case_variants_count(case_obj["_id"], case_obj["owner"], force_update_case=True)
180
+ store.case_variants_count(case_obj["_id"], case_obj["owner"], force_update_case=True)