scout-browser 4.88.1__py3-none-any.whl → 4.89__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/mongo/base.py +1 -1
- scout/adapter/mongo/case.py +185 -117
- scout/adapter/mongo/omics_variant.py +19 -0
- scout/build/case.py +1 -0
- scout/commands/load/variants.py +121 -40
- scout/commands/update/case.py +56 -10
- scout/constants/case_tags.py +5 -0
- scout/constants/disease_parsing.py +2 -2
- scout/constants/igv_tracks.py +2 -2
- scout/constants/indexes.py +8 -1
- scout/demo/643594.config.yaml +1 -0
- scout/demo/panel_1.txt +2 -0
- scout/demo/resources/ensembl_exons_37_reduced.txt +135 -0
- scout/demo/resources/ensembl_exons_38_reduced.txt +166 -0
- scout/demo/resources/ensembl_genes_37_reduced.txt +2 -0
- scout/demo/resources/ensembl_genes_38_reduced.txt +2 -0
- scout/demo/resources/ensembl_transcripts_37_reduced.txt +27 -0
- scout/demo/resources/ensembl_transcripts_38_reduced.txt +36 -0
- scout/demo/resources/hgnc_reduced_set.txt +2 -0
- scout/log/handlers.py +2 -1
- scout/log/log.py +48 -61
- scout/models/case/case_loading_models.py +2 -0
- scout/parse/omim.py +2 -2
- scout/server/app.py +23 -7
- scout/server/blueprints/alignviewers/controllers.py +46 -23
- scout/server/blueprints/cases/controllers.py +21 -47
- scout/server/blueprints/cases/templates/cases/case_report.html +4 -1
- scout/server/blueprints/cases/templates/cases/case_sma.html +19 -0
- scout/server/blueprints/cases/templates/cases/collapsible_actionbar.html +7 -7
- scout/server/blueprints/cases/templates/cases/individuals_table.html +1 -1
- scout/server/blueprints/clinvar/form.py +1 -1
- scout/server/blueprints/clinvar/templates/clinvar/clinvar_submissions.html +2 -2
- scout/server/blueprints/clinvar/templates/clinvar/multistep_add_variant.html +9 -3
- scout/server/blueprints/institutes/controllers.py +11 -38
- scout/server/blueprints/institutes/forms.py +18 -4
- scout/server/blueprints/institutes/templates/overview/cases.html +137 -46
- scout/server/blueprints/login/views.py +16 -12
- scout/server/blueprints/panels/controllers.py +4 -1
- scout/server/blueprints/panels/templates/panels/panel.html +1 -1
- scout/server/blueprints/panels/templates/panels/panels.html +5 -5
- scout/server/blueprints/public/templates/public/index.html +18 -10
- scout/server/blueprints/variant/templates/variant/components.html +0 -1
- scout/server/blueprints/variant/templates/variant/gene_disease_relations.html +1 -1
- scout/server/config.py +3 -0
- scout/server/extensions/__init__.py +2 -0
- scout/server/extensions/chanjo2_extension.py +46 -0
- scout/server/extensions/chanjo_extension.py +44 -1
- scout/server/extensions/matchmaker_extension.py +0 -1
- scout/server/links.py +11 -2
- scout/server/templates/report_base.html +1 -0
- scout/utils/convert.py +1 -1
- scout/utils/date.py +1 -1
- {scout_browser-4.88.1.dist-info → scout_browser-4.89.dist-info}/METADATA +1 -1
- {scout_browser-4.88.1.dist-info → scout_browser-4.89.dist-info}/RECORD +59 -58
- {scout_browser-4.88.1.dist-info → scout_browser-4.89.dist-info}/LICENSE +0 -0
- {scout_browser-4.88.1.dist-info → scout_browser-4.89.dist-info}/WHEEL +0 -0
- {scout_browser-4.88.1.dist-info → scout_browser-4.89.dist-info}/entry_points.txt +0 -0
- {scout_browser-4.88.1.dist-info → scout_browser-4.89.dist-info}/top_level.txt +0 -0
@@ -47,16 +47,20 @@ def load_user(user_id):
|
|
47
47
|
@public_endpoint
|
48
48
|
def login():
|
49
49
|
"""Login a user if they have access."""
|
50
|
-
|
51
|
-
|
50
|
+
|
51
|
+
if current_app.config.get("USERS_ACTIVITY_LOG_PATH"):
|
52
|
+
if request.form.get("consent_checkbox") is None and "consent_given" not in session:
|
53
|
+
flash(
|
54
|
+
"Logging user activity is a requirement for using this site and accessing your account. Without consent to activity logging, you will not be able to log in into Scout.",
|
55
|
+
"warning",
|
56
|
+
)
|
57
|
+
return redirect(url_for("public.index"))
|
58
|
+
session["consent_given"] = True
|
52
59
|
|
53
60
|
user_id = None
|
54
61
|
user_mail = None
|
55
62
|
|
56
|
-
if (
|
57
|
-
current_app.config.get("LDAP_HOST", current_app.config.get("LDAP_SERVER"))
|
58
|
-
and request.method == "POST"
|
59
|
-
):
|
63
|
+
if current_app.config.get("LDAP_HOST", current_app.config.get("LDAP_SERVER")):
|
60
64
|
ldap_authorized = controllers.ldap_authorized(
|
61
65
|
request.form.get("ldap_user"), request.form.get("ldap_password")
|
62
66
|
)
|
@@ -66,20 +70,19 @@ def login():
|
|
66
70
|
flash("User not authorized by LDAP server", "warning")
|
67
71
|
return redirect(url_for("public.index"))
|
68
72
|
|
69
|
-
|
73
|
+
elif current_app.config.get("GOOGLE"):
|
70
74
|
if session.get("email"):
|
71
75
|
user_mail = session["email"]
|
72
76
|
session.pop("email", None)
|
73
77
|
else:
|
74
|
-
LOG.info("Google Login!")
|
75
78
|
redirect_uri = url_for(".authorized", _external=True)
|
76
79
|
try:
|
77
80
|
return oauth_client.google.authorize_redirect(redirect_uri)
|
78
81
|
except Exception as ex:
|
79
82
|
flash("An error has occurred while logging in user using Google OAuth")
|
80
83
|
|
81
|
-
|
82
|
-
user_mail = request.
|
84
|
+
elif request.form.get("email"): # log in against Scout database
|
85
|
+
user_mail = request.form["email"]
|
83
86
|
LOG.info("Validating user %s email %s against Scout database", user_id, user_mail)
|
84
87
|
|
85
88
|
user_obj = store.user(email=user_mail, user_id=user_id)
|
@@ -101,6 +104,7 @@ def login():
|
|
101
104
|
@public_endpoint
|
102
105
|
def authorized():
|
103
106
|
"""Google auth callback function"""
|
107
|
+
|
104
108
|
token = oauth_client.google.authorize_access_token()
|
105
109
|
google_user = oauth_client.google.parse_id_token(token, None)
|
106
110
|
session["email"] = google_user.get("email").lower()
|
@@ -116,6 +120,7 @@ def logout():
|
|
116
120
|
session.pop("email", None)
|
117
121
|
session.pop("name", None)
|
118
122
|
session.pop("locale", None)
|
123
|
+
session.pop("consent_given", None)
|
119
124
|
flash("you logged out", "success")
|
120
125
|
return redirect(url_for("public.index"))
|
121
126
|
|
@@ -130,7 +135,6 @@ def users():
|
|
130
135
|
def perform_login(user_dict):
|
131
136
|
if login_user(user_dict, remember=True):
|
132
137
|
flash("you logged in as: {}".format(user_dict.name), "success")
|
133
|
-
|
134
|
-
return redirect(request.args.get("next") or next_url or url_for("cases.index"))
|
138
|
+
return redirect(url_for("cases.index"))
|
135
139
|
flash("sorry, you could not log in", "warning")
|
136
140
|
return redirect(url_for("public.index"))
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
import datetime as dt
|
3
3
|
import logging
|
4
|
+
import re
|
4
5
|
|
5
6
|
from flask import flash, redirect
|
6
7
|
from flask_login import current_user
|
@@ -309,9 +310,11 @@ def downloaded_panel_name(panel_obj, format) -> str:
|
|
309
310
|
Returns:
|
310
311
|
a string describing the panel
|
311
312
|
"""
|
313
|
+
sanitized_panel_id = re.sub(r"[^a-zA-Z_\-]+", "", panel_obj["panel_name"])
|
314
|
+
|
312
315
|
return "_".join(
|
313
316
|
[
|
314
|
-
|
317
|
+
sanitized_panel_id,
|
315
318
|
str(panel_obj["version"]),
|
316
319
|
dt.datetime.now().strftime(DATE_DAY_FORMATTER),
|
317
320
|
f"scout.{format}",
|
@@ -76,7 +76,7 @@
|
|
76
76
|
</li>
|
77
77
|
<li class="list-group-item">
|
78
78
|
<label for="date">Date</label>
|
79
|
-
<span class="float-end" id="date">{{ panel.date.date() }
|
79
|
+
<span class="float-end" id="date">{{panel._id.generation_time.strftime('%Y-%m-%d')}} {% if panel.hidden %} deleted:{{ panel.date.date()}} {% endif %}</span>
|
80
80
|
</li>
|
81
81
|
<li class="list-group-item">
|
82
82
|
<label for="mainainer">Maintainers</label>
|
@@ -109,7 +109,7 @@
|
|
109
109
|
</div>
|
110
110
|
<div class="col-sm-3 text-center">
|
111
111
|
<input type="text" name="new_panel_name" class="form-control" placeholder="Panel ID" required
|
112
|
-
pattern="
|
112
|
+
pattern="[A-Za-z0-9_\-]+" title="Only alphanumeric characters (A-Z+a-z+0-9), hyphens, and underscores allowed.">
|
113
113
|
</div>
|
114
114
|
<div class="col-sm-4 text-center">
|
115
115
|
<input type="text" name="display_name" class="form-control" placeholder="Full name">
|
@@ -150,8 +150,8 @@
|
|
150
150
|
<table class="table table-striped" id="panelTable" style="table-layout: fixed;">
|
151
151
|
<thead>
|
152
152
|
<tr>
|
153
|
-
<th style="width:
|
154
|
-
<th>Version</th>
|
153
|
+
<th style="width: 20%">Name</th>
|
154
|
+
<th style="width: 20%">Version</th>
|
155
155
|
<th>Number of genes</th>
|
156
156
|
<th>History</th>
|
157
157
|
<th></th>
|
@@ -170,10 +170,10 @@
|
|
170
170
|
<span class="badge bg-danger" data-bs-toggle="tooltip" title="This panel was removed">Removed</span>
|
171
171
|
{% endif %}
|
172
172
|
</td>
|
173
|
-
<td>{{ panel.version }} ({{ panel.date.date()}})</td>
|
173
|
+
<td>{{ panel.version }} ({{panel._id.generation_time.strftime('%Y-%m-%d')}} {% if panel.hidden %} deleted:{{ panel.date.date()}} {% endif %})</td>
|
174
174
|
<td><span class="badge rounded-pill bg-secondary">{{ panel.genes|length}}</span></td>
|
175
175
|
<td><button id="{{panel._id}}" type="button" data-bs-toggle="collapse" href="#paneldiv_{{panel._id}}" aria-expanded="false" aria-controls="paneldiv_{{panel._id}}" class="btn btn-primary btn-xs"><span class="fa fa-search-plus"></span></button><br>{{ history_view(panel._id, panel.panel_name) }}</td>
|
176
|
-
<td><button id="{{panel._id}}" type="button" data-bs-toggle="collapse" href="#modifydiv_{{panel._id}}" aria-expanded="false" aria-controls="modifydiv_{{panel._id}}" class="btn btn-warning btn-xs"><span class="fa fa-pen-square"></span></button
|
176
|
+
<td><button id="{{panel._id}}" type="button" data-bs-toggle="collapse" href="#modifydiv_{{panel._id}}" aria-expanded="false" aria-controls="modifydiv_{{panel._id}}" class="btn btn-warning btn-xs"><span class="fa fa-pen-square"></span></button></td>
|
177
177
|
<td>
|
178
178
|
{% if panel.hidden %}
|
179
179
|
<form action="{{ url_for('panels.panel_restore', panel_id=panel._id) }}" method="POST">
|
@@ -20,12 +20,12 @@
|
|
20
20
|
</a>
|
21
21
|
</p>
|
22
22
|
{% else %}
|
23
|
-
{
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
<form class="row" method="POST" action="{{ url_for('login.login') }}">
|
24
|
+
{% if config.GOOGLE %}
|
25
|
+
<button name="googleLogin" class="btn btn-primary btn-lg text-white" href="{{ url_for('login.login') }}" type="submit">
|
26
|
+
Login with Google
|
27
|
+
</button>
|
28
|
+
{% elif config.LDAP_HOST or config.LDAP_SERVER %}
|
29
29
|
<div class="col-5">
|
30
30
|
<input type="text" name="ldap_user" class="form-control" placeholder="user email/id" required>
|
31
31
|
</div>
|
@@ -35,9 +35,7 @@
|
|
35
35
|
<div class="col-2">
|
36
36
|
<button type="submit" class="btn btn-primary form-control text-white">Login</button>
|
37
37
|
</div>
|
38
|
-
</form>
|
39
38
|
{% else %}
|
40
|
-
<form action="{{ url_for('login.login') }}">
|
41
39
|
<div class="row">
|
42
40
|
<div class="col-8">
|
43
41
|
<input type="text" placeholder="email" class="form-control" name="email">
|
@@ -46,8 +44,18 @@
|
|
46
44
|
<button type="submit" class="btn btn-primary form-control text-white">Login</button>
|
47
45
|
</div>
|
48
46
|
</div>
|
49
|
-
|
50
|
-
|
47
|
+
{% endif %}
|
48
|
+
<!-- Consent Banner -->
|
49
|
+
{% if config.USERS_ACTIVITY_LOG_PATH %}
|
50
|
+
<div class="row mt-3 ms-0 alert-warning" style="text-align: center; padding: 20px;">
|
51
|
+
<p>To ensure security and improve functionality, we log user activity, including interactions and navigation. This helps us enhance performance and maintain platform safety.
|
52
|
+
By checking the box, you agree that your activity will be logged, which is required to use this portal and log in.</p>
|
53
|
+
<label>
|
54
|
+
<input type="checkbox" name="consent_checkbox"> I agree to my activity being logged
|
55
|
+
</label>
|
56
|
+
</div>
|
57
|
+
{% endif %}
|
58
|
+
</form>
|
51
59
|
{% endif %}
|
52
60
|
</div>
|
53
61
|
<div class="container bg-light rounded-3 py-4">
|
@@ -273,7 +273,6 @@
|
|
273
273
|
{% if gene.decipher_link %}
|
274
274
|
<a href="{{ gene.decipher_link }}" class="btn btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank">Decipher</a>
|
275
275
|
{% endif %}
|
276
|
-
<a href="http://tools.genes.toronto.edu/" class="btn btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank">SPANR</a>
|
277
276
|
<a href="{{ gene.reactome_link }}" class="btn btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank">Reactome</a>
|
278
277
|
<a href="{{ gene.expression_atlas_link }}" class="btn btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank">Expr. Atlas</a>
|
279
278
|
<a href="{{ gene.clingen_link }}" class="btn btn-secondary text-white" rel="noopener" referrerpolicy="no-referrer" target="_blank">ClinGen</a>
|
@@ -50,7 +50,7 @@
|
|
50
50
|
{% if gene.common and gene.disease_terms %}
|
51
51
|
{% for disease_term in gene.disease_terms %}
|
52
52
|
{% if disease_term.source == 'ORPHA' %}
|
53
|
-
<tr data-bs-toggle="tooltip" title="Some ORPHA disorders are phenotypic umbrella terms for multiple genetic entities. The inheritance models are in this case a set derived from all those entities, not necessarily
|
53
|
+
<tr data-bs-toggle="tooltip" title="Some ORPHA disorders are phenotypic umbrella terms for multiple genetic entities. The inheritance models are in this case a set derived from all those entities, not necessarily modes of inheritance known for this gene. ORPHA inheritance modes will not be shown on the general case report.">
|
54
54
|
<td>
|
55
55
|
<a href="http://omim.org/entry/{{ gene.common.omim_id }}" rel="noopener" target="_blank">
|
56
56
|
{{ gene.common.hgnc_symbol }}
|
scout/server/config.py
CHANGED
@@ -151,3 +151,6 @@ SV_RANK_MODEL_LINK_POSTFIX = "-.ini"
|
|
151
151
|
# BIONANO_ACCESS = "https://bionano-access.scilifelab.se"
|
152
152
|
# BIONANO_USERNAME = "USERNAME"
|
153
153
|
# BIONANO_PASSWORD = "PASSWORD"
|
154
|
+
|
155
|
+
# Uncomment and customise to log users' activity to file
|
156
|
+
# USERS_ACTIVITY_LOG_PATH = "users_activity.log"
|
@@ -10,6 +10,7 @@ from scout.utils.track_resources import AlignTrackHandler
|
|
10
10
|
|
11
11
|
from .beacon_extension import Beacon
|
12
12
|
from .bionano_extension import BioNanoAccessAPI
|
13
|
+
from .chanjo2_extension import Chanjo2Client
|
13
14
|
from .chanjo_extension import ChanjoReport
|
14
15
|
from .clinvar_extension import ClinVarApi
|
15
16
|
from .gens_extension import GensViewer
|
@@ -37,3 +38,4 @@ beacon = Beacon()
|
|
37
38
|
config_igv_tracks = AlignTrackHandler()
|
38
39
|
bionano_access = BioNanoAccessAPI()
|
39
40
|
chanjo_report = ChanjoReport()
|
41
|
+
chanjo2 = Chanjo2Client()
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import logging
|
2
|
+
from typing import Dict
|
3
|
+
|
4
|
+
import requests
|
5
|
+
from flask import current_app
|
6
|
+
|
7
|
+
REF_CHROM = "14"
|
8
|
+
MT_CHROM = "MT"
|
9
|
+
LOG = logging.getLogger(__name__)
|
10
|
+
|
11
|
+
|
12
|
+
class Chanjo2Client:
|
13
|
+
"""Runs requests to chanjo2 and returns results in the expected format."""
|
14
|
+
|
15
|
+
def mt_coverage_stats(self, individuals: dict) -> Dict[str, dict]:
|
16
|
+
"""Sends a POST requests to the chanjo2 coverage/d4/interval to collect stats for the MT case report."""
|
17
|
+
|
18
|
+
chanjo2_chrom_cov_url: str = "/".join(
|
19
|
+
[current_app.config.get("CHANJO2_URL"), "coverage/d4/interval/"]
|
20
|
+
)
|
21
|
+
coverage_stats = {}
|
22
|
+
for ind in individuals:
|
23
|
+
|
24
|
+
if not ind.get("d4_file"):
|
25
|
+
continue
|
26
|
+
chrom_cov_query = {"coverage_file_path": ind["d4_file"]}
|
27
|
+
|
28
|
+
# Get mean coverage over chr14
|
29
|
+
chrom_cov_query["chromosome"] = REF_CHROM
|
30
|
+
resp = requests.post(chanjo2_chrom_cov_url, json=chrom_cov_query)
|
31
|
+
autosome_cov = resp.json().get("mean_coverage")
|
32
|
+
|
33
|
+
# Get mean coverage over chrMT
|
34
|
+
chrom_cov_query["chromosome"] = MT_CHROM
|
35
|
+
resp = requests.post(chanjo2_chrom_cov_url, json=chrom_cov_query)
|
36
|
+
|
37
|
+
mt_cov = resp.json().get("mean_coverage")
|
38
|
+
|
39
|
+
coverage_info = dict(
|
40
|
+
mt_coverage=mt_cov,
|
41
|
+
autosome_cov=autosome_cov,
|
42
|
+
mt_copy_number=round((mt_cov / autosome_cov) * 2, 2),
|
43
|
+
)
|
44
|
+
coverage_stats[ind["individual_id"]] = coverage_info
|
45
|
+
|
46
|
+
return coverage_stats
|
@@ -2,13 +2,16 @@
|
|
2
2
|
Generate coverage reports using chanjo and chanjo-report. Documentation under -> `docs/admin-guide/chanjo_coverage_integration.md`
|
3
3
|
"""
|
4
4
|
|
5
|
+
import json
|
5
6
|
import logging
|
6
7
|
|
7
|
-
|
8
|
+
import requests
|
9
|
+
from flask import current_app, request, url_for
|
8
10
|
from flask_babel import Babel
|
9
11
|
from markupsafe import Markup
|
10
12
|
|
11
13
|
LOG = logging.getLogger(__name__)
|
14
|
+
REF_CHROM_MT_STATS = "14"
|
12
15
|
|
13
16
|
|
14
17
|
class ChanjoReport:
|
@@ -57,3 +60,43 @@ class ChanjoReport:
|
|
57
60
|
app.register_blueprint(report_bp, url_prefix="/reports")
|
58
61
|
app.config["chanjo_report"] = True
|
59
62
|
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True if app.debug else False
|
63
|
+
|
64
|
+
def mt_coverage_stats(self, individuals: dict) -> dict:
|
65
|
+
"""Send a request to chanjo endpoint to retrieve MT vs autosome coverage stats
|
66
|
+
|
67
|
+
Args:
|
68
|
+
individuals(dict): case_obj["individuals"] object
|
69
|
+
|
70
|
+
Returns:
|
71
|
+
coverage_stats(dict): a dictionary with mean MT and autosome transcript coverage stats
|
72
|
+
"""
|
73
|
+
coverage_stats = {}
|
74
|
+
ind_ids = []
|
75
|
+
for ind in individuals:
|
76
|
+
ind_ids.append(ind["individual_id"])
|
77
|
+
|
78
|
+
# Prepare complete url to Chanjo report chromosome mean coverage calculation endpoint
|
79
|
+
cov_calc_url = url_for("report.json_chrom_coverage", _external=True)
|
80
|
+
# Prepare request data to calculate mean MT coverage
|
81
|
+
data = dict(sample_ids=",".join(ind_ids), chrom="MT")
|
82
|
+
# Send POST request with data to chanjo endpoint
|
83
|
+
resp = requests.post(cov_calc_url, json=data)
|
84
|
+
mt_cov_data = json.loads(resp.text)
|
85
|
+
|
86
|
+
# Change request data to calculate mean autosomal coverage
|
87
|
+
data["chrom"] = REF_CHROM_MT_STATS
|
88
|
+
# Send POST request with data to chanjo endpoint
|
89
|
+
resp = requests.post(cov_calc_url, json=data)
|
90
|
+
ref_cov_data = json.loads(resp.text) # mean coverage over the transcripts of ref chrom
|
91
|
+
|
92
|
+
for ind in ind_ids:
|
93
|
+
if not (mt_cov_data.get(ind) and ref_cov_data.get(ind)):
|
94
|
+
continue
|
95
|
+
coverage_info = dict(
|
96
|
+
mt_coverage=round(mt_cov_data[ind], 2),
|
97
|
+
autosome_cov=round(ref_cov_data[ind], 2),
|
98
|
+
mt_copy_number=round((mt_cov_data[ind] / ref_cov_data[ind]) * 2, 2),
|
99
|
+
)
|
100
|
+
coverage_stats[ind] = coverage_info
|
101
|
+
|
102
|
+
return coverage_stats
|
scout/server/links.py
CHANGED
@@ -819,6 +819,15 @@ def alamut_gene_link(
|
|
819
819
|
url_template(str): link to Alamut browser
|
820
820
|
"""
|
821
821
|
|
822
|
+
def get_gene_canonical_tx(gene: dict) -> str:
|
823
|
+
"""Returns the canonical transcript of a gene."""
|
824
|
+
if gene.get("canonical_transcript"):
|
825
|
+
return gene["canonical_transcript"]
|
826
|
+
|
827
|
+
for tx in gene.get("transcripts"):
|
828
|
+
if tx.get("is_canonical"):
|
829
|
+
return tx["transcript_id"]
|
830
|
+
|
822
831
|
if current_app.config.get("HIDE_ALAMUT_LINK"):
|
823
832
|
return False
|
824
833
|
|
@@ -828,7 +837,7 @@ def alamut_gene_link(
|
|
828
837
|
(search_verb, alamut_key_arg, alamut_inst_arg) = _get_alamut_config(institute_obj)
|
829
838
|
|
830
839
|
url_template = (
|
831
|
-
"http://localhost:10000/{search_verb}?{alamut_key_arg}{alamut_inst_arg}request={
|
840
|
+
"http://localhost:10000/{search_verb}?{alamut_key_arg}{alamut_inst_arg}request={canonical_transcript}{build_str}:"
|
832
841
|
"{hgvs_identifier}"
|
833
842
|
)
|
834
843
|
|
@@ -845,7 +854,7 @@ def alamut_gene_link(
|
|
845
854
|
search_verb=search_verb,
|
846
855
|
alamut_key_arg=alamut_key_arg,
|
847
856
|
alamut_inst_arg=alamut_inst_arg,
|
848
|
-
|
857
|
+
canonical_transcript=get_gene_canonical_tx(gene=gene_obj),
|
849
858
|
build_str=build_str,
|
850
859
|
hgvs_identifier=quote(hgvs_raw),
|
851
860
|
)
|
@@ -6,6 +6,7 @@
|
|
6
6
|
{% block css %}
|
7
7
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
8
8
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
9
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='bs_styles.css') }}">
|
9
10
|
<style>
|
10
11
|
tr.light-grey td{
|
11
12
|
background-color: LightGray;
|
scout/utils/convert.py
CHANGED
@@ -53,7 +53,7 @@ def amino_acid_residue_change_3_to_1(protein_sequence_name):
|
|
53
53
|
if protein_sequence_name is None:
|
54
54
|
return None
|
55
55
|
|
56
|
-
p = re.compile("p
|
56
|
+
p = re.compile(r"p\.([A-Za-z]+)(\d+)([A-Za-z]+)")
|
57
57
|
m = p.match(protein_sequence_name)
|
58
58
|
if m is None:
|
59
59
|
return None
|
scout/utils/date.py
CHANGED
@@ -11,7 +11,7 @@ def match_date(date):
|
|
11
11
|
Returns:
|
12
12
|
bool
|
13
13
|
"""
|
14
|
-
date_pattern = re.compile("^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])")
|
14
|
+
date_pattern = re.compile(r"^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])")
|
15
15
|
if re.match(date_pattern, date):
|
16
16
|
return True
|
17
17
|
|