From 6bc4701bb6113573adf380e5a0d5a9bd117fa7fa Mon Sep 17 00:00:00 2001 From: mjshepherd Date: Mon, 25 May 2015 12:38:23 -0400 Subject: [PATCH] Issue #77: Top exomiser hits now uses the variant display table from variant store application --- .../script/ExomiserViewScriptService.java | 42 ++- .../resources/PhenoTips/VariantDisplay.xml | 316 +----------------- 2 files changed, 42 insertions(+), 316 deletions(-) diff --git a/similarity-data-impl/src/main/java/org/phenotips/data/similarity/script/ExomiserViewScriptService.java b/similarity-data-impl/src/main/java/org/phenotips/data/similarity/script/ExomiserViewScriptService.java index 68c05c0e1..8f9334d73 100644 --- a/similarity-data-impl/src/main/java/org/phenotips/data/similarity/script/ExomiserViewScriptService.java +++ b/similarity-data-impl/src/main/java/org/phenotips/data/similarity/script/ExomiserViewScriptService.java @@ -89,9 +89,10 @@ public boolean hasGenotype(Patient patient) */ public JSONArray getTopGenesAsJSON(Patient patient, int g, int v) { - JSONArray result = new JSONArray(); - if (patient == null || g <= 0) { - return result; + JSONArray variantsJSON = new JSONArray(); + + if (patient == null || g < 0) { + return variantsJSON; } boolean restrictGenes = @@ -99,26 +100,43 @@ public JSONArray getTopGenesAsJSON(Patient patient, int g, int v) int maxGenes = restrictGenes ? MAXIMUM_UNPRIVILEGED_GENES : g; Exome patientExome = this.exomeManager.getExome(patient); + for (String geneName : patientExome.getTopGenes(maxGenes)) { - JSONObject geneJSON = new JSONObject(); - geneJSON.put("name", geneName); - geneJSON.put("score", patientExome.getGeneScore(geneName)); - JSONArray variantsJSON = new JSONArray(); + Double geneScore = patientExome.getGeneScore(geneName); + List topVariants = patientExome.getTopVariants(geneName); + boolean restrictVariants = (!this.pm.getPatientAccess(patient).hasAccessLevel(this.editAccess) && v > MAXIMUM_UNPRIVILEGED_VARIANTS); int maxVars = restrictVariants ? MAXIMUM_UNPRIVILEGED_VARIANTS : v; - List topVariants = patientExome.getTopVariants(geneName); maxVars = Math.min(maxVars, topVariants.size()); + for (int i = 0; i < maxVars; i++) { Variant variant = topVariants.get(i); if (variant != null) { - variantsJSON.put(variant.toJSON()); + variantsJSON.put(this.mapToGAVariantJSON(variant, geneName, geneScore)); } } - geneJSON.put("variants", variantsJSON); - result.put(geneJSON); } - return result; + return variantsJSON; + } + + private JSONObject mapToGAVariantJSON(Variant variant, String geneName, Double geneScore) + { + JSONObject resultJson = new JSONObject(); + resultJson.put("start", variant.getPosition()); + resultJson.put("referenceBases", variant.getRef()); + resultJson.put("alternateBases", variant.getAlt()); + resultJson.put("referenceName", variant.getChrom()); + resultJson.put("end", variant.getPosition() + variant.getAlt().length()); + + JSONObject infoJson = new JSONObject(); + infoJson.put("EXOMISER_VARIANT_SCORE", variant.getScore()); + infoJson.put("EXOMISER_GENE_VARIANT_SCORE", geneScore); + infoJson.put("GENE_EFFECT", variant.getAnnotation("FUNCTIONAL_CLASS")); + infoJson.put("GENE", geneName); + + resultJson.put("info", infoJson); + return resultJson; } } diff --git a/ui/src/main/resources/PhenoTips/VariantDisplay.xml b/ui/src/main/resources/PhenoTips/VariantDisplay.xml index fcb3402d9..592114379 100644 --- a/ui/src/main/resources/PhenoTips/VariantDisplay.xml +++ b/ui/src/main/resources/PhenoTips/VariantDisplay.xml @@ -134,7 +134,6 @@ variantDisplayServiceURL : "${xwiki.getURL('PhenoTips.VariantDisplay', 'get')}", DEFAULT_NUMBER_OF_GENES : "5", DEFAULT_NUMBER_OF_VARIANTS : "3", - RESULTS_TABLE_MARKER : "variant-display-table", initialize : function (query, resultsContainer, options) { if (!query || !resultsContainer) {return;} @@ -146,8 +145,9 @@ } this.launchSearch(); - + this.tableContainer = new Element('div'); this.optionsContainer = new Element('div', {'class' : 'variant-display-options'}); + this.container.insert({top : this.tableContainer}); this.container.insert({bottom : this.optionsContainer}); this.initializeOptionsContainer(); @@ -238,8 +238,8 @@ if (data.query.id != this.query) {return;} // Empty the container to make room for the new results - if (this.resultsTable) { - this.resultsTable.remove(); + if (this.container.select('.variant-display-table')[0]) { + this.container.select('.variant-display-table')[0].remove(); } // Show result summary @@ -251,168 +251,20 @@ // Process results var _this = this; - this.resultsTable = new Element('table', {'class' : this.RESULTS_TABLE_MARKER}); - this.container.insert({top : this.resultsTable}); - - var columns = { - "GeneScore" : { - display: _this._displayResultGeneScore.bind(_this), - headings : [_this.Strings["geneScoreHeading"]] - }, - "Gene" : { - display: _this._displayResultGene.bind(_this), - headings : [_this.Strings["geneHeading"]] - }, - "Variant": { - display: _this._displayResultVariant.bind(_this), - headings : [_this.Strings["variantPosition"], _this.Strings["variantChange"], _this.Strings["variantType"]] - } - }; - - this._displayTableHeader(columns, this.resultsTable); - data.results.each(function(r) { - _this._displayResultRow(r, columns, _this.resultsTable); - }); - delete this._queryFeatures; - delete this._data; - }, - _displayTableHeader : function (columns, table) { - var row = this._getEmptyTableRow(table); - for (var c in columns) { - if (!columns.hasOwnProperty(c)) { - continue; - } - var headings = columns[c].headings; - for (var h in headings) { - if (!headings.hasOwnProperty(h)) { - continue; - } - row.insert(new Element("th", {"class" : "variant-display-heading"}).update(headings[h]).addClassName(c)); - } - } - return row; - }, - _getEmptyTableRow : function (table) { - //small trick for styling the tables, empty rows are divisions between genes - if (table.lastChild && table.lastChild.childElements().length == 0){ - table.lastChild.previous().addClassName("last-row-for-gene"); - } - var row = new Element('tr'); - table.insert(row); - return row; - }, - _displayResultRow : function (result, columns, table) { - var row = this._getEmptyTableRow(table); - for (var c in columns) { - row.insert(columns[c].display(result)); - } - return row; - }, - _getLastRow : function (table) { - var row = table.rows[table.rows.length-1]; - return row; - }, - _addToResultRow : function (result, columns, table) { - var row = this._getLastRow(table); - for (var c in columns) { - row.insert(columns[c].display(result)); - } - return row; - }, - _displayResultGene : function (r) { - var content = new Element('td', {'class' : 'gene-name', 'rowspan' : r.variants.length}); - var geneName = new Element('p', {'class' : 'gene-name'}); - geneName.update(r.name); - content.insert(geneName) - return content; - }, - _displayResultGeneScore : function (r) { - var content = new Element('td', {'class' : 'gene-score', 'rowspan' : r.variants.length}); - var functionality = r.score; - var geneScore = new Element('div', {'class' : 'gene-score'}); - geneScore.insert(this.Utils.generateSegmentedBar(5, functionality)); - content.insert(geneScore); - return content; - }, - _displayResultVariant : function (r) { - var variantSubTable = new Element ('table'); - var _this = this; - var variantColumns = { - "Position" : { - display: this._displayResultVariantPosition.bind(this) - }, - "Change" : { - display: this._displayResultVariantChange.bind(this) - }, - "Type" : { - display: this._displayResultVariantType.bind(this) - }, - }; - for (var i = 0; i<r.variants.length; i++){ - _this._addToResultRow(r.variants[i], variantColumns, _this.resultsTable); - if (!r.variants[i+1]){ - //adding a class for styling the table - _this.resultsTable.lastChild.addClassName("last-row-for-gene"); - } else { - _this.resultsTable.insertRow(); - } - } - }, - - _displayResultVariantPosition : function (r) { - var content = new Element('td', {'class' : 'variant-position'}); - var _this = this; - if (r.chrom && r.position && r.ref) { - var start = r.position; - var end = r.position + r.ref.length; - var positionText = _this.Strings["positionPhrase"].replace("__CHROMOSOME__",r.chrom.toUpperCase()).replace("__START__", start).replace("__STOP__", end); - var positionURLFragment = "chr" + r.chrom.toUpperCase() + ":" + start + "-" + end; - var assembly = r.assembly || "hg19"; - var position = new Element('a', { - 'href' : 'http://genome.ucsc.edu/cgi-bin/hgTracks?db=' + assembly + '&position=' + encodeURIComponent(positionURLFragment), - 'class' : 'button secondary', - 'target' : '__blank', - 'title' : _this.Strings["variantPositionLinkTitle"] - }).update(positionText).wrap('span', {'class' : 'buttonwrapper'}); - content.insert(position); + if (PhenoTips && PhenoTips.widgets && PhenoTips.widgets.VariantDisplayTable) { + var variantColumns =["GENE", "EXOMISER_GENE_VARIANT_SCORE", "B_UCSC_POSITION_LINK","chr", "pos", "ref", "alt", "GENE_EFFECT"]; + new PhenoTips.widgets.VariantDisplayTable(data.results, variantColumns, this.tableContainer); + } else { + console.log("Unable to display top exomiser hits: VariantTableWidget not found"); } - return content; - - }, - - _displayResultVariantChange : function (r) { - var content = new Element('td', {'class' : 'variant-change'}); - var displayedRef = (r.ref.length > 10) ? (r.ref.substring(0,10)+"...") : r.ref; - var displayedAlt = (r.alt.length > 10) ? (r.alt.substring(0,10)+"...") : r.alt; - content.update("<span class='dna-fragment ref'>" + displayedRef + "</span> → <span class='dna-fragment alt'>" + displayedAlt + "</span>"); - return content; - }, - _displayResultVariantType : function (r) { - var content = new Element('td', {'class' : 'variant-type'}).update("<span class='variant-type-text'>" + r.type + "</span>"); - return content; - }, - - Utils : { - generateSegmentedBar : function (count, value) { - var barOptions = { - 'segments' : count - }; - return new PhenoTips.widgets.SegmentedBar(value, barOptions).generateSegmentedBar(); - }, + delete this._data; }, Strings : { "options.numberOfGenes": "Maximum number of genes: ", "options.numberOfVariants": "Maximum variants per gene: ", - "positionPhrase" : "chr__CHROMOSOME__: __START__ - __STOP__", - "variantPositionLinkTitle" : 'Visualize in the UCSC Genome Browser', - "geneScoreHeading": "Score", - "geneHeading" : "Gene", - "variantPosition" : "Variant Position", - "variantChange" : "Variant", - "variantType" : "Effect", "optionsButton" : "Options", "hideOptionsButton": "Hide Options", "refreshButton" : "Refresh" @@ -445,152 +297,6 @@ onDemand - - PhenoTips.VariantDisplay - 0 - XWiki.StyleSheetExtension - dbe38413-4d80-48f3-875f-0e854b822384 - - XWiki.StyleSheetExtension - - - - - - - - - 0 - 0 - select - 0 - cache - 5 - Caching policy - 0 - - ,| - 1 - 0 - long|short|default|forbid - com.xpn.xwiki.objects.classes.StaticListClass - - - 0 - code - 2 - Code - 20 - 50 - 0 - com.xpn.xwiki.objects.classes.TextAreaClass - - - 0 - name - 1 - Name - 30 - 0 - com.xpn.xwiki.objects.classes.StringClass - - - 0 - select - yesno - parse - 4 - Parse content - 0 - com.xpn.xwiki.objects.classes.BooleanClass - - - 0 - 0 - select - 0 - use - 3 - Use this extension - 0 - - ,| - 1 - 0 - currentPage=Always on this page|onDemand=On demand|always=Always on this wiki - com.xpn.xwiki.objects.classes.StaticListClass - - - - default - - - #template("colorThemeInit.vm") -td.gene-score { - border-bottom : 1px solid $theme.textColor; - border-right: none; -} - -td.gene-name { - border-bottom: 1px solid $theme.textColor; -} - -td.gene-name, td.variant-position, td.variant-change, td.variant-type { - text-align: left; -} - -th.variant-display-heading{ - border-top: 1px solid black; - border-bottom: 1px solid black; -} - -th.variant-display-heading:first-child { - border: 1px solid black; - border-right: none; -} - -th.variant-display-heading:last-child { - border-right: 1px solid black; -} - -table.variant-display-table{ - margin:0; - margin-bottom: 1px; - width: 100%; -} - -table.variant-display-table td{ - padding: 10px; -} - -#variant_display_container{ - display:inline-block; - width: 100%; -} - -.variant-display-table > .last-row-for-gene > td { - border-bottom: 1px solid $theme.textColor; -} - -.variant-display-table .variant-position .button.secondary { - text-transform: none; -} - -.variant-display-table .segmented-bar { - font-size: 90%; -} - - - - VariantTableStyle - - - 1 - - - onDemand - - PhenoTips.VariantDisplay 1 @@ -762,6 +468,8 @@ table.variant-display-table td{ #if ($xcontext.action == 'view' && $xwiki.hasAccessLevel('view', $xcontext.user, 'PhenoTips.VariantDisplay') && $services.patientVariantView.hasGenotype($patient)) $xwiki.jsx.use('PhenoTips.VariantDisplay', {'minify' : false})## $xwiki.ssx.use('PhenoTips.VariantDisplay')## + $xwiki.jsx.use('PhenoTips.VariantTableWidget', {'minify' : false})## + $xwiki.ssx.use('PhenoTips.VariantTableWidget')## === Top genes in VCF === {{html clean=false}}<p class=box hint">Gene scores are computed from the uploaded VCF file and patient phenotypes using <a href="http://www.sanger.ac.uk/resources/software/exomiser/" target="_blank">the Exomiser</a>. Each score reflects the phenotypic relevance of the gene and the harmfulness and allele frequency of the variants.</p> <div id="variant_display_container"></div>{{/html}}##