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
scout/server/app.py
CHANGED
@@ -8,7 +8,6 @@ from urllib.parse import parse_qsl, unquote, urlsplit
|
|
8
8
|
|
9
9
|
import coloredlogs
|
10
10
|
from flask import Flask, current_app, redirect, request, url_for
|
11
|
-
from flask_babel import Babel
|
12
11
|
from flask_cors import CORS
|
13
12
|
from flask_login import current_user
|
14
13
|
from markdown import markdown as python_markdown
|
@@ -36,16 +35,6 @@ from .blueprints import (
|
|
36
35
|
|
37
36
|
LOG = logging.getLogger(__name__)
|
38
37
|
|
39
|
-
try:
|
40
|
-
from chanjo_report.server.app import configure_template_filters
|
41
|
-
from chanjo_report.server.blueprints import report_bp
|
42
|
-
from chanjo_report.server.extensions import api as chanjo_api
|
43
|
-
except ImportError:
|
44
|
-
chanjo_api = None
|
45
|
-
report_bp = None
|
46
|
-
configure_template_filters = None
|
47
|
-
LOG.info("chanjo report not installed!")
|
48
|
-
|
49
38
|
|
50
39
|
def create_app(config_file=None, config=None):
|
51
40
|
"""Flask app factory function."""
|
@@ -111,8 +100,8 @@ def configure_extensions(app):
|
|
111
100
|
extensions.mail.init_app(app)
|
112
101
|
|
113
102
|
if app.config.get("SQLALCHEMY_DATABASE_URI"):
|
103
|
+
extensions.chanjo_report.init_app(app)
|
114
104
|
LOG.info("Chanjo extension enabled")
|
115
|
-
configure_coverage(app)
|
116
105
|
|
117
106
|
if app.config.get("LOQUSDB_SETTINGS"):
|
118
107
|
LOG.info("LoqusDB enabled")
|
@@ -157,9 +146,9 @@ def configure_extensions(app):
|
|
157
146
|
# setup connection to google oauth2
|
158
147
|
configure_oauth_login(app)
|
159
148
|
|
160
|
-
if app.config.get("CLOUD_IGV_TRACKS"):
|
161
|
-
LOG.info("Collecting IGV tracks from cloud resources")
|
162
|
-
extensions.
|
149
|
+
if app.config.get("CUSTOM_IGV_TRACKS") or app.config.get("CLOUD_IGV_TRACKS"):
|
150
|
+
LOG.info("Collecting IGV tracks from cloud or local resources")
|
151
|
+
extensions.config_igv_tracks.init_app(app)
|
163
152
|
|
164
153
|
if app.config.get("PHENOPACKET_API_URL"):
|
165
154
|
LOG.info("Enable Phenopacket API")
|
@@ -319,38 +308,3 @@ def configure_email_logging(app):
|
|
319
308
|
)
|
320
309
|
)
|
321
310
|
app.logger.addHandler(mail_handler)
|
322
|
-
|
323
|
-
|
324
|
-
def configure_coverage(app):
|
325
|
-
"""Setup coverage related extensions."""
|
326
|
-
# setup chanjo report
|
327
|
-
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True if app.debug else False
|
328
|
-
if chanjo_api:
|
329
|
-
chanjo_api.init_app(app)
|
330
|
-
configure_template_filters(app)
|
331
|
-
# register chanjo report blueprint
|
332
|
-
app.register_blueprint(report_bp, url_prefix="/reports")
|
333
|
-
|
334
|
-
babel = Babel()
|
335
|
-
|
336
|
-
def get_locale():
|
337
|
-
"""Determine locale to use for translations."""
|
338
|
-
accept_languages = current_app.config.get("ACCEPT_LANGUAGES", ["en"])
|
339
|
-
|
340
|
-
# first check request args
|
341
|
-
session_language = Markup.escape(request.args.get("lang"))
|
342
|
-
if session_language in accept_languages:
|
343
|
-
current_app.logger.info("using session language: %s", session_language)
|
344
|
-
return session_language
|
345
|
-
|
346
|
-
# language can be forced in config
|
347
|
-
user_language = current_app.config.get("REPORT_LANGUAGE")
|
348
|
-
if user_language:
|
349
|
-
return user_language
|
350
|
-
|
351
|
-
# try to guess the language from the user accept header that
|
352
|
-
# the browser transmits. We support de/fr/en in this example.
|
353
|
-
# The best match wins.
|
354
|
-
return request.accept_languages.best_match(accept_languages)
|
355
|
-
|
356
|
-
babel.init_app(app, locale_selector=get_locale)
|
@@ -7,7 +7,7 @@ from flask import flash, session
|
|
7
7
|
from flask_login import current_user
|
8
8
|
|
9
9
|
from scout.constants import CASE_SPECIFIC_TRACKS, HUMAN_REFERENCE, IGV_TRACKS
|
10
|
-
from scout.server.extensions import
|
10
|
+
from scout.server.extensions import config_igv_tracks, store
|
11
11
|
from scout.server.utils import case_append_alignments, find_index
|
12
12
|
from scout.utils.ensembl_rest_clients import EnsemblRestApiClient
|
13
13
|
|
@@ -34,15 +34,16 @@ def check_session_tracks(resource):
|
|
34
34
|
return True
|
35
35
|
|
36
36
|
|
37
|
-
def set_session_tracks(display_obj):
|
37
|
+
def set_session_tracks(display_obj: dict):
|
38
38
|
"""Save igv tracks as a session object. This way it's easy to verify that a user is requesting one of these files from remote_static view endpoint
|
39
39
|
|
40
40
|
Args:
|
41
41
|
display_obj(dict): A display object containing case name, list of genes, locus and tracks
|
42
42
|
"""
|
43
|
+
|
43
44
|
session_tracks = list(display_obj.get("reference_track", {}).values())
|
44
45
|
for key, track_items in display_obj.items():
|
45
|
-
if key not in ["tracks", "custom_tracks", "sample_tracks", "
|
46
|
+
if key not in ["tracks", "custom_tracks", "sample_tracks", "config_custom_tracks"]:
|
46
47
|
continue
|
47
48
|
for track_item in track_items:
|
48
49
|
session_tracks += list(track_item.values())
|
@@ -107,7 +108,7 @@ def make_igv_tracks(case_obj, variant_id, chrom=None, start=None, stop=None):
|
|
107
108
|
set_case_specific_tracks(display_obj, case_obj)
|
108
109
|
|
109
110
|
# Set up custom cloud public tracks, if available
|
110
|
-
|
111
|
+
set_config_custom_tracks(display_obj, build)
|
111
112
|
|
112
113
|
display_obj["display_center_guide"] = True
|
113
114
|
|
@@ -295,23 +296,20 @@ def set_case_specific_tracks(display_obj, case_obj):
|
|
295
296
|
display_obj[track] = track_info
|
296
297
|
|
297
298
|
|
298
|
-
def
|
299
|
-
"""Set up custom public tracks stored in a cloud bucket
|
300
|
-
|
301
|
-
Args:
|
302
|
-
display_obj(dict) dictionary containing all tracks info
|
303
|
-
build(string) "37" or "38"
|
304
|
-
"""
|
299
|
+
def set_config_custom_tracks(display_obj: dict, build: str):
|
300
|
+
"""Set up custom public or private tracks stored in a cloud bucket or locally. These tracks were those specified in the Scout config file.
|
301
|
+
Respect user's preferences."""
|
305
302
|
user_obj = store.user(email=current_user.email)
|
306
303
|
custom_tracks_names = user_obj.get("igv_tracks")
|
307
304
|
|
308
|
-
|
309
|
-
|
310
|
-
|
305
|
+
config_custom_tracks = []
|
306
|
+
|
307
|
+
if hasattr(config_igv_tracks, "tracks"):
|
308
|
+
build_tracks = config_igv_tracks.tracks.get(build, [])
|
311
309
|
for track in build_tracks:
|
312
310
|
# Do not display track if user doesn't want to see it
|
313
311
|
if custom_tracks_names and track["name"] not in custom_tracks_names:
|
314
312
|
continue
|
315
|
-
|
316
|
-
if
|
317
|
-
display_obj["
|
313
|
+
config_custom_tracks.append(track)
|
314
|
+
if config_custom_tracks:
|
315
|
+
display_obj["config_custom_tracks"] = config_custom_tracks
|
@@ -64,13 +64,23 @@
|
|
64
64
|
{% endif %}
|
65
65
|
},
|
66
66
|
{% endfor %}
|
67
|
-
{% for custTrack in
|
67
|
+
{% for custTrack in config_custom_tracks %}
|
68
68
|
{
|
69
69
|
name: "{{ custTrack.name }}",
|
70
70
|
type: "{{ custTrack.type }}",
|
71
71
|
format: "{{ custTrack.format }}",
|
72
|
-
|
73
|
-
|
72
|
+
height: 70,
|
73
|
+
{% if "http" in custTrack.url %}
|
74
|
+
url: "{{ url_for('alignviewers.remote_cors', remote_url=custTrack.url) }}",
|
75
|
+
{% if custTrack.indexURL %}
|
76
|
+
indexURL: "{{ url_for('alignviewers.remote_cors', remote_url=custTrack.indexURL) }}",
|
77
|
+
{% endif %}
|
78
|
+
{% else %}
|
79
|
+
url: "{{ url_for('alignviewers.remote_static', file=custTrack.url) }}",
|
80
|
+
{% if custTrack.indexURL %}
|
81
|
+
indexURL: "{{ url_for('alignviewers.remote_static', file=custTrack.indexURL) }}",
|
82
|
+
{% endif %}
|
83
|
+
{% endif %}
|
74
84
|
},
|
75
85
|
{% endfor %}
|
76
86
|
{% for wtrack in rhocall_wig %}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
import logging
|
3
|
+
from typing import Optional
|
3
4
|
|
4
5
|
import requests
|
5
6
|
from flask import (
|
@@ -11,7 +12,6 @@ from flask import (
|
|
11
12
|
request,
|
12
13
|
session,
|
13
14
|
)
|
14
|
-
from flask_login import current_user
|
15
15
|
|
16
16
|
from scout.server.extensions import store
|
17
17
|
from scout.server.utils import institute_and_case
|
@@ -119,20 +119,15 @@ def sashimi_igv(institute_id, case_name, variant_id=None):
|
|
119
119
|
@alignviewers_bp.route(
|
120
120
|
"/<institute_id>/<case_name>/<variant_id>/<chrom>/<start>/<stop>/igv", methods=["GET"]
|
121
121
|
) # from SV variant page, where you have to pass breakpoints coordinates
|
122
|
-
def igv(
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
stop(int/None): stop of the genomic interval to be displayed
|
132
|
-
|
133
|
-
Returns:
|
134
|
-
a string, corresponging to the HTML rendering of the IGV alignments page
|
135
|
-
"""
|
122
|
+
def igv(
|
123
|
+
institute_id: str,
|
124
|
+
case_name: str,
|
125
|
+
variant_id: Optional[str] = None,
|
126
|
+
chrom: Optional[str] = None,
|
127
|
+
start: Optional[int] = None,
|
128
|
+
stop: Optional[int] = None,
|
129
|
+
) -> Response:
|
130
|
+
"""Visualize BAM alignments using igv.js (https://github.com/igvteam/igv.js)."""
|
136
131
|
_, case_obj = institute_and_case(
|
137
132
|
store, institute_id, case_name
|
138
133
|
) # This function takes care of checking if user is authorized to see resource
|
@@ -48,6 +48,7 @@ from scout.server.utils import (
|
|
48
48
|
case_has_chanjo2_coverage,
|
49
49
|
case_has_chanjo_coverage,
|
50
50
|
case_has_mt_alignments,
|
51
|
+
case_has_mtdna_report,
|
51
52
|
case_has_rna_tracks,
|
52
53
|
institute_and_case,
|
53
54
|
)
|
@@ -62,6 +63,8 @@ JSON_HEADERS = {
|
|
62
63
|
|
63
64
|
COVERAGE_REPORT_TIMEOUT = 20
|
64
65
|
|
66
|
+
PANEL_PROJECTION = {"version": 1, "display_name": 1, "genes": 1}
|
67
|
+
|
65
68
|
|
66
69
|
def phenomizer_diseases(hpo_ids, case_obj, p_value_treshold=1):
|
67
70
|
"""Return the list of HGNC symbols that match annotated HPO terms on Phenomizer
|
@@ -278,22 +281,16 @@ def sma_case(store, institute_obj, case_obj):
|
|
278
281
|
return data
|
279
282
|
|
280
283
|
|
281
|
-
def case(
|
284
|
+
def case(
|
285
|
+
store: MongoAdapter, institute_obj: dict, case_obj: dict, hide_matching: bool = True
|
286
|
+
) -> dict:
|
282
287
|
"""Preprocess a single case.
|
283
288
|
|
284
289
|
Prepare the case to be displayed in the case view.
|
285
290
|
|
286
|
-
|
287
|
-
store(adapter.MongoAdapter)
|
288
|
-
institute_obj(models.Institute)
|
289
|
-
case_obj(models.Case)
|
290
|
-
|
291
|
-
Returns:
|
292
|
-
data(dict): includes the cases, how many there are and the limit.
|
293
|
-
|
291
|
+
The return data dict includes the cases, how many there are and the limit.
|
294
292
|
"""
|
295
293
|
# Convert individual information to more readable format
|
296
|
-
|
297
294
|
_populate_case_individuals(case_obj)
|
298
295
|
|
299
296
|
case_obj["assignees"] = [
|
@@ -305,6 +302,7 @@ def case(store, institute_obj, case_obj):
|
|
305
302
|
case_has_mt_alignments(case_obj)
|
306
303
|
case_has_chanjo_coverage(case_obj)
|
307
304
|
case_has_chanjo2_coverage(case_obj)
|
305
|
+
case_has_mtdna_report(case_obj)
|
308
306
|
|
309
307
|
case_groups = {}
|
310
308
|
case_group_label = {}
|
@@ -395,31 +393,40 @@ def case(store, institute_obj, case_obj):
|
|
395
393
|
"case_images", case_obj["custom_images"].get("case", {})
|
396
394
|
)
|
397
395
|
|
398
|
-
|
399
|
-
|
396
|
+
other_causatives = []
|
397
|
+
other_causatives_in_default_panels = []
|
398
|
+
default_managed_variants = []
|
399
|
+
managed_variants = []
|
400
400
|
|
401
|
-
|
402
|
-
|
403
|
-
|
401
|
+
if hide_matching is False:
|
402
|
+
# Limit secondary findings according to institute settings
|
403
|
+
limit_genes = store.safe_genes_filter(institute_obj["_id"])
|
404
404
|
|
405
|
-
|
406
|
-
|
407
|
-
|
405
|
+
limit_genes_default_panels = _limit_genes_on_default_panels(
|
406
|
+
case_obj["default_genes"], limit_genes
|
407
|
+
)
|
408
408
|
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
"managed_variants": [
|
409
|
+
other_causatives, other_causatives_in_default_panels = _matching_causatives(
|
410
|
+
store, case_obj, limit_genes, limit_genes_default_panels
|
411
|
+
)
|
412
|
+
|
413
|
+
managed_variants = [
|
415
414
|
var for var in store.check_managed(case_obj=case_obj, limit_genes=limit_genes)
|
416
|
-
]
|
417
|
-
|
415
|
+
]
|
416
|
+
default_managed_variants = [
|
418
417
|
var
|
419
418
|
for var in store.check_managed(
|
420
419
|
case_obj=case_obj, limit_genes=limit_genes_default_panels
|
421
420
|
)
|
422
|
-
]
|
421
|
+
]
|
422
|
+
|
423
|
+
data = {
|
424
|
+
"institute": institute_obj,
|
425
|
+
"case": case_obj,
|
426
|
+
"other_causatives": other_causatives,
|
427
|
+
"default_other_causatives": other_causatives_in_default_panels,
|
428
|
+
"managed_variants": managed_variants,
|
429
|
+
"default_managed_variants": default_managed_variants,
|
423
430
|
"comments": store.events(institute_obj, case=case_obj, comments=True),
|
424
431
|
"hpo_groups": pheno_groups,
|
425
432
|
"case_groups": case_groups,
|
@@ -441,6 +448,7 @@ def case(store, institute_obj, case_obj):
|
|
441
448
|
"mme_nodes": matchmaker.connected_nodes,
|
442
449
|
"gens_info": gens.connection_settings(case_obj.get("genome_build")),
|
443
450
|
"display_rerunner": rerunner.connection_settings.get("display", False),
|
451
|
+
"hide_matching": hide_matching,
|
444
452
|
}
|
445
453
|
|
446
454
|
return data
|
@@ -496,8 +504,12 @@ def _get_default_panel_genes(store: MongoAdapter, case_obj: dict) -> list:
|
|
496
504
|
continue
|
497
505
|
panel_name = panel_info["panel_name"]
|
498
506
|
panel_version = panel_info.get("version")
|
499
|
-
panel_obj = store.gene_panel(
|
500
|
-
|
507
|
+
panel_obj = store.gene_panel(
|
508
|
+
panel_name,
|
509
|
+
version=panel_version,
|
510
|
+
projection=PANEL_PROJECTION,
|
511
|
+
)
|
512
|
+
latest_panel = store.gene_panel(panel_name, projection=PANEL_PROJECTION)
|
501
513
|
panel_info["removed"] = False if latest_panel is None else latest_panel.get("hidden", False)
|
502
514
|
if not panel_obj:
|
503
515
|
panel_obj = latest_panel
|
@@ -555,19 +567,17 @@ def check_outdated_gene_panel(panel_obj, latest_panel):
|
|
555
567
|
missing_genes, extra_genes
|
556
568
|
"""
|
557
569
|
# Create a list of minified gene object for the case panel {hgnc_id, gene_symbol}
|
558
|
-
case_panel_genes = [
|
559
|
-
{"hgnc_id": gene["hgnc_id"], "symbol": gene.get("symbol", gene["hgnc_id"])}
|
560
|
-
for gene in panel_obj["genes"]
|
561
|
-
]
|
570
|
+
case_panel_genes = set([gene.get("symbol", gene["hgnc_id"]) for gene in panel_obj["genes"]])
|
562
571
|
# And for the latest panel
|
563
|
-
latest_panel_genes =
|
564
|
-
|
565
|
-
|
566
|
-
]
|
572
|
+
latest_panel_genes = set(
|
573
|
+
[gene.get("symbol", gene["hgnc_id"]) for gene in latest_panel["genes"]]
|
574
|
+
)
|
567
575
|
# Extract the genes unique to case panel
|
568
|
-
extra_genes =
|
576
|
+
extra_genes = case_panel_genes.difference(latest_panel_genes)
|
577
|
+
|
569
578
|
# Extract the genes unique to latest panel
|
570
|
-
missing_genes =
|
579
|
+
missing_genes = latest_panel_genes.difference(case_panel_genes)
|
580
|
+
|
571
581
|
return extra_genes, missing_genes
|
572
582
|
|
573
583
|
|
@@ -674,7 +684,7 @@ def case_report_content(store: MongoAdapter, institute_obj: dict, case_obj: dict
|
|
674
684
|
return data
|
675
685
|
|
676
686
|
|
677
|
-
def mt_coverage_stats(individuals, ref_chrom="14"):
|
687
|
+
def mt_coverage_stats(individuals, ref_chrom="14") -> dict:
|
678
688
|
"""Send a request to chanjo report endpoint to retrieve MT vs autosome coverage stats
|
679
689
|
|
680
690
|
Args:
|
@@ -732,10 +742,9 @@ def mt_excel_files(store, case_obj, temp_excel_dir):
|
|
732
742
|
"""
|
733
743
|
today = datetime.datetime.now().strftime(DATE_DAY_FORMATTER)
|
734
744
|
samples = case_obj.get("individuals")
|
735
|
-
file_header = MT_EXPORT_HEADER
|
736
745
|
coverage_stats = None
|
737
746
|
# if chanjo connection is established, include MT vs AUTOSOME coverage stats
|
738
|
-
if current_app.config.get("
|
747
|
+
if current_app.config.get("chanjo_report"):
|
739
748
|
coverage_stats = mt_coverage_stats(samples)
|
740
749
|
|
741
750
|
query = {"chrom": "MT"}
|
@@ -765,9 +774,8 @@ def mt_excel_files(store, case_obj, temp_excel_dir):
|
|
765
774
|
for col, field in enumerate(line): # each field in line becomes a cell
|
766
775
|
Report_Sheet.write(row, col, field)
|
767
776
|
|
768
|
-
if
|
769
|
-
|
770
|
-
): # it's None if app is not connected to Chanjo or {} if samples are not in Chanjo db
|
777
|
+
# coverage_stats is None if app is not connected to Chanjo or {} if samples are not in Chanjo db
|
778
|
+
if coverage_stats and sample_id in coverage_stats:
|
771
779
|
# Write coverage stats header after introducing 2 empty lines
|
772
780
|
for col, field in enumerate(MT_COV_STATS_HEADER):
|
773
781
|
Report_Sheet.write(row + 3, col, field)
|
@@ -805,27 +813,6 @@ def update_synopsis(store, institute_obj, case_obj, user_obj, new_synopsis):
|
|
805
813
|
store.update_synopsis(institute_obj, case_obj, user_obj, link, content=new_synopsis)
|
806
814
|
|
807
815
|
|
808
|
-
def _update_case(store, case_obj, user_obj, institute_obj, verb):
|
809
|
-
"""Update case with new sample data, and create an associated event"""
|
810
|
-
store.update_case(case_obj, keep_date=True)
|
811
|
-
|
812
|
-
link = url_for(
|
813
|
-
"cases.case",
|
814
|
-
institute_id=institute_obj["_id"],
|
815
|
-
case_name=case_obj["display_name"],
|
816
|
-
)
|
817
|
-
|
818
|
-
store.create_event(
|
819
|
-
institute=institute_obj,
|
820
|
-
case=case_obj,
|
821
|
-
user=user_obj,
|
822
|
-
link=link,
|
823
|
-
category="case",
|
824
|
-
verb=verb,
|
825
|
-
subject=case_obj["display_name"],
|
826
|
-
)
|
827
|
-
|
828
|
-
|
829
816
|
def update_individuals(store, institute_obj, case_obj, user_obj, ind, age, tissue):
|
830
817
|
"""Handle update of individual data (age and/or Tissue type) for a case"""
|
831
818
|
|
@@ -841,8 +828,13 @@ def update_individuals(store, institute_obj, case_obj, user_obj, ind, age, tissu
|
|
841
828
|
|
842
829
|
case_obj["individuals"] = case_individuals
|
843
830
|
|
844
|
-
|
845
|
-
|
831
|
+
link = url_for(
|
832
|
+
"cases.case",
|
833
|
+
institute_id=institute_obj["_id"],
|
834
|
+
case_name=case_obj["display_name"],
|
835
|
+
)
|
836
|
+
|
837
|
+
store.update_case_individual(case_obj, user_obj, institute_obj, link)
|
846
838
|
|
847
839
|
|
848
840
|
def update_cancer_samples(
|
@@ -866,8 +858,13 @@ def update_cancer_samples(
|
|
866
858
|
|
867
859
|
case_obj["individuals"] = case_samples
|
868
860
|
|
869
|
-
|
870
|
-
|
861
|
+
link = url_for(
|
862
|
+
"cases.case",
|
863
|
+
institute_id=institute_obj["_id"],
|
864
|
+
case_name=case_obj["display_name"],
|
865
|
+
)
|
866
|
+
|
867
|
+
store.update_case_sample(case_obj, user_obj, institute_obj, link)
|
871
868
|
|
872
869
|
|
873
870
|
def _all_hpo_gene_list_genes(
|
@@ -1431,13 +1428,13 @@ def _matching_causatives(
|
|
1431
1428
|
other_causatives_in_default_panels = []
|
1432
1429
|
|
1433
1430
|
for causative in matching_causatives:
|
1434
|
-
hgnc_ids =
|
1431
|
+
hgnc_ids = {gene.get("hgnc_id") for gene in causative.get("genes", [])}
|
1435
1432
|
# Fetch all matching causatives if no causatives_filter defined
|
1436
1433
|
# or only causatives matching the filter:
|
1437
|
-
if not other_causatives_filter or (
|
1434
|
+
if not other_causatives_filter or (hgnc_ids & set(other_causatives_filter)):
|
1438
1435
|
other_causatives.append(causative)
|
1439
1436
|
# Only matching causatives in default gene panels:
|
1440
|
-
if
|
1437
|
+
if hgnc_ids & set(other_causatives_in_default_panels_filter):
|
1441
1438
|
other_causatives_in_default_panels.append(causative)
|
1442
1439
|
|
1443
1440
|
return other_causatives, other_causatives_in_default_panels
|