diff --git a/src/common/db_IO.py b/src/common/db_IO.py index 2aac6a76..fbfe4c10 100644 --- a/src/common/db_IO.py +++ b/src/common/db_IO.py @@ -921,6 +921,12 @@ def get_gene(self, gene_id): # return all info of a gene for the gene page result = self.cursor.fetchone() return result + def get_gene_ids_with_variants(self): + command = "SELECT gene_id AS symbol FROM transcript WHERE name in (SELECT transcript_name FROM variant_consequence) GROUP BY gene_id" + self.cursor.execute(command) + result = self.cursor.fetchall() + return [x[0] for x in result] + def get_transcripts(self, gene_id): command = "SELECT gene_id,name,biotype,length,is_gencode_basic,is_mane_select,is_mane_plus_clinical,is_ensembl_canonical,is_gencode_basic+is_mane_select+is_mane_plus_clinical+is_ensembl_canonical total_flags FROM transcript WHERE gene_id = %s" self.cursor.execute(command, (gene_id, )) diff --git a/src/common/models.py b/src/common/models.py index 00138cff..9453b240 100644 --- a/src/common/models.py +++ b/src/common/models.py @@ -221,34 +221,63 @@ class Criterium: strength: str evidence: str + def display_name(self): + the_name = self.name.lower() + fancy_name = self.name + '_' + self.type + possible_criteria = ['pvs', 'ps', 'pm', 'pp', 'ba', 'bs', 'bp'] + for criterium in possible_criteria: + if criterium in the_name and self.type != criterium: + return fancy_name + return self.name + + + #def strength_to_string(self): + # print(self.strength) + # if self.strength == "very strong pathogenic": + # return "vs" + # if self.strength == "strong pathogenic": + # return "s" + # if self.strength == "medium pathogenic": + # return "m" + # if self.strength == "supporting pathogenic": + # return "p" + # if self.strength == "stand-alone benign": + # return "ba" + # if self.strength == "supporting benign": + # return "p" + # if self.strength == "strong benign": + # return "s" + + def to_vcf(self): info = "~2B".join([self.name, self.strength, self.evidence]) # sep: + return info def criterium_to_num(self): - if 'pvs' in self.name: + the_name = self.name.lower() + if 'pvs' in the_name: return 1 - if 'ps' in self.name: + if 'ps' in the_name: return 2 - if 'pm' in self.name: + if 'pm' in the_name: return 3 - if 'pp' in self.name: + if 'pp' in the_name: return 4 - if 'bp' in self.name: + if 'bp' in the_name: return 5 - if 'bs' in self.name: + if 'bs' in the_name: return 6 - if 'ba' in self.name: + if 'ba' in the_name: return 7 - if '1.' in self.name: + if '1.' in the_name: return 5 - if '2.' in self.name: + if '2.' in the_name: return 4 - if '3.' in self.name: + if '3.' in the_name: return 3 - if '4.' in self.name: + if '4.' in the_name: return 2 - if '5.' in self.name: + if '5.' in the_name: return 1 @dataclass diff --git a/src/frontend_celery/webapp/doc/doc_routes.py b/src/frontend_celery/webapp/doc/doc_routes.py index ad9341c1..bd7e6309 100644 --- a/src/frontend_celery/webapp/doc/doc_routes.py +++ b/src/frontend_celery/webapp/doc/doc_routes.py @@ -5,6 +5,8 @@ import common.functions as functions from common.db_IO import Connection from ..utils import require_permission +from ..utils import * +from ..tasks import send_mail doc_blueprint = Blueprint( 'doc', @@ -39,4 +41,60 @@ def documentation(): @doc_blueprint.route('/changelog') def changelog(): - return render_template('doc/changelog.html') \ No newline at end of file + return render_template('doc/changelog.html') + + +@doc_blueprint.route('/contact', methods=['GET', 'POST']) +def contact(): + conn = get_connection() + + core_gene_transcripts = {} + core_gene_ids = conn.get_gene_ids_with_variants() + for core_gene_id in core_gene_ids: + core_gene = conn.get_gene(core_gene_id) + if core_gene is None: + continue + core_gene_symbol = core_gene[2] + current_transcripts = conn.get_transcripts(core_gene_id) + core_gene_transcripts[core_gene_symbol] = current_transcripts + + do_redirect = False + + if request.method == "POST": + first_name = request.form.get('first_name') + last_name = request.form.get('last_name') + institution = request.form.get('institution') + e_mail = request.form.get('e_mail') + gene = request.form.get('gene') + transcript = request.form.get('transcript') + hgvs_c = request.form.get('c_hgvs') + hgvs_p = request.form.get('p_hgvs') + question = request.form.get('question') + comment = request.form.get('comment') + if any([x is None for x in [first_name, last_name, institution, e_mail, gene, transcript, question]]): + flash("You must provide your first and last name, institution, e-mail, gene, transcript and your question", "alert-danger") + #return render_template('doc/contact.html', core_gene_transcripts = core_gene_transcripts) + elif hgvs_c is None and hgvs_p is None: + flash("You must provide either hgvs_c or hgvs_p", "alert-danger") + #return render_template('doc/contact.html', core_gene_transcripts = core_gene_transcripts) + else: + hgvs_for_subject = ' / '.join([x for x in [hgvs_c, hgvs_p] if x is not None]) + sender = "noreply@heredivar.uni-koeln.de" + text_body = render_template("doc/mail_variant_enquiry.html", + first_name = first_name, + last_name = last_name, + institution = institution, + e_mail = e_mail, + gene = gene, + transcript = transcript, + hgvs_c = hgvs_c, + hgvs_p = hgvs_p, + question = question, + comment = comment) + send_mail(subject = "HerediVar: enquiry for variant " + hgvs_for_subject, sender = sender, recipient = "marvin.doebel@med.uni-tuebingen.de", text_body = text_body) + flash("Success! Thanks for reaching out to us! You will hear from us soon.", "alert-success") + do_redirect = True + + if do_redirect: + return redirect(url_for('doc.contact')) + return render_template('doc/contact.html', core_gene_transcripts = core_gene_transcripts) \ No newline at end of file diff --git a/src/frontend_celery/webapp/static/js/classify.js b/src/frontend_celery/webapp/static/js/classify.js index b3697d71..55702359 100644 --- a/src/frontend_celery/webapp/static/js/classify.js +++ b/src/frontend_celery/webapp/static/js/classify.js @@ -389,7 +389,7 @@ function preselect_criteria_from_database(scheme) { //console.log(selected_criteria) for(var i = 0; i < selected_criteria.length; i++) { var current_data = selected_criteria[i]; - var current_criterium = current_data['name'].toLowerCase(); + var current_criterium = current_data['name'].toUpperCase(); var current_evidence = current_data['evidence']; var current_strength = current_data['type']; @@ -697,9 +697,9 @@ function create_criteria_buttons() { } if (last_criterium_type != criterium_type) { - if (['b', '1', '2'].includes(last_criterium_type[0])) { + if (['B', '1', '2'].includes(last_criterium_type[0])) { benign_criteria_container.appendChild(container) - } else if (['p', '4', '5'].includes(last_criterium_type[0])) { + } else if (['P', '4', '5'].includes(last_criterium_type[0])) { pathogenic_criteria_container.appendChild(container) } else if (container.hasChildNodes()) { uncertain_criteria_container.appendChild(container) @@ -713,9 +713,9 @@ function create_criteria_buttons() { } // add the last column of buttons - if (['b', '1', '2'].includes(last_criterium_type[0])) { + if (['B', '1', '2'].includes(last_criterium_type[0])) { benign_criteria_container.appendChild(container) - } else if (['p', '4', '5'].includes(last_criterium_type[0])) { + } else if (['P', '4', '5'].includes(last_criterium_type[0])) { pathogenic_criteria_container.appendChild(container) } else { uncertain_criteria_container.appendChild(container) @@ -738,7 +738,7 @@ function create_criteria_buttons() { function compare_criteria() { return function(a, b) { if (scheme_type === 'acmg') { - const criterium_order = {'pvs': 1, 'ps': 2, 'pm': 3, 'pp': 4, 'bp': 5, 'bs': 6, 'ba': 7} + const criterium_order = {'PVS': 1, 'PS': 2, 'PM': 3, 'PP': 4, 'BP': 5, 'BS': 6, 'BA': 7} const a_letters = a.slice(0, -1) const a_crit_num = parseInt(a.slice(-1)) const b_letters = b.slice(0, -1) @@ -775,7 +775,7 @@ function compare_criteria() { // sort helper function compare_strength() { return function(a, b) { - const strength_order = {'pvs': 1, 'ps': 2, 'pm': 3, 'pp': 4, 'bp': 5, 'bs': 6, 'ba': 7} + const strength_order = {'PVS': 1, 'PS': 2, 'PM': 3, 'PP': 4, 'BP': 5, 'BS': 6, 'BA': 7} a_num = strength_order[a] b_num = strength_order[b] @@ -1174,6 +1174,17 @@ function update_criterium_button_background(criterium_id) { } } +function update_criterium_button_label(criterium_id) { + var criterium_strength_select = document.getElementById(criterium_id + '_strength'); + var criterium_button_label = document.getElementById(criterium_id + '_label'); + + if (criterium_strength_select.getAttribute('default_strength') != criterium_strength_select.value) { + criterium_button_label.innerText = criterium_id + '_' + criterium_strength_select.value + } else { + criterium_button_label.innerText = criterium_id + } +} + // select and unselect the criterium itself + its associated strength input check which holds information about its user-assigned strenght function toggle_criterium(criterium_id) { var obj = document.getElementById(criterium_id) @@ -1188,6 +1199,7 @@ function set_criterium(criterium_id, is_checked) { var obj = document.getElementById(criterium_id) obj.checked = is_checked update_criterium_button_background(criterium_id) + update_criterium_button_label(criterium_id) document.getElementById(criterium_id + '_strength').checked = obj.checked const current_disable_group = classification_schemas[scheme]['criteria'][criterium_id]['mutually_exclusive_criteria'] enable_disable_buttons(current_disable_group, obj.checked) @@ -1202,6 +1214,7 @@ function update_criterium_strength(obj, criterium_id) { strength_obj.value = obj.value update_classification_preview() update_criterium_button_background(criterium_id) + update_criterium_button_label(criterium_id) } diff --git a/src/frontend_celery/webapp/static/js/contact.js b/src/frontend_celery/webapp/static/js/contact.js new file mode 100644 index 00000000..94f2a7c1 --- /dev/null +++ b/src/frontend_celery/webapp/static/js/contact.js @@ -0,0 +1,60 @@ +const core_gene_transcripts = JSON.parse(flask_data.dataset.coreGeneTranscripts) + + +function create_option(value, text) { + var option = document.createElement('option') + option.classList.add("color_black") + option.value = value + option.innerText = text + return option +} + +function clear_options(select) { + var i, L = select.options.length - 1; + for(i = L; i >= 0; i--) { + select.remove(i); + } +} + +function create_default_option() { + var option = document.createElement('option') + option.classList.add() + option.value = "" + option.selected = "selected" + option.disabled = true + option.hidden = true + option.innerText = "Choose a gene before choosing the transcript" + return option +} + + +function switch_gene() { + const gene_select = document.getElementById('gene') + const selected_gene = gene_select.value + if (selected_gene == "") { + return + } + const transcripts_oi = core_gene_transcripts[selected_gene] + const transcript_select = document.getElementById('transcript') + + + clear_options(transcript_select) + transcript_select.appendChild(create_default_option()) + + for (var i = 0; i < transcripts_oi.length; i++) { + var current_transcript = transcripts_oi[i] + var current_transcript_name = current_transcript[1] + var new_option = create_option(current_transcript_name, current_transcript_name) + transcript_select.appendChild(new_option) + } +} + + + +$(document).ready(function() { + $('#gene').change(function () { + switch_gene(); + }); + + switch_gene() +}); \ No newline at end of file diff --git a/src/frontend_celery/webapp/static/js/search.js b/src/frontend_celery/webapp/static/js/search.js index 37c30e8b..337620bd 100644 --- a/src/frontend_celery/webapp/static/js/search.js +++ b/src/frontend_celery/webapp/static/js/search.js @@ -22,7 +22,9 @@ $(document).ready(function(){ if (do_select_all_variants) { // preselect the select all check from previous request document.getElementById("select_all_variants").checked = true select_all_variants() - } + } else { + document.getElementById("select_all_variants").checked = false + } // preselect the single variant checks const variant_selects = document.getElementsByClassName("variant_select") diff --git a/src/frontend_celery/webapp/templates/doc/contact.html b/src/frontend_celery/webapp/templates/doc/contact.html new file mode 100644 index 00000000..5f28f7e7 --- /dev/null +++ b/src/frontend_celery/webapp/templates/doc/contact.html @@ -0,0 +1,156 @@ +{% extends 'base.html' %} + + +{% block content %} + +
+ + +

