scout-browser 4.92__py3-none-any.whl → 4.94__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/adapter/mongo/base.py +3 -0
- scout/adapter/mongo/case.py +27 -2
- scout/adapter/mongo/ccv.py +131 -0
- scout/adapter/mongo/query.py +88 -53
- scout/adapter/mongo/variant.py +6 -5
- scout/adapter/mongo/variant_events.py +45 -1
- scout/build/ccv.py +59 -0
- scout/commands/export/export_command.py +0 -0
- scout/commands/load/base.py +0 -0
- scout/commands/load/user.py +0 -0
- scout/commands/serve.py +2 -1
- scout/commands/update/disease.py +0 -0
- scout/commands/update/genes.py +0 -0
- scout/commands/wipe_database.py +0 -0
- scout/constants/__init__.py +2 -0
- scout/constants/case_tags.py +2 -0
- scout/constants/ccv.py +244 -0
- scout/demo/643594.config.yaml +2 -2
- scout/demo/images/custom_images/1300x1000.jpg +0 -0
- scout/models/ccv_evaluation.py +26 -0
- scout/models/variant/variant.py +1 -0
- scout/parse/variant/compound.py +0 -0
- scout/parse/variant/gene.py +0 -0
- scout/parse/variant/genotype.py +0 -0
- scout/resources/custom_igv_tracks/mane.bb +0 -0
- scout/server/blueprints/cases/controllers.py +21 -0
- scout/server/blueprints/cases/templates/cases/case_report.html +53 -0
- scout/server/blueprints/cases/templates/cases/collapsible_actionbar.html +2 -2
- scout/server/blueprints/cases/templates/cases/index.html +0 -2
- scout/server/blueprints/clinvar/controllers.py +4 -5
- scout/server/blueprints/institutes/controllers.py +129 -67
- scout/server/blueprints/institutes/forms.py +5 -2
- scout/server/blueprints/institutes/templates/overview/cases.html +6 -0
- scout/server/blueprints/institutes/templates/overview/causatives.html +1 -1
- scout/server/blueprints/institutes/templates/overview/utils.html +18 -6
- scout/server/blueprints/institutes/templates/overview/verified.html +1 -1
- scout/server/blueprints/institutes/views.py +4 -0
- scout/server/blueprints/panels/controllers.py +5 -6
- scout/server/blueprints/panels/templates/panels/panel.html +5 -5
- scout/server/blueprints/variant/controllers.py +148 -1
- scout/server/blueprints/variant/templates/variant/cancer-variant.html +1 -1
- scout/server/blueprints/variant/templates/variant/ccv.html +183 -0
- scout/server/blueprints/variant/templates/variant/components.html +61 -3
- scout/server/blueprints/variant/templates/variant/tx_overview.html +3 -3
- scout/server/blueprints/variant/templates/variant/variant.html +1 -1
- scout/server/blueprints/variant/templates/variant/variant_details.html +29 -11
- scout/server/blueprints/variant/utils.py +21 -1
- scout/server/blueprints/variant/views.py +114 -3
- scout/server/blueprints/variants/controllers.py +31 -0
- scout/server/blueprints/variants/templates/variants/cancer-sv-variants.html +4 -18
- scout/server/blueprints/variants/templates/variants/cancer-variants.html +4 -13
- scout/server/blueprints/variants/templates/variants/components.html +77 -73
- scout/server/blueprints/variants/templates/variants/indicators.html +11 -0
- scout/server/blueprints/variants/templates/variants/sv-variants.html +2 -2
- scout/server/links.py +1 -1
- scout/server/static/custom_images.js +19 -2
- scout/utils/acmg.py +0 -1
- scout/utils/ccv.py +201 -0
- scout/utils/md5.py +0 -0
- {scout_browser-4.92.dist-info → scout_browser-4.94.dist-info}/METADATA +67 -45
- {scout_browser-4.92.dist-info → scout_browser-4.94.dist-info}/RECORD +54 -49
- {scout_browser-4.92.dist-info → scout_browser-4.94.dist-info}/WHEEL +1 -2
- scout/__version__.py +0 -1
- scout/demo/images/custom_images/640x480_two.jpg +0 -0
- scout_browser-4.92.dist-info/top_level.txt +0 -1
- {scout_browser-4.92.dist-info → scout_browser-4.94.dist-info}/entry_points.txt +0 -0
- {scout_browser-4.92.dist-info → scout_browser-4.94.dist-info/licenses}/LICENSE +0 -0
scout/adapter/mongo/base.py
CHANGED
@@ -34,6 +34,7 @@ from flask import current_app
|
|
34
34
|
from .acmg import ACMGHandler
|
35
35
|
from .case import CaseHandler
|
36
36
|
from .case_group import CaseGroupHandler
|
37
|
+
from .ccv import CCVHandler
|
37
38
|
from .clinvar import ClinVarHandler
|
38
39
|
from .cytoband import CytobandHandler
|
39
40
|
from .disease_terms import DiagnosisHandler
|
@@ -61,6 +62,7 @@ class MongoAdapter(
|
|
61
62
|
ACMGHandler,
|
62
63
|
CaseGroupHandler,
|
63
64
|
CaseHandler,
|
65
|
+
CCVHandler,
|
64
66
|
ClinVarHandler,
|
65
67
|
CytobandHandler,
|
66
68
|
DiagnosisHandler,
|
@@ -97,6 +99,7 @@ class MongoAdapter(
|
|
97
99
|
"""Setup connection to database."""
|
98
100
|
self.db = database
|
99
101
|
self.acmg_collection = database.acmg
|
102
|
+
self.ccv_collection = database.ccv
|
100
103
|
self.case_collection = database.case
|
101
104
|
self.case_group_collection = database.case_group
|
102
105
|
self.clinvar_collection = database.clinvar
|
scout/adapter/mongo/case.py
CHANGED
@@ -11,7 +11,7 @@ from bson import ObjectId
|
|
11
11
|
from werkzeug.datastructures import ImmutableMultiDict
|
12
12
|
|
13
13
|
from scout.build.case import build_case
|
14
|
-
from scout.constants import ACMG_MAP, FILE_TYPE_MAP, ID_PROJECTION, OMICS_FILE_TYPE_MAP
|
14
|
+
from scout.constants import ACMG_MAP, CCV_MAP, FILE_TYPE_MAP, ID_PROJECTION, OMICS_FILE_TYPE_MAP
|
15
15
|
from scout.exceptions import ConfigError, IntegrityError
|
16
16
|
from scout.parse.variant.ids import parse_document_id
|
17
17
|
from scout.utils.algorithms import ui_score
|
@@ -1272,6 +1272,16 @@ class CaseHandler(object):
|
|
1272
1272
|
{"$set": {"case_id": family_id, "variant_specific": new_specific_id}},
|
1273
1273
|
)
|
1274
1274
|
|
1275
|
+
# update ClinGen-CGC-VIGG classification
|
1276
|
+
for ccv_obj in self.ccv_collection.find({"case_id": case_obj["_id"]}):
|
1277
|
+
LOG.info("update ClinGen-CGC-VIGG classification: %s", ccv_obj["classification"])
|
1278
|
+
ccv_variant = self.variant(ccv_obj["variant_specific"])
|
1279
|
+
new_specific_id = get_variantid(ccv_variant, family_id)
|
1280
|
+
self.ccv_collection.find_one_and_update(
|
1281
|
+
{"_id": ccv_obj["_id"]},
|
1282
|
+
{"$set": {"case_id": family_id, "variant_specific": new_specific_id}},
|
1283
|
+
)
|
1284
|
+
|
1275
1285
|
# update events
|
1276
1286
|
institute_obj = self.institute(case_obj["owner"])
|
1277
1287
|
for event_obj in self.events(institute_obj, case=case_obj):
|
@@ -1344,6 +1354,7 @@ class CaseHandler(object):
|
|
1344
1354
|
'mosaic_tags' : [list of variant ids],
|
1345
1355
|
'cancer_tier': [list of variant ids],
|
1346
1356
|
'acmg_classification': [list of variant ids]
|
1357
|
+
'ccv_classification': [list of variant ids]
|
1347
1358
|
'is_commented': [list of variant ids]
|
1348
1359
|
"""
|
1349
1360
|
updated_variants = {
|
@@ -1352,6 +1363,7 @@ class CaseHandler(object):
|
|
1352
1363
|
"mosaic_tags": [],
|
1353
1364
|
"cancer_tier": [],
|
1354
1365
|
"acmg_classification": [],
|
1366
|
+
"ccv_classification": [],
|
1355
1367
|
"is_commented": [],
|
1356
1368
|
}
|
1357
1369
|
|
@@ -1394,8 +1406,10 @@ class CaseHandler(object):
|
|
1394
1406
|
verb = action
|
1395
1407
|
if action == "acmg_classification":
|
1396
1408
|
verb = "acmg"
|
1397
|
-
|
1409
|
+
if action == "is_commented":
|
1398
1410
|
verb = "comment"
|
1411
|
+
if action == "ccv_classification":
|
1412
|
+
verb = "ccv"
|
1399
1413
|
|
1400
1414
|
old_event = self.event_collection.find_one(
|
1401
1415
|
{
|
@@ -1444,6 +1458,17 @@ class CaseHandler(object):
|
|
1444
1458
|
acmg_str=str_classif,
|
1445
1459
|
)
|
1446
1460
|
|
1461
|
+
if action == "ccv_classification":
|
1462
|
+
str_classif = CCV_MAP.get(old_var.get("ccv_classification"))
|
1463
|
+
updated_variant = self.update_ccv(
|
1464
|
+
institute_obj=institute_obj,
|
1465
|
+
case_obj=case_obj,
|
1466
|
+
user_obj=user_obj,
|
1467
|
+
link=link,
|
1468
|
+
variant_obj=new_var,
|
1469
|
+
ccv_str=str_classif,
|
1470
|
+
)
|
1471
|
+
|
1447
1472
|
if action in update_action_map.keys():
|
1448
1473
|
updated_variant = update_action_map[action](
|
1449
1474
|
institute_obj,
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
import logging
|
3
|
+
|
4
|
+
import pymongo
|
5
|
+
from bson import ObjectId
|
6
|
+
|
7
|
+
from scout.build.ccv import build_ccv_evaluation
|
8
|
+
from scout.utils.ccv import get_ccv
|
9
|
+
|
10
|
+
log = logging.getLogger(__name__)
|
11
|
+
|
12
|
+
|
13
|
+
class CCVHandler(object):
|
14
|
+
def submit_ccv_evaluation(
|
15
|
+
self,
|
16
|
+
variant_obj,
|
17
|
+
user_obj,
|
18
|
+
institute_obj,
|
19
|
+
case_obj,
|
20
|
+
link,
|
21
|
+
criteria=None,
|
22
|
+
classification=None,
|
23
|
+
):
|
24
|
+
"""Submit an evaluation to the database
|
25
|
+
|
26
|
+
Get all the relevant information, build an evaluation_obj
|
27
|
+
|
28
|
+
Args:
|
29
|
+
variant_obj(dict)
|
30
|
+
user_obj(dict)
|
31
|
+
institute_obj(dict)
|
32
|
+
case_obj(dict)
|
33
|
+
link(str): variant url
|
34
|
+
criteria(list(dict)):
|
35
|
+
[
|
36
|
+
{
|
37
|
+
'term': str,
|
38
|
+
'comment': str,
|
39
|
+
'modifier': str,
|
40
|
+
'links': list(str)
|
41
|
+
},
|
42
|
+
.
|
43
|
+
.
|
44
|
+
]
|
45
|
+
classification(int)
|
46
|
+
"""
|
47
|
+
criteria = criteria or []
|
48
|
+
|
49
|
+
variant_specific = variant_obj["_id"]
|
50
|
+
variant_id = variant_obj["variant_id"]
|
51
|
+
user_id = user_obj["_id"]
|
52
|
+
user_name = user_obj.get("name", user_obj["_id"])
|
53
|
+
institute_id = institute_obj["_id"]
|
54
|
+
case_id = case_obj["_id"]
|
55
|
+
|
56
|
+
evaluation_terms = []
|
57
|
+
for evaluation_info in criteria:
|
58
|
+
term = evaluation_info["term"]
|
59
|
+
if evaluation_info.get("modifier"):
|
60
|
+
term += "_" + evaluation_info.get("modifier")
|
61
|
+
evaluation_terms.append(term)
|
62
|
+
|
63
|
+
if classification is None:
|
64
|
+
classification = get_ccv(evaluation_terms)
|
65
|
+
|
66
|
+
if classification:
|
67
|
+
evaluation_obj = build_ccv_evaluation(
|
68
|
+
variant_specific=variant_specific,
|
69
|
+
variant_id=variant_id,
|
70
|
+
user_id=user_id,
|
71
|
+
user_name=user_name,
|
72
|
+
institute_id=institute_id,
|
73
|
+
case_id=case_id,
|
74
|
+
ccv_classification=classification,
|
75
|
+
ccv_criteria=criteria,
|
76
|
+
)
|
77
|
+
|
78
|
+
self._load_ccv_evaluation(evaluation_obj)
|
79
|
+
|
80
|
+
# Update the ccv classification for the variant:
|
81
|
+
self.update_ccv(institute_obj, case_obj, user_obj, link, variant_obj, classification)
|
82
|
+
return classification
|
83
|
+
|
84
|
+
def _load_ccv_evaluation(self, evaluation_obj):
|
85
|
+
"""Load a evaluation object into the database"""
|
86
|
+
res = self.ccv_collection.insert_one(evaluation_obj)
|
87
|
+
return res
|
88
|
+
|
89
|
+
def delete_ccv_evaluation(self, evaluation_obj):
|
90
|
+
"""Delete an evaluation from the database
|
91
|
+
|
92
|
+
Args:
|
93
|
+
evaluation_obj(dict)
|
94
|
+
|
95
|
+
"""
|
96
|
+
self.ccv_collection.delete_one({"_id": evaluation_obj["_id"]})
|
97
|
+
|
98
|
+
def get_ccv_evaluation(self, evaluation_id):
|
99
|
+
"""Get a single evaluation from the database
|
100
|
+
|
101
|
+
Args:
|
102
|
+
evaluation_id(str)
|
103
|
+
|
104
|
+
"""
|
105
|
+
return self.ccv_collection.find_one({"_id": ObjectId(evaluation_id)})
|
106
|
+
|
107
|
+
def get_ccv_evaluations(self, variant_obj):
|
108
|
+
"""Return all evaluations for a certain variant.
|
109
|
+
|
110
|
+
Args:
|
111
|
+
variant_obj (dict): variant dict from the database
|
112
|
+
|
113
|
+
Returns:
|
114
|
+
pymongo.cursor: database cursor
|
115
|
+
"""
|
116
|
+
query = dict(variant_id=variant_obj["variant_id"])
|
117
|
+
res = self.ccv_collection.find(query).sort([("created_at", pymongo.DESCENDING)])
|
118
|
+
return res
|
119
|
+
|
120
|
+
def get_ccv_evaluations_case_specific(self, document_id):
|
121
|
+
"""Return all evaluations for a certain variant, in a certain case as determined by document id.
|
122
|
+
|
123
|
+
Args:
|
124
|
+
document_id: variant document id from the db; an md5 hash including the case id.
|
125
|
+
|
126
|
+
Returns:
|
127
|
+
res: pymongo.cursor
|
128
|
+
"""
|
129
|
+
query = dict(variant_specific=document_id)
|
130
|
+
res = self.ccv_collection.find(query).sort([("created_at", pymongo.DESCENDING)])
|
131
|
+
return res
|
scout/adapter/mongo/query.py
CHANGED
@@ -474,63 +474,98 @@ class QueryHandler(object):
|
|
474
474
|
|
475
475
|
return mongo_query
|
476
476
|
|
477
|
-
def
|
478
|
-
"""
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
477
|
+
def get_position_query(self, chrom: str, start: int, end: int) -> dict:
|
478
|
+
"""Helper function that returns a dictionary containing start and stop coordinates.
|
479
|
+
|
480
|
+
The position query consists of 3 parts, each of them elements of the $or
|
481
|
+
First part applies to searches when chromosome and end_chrom are the same.
|
482
|
+
Here are the possible overlapping search scenarios:
|
483
|
+
# Case 1
|
484
|
+
# filter xxxxxxxxx
|
485
|
+
# Variant xxxxxxxx
|
486
|
+
|
487
|
+
# Case 2
|
488
|
+
# filter xxxxxxxxx
|
489
|
+
# Variant xxxxxxxx
|
490
|
+
|
491
|
+
# Case 3
|
492
|
+
# filter xxxxxxxxx
|
493
|
+
# Variant xx
|
494
|
+
|
495
|
+
# Case 4
|
496
|
+
# filter xxxxxxxxx
|
497
|
+
# Variant xxxxxxxxxxxxxx
|
498
|
+
|
499
|
+
Second and third elements of the $or cover queries for variants where chromosome != end_chrom.
|
500
|
+
In this situation there are the following scenarios:
|
501
|
+
- Case chromosome != end_chrom, position matching 'chromosome'
|
502
|
+
- Case chromosome != end_chrom, position matching 'end_chrom'
|
503
|
+
"""
|
484
504
|
|
485
|
-
|
486
|
-
|
505
|
+
return {
|
506
|
+
"$or": [
|
507
|
+
# Case chromosome == end_chrom
|
508
|
+
{
|
509
|
+
"$and": [
|
510
|
+
{"chromosome": chrom},
|
511
|
+
{"end_chrom": chrom},
|
512
|
+
{
|
513
|
+
"$or": [
|
514
|
+
# Overlapping cases 1-4 (chromosome == end_chrom)
|
515
|
+
{"end": {"$gte": start, "$lte": end}}, # Case 1
|
516
|
+
{"position": {"$gte": start, "$lte": end}}, # Case 2
|
517
|
+
{
|
518
|
+
"$and": [
|
519
|
+
{"position": {"$lte": start}},
|
520
|
+
{"end": {"$gte": end}},
|
521
|
+
]
|
522
|
+
}, # Case 3
|
523
|
+
{
|
524
|
+
"$and": [
|
525
|
+
{"position": {"$gte": start}},
|
526
|
+
{"end": {"$lte": end}},
|
527
|
+
]
|
528
|
+
}, # Case 4
|
529
|
+
]
|
530
|
+
},
|
531
|
+
]
|
532
|
+
},
|
533
|
+
# Case chromosome != end_chrom, position matching 'chromosome'
|
534
|
+
{
|
535
|
+
"$and": [
|
536
|
+
{"chromosome": chrom},
|
537
|
+
{"end_chrom": {"$ne": chrom}},
|
538
|
+
{"position": {"$gte": start}},
|
539
|
+
{"position": {"$lte": end}},
|
540
|
+
]
|
541
|
+
},
|
542
|
+
# Case chromosome != end_chrom, position matching 'end_chrom'
|
543
|
+
{
|
544
|
+
"$and": [
|
545
|
+
{"chromosome": {"$ne": chrom}},
|
546
|
+
{"end_chrom": chrom},
|
547
|
+
{"end": {"$gte": start}},
|
548
|
+
{"end": {"$lte": end}},
|
549
|
+
]
|
550
|
+
},
|
551
|
+
]
|
552
|
+
}
|
487
553
|
|
554
|
+
def sv_coordinate_query(self, query: dict) -> dict:
|
555
|
+
"""Adds genomic coordinated-related filters to the query object
|
556
|
+
This method is called to build coordinate query for sv variants
|
488
557
|
"""
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
# Variant xxxxxxxx
|
500
|
-
|
501
|
-
# 3
|
502
|
-
# filter xxxxxxxxx
|
503
|
-
# Variant xx
|
504
|
-
|
505
|
-
# 4
|
506
|
-
# filter xxxxxxxxx
|
507
|
-
# Variant xxxxxxxxxxxxxx
|
508
|
-
position_query = {
|
509
|
-
"$or": [
|
510
|
-
{"end": {"$gte": int(query["start"]), "$lte": int(query["end"])}}, # 1
|
511
|
-
{
|
512
|
-
"position": {
|
513
|
-
"$lte": int(query["end"]),
|
514
|
-
"$gte": int(query["start"]),
|
515
|
-
}
|
516
|
-
}, # 2
|
517
|
-
{
|
518
|
-
"$and": [
|
519
|
-
{"position": {"$gte": int(query["start"])}},
|
520
|
-
{"end": {"$lte": int(query["end"])}},
|
521
|
-
]
|
522
|
-
}, # 3
|
523
|
-
{
|
524
|
-
"$and": [
|
525
|
-
{"position": {"$lte": int(query["start"])}},
|
526
|
-
{"end": {"$gte": int(query["end"])}},
|
527
|
-
]
|
528
|
-
}, # 4
|
529
|
-
]
|
558
|
+
if (
|
559
|
+
query.get("start") is not None and query.get("end") is not None
|
560
|
+
): # query contains full coordinates
|
561
|
+
chrom = query["chrom"]
|
562
|
+
start = int(query["start"])
|
563
|
+
end = int(query["end"])
|
564
|
+
coordinate_query = self.get_position_query(chrom=chrom, start=start, end=end)
|
565
|
+
else: # query contains only chromosome info
|
566
|
+
coordinate_query = {
|
567
|
+
"$or": [{"chromosome": query["chrom"]}, {"end_chrom": query["chrom"]}]
|
530
568
|
}
|
531
|
-
coordinate_query = {"$and": [chromosome_query, position_query]}
|
532
|
-
else:
|
533
|
-
coordinate_query = chromosome_query
|
534
569
|
return coordinate_query
|
535
570
|
|
536
571
|
def gene_filter(self, query, build="37"):
|
scout/adapter/mongo/variant.py
CHANGED
@@ -311,14 +311,14 @@ class VariantHandler(VariantLoader):
|
|
311
311
|
"category": variant_obj["category"], # sv
|
312
312
|
"variant_type": variant_obj["variant_type"], # clinical or research
|
313
313
|
"sub_category": variant_obj["sub_category"], # example -> "del"
|
314
|
-
"$
|
314
|
+
"$or": coordinate_query["$or"], # query for overlapping SV variants
|
315
315
|
}
|
316
|
-
|
317
316
|
overlapping_svs = list(
|
318
317
|
self.variant_collection.find(
|
319
318
|
query,
|
320
319
|
)
|
321
320
|
)
|
321
|
+
|
322
322
|
if not overlapping_svs:
|
323
323
|
return None
|
324
324
|
if len(overlapping_svs) == 1:
|
@@ -721,7 +721,7 @@ class VariantHandler(VariantLoader):
|
|
721
721
|
def evaluated_variant_ids_from_events(self, case_id, institute_id):
|
722
722
|
"""Returns variant ids for variants that have been evaluated
|
723
723
|
Return all variants, snvs/indels and svs from case case_id
|
724
|
-
which have an event entry for 'acmg_classification', 'manual_rank', 'dismiss_variant',
|
724
|
+
which have an event entry for 'acmg_classification', 'ccv_classification', 'manual_rank', 'dismiss_variant',
|
725
725
|
'cancer_tier', 'mosaic_tags'.
|
726
726
|
Args:
|
727
727
|
case_id(str)
|
@@ -732,6 +732,7 @@ class VariantHandler(VariantLoader):
|
|
732
732
|
|
733
733
|
evaluation_verbs = [
|
734
734
|
"acmg",
|
735
|
+
"ccv",
|
735
736
|
"manual_rank",
|
736
737
|
"cancer_tier",
|
737
738
|
"dismiss_variant",
|
@@ -758,7 +759,7 @@ class VariantHandler(VariantLoader):
|
|
758
759
|
"""Returns variants that have been evaluated
|
759
760
|
|
760
761
|
Return all variants, snvs/indels and svs from case case_id and institute_id
|
761
|
-
which have a entry for 'acmg_classification', 'manual_rank', 'dismiss_variant',
|
762
|
+
which have a entry for 'acmg_classification', 'ccv_classification', 'manual_rank', 'dismiss_variant',
|
762
763
|
'cancer_tier' or if they are commented.
|
763
764
|
|
764
765
|
Return only if the variants still exist and still have the assessment.
|
@@ -778,11 +779,11 @@ class VariantHandler(VariantLoader):
|
|
778
779
|
query = {
|
779
780
|
"$and": [
|
780
781
|
{"variant_id": {"$in": variant_ids}},
|
781
|
-
{"institute": institute_id},
|
782
782
|
{"case_id": case_id},
|
783
783
|
{
|
784
784
|
"$or": [
|
785
785
|
{"acmg_classification": {"$exists": True}},
|
786
|
+
{"ccv_classification": {"$exists": True}},
|
786
787
|
{"manual_rank": {"$exists": True}},
|
787
788
|
{"cancer_tier": {"$exists": True}},
|
788
789
|
{"dismiss_variant": {"$exists": True}},
|
@@ -4,7 +4,7 @@ from typing import Dict, List
|
|
4
4
|
|
5
5
|
import pymongo
|
6
6
|
|
7
|
-
from scout.constants import CANCER_TIER_OPTIONS, MANUAL_RANK_OPTIONS, REV_ACMG_MAP
|
7
|
+
from scout.constants import CANCER_TIER_OPTIONS, MANUAL_RANK_OPTIONS, REV_ACMG_MAP, REV_CCV_MAP
|
8
8
|
|
9
9
|
SANGER_OPTIONS = ["True positive", "False positive", "Not validated"]
|
10
10
|
|
@@ -931,3 +931,47 @@ class VariantEventHandler(object):
|
|
931
931
|
|
932
932
|
LOG.debug("Variant updated")
|
933
933
|
return updated_variant
|
934
|
+
|
935
|
+
def update_ccv(self, institute_obj, case_obj, user_obj, link, variant_obj, ccv_str):
|
936
|
+
"""Create an event for updating the ClinGen-CGC-VIGG classification of a variant.
|
937
|
+
|
938
|
+
Arguments:
|
939
|
+
institute_obj (dict): A Institute object
|
940
|
+
case_obj (dict): Case object
|
941
|
+
user_obj (dict): A User object
|
942
|
+
link (str): The url to be used in the event
|
943
|
+
variant_obj (dict): A variant object
|
944
|
+
ccv_str (str): The new ClinGen-CGC-VIGG classification string
|
945
|
+
|
946
|
+
Returns:
|
947
|
+
updated_variant
|
948
|
+
"""
|
949
|
+
self.create_event(
|
950
|
+
institute=institute_obj,
|
951
|
+
case=case_obj,
|
952
|
+
user=user_obj,
|
953
|
+
link=link,
|
954
|
+
category="variant",
|
955
|
+
verb="ccv",
|
956
|
+
variant=variant_obj,
|
957
|
+
subject=variant_obj["display_name"],
|
958
|
+
)
|
959
|
+
LOG.info(
|
960
|
+
"Setting ClinGen-CGC-VIGG to {} for: {}".format(ccv_str, variant_obj["display_name"])
|
961
|
+
)
|
962
|
+
|
963
|
+
if ccv_str is None:
|
964
|
+
updated_variant = self.variant_collection.find_one_and_update(
|
965
|
+
{"_id": variant_obj["_id"]},
|
966
|
+
{"$unset": {"ccv_classification": 1}},
|
967
|
+
return_document=pymongo.ReturnDocument.AFTER,
|
968
|
+
)
|
969
|
+
else:
|
970
|
+
updated_variant = self.variant_collection.find_one_and_update(
|
971
|
+
{"_id": variant_obj["_id"]},
|
972
|
+
{"$set": {"ccv_classification": REV_CCV_MAP[ccv_str]}},
|
973
|
+
return_document=pymongo.ReturnDocument.AFTER,
|
974
|
+
)
|
975
|
+
|
976
|
+
LOG.debug("Variant updated")
|
977
|
+
return updated_variant
|
scout/build/ccv.py
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
import logging
|
2
|
+
import datetime
|
3
|
+
|
4
|
+
LOG = logging.getLogger(__name__)
|
5
|
+
|
6
|
+
|
7
|
+
def build_ccv_evaluation(
|
8
|
+
variant_specific,
|
9
|
+
variant_id,
|
10
|
+
user_id,
|
11
|
+
user_name,
|
12
|
+
institute_id,
|
13
|
+
case_id,
|
14
|
+
ccv_classification,
|
15
|
+
ccv_criteria,
|
16
|
+
):
|
17
|
+
"""Build a ClinGen-CGC-VIGG evaluation object ready to be inserted to database
|
18
|
+
|
19
|
+
Args:
|
20
|
+
variant_specific(str): md5 string for the specific variant
|
21
|
+
variant_id(str): md5 string for the common variant
|
22
|
+
user_id(str)
|
23
|
+
user_name(str)
|
24
|
+
institute_id(str)
|
25
|
+
case_id(str)
|
26
|
+
ccv_classification(str): The ClinGen-CGC-VIGG classification
|
27
|
+
ccv_criteria(list(dict)): A list of dictionaries with ClinGen-CGC-VIGG criteria
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
evaluation_obj(dict): Correctly formatted evaluation object
|
31
|
+
|
32
|
+
"""
|
33
|
+
LOG.info(
|
34
|
+
"Creating ClinGen-CGC-VIGG classification: %s for variant %s",
|
35
|
+
ccv_classification,
|
36
|
+
variant_id,
|
37
|
+
)
|
38
|
+
ccv_criteria = ccv_criteria or []
|
39
|
+
evaluation_obj = dict(
|
40
|
+
variant_specific=variant_specific,
|
41
|
+
variant_id=variant_id,
|
42
|
+
institute_id=institute_id,
|
43
|
+
case_id=case_id,
|
44
|
+
ccv_classification=ccv_classification,
|
45
|
+
user_id=user_id,
|
46
|
+
user_name=user_name,
|
47
|
+
created_at=datetime.datetime.now(),
|
48
|
+
)
|
49
|
+
criteria_objs = []
|
50
|
+
for info in ccv_criteria:
|
51
|
+
criteria_obj = {}
|
52
|
+
for criterion_key in ["term", "comment", "links", "modifier"]:
|
53
|
+
if criterion_key in info:
|
54
|
+
criteria_obj[criterion_key] = info[criterion_key]
|
55
|
+
criteria_objs.append(criteria_obj)
|
56
|
+
|
57
|
+
evaluation_obj["ccv_criteria"] = criteria_objs
|
58
|
+
|
59
|
+
return evaluation_obj
|
File without changes
|
scout/commands/load/base.py
CHANGED
File without changes
|
scout/commands/load/user.py
CHANGED
File without changes
|
scout/commands/serve.py
CHANGED
@@ -22,7 +22,8 @@ def serve(host, port, debug, livereload, test):
|
|
22
22
|
"""Start the web server."""
|
23
23
|
|
24
24
|
# Verify the database connectivity before launching the app
|
25
|
-
mongo_client = current_app.config.get("MONGO_DATABASE").
|
25
|
+
mongo_client = current_app.config.get("MONGO_DATABASE").client
|
26
|
+
|
26
27
|
try:
|
27
28
|
mongo_client.server_info()
|
28
29
|
if test:
|
scout/commands/update/disease.py
CHANGED
File without changes
|
scout/commands/update/genes.py
CHANGED
File without changes
|
scout/commands/wipe_database.py
CHANGED
File without changes
|
scout/constants/__init__.py
CHANGED
@@ -23,6 +23,7 @@ from .case_tags import (
|
|
23
23
|
VERBS_ICONS_MAP,
|
24
24
|
VERBS_MAP,
|
25
25
|
)
|
26
|
+
from .ccv import CCV_COMPLETE_MAP, CCV_CRITERIA, CCV_MAP, CCV_OPTIONS, REV_CCV_MAP
|
26
27
|
from .clinvar import (
|
27
28
|
AFFECTED_STATUS,
|
28
29
|
ALLELE_OF_ORIGIN,
|
@@ -126,6 +127,7 @@ COLLECTIONS = [
|
|
126
127
|
"disease_term",
|
127
128
|
"variant",
|
128
129
|
"acmg",
|
130
|
+
"ccv",
|
129
131
|
]
|
130
132
|
|
131
133
|
BUILDS = ["37", "38", "GRCh38"]
|
scout/constants/case_tags.py
CHANGED
@@ -43,6 +43,7 @@ CASE_REPORT_VARIANT_TYPES = {
|
|
43
43
|
"partial_causatives_detailed": "partial_causatives",
|
44
44
|
"suspects_detailed": "suspects",
|
45
45
|
"classified_detailed": "acmg_classification",
|
46
|
+
"ccv_classified_detailed": "ccv_classification",
|
46
47
|
"tagged_detailed": "manual_rank",
|
47
48
|
"tier_detailed": "cancer_tier",
|
48
49
|
"dismissed_detailed": "dismiss_variant",
|
@@ -105,6 +106,7 @@ CASE_TAGS = {
|
|
105
106
|
|
106
107
|
VERBS_MAP = {
|
107
108
|
"acmg": "updated ACMG classification for",
|
109
|
+
"ccv": "updated ClinGen-CGC-VIGG classification for",
|
108
110
|
"add_case": "added case",
|
109
111
|
"add_cohort": "updated cohort for",
|
110
112
|
"add_phenotype": "added HPO term for",
|