scout-browser 4.101.0__py3-none-any.whl → 4.103.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 (87) hide show
  1. scout/adapter/mongo/case.py +26 -122
  2. scout/adapter/mongo/clinvar.py +98 -32
  3. scout/adapter/mongo/event.py +0 -47
  4. scout/adapter/mongo/hgnc.py +7 -2
  5. scout/adapter/mongo/omics_variant.py +8 -0
  6. scout/adapter/mongo/variant_loader.py +12 -4
  7. scout/build/variant/variant.py +1 -0
  8. scout/commands/load/variants.py +1 -1
  9. scout/commands/update/user.py +87 -49
  10. scout/constants/__init__.py +4 -0
  11. scout/constants/clinvar.py +10 -0
  12. scout/constants/igv_tracks.py +6 -2
  13. scout/constants/phenotype.py +1 -0
  14. scout/constants/variant_tags.py +18 -0
  15. scout/demo/NIST.trgt.stranger.vcf.gz +0 -0
  16. scout/demo/NIST.trgt.stranger.vcf.gz.tbi +0 -0
  17. scout/demo/__init__.py +1 -0
  18. scout/load/hpo.py +8 -2
  19. scout/models/clinvar.py +86 -0
  20. scout/parse/variant/coordinates.py +5 -1
  21. scout/parse/variant/gene.py +5 -9
  22. scout/parse/variant/genotype.py +66 -42
  23. scout/parse/variant/variant.py +2 -0
  24. scout/server/app.py +71 -2
  25. scout/server/blueprints/alignviewers/controllers.py +8 -6
  26. scout/server/blueprints/alignviewers/templates/alignviewers/igv_viewer.html +4 -0
  27. scout/server/blueprints/alignviewers/templates/alignviewers/utils.html +1 -1
  28. scout/server/blueprints/cases/controllers.py +57 -29
  29. scout/server/blueprints/cases/templates/cases/case_report.html +28 -90
  30. scout/server/blueprints/cases/templates/cases/matchmaker.html +1 -1
  31. scout/server/blueprints/cases/templates/cases/phenotype.html +1 -1
  32. scout/server/blueprints/cases/templates/cases/utils.html +34 -53
  33. scout/server/blueprints/cases/views.py +32 -33
  34. scout/server/blueprints/clinvar/controllers.py +235 -54
  35. scout/server/blueprints/clinvar/form.py +38 -1
  36. scout/server/blueprints/clinvar/static/form_style.css +8 -1
  37. scout/server/blueprints/clinvar/templates/clinvar/clinvar_onc_submissions.html +200 -0
  38. scout/server/blueprints/clinvar/templates/clinvar/clinvar_submissions.html +3 -2
  39. scout/server/blueprints/clinvar/templates/clinvar/components.html +198 -0
  40. scout/server/blueprints/clinvar/templates/clinvar/multistep_add_onc_variant.html +187 -0
  41. scout/server/blueprints/clinvar/templates/clinvar/multistep_add_variant.html +9 -348
  42. scout/server/blueprints/clinvar/templates/clinvar/scripts.html +193 -0
  43. scout/server/blueprints/clinvar/views.py +90 -13
  44. scout/server/blueprints/diagnoses/controllers.py +4 -8
  45. scout/server/blueprints/diagnoses/templates/diagnoses/diagnoses.html +1 -1
  46. scout/server/blueprints/diagnoses/templates/diagnoses/disease_term.html +1 -1
  47. scout/server/blueprints/diagnoses/views.py +2 -2
  48. scout/server/blueprints/institutes/controllers.py +148 -75
  49. scout/server/blueprints/institutes/forms.py +1 -0
  50. scout/server/blueprints/institutes/templates/overview/cases.html +1 -1
  51. scout/server/blueprints/institutes/templates/overview/gene_variants.html +15 -6
  52. scout/server/blueprints/institutes/templates/overview/institute_sidebar.html +28 -2
  53. scout/server/blueprints/institutes/templates/overview/utils.html +1 -1
  54. scout/server/blueprints/institutes/views.py +17 -4
  55. scout/server/blueprints/login/controllers.py +2 -1
  56. scout/server/blueprints/login/views.py +5 -2
  57. scout/server/blueprints/mme/templates/mme/mme_submissions.html +2 -2
  58. scout/server/blueprints/omics_variants/templates/omics_variants/outliers.html +2 -2
  59. scout/server/blueprints/omics_variants/views.py +2 -2
  60. scout/server/blueprints/phenotypes/controllers.py +15 -2
  61. scout/server/blueprints/phenotypes/templates/phenotypes/hpo_terms.html +1 -1
  62. scout/server/blueprints/variant/controllers.py +11 -12
  63. scout/server/blueprints/variant/templates/variant/cancer-variant.html +2 -1
  64. scout/server/blueprints/variant/templates/variant/components.html +0 -1
  65. scout/server/blueprints/variant/templates/variant/sv-variant.html +2 -1
  66. scout/server/blueprints/variant/templates/variant/utils.html +1 -1
  67. scout/server/blueprints/variant/templates/variant/variant.html +2 -2
  68. scout/server/blueprints/variant/templates/variant/variant_details.html +100 -84
  69. scout/server/blueprints/variant/utils.py +25 -0
  70. scout/server/blueprints/variants/controllers.py +11 -42
  71. scout/server/blueprints/variants/templates/variants/cancer-variants.html +5 -3
  72. scout/server/blueprints/variants/templates/variants/str-variants.html +4 -1
  73. scout/server/blueprints/variants/templates/variants/sv-variants.html +3 -3
  74. scout/server/blueprints/variants/templates/variants/utils.html +4 -0
  75. scout/server/blueprints/variants/templates/variants/variants.html +4 -4
  76. scout/server/blueprints/variants/views.py +9 -8
  77. scout/server/config.py +3 -0
  78. scout/server/extensions/beacon_extension.py +7 -2
  79. scout/server/extensions/clinvar_extension.py +2 -2
  80. scout/server/templates/bootstrap_global.html +11 -1
  81. scout/server/templates/layout.html +6 -1
  82. scout/server/utils.py +24 -3
  83. {scout_browser-4.101.0.dist-info → scout_browser-4.103.0.dist-info}/METADATA +1 -1
  84. {scout_browser-4.101.0.dist-info → scout_browser-4.103.0.dist-info}/RECORD +87 -81
  85. {scout_browser-4.101.0.dist-info → scout_browser-4.103.0.dist-info}/WHEEL +0 -0
  86. {scout_browser-4.101.0.dist-info → scout_browser-4.103.0.dist-info}/entry_points.txt +0 -0
  87. {scout_browser-4.101.0.dist-info → scout_browser-4.103.0.dist-info}/licenses/LICENSE +0 -0