{% block title %} Kontaktformular {% endblock %}

+ + + +
+ +
+ Sollten sie eine Anfrage zur Klassifizierung einer Variante in den von uns untersuchten Kerngenen für + erblichen Brust- und/oder Eierstockkrebs haben, nutzen sie bitte das folgende Kontaktformular. Gerne + teilen wir Ihnen die Einschätzung der VUS-Task-Force mit, sofern die Variante im DK-FBREK bereits dokumentiert + und bewertet wurde. Sollte die Variante von uns noch nicht gefunden worden sein, werden wir ihnen dies + ebenfalls mitteilen. Sie können sich dann für die Einschleusung Ihrer Ratsuchenden in die DK-FBREK + Betreuung mit Aufnahme der VUS in unser Bewertungskonzept inkl. der Teilnahme Ihrer Ratsuchenden + an unserem Recall-System an eines der DK-FBREK Zentren wenden. Bitte haben sie Verständnis dafür, + dass wir nur vollständige Anfragen beantworten können. +
+ + +
+
+

Enquiry

+ +
+ + +
If the gene you are looking for is not in this dropdown we do not have information about your variant
+
+ +
+ + +
+ + + +
+ + + +
+ Please provide either c.HGVS or p.HGVS! +
+
Provide at least one of c.HGVS and p.HGVS.
+
+ +
+ + + +
+ Please provide either c.HGVS or p.HGVS! +
+
+ +
+ + + +
+ Please provide the question you try to answer! +
+
+ +
+ + + +
+ +

