From 475c3ee4f717b8c0c1717dd7beee031cf13930a0 Mon Sep 17 00:00:00 2001 From: loeswerkman Date: Wed, 6 Oct 2021 08:02:06 +0200 Subject: [PATCH 01/95] Add 'relative to' message to both DNA fields --- src/class/object_genome_variants.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/class/object_genome_variants.php b/src/class/object_genome_variants.php index e2f4377a..c0517e18 100644 --- a/src/class/object_genome_variants.php +++ b/src/class/object_genome_variants.php @@ -352,8 +352,11 @@ function getForm () } // Add genome build name to VOG/DNA field. - $this->aColumns['VariantOnGenome/DNA']['description_form'] = 'Relative to ' . $_CONF['refseq_build'] . ' / ' . $_SETT['human_builds'][$_CONF['refseq_build']]['ncbi_name'] . '.' . - (!$this->aColumns['VariantOnGenome/DNA']['description_form']? '' : '
' . $this->aColumns['VariantOnGenome/DNA']['description_form']); + $aActiveBuilds = $_DB->query('SELECT id, name, column_suffix FROM ' . TABLE_GENOME_BUILDS)->fetchAllGroupAssoc(); + foreach($aActiveBuilds as $sBuild => $aBuild) { + $sSuffixWithSlash = (!$aBuild['column_suffix']? '' : '/' . $aBuild['column_suffix']); + $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['description_form'] = 'Relative to ' . $aBuild['name'] . '.'; + } // FIXME; right now two blocks in this array are put in, and optionally removed later. However, the if() above can build an entire block, such that one of the two big unset()s can be removed. // A similar if() to create the "authorization" block, or possibly an if() in the building of this form array, is easier to understand and more efficient. From 998fd1b8c47206bbdb72b744bd72f1bc70ca6af1 Mon Sep 17 00:00:00 2001 From: loeswerkman Date: Thu, 7 Oct 2021 10:49:42 +0200 Subject: [PATCH 02/95] Allow element data to be added into HTML via viewForm --- src/class/object_custom.php | 5 +++++ src/inc-lib-form.php | 16 +++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/class/object_custom.php b/src/class/object_custom.php index 3b703530..5dc4b26a 100644 --- a/src/class/object_custom.php +++ b/src/class/object_custom.php @@ -295,6 +295,11 @@ function buildForm ($sPrefix = '') $aFormData[$sPrefix . $sCol] = $aEntry; } + // The element data will be passed on, so that viewForm can make sure it will be added to the HTML. + if (!empty($aCol['element_data'])) { + $aFormData[$sPrefix . $sCol][] = $aCol['element_data']; + } + // Any custom links we want to mention? if (!empty($aCol['custom_links'])) { $sLinks = ''; diff --git a/src/inc-lib-form.php b/src/inc-lib-form.php index 6bbd194d..808ddcb6 100644 --- a/src/inc-lib-form.php +++ b/src/inc-lib-form.php @@ -885,7 +885,7 @@ function lovd_viewForm ($a, * 'end_fieldset', * array('
', '', 'print', ''), * array('
', '', 'note', ''), - * array('
', '', 'text|password|file', '', ), + * array('
', '', 'text|password|file', '', , ''), * array('
', '', 'textarea', '', , ), * array('
', '', 'select', '', , (array, key => val|query, [0] => [1]), ' . $sDataSuffix); + // When element data is given, it will be added into the HTML code in a 'data-...' format, + // so that HTML recognises it. This way, JavaScript can see and use this data. + array_walk($aElementData, function (&$sVal, $sKey) { + $sVal = 'data-' . str_replace('_', '-', $sKey) . '="' . htmlspecialchars($sVal) . '"'; + }); + + print('' . $sDataSuffix); continue; From eb3b9ea38b17bd2f34272af71628a627104c71c9 Mon Sep 17 00:00:00 2001 From: loeswerkman Date: Thu, 7 Oct 2021 10:57:53 +0200 Subject: [PATCH 03/95] Add genome build as element data into viewForm --- src/class/object_genome_variants.php | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/class/object_genome_variants.php b/src/class/object_genome_variants.php index c0517e18..06039cb9 100644 --- a/src/class/object_genome_variants.php +++ b/src/class/object_genome_variants.php @@ -222,15 +222,15 @@ function __construct () - function buildForm ($sPrefix = '') - { - $aForm = parent::buildForm($sPrefix); - // Link to HGVS for nomenclature. - if (isset($aForm[$sPrefix . 'VariantOnGenome/DNA'])) { - $aForm[$sPrefix . 'VariantOnGenome/DNA'][0] = str_replace('(HGVS format)', '(HGVS format)', $aForm[$sPrefix . 'VariantOnGenome/DNA'][0]); - } - return $aForm; - } +// function buildForm ($sPrefix = '') +// { +// $aForm = parent::buildForm($sPrefix); +// // Link to HGVS for nomenclature. +// if (isset($aForm[$sPrefix . 'VariantOnGenome/DNA'])) { +// $aForm[$sPrefix . 'VariantOnGenome/DNA'][0] = str_replace('(HGVS format)', '(HGVS format)', $aForm[$sPrefix . 'VariantOnGenome/DNA'][0]); +// } +// return $aForm; +// } @@ -351,11 +351,13 @@ function getForm () } } - // Add genome build name to VOG/DNA field. + // Add genome build name and element data to VOG/DNA field, and add in the link to the HGVS website. $aActiveBuilds = $_DB->query('SELECT id, name, column_suffix FROM ' . TABLE_GENOME_BUILDS)->fetchAllGroupAssoc(); - foreach($aActiveBuilds as $sBuild => $aBuild) { + foreach ($aActiveBuilds as $sBuild => $aBuild) { $sSuffixWithSlash = (!$aBuild['column_suffix']? '' : '/' . $aBuild['column_suffix']); $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['description_form'] = 'Relative to ' . $aBuild['name'] . '.'; + $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['element_data'] = array('genome_build' => $sBuild); + $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['form_type'][0] = str_replace('(HGVS format)', '(HGVS format)', $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['form_type'][0]); } // FIXME; right now two blocks in this array are put in, and optionally removed later. However, the if() above can build an entire block, such that one of the two big unset()s can be removed. From 1d121fd739bdb87c875eb1862196d8ef7c4ffb9f Mon Sep 17 00:00:00 2001 From: loeswerkman Date: Thu, 7 Oct 2021 13:36:55 +0200 Subject: [PATCH 04/95] Redo code to add source to variants using element data --- src/inc-js-variants.php | 10 ++++++---- src/variants.php | 16 +++------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index 42625925..061dd424 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -33,7 +33,7 @@ *************/ header('Content-type: text/javascript; charset=UTF-8'); -header('Expires: ' . date('r', time()+(180*60))); +// header('Expires: ' . date('r', time()+(180*60))); TODO: Weer aanzetten voor je commit! define('AJAX_FALSE', '0'); define('AJAX_TRUE', '1'); @@ -45,6 +45,7 @@ $_SETT = array('objectid_length' => array('transcripts' => 8)); ?> + function lovd_checkHGVS (e) { // Function that is being called everytime a change has been made to a DNA field, @@ -186,8 +187,9 @@ function lovd_convertPosition (oElement) if (oThisDNA.attr("name").indexOf("VariantOnTranscript") >= 0) { sSource = "VOT"; } else { - pos = oThisDNA.attr("name").lastIndexOf("/"); - sSource = oThisDNA.attr("name").substr(pos + 1); + sSource = oThisDNA.data('genomeBuild'); + // pos = oThisDNA.attr("name").lastIndexOf("/"); + // sSource = oThisDNA.attr("name").substr(pos + 1); } oVariantSource.val(sSource); } @@ -555,4 +557,4 @@ function lovd_highlightInput (oElement) oTranscriptVariants.change(); } } -}); +}); \ No newline at end of file diff --git a/src/variants.php b/src/variants.php index 1dc76ad8..38921546 100644 --- a/src/variants.php +++ b/src/variants.php @@ -833,18 +833,8 @@ function(sData) { // If the source is a transcript, we describe it with an empty string. $_POST['source'] = ''; - } else { - // If the source of the variant is not a transcript, it is a genome build. - // We will then send the ID of this genome build to the database. - // We have received the last piece of the field used, which may - // be a genome build (from VOG/DNA/hg38) or "DNA" (from VOG/DNA). - $sColumnSuffix = ($_POST['source'] == 'DNA'? '' : $_POST['source']); - - // Get the ID by its column suffix and give this as the source. - $sID = $_DB->query( - 'SELECT id FROM ' . TABLE_GENOME_BUILDS . ' - WHERE column_suffix = ?', array($sColumnSuffix))->fetchColumn(); - $_POST['source'] = $sID; + } elseif (!$_DB->query('SELECT COUNT(*) FROM ' . TABLE_GENOME_BUILDS . ' WHERE ID = ?', array($_POST['source']))->fetchColumn()) { + unset($aFieldsGenome[array_search('source', $aFieldsGenome)]); } $_POST['owned_by'] = ($_AUTH['level'] >= LEVEL_CURATOR? $_POST['owned_by'] : $_AUTH['id']); @@ -957,7 +947,7 @@ function(sData) { // Table. print('
' . "\n" . - ' ' . "\n"); + ' ' . "\n"); // Array which will make up the form table. $aForm = array_merge( From 2fc7097a4bc93041d1b7c54633e90c9c212da9c4 Mon Sep 17 00:00:00 2001 From: loeswerkman Date: Thu, 7 Oct 2021 15:56:54 +0200 Subject: [PATCH 05/95] Add map button to all DNA fields in variant data entry form --- src/inc-js-variants.php | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index 061dd424..a10baa3e 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -33,7 +33,7 @@ *************/ header('Content-type: text/javascript; charset=UTF-8'); -// header('Expires: ' . date('r', time()+(180*60))); TODO: Weer aanzetten voor je commit! +header('Expires: ' . date('r', time()+(180*60))); define('AJAX_FALSE', '0'); define('AJAX_TRUE', '1'); @@ -42,7 +42,8 @@ define('AJAX_NO_AUTH', '8'); define('AJAX_DATA_ERROR', '9'); -$_SETT = array('objectid_length' => array('transcripts' => 8)); +$_SETT = array('objectid_length' => array('transcripts' => 8), + 'variant_validator' => array('genome_builds' => array('hg19', 'hg38'))); ?> @@ -81,7 +82,7 @@ function lovd_checkHGVS (e) if (e.type == 'change' && !bHGVS && oVariantDNA.val()) { // This is a "real" onChange call(), we couldn't match the variant, but we do have something filled in. Check with Mutalyzer! - if (oVariantDNA.attr('name') == 'VariantOnGenome/DNA') { + if (oVariantDNA.attr('name').substring(0, 'VariantOnGenome/DNA'.length) == 'VariantOnGenome/DNA') { var sVariantNotation = 'g:' + oVariantDNA.val(); // The actual chromosome is not important, it's just the variant syntax that matters here. } else { var sVariantNotation = 'c:' + oVariantDNA.val(); // The actual transcript is not important, it's just the variant syntax that matters here. @@ -193,6 +194,7 @@ function lovd_convertPosition (oElement) } oVariantSource.val(sSource); } + var oAllDNA = $('input[name$="_VariantOnTranscript/DNA"]'); $(oAllDNA).removeClass().siblings('img:first').attr({ src: 'gfx/trans.png', @@ -217,7 +219,7 @@ className: '', onmouseout: '' }).show(); - if (oThisDNA.attr('name') == 'VariantOnGenome/DNA') { + if (oThisDNA.attr('name').substring(0, 'VariantOnGenome/DNA'.length) == 'VariantOnGenome/DNA') { // This function was called from the genomic variant, so build a list of genes and prepare the variant accordingly for mutalyzer. var sVariantNotation = 'chr:' + oThisDNA.val(); var aGenes = []; @@ -241,7 +243,7 @@ className: '', $.get('ajax/convert_position.php', { variant: sVariantNotation, gene: sGene }, function(sData) { if (sData != '' && sData != '' && sData != '') { - if (oThisDNA.attr('name') == 'VariantOnGenome/DNA') { + if (oThisDNA.attr('name').substring(0, 'VariantOnGenome/DNA'.length) == 'VariantOnGenome/DNA') { // This function was called from the genomic variant, so fill in the return values from mutalyzer in the transcript DNA fields. aVariants = sData.split(';'); var nVariants = aVariants.length; @@ -517,21 +519,29 @@ function lovd_highlightInput (oElement) $(function () { - var oGenomicVariant = $('#variantForm input[name="VariantOnGenome/DNA"]'); + var oGenomicVariants = $('#variantForm input[name^="VariantOnGenome/DNA"]'); var oTranscriptVariants = $('#variantForm input[name$="_VariantOnTranscript/DNA"]'); - // Add the button and image at the end of the genomic DNA field. - oGenomicVariant.parent().append('   '); // Add an onChange event that runs lovd_checkHGVS. - oGenomicVariant.change(lovd_checkHGVS); + oGenomicVariants.change(lovd_checkHGVS); // Add same function to the onKeyUp event, but then it will check itself if the variant is likely to be complete. - oGenomicVariant.keyup(lovd_checkHGVS); + oGenomicVariants.keyup(lovd_checkHGVS); - if (oGenomicVariant.val() !== '') { + if (oGenomicVariants.val() !== '') { // Variant field already has content, check HGVS now because if we're on an edit form we // want the buttons to be ready. - oGenomicVariant.change(); + oGenomicVariants.change(); } + // Add the button and image at the end of the genomic DNA fields. + var aSupportedBuilds = [""]; + for (i=0; i < oGenomicVariants.length; i++) { + var oGenomicVariant = oGenomicVariants.eq(i); + if (aSupportedBuilds.includes(oGenomicVariant.data('genome-build'))) { + oGenomicVariant.parent().append('   '); + } + } + + if (oTranscriptVariants[0] != undefined) { // Add the buttons and images at the end of the transcripts DNA fields. oTranscriptVariants.parent().append('   '); From 1d3dad73e57a6ba4adeea040b616ef0c8083eaee Mon Sep 17 00:00:00 2001 From: Ivo Fokkema Date: Fri, 8 Oct 2021 17:22:03 +0200 Subject: [PATCH 06/95] Remove disabled method. --- src/class/object_genome_variants.php | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/class/object_genome_variants.php b/src/class/object_genome_variants.php index 06039cb9..43e3c37d 100644 --- a/src/class/object_genome_variants.php +++ b/src/class/object_genome_variants.php @@ -4,8 +4,8 @@ * LEIDEN OPEN VARIATION DATABASE (LOVD) * * Created : 2010-12-20 - * Modified : 2021-08-12 - * For LOVD : 3.0-27 + * Modified : 2021-10-08 + * For LOVD : 3.5-pre-03 * * Copyright : 2004-2021 Leiden University Medical Center; http://www.LUMC.nl/ * Programmers : Ivar C. Lugtenburg @@ -222,20 +222,6 @@ function __construct () -// function buildForm ($sPrefix = '') -// { -// $aForm = parent::buildForm($sPrefix); -// // Link to HGVS for nomenclature. -// if (isset($aForm[$sPrefix . 'VariantOnGenome/DNA'])) { -// $aForm[$sPrefix . 'VariantOnGenome/DNA'][0] = str_replace('(HGVS format)', '(HGVS format)', $aForm[$sPrefix . 'VariantOnGenome/DNA'][0]); -// } -// return $aForm; -// } - - - - - function checkFields ($aData, $zData = false, $aOptions = array()) { global $_AUTH, $_SETT; From e6074238bef2b49a5cbd0e0acb5f9aa82a6e0f4d Mon Sep 17 00:00:00 2001 From: Ivo Fokkema Date: Fri, 8 Oct 2021 17:22:36 +0200 Subject: [PATCH 07/95] When adding to the DNA field description, don't overwrite anything. --- src/class/object_genome_variants.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/class/object_genome_variants.php b/src/class/object_genome_variants.php index 43e3c37d..567480aa 100644 --- a/src/class/object_genome_variants.php +++ b/src/class/object_genome_variants.php @@ -337,11 +337,12 @@ function getForm () } } - // Add genome build name and element data to VOG/DNA field, and add in the link to the HGVS website. + // Add genome build name and element data to VOG/DNA fields, and add in the link to the HGVS website. $aActiveBuilds = $_DB->query('SELECT id, name, column_suffix FROM ' . TABLE_GENOME_BUILDS)->fetchAllGroupAssoc(); foreach ($aActiveBuilds as $sBuild => $aBuild) { $sSuffixWithSlash = (!$aBuild['column_suffix']? '' : '/' . $aBuild['column_suffix']); - $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['description_form'] = 'Relative to ' . $aBuild['name'] . '.'; + $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['description_form'] = 'Relative to ' . $aBuild['name'] . '.' . + (!$this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['description_form']? '' : '
' . $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['description_form']); $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['element_data'] = array('genome_build' => $sBuild); $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['form_type'][0] = str_replace('(HGVS format)', '(HGVS format)', $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['form_type'][0]); } From 77a3e864785f3d5610e29aacb05f5dbae095d683 Mon Sep 17 00:00:00 2001 From: Ivo Fokkema Date: Fri, 8 Oct 2021 17:24:34 +0200 Subject: [PATCH 08/95] Improved efficiency of variables a bit, shortening the code. --- src/class/object_genome_variants.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/class/object_genome_variants.php b/src/class/object_genome_variants.php index 567480aa..cf68f08a 100644 --- a/src/class/object_genome_variants.php +++ b/src/class/object_genome_variants.php @@ -340,11 +340,11 @@ function getForm () // Add genome build name and element data to VOG/DNA fields, and add in the link to the HGVS website. $aActiveBuilds = $_DB->query('SELECT id, name, column_suffix FROM ' . TABLE_GENOME_BUILDS)->fetchAllGroupAssoc(); foreach ($aActiveBuilds as $sBuild => $aBuild) { - $sSuffixWithSlash = (!$aBuild['column_suffix']? '' : '/' . $aBuild['column_suffix']); - $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['description_form'] = 'Relative to ' . $aBuild['name'] . '.' . - (!$this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['description_form']? '' : '
' . $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['description_form']); - $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['element_data'] = array('genome_build' => $sBuild); - $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['form_type'][0] = str_replace('(HGVS format)', '(HGVS format)', $this->aColumns['VariantOnGenome/DNA' . $sSuffixWithSlash]['form_type'][0]); + $sColumn = 'VariantOnGenome/DNA' . (!$aBuild['column_suffix']? '' : '/' . $aBuild['column_suffix']); + $this->aColumns[$sColumn]['description_form'] = 'Relative to ' . $aBuild['name'] . '.' . + (!$this->aColumns[$sColumn]['description_form']? '' : '
' . $this->aColumns[$sColumn]['description_form']); + $this->aColumns[$sColumn]['element_data'] = array('genome_build' => $sBuild); + $this->aColumns[$sColumn]['form_type'][0] = str_replace('(HGVS format)', '(HGVS format)', $this->aColumns[$sColumn]['form_type'][0]); } // FIXME; right now two blocks in this array are put in, and optionally removed later. However, the if() above can build an entire block, such that one of the two big unset()s can be removed. From 68f4ff4b44fd5f72f2145a44bdc1b8945d909274 Mon Sep 17 00:00:00 2001 From: Ivo Fokkema Date: Fri, 8 Oct 2021 18:10:37 +0200 Subject: [PATCH 09/95] Clean up the code a bit, and simply selecting VOG/DNA fields in JS. --- src/class/object_custom.php | 3 ++- src/class/object_genome_builds.php | 2 +- src/inc-js-variants.php | 20 +++++++++++--------- src/inc-lib-form.php | 4 ++-- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/class/object_custom.php b/src/class/object_custom.php index 5dc4b26a..b36e7960 100644 --- a/src/class/object_custom.php +++ b/src/class/object_custom.php @@ -295,7 +295,8 @@ function buildForm ($sPrefix = '') $aFormData[$sPrefix . $sCol] = $aEntry; } - // The element data will be passed on, so that viewForm can make sure it will be added to the HTML. + // The element data will be passed on, so that viewForm() can make sure it will be added to the HTML. + // NOTE: Element data is not stored in the database, but added by, for instance, getForm(). if (!empty($aCol['element_data'])) { $aFormData[$sPrefix . $sCol][] = $aCol['element_data']; } diff --git a/src/class/object_genome_builds.php b/src/class/object_genome_builds.php index ef5e32f9..53f16d35 100644 --- a/src/class/object_genome_builds.php +++ b/src/class/object_genome_builds.php @@ -123,7 +123,7 @@ function prepareData ($zData = '', $sView = 'list') $sDNAColumn = 'VariantOnGenome/DNA' . (!$zData['column_suffix']? '' : '/') . $zData['column_suffix']; $nPercentComplete = (int) $_DB->query( 'SELECT ROUND( - (SELECT COUNT(*) FROM ' . TABLE_VARIANTS. ' + (SELECT COUNT(*) FROM ' . TABLE_VARIANTS . ' WHERE `' . $sDNAColumn . '` IS NOT NULL AND `' . $sDNAColumn . '` != "") / ( SELECT COUNT(*) FROM ' . TABLE_VARIANTS . ') * 100)')->fetchColumn(); diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index a10baa3e..ce6cf9d2 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -42,11 +42,13 @@ define('AJAX_NO_AUTH', '8'); define('AJAX_DATA_ERROR', '9'); -$_SETT = array('objectid_length' => array('transcripts' => 8), - 'variant_validator' => array('genome_builds' => array('hg19', 'hg38'))); +$_SETT = array( + 'objectid_length' => array('transcripts' => 8), + 'variant_validator' => array( + 'genome_builds' => array('hg19', 'hg38')), +); ?> - function lovd_checkHGVS (e) { // Function that is being called everytime a change has been made to a DNA field, @@ -82,7 +84,7 @@ function lovd_checkHGVS (e) if (e.type == 'change' && !bHGVS && oVariantDNA.val()) { // This is a "real" onChange call(), we couldn't match the variant, but we do have something filled in. Check with Mutalyzer! - if (oVariantDNA.attr('name').substring(0, 'VariantOnGenome/DNA'.length) == 'VariantOnGenome/DNA') { + if (oVariantDNA.filter("[name^='VariantOnGenome/DNA']").size()) { var sVariantNotation = 'g:' + oVariantDNA.val(); // The actual chromosome is not important, it's just the variant syntax that matters here. } else { var sVariantNotation = 'c:' + oVariantDNA.val(); // The actual transcript is not important, it's just the variant syntax that matters here. @@ -189,8 +191,6 @@ function lovd_convertPosition (oElement) sSource = "VOT"; } else { sSource = oThisDNA.data('genomeBuild'); - // pos = oThisDNA.attr("name").lastIndexOf("/"); - // sSource = oThisDNA.attr("name").substr(pos + 1); } oVariantSource.val(sSource); } @@ -204,12 +204,14 @@ className: '', onmouseover: '', onmouseout: '' }).show(); + var oAllProteins = $('input[name$="_VariantOnTranscript/Protein"]'); $(oAllProteins).siblings('img:first').attr({ src: 'gfx/trans.png', alt: '', title: '' }).show(); + $(oThisDNA).siblings('img:first').attr({ src: 'gfx/lovd_loading.gif', alt: 'Loading...', @@ -219,7 +221,7 @@ className: '', onmouseout: '' }).show(); - if (oThisDNA.attr('name').substring(0, 'VariantOnGenome/DNA'.length) == 'VariantOnGenome/DNA') { + if (oThisDNA.filter("[name^='VariantOnGenome/DNA']").size()) { // This function was called from the genomic variant, so build a list of genes and prepare the variant accordingly for mutalyzer. var sVariantNotation = 'chr:' + oThisDNA.val(); var aGenes = []; @@ -243,7 +245,7 @@ className: '', $.get('ajax/convert_position.php', { variant: sVariantNotation, gene: sGene }, function(sData) { if (sData != '' && sData != '' && sData != '') { - if (oThisDNA.attr('name').substring(0, 'VariantOnGenome/DNA'.length) == 'VariantOnGenome/DNA') { + if (oThisDNA.filter("[name^='VariantOnGenome/DNA']").size()) { // This function was called from the genomic variant, so fill in the return values from mutalyzer in the transcript DNA fields. aVariants = sData.split(';'); var nVariants = aVariants.length; @@ -567,4 +569,4 @@ function lovd_highlightInput (oElement) oTranscriptVariants.change(); } } -}); \ No newline at end of file +}); diff --git a/src/inc-lib-form.php b/src/inc-lib-form.php index 808ddcb6..020cc039 100644 --- a/src/inc-lib-form.php +++ b/src/inc-lib-form.php @@ -1011,8 +1011,8 @@ function lovd_viewForm ($a, $GLOBALS['_' . $sMethod][$sName] = ''; } - // When element data is given, it will be added into the HTML code in a 'data-...' format, - // so that HTML recognises it. This way, JavaScript can see and use this data. + // When $aElementData is given, it will be added into the HTML code in a 'data-...' format, + // so that jQuery can easily extract it and use it. array_walk($aElementData, function (&$sVal, $sKey) { $sVal = 'data-' . str_replace('_', '-', $sKey) . '="' . htmlspecialchars($sVal) . '"'; }); From a9dbc6d346e1b15017b5aeba0eca8d639638f8df Mon Sep 17 00:00:00 2001 From: loeswerkman Date: Fri, 15 Oct 2021 12:00:28 +0200 Subject: [PATCH 10/95] Add IsHGVS function and Unit test --- tests/unit_tests/GetVariantInfoTest.php | 280 ++++++++++++------------ 1 file changed, 140 insertions(+), 140 deletions(-) diff --git a/tests/unit_tests/GetVariantInfoTest.php b/tests/unit_tests/GetVariantInfoTest.php index 2027ce34..143be8aa 100644 --- a/tests/unit_tests/GetVariantInfoTest.php +++ b/tests/unit_tests/GetVariantInfoTest.php @@ -1,140 +1,140 @@ - - * Ivo F.A.C. Fokkema - * - * - * This file is part of LOVD. - * - * LOVD is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LOVD is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LOVD. If not, see . - * - *************/ - - -require_once 'src/inc-lib-init.php'; - -class GetVariantInfoTest extends PHPUnit_Framework_TestCase -{ - - /** - * @dataProvider dataProviderGetVariantInfo - */ - public function testGetVariantInfo ($sInput, $aOutput) - { - // Test lovd_getVariantInfo with data from - // dataProviderGetVariantInfo(). - $this->assertEquals(lovd_getVariantInfo($sInput), $aOutput); - } - - - public static function dataProviderGetVariantInfo () - { - // Data provider for testGetVariantInfo(). - // Fixme: extend below with more complex variant descriptions. - return array( - array('g.123dup', array( - 'position_start' => 123, - 'position_end' => 123, - 'type' => 'dup', - 'warnings' => array(), - )), - array('c.123dup', array( - 'position_start' => 123, - 'position_end' => 123, - 'position_start_intron' => 0, - 'position_end_intron' => 0, - 'type' => 'dup', - 'warnings' => array(), - )), - array('m.123dup', array( - 'position_start' => 123, - 'position_end' => 123, - 'type' => 'dup', - 'warnings' => array(), - )), - array('n.123dup', array( - 'position_start' => 123, - 'position_end' => 123, - 'position_start_intron' => 0, - 'position_end_intron' => 0, - 'type' => 'dup', - 'warnings' => array(), - )), - array('g.(?_112043201)_(112181937_?)del', array( - 'position_start' => 112043201, - 'position_end' => 112181937, - 'type' => 'del', - 'warnings' => array(), - )), - array('g.(100_200)_(400_500)del', array( - 'position_start' => 150, - 'position_end' => 450, - 'type' => 'del', - 'warnings' => array(), - )), - array('g.100_(400_500)del', array( - 'position_start' => 100, - 'position_end' => 450, - 'type' => 'del', - 'warnings' => array(), - )), - array('g.(100_200)_500del', array( - 'position_start' => 150, - 'position_end' => 500, - 'type' => 'del', - 'warnings' => array(), - )), - array('g.100612527_100612529delinsAA', array( - 'position_start' => 100612527, - 'position_end' => 100612529, - 'type' => 'delins', - 'warnings' => array(), - )), - array('g.100612529_100612527delinsAA', array( - 'position_start' => 100612527, - 'position_end' => 100612529, - 'type' => 'delins', - 'warnings' => array( - 'WPOSITIONSSWAPPED' => 'Variant end position is higher than variant start position.', - ), - )), - array('g.100612529_100612527delinsAA', array( - 'position_start' => 100612527, - 'position_end' => 100612529, - 'type' => 'delins', - 'warnings' => array( - 'WPOSITIONSSWAPPED' => 'Variant end position is higher than variant start position.', - ), - )), - array('c.10000000_10000000del', array( - 'position_start' => 8388607, - 'position_end' => 8388607, - 'position_start_intron' => 0, - 'position_end_intron' => 0, - 'type' => 'del', - 'warnings' => array( - 'WPOSITIONSLIMIT' => 'Positions are beyond the possible limits of their type: position_start, position_end.', - ), - )), - ); - } -} + + * Ivo F.A.C. Fokkema + * + * + * This file is part of LOVD. + * + * LOVD is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LOVD is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LOVD. If not, see . + * + *************/ + + +require_once 'src/inc-lib-init.php'; + +class GetVariantInfoTest extends PHPUnit_Framework_TestCase +{ + + /** + * @dataProvider dataProviderGetVariantInfo + */ + public function testGetVariantInfo ($sInput, $aOutput) + { + // Test lovd_getVariantInfo with data from + // dataProviderGetVariantInfo(). + $this->assertEquals(lovd_getVariantInfo($sInput), $aOutput); + } + + + public static function dataProviderGetVariantInfo () + { + // Data provider for testGetVariantInfo(). + // Fixme: extend below with more complex variant descriptions. + return array( + array('g.123dup', array( + 'position_start' => 123, + 'position_end' => 123, + 'type' => 'dup', + 'warnings' => array(), + )), + array('c.123dup', array( + 'position_start' => 123, + 'position_end' => 123, + 'position_start_intron' => 0, + 'position_end_intron' => 0, + 'type' => 'dup', + 'warnings' => array(), + )), + array('m.123dup', array( + 'position_start' => 123, + 'position_end' => 123, + 'type' => 'dup', + 'warnings' => array(), + )), + array('n.123dup', array( + 'position_start' => 123, + 'position_end' => 123, + 'position_start_intron' => 0, + 'position_end_intron' => 0, + 'type' => 'dup', + 'warnings' => array(), + )), + array('g.(?_112043201)_(112181937_?)del', array( + 'position_start' => 112043201, + 'position_end' => 112181937, + 'type' => 'del', + 'warnings' => array(), + )), + array('g.(100_200)_(400_500)del', array( + 'position_start' => 150, + 'position_end' => 450, + 'type' => 'del', + 'warnings' => array(), + )), + array('g.100_(400_500)del', array( + 'position_start' => 100, + 'position_end' => 450, + 'type' => 'del', + 'warnings' => array(), + )), + array('g.(100_200)_500del', array( + 'position_start' => 150, + 'position_end' => 500, + 'type' => 'del', + 'warnings' => array(), + )), + array('g.100612527_100612529delinsAA', array( + 'position_start' => 100612527, + 'position_end' => 100612529, + 'type' => 'delins', + 'warnings' => array(), + )), + array('g.100612529_100612527delinsAA', array( + 'position_start' => 100612527, + 'position_end' => 100612529, + 'type' => 'delins', + 'warnings' => array( + 'WPOSITIONSSWAPPED' => 'Variant end position is higher than variant start position.', + ), + )), + array('g.100612529_100612527delinsAA', array( + 'position_start' => 100612527, + 'position_end' => 100612529, + 'type' => 'delins', + 'warnings' => array( + 'WPOSITIONSSWAPPED' => 'Variant end position is higher than variant start position.', + ), + )), + array('c.10000000_10000000del', array( + 'position_start' => 8388607, + 'position_end' => 8388607, + 'position_start_intron' => 0, + 'position_end_intron' => 0, + 'type' => 'del', + 'warnings' => array( + 'WPOSITIONSLIMIT' => 'Positions are beyond the possible limits of their type: position_start, position_end.', + ), + )), + ); + } +} From 4e83069179b2c5e7591f4ac291974243a0a5ab0d Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Fri, 21 Jan 2022 15:49:00 +0100 Subject: [PATCH 11/95] Open checkHGVS dialogue in variant creation form If something is off with a given variant, a dialogue will now open to inform the user of these issues and propose a possible fix. Also: fixed issue with outdated curly brackets as used to index a string. --- src/ajax/check_hgvs_dialogue.php | 134 ++++++++++++++++ src/inc-js-variants.php | 252 +++++++++++++++---------------- src/inc-lib-init.php | 10 +- 3 files changed, 263 insertions(+), 133 deletions(-) create mode 100644 src/ajax/check_hgvs_dialogue.php diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php new file mode 100644 index 00000000..940b9bef --- /dev/null +++ b/src/ajax/check_hgvs_dialogue.php @@ -0,0 +1,134 @@ + + * + * + * This file is part of LOVD. + * + * LOVD is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LOVD is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LOVD. If not, see . + * + *************/ + +define('ROOT_PATH', '../'); +require ROOT_PATH . 'inc-init.php'; +require ROOT_PATH . 'inc-lib-variants.php'; +header('Content-type: text/javascript; charset=UTF-8'); + +// TODO: All spots where $sTranscriptID is set to false -> check. +// TODO: Maak call naar ander script dat protein/RNA changes toevoegt. +// URL: /ajax/check_hgvs_dialogue.php/variant=g.1del + + +$sVariant = $_REQUEST['var']; +$sName = $_REQUEST['name']; + + +// If the variant is empty, we want to set the HGVS check to neutral. +if (!$_REQUEST['var']) { + exit(' + var oInput = $(\'input[name$="' . $sName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + '); +} + + + +// If the variant is HGVS, we set the HGVS check to a 'check'. +if (lovd_getVariantInfo($sVariant, false, true)) { + exit(' + var oInput = $(\'input[name$="' . $sName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/check.png"}).show(); + '); +} + + + +// Retrieving information and fixes on the variant. +$aVariant = lovd_getVariantInfo($sVariant, false); +// To use after updating getVariantInfo: +// $aVariantIssues = ($aVariant === false? array() : array_merge($aVariant['errors'], $aVariant['warnings'])); +$aVariant = ($aVariant === false? array() : $aVariant['warnings']); +$sFixedVariant = lovd_fixHGVS($sVariant); + + + +// Preparing the buttons. +print(' +// Preparing the buttons. +var oButtonYes = {"Yes":function () { + var oInput = $(\'input[name$="' . $sName . '"]\'); + oInput.val("' . $sFixedVariant . '"); + oInput.siblings("img:first").attr({src: "gfx/check.png"}).show(); + $(this).dialog("close"); +}}; +var oButtonNo = {"No, I will take a look myself":function () { + var oInput = $(\'input[name$="' . $sName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/cross.png"}).show(); + $(this).dialog("close"); +}}; +var oButtonOK = {"OK":function () { + var oInput = $(\'input[name$="' . $sName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/cross.png"}).show(); + $(this).dialog("close"); +}}; +'); + + + +// Preparing the dialogue's contents and buttons. +$sResponse = 'Your variant (\"' . $sVariant . '\") did not pass our HGVS check.

'; + +if (!empty($aVariantIssues)) { + $sResponse .= 'We found the following problems:
- '; + $sResponse .= implode('
-', $aVariantIssues) . '

'; +} + +if ($sFixedVariant !== $sVariant + && lovd_getVariantInfo($sFixedVariant, false, true)) { + $sResponse .= 'Did you mean \"' . $sFixedVariant . '\"?
'; + $sButtons = 'oButtonYes, oButtonNo'; + +} else { + $sResponse .= 'Please check your variant for errors and try again.
'; + $sButtons = 'oButtonOK'; +} + + + + +// Printing the dialogue. +print(' +// Setting up the dialogue. +$("body").append("
"); +$("#variantCheckDialogue").dialog({ + draggable:false,resizable:false,minWidth:600,show:"fade",closeOnEscape:false,hide:"fade",modal:true, + open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); } +}); + +// Placing the contents. +$("#variantCheckDialogue").html("' . $sResponse . '"); + +// Placing the buttons. +$("#variantCheckDialogue").dialog({buttons: $.extend({}, ' . $sButtons . ')}); +'); + +?> diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index 42625925..e4a94970 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -33,7 +33,7 @@ *************/ header('Content-type: text/javascript; charset=UTF-8'); -header('Expires: ' . date('r', time()+(180*60))); +header('Expires: ' . date('r', time())); define('AJAX_FALSE', '0'); define('AJAX_TRUE', '1'); @@ -45,117 +45,129 @@ $_SETT = array('objectid_length' => array('transcripts' => 8)); ?> -function lovd_checkHGVS (e) -{ - // Function that is being called everytime a change has been made to a DNA field, - // either from an onKeyUp or onChange, although the onKeyUp only uses this function partially. - // This will run the Mutalyzer checkHGVS module (if needed) and will return the response to the user. - - var oVariantDNA = $(this); - oVariantDNA.removeClass(); - - // If we're a "preliminary" trigger, actually run when a key has been pressed, we just want a quick check - // if the DNA field seems correct. If so, we show the mark and the buttons, just like a "real" onChange(). - // However, when it doesn't look good, we don't request Mutalyzer (to confirm, they should know best) - // unless we're a "real" onChange() request. - - var bHGVS; // True -> correct syntax; False -> We don't recognize it, but Mutalyzer might. - // First check: genomic field should start with g. or m., cDNA field should start with c. or n.. - if (oVariantDNA.attr('name') == 'VariantOnGenome/DNA' && !/^(g|m)\./.test(oVariantDNA.val().substring(0, 2))) { - bHGVS = false; - } else if (oVariantDNA.attr('name') != 'VariantOnGenome/DNA' && !/^(c|n)\./.test(oVariantDNA.val().substring(0, 2))) { - bHGVS = false; - } else { - // Try to match simple stuff: deletions, duplications, insertions, inversions and substitutions. - var oRegExp = /^[cgmn]\.\-?\d+([-+]\d+)?([ACGT]>[ACGT]|(_\-?\d+([-+]\d+)?)?d(el|up)([ACGT])*|_\-?\d+([-+]\d+)?(inv|ins([ACGT])+))$/; - // "false" doesn't necessarily mean false here! Just means this check doesn't recognize it. Mutalyzer may still. - bHGVS = (oRegExp.test(oVariantDNA.val())); - } - - // Grab the corresponding protein description field if it exists. - var oProtein = $(oVariantDNA).parent().parent().siblings().find('input[name="' + $(oVariantDNA).attr('name').substring(0, ) + '_VariantOnTranscript/Protein"]'); - - // Add a transparent placeholder for the indicator at the protein field, so that the form will not shift when it is added. - oProtein.siblings('img:first').removeClass().attr('src', 'gfx/trans.png'); - - if (e.type == 'change' && !bHGVS && oVariantDNA.val()) { - // This is a "real" onChange call(), we couldn't match the variant, but we do have something filled in. Check with Mutalyzer! - if (oVariantDNA.attr('name') == 'VariantOnGenome/DNA') { - var sVariantNotation = 'g:' + oVariantDNA.val(); // The actual chromosome is not important, it's just the variant syntax that matters here. - } else { - var sVariantNotation = 'c:' + oVariantDNA.val(); // The actual transcript is not important, it's just the variant syntax that matters here. - } - - // Now we have to check with Mutalyzer... - $(oVariantDNA).siblings('img:first').attr({ - src: 'gfx/lovd_loading.gif', - alt: 'Loading...', - title: 'Loading...', - className: '', - onmouseover: '', - onmouseout: '' - }).show(); - - // Make the call to Mutalyzer to see if the variant is correct HGVS. - $.get('ajax/check_hgvs.php', { variant: sVariantNotation }, - function(sData) { - if (sData != '') { - // Either Mutalyzer says No, our regexp didn't find a c. or g. at the beginning or user lost $_AUTH. - oVariantDNA.siblings('img:first').attr({ - src: 'gfx/cross.png', - alt: (sData == ? 'Unexpected response from Mutalyzer. Please try again later.' : 'Not a valid HGVS syntax!'), - title: (sData == ? 'Unexpected response from Mutalyzer. Please try again later.' : 'Not a valid HGVS syntax!'), - }).show(); - // Now hide the "Map variant" and "Predict" buttons. - if (!$.isEmptyObject(aTranscripts)) { - oVariantDNA.siblings('button:eq(0)').hide(); - oProtein.siblings('button:eq(0)').hide(); - } - - } else { - oVariantDNA.siblings('img:first').attr({ - src: 'gfx/check.png', - alt: 'Valid HGVS syntax!', - title: 'Valid HGVS syntax!' - }).show(); - // Check if the variant description is a c.? or a g.?. If it is, then do not let the user map the variant. - if (oVariantDNA.val().substring(1,3) == '.?') { - oVariantDNA.siblings('button:eq(0)').hide(); - oProtein.siblings('button:eq(0)').hide(); - } else if (!$.isEmptyObject(aTranscripts)) { - // Only enable the mapping buttons when there are transcripts added to this variant. - oVariantDNA.siblings('button:eq(0)').show(); - oProtein.siblings('button:eq(0)').show(); - // Hide possible 'view prediction button' - $('#' + jq_escape(oProtein.attr('name')) + '_view_prediction').remove(); - } - } - }); - - } else if (bHGVS) { - // We didn't need Mutalyzer, and we know we've got a good-looking variant here. - oVariantDNA.siblings('img:first').attr({ - src: 'gfx/check.png', - alt: 'Valid HGVS syntax!', - title: 'Valid HGVS syntax!' - }).show(); - if (!$.isEmptyObject(aTranscripts)) { - // Only enable the mapping buttons when there are transcripts added to this variant. - oVariantDNA.siblings('button:eq(0)').show(); - oProtein.siblings('button:eq(0)').show(); - // Hide possible 'view prediction button' - $('#' + jq_escape(oProtein.attr('name')) + '_view_prediction').remove(); - } - - } else { - // No HGVS syntax, but no "real" onChange trigger yet, either. - oVariantDNA.siblings('img:first').hide(); - if (!$.isEmptyObject(aTranscripts)) { - oVariantDNA.siblings('button:eq(0)').hide(); - oProtein.siblings('button:eq(0)').hide(); - } - } - return false; +// function lovd_checkHGVS (e) +// { +// // Function that is being called everytime a change has been made to a DNA field, +// // either from an onKeyUp or onChange, although the onKeyUp only uses this function partially. +// // This will run the Mutalyzer checkHGVS module (if needed) and will return the response to the user. +// +// var oVariantDNA = $(this); +// oVariantDNA.removeClass(); +// +// // If we're a "preliminary" trigger, actually run when a key has been pressed, we just want a quick check +// // if the DNA field seems correct. If so, we show the mark and the buttons, just like a "real" onChange(). +// // However, when it doesn't look good, we don't request Mutalyzer (to confirm, they should know best) +// // unless we're a "real" onChange() request. +// +// var bHGVS; // True -> correct syntax; False -> We don't recognize it, but Mutalyzer might. +// // First check: genomic field should start with g. or m., cDNA field should start with c. or n.. +// if (oVariantDNA.attr('name') == 'VariantOnGenome/DNA' && !/^(g|m)\./.test(oVariantDNA.val().substring(0, 2))) { +// bHGVS = false; +// } else if (oVariantDNA.attr('name') != 'VariantOnGenome/DNA' && !/^(c|n)\./.test(oVariantDNA.val().substring(0, 2))) { +// bHGVS = false; +// } else { +// // Try to match simple stuff: deletions, duplications, insertions, inversions and substitutions. +// var oRegExp = /^[cgmn]\.\-?\d+([-+]\d+)?([ACGT]>[ACGT]|(_\-?\d+([-+]\d+)?)?d(el|up)([ACGT])*|_\-?\d+([-+]\d+)?(inv|ins([ACGT])+))$/; +// // "false" doesn't necessarily mean false here! Just means this check doesn't recognize it. Mutalyzer may still. +// bHGVS = (oRegExp.test(oVariantDNA.val())); +// } +// +// // Grab the corresponding protein description field if it exists. +// var oProtein = $(oVariantDNA).parent().parent().siblings().find('input[name="' + $(oVariantDNA).attr('name').substring(0, //) + '_VariantOnTranscript/Protein"]'); +// +// // Add a transparent placeholder for the indicator at the protein field, so that the form will not shift when it is added. +// oProtein.siblings('img:first').removeClass().attr('src', 'gfx/trans.png'); +// +// if (e.type == 'change' && !bHGVS && oVariantDNA.val()) { +// // This is a "real" onChange call(), we couldn't match the variant, but we do have something filled in. Check with Mutalyzer! +// if (oVariantDNA.attr('name') == 'VariantOnGenome/DNA') { +// var sVariantNotation = 'g:' + oVariantDNA.val(); // The actual chromosome is not important, it's just the variant syntax that matters here. +// } else { +// var sVariantNotation = 'c:' + oVariantDNA.val(); // The actual transcript is not important, it's just the variant syntax that matters here. +// } +// +// // Now we have to check with Mutalyzer... +// $(oVariantDNA).siblings('img:first').attr({ +// src: 'gfx/lovd_loading.gif', +// alt: 'Loading...', +// title: 'Loading...', +// className: '', +// onmouseover: '', +// onmouseout: '' +// }).show(); +// +// // Make the call to Mutalyzer to see if the variant is correct HGVS. +// $.get('ajax/check_hgvs.php', { variant: sVariantNotation }, +// function(sData) { +// if (sData != '//') { +// // Either Mutalyzer says No, our regexp didn't find a c. or g. at the beginning or user lost $_AUTH. +// oVariantDNA.siblings('img:first').attr({ +// src: 'gfx/cross.png', +// alt: (sData == //? 'Unexpected response from Mutalyzer. Please try again later.' : 'Not a valid HGVS syntax!'), +// title: (sData == //? 'Unexpected response from Mutalyzer. Please try again later.' : 'Not a valid HGVS syntax!'), +// }).show(); +// // Now hide the "Map variant" and "Predict" buttons. +// if (!$.isEmptyObject(aTranscripts)) { +// oVariantDNA.siblings('button:eq(0)').hide(); +// oProtein.siblings('button:eq(0)').hide(); +// } +// +// } else { +// oVariantDNA.siblings('img:first').attr({ +// src: 'gfx/check.png', +// alt: 'Valid HGVS syntax!', +// title: 'Valid HGVS syntax!' +// }).show(); +// // Check if the variant description is a c.? or a g.?. If it is, then do not let the user map the variant. +// if (oVariantDNA.val().substring(1,3) == '.?') { +// oVariantDNA.siblings('button:eq(0)').hide(); +// oProtein.siblings('button:eq(0)').hide(); +// } else if (!$.isEmptyObject(aTranscripts)) { +// // Only enable the mapping buttons when there are transcripts added to this variant. +// oVariantDNA.siblings('button:eq(0)').show(); +// oProtein.siblings('button:eq(0)').show(); +// // Hide possible 'view prediction button' +// $('#' + jq_escape(oProtein.attr('name')) + '_view_prediction').remove(); +// } +// } +// }); +// +// } else if (bHGVS) { +// // We didn't need Mutalyzer, and we know we've got a good-looking variant here. +// oVariantDNA.siblings('img:first').attr({ +// src: 'gfx/check.png', +// alt: 'Valid HGVS syntax!', +// title: 'Valid HGVS syntax!' +// }).show(); +// if (!$.isEmptyObject(aTranscripts)) { +// // Only enable the mapping buttons when there are transcripts added to this variant. +// oVariantDNA.siblings('button:eq(0)').show(); +// oProtein.siblings('button:eq(0)').show(); +// // Hide possible 'view prediction button' +// $('#' + jq_escape(oProtein.attr('name')) + '_view_prediction').remove(); +// } +// +// } else { +// // No HGVS syntax, but no "real" onChange trigger yet, either. +// oVariantDNA.siblings('img:first').hide(); +// if (!$.isEmptyObject(aTranscripts)) { +// oVariantDNA.siblings('button:eq(0)').hide(); +// oProtein.siblings('button:eq(0)').hide(); +// } +// } +// return false; +// } + + + + + +// Checking the input variant. +function lovd_checkHGVS(e) { + var sVariant = $(this).val(); + var sName = $(this).attr("name"); + $.get("ajax/check_hgvs_dialogue.php?var=" + encodeURIComponent(sVariant) + "&name=" + encodeURIComponent(sName)) + .fail(function(){alert("Error checking your variant, please try again later.");}); } @@ -521,14 +533,6 @@ function lovd_highlightInput (oElement) oGenomicVariant.parent().append('   '); // Add an onChange event that runs lovd_checkHGVS. oGenomicVariant.change(lovd_checkHGVS); - // Add same function to the onKeyUp event, but then it will check itself if the variant is likely to be complete. - oGenomicVariant.keyup(lovd_checkHGVS); - - if (oGenomicVariant.val() !== '') { - // Variant field already has content, check HGVS now because if we're on an edit form we - // want the buttons to be ready. - oGenomicVariant.change(); - } if (oTranscriptVariants[0] != undefined) { // Add the buttons and images at the end of the transcripts DNA fields. @@ -540,19 +544,11 @@ function lovd_highlightInput (oElement) } // Add an onChange event that runs lovd_checkHGVS. oTranscriptVariants.change(lovd_checkHGVS); - // Add same function to the onKeyUp event, but then it will check itself if the variant is likely to be complete. - oTranscriptVariants.keyup(lovd_checkHGVS); var oProteinVariants = $('#variantForm input[name$="_VariantOnTranscript/Protein"]'); if (oProteinVariants[0] != undefined) { // Add the buttons and images at the end of the protein description fields. oProteinVariants.parent().append('   '); } - - if (oTranscriptVariants.val() !== '') { - // Variant field already has content, check HGVS now because if we're on an edit form we - // want the buttons to be ready. - oTranscriptVariants.change(); - } } }); diff --git a/src/inc-lib-init.php b/src/inc-lib-init.php index 87e9dfcc..4ce2df66 100644 --- a/src/inc-lib-init.php +++ b/src/inc-lib-init.php @@ -1189,7 +1189,7 @@ function lovd_getVariantInfo ($sVariant, $sTranscriptID = '', $bCheckHGVS = fals } // Convert 3' UTR notations into normal notations. - if ($sStartPosition{0} == '*' || ($sEndPosition && $sEndPosition{0} == '*')) { + if ($sStartPosition[0] == '*' || ($sEndPosition && $sEndPosition[0] == '*')) { // Check if a transcript ID has been provided. if ($sTranscriptID === '') { // No, but we'll need it. @@ -1197,10 +1197,10 @@ function lovd_getVariantInfo ($sVariant, $sTranscriptID = '', $bCheckHGVS = fals } // Translate positions. - if ($sStartPosition{0} == '*') { + if ($sStartPosition[0] == '*') { $sStartPosition = substr($sStartPosition, 1) + $aTranscriptOffsets[$sTranscriptID]; } - if ($sEndPosition && $sEndPosition{0} == '*') { + if ($sEndPosition && $sEndPosition[0] == '*') { $sEndPosition = substr($sEndPosition, 1) + $aTranscriptOffsets[$sTranscriptID]; } } @@ -1293,8 +1293,8 @@ function lovd_getVariantInfo ($sVariant, $sTranscriptID = '', $bCheckHGVS = fals } // Convert 3' UTR notations into normal notations. - if ($sStartPositionEarly{0} == '*' || ($sStartPositionLate && $sStartPositionLate{0} == '*') - || $sEndPositionEarly{0} == '*' || ($sEndPositionLate && $sEndPositionLate{0} == '*')) { + if ($sStartPositionEarly[0] == '*' || ($sStartPositionLate && $sStartPositionLate[0] == '*') + || $sEndPositionEarly[0] == '*' || ($sEndPositionLate && $sEndPositionLate[0] == '*')) { // Check if a transcript ID has been provided. if ($sTranscriptID === '') { // No, but we'll need it. From 8949e05efc3215f9cc6142fb4f92dde27f6ba54c Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 27 Jan 2022 09:33:42 +0100 Subject: [PATCH 12/95] Create and implement the isHGVS wrapper function The isHGVS function is created to increase readability when doing an HGVS check. Before this commit, this was done using lovd_getVariantInfo($sVariant, false, true); not very readable. Now this can simply be done using lovd_isHGVS($sVariant). --- src/ajax/check_hgvs_dialogue.php | 4 ++-- src/inc-lib-init.php | 14 ++++++++++++++ src/inc-lib-variants.php | 2 +- src/scripts/fix_variant_descriptions.php | 4 ++-- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 940b9bef..cf98fe98 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -53,7 +53,7 @@ // If the variant is HGVS, we set the HGVS check to a 'check'. -if (lovd_getVariantInfo($sVariant, false, true)) { +if (lovd_isHGVS($sVariant)) { exit(' var oInput = $(\'input[name$="' . $sName . '"]\'); oInput.siblings("img:first").attr({src: "gfx/check.png"}).show(); @@ -103,7 +103,7 @@ } if ($sFixedVariant !== $sVariant - && lovd_getVariantInfo($sFixedVariant, false, true)) { + && lovd_isHGVS($sFixedVariant)) { $sResponse .= 'Did you mean \"' . $sFixedVariant . '\"?
'; $sButtons = 'oButtonYes, oButtonNo'; diff --git a/src/inc-lib-init.php b/src/inc-lib-init.php index 4ce2df66..fc1599e4 100644 --- a/src/inc-lib-init.php +++ b/src/inc-lib-init.php @@ -1099,6 +1099,8 @@ function lovd_getVariantInfo ($sVariant, $sTranscriptID = '', $bCheckHGVS = fals // function to just check if the variant is HGVS or not. It will in this // case be more stringent than the function normally is, checking the // variant further in details, but it will only return a boolean value. + // When using this function to do a HGVS check ($bCheckHGVS=true), please + // use the wrapper lovd_isHGVS to increase readability. global $_DB; static $aTranscriptOffsets = array(); @@ -1836,6 +1838,18 @@ function lovd_isColleagueOfOwner ($sType, $Data, $bMustHaveEditPermission = true +function lovd_isHGVS($sVariant) +{ + // This wrapper calls the HGVS check functionality of lovd_getVariantInfo. + // To increase readability, please use this function rather than a direct + // call to getVariantInfo when checking the HGVS of a variant. + return lovd_getVariantInfo($sVariant, false, true); +} + + + + + function lovd_isOwner ($sType, $Data) { // Checks if the current user (specified by global $_AUTH) is owner of the diff --git a/src/inc-lib-variants.php b/src/inc-lib-variants.php index 5cdabf4d..606f01d1 100644 --- a/src/inc-lib-variants.php +++ b/src/inc-lib-variants.php @@ -50,7 +50,7 @@ function lovd_fixHGVS ($sVariant, $sType = 'g') } // Do a quick HGVS check. - if (lovd_getVariantInfo($sVariant, '', true)) { + if (lovd_isHGVS($sVariant)) { // All good! return $sVariant; } diff --git a/src/scripts/fix_variant_descriptions.php b/src/scripts/fix_variant_descriptions.php index f9bc1ea0..4523434f 100644 --- a/src/scripts/fix_variant_descriptions.php +++ b/src/scripts/fix_variant_descriptions.php @@ -549,7 +549,7 @@ function ($sVOT) } elseif ($aVOT['RNA'] == str_replace('?', '', $aVVVot['data']['RNA']) || (strpos($aVOT['RNA'], 'spl') !== false && preg_match('/[0-9]+[+-][0-9]+/', $aVVVot['data']['DNA']))) { // We ignore small differences, where maybe the RNA has been verified. - } elseif (lovd_getVariantInfo(lovd_fixHGVS('c' . strstr($aVOT['RNA'], '.'), 'c'), '', true) + } elseif (lovd_isHGVS(lovd_fixHGVS('c' . strstr($aVOT['RNA'], '.'), 'c')) || preg_match('/^r\.\[[0-9]+/', $aVOT['RNA'])) { // If the RNA variant looks like a full variant description, // the current value must be better (or at least more @@ -941,7 +941,7 @@ function ($sVOT) } elseif ($aVOT['RNA'] == str_replace('?', '', $aVVVot['data']['RNA']) || (strpos($aVOT['RNA'], 'spl') !== false && preg_match('/[0-9]+[+-][0-9]+/', $aVVVot['data']['DNA']))) { // We ignore small differences, where maybe the RNA has been verified. - } elseif (lovd_getVariantInfo(lovd_fixHGVS('c' . strstr($aVOT['RNA'], '.'), 'c'), '', true) + } elseif (lovd_isHGVS(lovd_fixHGVS('c' . strstr($aVOT['RNA'], '.'), 'c')) || preg_match('/^r\.\[[0-9]+/', $aVOT['RNA'])) { // If the RNA variant looks like a full variant description, // the current value must be better (or at least more From d94faee06d4221b3dd9d8ac24598d3ef8136cddb Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 10 Feb 2022 18:29:02 +0100 Subject: [PATCH 13/95] Add an '@' before the ob_end_flush() --- src/ajax/mobidetails.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ajax/mobidetails.php b/src/ajax/mobidetails.php index 062692e8..00988831 100644 --- a/src/ajax/mobidetails.php +++ b/src/ajax/mobidetails.php @@ -114,7 +114,7 @@ print(' $("#mobidetails_dialog").html("\'Please"); '); - ob_end_flush(); + @ob_end_flush(); flush(); // Now check with MobiDetails. From 2d9c9c7f3afb8383721ae3f4ca08875164cc6add Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 10 Feb 2022 18:31:03 +0100 Subject: [PATCH 14/95] Add 'supported_by_VV' to GBs in --- src/inc-init.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/inc-init.php b/src/inc-init.php index 76118a91..141aef6b 100644 --- a/src/inc-init.php +++ b/src/inc-init.php @@ -360,6 +360,7 @@ 'hg18' => array( 'ncbi_name' => 'Build 36.1', + 'supported_by_VV' => false, // FIXME: This information is also stored in the chromosomes table. // Remove it from here? 'ncbi_sequences' => @@ -394,6 +395,7 @@ 'hg19' => array( 'ncbi_name' => 'GRCh37', + 'supported_by_VV' => true, // FIXME: This information is also stored in the chromosomes table. // Remove it from here? 'ncbi_sequences' => @@ -429,6 +431,7 @@ 'hg38' => array( 'ncbi_name' => 'GRCh38', + 'supported_by_VV' => true, // FIXME: This information is also stored in the chromosomes table. // Remove it from here? 'ncbi_sequences' => From b1ccf66e78b07f8ff48068dbcf0b3e2d20d02a9e Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 10 Feb 2022 18:32:33 +0100 Subject: [PATCH 15/95] Fix spelling --- src/class/variant_validator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/variant_validator.php b/src/class/variant_validator.php index 12f71173..2247ac8b 100644 --- a/src/class/variant_validator.php +++ b/src/class/variant_validator.php @@ -882,7 +882,7 @@ public function verifyVariant ($sVariant, $aOptions = array()) // NM, we end up with only one NM here. $aJSON = current($aJSON); - // Add a warning in case we submitted a intronic variant while not + // Add a warning in case we submitted an intronic variant while not // using an NC reference sequence. if (preg_match('/^N[MR]_.+[0-9]+[+-][0-9]+/', $sVariant)) { $aData['warnings']['WINTRONICWITHOUTNC'] = 'Without using a genomic reference sequence, intronic bases can not be verified.' . From e0b4d908b7ee2f7f3bb0bb580aa4173754f867c7 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 10 Feb 2022 18:34:34 +0100 Subject: [PATCH 16/95] WIP: Redoing the mapping and validation through VV This large commit stores the outlines of the approach on how to open the dialogue, perform tests, do the mapping and make sure only validated variants are passed onto the database. --- src/ajax/check_hgvs_dialogue.php | 528 +++++++++++++++++++++++++++---- src/inc-js-variants.php | 32 +- 2 files changed, 501 insertions(+), 59 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index cf98fe98..69266870 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -33,102 +33,522 @@ require ROOT_PATH . 'inc-lib-variants.php'; header('Content-type: text/javascript; charset=UTF-8'); -// TODO: All spots where $sTranscriptID is set to false -> check. -// TODO: Maak call naar ander script dat protein/RNA changes toevoegt. -// URL: /ajax/check_hgvs_dialogue.php/variant=g.1del +// Fixme; Add to buttonOKValid and buttonOKCouldBeValid: mp5 translation of all input. +// Getting all variables from the URL. +$sVariant = htmlspecialchars($_REQUEST['var']); +$sFieldName = htmlspecialchars($_REQUEST['fieldName']); +$sRefSeqInfo = htmlspecialchars($_REQUEST['refSeqInfo']); +$aTranscripts = explode('|', htmlspecialchars($_REQUEST['transcripts'])); +$aActiveGBs = $_DB->query('SELECT column_suffix, id FROM ' . TABLE_GENOME_BUILDS)->fetchAllCombine(); -$sVariant = $_REQUEST['var']; -$sName = $_REQUEST['name']; - -// If the variant is empty, we want to set the HGVS check to neutral. -if (!$_REQUEST['var']) { - exit(' - var oInput = $(\'input[name$="' . $sName . '"]\'); +// If the variant is empty, we want to reset all results of this script. +if (!$sVariant) { + print(' + // Resetting all values. + var oInput = $(\'input[name$="' . $sFieldName . '"]\'); oInput.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); + '); // TODO: Remove the mp5 translated variant from the HTML. + + // Returning the mapping for transcript, RNA and protein variants. + foreach($aTranscripts as $sTranscript) { + print(' + var oTranscriptField = $("input").filter(function() { + return $(this).data("id_ncbi") == "' . $sTranscript . '" + }); + oTranscriptField.val(""); + var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); + '); + } + + // Returning the mapping for genomic variants. + foreach($aActiveGBs as $sGBSuffix => $sGBID) { + print(' + var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix? '' : '/' . $sGBSuffix) . '"]\'); + oGenomicVariant.val(""); + '); + } + + // Closing the script. + exit(); } -// If the variant is HGVS, we set the HGVS check to a 'check'. -if (lovd_isHGVS($sVariant)) { - exit(' - var oInput = $(\'input[name$="' . $sName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/check.png"}).show(); + + +// Create a PHP function to easily update the dialogue. +function update_dialogue($sText, $aButtons = array()) +{ + // This function fills the variantCheckDialogue with the given + // text, adds the right buttons and sends it to the user. + print(' + // Updating the contents. + $("#variantCheckDialogue").html("' . $sText . '"); '); + + print(($aButtons? ' + // Placing the buttons. + $("#variantCheckDialogue").dialog({buttons: $.extend({}, ' . implode(', ', $aButtons) . ')}); + ' : ' + // Removing buttons. + $("#variantCheckDialogue").dialog({buttons: {}}); + ')); + + // Sending the contents directly to the user. + flush(); } +// And a function to easily append to the dialogue. +function append_to_dialogue($sText) +{ + // This function fills the variantCheckDialogue with the given + // text, adds the right buttons and sends it to the user. + print(' + // Updating the contents. + $("#variantCheckDialogue").append("' . $sText . '"); + '); + + // Sending the contents directly to the user. + flush(); +} + -// Retrieving information and fixes on the variant. -$aVariant = lovd_getVariantInfo($sVariant, false); -// To use after updating getVariantInfo: -// $aVariantIssues = ($aVariant === false? array() : array_merge($aVariant['errors'], $aVariant['warnings'])); -$aVariant = ($aVariant === false? array() : $aVariant['warnings']); -$sFixedVariant = lovd_fixHGVS($sVariant); // Preparing the buttons. +$sButtonYes = 'oButtonYes'; +$sButtonNo = 'oButtonNo'; +$sButtonOKValid = 'oButtonOKValid'; +$sButtonOKInvalid = 'oButtonOKInvalid'; +$sButtonOKCouldBeValid = 'oButtonOKCouldBeValid'; + + + + + +// Opening the dialogue. +print(' +// Setting up the dialogue. +$("body").append("
"); +$("#variantCheckDialogue").dialog({ + draggable:true,resizable:false,minWidth:600,show:"fade",closeOnEscape:false,hide:"fade",modal:true, + open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); } +}); + +// Notifying user of what is happening. +$("#variantCheckDialogue").html("Performing initial checks..."); +'); + +// Ending the output buffering and sending the dialogue directly to the user. +@ob_end_flush(); +flush(); + print(' // Preparing the buttons. -var oButtonYes = {"Yes":function () { - var oInput = $(\'input[name$="' . $sName . '"]\'); - oInput.val("' . $sFixedVariant . '"); - oInput.siblings("img:first").attr({src: "gfx/check.png"}).show(); +var ' . $sButtonYes . ' = {"Yes":function () { + // The user accepts the given fixed variant. + // We will fill in this fixed variant, close the dialogue, + // and perform a new call to this script by activating + // the onChange. + var oInput = $(\'input[name$="' . $sFieldName . '"]\'); + oInput.val("' . lovd_fixHGVS($sVariant) . '"); $(this).dialog("close"); + oInput.change(); }}; -var oButtonNo = {"No, I will take a look myself":function () { - var oInput = $(\'input[name$="' . $sName . '"]\'); +var ' . $sButtonNo . ' = {"No, I will take a look myself":function () { + // The user does not accept the given fixed variant. + var oInput = $(\'input[name$="' . $sFieldName . '"]\'); oInput.siblings("img:first").attr({src: "gfx/cross.png"}).show(); $(this).dialog("close"); }}; -var oButtonOK = {"OK":function () { - var oInput = $(\'input[name$="' . $sName . '"]\'); +var ' . $sButtonOKValid . ' = {"OK":function () { + // The variant was mapped and looks just great! + var oInput = $(\'input[name$="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/check.png"}).show(); + $(this).dialog("close"); +}}; +var ' . $sButtonOKInvalid . ' = {"OK":function () { + // The user agrees to change its invalid input manually. + var oInput = $(\'input[name$="' . $sFieldName . '"]\'); oInput.siblings("img:first").attr({src: "gfx/cross.png"}).show(); $(this).dialog("close"); }}; +var ' . $sButtonOKCouldBeValid . ' = {"OK":function () { + // We could not validate this variant, but the problem lies with us. + // We will accept this variant and the uncertainty that comes with it. + var oInput = $(\'input[name$="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/check_orange.png"}).show(); + $(this).dialog("close"); +}}; '); -// Preparing the dialogue's contents and buttons. -$sResponse = 'Your variant (\"' . $sVariant . '\") did not pass our HGVS check.

'; -if (!empty($aVariantIssues)) { - $sResponse .= 'We found the following problems:
- '; - $sResponse .= implode('
-', $aVariantIssues) . '

'; + +// Check whether this variant is supported by LOVD. +$aVariant = lovd_getVariantInfo($sVariant, false); +$bIsSupportedByLOVD = !isset($aVariant['errors']['ENOTSUPPORTED']); + +if (!$bIsSupportedByLOVD) { + // If the variant is not supported by LOVD, we cannot perform an HGVS check nor the mapping. + // We will notify the user and end the script here. + + update_dialogue( + 'Your variant contains syntax which our HGVS check cannot recognise. ' . + 'Therefore, we cannot validate your variant nor map it to other reference sequences. ' . + 'Please thoroughly validate your variant by hand.', + array($sButtonOKCouldBeValid)); + exit(); +} + + + + + +// Perform our HGVS check. +if (!lovd_isHGVS($sVariant)) { + // If the variant is not HGVS, we cannot send the variant to + // VariantValidator yet. We will try to see if our fixHGVS + // function knows what to do, but if not, we need to exit + // this script and wait for the user to return with a variant + // which we can interpret. + + // Let the user know that the given variant did not pass our HGVS check. + $sResponse = 'Your variant (\"' . $sVariant . '\") did not pass our HGVS check.

'; + + + // Show the user the warnings and errors we found through getVariantInfo. + $aVariantIssues = ($aVariant === false? array() : array_merge(array_values($aVariant['errors']), array_values($aVariant['warnings']))); + + if (!empty($aVariantIssues)) { + $sResponse .= 'We found the following problems:
- '; + $sResponse .= implode('
-', $aVariantIssues) . '

'; + } + + + // Show the fixed variant if fixHGVS was successful. + $sFixedVariant = lovd_fixHGVS($sVariant); + + if ($sFixedVariant !== $sVariant && lovd_isHGVS($sFixedVariant)) { + // Good, we can propose a fix. If the user agrees with the fix, + // we can continue to the mapping. + update_dialogue($sResponse . 'Did you mean \"' . $sFixedVariant . '\"?
', + array($sButtonYes, $sButtonNo)); + + // Our 'Yes' button sets the steps in motion which change the user's + // input into the fixed variant, and reactivates the dialogue. + // It is then started from the top. We can thus exit the script here. + exit(); + + } else { + // We could not propose a fix. We will end the script. + update_dialogue($sResponse . 'Please check your variant for errors and try again.
', + array($sButtonOKInvalid)); + exit(); + } +} + +// Passed the HGVS check. Inform the user. +update_dialogue('Your variant passed our HGVS syntax check.'); + + + + + +// Check whether VariantValidator supports the syntax of the variant. +$bIsSupportedByVV = + !(isset($aVariant['warnings']['WNOTSUPPORTED']) + || isset($aVariant['messages']['IUNCERTAINPOSITIONS']) + || isset($aVariant['messages']['IPOSTIONRANGE'])); + +if (!$bIsSupportedByVV) { + // If syntax was found which VariantValidator does not support, we + // cannot send the variant in for mapping. We will notify the + // user of this and exit this script. + update_dialogue('Your variant contains syntax which VariantValidator cannot recognise. ' . + 'Therefore, we cannot map your variant nor validate the positions.', + array($sButtonOKCouldBeValid)); + exit(); +} + + + + + +// Prepare the call to VariantValidator to validate the variant. +update_dialogue('Preparing the mapping...'); + +// Retrieve the reference sequence from the info given through the URL. +if (strpos($sRefSeqInfo, '-') === false) { + // The hashtag serves as our little communication tool; it tells + // us that the given input was a GB suffix. When no hashtag was + // found, we know that the input was the reference sequence of + // a transcript. + $sType = 'VOT'; + $sReferenceSequence = $sRefSeqInfo; + +} else { + // We know we got information on a GB. This is given through + // JS in the format of #. + $sType = 'VOG'; + list($sCurrentGBSuffix, $sChromosome) = explode('-', $sRefSeqInfo); + + if (!$_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['supported_by_VV']) { + // If the given genome build is not supported by VV, we cannot fully validate + // the variants... We will have to accept these variants into the database + // anyway, since this issue lies with us. Fixme; Is this true though? Do we want to accept these variants? + update_dialogue( + 'This genome build is not supported for mapping or validation.' . + ' Please start the mapping with a transcript ' . (count($aActiveGBs) > 1 ? '' : 'or a different genome build') . '.', + array($sButtonOKValid)); + exit(); + } + + if (!isset($_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome])) { + // The combination of chromosome and build is not known by LOVD. + // Something probably went wrong on the user's end. We will inform + // the user and exit the script. + update_dialogue( + 'An unknown combination of genome build and chromosome was given.' . + ' This means we cannot perform the mapping. Please try again later.', + array($sButtonOKInvalid)); + exit(); + } + + $sReferenceSequence = $_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome]; } -if ($sFixedVariant !== $sVariant - && lovd_isHGVS($sFixedVariant)) { - $sResponse .= 'Did you mean \"' . $sFixedVariant . '\"?
'; - $sButtons = 'oButtonYes, oButtonNo'; + +// Check if the description itself holds a reference sequence. +// if (lovd_holdsRefSeq($sVariant)) { Fixme; Update line below with this line once the necessary code has been pulled in -> Committed in feat/checkHGVSTool on January 14th 2022; ID 7abf9d70dc3094f5f9cfa0dfc43039c49b4217ff. +if (preg_match('/.*:[a-z]\./', $sVariant)) { + // The given variant description holds a reference sequence. + $sRefSeqInDescription = substr($sVariant, 0, strpos($sVariant, ':')); + + if ($sRefSeqInDescription == $sReferenceSequence) { + // Perfect, no issues found; the user redundantly gave + // the reference sequence in the variant description, + // but that is no problem at all, since the given + // refSeq matches our expectations. + $sFullVariant = $sVariant; + + } else { + // The user gave a refSeq within the variant description + // input which does not match our expectations. The variant + // is then likely to be wrong. We cannot accept it. + update_dialogue( + 'The reference sequence given in the input description, does not equal the' . + ' reference sequence matched to the variant automatically by LOVD. Please have' . + ' another look and perhaps try again from a different input field.', + array($sButtonOKInvalid)); + exit(); + } } else { - $sResponse .= 'Please check your variant for errors and try again.
'; - $sButtons = 'oButtonOK'; + // The given variant does not hold a reference sequence. + $sFullVariant = $sReferenceSequence . ':' . $sVariant; } -// Printing the dialogue. -print(' -// Setting up the dialogue. -$("body").append("
"); -$("#variantCheckDialogue").dialog({ - draggable:false,resizable:false,minWidth:600,show:"fade",closeOnEscape:false,hide:"fade",modal:true, - open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); } -}); -// Placing the contents. -$("#variantCheckDialogue").html("' . $sResponse . '"); +// Call VariantValidator. +append_to_dialogue('
' . $sFullVariant . ' is ready.

Mapping the variant...'); + +require ROOT_PATH . 'class/variant_validator.php'; +$_VV = new LOVD_VV(); +$aMappedVariant = ( + $sType == 'VOG'? + $_VV->verifyGenomic($sFullVariant, array( + 'map_to_transcripts' => true, // Should we map the variant to transcripts? + 'predict_protein' => true, // Should we get protein predictions? + 'lift_over' => (count($aActiveGBs) > 1), // Should we get other genomic mappings of this variant? + 'select_transcripts' => $aTranscripts, // Should we limit our output to only a certain set of transcripts? + )) : + $_VV->verifyVariant($sFullVariant, array('select_transcripts' => $aTranscripts)) +); + + + + + +// Check if VariantValidator bumped into any issues. +if (!empty($aMappedVariant['errors'])) { + // The variant holds a fatal issue. We will exit the script and not + // accept this variant into the database. + + update_dialogue( + 'We could not valide nor map your variant because of the following problem(s):
- ' . + implode('
-', $aMappedVariant['errors']) . '

' . + 'Please take another look at your variant and try again.', + array($sButtonOKInvalid)); + + exit(); +} + +// Check for warnings. +if (!empty($aMappedVariant['warnings'])) { + // One or more warnings were found. Perhaps the variant was corrected? + + if (isset($aMappedVariant['warnings']['WROLLBACK']) + || isset($aMappedVariant['warnings']['WCORRECTED'])) { + // The variant was corrected. + append_to_dialogue('Your variant was corrected to ' . $aMappedVariant['data']['DNA'] . + ' to fully match HGVS guidelines.'); + $bImprovedByVV = true; + } + + if (isset($aMappedVariant['warnings']['WFLAG'])) { + // This type of warning tells us that VariantValidator had a problem + // which is an issue with them, not us nor our user. We can only get + // the mapping on all genome builds, not on (other) transcripts. + // We will notify the user. + append_to_dialogue('Your variant could not be fully validated due to unknown issues.'); + // Fixme; Either find a fix within VV, or Call Mutalyzer. + } + +// Check whether the mapping was successful. +} elseif (!isset($aMappedVariant['data']['DNA']) + || empty($aMappedVariant['data']['DNA'])) { + // Although we did not receive any warnings or errors, the DNA field + // is left empty. This means we have no information on the mapping + // and there is not much we can do... We will inform the user that + // an unknown error occurred and that they should try again later. + update_dialogue( + 'An unknown error occurred while trying to validate and map your variant.' . + ' We are sorry for the inconvenience. Please try again later.', + array($sButtonOKInvalid)); + + exit(); +} + + + + + +// When sending in a variant on transcript, VariantValidator only +// returns the variant as mapped on that one transcript. If we are +// on a VOT creation form, and there are multiple transcripts open, +// we want each transcript to get a mapping. To get this, we then +// need to call VariantValidator a second time using one of the +// genomic variant as were returned using our first call. +if ($sType == 'VOT' && count($aTranscripts) > 1) { + + $aMappedViaGB = ( + !isset($aMappedVariant['data']['genomic_mappings']['hg38'])? // Yes=We have a genomic reference from our first call; No=We don't have a genomic reference. + array() : + $_VV->verifyGenomic($aMappedVariant['data']['genomic_mappings']['hg38'], array( + 'map_to_transcripts' => true, // Should we map the variant to transcripts? + 'predict_protein' => true, // Should we get protein predictions? + 'lift_over' => true, // Should we get other genomic mappings of this variant? + 'select_transcripts' => $aTranscripts, // Should we limit our output to only a certain set of transcripts? + )) + ); + + if (!isset($aMappedViaGB['data']['transcript_mappings'])) { + // If for any reason no genomic mappings were given, we cannot perform this + // extra step, and will thus miss some information. We will inform the user. + append_to_dialogue('Your variant could not be mapped to all transcripts due to unknown issues.'); + } + + $aMappedVariant['data']['transcript_mappings'] = $aMappedViaGB['data']['transcript_mappings']; + + unset($aMappedViaGB); // We don't need the rest of this information. +} + + + + + +// Add mapping information to the right fields. + +// Returning the mapping for transcript, RNA and protein variants. +foreach($aTranscripts as $sTranscript) { + $aTranscriptData = ($sTranscript == $sReferenceSequence? + $aMappedVariant['data'] : + (isset($aMappedVariant['data']['transcript_mappings'][$sTranscript])? + $aMappedVariant['data']['transcript_mappings'][$sTranscript] : + array('DNA' => 'not_mapped', 'RNA' => 'not_mapped', 'protein' => 'not_mapped') + ) + ); + print(' + var oTranscriptField = $("input").filter(function() { + return $(this).data("id_ncbi") == "' . $sTranscript . '" + }); + oTranscriptField.val("' . $aTranscriptData['DNA'] . '"); + var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '"); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '"); + '); +} + +// Returning the mapping for genomic variants. +foreach($aActiveGBs as $sGBSuffix => $sGBID) { + if (!$_SETT['human_builds'][$sGBID]['supported_by_VV']) { + // If a genome build is active which is not supported by VV, we won't have + // received mapping information on it. We will send a 'not_mapped' message. + $sMappedGenomicVariant = 'not_mapped'; + + } else { + // The genome build is supported by VV and we are thus good to go. + + if (isset($sCurrentGBSuffix) && $sGBSuffix == $sCurrentGBSuffix) { + // The current GB is the GB which is the direct reference of our input variant. + // When this is the case, our output is already perfectly formatted as a string. + $sMappedGenomicVariant = $aMappedVariant['data']['DNA']; + + } elseif ($sType == 'VOT') { + // When VV was called using a variant on transcript, we always + // get only one possible mapping. It is thus formatted as a string. + $sMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; + + } else { + // Our output is formatted as an array. + $aMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; + + if (count($aMappedGenomicVariant) <= 1) { + // Only one variant was found. Great! We don't have to do anything. + $sMappedGenomicVariant = $aMappedGenomicVariant[0]; + + } else { + // Multiple possible genomic variants were found. We now need to + // concatenate them cleanly. We will do this as follows: + // NC_1233456.1:g.1del + NC_123456.1:g.2_3del + NC_123456.1:g.4del = NC_123456.1:g.1del^2_3del^4del. + // We'll also give the user a heads-up. + append_to_dialogue('There were multiple genomic variant predictions for build ' . $sGBID . '.'); + + $sMappedGenomicVariant = + preg_replace('/(.*:[a-z]\.).*/', '', $aMappedGenomicVariant[0]) . + implode('^', + array_map(function ($sFullVariant) { + return preg_replace('/.*:[a-z]\./', '', $sFullVariant); + }, $aMappedGenomicVariant) + ); + } + } + } + + print(' + var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix? '' : '/' . $sGBSuffix) . '"]\'); + oGenomicVariant.val("' . $sMappedGenomicVariant . '"); + '); +} + + + -// Placing the buttons. -$("#variantCheckDialogue").dialog({buttons: $.extend({}, ' . $sButtons . ')}); -'); +// Send final message to the user. +update_dialogue( + 'Your variant was successfully mapped' . (!isset($bImprovedByVV)? '' : ', improved') . + ' and validated by VariantValidator. Thank you for your patience!', + array($sButtonOKValid)); ?> diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index e4a94970..c4ee3438 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -165,9 +165,31 @@ // Checking the input variant. function lovd_checkHGVS(e) { var sVariant = $(this).val(); - var sName = $(this).attr("name"); - $.get("ajax/check_hgvs_dialogue.php?var=" + encodeURIComponent(sVariant) + "&name=" + encodeURIComponent(sName)) - .fail(function(){alert("Error checking your variant, please try again later.");}); + var sFieldName = $(this).attr("name"); + var oChromosome = $('select[name="chromosome"]'); + var sChromosome = ( + oChromosome.length ? // Yes=VOG form; No=VOT form. + oChromosome.val() : + $("td:contains('Chromosome')").last().filter(function () { + return $(this).html() === "Chromosome"; + }).siblings().eq(1).html() + ); + var sRefSeqInfo = ( + sFieldName[0] !== 'V'? // Yes=RefSeq is a transcript; No=RefSeq is genomic. + $(this).data('id_ncbi') : + sFieldName.substring(sFieldName.indexOf('DNA') + 3).replace(/\//, '') + '-' + sChromosome + ); + var sTranscripts = $($('#variantForm input[name$="_VariantOnTranscript/DNA"]')).map(function(){ + return $(this).data('id_ncbi'); + }).get().join('|'); + + $.get("ajax/check_hgvs_dialogue.php?" + + "var=" + encodeURIComponent(sVariant) + + "&fieldName=" + encodeURIComponent(sFieldName) + + "&refSeqInfo=" + encodeURIComponent(sRefSeqInfo) + + "&transcripts=" + encodeURIComponent(sTranscripts)) + // .fail(function(){alert("Error checking your variant, please try again later.");}) + ; } @@ -258,7 +280,7 @@ function(sData) { for (i = 0; i < nVariants; i++) { var aVariant = /^([A-Z]{2}_\d{6,9}\.\d{1,2}(?:\([A-Z0-9]+_v\d{3}\))?):([cn]\..+)$/.exec(aVariants[i]); if (aVariant != null) { - var oInput = $('#variantForm input[id_ncbi="' + aVariant[1] + '"]'); + var oInput = $('#variantForm input[data-id_ncbi="' + aVariant[1] + '"]'); if (oInput[0] != undefined) { // If the transcript returned by mutalyzer is present in the form, fill in the respons from mutalyzer. oInput.val(aVariant[2]); @@ -540,7 +562,7 @@ function lovd_highlightInput (oElement) var nTranscriptVariants = oTranscriptVariants.size(); for (i=0; i < nTranscriptVariants; i++) { // Add an artificial attribute "id_ncbi" to the transcripts DNA input field. This is needed to link the response from Mutalyzer to this field, if needed. - $(oTranscriptVariants[i]).attr('id_ncbi', aTranscripts[$(oTranscriptVariants[i]).attr('name').substring(0, )][0]); + $(oTranscriptVariants[i]).data('id_ncbi', aTranscripts[$(oTranscriptVariants[i]).attr('name').substring(0, )][0]); } // Add an onChange event that runs lovd_checkHGVS. oTranscriptVariants.change(lovd_checkHGVS); From 63e05e5d6a45b721b5626fd342b89edfef8ca792 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Mon, 21 Feb 2022 14:34:30 +0100 Subject: [PATCH 17/95] Simplify and clean up code; shorten the output To sum, this commit: - simplifies and cleans up parts of the code; - reduces the amount of output sent to the user, by using images instead of sentences to update the user on the status of the steps; - makes sure the form receives images to communicate status updates as well, and blocks all options that should be blocked after some input fields have been automatically filled. --- src/ajax/check_hgvs_dialogue.php | 331 +++++++++++++++++-------------- src/inc-js-variants.php | 14 +- 2 files changed, 193 insertions(+), 152 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 69266870..d4e283d4 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -58,6 +58,8 @@ return $(this).data("id_ncbi") == "' . $sTranscript . '" }); oTranscriptField.val(""); + oTranscriptField.prop("disabled", false); + oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); @@ -69,6 +71,8 @@ print(' var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix? '' : '/' . $sGBSuffix) . '"]\'); oGenomicVariant.val(""); + oGenomicVariant.prop("disabled", false); + oGenomicVariant.siblings("img:first").attr({src: "gfx/trans.png"}).show(); '); } @@ -81,18 +85,23 @@ // Create a PHP function to easily update the dialogue. -function update_dialogue($sText, $aButtons = array()) +function update_dialogue($sText, $sButtons='', $bCleanSlate=false) { // This function fills the variantCheckDialogue with the given // text, adds the right buttons and sends it to the user. - print(' + // If $bCleanSlate, it will remove the old text and start over; + // if !$bCleanSlate, it will append. + print(($bCleanSlate? ' // Updating the contents. - $("#variantCheckDialogue").html("' . $sText . '"); - '); + $("#variantCheckDialogue").html("' . $sText . '

"); + ' : ' + // Appending to the contents. + $("#variantCheckDialogue").append("' . $sText . '

"); + ')); - print(($aButtons? ' + print(($sButtons? ' // Placing the buttons. - $("#variantCheckDialogue").dialog({buttons: $.extend({}, ' . implode(', ', $aButtons) . ')}); + $("#variantCheckDialogue").dialog({buttons: $.extend({}, ' . $sButtons . ')}); ' : ' // Removing buttons. $("#variantCheckDialogue").dialog({buttons: {}}); @@ -103,23 +112,26 @@ function update_dialogue($sText, $aButtons = array()) } -// And a function to easily append to the dialogue. -function append_to_dialogue($sText) -{ - // This function fills the variantCheckDialogue with the given - // text, adds the right buttons and sends it to the user. - print(' - // Updating the contents. - $("#variantCheckDialogue").append("' . $sText . '"); - '); - - // Sending the contents directly to the user. - flush(); +// Create a PHP function to easily update the images to the left of each step. +function update_images_per_step ($nStep, $sImage) { + // This function takes a step in the format of an integer, and + // replaces the image which was put next to this step by the + // given $sImage. + print('$("#' . $nStep . '").attr({src: "' . $sImage . '"});'); } +// Preparing the steps. +$sStepInitialChecks = 'statusChecks'; +$sStepMapping = 'statusMapping'; + +// Preparing the images. +$sImageNeutral = 'gfx/trans.png'; +$sImagePassed = 'gfx/check.png'; +$sImageFailed = 'gfx/cross.png'; +$sImageLoading = 'gfx/lovd_loading.gif'; // Preparing the buttons. $sButtonYes = 'oButtonYes'; @@ -128,27 +140,7 @@ function append_to_dialogue($sText) $sButtonOKInvalid = 'oButtonOKInvalid'; $sButtonOKCouldBeValid = 'oButtonOKCouldBeValid'; - - - - -// Opening the dialogue. -print(' -// Setting up the dialogue. -$("body").append("
"); -$("#variantCheckDialogue").dialog({ - draggable:true,resizable:false,minWidth:600,show:"fade",closeOnEscape:false,hide:"fade",modal:true, - open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); } -}); - -// Notifying user of what is happening. -$("#variantCheckDialogue").html("Performing initial checks..."); -'); - -// Ending the output buffering and sending the dialogue directly to the user. -@ob_end_flush(); -flush(); - +// Preparing the JS for the buttons. print(' // Preparing the buttons. var ' . $sButtonYes . ' = {"Yes":function () { @@ -156,40 +148,63 @@ function append_to_dialogue($sText) // We will fill in this fixed variant, close the dialogue, // and perform a new call to this script by activating // the onChange. - var oInput = $(\'input[name$="' . $sFieldName . '"]\'); + var oInput = $(\'input[name="' . $sFieldName . '"]\'); oInput.val("' . lovd_fixHGVS($sVariant) . '"); $(this).dialog("close"); oInput.change(); }}; var ' . $sButtonNo . ' = {"No, I will take a look myself":function () { // The user does not accept the given fixed variant. - var oInput = $(\'input[name$="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/cross.png"}).show(); + var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/cross.png", title: "Please check the HGVS syntax of your variant description before sending it into the database."}).show(); $(this).dialog("close"); }}; var ' . $sButtonOKValid . ' = {"OK":function () { // The variant was mapped and looks just great! - var oInput = $(\'input[name$="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/check.png"}).show(); + // All steps have already been taken; the only + // thing left to do is to close the dialogue. $(this).dialog("close"); }}; var ' . $sButtonOKInvalid . ' = {"OK":function () { - // The user agrees to change its invalid input manually. - var oInput = $(\'input[name$="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/cross.png"}).show(); + // The user agrees to change their invalid input manually. + var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/cross.png", title: "Your variant could not be validated..."}).show(); $(this).dialog("close"); }}; var ' . $sButtonOKCouldBeValid . ' = {"OK":function () { - // We could not validate this variant, but the problem lies with us. - // We will accept this variant and the uncertainty that comes with it. - var oInput = $(\'input[name$="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/check_orange.png"}).show(); + // We could not validate this variant, but the problem + // lies with us. We will accept this variant and the + // uncertainty that comes with it. + var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "Your variant could not be (in)validated..."}).show(); $(this).dialog("close"); }}; '); +// Opening the dialogue. +print(' +// Setting up the dialogue. +$("body").append("
"); +$("#variantCheckDialogue").dialog({ + draggable:true,resizable:false,minWidth:600,show:"fade",closeOnEscape:false,hide:"fade",modal:true, + open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); } +}); +'); + +update_dialogue( + ' Performing initial checks.' . + '
Mapping your variant.', + '', + true +); +// Ending the output buffering and sending the dialogue directly to the user. +@ob_end_flush(); +flush(); + + + // Check whether this variant is supported by LOVD. @@ -200,11 +215,12 @@ function append_to_dialogue($sText) // If the variant is not supported by LOVD, we cannot perform an HGVS check nor the mapping. // We will notify the user and end the script here. + update_images_per_step($sStepInitialChecks, $sImageFailed); update_dialogue( 'Your variant contains syntax which our HGVS check cannot recognise. ' . 'Therefore, we cannot validate your variant nor map it to other reference sequences. ' . - 'Please thoroughly validate your variant by hand.', - array($sButtonOKCouldBeValid)); + 'Please thoroughly validate yofur variant by hand.', + $sButtonOKCouldBeValid); exit(); } @@ -222,6 +238,7 @@ function append_to_dialogue($sText) // Let the user know that the given variant did not pass our HGVS check. $sResponse = 'Your variant (\"' . $sVariant . '\") did not pass our HGVS check.

'; + update_images_per_step($sStepInitialChecks, $sImageFailed); // Show the user the warnings and errors we found through getVariantInfo. @@ -240,7 +257,7 @@ function append_to_dialogue($sText) // Good, we can propose a fix. If the user agrees with the fix, // we can continue to the mapping. update_dialogue($sResponse . 'Did you mean \"' . $sFixedVariant . '\"?
', - array($sButtonYes, $sButtonNo)); + $sButtonYes . ', ' . $sButtonNo); // Our 'Yes' button sets the steps in motion which change the user's // input into the fixed variant, and reactivates the dialogue. @@ -250,14 +267,11 @@ function append_to_dialogue($sText) } else { // We could not propose a fix. We will end the script. update_dialogue($sResponse . 'Please check your variant for errors and try again.
', - array($sButtonOKInvalid)); + $sButtonOKInvalid); exit(); } } -// Passed the HGVS check. Inform the user. -update_dialogue('Your variant passed our HGVS syntax check.'); - @@ -271,10 +285,11 @@ function append_to_dialogue($sText) if (!$bIsSupportedByVV) { // If syntax was found which VariantValidator does not support, we // cannot send the variant in for mapping. We will notify the - // user of this and exit this script. + // user and exit this script. + update_images_per_step($sStepInitialChecks, $sImageFailed); update_dialogue('Your variant contains syntax which VariantValidator cannot recognise. ' . 'Therefore, we cannot map your variant nor validate the positions.', - array($sButtonOKCouldBeValid)); + $sButtonOKCouldBeValid); exit(); } @@ -282,43 +297,41 @@ function append_to_dialogue($sText) -// Prepare the call to VariantValidator to validate the variant. -update_dialogue('Preparing the mapping...'); - // Retrieve the reference sequence from the info given through the URL. if (strpos($sRefSeqInfo, '-') === false) { - // The hashtag serves as our little communication tool; it tells - // us that the given input was a GB suffix. When no hashtag was - // found, we know that the input was the reference sequence of - // a transcript. + // The '-' serves as our little communication tool; it tells + // us that the given input was a GB suffix. When no '-' was + // found, we know that the input was the reference sequence + // of a transcript. $sType = 'VOT'; $sReferenceSequence = $sRefSeqInfo; } else { // We know we got information on a GB. This is given through - // JS in the format of #. + // JS in the format of -. $sType = 'VOG'; list($sCurrentGBSuffix, $sChromosome) = explode('-', $sRefSeqInfo); if (!$_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['supported_by_VV']) { // If the given genome build is not supported by VV, we cannot fully validate // the variants... We will have to accept these variants into the database - // anyway, since this issue lies with us. Fixme; Is this true though? Do we want to accept these variants? - update_dialogue( - 'This genome build is not supported for mapping or validation.' . - ' Please start the mapping with a transcript ' . (count($aActiveGBs) > 1 ? '' : 'or a different genome build') . '.', - array($sButtonOKValid)); - exit(); + // anyway, since this issue lies with us. + die(' + $("#variantCheckDialogue").dialog("close"); + var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "We validated the syntax, but could not validate the positions."}).show(); + '); } if (!isset($_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome])) { // The combination of chromosome and build is not known by LOVD. // Something probably went wrong on the user's end. We will inform // the user and exit the script. + update_images_per_step($sStepInitialChecks, $sImageFailed); update_dialogue( 'An unknown combination of genome build and chromosome was given.' . - ' This means we cannot perform the mapping. Please try again later.', - array($sButtonOKInvalid)); + ' This means we cannot perform the mapping.', + $sButtonOKInvalid); exit(); } @@ -343,11 +356,12 @@ function append_to_dialogue($sText) // The user gave a refSeq within the variant description // input which does not match our expectations. The variant // is then likely to be wrong. We cannot accept it. + update_images_per_step($sStepInitialChecks, $sImageFailed); update_dialogue( 'The reference sequence given in the input description, does not equal the' . - ' reference sequence matched to the variant automatically by LOVD. Please have' . + ' reference sequence matched to the variant by LOVD automatically. Please have' . ' another look and perhaps try again from a different input field.', - array($sButtonOKInvalid)); + $sButtonOKInvalid); exit(); } @@ -361,17 +375,18 @@ function append_to_dialogue($sText) // Call VariantValidator. -append_to_dialogue('
' . $sFullVariant . ' is ready.

Mapping the variant...'); +update_images_per_step($sStepInitialChecks, $sImagePassed); +update_images_per_step($sStepMapping, $sImageLoading); require ROOT_PATH . 'class/variant_validator.php'; $_VV = new LOVD_VV(); $aMappedVariant = ( $sType == 'VOG'? $_VV->verifyGenomic($sFullVariant, array( - 'map_to_transcripts' => true, // Should we map the variant to transcripts? - 'predict_protein' => true, // Should we get protein predictions? - 'lift_over' => (count($aActiveGBs) > 1), // Should we get other genomic mappings of this variant? - 'select_transcripts' => $aTranscripts, // Should we limit our output to only a certain set of transcripts? + 'map_to_transcripts' => empty($aTranscript), // Should we map the variant to transcripts? + 'predict_protein' => empty($aTranscript), // Should we get protein predictions? + 'lift_over' => (count($aActiveGBs) > 1), // Should we get other genomic mappings of this variant? + 'select_transcripts' => (empty($aTranscripts)? array() : $aTranscripts), )) : $_VV->verifyVariant($sFullVariant, array('select_transcripts' => $aTranscripts)) ); @@ -385,12 +400,12 @@ function append_to_dialogue($sText) // The variant holds a fatal issue. We will exit the script and not // accept this variant into the database. + update_images_per_step($sStepMapping, $sImageFailed); update_dialogue( 'We could not valide nor map your variant because of the following problem(s):
- ' . implode('
-', $aMappedVariant['errors']) . '

' . 'Please take another look at your variant and try again.', - array($sButtonOKInvalid)); - + $sButtonOKInvalid); exit(); } @@ -401,7 +416,7 @@ function append_to_dialogue($sText) if (isset($aMappedVariant['warnings']['WROLLBACK']) || isset($aMappedVariant['warnings']['WCORRECTED'])) { // The variant was corrected. - append_to_dialogue('Your variant was corrected to ' . $aMappedVariant['data']['DNA'] . + update_dialogue('Your variant was corrected to ' . $aMappedVariant['data']['DNA'] . ' to fully match HGVS guidelines.'); $bImprovedByVV = true; } @@ -411,7 +426,7 @@ function append_to_dialogue($sText) // which is an issue with them, not us nor our user. We can only get // the mapping on all genome builds, not on (other) transcripts. // We will notify the user. - append_to_dialogue('Your variant could not be fully validated due to unknown issues.'); + update_dialogue('Your variant could not fully be validated due to unknown issues.'); // Fixme; Either find a fix within VV, or Call Mutalyzer. } @@ -422,11 +437,11 @@ function append_to_dialogue($sText) // is left empty. This means we have no information on the mapping // and there is not much we can do... We will inform the user that // an unknown error occurred and that they should try again later. + update_images_per_step($sStepMapping, $sImageFailed); update_dialogue( 'An unknown error occurred while trying to validate and map your variant.' . ' We are sorry for the inconvenience. Please try again later.', - array($sButtonOKInvalid)); - + $sButtonOKInvalid); exit(); } @@ -446,9 +461,9 @@ function append_to_dialogue($sText) !isset($aMappedVariant['data']['genomic_mappings']['hg38'])? // Yes=We have a genomic reference from our first call; No=We don't have a genomic reference. array() : $_VV->verifyGenomic($aMappedVariant['data']['genomic_mappings']['hg38'], array( - 'map_to_transcripts' => true, // Should we map the variant to transcripts? - 'predict_protein' => true, // Should we get protein predictions? - 'lift_over' => true, // Should we get other genomic mappings of this variant? + 'map_to_transcripts' => true, // Should we map the variant to transcripts? + 'predict_protein' => true, // Should we get protein predictions? + 'lift_over' => false, // Should we get other genomic mappings of this variant? 'select_transcripts' => $aTranscripts, // Should we limit our output to only a certain set of transcripts? )) ); @@ -456,7 +471,7 @@ function append_to_dialogue($sText) if (!isset($aMappedViaGB['data']['transcript_mappings'])) { // If for any reason no genomic mappings were given, we cannot perform this // extra step, and will thus miss some information. We will inform the user. - append_to_dialogue('Your variant could not be mapped to all transcripts due to unknown issues.'); + update_dialogue('Your variant could not be mapped to all transcripts due to unknown issues.'); } $aMappedVariant['data']['transcript_mappings'] = $aMappedViaGB['data']['transcript_mappings']; @@ -472,83 +487,109 @@ function append_to_dialogue($sText) // Returning the mapping for transcript, RNA and protein variants. foreach($aTranscripts as $sTranscript) { - $aTranscriptData = ($sTranscript == $sReferenceSequence? - $aMappedVariant['data'] : - (isset($aMappedVariant['data']['transcript_mappings'][$sTranscript])? - $aMappedVariant['data']['transcript_mappings'][$sTranscript] : - array('DNA' => 'not_mapped', 'RNA' => 'not_mapped', 'protein' => 'not_mapped') - ) - ); - print(' + if (!isset($aMappedVariant['data']['transcript_mappings'][$sTranscript]) + && $sTranscript != $sReferenceSequence) { + // If no mapping was found for this transcript, we skip it. + continue; + } + // Retrieving the info. + $aTranscriptData = ($sTranscript == $sReferenceSequence? // Yes=Variant of origin (stored directly in data); No=Other (stored in transcript_mappings) + $aMappedVariant['data'] : $aMappedVariant['data']['transcript_mappings'][$sTranscript]); + + // Filling in the input fields. + print(' + // Adding transcript info to the fields. var oTranscriptField = $("input").filter(function() { return $(this).data("id_ncbi") == "' . $sTranscript . '" }); - oTranscriptField.val("' . $aTranscriptData['DNA'] . '"); - var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '"); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '"); - '); + + if (!oTranscriptField.prop("disabled")) { + oTranscriptField.val("' . $aTranscriptData['DNA'] . '"); + oTranscriptField.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); + oTranscriptField.prop("disabled", true); + var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '"); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '"); + }'); } // Returning the mapping for genomic variants. foreach($aActiveGBs as $sGBSuffix => $sGBID) { - if (!$_SETT['human_builds'][$sGBID]['supported_by_VV']) { + if (!$_SETT['human_builds'][$sGBID]['supported_by_VV'] + || !isset($aMappedVariant['data']['genomic_mappings'][$sGBID]) ) { // If a genome build is active which is not supported by VV, we won't have - // received mapping information on it. We will send a 'not_mapped' message. - $sMappedGenomicVariant = 'not_mapped'; + // received mapping information on it. We will skip this variant. + continue; + } + // Retrieving the info. + if ($sType == 'VOT') { + // When VV was called using a variant on transcript, we always + // get only one possible mapping, which is formatted as a string. + $sMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; + + } elseif (isset($sCurrentGBSuffix) && $sGBSuffix == $sCurrentGBSuffix) { + // The current build is the build which is the direct reference of + // our input variant. When this is the case, our output is already + // formatted as a string as well. + $sMappedGenomicVariant = $aMappedVariant['data']['DNA']; } else { - // The genome build is supported by VV and we are thus good to go. + // Our output is formatted as an array, since multiple variants were possible. + $aMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; - if (isset($sCurrentGBSuffix) && $sGBSuffix == $sCurrentGBSuffix) { - // The current GB is the GB which is the direct reference of our input variant. - // When this is the case, our output is already perfectly formatted as a string. - $sMappedGenomicVariant = $aMappedVariant['data']['DNA']; - - } elseif ($sType == 'VOT') { - // When VV was called using a variant on transcript, we always - // get only one possible mapping. It is thus formatted as a string. - $sMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; + if (count($aMappedGenomicVariant) <= 1) { + // Only one variant was found. Great! We can simply take the first element. + $sMappedGenomicVariant = $aMappedGenomicVariant[0]; } else { - // Our output is formatted as an array. - $aMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; - - if (count($aMappedGenomicVariant) <= 1) { - // Only one variant was found. Great! We don't have to do anything. - $sMappedGenomicVariant = $aMappedGenomicVariant[0]; - - } else { - // Multiple possible genomic variants were found. We now need to - // concatenate them cleanly. We will do this as follows: - // NC_1233456.1:g.1del + NC_123456.1:g.2_3del + NC_123456.1:g.4del = NC_123456.1:g.1del^2_3del^4del. - // We'll also give the user a heads-up. - append_to_dialogue('There were multiple genomic variant predictions for build ' . $sGBID . '.'); - - $sMappedGenomicVariant = - preg_replace('/(.*:[a-z]\.).*/', '', $aMappedGenomicVariant[0]) . - implode('^', - array_map(function ($sFullVariant) { - return preg_replace('/.*:[a-z]\./', '', $sFullVariant); - }, $aMappedGenomicVariant) - ); - } + // Multiple possible variants were found. We will give the user a heads-up, + // and concatenate the variants cleanly as follows: + // NC_1233456.1:g.1del + NC_123456.1:g.2_3del + NC_123456.1:g.4del = + // NC_123456.1:g.1del^2_3del^4del. + update_dialogue('There were multiple genomic variant predictions for build ' . $sGBID . '.'); + + $sMappedGenomicVariant = + preg_replace('/(.*:[a-z]\.).*/', '', $aMappedGenomicVariant[0]) . + implode('^', + array_map(function ($sFullVariant) { + return preg_replace('/.*:[a-z]\./', '', $sFullVariant); + }, $aMappedGenomicVariant) + ); } } + // Filling in the input field. print(' - var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix? '' : '/' . $sGBSuffix) . '"]\'); - oGenomicVariant.val("' . $sMappedGenomicVariant . '"); - '); + // Adding genomic info the fields. + var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix? '' : '/' . $sGBSuffix) . '"]\'); + oGenomicVariant.val("' . preg_replace('/.*:/', '', $sMappedGenomicVariant) . '"); + oGenomicVariant.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); + oGenomicVariant.prop("disabled", true); + '); // Fixme; Find a cleaner way of cutting off the reference sequence. } +// Because we automatically filled all non-blocked positions, +// all open transcript fields have been blocked. We don't +// want the user to block the transcript input at this point +// so we disable the 'Ignore this transcript' option. +print(' +// Disabling the "ignore this transcript" option. +var oIgnoreOption = $(\'input[name^="ignore_"]\'); +oIgnoreOption.parent().html(""); +'); + + + + + // Send final message to the user. +update_images_per_step($sStepMapping, $sImagePassed); update_dialogue( 'Your variant was successfully mapped' . (!isset($bImprovedByVV)? '' : ', improved') . ' and validated by VariantValidator. Thank you for your patience!', - array($sButtonOKValid)); + $sButtonOKValid); ?> diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index c4ee3438..c880a221 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -188,7 +188,7 @@ function lovd_checkHGVS(e) { + "&fieldName=" + encodeURIComponent(sFieldName) + "&refSeqInfo=" + encodeURIComponent(sRefSeqInfo) + "&transcripts=" + encodeURIComponent(sTranscripts)) - // .fail(function(){alert("Error checking your variant, please try again later.");}) + .fail(function(){alert("Error checking your variant, please try again later.");}) ; } @@ -549,19 +549,19 @@ function lovd_highlightInput (oElement) $(function () { - var oGenomicVariant = $('#variantForm input[name="VariantOnGenome/DNA"]'); + var oGenomicVariants = $('#variantForm input[name^="VariantOnGenome/DNA"]'); var oTranscriptVariants = $('#variantForm input[name$="_VariantOnTranscript/DNA"]'); // Add the button and image at the end of the genomic DNA field. - oGenomicVariant.parent().append('   '); + oGenomicVariants.parent().append('   '); // Add an onChange event that runs lovd_checkHGVS. - oGenomicVariant.change(lovd_checkHGVS); + oGenomicVariants.change(lovd_checkHGVS); if (oTranscriptVariants[0] != undefined) { // Add the buttons and images at the end of the transcripts DNA fields. - oTranscriptVariants.parent().append('   '); + oTranscriptVariants.parent().append('   '); var nTranscriptVariants = oTranscriptVariants.size(); for (i=0; i < nTranscriptVariants; i++) { - // Add an artificial attribute "id_ncbi" to the transcripts DNA input field. This is needed to link the response from Mutalyzer to this field, if needed. + // Add an artificial attribute "id_ncbi" to the transcripts DNA input field. This is needed to link the response from VariantValidator to this field. $(oTranscriptVariants[i]).data('id_ncbi', aTranscripts[$(oTranscriptVariants[i]).attr('name').substring(0, )][0]); } // Add an onChange event that runs lovd_checkHGVS. @@ -570,7 +570,7 @@ function lovd_highlightInput (oElement) var oProteinVariants = $('#variantForm input[name$="_VariantOnTranscript/Protein"]'); if (oProteinVariants[0] != undefined) { // Add the buttons and images at the end of the protein description fields. - oProteinVariants.parent().append('   '); + oProteinVariants.parent().append('   '); } } }); From fce7fb8e94487a580c0f001d4e7fb2cd280a1da4 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Mon, 21 Feb 2022 17:10:15 +0100 Subject: [PATCH 18/95] Document the fact that flush() does not work here We noticed that flush() actually does not fully make sure the output is immediately shown to the users. Instead, what happens is this: When flush() is being called, the buffered output is duly sent to the browser. However, the browser (at least as tested on Chrome) only starts to execute the sent in code once the script of origin has stopped running. This means that flush() cannot be used to dynamically update the HTML webpage while processes are active on the background. --- src/ajax/mobidetails.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ajax/mobidetails.php b/src/ajax/mobidetails.php index 00988831..a9a5f771 100644 --- a/src/ajax/mobidetails.php +++ b/src/ajax/mobidetails.php @@ -111,6 +111,10 @@ $_SESSION['csrf_tokens']['mobidetails_confirm'] = md5(uniqid()); $sFormConfirmation = str_replace('{{CSRF_TOKEN}}', $_SESSION['csrf_tokens']['mobidetails_confirm'], $sFormConfirmation); + // This print statement and flush do not work. + // It seems that flush successfully forces the output + // to the browser, but the browser does not seem to + // execute the JS until the page has finished loading. (Chrome) print(' $("#mobidetails_dialog").html("\'Please"); '); From d7d5282d552c12ca2a5376ebc9c577446e767a3e Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Wed, 23 Feb 2022 19:15:17 +0100 Subject: [PATCH 19/95] Replaced flush() calls with recursive calls Because we realised that the browser does not execute code that was sent in before the end of the script using flush(), we now use recursive calls instead. This way, we made sure that the user's screen will already show the dialogue, even when the mapping is not done yet. --- src/ajax/check_hgvs_dialogue.php | 775 +++++++++++++++---------------- src/inc-js-variants.php | 3 +- 2 files changed, 387 insertions(+), 391 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index d4e283d4..5503e0f7 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -33,95 +33,15 @@ require ROOT_PATH . 'inc-lib-variants.php'; header('Content-type: text/javascript; charset=UTF-8'); -// Fixme; Add to buttonOKValid and buttonOKCouldBeValid: mp5 translation of all input. -// Getting all variables from the URL. + +// Preparing necessary functions and variables. +// Retrieving the variant and the transcripts and genome builds to map to. $sVariant = htmlspecialchars($_REQUEST['var']); -$sFieldName = htmlspecialchars($_REQUEST['fieldName']); -$sRefSeqInfo = htmlspecialchars($_REQUEST['refSeqInfo']); $aTranscripts = explode('|', htmlspecialchars($_REQUEST['transcripts'])); $aActiveGBs = $_DB->query('SELECT column_suffix, id FROM ' . TABLE_GENOME_BUILDS)->fetchAllCombine(); - - -// If the variant is empty, we want to reset all results of this script. -if (!$sVariant) { - print(' - // Resetting all values. - var oInput = $(\'input[name$="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); // TODO: Remove the mp5 translated variant from the HTML. - - // Returning the mapping for transcript, RNA and protein variants. - foreach($aTranscripts as $sTranscript) { - print(' - var oTranscriptField = $("input").filter(function() { - return $(this).data("id_ncbi") == "' . $sTranscript . '" - }); - oTranscriptField.val(""); - oTranscriptField.prop("disabled", false); - oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); - '); - } - - // Returning the mapping for genomic variants. - foreach($aActiveGBs as $sGBSuffix => $sGBID) { - print(' - var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix? '' : '/' . $sGBSuffix) . '"]\'); - oGenomicVariant.val(""); - oGenomicVariant.prop("disabled", false); - oGenomicVariant.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); - } - - // Closing the script. - exit(); -} - - - - - -// Create a PHP function to easily update the dialogue. -function update_dialogue($sText, $sButtons='', $bCleanSlate=false) -{ - // This function fills the variantCheckDialogue with the given - // text, adds the right buttons and sends it to the user. - // If $bCleanSlate, it will remove the old text and start over; - // if !$bCleanSlate, it will append. - print(($bCleanSlate? ' - // Updating the contents. - $("#variantCheckDialogue").html("' . $sText . '

"); - ' : ' - // Appending to the contents. - $("#variantCheckDialogue").append("' . $sText . '

"); - ')); - - print(($sButtons? ' - // Placing the buttons. - $("#variantCheckDialogue").dialog({buttons: $.extend({}, ' . $sButtons . ')}); - ' : ' - // Removing buttons. - $("#variantCheckDialogue").dialog({buttons: {}}); - ')); - - // Sending the contents directly to the user. - flush(); -} - - -// Create a PHP function to easily update the images to the left of each step. -function update_images_per_step ($nStep, $sImage) { - // This function takes a step in the format of an integer, and - // replaces the image which was put next to this step by the - // given $sImage. - print('$("#' . $nStep . '").attr({src: "' . $sImage . '"});'); -} - - - +// Retrieving the name of the input field. +$sFieldName = htmlspecialchars($_REQUEST['fieldName']); // Preparing the steps. $sStepInitialChecks = 'statusChecks'; @@ -129,8 +49,8 @@ function update_images_per_step ($nStep, $sImage) { // Preparing the images. $sImageNeutral = 'gfx/trans.png'; -$sImagePassed = 'gfx/check.png'; -$sImageFailed = 'gfx/cross.png'; +$sImagePassed = 'gfx/check.png'; +$sImageFailed = 'gfx/cross.png'; $sImageLoading = 'gfx/lovd_loading.gif'; // Preparing the buttons. @@ -141,6 +61,7 @@ function update_images_per_step ($nStep, $sImage) { $sButtonOKCouldBeValid = 'oButtonOKCouldBeValid'; // Preparing the JS for the buttons. +// Fixme; Add to buttonOKValid and buttonOKCouldBeValid: mp5 translation of all input. print(' // Preparing the buttons. var ' . $sButtonYes . ' = {"Yes":function () { @@ -182,283 +103,365 @@ function update_images_per_step ($nStep, $sImage) { '); +// Create a PHP function to easily update the dialogue. +function update_dialogue($sText, $sButtons = '', $bCleanSlate = false) +{ + // This function fills the variantCheckDialogue with the given + // text, adds the right buttons and sends it to the user. + // If $bCleanSlate, it will remove the old text and start over; + // if !$bCleanSlate, it will append. + print(($bCleanSlate ? ' + // Updating the contents. + $("#variantCheckDialogue").html("' . $sText . '

"); + ' : ' + // Appending to the contents. + $("#variantCheckDialogue").append("' . $sText . '

"); + ')); -// Opening the dialogue. -print(' -// Setting up the dialogue. -$("body").append("
"); -$("#variantCheckDialogue").dialog({ - draggable:true,resizable:false,minWidth:600,show:"fade",closeOnEscape:false,hide:"fade",modal:true, - open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); } -}); -'); + print(($sButtons ? ' + // Placing the buttons. + $("#variantCheckDialogue").dialog({buttons: $.extend({}, ' . $sButtons . ')}); + ' : ' + // Removing buttons. + $("#variantCheckDialogue").dialog({buttons: {}}); + ')); -update_dialogue( - ' Performing initial checks.' . - '
Mapping your variant.', - '', - true -); -// Ending the output buffering and sending the dialogue directly to the user. -@ob_end_flush(); -flush(); + // Sending the contents directly to the user. + flush(); +} +// Create a PHP function to easily update the images to the left of each step. +function update_images_per_step($nStep, $sImage) +{ + // This function takes a step in the format of an integer, and + // replaces the image which was put next to this step by the + // given $sImage. + print('$("#' . $nStep . '").attr({src: "' . $sImage . '"});'); +} -// Check whether this variant is supported by LOVD. -$aVariant = lovd_getVariantInfo($sVariant, false); -$bIsSupportedByLOVD = !isset($aVariant['errors']['ENOTSUPPORTED']); -if (!$bIsSupportedByLOVD) { - // If the variant is not supported by LOVD, we cannot perform an HGVS check nor the mapping. - // We will notify the user and end the script here. - update_images_per_step($sStepInitialChecks, $sImageFailed); - update_dialogue( - 'Your variant contains syntax which our HGVS check cannot recognise. ' . - 'Therefore, we cannot validate your variant nor map it to other reference sequences. ' . - 'Please thoroughly validate yofur variant by hand.', - $sButtonOKCouldBeValid); - exit(); -} +// Performing initial checks. +if ($_REQUEST['action'] == 'check') { + // If the variant is empty, we want to reset all results of this script. + if (!$sVariant) { + print(' + // Resetting all values. + var oInput = $(\'input[name$="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + '); // TODO: Remove the mp5 translated variant from the HTML. + + // Returning the mapping for transcript, RNA and protein variants. + foreach ($aTranscripts as $sTranscript) { + print(' + var oTranscriptField = $("input").filter(function() { + return $(this).data("id_ncbi") == "' . $sTranscript . '" + }); + oTranscriptField.val(""); + oTranscriptField.prop("disabled", false); + oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); + '); + } + // Returning the mapping for genomic variants. + foreach ($aActiveGBs as $sGBSuffix => $sGBID) { + print(' + var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); + oGenomicVariant.val(""); + oGenomicVariant.prop("disabled", false); + oGenomicVariant.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + '); + } + // Closing the script. + exit(); + } + // Retrieving information on the reference sequence from the URL. + $sRefSeqInfo = htmlspecialchars($_REQUEST['refSeqInfo']); -// Perform our HGVS check. -if (!lovd_isHGVS($sVariant)) { - // If the variant is not HGVS, we cannot send the variant to - // VariantValidator yet. We will try to see if our fixHGVS - // function knows what to do, but if not, we need to exit - // this script and wait for the user to return with a variant - // which we can interpret. + // Opening the dialogue. + print(' + // Setting up the dialogue. + $("body").append("
"); + $("#variantCheckDialogue").dialog({ + draggable:true,resizable:false,minWidth:600,show:"fade",closeOnEscape:false,hide:"fade",modal:true, + open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); } + }); + '); - // Let the user know that the given variant did not pass our HGVS check. - $sResponse = 'Your variant (\"' . $sVariant . '\") did not pass our HGVS check.

'; - update_images_per_step($sStepInitialChecks, $sImageFailed); + update_dialogue( + ' Performing initial checks.' . + '
Mapping your variant.', + '', + true + ); - // Show the user the warnings and errors we found through getVariantInfo. - $aVariantIssues = ($aVariant === false? array() : array_merge(array_values($aVariant['errors']), array_values($aVariant['warnings']))); + // Check whether this variant is supported by LOVD. + $aVariant = lovd_getVariantInfo($sVariant, false); + $bIsSupportedByLOVD = !isset($aVariant['errors']['ENOTSUPPORTED']); - if (!empty($aVariantIssues)) { - $sResponse .= 'We found the following problems:
- '; - $sResponse .= implode('
-', $aVariantIssues) . '

'; - } + if (!$bIsSupportedByLOVD) { + // If the variant is not supported by LOVD, we cannot perform an HGVS check nor the mapping. + // We will notify the user and end the script here. + update_images_per_step($sStepInitialChecks, $sImageFailed); + update_dialogue( + 'Your variant contains syntax which our HGVS check cannot recognise. ' . + 'Therefore, we cannot validate your variant nor map it to other reference sequences. ' . + 'Please thoroughly validate your variant by hand.', + $sButtonOKCouldBeValid); + exit(); + } - // Show the fixed variant if fixHGVS was successful. - $sFixedVariant = lovd_fixHGVS($sVariant); - if ($sFixedVariant !== $sVariant && lovd_isHGVS($sFixedVariant)) { - // Good, we can propose a fix. If the user agrees with the fix, - // we can continue to the mapping. - update_dialogue($sResponse . 'Did you mean \"' . $sFixedVariant . '\"?
', - $sButtonYes . ', ' . $sButtonNo); + // Perform our HGVS check. + if (!lovd_isHGVS($sVariant)) { + // If the variant is not HGVS, we cannot send the variant to + // VariantValidator yet. We will try to see if our fixHGVS + // function knows what to do, but if not, we need to exit + // this script and wait for the user to return with a variant + // which we can interpret. - // Our 'Yes' button sets the steps in motion which change the user's - // input into the fixed variant, and reactivates the dialogue. - // It is then started from the top. We can thus exit the script here. - exit(); + // Let the user know that the given variant did not pass our HGVS check. + $sResponse = 'Your variant (\"' . $sVariant . '\") did not pass our HGVS check.

'; + update_images_per_step($sStepInitialChecks, $sImageFailed); - } else { - // We could not propose a fix. We will end the script. - update_dialogue($sResponse . 'Please check your variant for errors and try again.
', - $sButtonOKInvalid); - exit(); - } -} + // Show the user the warnings and errors we found through getVariantInfo. + $aVariantIssues = ($aVariant === false ? array() : array_merge(array_values($aVariant['errors']), array_values($aVariant['warnings']))); + if (!empty($aVariantIssues)) { + $sResponse .= 'We found the following problems:
- '; + $sResponse .= implode('
-', $aVariantIssues) . '

'; + } + // Show the fixed variant if fixHGVS was successful. + $sFixedVariant = lovd_fixHGVS($sVariant); -// Check whether VariantValidator supports the syntax of the variant. -$bIsSupportedByVV = - !(isset($aVariant['warnings']['WNOTSUPPORTED']) - || isset($aVariant['messages']['IUNCERTAINPOSITIONS']) - || isset($aVariant['messages']['IPOSTIONRANGE'])); + if ($sFixedVariant !== $sVariant && lovd_isHGVS($sFixedVariant)) { + // Good, we can propose a fix. If the user agrees with the fix, + // we can continue to the mapping. + update_dialogue($sResponse . 'Did you mean \"' . $sFixedVariant . '\"?
', + $sButtonYes . ', ' . $sButtonNo); -if (!$bIsSupportedByVV) { - // If syntax was found which VariantValidator does not support, we - // cannot send the variant in for mapping. We will notify the - // user and exit this script. - update_images_per_step($sStepInitialChecks, $sImageFailed); - update_dialogue('Your variant contains syntax which VariantValidator cannot recognise. ' . - 'Therefore, we cannot map your variant nor validate the positions.', - $sButtonOKCouldBeValid); - exit(); -} + // Our 'Yes' button sets the steps in motion which change the user's + // input into the fixed variant, and reactivates the dialogue. + // It is then started from the top. + } else { + // We could not propose a fix. + update_dialogue($sResponse . 'Please check your variant for errors and try again.
', + $sButtonOKInvalid); + } + exit(); + } + // Check whether VariantValidator supports the syntax of the variant. + $bIsSupportedByVV = + !(isset($aVariant['warnings']['WNOTSUPPORTED']) + || isset($aVariant['messages']['IUNCERTAINPOSITIONS']) + || isset($aVariant['messages']['IPOSTIONRANGE'])); + if (!$bIsSupportedByVV) { + // If syntax was found which VariantValidator does not support, we + // cannot send the variant in for mapping. We will notify the + // user and exit this script. + update_images_per_step($sStepInitialChecks, $sImageFailed); + update_dialogue('Your variant contains syntax which VariantValidator cannot recognise. ' . + 'Therefore, we cannot map your variant nor validate the positions.', + $sButtonOKCouldBeValid); + exit(); + } -// Retrieve the reference sequence from the info given through the URL. -if (strpos($sRefSeqInfo, '-') === false) { - // The '-' serves as our little communication tool; it tells - // us that the given input was a GB suffix. When no '-' was - // found, we know that the input was the reference sequence - // of a transcript. - $sType = 'VOT'; - $sReferenceSequence = $sRefSeqInfo; -} else { - // We know we got information on a GB. This is given through - // JS in the format of -. - $sType = 'VOG'; - list($sCurrentGBSuffix, $sChromosome) = explode('-', $sRefSeqInfo); + // Retrieve the reference sequence from the info given through the URL. + if (strpos($sRefSeqInfo, '-') === false) { + // The '-' serves as our little communication tool; it tells + // us that the given input was a GB suffix. When no '-' was + // found, we know that the input was the reference sequence + // of a transcript. + $sType = 'VOT'; + $sReferenceSequence = $sRefSeqInfo; - if (!$_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['supported_by_VV']) { - // If the given genome build is not supported by VV, we cannot fully validate - // the variants... We will have to accept these variants into the database - // anyway, since this issue lies with us. - die(' + } else { + // We know we got information on a GB. This is given through + // JS in the format of -. + $sType = 'VOG'; + list($sCurrentGBSuffix, $sChromosome) = explode('-', $sRefSeqInfo); + + if (!$_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['supported_by_VV']) { + // If the given genome build is not supported by VV, we cannot fully validate + // the variants... We will have to accept these variants into the database + // anyway, since this issue lies with us. + die(' $("#variantCheckDialogue").dialog("close"); var oInput = $(\'input[name="' . $sFieldName . '"]\'); oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "We validated the syntax, but could not validate the positions."}).show(); '); - } + } - if (!isset($_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome])) { - // The combination of chromosome and build is not known by LOVD. - // Something probably went wrong on the user's end. We will inform - // the user and exit the script. - update_images_per_step($sStepInitialChecks, $sImageFailed); - update_dialogue( - 'An unknown combination of genome build and chromosome was given.' . - ' This means we cannot perform the mapping.', - $sButtonOKInvalid); - exit(); + if (!isset($_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome])) { + // The combination of chromosome and build is not known by LOVD. + // Something probably went wrong on the user's end. We will inform + // the user and exit the script. + update_images_per_step($sStepInitialChecks, $sImageFailed); + update_dialogue( + 'An unknown combination of genome build and chromosome was given.' . + ' This means we cannot perform the mapping.', + $sButtonOKInvalid); + exit(); + } + + $sReferenceSequence = $_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome]; } - $sReferenceSequence = $_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome]; -} + // Check if the description itself holds a reference sequence. + // if (lovd_holdsRefSeq($sVariant)) { Fixme; Update line below with this line once the necessary code has been pulled in -> Committed in feat/checkHGVSTool on January 14th 2022; ID 7abf9d70dc3094f5f9cfa0dfc43039c49b4217ff. + if (preg_match('/.*:[a-z]\./', $sVariant)) { + // The given variant description holds a reference sequence. + $sRefSeqInDescription = substr($sVariant, 0, strpos($sVariant, ':')); -// Check if the description itself holds a reference sequence. -// if (lovd_holdsRefSeq($sVariant)) { Fixme; Update line below with this line once the necessary code has been pulled in -> Committed in feat/checkHGVSTool on January 14th 2022; ID 7abf9d70dc3094f5f9cfa0dfc43039c49b4217ff. -if (preg_match('/.*:[a-z]\./', $sVariant)) { - // The given variant description holds a reference sequence. - $sRefSeqInDescription = substr($sVariant, 0, strpos($sVariant, ':')); + if ($sRefSeqInDescription == $sReferenceSequence) { + // Perfect, no issues found; the user redundantly gave + // the reference sequence in the variant description, + // but that is no problem at all, since the given + // refSeq matches our expectations. + $sVariant = $sVariant; - if ($sRefSeqInDescription == $sReferenceSequence) { - // Perfect, no issues found; the user redundantly gave - // the reference sequence in the variant description, - // but that is no problem at all, since the given - // refSeq matches our expectations. - $sFullVariant = $sVariant; + } else { + // The user gave a refSeq within the variant description + // input which does not match our expectations. The variant + // is then likely to be wrong. We cannot accept it. + update_images_per_step($sStepInitialChecks, $sImageFailed); + update_dialogue( + 'The reference sequence given in the input description, does not equal the' . + ' reference sequence matched to the variant by LOVD automatically. Please have' . + ' another look and perhaps try again from a different input field.', + $sButtonOKInvalid); + exit(); + } } else { - // The user gave a refSeq within the variant description - // input which does not match our expectations. The variant - // is then likely to be wrong. We cannot accept it. - update_images_per_step($sStepInitialChecks, $sImageFailed); - update_dialogue( - 'The reference sequence given in the input description, does not equal the' . - ' reference sequence matched to the variant by LOVD automatically. Please have' . - ' another look and perhaps try again from a different input field.', - $sButtonOKInvalid); - exit(); + // The given variant does not hold a reference sequence. + $sVariant = $sReferenceSequence . ':' . $sVariant; } -} else { - // The given variant does not hold a reference sequence. - $sFullVariant = $sReferenceSequence . ':' . $sVariant; -} - + // All checks have passed; we are ready for the mapping. + update_images_per_step($sStepInitialChecks, $sImagePassed); + update_images_per_step($sStepMapping, $sImageLoading); + print(' + $.get("ajax/check_hgvs_dialogue.php?" + + "action=map" + + "&var=' . $sVariant . '" + + "&fieldName=' . $sFieldName . '" + + "&type=' . $sType . '" + + "&refSeq=' . $sReferenceSequence . '" + + "&transcripts=' . implode('|', $aTranscripts) . '") + .fail(function(){alert("Error while trying to map your variant, please try again later.");}) + '); +} -// Call VariantValidator. -update_images_per_step($sStepInitialChecks, $sImagePassed); -update_images_per_step($sStepMapping, $sImageLoading); - -require ROOT_PATH . 'class/variant_validator.php'; -$_VV = new LOVD_VV(); -$aMappedVariant = ( - $sType == 'VOG'? - $_VV->verifyGenomic($sFullVariant, array( - 'map_to_transcripts' => empty($aTranscript), // Should we map the variant to transcripts? - 'predict_protein' => empty($aTranscript), // Should we get protein predictions? - 'lift_over' => (count($aActiveGBs) > 1), // Should we get other genomic mappings of this variant? - 'select_transcripts' => (empty($aTranscripts)? array() : $aTranscripts), - )) : - $_VV->verifyVariant($sFullVariant, array('select_transcripts' => $aTranscripts)) -); - +// Performing the mapping. +if ($_REQUEST['action'] == 'map') { -// Check if VariantValidator bumped into any issues. -if (!empty($aMappedVariant['errors'])) { - // The variant holds a fatal issue. We will exit the script and not - // accept this variant into the database. + // Retrieving necessary information from the URL. + $sType = urldecode($_REQUEST['type']); + $sReferenceSequence = urldecode($_REQUEST['refSeq']); - update_images_per_step($sStepMapping, $sImageFailed); - update_dialogue( - 'We could not valide nor map your variant because of the following problem(s):
- ' . - implode('
-', $aMappedVariant['errors']) . '

' . - 'Please take another look at your variant and try again.', - $sButtonOKInvalid); - exit(); -} + // Call VariantValidator. + require ROOT_PATH . 'class/variant_validator.php'; + $_VV = new LOVD_VV(); + $aMappedVariant = ( + $sType == 'VOG' ? + $_VV->verifyGenomic($sVariant, array( + 'map_to_transcripts' => empty($aTranscript), // Should we map the variant to transcripts? + 'predict_protein' => empty($aTranscript), // Should we get protein predictions? + 'lift_over' => (count($aActiveGBs) > 1), // Should we get other genomic mappings of this variant? + 'select_transcripts' => (empty($aTranscripts) ? array() : $aTranscripts), + )) : + $_VV->verifyVariant($sVariant, array('select_transcripts' => $aTranscripts)) + ); -// Check for warnings. -if (!empty($aMappedVariant['warnings'])) { - // One or more warnings were found. Perhaps the variant was corrected? - if (isset($aMappedVariant['warnings']['WROLLBACK']) - || isset($aMappedVariant['warnings']['WCORRECTED'])) { - // The variant was corrected. - update_dialogue('Your variant was corrected to ' . $aMappedVariant['data']['DNA'] . - ' to fully match HGVS guidelines.'); - $bImprovedByVV = true; - } + // Check if VariantValidator bumped into any issues. + if (!empty($aMappedVariant['errors'])) { + // The variant holds a fatal issue. We will exit the script and not + // accept this variant into the database. - if (isset($aMappedVariant['warnings']['WFLAG'])) { - // This type of warning tells us that VariantValidator had a problem - // which is an issue with them, not us nor our user. We can only get - // the mapping on all genome builds, not on (other) transcripts. - // We will notify the user. - update_dialogue('Your variant could not fully be validated due to unknown issues.'); - // Fixme; Either find a fix within VV, or Call Mutalyzer. + update_images_per_step($sStepMapping, $sImageFailed); + update_dialogue( + 'We could not valide nor map your variant because of the following problem(s):
- ' . + implode('
-', $aMappedVariant['errors']) . '

' . + 'Please take another look at your variant and try again.', + $sButtonOKInvalid); + exit(); } -// Check whether the mapping was successful. -} elseif (!isset($aMappedVariant['data']['DNA']) - || empty($aMappedVariant['data']['DNA'])) { - // Although we did not receive any warnings or errors, the DNA field - // is left empty. This means we have no information on the mapping - // and there is not much we can do... We will inform the user that - // an unknown error occurred and that they should try again later. - update_images_per_step($sStepMapping, $sImageFailed); - update_dialogue( - 'An unknown error occurred while trying to validate and map your variant.' . - ' We are sorry for the inconvenience. Please try again later.', - $sButtonOKInvalid); - exit(); -} + // Check for warnings. + if (!empty($aMappedVariant['warnings'])) { + // One or more warnings were found. Perhaps the variant was corrected? + if (isset($aMappedVariant['warnings']['WROLLBACK']) + || isset($aMappedVariant['warnings']['WCORRECTED'])) { + // The variant was corrected. + update_dialogue('Your variant was corrected to ' . $aMappedVariant['data']['DNA'] . + ' to fully match HGVS guidelines.'); + $bImprovedByVV = true; + } + if (isset($aMappedVariant['warnings']['WFLAG'])) { + // This type of warning tells us that VariantValidator had a problem + // which is an issue with them, not us nor our user. We can only get + // the mapping on all genome builds, not on (other) transcripts. + // We will notify the user. + update_dialogue('Your variant could not fully be validated due to unknown issues.'); + // Fixme; Either find a fix within VV, or Call Mutalyzer. + } + // Check whether the mapping was successful. + } elseif (!isset($aMappedVariant['data']['DNA']) + || empty($aMappedVariant['data']['DNA'])) { + // Although we did not receive any warnings or errors, the DNA field + // is left empty. This means we have no information on the mapping + // and there is not much we can do... We will inform the user that + // an unknown error occurred and that they should try again later. + update_images_per_step($sStepMapping, $sImageFailed); + update_dialogue( + 'An unknown error occurred while trying to validate and map your variant.' . + ' We are sorry for the inconvenience. Please try again later.', + $sButtonOKInvalid); + exit(); + } -// When sending in a variant on transcript, VariantValidator only -// returns the variant as mapped on that one transcript. If we are -// on a VOT creation form, and there are multiple transcripts open, -// we want each transcript to get a mapping. To get this, we then -// need to call VariantValidator a second time using one of the -// genomic variant as were returned using our first call. -if ($sType == 'VOT' && count($aTranscripts) > 1) { + // When sending in a variant on transcript, VariantValidator only + // returns the variant as mapped on that one transcript. If we are + // on a VOT creation form, and there are multiple transcripts open, + // we want each transcript to get a mapping. To get this, we then + // need to call VariantValidator a second time using one of the + // genomic variant as were returned using our first call. + if ($sType == 'VOT' && count($aTranscripts) > 1) { - $aMappedViaGB = ( - !isset($aMappedVariant['data']['genomic_mappings']['hg38'])? // Yes=We have a genomic reference from our first call; No=We don't have a genomic reference. + $aMappedViaGB = ( + !isset($aMappedVariant['data']['genomic_mappings']['hg38']) ? // Yes=We have a genomic reference from our first call; No=We don't have a genomic reference. array() : $_VV->verifyGenomic($aMappedVariant['data']['genomic_mappings']['hg38'], array( 'map_to_transcripts' => true, // Should we map the variant to transcripts? @@ -466,38 +469,35 @@ function update_images_per_step ($nStep, $sImage) { 'lift_over' => false, // Should we get other genomic mappings of this variant? 'select_transcripts' => $aTranscripts, // Should we limit our output to only a certain set of transcripts? )) - ); - - if (!isset($aMappedViaGB['data']['transcript_mappings'])) { - // If for any reason no genomic mappings were given, we cannot perform this - // extra step, and will thus miss some information. We will inform the user. - update_dialogue('Your variant could not be mapped to all transcripts due to unknown issues.'); - } - - $aMappedVariant['data']['transcript_mappings'] = $aMappedViaGB['data']['transcript_mappings']; - - unset($aMappedViaGB); // We don't need the rest of this information. -} + ); + if (!isset($aMappedViaGB['data']['transcript_mappings'])) { + // If for any reason no genomic mappings were given, we cannot perform this + // extra step, and will thus miss some information. We will inform the user. + update_dialogue('Your variant could not be mapped to all transcripts due to unknown issues.'); + } + $aMappedVariant['data']['transcript_mappings'] = $aMappedViaGB['data']['transcript_mappings']; + unset($aMappedViaGB); // We don't need the rest of this information. + } -// Add mapping information to the right fields. + // Add mapping information to the right fields. -// Returning the mapping for transcript, RNA and protein variants. -foreach($aTranscripts as $sTranscript) { - if (!isset($aMappedVariant['data']['transcript_mappings'][$sTranscript]) - && $sTranscript != $sReferenceSequence) { - // If no mapping was found for this transcript, we skip it. - continue; - } - // Retrieving the info. - $aTranscriptData = ($sTranscript == $sReferenceSequence? // Yes=Variant of origin (stored directly in data); No=Other (stored in transcript_mappings) - $aMappedVariant['data'] : $aMappedVariant['data']['transcript_mappings'][$sTranscript]); + // Returning the mapping for transcript, RNA and protein variants. + foreach ($aTranscripts as $sTranscript) { + if (!isset($aMappedVariant['data']['transcript_mappings'][$sTranscript]) + && $sTranscript != $sReferenceSequence) { + // If no mapping was found for this transcript, we skip it. + continue; + } + // Retrieving the info. + $aTranscriptData = ($sTranscript == $sReferenceSequence ? // Yes=Variant of origin (stored directly in data); No=Other (stored in transcript_mappings) + $aMappedVariant['data'] : $aMappedVariant['data']['transcript_mappings'][$sTranscript]); - // Filling in the input fields. - print(' + // Filling in the input fields. + print(' // Adding transcript info to the fields. var oTranscriptField = $("input").filter(function() { return $(this).data("id_ncbi") == "' . $sTranscript . '" @@ -511,85 +511,80 @@ function update_images_per_step ($nStep, $sImage) { $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '"); $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '"); }'); -} - -// Returning the mapping for genomic variants. -foreach($aActiveGBs as $sGBSuffix => $sGBID) { - if (!$_SETT['human_builds'][$sGBID]['supported_by_VV'] - || !isset($aMappedVariant['data']['genomic_mappings'][$sGBID]) ) { - // If a genome build is active which is not supported by VV, we won't have - // received mapping information on it. We will skip this variant. - continue; } - // Retrieving the info. - if ($sType == 'VOT') { - // When VV was called using a variant on transcript, we always - // get only one possible mapping, which is formatted as a string. - $sMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; - - } elseif (isset($sCurrentGBSuffix) && $sGBSuffix == $sCurrentGBSuffix) { - // The current build is the build which is the direct reference of - // our input variant. When this is the case, our output is already - // formatted as a string as well. - $sMappedGenomicVariant = $aMappedVariant['data']['DNA']; - - } else { - // Our output is formatted as an array, since multiple variants were possible. - $aMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; - if (count($aMappedGenomicVariant) <= 1) { - // Only one variant was found. Great! We can simply take the first element. - $sMappedGenomicVariant = $aMappedGenomicVariant[0]; + // Returning the mapping for genomic variants. + foreach ($aActiveGBs as $sGBSuffix => $sGBID) { + if (!$_SETT['human_builds'][$sGBID]['supported_by_VV'] + || !isset($aMappedVariant['data']['genomic_mappings'][$sGBID])) { + // If a genome build is active which is not supported by VV, we won't have + // received mapping information on it. We will skip this variant. + continue; + } + // Retrieving the info. + if ($sType == 'VOT') { + // When VV was called using a variant on transcript, we always + // get only one possible mapping, which is formatted as a string. + $sMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; + + } elseif (isset($sCurrentGBSuffix) && $sGBSuffix == $sCurrentGBSuffix) { + // The current build is the build which is the direct reference of + // our input variant. When this is the case, our output is already + // formatted as a string as well. + $sMappedGenomicVariant = $aMappedVariant['data']['DNA']; } else { - // Multiple possible variants were found. We will give the user a heads-up, - // and concatenate the variants cleanly as follows: - // NC_1233456.1:g.1del + NC_123456.1:g.2_3del + NC_123456.1:g.4del = - // NC_123456.1:g.1del^2_3del^4del. - update_dialogue('There were multiple genomic variant predictions for build ' . $sGBID . '.'); - - $sMappedGenomicVariant = - preg_replace('/(.*:[a-z]\.).*/', '', $aMappedGenomicVariant[0]) . - implode('^', - array_map(function ($sFullVariant) { - return preg_replace('/.*:[a-z]\./', '', $sFullVariant); - }, $aMappedGenomicVariant) - ); + // Our output is formatted as an array, since multiple variants were possible. + $aMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; + + if (count($aMappedGenomicVariant) <= 1) { + // Only one variant was found. Great! We can simply take the first element. + $sMappedGenomicVariant = $aMappedGenomicVariant[0]; + + } else { + // Multiple possible variants were found. We will give the user a heads-up, + // and concatenate the variants cleanly as follows: + // NC_1233456.1:g.1del + NC_123456.1:g.2_3del + NC_123456.1:g.4del = + // NC_123456.1:g.1del^2_3del^4del. + update_dialogue('There were multiple genomic variant predictions for build ' . $sGBID . '.'); + + $sMappedGenomicVariant = + preg_replace('/(.*:[a-z]\.).*/', '', $aMappedGenomicVariant[0]) . + implode('^', + array_map(function ($sFullVariant) { + return preg_replace('/.*:[a-z]\./', '', $sFullVariant); + }, $aMappedGenomicVariant) + ); + } } - } - - // Filling in the input field. - print(' - // Adding genomic info the fields. - var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix? '' : '/' . $sGBSuffix) . '"]\'); - oGenomicVariant.val("' . preg_replace('/.*:/', '', $sMappedGenomicVariant) . '"); - oGenomicVariant.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); - oGenomicVariant.prop("disabled", true); - '); // Fixme; Find a cleaner way of cutting off the reference sequence. -} - - - - - -// Because we automatically filled all non-blocked positions, -// all open transcript fields have been blocked. We don't -// want the user to block the transcript input at this point -// so we disable the 'Ignore this transcript' option. -print(' -// Disabling the "ignore this transcript" option. -var oIgnoreOption = $(\'input[name^="ignore_"]\'); -oIgnoreOption.parent().html(""); -'); + // Filling in the input field. + print(' + // Adding genomic info the fields. + var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); + oGenomicVariant.val("' . preg_replace('/.*:/', '', $sMappedGenomicVariant) . '"); + oGenomicVariant.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); + oGenomicVariant.prop("disabled", true); + '); // Fixme; Find a cleaner way of cutting off the reference sequence. + } + // Because we automatically filled all non-blocked positions, + // all open transcript fields have been blocked. We don't + // want the user to block the transcript input at this point + // so we disable the 'Ignore this transcript' option. + print(' + // Disabling the "ignore this transcript" option. + var oIgnoreOption = $(\'input[name^="ignore_"]\'); + oIgnoreOption.parent().html(""); + '); -// Send final message to the user. -update_images_per_step($sStepMapping, $sImagePassed); -update_dialogue( - 'Your variant was successfully mapped' . (!isset($bImprovedByVV)? '' : ', improved') . - ' and validated by VariantValidator. Thank you for your patience!', - $sButtonOKValid); + // Send final message to the user. + update_images_per_step($sStepMapping, $sImagePassed); + update_dialogue( + 'Your variant was successfully mapped' . (!isset($bImprovedByVV) ? '' : ', improved') . + ' and validated by VariantValidator. Thank you for your patience!', + $sButtonOKValid); +} ?> diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index c880a221..9b65103d 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -184,7 +184,8 @@ function lovd_checkHGVS(e) { }).get().join('|'); $.get("ajax/check_hgvs_dialogue.php?" - + "var=" + encodeURIComponent(sVariant) + + "action=check" + + "&var=" + encodeURIComponent(sVariant) + "&fieldName=" + encodeURIComponent(sFieldName) + "&refSeqInfo=" + encodeURIComponent(sRefSeqInfo) + "&transcripts=" + encodeURIComponent(sTranscripts)) From 4f3e8e50a840af63cb334111b78104529d0b0209 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 24 Feb 2022 10:27:05 +0100 Subject: [PATCH 20/95] Allow variants which VV cannot validate into the DB If VariantValidator returns false, if we use an unknown build, or if syntax was found which VV does not support, we now make sure these ARE allowed into the database anyway, since these issues are outside of the user's control. --- src/ajax/check_hgvs_dialogue.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 5503e0f7..556393a4 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -61,7 +61,7 @@ $sButtonOKCouldBeValid = 'oButtonOKCouldBeValid'; // Preparing the JS for the buttons. -// Fixme; Add to buttonOKValid and buttonOKCouldBeValid: mp5 translation of all input. +// Fixme; Add to buttonOKValid and buttonOKCouldBeValid: md5 translation of all input. print(' // Preparing the buttons. var ' . $sButtonYes . ' = {"Yes":function () { @@ -153,7 +153,7 @@ function update_images_per_step($nStep, $sImage) // Resetting all values. var oInput = $(\'input[name$="' . $sFieldName . '"]\'); oInput.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); // TODO: Remove the mp5 translated variant from the HTML. + '); // TODO: Remove the md5 translated variant from the HTML. // Returning the mapping for transcript, RNA and protein variants. foreach ($aTranscripts as $sTranscript) { @@ -400,6 +400,19 @@ function update_images_per_step($nStep, $sImage) $_VV->verifyVariant($sVariant, array('select_transcripts' => $aTranscripts)) ); + // Check for issues for which the user cannot be blamed. + if ($aMappedVariant === false + || in_array(array_keys($aMappedVariant['errors']), array(array('EBUILD'), array('ESYNTAX')))) { + // If our VV call returned false, or if we found an EBUILD or ESYNTAX + // error, this is an issue that lies with us, not the user. + // We will have to allow these variants into the database. + update_dialogue( + 'Something went wrong on our side, which means we could not map nor validate your variant.', + $sButtonOKCouldBeValid + ); + exit(); + } + // Check if VariantValidator bumped into any issues. if (!empty($aMappedVariant['errors'])) { @@ -408,7 +421,7 @@ function update_images_per_step($nStep, $sImage) update_images_per_step($sStepMapping, $sImageFailed); update_dialogue( - 'We could not valide nor map your variant because of the following problem(s):
- ' . + 'We could not validate nor map your variant because of the following problem(s):
- ' . implode('
-', $aMappedVariant['errors']) . '

' . 'Please take another look at your variant and try again.', $sButtonOKInvalid); From 5227038738c40511fb2eab906d6c62d6fde3a152 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 24 Feb 2022 10:45:55 +0100 Subject: [PATCH 21/95] Clean up the output and accredit VariantValidator To give more credits to VariantValidator and its crucial role in the mapping of the variants, we have added its name to the title of our dialogue. --- src/ajax/check_hgvs_dialogue.php | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 556393a4..06f91d3a 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -112,10 +112,10 @@ function update_dialogue($sText, $sButtons = '', $bCleanSlate = false) // if !$bCleanSlate, it will append. print(($bCleanSlate ? ' // Updating the contents. - $("#variantCheckDialogue").html("' . $sText . '

"); + $("#variantCheckDialogue").html("' . $sText . '
"); ' : ' // Appending to the contents. - $("#variantCheckDialogue").append("' . $sText . '

"); + $("#variantCheckDialogue").append("' . $sText . '
"); ')); print(($sButtons ? ' @@ -190,7 +190,7 @@ function update_images_per_step($nStep, $sImage) // Opening the dialogue. print(' // Setting up the dialogue. - $("body").append("
"); + $("body").append("
"); $("#variantCheckDialogue").dialog({ draggable:true,resizable:false,minWidth:600,show:"fade",closeOnEscape:false,hide:"fade",modal:true, open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); } @@ -198,8 +198,7 @@ function update_images_per_step($nStep, $sImage) '); update_dialogue( - ' Performing initial checks.' . - '
Mapping your variant.', + ' Performing initial checks.', '', true ); @@ -215,7 +214,7 @@ function update_images_per_step($nStep, $sImage) update_images_per_step($sStepInitialChecks, $sImageFailed); update_dialogue( - 'Your variant contains syntax which our HGVS check cannot recognise. ' . + '
Your variant contains syntax which our HGVS check cannot recognise. ' . 'Therefore, we cannot validate your variant nor map it to other reference sequences. ' . 'Please thoroughly validate your variant by hand.', $sButtonOKCouldBeValid); @@ -232,7 +231,7 @@ function update_images_per_step($nStep, $sImage) // which we can interpret. // Let the user know that the given variant did not pass our HGVS check. - $sResponse = 'Your variant (\"' . $sVariant . '\") did not pass our HGVS check.

'; + $sResponse = '
Your variant (\"' . $sVariant . '\") did not pass our HGVS check.

'; update_images_per_step($sStepInitialChecks, $sImageFailed); @@ -278,7 +277,7 @@ function update_images_per_step($nStep, $sImage) // cannot send the variant in for mapping. We will notify the // user and exit this script. update_images_per_step($sStepInitialChecks, $sImageFailed); - update_dialogue('Your variant contains syntax which VariantValidator cannot recognise. ' . + update_dialogue('
Your variant contains syntax which VariantValidator cannot recognise. ' . 'Therefore, we cannot map your variant nor validate the positions.', $sButtonOKCouldBeValid); exit(); @@ -317,7 +316,7 @@ function update_images_per_step($nStep, $sImage) // the user and exit the script. update_images_per_step($sStepInitialChecks, $sImageFailed); update_dialogue( - 'An unknown combination of genome build and chromosome was given.' . + '
An unknown combination of genome build and chromosome was given.' . ' This means we cannot perform the mapping.', $sButtonOKInvalid); exit(); @@ -346,7 +345,7 @@ function update_images_per_step($nStep, $sImage) // is then likely to be wrong. We cannot accept it. update_images_per_step($sStepInitialChecks, $sImageFailed); update_dialogue( - 'The reference sequence given in the input description, does not equal the' . + '
The reference sequence given in the input description, does not equal the' . ' reference sequence matched to the variant by LOVD automatically. Please have' . ' another look and perhaps try again from a different input field.', $sButtonOKInvalid); @@ -361,7 +360,7 @@ function update_images_per_step($nStep, $sImage) // All checks have passed; we are ready for the mapping. update_images_per_step($sStepInitialChecks, $sImagePassed); - update_images_per_step($sStepMapping, $sImageLoading); + update_dialogue(' Mapping your variant.'); print(' $.get("ajax/check_hgvs_dialogue.php?" @@ -406,8 +405,9 @@ function update_images_per_step($nStep, $sImage) // If our VV call returned false, or if we found an EBUILD or ESYNTAX // error, this is an issue that lies with us, not the user. // We will have to allow these variants into the database. + update_images_per_step($sStepMapping, $sImageFailed); update_dialogue( - 'Something went wrong on our side, which means we could not map nor validate your variant.', + '
Something went wrong on our side, which means we could not map nor validate your variant.', $sButtonOKCouldBeValid ); exit(); @@ -421,7 +421,7 @@ function update_images_per_step($nStep, $sImage) update_images_per_step($sStepMapping, $sImageFailed); update_dialogue( - 'We could not validate nor map your variant because of the following problem(s):
- ' . + '
We could not validate nor map your variant because of the following problem(s):
- ' . implode('
-', $aMappedVariant['errors']) . '

' . 'Please take another look at your variant and try again.', $sButtonOKInvalid); @@ -435,7 +435,7 @@ function update_images_per_step($nStep, $sImage) if (isset($aMappedVariant['warnings']['WROLLBACK']) || isset($aMappedVariant['warnings']['WCORRECTED'])) { // The variant was corrected. - update_dialogue('Your variant was corrected to ' . $aMappedVariant['data']['DNA'] . + update_dialogue('
Your variant was corrected to ' . $aMappedVariant['data']['DNA'] . ' to fully match HGVS guidelines.'); $bImprovedByVV = true; } @@ -445,7 +445,7 @@ function update_images_per_step($nStep, $sImage) // which is an issue with them, not us nor our user. We can only get // the mapping on all genome builds, not on (other) transcripts. // We will notify the user. - update_dialogue('Your variant could not fully be validated due to unknown issues.'); + update_dialogue('
Your variant could not fully be validated due to unknown issues.'); // Fixme; Either find a fix within VV, or Call Mutalyzer. } @@ -458,7 +458,7 @@ function update_images_per_step($nStep, $sImage) // an unknown error occurred and that they should try again later. update_images_per_step($sStepMapping, $sImageFailed); update_dialogue( - 'An unknown error occurred while trying to validate and map your variant.' . + '
An unknown error occurred while trying to validate and map your variant.' . ' We are sorry for the inconvenience. Please try again later.', $sButtonOKInvalid); exit(); @@ -487,7 +487,7 @@ function update_images_per_step($nStep, $sImage) if (!isset($aMappedViaGB['data']['transcript_mappings'])) { // If for any reason no genomic mappings were given, we cannot perform this // extra step, and will thus miss some information. We will inform the user. - update_dialogue('Your variant could not be mapped to all transcripts due to unknown issues.'); + update_dialogue('
Your variant could not be mapped to all transcripts due to unknown issues.'); } $aMappedVariant['data']['transcript_mappings'] = $aMappedViaGB['data']['transcript_mappings']; @@ -559,7 +559,7 @@ function update_images_per_step($nStep, $sImage) // and concatenate the variants cleanly as follows: // NC_1233456.1:g.1del + NC_123456.1:g.2_3del + NC_123456.1:g.4del = // NC_123456.1:g.1del^2_3del^4del. - update_dialogue('There were multiple genomic variant predictions for build ' . $sGBID . '.'); + update_dialogue('
There were multiple genomic variant predictions for build ' . $sGBID . '.'); $sMappedGenomicVariant = preg_replace('/(.*:[a-z]\.).*/', '', $aMappedGenomicVariant[0]) . @@ -596,7 +596,7 @@ function update_images_per_step($nStep, $sImage) // Send final message to the user. update_images_per_step($sStepMapping, $sImagePassed); update_dialogue( - 'Your variant was successfully mapped' . (!isset($bImprovedByVV) ? '' : ', improved') . + '
Your variant was successfully mapped' . (!isset($bImprovedByVV) ? '' : ', improved') . ' and validated by VariantValidator. Thank you for your patience!', $sButtonOKValid); } From 723cd57c1408b5c92c9522596d325e7b0ae41273 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 24 Feb 2022 11:04:20 +0100 Subject: [PATCH 22/95] Remove redundant VV call for multiple transcripts --- src/ajax/check_hgvs_dialogue.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 06f91d3a..98727606 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -480,7 +480,7 @@ function update_images_per_step($nStep, $sImage) 'map_to_transcripts' => true, // Should we map the variant to transcripts? 'predict_protein' => true, // Should we get protein predictions? 'lift_over' => false, // Should we get other genomic mappings of this variant? - 'select_transcripts' => $aTranscripts, // Should we limit our output to only a certain set of transcripts? + 'select_transcripts' => array_diff($aTranscripts, array($sReferenceSequence)), // Should we limit our output to only a certain set of transcripts? )) ); From 32cbf304727f1fa10888daaa171aa45671153753 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 24 Feb 2022 11:32:19 +0100 Subject: [PATCH 23/95] Change line separators from CRLF to LF --- src/ajax/check_hgvs_dialogue.php | 1206 +++++++++++++++--------------- 1 file changed, 603 insertions(+), 603 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 98727606..1da17cca 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -1,603 +1,603 @@ - - * - * - * This file is part of LOVD. - * - * LOVD is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * LOVD is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with LOVD. If not, see . - * - *************/ - -define('ROOT_PATH', '../'); -require ROOT_PATH . 'inc-init.php'; -require ROOT_PATH . 'inc-lib-variants.php'; -header('Content-type: text/javascript; charset=UTF-8'); - - -// Preparing necessary functions and variables. -// Retrieving the variant and the transcripts and genome builds to map to. -$sVariant = htmlspecialchars($_REQUEST['var']); -$aTranscripts = explode('|', htmlspecialchars($_REQUEST['transcripts'])); -$aActiveGBs = $_DB->query('SELECT column_suffix, id FROM ' . TABLE_GENOME_BUILDS)->fetchAllCombine(); - -// Retrieving the name of the input field. -$sFieldName = htmlspecialchars($_REQUEST['fieldName']); - -// Preparing the steps. -$sStepInitialChecks = 'statusChecks'; -$sStepMapping = 'statusMapping'; - -// Preparing the images. -$sImageNeutral = 'gfx/trans.png'; -$sImagePassed = 'gfx/check.png'; -$sImageFailed = 'gfx/cross.png'; -$sImageLoading = 'gfx/lovd_loading.gif'; - -// Preparing the buttons. -$sButtonYes = 'oButtonYes'; -$sButtonNo = 'oButtonNo'; -$sButtonOKValid = 'oButtonOKValid'; -$sButtonOKInvalid = 'oButtonOKInvalid'; -$sButtonOKCouldBeValid = 'oButtonOKCouldBeValid'; - -// Preparing the JS for the buttons. -// Fixme; Add to buttonOKValid and buttonOKCouldBeValid: md5 translation of all input. -print(' -// Preparing the buttons. -var ' . $sButtonYes . ' = {"Yes":function () { - // The user accepts the given fixed variant. - // We will fill in this fixed variant, close the dialogue, - // and perform a new call to this script by activating - // the onChange. - var oInput = $(\'input[name="' . $sFieldName . '"]\'); - oInput.val("' . lovd_fixHGVS($sVariant) . '"); - $(this).dialog("close"); - oInput.change(); -}}; -var ' . $sButtonNo . ' = {"No, I will take a look myself":function () { - // The user does not accept the given fixed variant. - var oInput = $(\'input[name="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/cross.png", title: "Please check the HGVS syntax of your variant description before sending it into the database."}).show(); - $(this).dialog("close"); -}}; -var ' . $sButtonOKValid . ' = {"OK":function () { - // The variant was mapped and looks just great! - // All steps have already been taken; the only - // thing left to do is to close the dialogue. - $(this).dialog("close"); -}}; -var ' . $sButtonOKInvalid . ' = {"OK":function () { - // The user agrees to change their invalid input manually. - var oInput = $(\'input[name="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/cross.png", title: "Your variant could not be validated..."}).show(); - $(this).dialog("close"); -}}; -var ' . $sButtonOKCouldBeValid . ' = {"OK":function () { - // We could not validate this variant, but the problem - // lies with us. We will accept this variant and the - // uncertainty that comes with it. - var oInput = $(\'input[name="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "Your variant could not be (in)validated..."}).show(); - $(this).dialog("close"); -}}; -'); - - -// Create a PHP function to easily update the dialogue. -function update_dialogue($sText, $sButtons = '', $bCleanSlate = false) -{ - // This function fills the variantCheckDialogue with the given - // text, adds the right buttons and sends it to the user. - // If $bCleanSlate, it will remove the old text and start over; - // if !$bCleanSlate, it will append. - print(($bCleanSlate ? ' - // Updating the contents. - $("#variantCheckDialogue").html("' . $sText . '
"); - ' : ' - // Appending to the contents. - $("#variantCheckDialogue").append("' . $sText . '
"); - ')); - - print(($sButtons ? ' - // Placing the buttons. - $("#variantCheckDialogue").dialog({buttons: $.extend({}, ' . $sButtons . ')}); - ' : ' - // Removing buttons. - $("#variantCheckDialogue").dialog({buttons: {}}); - ')); - - // Sending the contents directly to the user. - flush(); -} - - -// Create a PHP function to easily update the images to the left of each step. -function update_images_per_step($nStep, $sImage) -{ - // This function takes a step in the format of an integer, and - // replaces the image which was put next to this step by the - // given $sImage. - print('$("#' . $nStep . '").attr({src: "' . $sImage . '"});'); -} - - - - - -// Performing initial checks. -if ($_REQUEST['action'] == 'check') { - - // If the variant is empty, we want to reset all results of this script. - if (!$sVariant) { - print(' - // Resetting all values. - var oInput = $(\'input[name$="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); // TODO: Remove the md5 translated variant from the HTML. - - // Returning the mapping for transcript, RNA and protein variants. - foreach ($aTranscripts as $sTranscript) { - print(' - var oTranscriptField = $("input").filter(function() { - return $(this).data("id_ncbi") == "' . $sTranscript . '" - }); - oTranscriptField.val(""); - oTranscriptField.prop("disabled", false); - oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); - '); - } - - // Returning the mapping for genomic variants. - foreach ($aActiveGBs as $sGBSuffix => $sGBID) { - print(' - var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); - oGenomicVariant.val(""); - oGenomicVariant.prop("disabled", false); - oGenomicVariant.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); - } - - // Closing the script. - exit(); - } - - // Retrieving information on the reference sequence from the URL. - $sRefSeqInfo = htmlspecialchars($_REQUEST['refSeqInfo']); - - // Opening the dialogue. - print(' - // Setting up the dialogue. - $("body").append("
"); - $("#variantCheckDialogue").dialog({ - draggable:true,resizable:false,minWidth:600,show:"fade",closeOnEscape:false,hide:"fade",modal:true, - open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); } - }); - '); - - update_dialogue( - ' Performing initial checks.', - '', - true - ); - - - // Check whether this variant is supported by LOVD. - $aVariant = lovd_getVariantInfo($sVariant, false); - $bIsSupportedByLOVD = !isset($aVariant['errors']['ENOTSUPPORTED']); - - if (!$bIsSupportedByLOVD) { - // If the variant is not supported by LOVD, we cannot perform an HGVS check nor the mapping. - // We will notify the user and end the script here. - - update_images_per_step($sStepInitialChecks, $sImageFailed); - update_dialogue( - '
Your variant contains syntax which our HGVS check cannot recognise. ' . - 'Therefore, we cannot validate your variant nor map it to other reference sequences. ' . - 'Please thoroughly validate your variant by hand.', - $sButtonOKCouldBeValid); - exit(); - } - - - // Perform our HGVS check. - if (!lovd_isHGVS($sVariant)) { - // If the variant is not HGVS, we cannot send the variant to - // VariantValidator yet. We will try to see if our fixHGVS - // function knows what to do, but if not, we need to exit - // this script and wait for the user to return with a variant - // which we can interpret. - - // Let the user know that the given variant did not pass our HGVS check. - $sResponse = '
Your variant (\"' . $sVariant . '\") did not pass our HGVS check.

'; - update_images_per_step($sStepInitialChecks, $sImageFailed); - - - // Show the user the warnings and errors we found through getVariantInfo. - $aVariantIssues = ($aVariant === false ? array() : array_merge(array_values($aVariant['errors']), array_values($aVariant['warnings']))); - - if (!empty($aVariantIssues)) { - $sResponse .= 'We found the following problems:
- '; - $sResponse .= implode('
-', $aVariantIssues) . '

'; - } - - - // Show the fixed variant if fixHGVS was successful. - $sFixedVariant = lovd_fixHGVS($sVariant); - - if ($sFixedVariant !== $sVariant && lovd_isHGVS($sFixedVariant)) { - // Good, we can propose a fix. If the user agrees with the fix, - // we can continue to the mapping. - update_dialogue($sResponse . 'Did you mean \"' . $sFixedVariant . '\"?
', - $sButtonYes . ', ' . $sButtonNo); - - // Our 'Yes' button sets the steps in motion which change the user's - // input into the fixed variant, and reactivates the dialogue. - // It is then started from the top. - - } else { - // We could not propose a fix. - update_dialogue($sResponse . 'Please check your variant for errors and try again.
', - $sButtonOKInvalid); - } - exit(); - } - - - // Check whether VariantValidator supports the syntax of the variant. - $bIsSupportedByVV = - !(isset($aVariant['warnings']['WNOTSUPPORTED']) - || isset($aVariant['messages']['IUNCERTAINPOSITIONS']) - || isset($aVariant['messages']['IPOSTIONRANGE'])); - - if (!$bIsSupportedByVV) { - // If syntax was found which VariantValidator does not support, we - // cannot send the variant in for mapping. We will notify the - // user and exit this script. - update_images_per_step($sStepInitialChecks, $sImageFailed); - update_dialogue('
Your variant contains syntax which VariantValidator cannot recognise. ' . - 'Therefore, we cannot map your variant nor validate the positions.', - $sButtonOKCouldBeValid); - exit(); - } - - - // Retrieve the reference sequence from the info given through the URL. - if (strpos($sRefSeqInfo, '-') === false) { - // The '-' serves as our little communication tool; it tells - // us that the given input was a GB suffix. When no '-' was - // found, we know that the input was the reference sequence - // of a transcript. - $sType = 'VOT'; - $sReferenceSequence = $sRefSeqInfo; - - } else { - // We know we got information on a GB. This is given through - // JS in the format of -. - $sType = 'VOG'; - list($sCurrentGBSuffix, $sChromosome) = explode('-', $sRefSeqInfo); - - if (!$_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['supported_by_VV']) { - // If the given genome build is not supported by VV, we cannot fully validate - // the variants... We will have to accept these variants into the database - // anyway, since this issue lies with us. - die(' - $("#variantCheckDialogue").dialog("close"); - var oInput = $(\'input[name="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "We validated the syntax, but could not validate the positions."}).show(); - '); - } - - if (!isset($_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome])) { - // The combination of chromosome and build is not known by LOVD. - // Something probably went wrong on the user's end. We will inform - // the user and exit the script. - update_images_per_step($sStepInitialChecks, $sImageFailed); - update_dialogue( - '
An unknown combination of genome build and chromosome was given.' . - ' This means we cannot perform the mapping.', - $sButtonOKInvalid); - exit(); - } - - $sReferenceSequence = $_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome]; - } - - - // Check if the description itself holds a reference sequence. - // if (lovd_holdsRefSeq($sVariant)) { Fixme; Update line below with this line once the necessary code has been pulled in -> Committed in feat/checkHGVSTool on January 14th 2022; ID 7abf9d70dc3094f5f9cfa0dfc43039c49b4217ff. - if (preg_match('/.*:[a-z]\./', $sVariant)) { - // The given variant description holds a reference sequence. - $sRefSeqInDescription = substr($sVariant, 0, strpos($sVariant, ':')); - - if ($sRefSeqInDescription == $sReferenceSequence) { - // Perfect, no issues found; the user redundantly gave - // the reference sequence in the variant description, - // but that is no problem at all, since the given - // refSeq matches our expectations. - $sVariant = $sVariant; - - } else { - // The user gave a refSeq within the variant description - // input which does not match our expectations. The variant - // is then likely to be wrong. We cannot accept it. - update_images_per_step($sStepInitialChecks, $sImageFailed); - update_dialogue( - '
The reference sequence given in the input description, does not equal the' . - ' reference sequence matched to the variant by LOVD automatically. Please have' . - ' another look and perhaps try again from a different input field.', - $sButtonOKInvalid); - exit(); - } - - } else { - // The given variant does not hold a reference sequence. - $sVariant = $sReferenceSequence . ':' . $sVariant; - } - - - // All checks have passed; we are ready for the mapping. - update_images_per_step($sStepInitialChecks, $sImagePassed); - update_dialogue(' Mapping your variant.'); - - print(' - $.get("ajax/check_hgvs_dialogue.php?" - + "action=map" - + "&var=' . $sVariant . '" - + "&fieldName=' . $sFieldName . '" - + "&type=' . $sType . '" - + "&refSeq=' . $sReferenceSequence . '" - + "&transcripts=' . implode('|', $aTranscripts) . '") - .fail(function(){alert("Error while trying to map your variant, please try again later.");}) - '); -} - - - - - -// Performing the mapping. -if ($_REQUEST['action'] == 'map') { - - // Retrieving necessary information from the URL. - $sType = urldecode($_REQUEST['type']); - $sReferenceSequence = urldecode($_REQUEST['refSeq']); - - // Call VariantValidator. - require ROOT_PATH . 'class/variant_validator.php'; - $_VV = new LOVD_VV(); - $aMappedVariant = ( - $sType == 'VOG' ? - $_VV->verifyGenomic($sVariant, array( - 'map_to_transcripts' => empty($aTranscript), // Should we map the variant to transcripts? - 'predict_protein' => empty($aTranscript), // Should we get protein predictions? - 'lift_over' => (count($aActiveGBs) > 1), // Should we get other genomic mappings of this variant? - 'select_transcripts' => (empty($aTranscripts) ? array() : $aTranscripts), - )) : - $_VV->verifyVariant($sVariant, array('select_transcripts' => $aTranscripts)) - ); - - // Check for issues for which the user cannot be blamed. - if ($aMappedVariant === false - || in_array(array_keys($aMappedVariant['errors']), array(array('EBUILD'), array('ESYNTAX')))) { - // If our VV call returned false, or if we found an EBUILD or ESYNTAX - // error, this is an issue that lies with us, not the user. - // We will have to allow these variants into the database. - update_images_per_step($sStepMapping, $sImageFailed); - update_dialogue( - '
Something went wrong on our side, which means we could not map nor validate your variant.', - $sButtonOKCouldBeValid - ); - exit(); - } - - - // Check if VariantValidator bumped into any issues. - if (!empty($aMappedVariant['errors'])) { - // The variant holds a fatal issue. We will exit the script and not - // accept this variant into the database. - - update_images_per_step($sStepMapping, $sImageFailed); - update_dialogue( - '
We could not validate nor map your variant because of the following problem(s):
- ' . - implode('
-', $aMappedVariant['errors']) . '

' . - 'Please take another look at your variant and try again.', - $sButtonOKInvalid); - exit(); - } - - // Check for warnings. - if (!empty($aMappedVariant['warnings'])) { - // One or more warnings were found. Perhaps the variant was corrected? - - if (isset($aMappedVariant['warnings']['WROLLBACK']) - || isset($aMappedVariant['warnings']['WCORRECTED'])) { - // The variant was corrected. - update_dialogue('
Your variant was corrected to ' . $aMappedVariant['data']['DNA'] . - ' to fully match HGVS guidelines.'); - $bImprovedByVV = true; - } - - if (isset($aMappedVariant['warnings']['WFLAG'])) { - // This type of warning tells us that VariantValidator had a problem - // which is an issue with them, not us nor our user. We can only get - // the mapping on all genome builds, not on (other) transcripts. - // We will notify the user. - update_dialogue('
Your variant could not fully be validated due to unknown issues.'); - // Fixme; Either find a fix within VV, or Call Mutalyzer. - } - - // Check whether the mapping was successful. - } elseif (!isset($aMappedVariant['data']['DNA']) - || empty($aMappedVariant['data']['DNA'])) { - // Although we did not receive any warnings or errors, the DNA field - // is left empty. This means we have no information on the mapping - // and there is not much we can do... We will inform the user that - // an unknown error occurred and that they should try again later. - update_images_per_step($sStepMapping, $sImageFailed); - update_dialogue( - '
An unknown error occurred while trying to validate and map your variant.' . - ' We are sorry for the inconvenience. Please try again later.', - $sButtonOKInvalid); - exit(); - } - - - // When sending in a variant on transcript, VariantValidator only - // returns the variant as mapped on that one transcript. If we are - // on a VOT creation form, and there are multiple transcripts open, - // we want each transcript to get a mapping. To get this, we then - // need to call VariantValidator a second time using one of the - // genomic variant as were returned using our first call. - if ($sType == 'VOT' && count($aTranscripts) > 1) { - - $aMappedViaGB = ( - !isset($aMappedVariant['data']['genomic_mappings']['hg38']) ? // Yes=We have a genomic reference from our first call; No=We don't have a genomic reference. - array() : - $_VV->verifyGenomic($aMappedVariant['data']['genomic_mappings']['hg38'], array( - 'map_to_transcripts' => true, // Should we map the variant to transcripts? - 'predict_protein' => true, // Should we get protein predictions? - 'lift_over' => false, // Should we get other genomic mappings of this variant? - 'select_transcripts' => array_diff($aTranscripts, array($sReferenceSequence)), // Should we limit our output to only a certain set of transcripts? - )) - ); - - if (!isset($aMappedViaGB['data']['transcript_mappings'])) { - // If for any reason no genomic mappings were given, we cannot perform this - // extra step, and will thus miss some information. We will inform the user. - update_dialogue('
Your variant could not be mapped to all transcripts due to unknown issues.'); - } - - $aMappedVariant['data']['transcript_mappings'] = $aMappedViaGB['data']['transcript_mappings']; - - unset($aMappedViaGB); // We don't need the rest of this information. - } - - - // Add mapping information to the right fields. - - // Returning the mapping for transcript, RNA and protein variants. - foreach ($aTranscripts as $sTranscript) { - if (!isset($aMappedVariant['data']['transcript_mappings'][$sTranscript]) - && $sTranscript != $sReferenceSequence) { - // If no mapping was found for this transcript, we skip it. - continue; - } - // Retrieving the info. - $aTranscriptData = ($sTranscript == $sReferenceSequence ? // Yes=Variant of origin (stored directly in data); No=Other (stored in transcript_mappings) - $aMappedVariant['data'] : $aMappedVariant['data']['transcript_mappings'][$sTranscript]); - - // Filling in the input fields. - print(' - // Adding transcript info to the fields. - var oTranscriptField = $("input").filter(function() { - return $(this).data("id_ncbi") == "' . $sTranscript . '" - }); - - if (!oTranscriptField.prop("disabled")) { - oTranscriptField.val("' . $aTranscriptData['DNA'] . '"); - oTranscriptField.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); - oTranscriptField.prop("disabled", true); - var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '"); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '"); - }'); - } - - // Returning the mapping for genomic variants. - foreach ($aActiveGBs as $sGBSuffix => $sGBID) { - if (!$_SETT['human_builds'][$sGBID]['supported_by_VV'] - || !isset($aMappedVariant['data']['genomic_mappings'][$sGBID])) { - // If a genome build is active which is not supported by VV, we won't have - // received mapping information on it. We will skip this variant. - continue; - } - // Retrieving the info. - if ($sType == 'VOT') { - // When VV was called using a variant on transcript, we always - // get only one possible mapping, which is formatted as a string. - $sMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; - - } elseif (isset($sCurrentGBSuffix) && $sGBSuffix == $sCurrentGBSuffix) { - // The current build is the build which is the direct reference of - // our input variant. When this is the case, our output is already - // formatted as a string as well. - $sMappedGenomicVariant = $aMappedVariant['data']['DNA']; - - } else { - // Our output is formatted as an array, since multiple variants were possible. - $aMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; - - if (count($aMappedGenomicVariant) <= 1) { - // Only one variant was found. Great! We can simply take the first element. - $sMappedGenomicVariant = $aMappedGenomicVariant[0]; - - } else { - // Multiple possible variants were found. We will give the user a heads-up, - // and concatenate the variants cleanly as follows: - // NC_1233456.1:g.1del + NC_123456.1:g.2_3del + NC_123456.1:g.4del = - // NC_123456.1:g.1del^2_3del^4del. - update_dialogue('
There were multiple genomic variant predictions for build ' . $sGBID . '.'); - - $sMappedGenomicVariant = - preg_replace('/(.*:[a-z]\.).*/', '', $aMappedGenomicVariant[0]) . - implode('^', - array_map(function ($sFullVariant) { - return preg_replace('/.*:[a-z]\./', '', $sFullVariant); - }, $aMappedGenomicVariant) - ); - } - } - - // Filling in the input field. - print(' - // Adding genomic info the fields. - var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); - oGenomicVariant.val("' . preg_replace('/.*:/', '', $sMappedGenomicVariant) . '"); - oGenomicVariant.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); - oGenomicVariant.prop("disabled", true); - '); // Fixme; Find a cleaner way of cutting off the reference sequence. - } - - - // Because we automatically filled all non-blocked positions, - // all open transcript fields have been blocked. We don't - // want the user to block the transcript input at this point - // so we disable the 'Ignore this transcript' option. - print(' - // Disabling the "ignore this transcript" option. - var oIgnoreOption = $(\'input[name^="ignore_"]\'); - oIgnoreOption.parent().html(""); - '); - - - // Send final message to the user. - update_images_per_step($sStepMapping, $sImagePassed); - update_dialogue( - '
Your variant was successfully mapped' . (!isset($bImprovedByVV) ? '' : ', improved') . - ' and validated by VariantValidator. Thank you for your patience!', - $sButtonOKValid); -} -?> + + * + * + * This file is part of LOVD. + * + * LOVD is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * LOVD is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with LOVD. If not, see . + * + *************/ + +define('ROOT_PATH', '../'); +require ROOT_PATH . 'inc-init.php'; +require ROOT_PATH . 'inc-lib-variants.php'; +header('Content-type: text/javascript; charset=UTF-8'); + + +// Preparing necessary functions and variables. +// Retrieving the variant and the transcripts and genome builds to map to. +$sVariant = htmlspecialchars($_REQUEST['var']); +$aTranscripts = explode('|', htmlspecialchars($_REQUEST['transcripts'])); +$aActiveGBs = $_DB->query('SELECT column_suffix, id FROM ' . TABLE_GENOME_BUILDS)->fetchAllCombine(); + +// Retrieving the name of the input field. +$sFieldName = htmlspecialchars($_REQUEST['fieldName']); + +// Preparing the steps. +$sStepInitialChecks = 'statusChecks'; +$sStepMapping = 'statusMapping'; + +// Preparing the images. +$sImageNeutral = 'gfx/trans.png'; +$sImagePassed = 'gfx/check.png'; +$sImageFailed = 'gfx/cross.png'; +$sImageLoading = 'gfx/lovd_loading.gif'; + +// Preparing the buttons. +$sButtonYes = 'oButtonYes'; +$sButtonNo = 'oButtonNo'; +$sButtonOKValid = 'oButtonOKValid'; +$sButtonOKInvalid = 'oButtonOKInvalid'; +$sButtonOKCouldBeValid = 'oButtonOKCouldBeValid'; + +// Preparing the JS for the buttons. +// Fixme; Add to buttonOKValid and buttonOKCouldBeValid: md5 translation of all input. +print(' +// Preparing the buttons. +var ' . $sButtonYes . ' = {"Yes":function () { + // The user accepts the given fixed variant. + // We will fill in this fixed variant, close the dialogue, + // and perform a new call to this script by activating + // the onChange. + var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.val("' . lovd_fixHGVS($sVariant) . '"); + $(this).dialog("close"); + oInput.change(); +}}; +var ' . $sButtonNo . ' = {"No, I will take a look myself":function () { + // The user does not accept the given fixed variant. + var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/cross.png", title: "Please check the HGVS syntax of your variant description before sending it into the database."}).show(); + $(this).dialog("close"); +}}; +var ' . $sButtonOKValid . ' = {"OK":function () { + // The variant was mapped and looks just great! + // All steps have already been taken; the only + // thing left to do is to close the dialogue. + $(this).dialog("close"); +}}; +var ' . $sButtonOKInvalid . ' = {"OK":function () { + // The user agrees to change their invalid input manually. + var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/cross.png", title: "Your variant could not be validated..."}).show(); + $(this).dialog("close"); +}}; +var ' . $sButtonOKCouldBeValid . ' = {"OK":function () { + // We could not validate this variant, but the problem + // lies with us. We will accept this variant and the + // uncertainty that comes with it. + var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "Your variant could not be (in)validated..."}).show(); + $(this).dialog("close"); +}}; +'); + + +// Create a PHP function to easily update the dialogue. +function update_dialogue($sText, $sButtons = '', $bCleanSlate = false) +{ + // This function fills the variantCheckDialogue with the given + // text, adds the right buttons and sends it to the user. + // If $bCleanSlate, it will remove the old text and start over; + // if !$bCleanSlate, it will append. + print(($bCleanSlate ? ' + // Updating the contents. + $("#variantCheckDialogue").html("' . $sText . '
"); + ' : ' + // Appending to the contents. + $("#variantCheckDialogue").append("' . $sText . '
"); + ')); + + print(($sButtons ? ' + // Placing the buttons. + $("#variantCheckDialogue").dialog({buttons: $.extend({}, ' . $sButtons . ')}); + ' : ' + // Removing buttons. + $("#variantCheckDialogue").dialog({buttons: {}}); + ')); + + // Sending the contents directly to the user. + flush(); +} + + +// Create a PHP function to easily update the images to the left of each step. +function update_images_per_step($nStep, $sImage) +{ + // This function takes a step in the format of an integer, and + // replaces the image which was put next to this step by the + // given $sImage. + print('$("#' . $nStep . '").attr({src: "' . $sImage . '"});'); +} + + + + + +// Performing initial checks. +if ($_REQUEST['action'] == 'check') { + + // If the variant is empty, we want to reset all results of this script. + if (!$sVariant) { + print(' + // Resetting all values. + var oInput = $(\'input[name$="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + '); // TODO: Remove the md5 translated variant from the HTML. + + // Returning the mapping for transcript, RNA and protein variants. + foreach ($aTranscripts as $sTranscript) { + print(' + var oTranscriptField = $("input").filter(function() { + return $(this).data("id_ncbi") == "' . $sTranscript . '" + }); + oTranscriptField.val(""); + oTranscriptField.prop("disabled", false); + oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); + '); + } + + // Returning the mapping for genomic variants. + foreach ($aActiveGBs as $sGBSuffix => $sGBID) { + print(' + var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); + oGenomicVariant.val(""); + oGenomicVariant.prop("disabled", false); + oGenomicVariant.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + '); + } + + // Closing the script. + exit(); + } + + // Retrieving information on the reference sequence from the URL. + $sRefSeqInfo = htmlspecialchars($_REQUEST['refSeqInfo']); + + // Opening the dialogue. + print(' + // Setting up the dialogue. + $("body").append("
"); + $("#variantCheckDialogue").dialog({ + draggable:true,resizable:false,minWidth:600,show:"fade",closeOnEscape:false,hide:"fade",modal:true, + open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); } + }); + '); + + update_dialogue( + ' Performing initial checks.', + '', + true + ); + + + // Check whether this variant is supported by LOVD. + $aVariant = lovd_getVariantInfo($sVariant, false); + $bIsSupportedByLOVD = !isset($aVariant['errors']['ENOTSUPPORTED']); + + if (!$bIsSupportedByLOVD) { + // If the variant is not supported by LOVD, we cannot perform an HGVS check nor the mapping. + // We will notify the user and end the script here. + + update_images_per_step($sStepInitialChecks, $sImageFailed); + update_dialogue( + '
Your variant contains syntax which our HGVS check cannot recognise. ' . + 'Therefore, we cannot validate your variant nor map it to other reference sequences. ' . + 'Please thoroughly validate your variant by hand.', + $sButtonOKCouldBeValid); + exit(); + } + + + // Perform our HGVS check. + if (!lovd_isHGVS($sVariant)) { + // If the variant is not HGVS, we cannot send the variant to + // VariantValidator yet. We will try to see if our fixHGVS + // function knows what to do, but if not, we need to exit + // this script and wait for the user to return with a variant + // which we can interpret. + + // Let the user know that the given variant did not pass our HGVS check. + $sResponse = '
Your variant (\"' . $sVariant . '\") did not pass our HGVS check.

'; + update_images_per_step($sStepInitialChecks, $sImageFailed); + + + // Show the user the warnings and errors we found through getVariantInfo. + $aVariantIssues = ($aVariant === false ? array() : array_merge(array_values($aVariant['errors']), array_values($aVariant['warnings']))); + + if (!empty($aVariantIssues)) { + $sResponse .= 'We found the following problems:
- '; + $sResponse .= implode('
-', $aVariantIssues) . '

'; + } + + + // Show the fixed variant if fixHGVS was successful. + $sFixedVariant = lovd_fixHGVS($sVariant); + + if ($sFixedVariant !== $sVariant && lovd_isHGVS($sFixedVariant)) { + // Good, we can propose a fix. If the user agrees with the fix, + // we can continue to the mapping. + update_dialogue($sResponse . 'Did you mean \"' . $sFixedVariant . '\"?
', + $sButtonYes . ', ' . $sButtonNo); + + // Our 'Yes' button sets the steps in motion which change the user's + // input into the fixed variant, and reactivates the dialogue. + // It is then started from the top. + + } else { + // We could not propose a fix. + update_dialogue($sResponse . 'Please check your variant for errors and try again.
', + $sButtonOKInvalid); + } + exit(); + } + + + // Check whether VariantValidator supports the syntax of the variant. + $bIsSupportedByVV = + !(isset($aVariant['warnings']['WNOTSUPPORTED']) + || isset($aVariant['messages']['IUNCERTAINPOSITIONS']) + || isset($aVariant['messages']['IPOSTIONRANGE'])); + + if (!$bIsSupportedByVV) { + // If syntax was found which VariantValidator does not support, we + // cannot send the variant in for mapping. We will notify the + // user and exit this script. + update_images_per_step($sStepInitialChecks, $sImageFailed); + update_dialogue('
Your variant contains syntax which VariantValidator cannot recognise. ' . + 'Therefore, we cannot map your variant nor validate the positions.', + $sButtonOKCouldBeValid); + exit(); + } + + + // Retrieve the reference sequence from the info given through the URL. + if (strpos($sRefSeqInfo, '-') === false) { + // The '-' serves as our little communication tool; it tells + // us that the given input was a GB suffix. When no '-' was + // found, we know that the input was the reference sequence + // of a transcript. + $sType = 'VOT'; + $sReferenceSequence = $sRefSeqInfo; + + } else { + // We know we got information on a GB. This is given through + // JS in the format of -. + $sType = 'VOG'; + list($sCurrentGBSuffix, $sChromosome) = explode('-', $sRefSeqInfo); + + if (!$_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['supported_by_VV']) { + // If the given genome build is not supported by VV, we cannot fully validate + // the variants... We will have to accept these variants into the database + // anyway, since this issue lies with us. + die(' + $("#variantCheckDialogue").dialog("close"); + var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "We validated the syntax, but could not validate the positions."}).show(); + '); + } + + if (!isset($_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome])) { + // The combination of chromosome and build is not known by LOVD. + // Something probably went wrong on the user's end. We will inform + // the user and exit the script. + update_images_per_step($sStepInitialChecks, $sImageFailed); + update_dialogue( + '
An unknown combination of genome build and chromosome was given.' . + ' This means we cannot perform the mapping.', + $sButtonOKInvalid); + exit(); + } + + $sReferenceSequence = $_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome]; + } + + + // Check if the description itself holds a reference sequence. + // if (lovd_holdsRefSeq($sVariant)) { Fixme; Update line below with this line once the necessary code has been pulled in -> Committed in feat/checkHGVSTool on January 14th 2022; ID 7abf9d70dc3094f5f9cfa0dfc43039c49b4217ff. + if (preg_match('/.*:[a-z]\./', $sVariant)) { + // The given variant description holds a reference sequence. + $sRefSeqInDescription = substr($sVariant, 0, strpos($sVariant, ':')); + + if ($sRefSeqInDescription == $sReferenceSequence) { + // Perfect, no issues found; the user redundantly gave + // the reference sequence in the variant description, + // but that is no problem at all, since the given + // refSeq matches our expectations. + $sVariant = $sVariant; + + } else { + // The user gave a refSeq within the variant description + // input which does not match our expectations. The variant + // is then likely to be wrong. We cannot accept it. + update_images_per_step($sStepInitialChecks, $sImageFailed); + update_dialogue( + '
The reference sequence given in the input description, does not equal the' . + ' reference sequence matched to the variant by LOVD automatically. Please have' . + ' another look and perhaps try again from a different input field.', + $sButtonOKInvalid); + exit(); + } + + } else { + // The given variant does not hold a reference sequence. + $sVariant = $sReferenceSequence . ':' . $sVariant; + } + + + // All checks have passed; we are ready for the mapping. + update_images_per_step($sStepInitialChecks, $sImagePassed); + update_dialogue(' Mapping your variant.'); + + print(' + $.get("ajax/check_hgvs_dialogue.php?" + + "action=map" + + "&var=' . $sVariant . '" + + "&fieldName=' . $sFieldName . '" + + "&type=' . $sType . '" + + "&refSeq=' . $sReferenceSequence . '" + + "&transcripts=' . implode('|', $aTranscripts) . '") + .fail(function(){alert("Error while trying to map your variant, please try again later.");}) + '); +} + + + + + +// Performing the mapping. +if ($_REQUEST['action'] == 'map') { + + // Retrieving necessary information from the URL. + $sType = urldecode($_REQUEST['type']); + $sReferenceSequence = urldecode($_REQUEST['refSeq']); + + // Call VariantValidator. + require ROOT_PATH . 'class/variant_validator.php'; + $_VV = new LOVD_VV(); + $aMappedVariant = ( + $sType == 'VOG' ? + $_VV->verifyGenomic($sVariant, array( + 'map_to_transcripts' => empty($aTranscript), // Should we map the variant to transcripts? + 'predict_protein' => empty($aTranscript), // Should we get protein predictions? + 'lift_over' => (count($aActiveGBs) > 1), // Should we get other genomic mappings of this variant? + 'select_transcripts' => (empty($aTranscripts) ? array() : $aTranscripts), + )) : + $_VV->verifyVariant($sVariant, array('select_transcripts' => $aTranscripts)) + ); + + // Check for issues for which the user cannot be blamed. + if ($aMappedVariant === false + || in_array(array_keys($aMappedVariant['errors']), array(array('EBUILD'), array('ESYNTAX')))) { + // If our VV call returned false, or if we found an EBUILD or ESYNTAX + // error, this is an issue that lies with us, not the user. + // We will have to allow these variants into the database. + update_images_per_step($sStepMapping, $sImageFailed); + update_dialogue( + '
Something went wrong on our side, which means we could not map nor validate your variant.', + $sButtonOKCouldBeValid + ); + exit(); + } + + + // Check if VariantValidator bumped into any issues. + if (!empty($aMappedVariant['errors'])) { + // The variant holds a fatal issue. We will exit the script and not + // accept this variant into the database. + + update_images_per_step($sStepMapping, $sImageFailed); + update_dialogue( + '
We could not validate nor map your variant because of the following problem(s):
- ' . + implode('
-', $aMappedVariant['errors']) . '

' . + 'Please take another look at your variant and try again.', + $sButtonOKInvalid); + exit(); + } + + // Check for warnings. + if (!empty($aMappedVariant['warnings'])) { + // One or more warnings were found. Perhaps the variant was corrected? + + if (isset($aMappedVariant['warnings']['WROLLBACK']) + || isset($aMappedVariant['warnings']['WCORRECTED'])) { + // The variant was corrected. + update_dialogue('
Your variant was corrected to ' . $aMappedVariant['data']['DNA'] . + ' to fully match HGVS guidelines.'); + $bImprovedByVV = true; + } + + if (isset($aMappedVariant['warnings']['WFLAG'])) { + // This type of warning tells us that VariantValidator had a problem + // which is an issue with them, not us nor our user. We can only get + // the mapping on all genome builds, not on (other) transcripts. + // We will notify the user. + update_dialogue('
Your variant could not fully be validated due to unknown issues.'); + // Fixme; Either find a fix within VV, or Call Mutalyzer. + } + + // Check whether the mapping was successful. + } elseif (!isset($aMappedVariant['data']['DNA']) + || empty($aMappedVariant['data']['DNA'])) { + // Although we did not receive any warnings or errors, the DNA field + // is left empty. This means we have no information on the mapping + // and there is not much we can do... We will inform the user that + // an unknown error occurred and that they should try again later. + update_images_per_step($sStepMapping, $sImageFailed); + update_dialogue( + '
An unknown error occurred while trying to validate and map your variant.' . + ' We are sorry for the inconvenience. Please try again later.', + $sButtonOKInvalid); + exit(); + } + + + // When sending in a variant on transcript, VariantValidator only + // returns the variant as mapped on that one transcript. If we are + // on a VOT creation form, and there are multiple transcripts open, + // we want each transcript to get a mapping. To get this, we then + // need to call VariantValidator a second time using one of the + // genomic variant as were returned using our first call. + if ($sType == 'VOT' && count($aTranscripts) > 1) { + + $aMappedViaGB = ( + !isset($aMappedVariant['data']['genomic_mappings']['hg38']) ? // Yes=We have a genomic reference from our first call; No=We don't have a genomic reference. + array() : + $_VV->verifyGenomic($aMappedVariant['data']['genomic_mappings']['hg38'], array( + 'map_to_transcripts' => true, // Should we map the variant to transcripts? + 'predict_protein' => true, // Should we get protein predictions? + 'lift_over' => false, // Should we get other genomic mappings of this variant? + 'select_transcripts' => array_diff($aTranscripts, array($sReferenceSequence)), // Should we limit our output to only a certain set of transcripts? + )) + ); + + if (!isset($aMappedViaGB['data']['transcript_mappings'])) { + // If for any reason no genomic mappings were given, we cannot perform this + // extra step, and will thus miss some information. We will inform the user. + update_dialogue('
Your variant could not be mapped to all transcripts due to unknown issues.'); + } + + $aMappedVariant['data']['transcript_mappings'] = $aMappedViaGB['data']['transcript_mappings']; + + unset($aMappedViaGB); // We don't need the rest of this information. + } + + + // Add mapping information to the right fields. + + // Returning the mapping for transcript, RNA and protein variants. + foreach ($aTranscripts as $sTranscript) { + if (!isset($aMappedVariant['data']['transcript_mappings'][$sTranscript]) + && $sTranscript != $sReferenceSequence) { + // If no mapping was found for this transcript, we skip it. + continue; + } + // Retrieving the info. + $aTranscriptData = ($sTranscript == $sReferenceSequence ? // Yes=Variant of origin (stored directly in data); No=Other (stored in transcript_mappings) + $aMappedVariant['data'] : $aMappedVariant['data']['transcript_mappings'][$sTranscript]); + + // Filling in the input fields. + print(' + // Adding transcript info to the fields. + var oTranscriptField = $("input").filter(function() { + return $(this).data("id_ncbi") == "' . $sTranscript . '" + }); + + if (!oTranscriptField.prop("disabled")) { + oTranscriptField.val("' . $aTranscriptData['DNA'] . '"); + oTranscriptField.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); + oTranscriptField.prop("disabled", true); + var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '"); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '"); + }'); + } + + // Returning the mapping for genomic variants. + foreach ($aActiveGBs as $sGBSuffix => $sGBID) { + if (!$_SETT['human_builds'][$sGBID]['supported_by_VV'] + || !isset($aMappedVariant['data']['genomic_mappings'][$sGBID])) { + // If a genome build is active which is not supported by VV, we won't have + // received mapping information on it. We will skip this variant. + continue; + } + // Retrieving the info. + if ($sType == 'VOT') { + // When VV was called using a variant on transcript, we always + // get only one possible mapping, which is formatted as a string. + $sMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; + + } elseif (isset($sCurrentGBSuffix) && $sGBSuffix == $sCurrentGBSuffix) { + // The current build is the build which is the direct reference of + // our input variant. When this is the case, our output is already + // formatted as a string as well. + $sMappedGenomicVariant = $aMappedVariant['data']['DNA']; + + } else { + // Our output is formatted as an array, since multiple variants were possible. + $aMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; + + if (count($aMappedGenomicVariant) <= 1) { + // Only one variant was found. Great! We can simply take the first element. + $sMappedGenomicVariant = $aMappedGenomicVariant[0]; + + } else { + // Multiple possible variants were found. We will give the user a heads-up, + // and concatenate the variants cleanly as follows: + // NC_1233456.1:g.1del + NC_123456.1:g.2_3del + NC_123456.1:g.4del = + // NC_123456.1:g.1del^2_3del^4del. + update_dialogue('
There were multiple genomic variant predictions for build ' . $sGBID . '.'); + + $sMappedGenomicVariant = + preg_replace('/(.*:[a-z]\.).*/', '', $aMappedGenomicVariant[0]) . + implode('^', + array_map(function ($sFullVariant) { + return preg_replace('/.*:[a-z]\./', '', $sFullVariant); + }, $aMappedGenomicVariant) + ); + } + } + + // Filling in the input field. + print(' + // Adding genomic info the fields. + var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); + oGenomicVariant.val("' . preg_replace('/.*:/', '', $sMappedGenomicVariant) . '"); + oGenomicVariant.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); + oGenomicVariant.prop("disabled", true); + '); // Fixme; Find a cleaner way of cutting off the reference sequence. + } + + + // Because we automatically filled all non-blocked positions, + // all open transcript fields have been blocked. We don't + // want the user to block the transcript input at this point + // so we disable the 'Ignore this transcript' option. + print(' + // Disabling the "ignore this transcript" option. + var oIgnoreOption = $(\'input[name^="ignore_"]\'); + oIgnoreOption.parent().html(""); + '); + + + // Send final message to the user. + update_images_per_step($sStepMapping, $sImagePassed); + update_dialogue( + '
Your variant was successfully mapped' . (!isset($bImprovedByVV) ? '' : ', improved') . + ' and validated by VariantValidator. Thank you for your patience!', + $sButtonOKValid); +} +?> From 9915eda7ecffc8edc93fd533c173de12f802f581 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 24 Feb 2022 11:48:35 +0100 Subject: [PATCH 24/95] Reset the output if the variant is an empty string --- src/ajax/check_hgvs_dialogue.php | 79 +++++++++++++++++--------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 1da17cca..b2c395d6 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -34,7 +34,6 @@ header('Content-type: text/javascript; charset=UTF-8'); -// Preparing necessary functions and variables. // Retrieving the variant and the transcripts and genome builds to map to. $sVariant = htmlspecialchars($_REQUEST['var']); $aTranscripts = explode('|', htmlspecialchars($_REQUEST['transcripts'])); @@ -43,6 +42,47 @@ // Retrieving the name of the input field. $sFieldName = htmlspecialchars($_REQUEST['fieldName']); + + +// If the variant is empty, we want to reset all results of this script. +if (!$sVariant) { + print(' + // Resetting all values. + var oInput = $(\'input[name$="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + '); // TODO: Remove the md5 translated variant from the HTML. + + // Returning the mapping for transcript, RNA and protein variants. + foreach ($aTranscripts as $sTranscript) { + print(' + var oTranscriptField = $("input").filter(function() { + return $(this).data("id_ncbi") == "' . $sTranscript . '" + }); + oTranscriptField.val(""); + oTranscriptField.prop("disabled", false); + oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); + '); + } + + // Returning the mapping for genomic variants. + foreach ($aActiveGBs as $sGBSuffix => $sGBID) { + print(' + var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); + oGenomicVariant.val(""); + oGenomicVariant.prop("disabled", false); + oGenomicVariant.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + '); + } + + // Closing the script. + exit(); +} + + + // Preparing the steps. $sStepInitialChecks = 'statusChecks'; $sStepMapping = 'statusMapping'; @@ -147,43 +187,6 @@ function update_images_per_step($nStep, $sImage) // Performing initial checks. if ($_REQUEST['action'] == 'check') { - // If the variant is empty, we want to reset all results of this script. - if (!$sVariant) { - print(' - // Resetting all values. - var oInput = $(\'input[name$="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); // TODO: Remove the md5 translated variant from the HTML. - - // Returning the mapping for transcript, RNA and protein variants. - foreach ($aTranscripts as $sTranscript) { - print(' - var oTranscriptField = $("input").filter(function() { - return $(this).data("id_ncbi") == "' . $sTranscript . '" - }); - oTranscriptField.val(""); - oTranscriptField.prop("disabled", false); - oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); - '); - } - - // Returning the mapping for genomic variants. - foreach ($aActiveGBs as $sGBSuffix => $sGBID) { - print(' - var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); - oGenomicVariant.val(""); - oGenomicVariant.prop("disabled", false); - oGenomicVariant.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); - } - - // Closing the script. - exit(); - } - // Retrieving information on the reference sequence from the URL. $sRefSeqInfo = htmlspecialchars($_REQUEST['refSeqInfo']); From 6e4e443eb1ef950faa528eea8bd58e4101def742 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 24 Feb 2022 11:58:13 +0100 Subject: [PATCH 25/95] Handle exit as a statement instead of a function --- src/ajax/check_hgvs_dialogue.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index b2c395d6..22106824 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -78,7 +78,7 @@ } // Closing the script. - exit(); + exit; } @@ -221,7 +221,7 @@ function update_images_per_step($nStep, $sImage) 'Therefore, we cannot validate your variant nor map it to other reference sequences. ' . 'Please thoroughly validate your variant by hand.', $sButtonOKCouldBeValid); - exit(); + exit; } @@ -265,7 +265,7 @@ function update_images_per_step($nStep, $sImage) update_dialogue($sResponse . 'Please check your variant for errors and try again.
', $sButtonOKInvalid); } - exit(); + exit; } @@ -283,7 +283,7 @@ function update_images_per_step($nStep, $sImage) update_dialogue('
Your variant contains syntax which VariantValidator cannot recognise. ' . 'Therefore, we cannot map your variant nor validate the positions.', $sButtonOKCouldBeValid); - exit(); + exit; } @@ -322,7 +322,7 @@ function update_images_per_step($nStep, $sImage) '
An unknown combination of genome build and chromosome was given.' . ' This means we cannot perform the mapping.', $sButtonOKInvalid); - exit(); + exit; } $sReferenceSequence = $_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome]; @@ -352,7 +352,7 @@ function update_images_per_step($nStep, $sImage) ' reference sequence matched to the variant by LOVD automatically. Please have' . ' another look and perhaps try again from a different input field.', $sButtonOKInvalid); - exit(); + exit; } } else { @@ -413,7 +413,7 @@ function update_images_per_step($nStep, $sImage) '
Something went wrong on our side, which means we could not map nor validate your variant.', $sButtonOKCouldBeValid ); - exit(); + exit; } @@ -428,7 +428,7 @@ function update_images_per_step($nStep, $sImage) implode('
-', $aMappedVariant['errors']) . '

' . 'Please take another look at your variant and try again.', $sButtonOKInvalid); - exit(); + exit; } // Check for warnings. @@ -464,7 +464,7 @@ function update_images_per_step($nStep, $sImage) '
An unknown error occurred while trying to validate and map your variant.' . ' We are sorry for the inconvenience. Please try again later.', $sButtonOKInvalid); - exit(); + exit; } From ea1e4bd4e93ab44af090865e6c2276d5fd7ccc74 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Fri, 25 Feb 2022 10:21:04 +0100 Subject: [PATCH 26/95] Clean up bits of the code --- src/ajax/check_hgvs_dialogue.php | 15 +++++++++------ src/inc-js-variants.php | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 22106824..1d00909f 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -177,7 +177,10 @@ function update_images_per_step($nStep, $sImage) // This function takes a step in the format of an integer, and // replaces the image which was put next to this step by the // given $sImage. - print('$("#' . $nStep . '").attr({src: "' . $sImage . '"});'); + print(' + // Updating one of the status images. + $("#' . $nStep . '").attr({src: "' . $sImage . '"}); + '); } @@ -372,8 +375,8 @@ function update_images_per_step($nStep, $sImage) + "&fieldName=' . $sFieldName . '" + "&type=' . $sType . '" + "&refSeq=' . $sReferenceSequence . '" - + "&transcripts=' . implode('|', $aTranscripts) . '") - .fail(function(){alert("Error while trying to map your variant, please try again later.");}) + + "&transcripts=' . implode('|', $aTranscripts) . '" + ).fail(function(){alert("An error occurred while trying to map your variant, please try again later.");}) '); } @@ -394,9 +397,9 @@ function update_images_per_step($nStep, $sImage) $aMappedVariant = ( $sType == 'VOG' ? $_VV->verifyGenomic($sVariant, array( - 'map_to_transcripts' => empty($aTranscript), // Should we map the variant to transcripts? - 'predict_protein' => empty($aTranscript), // Should we get protein predictions? - 'lift_over' => (count($aActiveGBs) > 1), // Should we get other genomic mappings of this variant? + 'map_to_transcripts' => !empty($aTranscript), // Should we map the variant to transcripts? + 'predict_protein' => !empty($aTranscript), // Should we get protein predictions? + 'lift_over' => (count($aActiveGBs) > 1), // Should we get other genomic mappings of this variant? 'select_transcripts' => (empty($aTranscripts) ? array() : $aTranscripts), )) : $_VV->verifyVariant($sVariant, array('select_transcripts' => $aTranscripts)) diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index 9b65103d..fef09930 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -188,8 +188,8 @@ function lovd_checkHGVS(e) { + "&var=" + encodeURIComponent(sVariant) + "&fieldName=" + encodeURIComponent(sFieldName) + "&refSeqInfo=" + encodeURIComponent(sRefSeqInfo) - + "&transcripts=" + encodeURIComponent(sTranscripts)) - .fail(function(){alert("Error checking your variant, please try again later.");}) + + "&transcripts=" + encodeURIComponent(sTranscripts) + ).fail(function(){alert("Error checking your variant, please try again later.");}) ; } From 4f57803391aa084c6640d3845be62f5686bec85a Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Sat, 26 Feb 2022 08:23:11 +0100 Subject: [PATCH 27/95] WIP: Save md5 translation of validated variants The md5 translation of validated variants will later serve to check whether the received input was indeed validated, and can thus be sent to the database. --- src/ajax/check_hgvs_dialogue.php | 19 +++++++++++++++++-- src/inc-lib-variants.php | 19 +++++++++++++++++++ src/variants.php | 1 + 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 1d00909f..12880510 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -137,6 +137,7 @@ // lies with us. We will accept this variant and the // uncertainty that comes with it. var oInput = $(\'input[name="' . $sFieldName . '"]\'); + $("#codedVariants").val("' . lovd_getMD5TranslationOfVariants(array($sVariant)) . '"); oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "Your variant could not be (in)validated..."}).show(); $(this).dialog("close"); }}; @@ -503,6 +504,7 @@ function update_images_per_step($nStep, $sImage) // Add mapping information to the right fields. + $aAllValidatedVariants = array(); // Returning the mapping for transcript, RNA and protein variants. foreach ($aTranscripts as $sTranscript) { @@ -515,6 +517,9 @@ function update_images_per_step($nStep, $sImage) $aTranscriptData = ($sTranscript == $sReferenceSequence ? // Yes=Variant of origin (stored directly in data); No=Other (stored in transcript_mappings) $aMappedVariant['data'] : $aMappedVariant['data']['transcript_mappings'][$sTranscript]); + // Adding the validated variant to the rest of the validated variants. + array_push($aAllValidatedVariants, $aTranscriptData['DNA']); + // Filling in the input fields. print(' // Adding transcript info to the fields. @@ -577,14 +582,19 @@ function update_images_per_step($nStep, $sImage) } } + $sMappedGenomicVariant = preg_replace('/.*:/', '', $sMappedGenomicVariant); // Fixme; Find a cleaner way of cutting off the reference sequence. + + // Adding the validated variant to the rest of the validated variants. + array_push($aAllValidatedVariants, $sMappedGenomicVariant); + // Filling in the input field. print(' // Adding genomic info the fields. var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); - oGenomicVariant.val("' . preg_replace('/.*:/', '', $sMappedGenomicVariant) . '"); + oGenomicVariant.val("' . $sMappedGenomicVariant . '"); oGenomicVariant.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); oGenomicVariant.prop("disabled", true); - '); // Fixme; Find a cleaner way of cutting off the reference sequence. + '); } @@ -592,10 +602,15 @@ function update_images_per_step($nStep, $sImage) // all open transcript fields have been blocked. We don't // want the user to block the transcript input at this point // so we disable the 'Ignore this transcript' option. + // And now that we're all done, we can also fill in the md5 + // translation of our validated variants. print(' // Disabling the "ignore this transcript" option. var oIgnoreOption = $(\'input[name^="ignore_"]\'); oIgnoreOption.parent().html(""); + + // Adding the md5 translation of the validated variants. + $("#codedVariants").val("' . lovd_getMD5TranslationOfVariants($aAllValidatedVariants) . '"); '); diff --git a/src/inc-lib-variants.php b/src/inc-lib-variants.php index fb6ed3b7..5ecb7465 100644 --- a/src/inc-lib-variants.php +++ b/src/inc-lib-variants.php @@ -619,6 +619,25 @@ function lovd_fixHGVS ($sVariant, $sType = '') + +function lovd_getMD5TranslationOfVariants ($aVariants) +{ + // This function can be used to get a secret and unique + // key for a certain set of variants. + // The function should be given an array of variants + // that are to be translated into md5. The order of + // the variants does not matter, since this function + // will sort the variants before translating them into + // an md5 hash. + sort($aVariants); + return md5(implode('', $aVariants)); +} + + + + + + /** * Predict a protein description of a variant and given transcript using the * Mutalyzer webservice. diff --git a/src/variants.php b/src/variants.php index 3c7844fc..fb0ae761 100644 --- a/src/variants.php +++ b/src/variants.php @@ -957,6 +957,7 @@ function(sData) { // Table. print(' ' . "\n" . + ' ' . ' ' . "\n"); // Array which will make up the form table. From 4562560176923c81105054d490edef364f201903 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Sat, 26 Feb 2022 08:23:11 +0100 Subject: [PATCH 28/95] WIP: Save md5 translation of validated variants The md5 translation of validated variants will later serve to check whether the received input was indeed validated, and can thus be sent to the database. --- src/ajax/check_hgvs_dialogue.php | 20 +++++++++++++++++--- src/inc-lib-variants.php | 19 +++++++++++++++++++ src/variants.php | 1 + 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 1d00909f..972412bf 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -101,7 +101,6 @@ $sButtonOKCouldBeValid = 'oButtonOKCouldBeValid'; // Preparing the JS for the buttons. -// Fixme; Add to buttonOKValid and buttonOKCouldBeValid: md5 translation of all input. print(' // Preparing the buttons. var ' . $sButtonYes . ' = {"Yes":function () { @@ -137,6 +136,7 @@ // lies with us. We will accept this variant and the // uncertainty that comes with it. var oInput = $(\'input[name="' . $sFieldName . '"]\'); + $("#codedVariants").val("' . lovd_getMD5TranslationOfVariants(array($sVariant)) . '"); oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "Your variant could not be (in)validated..."}).show(); $(this).dialog("close"); }}; @@ -503,6 +503,7 @@ function update_images_per_step($nStep, $sImage) // Add mapping information to the right fields. + $aAllValidatedVariants = array(); // Returning the mapping for transcript, RNA and protein variants. foreach ($aTranscripts as $sTranscript) { @@ -515,6 +516,9 @@ function update_images_per_step($nStep, $sImage) $aTranscriptData = ($sTranscript == $sReferenceSequence ? // Yes=Variant of origin (stored directly in data); No=Other (stored in transcript_mappings) $aMappedVariant['data'] : $aMappedVariant['data']['transcript_mappings'][$sTranscript]); + // Adding the validated variant to the rest of the validated variants. + array_push($aAllValidatedVariants, $aTranscriptData['DNA']); + // Filling in the input fields. print(' // Adding transcript info to the fields. @@ -577,14 +581,19 @@ function update_images_per_step($nStep, $sImage) } } + $sMappedGenomicVariant = preg_replace('/.*:/', '', $sMappedGenomicVariant); // Fixme; Find a cleaner way of cutting off the reference sequence. + + // Adding the validated variant to the rest of the validated variants. + array_push($aAllValidatedVariants, $sMappedGenomicVariant); + // Filling in the input field. print(' // Adding genomic info the fields. var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); - oGenomicVariant.val("' . preg_replace('/.*:/', '', $sMappedGenomicVariant) . '"); + oGenomicVariant.val("' . $sMappedGenomicVariant . '"); oGenomicVariant.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); oGenomicVariant.prop("disabled", true); - '); // Fixme; Find a cleaner way of cutting off the reference sequence. + '); } @@ -592,10 +601,15 @@ function update_images_per_step($nStep, $sImage) // all open transcript fields have been blocked. We don't // want the user to block the transcript input at this point // so we disable the 'Ignore this transcript' option. + // And now that we're all done, we can also fill in the md5 + // translation of our validated variants. print(' // Disabling the "ignore this transcript" option. var oIgnoreOption = $(\'input[name^="ignore_"]\'); oIgnoreOption.parent().html(""); + + // Adding the md5 translation of the validated variants. + $("#codedVariants").val("' . lovd_getMD5TranslationOfVariants($aAllValidatedVariants) . '"); '); diff --git a/src/inc-lib-variants.php b/src/inc-lib-variants.php index fb6ed3b7..5ecb7465 100644 --- a/src/inc-lib-variants.php +++ b/src/inc-lib-variants.php @@ -619,6 +619,25 @@ function lovd_fixHGVS ($sVariant, $sType = '') + +function lovd_getMD5TranslationOfVariants ($aVariants) +{ + // This function can be used to get a secret and unique + // key for a certain set of variants. + // The function should be given an array of variants + // that are to be translated into md5. The order of + // the variants does not matter, since this function + // will sort the variants before translating them into + // an md5 hash. + sort($aVariants); + return md5(implode('', $aVariants)); +} + + + + + + /** * Predict a protein description of a variant and given transcript using the * Mutalyzer webservice. diff --git a/src/variants.php b/src/variants.php index 3c7844fc..fb0ae761 100644 --- a/src/variants.php +++ b/src/variants.php @@ -957,6 +957,7 @@ function(sData) { // Table. print(' ' . "\n" . + ' ' . ' ' . "\n"); // Array which will make up the form table. From 0ba1f0c2de915cb8f17fe1f983b897cb58afa690 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Tue, 1 Mar 2022 08:27:49 +0100 Subject: [PATCH 29/95] Fix bug when no transcripts are given --- src/ajax/check_hgvs_dialogue.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 972412bf..b0648dc7 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -36,7 +36,7 @@ // Retrieving the variant and the transcripts and genome builds to map to. $sVariant = htmlspecialchars($_REQUEST['var']); -$aTranscripts = explode('|', htmlspecialchars($_REQUEST['transcripts'])); +$aTranscripts = (empty($_REQUEST['transcripts'])? array() : explode('|', htmlspecialchars($_REQUEST['transcripts']))); $aActiveGBs = $_DB->query('SELECT column_suffix, id FROM ' . TABLE_GENOME_BUILDS)->fetchAllCombine(); // Retrieving the name of the input field. @@ -400,7 +400,7 @@ function update_images_per_step($nStep, $sImage) 'map_to_transcripts' => !empty($aTranscript), // Should we map the variant to transcripts? 'predict_protein' => !empty($aTranscript), // Should we get protein predictions? 'lift_over' => (count($aActiveGBs) > 1), // Should we get other genomic mappings of this variant? - 'select_transcripts' => (empty($aTranscripts) ? array() : $aTranscripts), + 'select_transcripts' => $aTranscripts, )) : $_VV->verifyVariant($sVariant, array('select_transcripts' => $aTranscripts)) ); From b0ffbbe1c4e3eaedbafb8265c0f554f85e04e9a8 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Tue, 1 Mar 2022 10:40:05 +0100 Subject: [PATCH 30/95] Fix issue causing blocked fields to not reach POST When using field.prop("disabled", true), the webpage assumes we don't want to see this information in the POST. However, in our case, we do want to get this info. So, instead of using disabled=true, we change the CSS of the input fields we want to block. --- src/ajax/check_hgvs_dialogue.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index b0648dc7..4b315b0e 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -52,14 +52,14 @@ oInput.siblings("img:first").attr({src: "gfx/trans.png"}).show(); '); // TODO: Remove the md5 translated variant from the HTML. - // Returning the mapping for transcript, RNA and protein variants. + // Resetting the mapping for transcript, RNA and protein variants. foreach ($aTranscripts as $sTranscript) { print(' var oTranscriptField = $("input").filter(function() { return $(this).data("id_ncbi") == "' . $sTranscript . '" }); oTranscriptField.val(""); - oTranscriptField.prop("disabled", false); + oTranscriptField.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); @@ -67,12 +67,12 @@ '); } - // Returning the mapping for genomic variants. + // Resetting the mapping for genomic variants. foreach ($aActiveGBs as $sGBSuffix => $sGBID) { print(' var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); oGenomicVariant.val(""); - oGenomicVariant.prop("disabled", false); + oGenomicVariant.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); oGenomicVariant.siblings("img:first").attr({src: "gfx/trans.png"}).show(); '); } @@ -529,7 +529,7 @@ function update_images_per_step($nStep, $sImage) if (!oTranscriptField.prop("disabled")) { oTranscriptField.val("' . $aTranscriptData['DNA'] . '"); oTranscriptField.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); - oTranscriptField.prop("disabled", true); + oTranscriptField.css({"pointer-events": "none", "background-color": "lightgrey", "color": "grey"}); var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '"); $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '"); @@ -592,7 +592,7 @@ function update_images_per_step($nStep, $sImage) var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); oGenomicVariant.val("' . $sMappedGenomicVariant . '"); oGenomicVariant.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); - oGenomicVariant.prop("disabled", true); + oGenomicVariant.css({"pointer-events": "none", "background-color": "lightgrey", "color": "grey"}); '); } From a8afce5178021382eda05efe69c91bc5dc78240a Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Tue, 1 Mar 2022 10:51:21 +0100 Subject: [PATCH 31/95] Fix issue when setting the md5 key after validation Also: remove redundancy in the code which resets all values when an input field was emptied, and reset the md5 key when the input field was emptied. --- src/ajax/check_hgvs_dialogue.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 4b315b0e..27ab1922 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -47,14 +47,14 @@ // If the variant is empty, we want to reset all results of this script. if (!$sVariant) { print(' - // Resetting all values. - var oInput = $(\'input[name$="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); // TODO: Remove the md5 translated variant from the HTML. + // Resetting the md5 key. + $(\'input[name="codedVariants"]\').val(""); + '); // Resetting the mapping for transcript, RNA and protein variants. foreach ($aTranscripts as $sTranscript) { - print(' + print(' + // Resetting the transcript fields. var oTranscriptField = $("input").filter(function() { return $(this).data("id_ncbi") == "' . $sTranscript . '" }); @@ -70,6 +70,7 @@ // Resetting the mapping for genomic variants. foreach ($aActiveGBs as $sGBSuffix => $sGBID) { print(' + // Resetting the genomic fields. var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); oGenomicVariant.val(""); oGenomicVariant.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); @@ -135,8 +136,8 @@ // We could not validate this variant, but the problem // lies with us. We will accept this variant and the // uncertainty that comes with it. + $(\'input[name="codedVariants"]\').val("' . lovd_getMD5TranslationOfVariants(array($sVariant)) . '"); var oInput = $(\'input[name="' . $sFieldName . '"]\'); - $("#codedVariants").val("' . lovd_getMD5TranslationOfVariants(array($sVariant)) . '"); oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "Your variant could not be (in)validated..."}).show(); $(this).dialog("close"); }}; @@ -609,7 +610,7 @@ function update_images_per_step($nStep, $sImage) oIgnoreOption.parent().html(""); // Adding the md5 translation of the validated variants. - $("#codedVariants").val("' . lovd_getMD5TranslationOfVariants($aAllValidatedVariants) . '"); + $(\'input[name="codedVariants"]\').val("' . lovd_getMD5TranslationOfVariants($aAllValidatedVariants) . '"); '); From 07b52e63ed05219cb883704703e69ef55f392114 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Tue, 1 Mar 2022 11:10:46 +0100 Subject: [PATCH 32/95] Update documentation to better fit the code --- src/ajax/check_hgvs_dialogue.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 5a85beba..551ed449 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -504,7 +504,8 @@ function update_images_per_step($nStep, $sImage) } - // Add mapping information to the right fields. + // Save an array with all validated variants, to later + // use to make an md5 key of the input. $aAllValidatedVariants = array(); // Returning the mapping for transcript, RNA and protein variants. From 7e75c354cc0a9fc5ba68e4ffd1a9c7166c70851f Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Tue, 1 Mar 2022 11:12:37 +0100 Subject: [PATCH 33/95] Fix indentation --- src/ajax/check_hgvs_dialogue.php | 74 ++++++++++++++++---------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 551ed449..75d71bf1 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -47,35 +47,35 @@ // If the variant is empty, we want to reset all results of this script. if (!$sVariant) { print(' - // Resetting the md5 key. - $(\'input[name="codedVariants"]\').val(""); - '); + // Resetting the md5 key. + $(\'input[name="codedVariants"]\').val(""); + '); // Resetting the mapping for transcript, RNA and protein variants. foreach ($aTranscripts as $sTranscript) { print(' - // Resetting the transcript fields. - var oTranscriptField = $("input").filter(function() { - return $(this).data("id_ncbi") == "' . $sTranscript . '" - }); - oTranscriptField.val(""); - oTranscriptField.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); - oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); - '); + // Resetting the transcript fields. + var oTranscriptField = $("input").filter(function() { + return $(this).data("id_ncbi") == "' . $sTranscript . '" + }); + oTranscriptField.val(""); + oTranscriptField.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); + oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); + '); } // Resetting the mapping for genomic variants. foreach ($aActiveGBs as $sGBSuffix => $sGBID) { print(' - // Resetting the genomic fields. - var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); - oGenomicVariant.val(""); - oGenomicVariant.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); - oGenomicVariant.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); + // Resetting the genomic fields. + var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); + oGenomicVariant.val(""); + oGenomicVariant.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); + oGenomicVariant.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + '); } // Closing the script. @@ -312,10 +312,10 @@ function update_images_per_step($nStep, $sImage) // the variants... We will have to accept these variants into the database // anyway, since this issue lies with us. die(' - $("#variantCheckDialogue").dialog("close"); - var oInput = $(\'input[name="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "We validated the syntax, but could not validate the positions."}).show(); - '); + $("#variantCheckDialogue").dialog("close"); + var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "We validated the syntax, but could not validate the positions."}).show(); + '); } if (!isset($_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome])) { @@ -524,19 +524,19 @@ function update_images_per_step($nStep, $sImage) // Filling in the input fields. print(' - // Adding transcript info to the fields. - var oTranscriptField = $("input").filter(function() { - return $(this).data("id_ncbi") == "' . $sTranscript . '" - }); - - if (!oTranscriptField.prop("disabled")) { - oTranscriptField.val("' . $aTranscriptData['DNA'] . '"); - oTranscriptField.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); - oTranscriptField.css({"pointer-events": "none", "background-color": "lightgrey", "color": "grey"}); - var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '"); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '"); - }'); + // Adding transcript info to the fields. + var oTranscriptField = $("input").filter(function() { + return $(this).data("id_ncbi") == "' . $sTranscript . '" + }); + + if (!oTranscriptField.prop("disabled")) { + oTranscriptField.val("' . $aTranscriptData['DNA'] . '"); + oTranscriptField.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); + oTranscriptField.css({"pointer-events": "none", "background-color": "lightgrey", "color": "grey"}); + var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '"); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '"); + }'); } // Returning the mapping for genomic variants. From fc9049197b323827d8ef8d37623d9f8112d66909 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Wed, 2 Mar 2022 10:07:32 +0100 Subject: [PATCH 34/95] Fetch GB IDs using the data element and not SQL Before this commit, the database was being queried to get the IDs of the active GBs. However, this would no longer be necessary, since we pulled in the code which attaches this information using the data functiona- lity of HTML/JS objects. So with this commit, the .data() function from jQuery replaces the previous DB query. Also: the way the transcripts were being identified and filled in after the mapping has been changed to match the new approach for the genome builds. --- src/ajax/check_hgvs_dialogue.php | 133 ++++++++++++++----------------- src/inc-js-variants.php | 2 +- 2 files changed, 62 insertions(+), 73 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 75d71bf1..c75467d1 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -34,10 +34,9 @@ header('Content-type: text/javascript; charset=UTF-8'); -// Retrieving the variant and the transcripts and genome builds to map to. +// Retrieving the variant and the transcripts to map to. $sVariant = htmlspecialchars($_REQUEST['var']); $aTranscripts = (empty($_REQUEST['transcripts'])? array() : explode('|', htmlspecialchars($_REQUEST['transcripts']))); -$aActiveGBs = $_DB->query('SELECT column_suffix, id FROM ' . TABLE_GENOME_BUILDS)->fetchAllCombine(); // Retrieving the name of the input field. $sFieldName = htmlspecialchars($_REQUEST['fieldName']); @@ -64,19 +63,17 @@ var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); - '); + '); // Fixme; Should this perhaps be rewritten using a JS loop, or by adjusting all variables at once in JS? } // Resetting the mapping for genomic variants. - foreach ($aActiveGBs as $sGBSuffix => $sGBID) { - print(' - // Resetting the genomic fields. - var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); - oGenomicVariant.val(""); - oGenomicVariant.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); - oGenomicVariant.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); - } + print(' + // Resetting the genomic fields. + var oGenomicVariants = $(\'#variantForm input[name^="VariantOnGenome/DNA"]\'); + oGenomicVariants.val(""); + oGenomicVariants.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); + oGenomicVariants.siblings("img:first").attr({src: "gfx/trans.png"}).show(); + '); // Closing the script. exit; @@ -294,8 +291,8 @@ function update_images_per_step($nStep, $sImage) // Retrieve the reference sequence from the info given through the URL. if (strpos($sRefSeqInfo, '-') === false) { - // The '-' serves as our little communication tool; it tells - // us that the given input was a GB suffix. When no '-' was + // The '-' serves as a communication tool; it tells us that + // the given input was a GB + chromosome. When no '-' is // found, we know that the input was the reference sequence // of a transcript. $sType = 'VOT'; @@ -305,9 +302,9 @@ function update_images_per_step($nStep, $sImage) // We know we got information on a GB. This is given through // JS in the format of -. $sType = 'VOG'; - list($sCurrentGBSuffix, $sChromosome) = explode('-', $sRefSeqInfo); + list($sGenomeBuildID, $sChromosome) = explode('-', $sRefSeqInfo); - if (!$_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['supported_by_VV']) { + if (!$_SETT['human_builds'][$sGenomeBuildID]['supported_by_VV']) { // If the given genome build is not supported by VV, we cannot fully validate // the variants... We will have to accept these variants into the database // anyway, since this issue lies with us. @@ -318,7 +315,7 @@ function update_images_per_step($nStep, $sImage) '); } - if (!isset($_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome])) { + if (!isset($_SETT['human_builds'][$sGenomeBuildID]['ncbi_sequences'][$sChromosome])) { // The combination of chromosome and build is not known by LOVD. // Something probably went wrong on the user's end. We will inform // the user and exit the script. @@ -330,7 +327,7 @@ function update_images_per_step($nStep, $sImage) exit; } - $sReferenceSequence = $_SETT['human_builds'][$aActiveGBs[$sCurrentGBSuffix]]['ncbi_sequences'][$sChromosome]; + $sReferenceSequence = $_SETT['human_builds'][$sGenomeBuildID]['ncbi_sequences'][$sChromosome]; } @@ -378,6 +375,7 @@ function update_images_per_step($nStep, $sImage) + "&type=' . $sType . '" + "&refSeq=' . $sReferenceSequence . '" + "&transcripts=' . implode('|', $aTranscripts) . '" + + "&genomeBuild=' . (!isset($sGenomeBuildID)? '' : $sGenomeBuildID) . '" ).fail(function(){alert("An error occurred while trying to map your variant, please try again later.");}) '); } @@ -392,6 +390,7 @@ function update_images_per_step($nStep, $sImage) // Retrieving necessary information from the URL. $sType = urldecode($_REQUEST['type']); $sReferenceSequence = urldecode($_REQUEST['refSeq']); + $sGenomeBuildID = urldecode($_REQUEST['genomeBuild']); // Call VariantValidator. require ROOT_PATH . 'class/variant_validator.php'; @@ -401,7 +400,7 @@ function update_images_per_step($nStep, $sImage) $_VV->verifyGenomic($sVariant, array( 'map_to_transcripts' => !empty($aTranscript), // Should we map the variant to transcripts? 'predict_protein' => !empty($aTranscript), // Should we get protein predictions? - 'lift_over' => (count($aActiveGBs) > 1), // Should we get other genomic mappings of this variant? + 'lift_over' => (1 < (int) $_DB->query('SELECT COUNT(*) FROM ' . TABLE_GENOME_BUILDS)->fetchColumn()), // Should we get other genomic mappings of this variant? 'select_transcripts' => $aTranscripts, )) : $_VV->verifyVariant($sVariant, array('select_transcripts' => $aTranscripts)) @@ -508,16 +507,20 @@ function update_images_per_step($nStep, $sImage) // use to make an md5 key of the input. $aAllValidatedVariants = array(); + // Save the ['data']['DNA'] variant to the right type of mapping + // to easily add it into the right fields. + if ($sType == 'VOT') { + // If the input type was a variant on transcript, the ['data']['DNA'] + // field holds information on a transcript mapping. + $aMappedVariant['data']['transcript_mappings'][$sReferenceSequence] = $aMappedVariant['data']; + } else { + // If the input was not a VOT, it was a genomic variant, meaning we + // should add the information into the genomic mappings. + $aMappedVariant['data']['genomic_mappings'][$sGenomeBuildID] = $aMappedVariant['data']['DNA']; + } + // Returning the mapping for transcript, RNA and protein variants. - foreach ($aTranscripts as $sTranscript) { - if (!isset($aMappedVariant['data']['transcript_mappings'][$sTranscript]) - && $sTranscript != $sReferenceSequence) { - // If no mapping was found for this transcript, we skip it. - continue; - } - // Retrieving the info. - $aTranscriptData = ($sTranscript == $sReferenceSequence ? // Yes=Variant of origin (stored directly in data); No=Other (stored in transcript_mappings) - $aMappedVariant['data'] : $aMappedVariant['data']['transcript_mappings'][$sTranscript]); + foreach ($aMappedVariant['data']['transcript_mappings'] as $sTranscript => $aTranscriptData) { // Adding the validated variant to the rest of the validated variants. array_push($aAllValidatedVariants, $aTranscriptData['DNA']); @@ -540,50 +543,34 @@ function update_images_per_step($nStep, $sImage) } // Returning the mapping for genomic variants. - foreach ($aActiveGBs as $sGBSuffix => $sGBID) { - if (!$_SETT['human_builds'][$sGBID]['supported_by_VV'] - || !isset($aMappedVariant['data']['genomic_mappings'][$sGBID])) { - // If a genome build is active which is not supported by VV, we won't have - // received mapping information on it. We will skip this variant. - continue; - } - // Retrieving the info. - if ($sType == 'VOT') { - // When VV was called using a variant on transcript, we always - // get only one possible mapping, which is formatted as a string. - $sMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; - - } elseif (isset($sCurrentGBSuffix) && $sGBSuffix == $sCurrentGBSuffix) { - // The current build is the build which is the direct reference of - // our input variant. When this is the case, our output is already - // formatted as a string as well. - $sMappedGenomicVariant = $aMappedVariant['data']['DNA']; + foreach ($aMappedVariant['data']['genomic_mappings'] as $sGBID => $aMappedGenomicVariant) { + if (is_string($aMappedGenomicVariant)) { + // The variant is a string. We don't need to make any edits. + $sMappedGenomicVariant = $aMappedGenomicVariant; + + } elseif (count($aMappedGenomicVariant) == 1) { + // The variant is formatted as an array, since multiple variants were + // possible. However, only one variant was found. We can simply take + // the first element. + $sMappedGenomicVariant = $aMappedGenomicVariant[0]; } else { - // Our output is formatted as an array, since multiple variants were possible. - $aMappedGenomicVariant = $aMappedVariant['data']['genomic_mappings'][$sGBID]; - - if (count($aMappedGenomicVariant) <= 1) { - // Only one variant was found. Great! We can simply take the first element. - $sMappedGenomicVariant = $aMappedGenomicVariant[0]; - - } else { - // Multiple possible variants were found. We will give the user a heads-up, - // and concatenate the variants cleanly as follows: - // NC_1233456.1:g.1del + NC_123456.1:g.2_3del + NC_123456.1:g.4del = - // NC_123456.1:g.1del^2_3del^4del. - update_dialogue('
There were multiple genomic variant predictions for build ' . $sGBID . '.'); - - $sMappedGenomicVariant = - preg_replace('/(.*:[a-z]\.).*/', '', $aMappedGenomicVariant[0]) . - implode('^', - array_map(function ($sFullVariant) { - return preg_replace('/.*:[a-z]\./', '', $sFullVariant); - }, $aMappedGenomicVariant) - ); - } + // Multiple possible variants were found. We will inform the user, + // and concatenate the variants similarly to the example below: + // NC_1233456.1:g.1del + NC_123456.1:g.2_3del + NC_123456.1:g.4del = + // NC_123456.1:g.1del^2_3del^4del. + update_dialogue('
There were multiple genomic variant predictions for build ' . $sGBID . '.'); + + $sMappedGenomicVariant = + preg_replace('/(.*:[a-z]\.).*/', '', $aMappedGenomicVariant[0]) . + implode('^', + array_map(function ($sFullVariant) { + return preg_replace('/.*:[a-z]\./', '', $sFullVariant); + }, $aMappedGenomicVariant) + ); } + // Removing the reference sequence. $sMappedGenomicVariant = preg_replace('/.*:/', '', $sMappedGenomicVariant); // Fixme; Find a cleaner way of cutting off the reference sequence. // Adding the validated variant to the rest of the validated variants. @@ -592,10 +579,12 @@ function update_images_per_step($nStep, $sImage) // Filling in the input field. print(' // Adding genomic info the fields. - var oGenomicVariant = $(\'#variantForm input[name$="VariantOnGenome/DNA' . (!$sGBSuffix ? '' : '/' . $sGBSuffix) . '"]\'); - oGenomicVariant.val("' . $sMappedGenomicVariant . '"); - oGenomicVariant.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); - oGenomicVariant.css({"pointer-events": "none", "background-color": "lightgrey", "color": "grey"}); + var oGenomicField = $("input").filter(function() { + return $(this).data("genomeBuild") == "' . $sGBID . '" + }); + oGenomicField.val("' . $sMappedGenomicVariant . '"); + oGenomicField.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); + oGenomicField.css({"pointer-events": "none", "background-color": "lightgrey", "color": "grey"}); '); } diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index 47071af3..9ecfdaab 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -181,7 +181,7 @@ function lovd_checkHGVS(e) { var sRefSeqInfo = ( sFieldName[0] !== 'V'? // Yes=RefSeq is a transcript; No=RefSeq is genomic. $(this).data('id_ncbi') : - sFieldName.substring(sFieldName.indexOf('DNA') + 3).replace(/\//, '') + '-' + sChromosome + $(this).data('genomeBuild') + '-' + sChromosome ); var sTranscripts = $($('#variantForm input[name$="_VariantOnTranscript/DNA"]')).map(function(){ return $(this).data('id_ncbi'); From afda306b78ab68bf4e8d4d52265201491b5ff3bb Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Wed, 2 Mar 2022 10:23:48 +0100 Subject: [PATCH 35/95] Clean up code that checks refSeqs in description A quick clean-up was needed after a find and replace resulted in issues concerning the variable $sFullVariant/$sVariant after checking whether the variant as found in the input field already held a refSeq. --- src/ajax/check_hgvs_dialogue.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index c75467d1..1eb64b7f 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -342,7 +342,7 @@ function update_images_per_step($nStep, $sImage) // the reference sequence in the variant description, // but that is no problem at all, since the given // refSeq matches our expectations. - $sVariant = $sVariant; + $sFullVariant = $sVariant; } else { // The user gave a refSeq within the variant description @@ -359,7 +359,7 @@ function update_images_per_step($nStep, $sImage) } else { // The given variant does not hold a reference sequence. - $sVariant = $sReferenceSequence . ':' . $sVariant; + $sFullVariant = $sReferenceSequence . ':' . $sVariant; } @@ -370,7 +370,7 @@ function update_images_per_step($nStep, $sImage) print(' $.get("ajax/check_hgvs_dialogue.php?" + "action=map" - + "&var=' . $sVariant . '" + + "&var=' . $sFullVariant . '" + "&fieldName=' . $sFieldName . '" + "&type=' . $sType . '" + "&refSeq=' . $sReferenceSequence . '" From 20ea1e3c43314d2bb7728bfd3ccce5beced0a897 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Wed, 2 Mar 2022 10:28:44 +0100 Subject: [PATCH 36/95] Stop blocking the 'Ignore this transcript' button Previously, we blocked this button since clicking it twice could unblock fields which we specifically blocked after mapping. However, since our new approach for the blockage (now using pointer-events= none instead of disabled=true), this no longer serves a purpose. For user friendliness, it could potentially be good to leave the button open. --- src/ajax/check_hgvs_dialogue.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 1eb64b7f..8c8ede7a 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -589,17 +589,9 @@ function update_images_per_step($nStep, $sImage) } - // Because we automatically filled all non-blocked positions, - // all open transcript fields have been blocked. We don't - // want the user to block the transcript input at this point - // so we disable the 'Ignore this transcript' option. // And now that we're all done, we can also fill in the md5 // translation of our validated variants. - print(' - // Disabling the "ignore this transcript" option. - var oIgnoreOption = $(\'input[name^="ignore_"]\'); - oIgnoreOption.parent().html(""); - + print(' // Adding the md5 translation of the validated variants. $(\'input[name="codedVariants"]\').val("' . lovd_getMD5TranslationOfVariants($aAllValidatedVariants) . '"); '); From d9bf91311efe4be29802a76aff6fe3e0798ddef2 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Wed, 2 Mar 2022 10:45:23 +0100 Subject: [PATCH 37/95] Fix bug and add comment to code which resets values It seems that the reset fails to reset ALL values; for the genome builds, it only changes the first image to trans.png; not the rest of them. This should be fixed in the future. --- src/ajax/check_hgvs_dialogue.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 8c8ede7a..6e2593ba 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -61,8 +61,8 @@ oTranscriptField.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); + $(\'#variantForm input[name^="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); + $(\'#variantForm input[name^="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); '); // Fixme; Should this perhaps be rewritten using a JS loop, or by adjusting all variables at once in JS? } @@ -73,7 +73,7 @@ oGenomicVariants.val(""); oGenomicVariants.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); oGenomicVariants.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); + '); // Fixme; this only changes the image next to the first genome build. Why? // Closing the script. exit; From 0a82e7fe346a838957394b30def2146b4e797bc8 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 09:32:43 +0100 Subject: [PATCH 38/95] Reset all values when the dialogue is called Also: clean up the code of this reset a bit. --- src/ajax/check_hgvs_dialogue.php | 52 +++++++++++++------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 6e2593ba..a9d92da8 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -43,39 +43,29 @@ -// If the variant is empty, we want to reset all results of this script. -if (!$sVariant) { - print(' - // Resetting the md5 key. - $(\'input[name="codedVariants"]\').val(""); - '); +// We will reset all results and start from scratch. +print(' +// Resetting the md5 key. +$(\'input[name="codedVariants"]\').val(""); + +// Resetting the transcript fields. +var oTranscriptFields = $(\'#variantForm input[name$="VariantOnTranscript/DNA"]\'); +oTranscriptFields.val(""); +oTranscriptFields.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); +oTranscriptFields.siblings("img").attr({src: "gfx/trans.png"}).show(); +$(\'#variantForm input[name$="VariantOnTranscript/RNA"]\').val(""); +$(\'#variantForm input[name$="VariantOnTranscript/Protein"]\').val(""); + +// Resetting the genomic fields. +var oGenomicVariants = $(\'#variantForm input[name^="VariantOnGenome/DNA"]\'); +oGenomicVariants.val(""); +oGenomicVariants.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); +oGenomicVariants.siblings("img").attr({src: "gfx/trans.png"}).show(); +'); - // Resetting the mapping for transcript, RNA and protein variants. - foreach ($aTranscripts as $sTranscript) { - print(' - // Resetting the transcript fields. - var oTranscriptField = $("input").filter(function() { - return $(this).data("id_ncbi") == "' . $sTranscript . '" - }); - oTranscriptField.val(""); - oTranscriptField.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); - oTranscriptField.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); - $(\'#variantForm input[name^="\' + sBaseOfFieldName + "RNA" + \'"]\').val(""); - $(\'#variantForm input[name^="\' + sBaseOfFieldName + "Protein" + \'"]\').val(""); - '); // Fixme; Should this perhaps be rewritten using a JS loop, or by adjusting all variables at once in JS? - } - // Resetting the mapping for genomic variants. - print(' - // Resetting the genomic fields. - var oGenomicVariants = $(\'#variantForm input[name^="VariantOnGenome/DNA"]\'); - oGenomicVariants.val(""); - oGenomicVariants.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); - oGenomicVariants.siblings("img:first").attr({src: "gfx/trans.png"}).show(); - '); // Fixme; this only changes the image next to the first genome build. Why? - - // Closing the script. +if (!$sVariant) { + // If the variant is empty, we can close the script. exit; } From a9f8773845ccf7f2ae14ed06875a54e886ba230e Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 09:35:50 +0100 Subject: [PATCH 39/95] Add the source of the variant when it is mapped --- src/ajax/check_hgvs_dialogue.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index a9d92da8..702c41bf 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -382,6 +382,12 @@ function update_images_per_step($nStep, $sImage) $sReferenceSequence = urldecode($_REQUEST['refSeq']); $sGenomeBuildID = urldecode($_REQUEST['genomeBuild']); + // Add the source of the variant which will be mapped. + print(' + // Add source. + $(\'#variantForm input[name="source"]\').val("' . ($sType == 'VOT'? $sType : $sGenomeBuildID) . '"); + '); + // Call VariantValidator. require ROOT_PATH . 'class/variant_validator.php'; $_VV = new LOVD_VV(); From daee26802d4ad2554d13ade792ac34daf1518924 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 09:39:07 +0100 Subject: [PATCH 40/95] Trigger HGVS check when the chromosome is updated --- src/inc-js-variants.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index 9ecfdaab..6933bb28 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -563,6 +563,17 @@ function lovd_highlightInput (oElement) // Add an onChange event that runs lovd_checkHGVS. oGenomicVariants.change(lovd_checkHGVS); + $('#variantForm select[name="chromosome"]').change(function (e) { + // We want to make sure that anytime the chromosome is updated, + // the HGVS check and mapping is rerun using the new chromosome. + var sSource = $('#variantForm input[name="source"]').val(); + if (sSource != '') { + $("input").filter(function() { + return $(this).data("genomeBuild") == sSource; + }).change(); + } + }); + if (oTranscriptVariants[0] != undefined) { // Add the buttons and images at the end of the transcripts DNA fields. oTranscriptVariants.parent().append('   '); From ee315bb0d50d10a49280a77ee558fe5d0d6ea1eb Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 09:40:42 +0100 Subject: [PATCH 41/95] Stop expiring the cache for inc-js-variants.php --- src/inc-js-variants.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index 6933bb28..f58bc08b 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -33,7 +33,6 @@ *************/ header('Content-type: text/javascript; charset=UTF-8'); -header('Expires: ' . date('r', time())); define('AJAX_FALSE', '0'); define('AJAX_TRUE', '1'); From 3e3b6915df9626bb7b6e78b16266de9d44143873 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 10:59:30 +0100 Subject: [PATCH 42/95] Add css classes to the input fields to show status The newly added css classes should further help the user understand which of their variants are validated and which are not. Also, since we are now no longer using pointer-events=none, this means the user can change their variant input if they want to, which will simply retrigger the dialogue and mapping. --- src/ajax/check_hgvs_dialogue.php | 14 +++++++++----- src/styles.css | 6 +++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 702c41bf..466483c9 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -51,7 +51,7 @@ // Resetting the transcript fields. var oTranscriptFields = $(\'#variantForm input[name$="VariantOnTranscript/DNA"]\'); oTranscriptFields.val(""); -oTranscriptFields.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); +oTranscriptFields.removeClass(); oTranscriptFields.siblings("img").attr({src: "gfx/trans.png"}).show(); $(\'#variantForm input[name$="VariantOnTranscript/RNA"]\').val(""); $(\'#variantForm input[name$="VariantOnTranscript/Protein"]\').val(""); @@ -59,7 +59,7 @@ // Resetting the genomic fields. var oGenomicVariants = $(\'#variantForm input[name^="VariantOnGenome/DNA"]\'); oGenomicVariants.val(""); -oGenomicVariants.css({"pointer-events": "auto", "background-color": "white", "color": "black"}); +oGenomicVariants.removeClass(); oGenomicVariants.siblings("img").attr({src: "gfx/trans.png"}).show(); '); @@ -104,6 +104,7 @@ var ' . $sButtonNo . ' = {"No, I will take a look myself":function () { // The user does not accept the given fixed variant. var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.attr("class", "err"); oInput.siblings("img:first").attr({src: "gfx/cross.png", title: "Please check the HGVS syntax of your variant description before sending it into the database."}).show(); $(this).dialog("close"); }}; @@ -116,7 +117,8 @@ var ' . $sButtonOKInvalid . ' = {"OK":function () { // The user agrees to change their invalid input manually. var oInput = $(\'input[name="' . $sFieldName . '"]\'); - oInput.siblings("img:first").attr({src: "gfx/cross.png", title: "Your variant could not be validated..."}).show(); + oInput.attr("class", "err"); + oInput.siblings("img:first").attr({src: "gfx/cross.png", title: "Your variant is not validated..."}).show(); $(this).dialog("close"); }}; var ' . $sButtonOKCouldBeValid . ' = {"OK":function () { @@ -126,6 +128,7 @@ $(\'input[name="codedVariants"]\').val("' . lovd_getMD5TranslationOfVariants(array($sVariant)) . '"); var oInput = $(\'input[name="' . $sFieldName . '"]\'); $("#codedVariants").val("' . lovd_getMD5TranslationOfVariants(array($sVariant)) . '"); + oInput.attr("class", "warn"); oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "Your variant could not be (in)validated..."}).show(); $(this).dialog("close"); }}; @@ -301,6 +304,7 @@ function update_images_per_step($nStep, $sImage) die(' $("#variantCheckDialogue").dialog("close"); var oInput = $(\'input[name="' . $sFieldName . '"]\'); + oInput.attr("class", "warn"); oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "We validated the syntax, but could not validate the positions."}).show(); '); } @@ -531,7 +535,7 @@ function update_images_per_step($nStep, $sImage) if (!oTranscriptField.prop("disabled")) { oTranscriptField.val("' . $aTranscriptData['DNA'] . '"); oTranscriptField.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); - oTranscriptField.css({"pointer-events": "none", "background-color": "lightgrey", "color": "grey"}); + oTranscriptField.attr("class", "acc"); var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '"); $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '"); @@ -580,7 +584,7 @@ function update_images_per_step($nStep, $sImage) }); oGenomicField.val("' . $sMappedGenomicVariant . '"); oGenomicField.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); - oGenomicField.css({"pointer-events": "none", "background-color": "lightgrey", "color": "grey"}); + oGenomicField.attr("class", "acc"); '); } diff --git a/src/styles.css b/src/styles.css index 30c73601..3c215ece 100644 --- a/src/styles.css +++ b/src/styles.css @@ -108,7 +108,7 @@ table.error td {padding : 0px 4px;} -/* Error messages on forms, required by lovd_errorPrint() */ +/* Error, warning and accepted messages on forms, required by lovd_errorPrint() */ div.err {font-size : 11px; border : 1px solid #FF0000; background : #F3F3F3; padding : 5px;} input.err, textarea.err, button.err, select.err {border : 1px solid #EE0000;} @@ -118,6 +118,10 @@ input.warn, textarea.warn, button.warn, select.warn {border : 1px solid #CCAA00;} input.warn:hover, input.warn:focus, textarea.warn:hover, textarea.warn:focus, button.warn:hover, select.warn:hover, select.warn:focus {background : #FFFFE8; border : 1px solid #AA6600;} +input.acc, textarea.acc, button.acc, select.acc +{background : #e9fae1; border : 1px solid #60b932;} +input.acc:hover, input.acc:focus, textarea.acc:hover, textarea.acc:focus, button.acc:hover, select.acc:hover, select.acc:focus +{background : #d7ffc4; border : 1px solid #448a21;} From fb3ce67ebcc79e8d18f1d8b5f8df8165af826201 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 11:03:53 +0100 Subject: [PATCH 43/95] Fix bug when resetting the script Before this commit, the script would reset all values right at the start, even if no mapping was done. That is neither necessary nor clever, since this meant that, if a variant was changed but could not be mapped, its very own field would be emptied and not filled again. So, now we reset the script only when necessary: so when the variant input was left empty (to allow the user a fresh start), and when the mapping was done (so newly mapped variants are sure to be coherent). --- src/ajax/check_hgvs_dialogue.php | 51 +++++++++++++++++++------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 466483c9..78d14e9f 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -43,29 +43,36 @@ -// We will reset all results and start from scratch. -print(' -// Resetting the md5 key. -$(\'input[name="codedVariants"]\').val(""); - -// Resetting the transcript fields. -var oTranscriptFields = $(\'#variantForm input[name$="VariantOnTranscript/DNA"]\'); -oTranscriptFields.val(""); -oTranscriptFields.removeClass(); -oTranscriptFields.siblings("img").attr({src: "gfx/trans.png"}).show(); -$(\'#variantForm input[name$="VariantOnTranscript/RNA"]\').val(""); -$(\'#variantForm input[name$="VariantOnTranscript/Protein"]\').val(""); - -// Resetting the genomic fields. -var oGenomicVariants = $(\'#variantForm input[name^="VariantOnGenome/DNA"]\'); -oGenomicVariants.val(""); -oGenomicVariants.removeClass(); -oGenomicVariants.siblings("img").attr({src: "gfx/trans.png"}).show(); -'); +// Initialise the function that will allow us to reset all values. +function reset_all_values() +{ + // This function can be called to reset all values from the + // output of this script. + print(' + // Resetting the md5 key. + $(\'input[name="codedVariants"]\').val(""); + + // Resetting the transcript fields. + var oTranscriptFields = $(\'#variantForm input[name$="VariantOnTranscript/DNA"]\'); + oTranscriptFields.val(""); + oTranscriptFields.removeClass(); + oTranscriptFields.siblings("img").attr({src: "gfx/trans.png"}).show(); + $(\'#variantForm input[name$="VariantOnTranscript/RNA"]\').val(""); + $(\'#variantForm input[name$="VariantOnTranscript/Protein"]\').val(""); + + // Resetting the genomic fields. + var oGenomicVariants = $(\'#variantForm input[name^="VariantOnGenome/DNA"]\'); + oGenomicVariants.val(""); + oGenomicVariants.removeClass(); + oGenomicVariants.siblings("img").attr({src: "gfx/trans.png"}).show(); + '); +} if (!$sVariant) { - // If the variant is empty, we can close the script. + // If the variant is empty, we should reset all values + // and close the script. + reset_all_values(); exit; } @@ -502,6 +509,10 @@ function update_images_per_step($nStep, $sImage) unset($aMappedViaGB); // We don't need the rest of this information. } + // We have the mapping data and can now send it to the + // input fields. Before we start, we reset all the fields + // to make sure all the input is coherent. + reset_all_values(); // Save an array with all validated variants, to later // use to make an md5 key of the input. From 534d05f2b9db984b86e667d32f4d0295f7d95768 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 11:31:50 +0100 Subject: [PATCH 44/95] Simplify code and add class to RNA&Protein fields --- src/ajax/check_hgvs_dialogue.php | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 78d14e9f..dfd1fdab 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -54,16 +54,14 @@ function reset_all_values() // Resetting the transcript fields. var oTranscriptFields = $(\'#variantForm input[name$="VariantOnTranscript/DNA"]\'); - oTranscriptFields.val(""); - oTranscriptFields.removeClass(); + oTranscriptFields.val("").removeClass(); oTranscriptFields.siblings("img").attr({src: "gfx/trans.png"}).show(); - $(\'#variantForm input[name$="VariantOnTranscript/RNA"]\').val(""); - $(\'#variantForm input[name$="VariantOnTranscript/Protein"]\').val(""); + $(\'#variantForm input[name$="VariantOnTranscript/RNA"]\').val("").removeClass(); + $(\'#variantForm input[name$="VariantOnTranscript/Protein"]\').val("").removeClass(); // Resetting the genomic fields. var oGenomicVariants = $(\'#variantForm input[name^="VariantOnGenome/DNA"]\'); - oGenomicVariants.val(""); - oGenomicVariants.removeClass(); + oGenomicVariants.val("").removeClass(); oGenomicVariants.siblings("img").attr({src: "gfx/trans.png"}).show(); '); } @@ -544,12 +542,11 @@ function update_images_per_step($nStep, $sImage) }); if (!oTranscriptField.prop("disabled")) { - oTranscriptField.val("' . $aTranscriptData['DNA'] . '"); + oTranscriptField.val("' . $aTranscriptData['DNA'] . '").attr("class", "acc");; oTranscriptField.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); - oTranscriptField.attr("class", "acc"); var sBaseOfFieldName = oTranscriptField.attr("name").substring(0, oTranscriptField.attr("name").indexOf("DNA")); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '"); - $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '"); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "RNA" + \'"]\').val("' . $aTranscriptData['RNA'] . '").attr("class", "acc"); + $(\'#variantForm input[name$="\' + sBaseOfFieldName + "Protein" + \'"]\').val("' . $aTranscriptData['protein'] . '").attr("class", "acc"); }'); } @@ -593,9 +590,8 @@ function update_images_per_step($nStep, $sImage) var oGenomicField = $("input").filter(function() { return $(this).data("genomeBuild") == "' . $sGBID . '" }); - oGenomicField.val("' . $sMappedGenomicVariant . '"); + oGenomicField.val("' . $sMappedGenomicVariant . '").attr("class", "acc"); oGenomicField.siblings("img:first").attr({src: "gfx/check.png", title: "Validated"}).show(); - oGenomicField.attr("class", "acc"); '); } From bc8b39cc6b6a69ed89dbed4e45622a8997b22c3d Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 13:25:45 +0100 Subject: [PATCH 45/95] Disable the Enter for all DNA fields The Enter button could be used to bypass the HGVS check and go right to the submit. This is now disabled, to make sure a check will take place before the form can be submitted. --- src/inc-js-variants.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index f58bc08b..27c6806e 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -573,6 +573,14 @@ function lovd_highlightInput (oElement) } }); + // We disable the effect of the Enter key, since we do not want the user + // to be able to easily submit the form (which is the default effect of Enter), + // since this would mean the onchange would be bypassed and the HGVS check would + // not be run. + $(document).on("keydown", "input[name*='DNA']", function(event) { + return event.key != "Enter"; + }); + if (oTranscriptVariants[0] != undefined) { // Add the buttons and images at the end of the transcripts DNA fields. oTranscriptVariants.parent().append('   '); From 83b07f094a947e7766dcad788906b33afdcc8109 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 14:19:27 +0100 Subject: [PATCH 46/95] Fix all code that has to do with URL encoding --- src/ajax/check_hgvs_dialogue.php | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index dfd1fdab..5ce3e591 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -35,11 +35,11 @@ // Retrieving the variant and the transcripts to map to. -$sVariant = htmlspecialchars($_REQUEST['var']); -$aTranscripts = (empty($_REQUEST['transcripts'])? array() : explode('|', htmlspecialchars($_REQUEST['transcripts']))); +$sVariant = $_REQUEST['var']; +$aTranscripts = (empty($_REQUEST['transcripts'])? array() : explode('|', $_REQUEST['transcripts'])); // Retrieving the name of the input field. -$sFieldName = htmlspecialchars($_REQUEST['fieldName']); +$sFieldName = $_REQUEST['fieldName']; @@ -102,14 +102,14 @@ function reset_all_values() // and perform a new call to this script by activating // the onChange. var oInput = $(\'input[name="' . $sFieldName . '"]\'); - oInput.val("' . lovd_fixHGVS($sVariant) . '"); + oInput.val("' . addslashes(lovd_fixHGVS($sVariant)) . '"); $(this).dialog("close"); oInput.change(); }}; var ' . $sButtonNo . ' = {"No, I will take a look myself":function () { // The user does not accept the given fixed variant. var oInput = $(\'input[name="' . $sFieldName . '"]\'); - oInput.attr("class", "err"); + oInput.val("' . addslashes($sVariant) . '").attr("class", "err"); oInput.siblings("img:first").attr({src: "gfx/cross.png", title: "Please check the HGVS syntax of your variant description before sending it into the database."}).show(); $(this).dialog("close"); }}; @@ -122,7 +122,7 @@ function reset_all_values() var ' . $sButtonOKInvalid . ' = {"OK":function () { // The user agrees to change their invalid input manually. var oInput = $(\'input[name="' . $sFieldName . '"]\'); - oInput.attr("class", "err"); + oInput.val("' . addslashes($sVariant) . '").attr("class", "err"); oInput.siblings("img:first").attr({src: "gfx/cross.png", title: "Your variant is not validated..."}).show(); $(this).dialog("close"); }}; @@ -133,7 +133,7 @@ function reset_all_values() $(\'input[name="codedVariants"]\').val("' . lovd_getMD5TranslationOfVariants(array($sVariant)) . '"); var oInput = $(\'input[name="' . $sFieldName . '"]\'); $("#codedVariants").val("' . lovd_getMD5TranslationOfVariants(array($sVariant)) . '"); - oInput.attr("class", "warn"); + oInput.val("' . addslashes($sVariant) . '").attr("class", "warn"); oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "Your variant could not be (in)validated..."}).show(); $(this).dialog("close"); }}; @@ -234,7 +234,7 @@ function update_images_per_step($nStep, $sImage) // which we can interpret. // Let the user know that the given variant did not pass our HGVS check. - $sResponse = '
Your variant (\"' . $sVariant . '\") did not pass our HGVS check.

'; + $sResponse = '
Your variant (\"' . htmlspecialchars($sVariant) . '\") did not pass our HGVS check.

'; update_images_per_step($sStepInitialChecks, $sImageFailed); @@ -243,7 +243,9 @@ function update_images_per_step($nStep, $sImage) if (!empty($aVariantIssues)) { $sResponse .= 'We found the following problems:
- '; - $sResponse .= implode('
-', $aVariantIssues) . '

'; + $sResponse .= implode('
-', array_map(function($sVariantIssue) { + return addslashes($sVariantIssue); + }, $aVariantIssues)) . '

'; } @@ -369,7 +371,7 @@ function update_images_per_step($nStep, $sImage) print(' $.get("ajax/check_hgvs_dialogue.php?" + "action=map" - + "&var=' . $sFullVariant . '" + + "&var=' . urlencode($sFullVariant) . '" + "&fieldName=' . $sFieldName . '" + "&type=' . $sType . '" + "&refSeq=' . $sReferenceSequence . '" @@ -387,9 +389,9 @@ function update_images_per_step($nStep, $sImage) if ($_REQUEST['action'] == 'map') { // Retrieving necessary information from the URL. - $sType = urldecode($_REQUEST['type']); - $sReferenceSequence = urldecode($_REQUEST['refSeq']); - $sGenomeBuildID = urldecode($_REQUEST['genomeBuild']); + $sType = $_REQUEST['type']; + $sReferenceSequence = $_REQUEST['refSeq']; + $sGenomeBuildID = $_REQUEST['genomeBuild']; // Add the source of the variant which will be mapped. print(' From 4fa5279f8878ce39310a3f894d7351873cefecdb Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 14:20:32 +0100 Subject: [PATCH 47/95] Reset all values based on whether mapping status After reconsideration, only resetting the values when an empty variant was given or the mapping was about to be done, was not enough. Instead, we now reset all values IF there were no variants which were successfully mapped. Since, if there was successful mapping, this should get priority, and, if there was no mapping, we want the variant to stay in place to allow the user to choose themselves whether they want to keep or change it. This is all done with the idea in mind that we will follow-up with code which performs an additional quality test in the POST of the variantCreationForm, so that we are really sure only clean variants are inserted. --- src/ajax/check_hgvs_dialogue.php | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 5ce3e591..2794e12e 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -43,15 +43,12 @@ -// Initialise the function that will allow us to reset all values. -function reset_all_values() -{ - // This function can be called to reset all values from the - // output of this script. - print(' - // Resetting the md5 key. - $(\'input[name="codedVariants"]\').val(""); - +// Reset all values. +print(' +// Resetting the md5 key. +$(\'input[name="codedVariants"]\').val(""); + +if ($(\'#variantForm input[name*="VariantOn"]\').hasClass("acc")) { // Resetting the transcript fields. var oTranscriptFields = $(\'#variantForm input[name$="VariantOnTranscript/DNA"]\'); oTranscriptFields.val("").removeClass(); @@ -63,14 +60,12 @@ function reset_all_values() var oGenomicVariants = $(\'#variantForm input[name^="VariantOnGenome/DNA"]\'); oGenomicVariants.val("").removeClass(); oGenomicVariants.siblings("img").attr({src: "gfx/trans.png"}).show(); - '); } +'); if (!$sVariant) { - // If the variant is empty, we should reset all values - // and close the script. - reset_all_values(); + // If the variant is empty, we can simply close the script. exit; } @@ -510,9 +505,7 @@ function update_images_per_step($nStep, $sImage) } // We have the mapping data and can now send it to the - // input fields. Before we start, we reset all the fields - // to make sure all the input is coherent. - reset_all_values(); + // input fields. // Save an array with all validated variants, to later // use to make an md5 key of the input. From bb648a1728f17ce03113330f27dfe7a6583653a4 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 14:31:23 +0100 Subject: [PATCH 48/95] Make sure the dialog is closed if an error occurs --- src/ajax/check_hgvs_dialogue.php | 2 +- src/inc-js-variants.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index 2794e12e..d68aa372 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -372,7 +372,7 @@ function update_images_per_step($nStep, $sImage) + "&refSeq=' . $sReferenceSequence . '" + "&transcripts=' . implode('|', $aTranscripts) . '" + "&genomeBuild=' . (!isset($sGenomeBuildID)? '' : $sGenomeBuildID) . '" - ).fail(function(){alert("An error occurred while trying to map your variant, please try again later.");}) + ).fail(function(){alert("An error occurred while trying to map your variant, please try again later.");$("#variantCheckDialogue").dialog("close");}) '); } diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index 27c6806e..354e7f80 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -192,7 +192,7 @@ function lovd_checkHGVS(e) { + "&fieldName=" + encodeURIComponent(sFieldName) + "&refSeqInfo=" + encodeURIComponent(sRefSeqInfo) + "&transcripts=" + encodeURIComponent(sTranscripts) - ).fail(function(){alert("Error checking your variant, please try again later.");}) + ).fail(function(){alert("An error occurred while checking your variant, please try again later.");$("#variantCheckDialogue").dialog("close");}) ; } From 3ea60b2390ba50411307049984d0ad9737d0f7f0 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 15:24:00 +0100 Subject: [PATCH 49/95] Remove md5 key; Use checkFields to check input Where we initially wanted to use an md5 hash to check whether our input variants were indeed validated, we now realised that it would be both easier and cleaner to use the checkFields function combined with a call to getVariantInfo. --- src/ajax/check_hgvs_dialogue.php | 18 +----------------- src/class/object_genome_variants.php | 13 +++++++++++++ 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/ajax/check_hgvs_dialogue.php b/src/ajax/check_hgvs_dialogue.php index d68aa372..ade9650d 100644 --- a/src/ajax/check_hgvs_dialogue.php +++ b/src/ajax/check_hgvs_dialogue.php @@ -45,9 +45,7 @@ // Reset all values. print(' -// Resetting the md5 key. -$(\'input[name="codedVariants"]\').val(""); - +// Resetting all values. if ($(\'#variantForm input[name*="VariantOn"]\').hasClass("acc")) { // Resetting the transcript fields. var oTranscriptFields = $(\'#variantForm input[name$="VariantOnTranscript/DNA"]\'); @@ -125,9 +123,7 @@ // We could not validate this variant, but the problem // lies with us. We will accept this variant and the // uncertainty that comes with it. - $(\'input[name="codedVariants"]\').val("' . lovd_getMD5TranslationOfVariants(array($sVariant)) . '"); var oInput = $(\'input[name="' . $sFieldName . '"]\'); - $("#codedVariants").val("' . lovd_getMD5TranslationOfVariants(array($sVariant)) . '"); oInput.val("' . addslashes($sVariant) . '").attr("class", "warn"); oInput.siblings("img:first").attr({src: "gfx/check_orange.png", title: "Your variant could not be (in)validated..."}).show(); $(this).dialog("close"); @@ -507,10 +503,6 @@ function update_images_per_step($nStep, $sImage) // We have the mapping data and can now send it to the // input fields. - // Save an array with all validated variants, to later - // use to make an md5 key of the input. - $aAllValidatedVariants = array(); - // Save the ['data']['DNA'] variant to the right type of mapping // to easily add it into the right fields. if ($sType == 'VOT') { @@ -591,14 +583,6 @@ function update_images_per_step($nStep, $sImage) } - // And now that we're all done, we can also fill in the md5 - // translation of our validated variants. - print(' - // Adding the md5 translation of the validated variants. - $(\'input[name="codedVariants"]\').val("' . lovd_getMD5TranslationOfVariants($aAllValidatedVariants) . '"); - '); - - // Send final message to the user. update_images_per_step($sStepMapping, $sImagePassed); update_dialogue( diff --git a/src/class/object_genome_variants.php b/src/class/object_genome_variants.php index 4a784109..f53c8707 100644 --- a/src/class/object_genome_variants.php +++ b/src/class/object_genome_variants.php @@ -254,6 +254,19 @@ function checkFields ($aData, $zData = false, $aOptions = array()) } } + foreach ($aData as $sField => $sVariant) { + if (preg_match('/DNA/', $sField)) { + $aVariantInfo = lovd_getVariantInfo($sVariant, false); + if (!lovd_isHGVS($sVariant) + && !isset($aVariantInfo['errors']['ENOTSUPPORTED']) // Supported by LOVD. + && !(isset($aVariant['warnings']['WNOTSUPPORTED']) // Supported by VariantValidator. + || isset($aVariant['messages']['IUNCERTAINPOSITIONS']) + || isset($aVariant['messages']['IPOSTIONRANGE']))) { + lovd_errorAdd($sField, 'The variant ' . $sVariant . ' did not pass our checks. Please take another look and try again.'); + } + } + } + // Do this before running checkFields so that we have time to predict the DBID and fill it in. if (!empty($aData['VariantOnGenome/DNA']) // DNA filled in. && isset($this->aColumns['VariantOnGenome/DBID']) // DBID column active. From 186176bc6f6214ca64c81a0f92b47f6ac1993ff5 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 15:29:30 +0100 Subject: [PATCH 50/95] Add documentation to the checkFields addition --- src/class/object_genome_variants.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/class/object_genome_variants.php b/src/class/object_genome_variants.php index f53c8707..710ccb55 100644 --- a/src/class/object_genome_variants.php +++ b/src/class/object_genome_variants.php @@ -256,6 +256,11 @@ function checkFields ($aData, $zData = false, $aOptions = array()) foreach ($aData as $sField => $sVariant) { if (preg_match('/DNA/', $sField)) { + // We want to check the input of all DNA fields: are these variant + // descriptions indeed cleanly formatted? And if our check seems + // to fail, is this perhaps because it holds syntax that we do + // not support? If we DO support the syntax but the variant does + // not seem to be HGVS, we will send an error. $aVariantInfo = lovd_getVariantInfo($sVariant, false); if (!lovd_isHGVS($sVariant) && !isset($aVariantInfo['errors']['ENOTSUPPORTED']) // Supported by LOVD. From c9cbda43ce8c6828669049836155c3ae79f0e1b5 Mon Sep 17 00:00:00 2001 From: Loes Werkman Date: Thu, 3 Mar 2022 16:42:33 +0100 Subject: [PATCH 51/95] Get rid of the $_GET['chromosome'] usage In inc-js-variants.php, we will now get the chromosome from the input field instead of doing so through GET. --- src/inc-js-variants.php | 9 ++++++++- src/variants.php | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/inc-js-variants.php b/src/inc-js-variants.php index 354e7f80..b8f8d5a5 100644 --- a/src/inc-js-variants.php +++ b/src/inc-js-variants.php @@ -257,7 +257,14 @@ className: '', if (oThisDNA.filter("[name^='VariantOnGenome/DNA']").size()) { // This function was called from the genomic variant, so build a list of genes and prepare the variant accordingly for mutalyzer. - var sVariantNotation = 'chr:' + oThisDNA.val(); + var sChromosome = ( + oChromosome.length ? // Yes=VOG form; No=VOT form. + oChromosome.val() : + $("td:contains('Chromosome')").last().filter(function () { + return $(this).html() === "Chromosome"; + }).siblings().eq(1).html() + ); + var sVariantNotation = 'chr' + sChromosome + ':' + oThisDNA.val(); var aGenes = []; for (nTranscriptID in aTranscripts) { if ($.inArray(aTranscripts[nTranscriptID][1], aGenes) == -1) { diff --git a/src/variants.php b/src/variants.php index 5150581a..ffd59b6a 100644 --- a/src/variants.php +++ b/src/variants.php @@ -961,7 +961,7 @@ function(sData) { print("\n" . ' ' . "\n\n"); - lovd_includeJS('inc-js-variants.php?chromosome=' . $_POST['chromosome']); + lovd_includeJS('inc-js-variants.php'); ?>