@@ -14,8 +14,6 @@ from werkzeug.datastructures import ImmutableMultiDict
14
14
 
15
15
  from scout.build.case import build_case
16
16
  from scout.constants import (
17
- ACMG_MAP,
18
- CCV_MAP,
19
17
  ID_PROJECTION,
20
18
  ORDERED_FILE_TYPE_MAP,
21
19
  ORDERED_OMICS_FILE_TYPE_MAP,
@@ -1052,7 +1050,7 @@ class CaseHandler(object):
1052
1050
  self.update_case_sanger_variants(institute_obj, case_obj, old_sanger_variants)
1053
1051
 
1054
1052
  if keep_actions and old_evaluated_variants:
1055
- self.update_variant_actions(institute_obj, case_obj, old_evaluated_variants)
1053
+ self.update_variant_actions(case_obj, old_evaluated_variants)
1056
1054
 
1057
1055
  return case_obj
1058
1056
 
@@ -1372,15 +1370,12 @@ class CaseHandler(object):
1372
1370
 
1373
1371
  return case_verif_variants
1374
1372
 
1375
- def update_variant_actions(self, institute_obj, case_obj, old_eval_variants):
1373
+ def update_variant_actions(
1374
+ self, case_obj: dict, old_eval_variants: List[dict]
1375
+ ) -> Dict[str, List[str]]:
1376
1376
  """Update existing variants of a case according to the tagged status
1377
1377
  (manual_rank, dismiss_variant, mosaic_tags) of its previous variants
1378
1378
 
1379
- Accepts:
1380
- institute_obj(dict): an institute object
1381
- case_obj(dict): a case object
1382
- old_eval_variants(list(Variant))
1383
-
1384
1379
  Returns:
1385
1380
  updated_variants(dict): a dictionary like this:
1386
1381
  'manual_rank' : [list of variant ids],
@@ -1391,131 +1386,43 @@ class CaseHandler(object):
1391
1386
  'ccv_classification': [list of variant ids]
1392
1387
  'is_commented': [list of variant ids]
1393
1388
  """
1394
- updated_variants = {
1395
- "manual_rank": [],
1396
- "dismiss_variant": [],
1397
- "mosaic_tags": [],
1398
- "cancer_tier": [],
1399
- "acmg_classification": [],
1400
- "ccv_classification": [],
1401
- "is_commented": [],
1402
- }
1403
-
1404
- update_action_map = {
1405
- "manual_rank": self.update_manual_rank,
1406
- "dismiss_variant": self.update_dismiss_variant,
1407
- "mosaic_tags": self.update_mosaic_tags,
1408
- "cancer_tier": self.update_cancer_tier,
1409
- }
1410
-
1389
+ ACTION_KEYS = [
1390
+ "manual_rank",
1391
+ "dismiss_variant",
1392
+ "mosaic_tags",
1393
+ "cancer_tier",
1394
+ "acmg_classification",
1395
+ "ccv_classification",
1396
+ "is_commented",
1397
+ ]
1398
+ updated_variants = {action: [] for action in ACTION_KEYS}
1411
1399
  LOG.debug(
1412
1400
  "Updating action status for {} variants in case:{}".format(
1413
1401
  len(old_eval_variants), case_obj["_id"]
1414
1402
  )
1415
1403
  )
1416
-
1417
1404
  n_status_updated = 0
1418
1405
  for old_var in old_eval_variants:
1419
1406
  # search for the same variant in newly uploaded vars for this case
1420
1407
  display_name = old_var["display_name"]
1421
-
1422
1408
  new_var = self.variant_collection.find_one(
1423
1409
  {"case_id": case_obj["_id"], "display_name": display_name}
1424
1410
  )
1425
-
1426
1411
  if new_var is None: # same var is no more among case variants, skip it
1427
1412
  LOG.warning(
1428
1413
  "Trying to propagate manual action from an old variant to a new, but couldn't find same variant any more"
1429
1414
  )
1430
1415
  continue
1431
1416
 
1432
- for action in list(
1433
- updated_variants.keys()
1434
- ): # manual_rank, dismiss_variant, mosaic_tags
1435
- # collect only the latest associated event:
1436
- if (
1437
- old_var.get(action) is None and action != "is_commented"
1438
- ): # tag new variant accordingly
1439
- continue
1440
- verb = action
1441
- if action == "acmg_classification":
1442
- verb = "acmg"
1443
- if action == "is_commented":
1444
- verb = "comment"
1445
- if action == "ccv_classification":
1446
- verb = "ccv"
1447
-
1448
- old_event = self.event_collection.find_one(
1449
- {
1450
- "case": case_obj["_id"],
1451
- "verb": verb,
1452
- "variant_id": old_var["variant_id"],
1453
- "category": "variant",
1454
- },
1455
- sort=[("updated_at", pymongo.DESCENDING)],
1456
- )
1457
-
1458
- if old_event is None:
1459
- continue
1460
-
1461
- user_obj = self.user(old_event["user_id"])
1462
- if user_obj is None:
1463
- continue
1464
-
1465
- updated_variant = None
1466
-
1467
- if action == "is_commented":
1468
- updated_comments = self.comments_reupload(
1469
- old_var, new_var, institute_obj, case_obj
1470
- )
1471
- if updated_comments > 0:
1472
- LOG.info(
1473
- "Created {} new comments for variant {} after reupload".format(
1474
- updated_comments, display_name
1475
- )
1476
- )
1477
- updated_variant = new_var
1478
-
1479
- # create a link to the new variant for the events
1480
- link = "/{0}/{1}/{2}".format(
1481
- new_var["institute"], case_obj["display_name"], new_var["_id"]
1482
- )
1483
-
1484
- if action == "acmg_classification":
1485
- str_classif = ACMG_MAP.get(old_var.get("acmg_classification"))
1486
- updated_variant = self.update_acmg(
1487
- institute_obj=institute_obj,
1488
- case_obj=case_obj,
1489
- user_obj=user_obj,
1490
- link=link,
1491
- variant_obj=new_var,
1492
- acmg_str=str_classif,
1417
+ for action in ACTION_KEYS:
1418
+ if old_var.get(action):
1419
+ updated_variant = self.variant_collection.find_one_and_update(
1420
+ {"_id": new_var["_id"]},
1421
+ {"$set": {action: old_var.get(action)}},
1493
1422
  )
1494
-
1495
- if action == "ccv_classification":
1496
- str_classif = CCV_MAP.get(old_var.get("ccv_classification"))
1497
- updated_variant = self.update_ccv(
1498
- institute_obj=institute_obj,
1499
- case_obj=case_obj,
1500
- user_obj=user_obj,
1501
- link=link,
1502
- variant_obj=new_var,
1503
- ccv_str=str_classif,
1504
- )
1505
-
1506
- if action in update_action_map.keys():
1507
- updated_variant = update_action_map[action](
1508
- institute_obj,
1509
- case_obj,
1510
- user_obj,
1511
- link,
1512
- new_var,
1513
- old_var.get(action),
1514
- )
1515
-
1516
- if updated_variant is not None:
1517
- n_status_updated += 1
1518
- updated_variants[action].append(updated_variant["_id"])
1423
+ if updated_variant:
1424
+ n_status_updated += 1
1425
+ updated_variants[action].append(new_var["_id"])
1519
1426
 
1520
1427
  LOG.info("Variant actions updated {} times".format(n_status_updated))
1521
1428
  return updated_variants
@@ -1591,14 +1498,11 @@ class CaseHandler(object):
1591
1498
 
1592
1499
  else:
1593
1500
  # old variant had Sanger validation ordered
1594
- # check old event to collect user_obj that ordered the verification:
1595
1501
  # set sanger ordered status for the new variant as well:
1596
- updated_var = self.order_verification(
1597
- institute=institute_obj,
1598
- case=case_obj,
1599
- user=user_obj,
1600
- link=link,
1601
- variant=new_var,
1502
+ updated_var = self.variant_collection.find_one_and_update(
1503
+ {"_id": new_var["_id"]},
1504
+ {"$set": {"sanger_ordered": True}},
1505
+ return_document=pymongo.ReturnDocument.AFTER,
1602
1506
  )
1603
1507
  if updated_var:
1604
1508
  updated_variants["updated_ordered"].append(updated_var["_id"])
@@ -1,29 +1,48 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import logging
3
+ import re
3
4
  from datetime import datetime
4
- from typing import List, Optional
5
+ from typing import Dict, List, Optional
5
6
 
6
7
  import pymongo
7
- from bson import ObjectId
8
8
  from bson.objectid import ObjectId
9
9
  from pymongo import ReturnDocument
10
10
 
11
+ from scout.constants.clinvar import ASSERTION_CRITERIA_ONC_ID, ASSERTION_ONC_ONC_DB
12
+
11
13
  LOG = logging.getLogger(__name__)
12
14
 
13
15
 
14
16
  class ClinVarHandler(object):
15
17
  """Class to handle clinvar submissions for the mongo adapter"""
16
18
 
17
- def create_submission(self, institute_id: str, user_id: str) -> ObjectId:
18
- """Create an open ClinVar submission for an institute."""
19
+ def create_germline_submission(self, institute_id: str, user_id: str) -> ObjectId:
20
+ """Create an open ClinVar germline submission for an institute."""
21
+
22
+ submission_obj = {
23
+ "status": "open",
24
+ "created_at": datetime.now(),
25
+ "institute_id": institute_id,
26
+ "created_by": user_id,
27
+ }
28
+ LOG.info("Creating a new ClinVar germline submission for institute %s", institute_id)
29
+ result = self.clinvar_submission_collection.insert_one(submission_obj)
30
+ return result.inserted_id
31
+
32
+ def create_oncogenicity_submission(self, institute_id: str, user_id: str) -> ObjectId:
33
+ """Create an open ClinVar oncogenicity submission for an institute."""
19
34
 
20
35
  submission_obj = {
21
36
  "status": "open",
37
+ "type": "oncogenicity",
22
38
  "created_at": datetime.now(),
39
+ "updated_at": datetime.now(),
23
40
  "institute_id": institute_id,
24
41
  "created_by": user_id,
42
+ "assertionCriteria": {"db": ASSERTION_ONC_ONC_DB, "id": ASSERTION_CRITERIA_ONC_ID},
43
+ "oncogenicitySubmission": [],
25
44
  }
26
- LOG.info("Creating a new ClinVar submission for institute %s", institute_id)
45
+ LOG.info("Creating a new ClinVar oncogenicity submission for institute %s", institute_id)
27
46
  result = self.clinvar_submission_collection.insert_one(submission_obj)
28
47
  return result.inserted_id
29
48
 
@@ -65,18 +84,31 @@ class ClinVarHandler(object):
65
84
  # return deleted_count, deleted_submissions
66
85
  return deleted_objects, deleted_submissions
67
86
 
68
- def get_open_clinvar_submission(self, institute_id: str, user_id: str) -> dict:
69
- """Retrieve the database id of an open ClinVar submission for an institute,
87
+ def get_open_germline_clinvar_submission(self, institute_id: str, user_id: str) -> dict:
88
+ """Retrieve the database id of an open ClinVar germline submission for an institute,
70
89
  if none is available then creates a new submission dictionary and returns it.
71
90
  """
72
91
 
73
- LOG.info("Retrieving an open clinvar submission for institute %s", institute_id)
74
92
  query = dict(institute_id=institute_id, status="open")
75
93
  submission = self.clinvar_submission_collection.find_one(query)
76
94
 
77
95
  # If there is no open submission for this institute, create one
78
96
  if submission is None:
79
- submission_id = self.create_submission(institute_id, user_id)
97
+ submission_id = self.create_germline_submission(institute_id, user_id)
98
+ submission = self.clinvar_submission_collection.find_one({"_id": submission_id})
99
+
100
+ return submission
101
+
102
+ def get_open_onc_clinvar_submission(self, institute_id: str, user_id: str) -> dict:
103
+ """Retrieve the database id of an open ClinVar oncogenicity submission for an institute,
104
+ if none is available then creates a new submission dictionary and returns it.
105
+ """
106
+
107
+ query = dict(institute_id=institute_id, status="open", type="oncogenicity")
108
+ submission = self.clinvar_submission_collection.find_one(query)
109
+ # If there is no open submission for this institute, create one
110
+ if submission is None:
111
+ submission_id = self.create_oncogenicity_submission(institute_id, user_id)
80
112
  submission = self.clinvar_submission_collection.find_one({"_id": submission_id})
81
113
 
82
114
  return submission
@@ -230,9 +262,14 @@ class ClinVarHandler(object):
230
262
  "updated_at": result.get("updated_at"),
231
263
  }
232
264
 
233
- def clinvar_submissions(self, institute_id: str) -> List[dict]:
234
- """Collect all open and closed clinvar submissions for an institute"""
235
- query = dict(institute_id=institute_id)
265
+ def get_clinvar_onc_submissions(self, institute_id: str) -> pymongo.cursor.Cursor:
266
+ """Collect all open and closed ClinVar oncogenocity submissions for an institute."""
267
+ query = {"institute_id": institute_id, "type": "oncogenicity"}
268
+ return self.clinvar_submission_collection.find(query).sort("updated_at", pymongo.DESCENDING)
269
+
270
+ def get_clinvar_germline_submissions(self, institute_id: str) -> List[dict]:
271
+ """Collect all open and closed ClinVar germline submissions for an institute."""
272
+ query = {"institute_id": institute_id, "type": {"$exists": False}}
236
273
  results = list(
237
274
  self.clinvar_submission_collection.find(query).sort("updated_at", pymongo.DESCENDING)
238
275
  )
@@ -298,8 +335,8 @@ class ClinVarHandler(object):
298
335
  criteria = {"assertionCriteriaDB": amc_db, "assertionCriteriaID": amc_id}
299
336
  return criteria
300
337
 
301
- def clinvar_objs(self, submission_id, key_id):
302
- """Collects a list of objects from the clinvar collection (variants of case data) as specified by the key_id in the clinvar submission
338
+ def clinvar_objs(self, submission_id: str, key_id: str) -> list:
339
+ """Collects a list of objects from the ClinVar collection (variants of case data) as specified by the key_id in the submission.
303
340
 
304
341
  Args:
305
342
  submission_id(str): the _id key of a clinvar submission
@@ -308,8 +345,8 @@ class ClinVarHandler(object):
308
345
 
309
346
  Returns:
310
347
  clinvar_objects(list) : a list of clinvar objects (either variants of casedata)
311
-
312
348
  """
349
+
313
350
  # Get a submission object
314
351
  submission = self.clinvar_submission_collection.find_one({"_id": ObjectId(submission_id)})
315
352
 
@@ -319,7 +356,7 @@ class ClinVarHandler(object):
319
356
  clinvar_objects = self.clinvar_collection.find({"_id": {"$in": clinvar_obj_ids}})
320
357
  return list(clinvar_objects)
321
358
 
322
- return None
359
+ return []
323
360
 
324
361
  def rename_casedata_samples(self, submission_id, case_id, old_name, new_name):
325
362
  """Rename all samples associated to a clinVar submission
@@ -393,30 +430,32 @@ class ClinVarHandler(object):
393
430
  self.clinvar_collection.delete_one({"_id": object_id})
394
431
 
395
432
  # in any case remove reference to it in the submission object 'case_data' list field
396
- self.clinvar_submission_collection.find_one_and_update(
397
- {"_id": ObjectId(submission_id)}, {"$pull": {"case_data": object_id}}
398
- )
399
433
 
400
434
  return self.clinvar_submission_collection.find_one_and_update(
401
- {"_id": submission_id},
402
- {"$set": {"updated_at": datetime.now()}},
403
- return_document=pymongo.ReturnDocument.AFTER,
435
+ {"_id": ObjectId(submission_id)},
436
+ {
437
+ "$set": {"updated_at": datetime.now()},
438
+ "$pull": {"case_data": {"$regex": f"^{re.escape(object_id)}"}},
439
+ },
440
+ return_document=ReturnDocument.AFTER,
404
441
  )
405
442
 
406
- def case_to_clinVars(self, case_id):
407
- """Get all variants included in clinvar submissions for a case
443
+ def delete_clinvar_onc_var(self, submission: str, variant_id: str) -> dict:
444
+ """Removes an oncogenicity submission or one or its variants."""
408
445
 
409
- Args:
410
- case_id(str): a case _id
411
-
412
- Returns:
413
- submission_variants(dict): keys are variant ids and values are variant submission objects
446
+ return self.clinvar_submission_collection.find_one_and_update(
447
+ {"_id": ObjectId(submission)},
448
+ {"$pull": {"oncogenicitySubmission": {"variant_id": variant_id}}},
449
+ return_document=pymongo.ReturnDocument.AFTER,
450
+ )
414
451
 
415
- """
452
+ def case_to_clinvars(self, case_id: str) -> Dict[str, dict]:
453
+ """Get all variants included in ClinVar submissions for a case. Returns a dictionary with variant IDs as keys and submissions as values."""
416
454
  query = dict(case_id=case_id, csv_type="variant")
417
- clinvar_objs = list(self.clinvar_collection.find(query))
455
+ germline_clinvar_objs = list(self.clinvar_collection.find(query))
456
+ oncogenic_clinvar_objs = []
418
457
  submitted_vars = {}
419
- for clinvar in clinvar_objs:
458
+ for clinvar in germline_clinvar_objs + oncogenic_clinvar_objs:
420
459
  submitted_vars[clinvar.get("local_id")] = clinvar
421
460
 
422
461
  return submitted_vars
@@ -454,3 +493,30 @@ class ClinVarHandler(object):
454
493
  for clinvar_var in clinvar_vars_for_case:
455
494
  if variant_id in clinvar_var["link"]:
456
495
  return clinvar_var["user_name"]
496
+
497
+ def get_onc_submission_json(self, submission: str) -> Optional[dict]:
498
+ """Returns a json oncogenicity submission file, as a json."""
499
+
500
+ submission_dict = self.clinvar_submission_collection.find_one(
501
+ {"_id": ObjectId(submission), "type": "oncogenicity"}
502
+ )
503
+ if not submission_dict:
504
+ return
505
+
506
+ for key in [
507
+ "_id",
508
+ "clinvar_subm_id",
509
+ "status",
510
+ "type",
511
+ "created_at",
512
+ "updated_at",
513
+ "created_by",
514
+ "institute_id",
515
+ ]:
516
+ submission_dict.pop(key, None)
517
+
518
+ for var in submission_dict.get("oncogenicitySubmission", []):
519
+ for key in ["institute_id", "case_id", "case_name", "variant_id"]:
520
+ var.pop(key, None)
521
+
522
+ return submission_dict
@@ -552,50 +552,3 @@ class EventHandler(CaseEventHandler, VariantEventHandler):
552
552
  )
553
553
  self.event_collection.insert_one(event)
554
554
  return updated_comment
555
-
556
- def comments_reupload(self, old_var, new_var, institute_obj, case_obj):
557
- """Creates comments for a new variant after variant reupload
558
-
559
- Accepts:
560
- old_var(Variant): the deleted variant
561
- new_var(Variant): the new variant replacing old_var
562
- institute_obj(dict): an institute object
563
- case_obj(dict): a case object
564
-
565
- Returns:
566
- new_comments(int): the number of created comments
567
- """
568
- new_comments = 0
569
-
570
- if new_var["_id"] == old_var["_id"]:
571
- return new_comments
572
-
573
- link = "/{0}/{1}/{2}".format(new_var["institute"], case_obj["display_name"], new_var["_id"])
574
-
575
- # collect all comments for the old variant
576
- comments_query = self.events(
577
- variant_id=old_var["variant_id"],
578
- comments=True,
579
- institute=institute_obj,
580
- case=case_obj,
581
- )
582
-
583
- # and create the same comment for the new variant
584
- for old_comment in comments_query:
585
- comment_user = self.user(old_comment["user_id"])
586
- if comment_user is None:
587
- continue
588
-
589
- updated_comment = self.comment(
590
- institute=institute_obj,
591
- case=case_obj,
592
- user=comment_user,
593
- link=link,
594
- variant=new_var,
595
- content=old_comment.get("content"),
596
- comment_level=old_comment.get("level"),
597
- )
598
- if updated_comment:
599
- new_comments += 1
600
-
601
- return new_comments
@@ -1,5 +1,5 @@
1
1
  import logging
2
- from typing import Dict, Set
2
+ from typing import Dict, Optional, Set
3
3
 
4
4
  import intervaltree
5
5
  from pymongo.errors import BulkWriteError, DuplicateKeyError
@@ -44,7 +44,9 @@ class GeneHandler(object):
44
44
 
45
45
  return result
46
46
 
47
- def hgnc_gene_caption(self, hgnc_identifier, build=None):
47
+ def hgnc_gene_caption(
48
+ self, hgnc_identifier: Optional[int] = None, build: Optional[str] = None
49
+ ) -> Optional[dict]:
48
50
  """Fetch the current hgnc gene symbol and similar caption info for a gene in a lightweight dict
49
51
  Avoid populating transcripts, exons etc that would be added on a full gene object. Use hgnc_gene() if
50
52
  you need to use those.
@@ -57,6 +59,9 @@ class GeneHandler(object):
57
59
  gene_caption(dict): light pymongo document with keys "hgnc_symbol", "description", "chromosome", "start", "end".
58
60
  """
59
61
 
62
+ if not hgnc_identifier:
63
+ return
64
+
60
65
  query = {"hgnc_id": int(hgnc_identifier)}
61
66
 
62
67
  if build in ["37", "38"]:
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ import os
2
3
  from typing import Dict, Iterable, List, Optional
3
4
 
4
5
  from pymongo import ASCENDING, DESCENDING
@@ -130,6 +131,13 @@ class OmicsVariantHandler:
130
131
 
131
132
  nr_inserted = 0
132
133
 
134
+ file_path = case_obj["omics_files"].get(file_type) if case_obj.get("omics_files") else None
135
+ if file_path is None or os.path.exists(file_path) is False:
136
+ LOG.warning(
137
+ f"File '{file_path}' not found on disk. Please update case {case_obj['_id']} with a valid file path for {file_type}."
138
+ )
139
+ return
140
+
133
141
  file_handle = open(case_obj["omics_files"].get(file_type), "r")
134
142
 
135
143
  for omics_info in parse_omics_file(file_handle, omics_file_type=omics_file_type):
@@ -642,7 +642,6 @@ class VariantLoader(object):
642
642
  Returns:
643
643
  nr_inserted(int)
644
644
  """
645
-
646
645
  institute_id = case_obj["owner"]
647
646
 
648
647
  nr_inserted = 0
@@ -658,10 +657,19 @@ class VariantLoader(object):
658
657
  if vcf_dict["category"] != category:
659
658
  continue
660
659
 
661
- LOG.info(f"Loading'{vcf_file_key}' variants")
662
- variant_file = case_obj["vcf_files"].get(vcf_file_key)
660
+ variant_file = (
661
+ case_obj["vcf_files"].get(vcf_file_key) if case_obj.get("vcf_files") else None
662
+ )
663
+
664
+ if variant_file:
665
+ LOG.info(f"Loading {vcf_file_key} variants")
666
+ else:
667
+ continue
663
668
 
664
- if not variant_file or not self._has_variants_in_file(variant_file):
669
+ if not self._has_variants_in_file(variant_file):
670
+ LOG.warning(
671
+ f"File '{variant_file}' not found on disk. Please update case {case_obj['_id']} with a valid file path for the {category} variant category ."
672
+ )
665
673
  continue
666
674
 
667
675
  vcf_obj = VCF(variant_file)
@@ -190,6 +190,7 @@ def build_variant(
190
190
  variant_obj["position"] = int(variant["position"])
191
191
  variant_obj["quality"] = float(variant["quality"]) if variant["quality"] else None
192
192
  variant_obj["rank_score"] = float(variant["rank_score"])
193
+ variant_obj["norm_rank_score"] = float(variant["norm_rank_score"])
193
194
  variant_obj["simple_id"] = variant["ids"].get("simple_id")
194
195
  variant_obj["sub_category"] = variant.get("sub_category")
195
196
 
@@ -274,4 +274,4 @@ def variants(
274
274
  adapter.update_case_sanger_variants(institute_obj, case_obj, old_sanger_variants)
275
275
 
276
276
  if keep_actions and old_evaluated_variants:
277
- adapter.update_variant_actions(institute_obj, case_obj, old_evaluated_variants)
277
+ adapter.update_variant_actions(case_obj, old_evaluated_variants)