Contact information

+
+ + + +
+ Please provide your last name! +
+
+ +
+ + + +
+ Please provide your first name! +
+
+ +
+ + + +
+ Please provide your institution! +
+
+ +
+ + + +
+ Please provide your e-mail! +
+
+ + +
+
+ + + +
+ + + + + +
+ +{% endblock %} + +{% block special_scripts %} + +{% endblock%} \ No newline at end of file diff --git a/src/frontend_celery/webapp/templates/doc/mail_variant_enquiry.html b/src/frontend_celery/webapp/templates/doc/mail_variant_enquiry.html new file mode 100644 index 00000000..cc5ea974 --- /dev/null +++ b/src/frontend_celery/webapp/templates/doc/mail_variant_enquiry.html @@ -0,0 +1,17 @@ +

Someone is interested in recieving information about a variant!

+ + +Enquiry: +
Gene: {{gene}}
+
Transcript: {{transcript}}
+
c.HGVS: {{hgvs_c}}
+
p.HGVS: {{hgvs_p}}
+
Question: {{question}}
+ +

Comment: {{comment}}

+ +Contact information: +
First name: {{first_name}}
+
Last name: {{last_name}}
+
Institution: {{institution}}
+
E-mail: {{e_mail}}
\ No newline at end of file diff --git a/src/frontend_celery/webapp/templates/index.html b/src/frontend_celery/webapp/templates/index.html index 20affe3c..fcc54919 100644 --- a/src/frontend_celery/webapp/templates/index.html +++ b/src/frontend_celery/webapp/templates/index.html @@ -52,7 +52,7 @@

{% block title %} Welcome to HerediVar {% endblock %}

die kollaborative Klassifikation von genetischen Varianten unter Automatisierung vieler Annotations- und Arbeitsschritte ermöglicht und so zukünftig die Bearbeitung einer großen Zahl von Varianten und die Einspeisung der konsentierten Variantenbewertung des Konsortiums in die frei zugängliche ClinVar-Datenbank ermöglicht. Weitere Informationen zum HerediVar Projekt und den beteiligten Institutionen finden sie unter der Projektbeschreibung. Für Anfragen nutzen sie bitte das - Kontaktformular. + Kontaktformular. @@ -101,10 +101,13 @@

Changelog

  • Moved previous changelog announcements to a new page
  • The admin dashboard now allows reannotation of a user defined set of databases
  • The admin dashboard now shows an overview of all annotations and annotation errors / warnings
  • +
  • Added a contact form where unregistered people can ask a question about a variant
  • +
  • Added suffix to criteria names if the selected strength is not the default strength
  • Bugfixes: Known issues: