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.
- scout/__version__.py +1 -1
- scout/adapter/client.py +1 -0
- scout/adapter/mongo/base.py +0 -1
- scout/adapter/mongo/case.py +19 -37
- scout/adapter/mongo/case_events.py +98 -2
- scout/adapter/mongo/hgnc.py +39 -22
- scout/adapter/mongo/institute.py +3 -9
- scout/adapter/mongo/panel.py +2 -1
- scout/adapter/mongo/variant.py +12 -2
- scout/adapter/mongo/variant_loader.py +156 -141
- scout/build/genes/hgnc_gene.py +5 -134
- scout/commands/base.py +1 -0
- scout/commands/download/ensembl.py +1 -0
- scout/commands/download/everything.py +1 -0
- scout/commands/download/exac.py +1 -0
- scout/commands/download/hgnc.py +1 -0
- scout/commands/download/hpo.py +1 -0
- scout/commands/download/omim.py +1 -0
- scout/commands/export/database.py +1 -0
- scout/commands/load/panel.py +1 -0
- scout/commands/load/report.py +1 -0
- scout/commands/update/case.py +10 -10
- scout/commands/update/individual.py +6 -1
- scout/commands/update/omim.py +1 -0
- scout/commands/update/panelapp.py +1 -0
- scout/constants/file_types.py +86 -13
- scout/export/exon.py +1 -0
- scout/load/__init__.py +0 -1
- scout/load/all.py +8 -5
- scout/load/hgnc_gene.py +1 -1
- scout/load/panel.py +8 -4
- scout/load/setup.py +1 -0
- scout/models/case/case_loading_models.py +6 -16
- scout/models/hgnc_map.py +50 -87
- scout/models/phenotype_term.py +3 -3
- scout/parse/case.py +0 -1
- scout/parse/disease_terms.py +1 -0
- scout/parse/omim.py +1 -0
- scout/parse/orpha.py +1 -0
- scout/parse/panel.py +40 -15
- scout/parse/variant/conservation.py +1 -0
- scout/resources/__init__.py +3 -0
- scout/server/app.py +4 -50
- scout/server/blueprints/alignviewers/controllers.py +15 -17
- scout/server/blueprints/alignviewers/templates/alignviewers/igv_viewer.html +13 -3
- scout/server/blueprints/alignviewers/views.py +10 -15
- scout/server/blueprints/cases/controllers.py +70 -73
- scout/server/blueprints/cases/templates/cases/case.html +94 -71
- scout/server/blueprints/cases/templates/cases/collapsible_actionbar.html +1 -1
- scout/server/blueprints/cases/templates/cases/phenotype.html +8 -6
- scout/server/blueprints/cases/templates/cases/utils.html +3 -3
- scout/server/blueprints/cases/views.py +8 -6
- scout/server/blueprints/panels/forms.py +1 -0
- scout/server/blueprints/variant/controllers.py +14 -19
- scout/server/blueprints/variant/templates/variant/acmg.html +25 -16
- scout/server/blueprints/variant/templates/variant/components.html +11 -6
- scout/server/blueprints/variant/views.py +5 -2
- scout/server/blueprints/variants/controllers.py +12 -28
- scout/server/blueprints/variants/views.py +1 -1
- scout/server/config.py +16 -4
- scout/server/extensions/__init__.py +4 -2
- scout/server/extensions/beacon_extension.py +1 -0
- scout/server/extensions/bionano_extension.py +1 -0
- scout/server/extensions/chanjo_extension.py +59 -0
- scout/server/extensions/gens_extension.py +1 -0
- scout/server/extensions/ldap_extension.py +5 -3
- scout/server/extensions/loqus_extension.py +16 -14
- scout/server/extensions/matchmaker_extension.py +1 -0
- scout/server/extensions/mongo_extension.py +1 -0
- scout/server/extensions/phenopacket_extension.py +1 -0
- scout/server/extensions/rerunner_extension.py +1 -0
- scout/server/links.py +4 -4
- scout/server/static/bs_styles.css +20 -2
- scout/server/utils.py +16 -2
- scout/utils/acmg.py +33 -20
- scout/utils/ensembl_rest_clients.py +1 -0
- scout/utils/scout_requests.py +1 -0
- scout/utils/sort.py +21 -0
- scout/utils/track_resources.py +70 -0
- {scout_browser-4.82.2.dist-info → scout_browser-4.84.dist-info}/METADATA +2 -5
- {scout_browser-4.82.2.dist-info → scout_browser-4.84.dist-info}/RECORD +85 -84
- {scout_browser-4.82.2.dist-info → scout_browser-4.84.dist-info}/WHEEL +1 -1
- {scout_browser-4.82.2.dist-info → scout_browser-4.84.dist-info}/entry_points.txt +0 -1
- scout/load/case.py +0 -36
- scout/utils/cloud_resources.py +0 -61
- {scout_browser-4.82.2.dist-info → scout_browser-4.84.dist-info}/LICENSE +0 -0
- {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
|
-
|
206
|
-
# Possible variant types 'clinical', 'research'
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
if case_obj.get("vcf_files", {}).get(file_type)
|
211
|
-
|
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
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
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
|
-
|
227
|
-
|
227
|
+
# Fetch all variants from a chromosome
|
228
|
+
query = {"variant_type": var_type, "chrom": chrom}
|
228
229
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
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
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
239
|
+
# Initiate a bulk
|
240
|
+
bulk = {}
|
241
|
+
current_region = None
|
242
|
+
special = False
|
242
243
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
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
|
-
|
251
|
-
|
251
|
+
update_bulk = True
|
252
|
+
new_region = None
|
252
253
|
|
253
|
-
|
254
|
-
|
255
|
-
|
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
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
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
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
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
|
-
|
269
|
+
current_region = new_region
|
269
270
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
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
|
-
|
278
|
-
|
278
|
+
if new_region:
|
279
|
+
bulk[var_id] = var_obj
|
279
280
|
|
280
|
-
|
281
|
-
|
281
|
+
if not bulk:
|
282
|
+
continue
|
282
283
|
|
283
|
-
|
284
|
-
|
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
|
-
|
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
|
674
|
+
if not variant_files:
|
663
675
|
raise SyntaxError(
|
664
|
-
"VCF
|
676
|
+
"VCF files for {} {} does not seem to exist".format(category, variant_type)
|
665
677
|
)
|
666
678
|
|
667
|
-
|
668
|
-
|
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
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
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
|
-
|
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
|
scout/build/genes/hgnc_gene.py
CHANGED
@@ -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
|
18
|
+
def build_hgnc_gene(gene_info: dict, build: bool = "37") -> dict:
|
19
|
+
"""Build a HGNC gene object"""
|
21
20
|
|
22
|
-
|
23
|
-
|
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
scout/commands/download/exac.py
CHANGED
scout/commands/download/hgnc.py
CHANGED
scout/commands/download/hpo.py
CHANGED
scout/commands/download/omim.py
CHANGED
scout/commands/load/panel.py
CHANGED
scout/commands/load/report.py
CHANGED
scout/commands/update/case.py
CHANGED
@@ -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 =
|
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
|
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
|
-
|
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 =
|
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
|
-
|
163
|
-
|
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
|
-
|
171
|
+
store.delete_variants(case_id, variant_type="research", category="sv")
|
172
172
|
if updated_case.get("is_research"):
|
173
|
-
|
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
|
-
|
180
|
+
store.case_variants_count(case_obj["_id"], case_obj["owner"], force_update_case=True)
|