UNPKG

ucsc-xena-client

Version:

UCSC Xena Client. Functional genomics visualizations.

327 lines (295 loc) 7.67 kB
'use strict'; var Highcharts = require('highcharts/highstock'); require('highcharts/highcharts-more')(Highcharts); function hcLabelRender() { var s = this.name; var r = ""; var lastAppended = 0; var lastSpace = -1; for (var i = 0; i < s.length; i++) { if (s.charAt(i) === ' ') { lastSpace = i; } if (i - lastAppended > 20) { if (lastSpace === -1) { lastSpace = i; } r += s.substring(lastAppended, lastSpace); lastAppended = lastSpace; lastSpace = -1; r += "<br>"; } } r += s.substring(lastAppended, s.length); return r; } var chartOptions = { chart: { renderTo: 'myChart' }, subtitle: { useHTML: true }, scrollbar: { enabled: true }, legend: { title: { style: { fontStyle: 'italic', width: '100px' } }, enabled: true, labelFormatter: hcLabelRender, itemHoverStyle: { color: '#ff6600' }, navigation: { activeColor: '#3E576F', animation: true, arrowSize: 12, inactiveColor: '#CCC', style: { fontWeight: 'bold', color: '#333', fontSize: '12px' } } }, credits: { text: 'xena.ucsc.edu', href: 'http://xena.ucsc.edu' } }; // x categorical, Y categorical function columnChartOptions(chartOptions, categories, xAxisTitle, yAxisType, Y, showLegend) { var yAxisTitle = yAxisType === 'Histogram' ? 'Histogram' : 'Distribution'; chartOptions.chart.zoomType = 'x'; chartOptions.legend.align = 'right'; chartOptions.legend.verticalAlign = 'middle'; chartOptions.legend.layout = 'vertical'; chartOptions.legend.title.style = { width: "100px", fontStyle: 'italic' }; if (showLegend) { chartOptions.legend.title.text = Y; } else { chartOptions.legend.title = {}; } chartOptions.title = { text: yAxisTitle + " of " + Y + (xAxisTitle === "" ? "" : " according to " + xAxisTitle) }; chartOptions.xAxis = { title: { text: xAxisTitle }, type: 'category', categories: categories, minRange: -1 }; chartOptions.yAxis = { title: { text: yAxisType === "Histogram" ? "count" : "distribution" } }; chartOptions.plotOptions = { errorbar: { color: 'gray' } }; //tooltip if (xAxisTitle === "" && yAxisType === 'Histogram') { //histogram chartOptions.tooltip = { formatter: function formatter() { return Y + '<br>' + categories[this.point.x] + '<br>' + '<b> n = ' + this.point.y + '</b>'; }, hideDelay: 0 }; } else if (xAxisTitle === "" && yAxisType !== 'Histogram') { //distribution chartOptions.tooltip = { formatter: function formatter() { return Y + '=' + categories[this.point.x] + '<br>' + '<b>' + this.point.y.toPrecision(3) + '%</b>'; }, hideDelay: 0 }; } else { chartOptions.tooltip = { headerFormat: xAxisTitle + ' : {point.key}<br>', formatter: function formatter() { var nNumber = this.series.userOptions.description ? this.series.userOptions.description[this.point.x] : 0; return Y + '=<b>' + this.series.name + '</b>' + '<br>' + '<b>' + this.point.y + '%</b>' + '</b><br>' + 'n = ' + nNumber; }, hideDelay: 0 }; } if (categories.length > 15) { chartOptions.xAxis.labels = { rotation: -90 }; } chartOptions.yAxis.labels = { format: yAxisType === "Histogram" ? '{value}' : '{value} %' }; return chartOptions; } // x categorical y float boxplot function columnChartFloat(chartOptions, categories, xAxisTitle, yAxisTitle) { chartOptions.chart.zoomType = 'x'; chartOptions.legend.align = 'right'; chartOptions.legend.margin = 5; chartOptions.legend.title.text = xAxisTitle; chartOptions.legend.verticalAlign = 'middle'; chartOptions.legend.layout = 'vertical'; chartOptions.title = { text: '' // boxplot no chart tile because both x and y axis are clearlly marked. }; chartOptions.xAxis = { title: { text: xAxisTitle }, type: 'category', categories: categories.length === 1 ? [''] : categories, minRange: -1 }; chartOptions.yAxis = { title: { text: yAxisTitle } }; chartOptions.tooltip = { headerFormat: xAxisTitle + ' : {series.name}<br>', formatter: function formatter() { var nNumber = this.series.userOptions.description ? this.series.userOptions.description[this.point.x] : 0; return (xAxisTitle ? xAxisTitle + ' : ' : '') + this.series.name + '<br>' + (categories.length > 1 ? yAxisTitle + ' ' : '') + categories[this.point.x] + ': <b>' + this.point.median.toPrecision(3) + '</b>' + ' (' + this.point.low.toPrecision(3) + ',' + this.point.q1.toPrecision(3) + ',' + this.point.q3.toPrecision(3) + ',' + this.point.high.toPrecision(3) + ')<br>' + '</b><br>' + (nNumber ? 'n = ' + nNumber : ''); }, hideDelay: 0 }; if (categories.length > 5) { chartOptions.xAxis.labels = { rotation: -90 }; } chartOptions.plotOptions = { errorbar: { color: 'gray' } }; return chartOptions; } function scatterChart(chartOptions, xlabel, ylabel, samplesLength) { var xAxisTitle = xlabel, yAxisTitle = ylabel; chartOptions.chart.zoomType = 'xy'; chartOptions.chart.type = 'scatter'; chartOptions.chart.boost = { useGPUTranslations: true, usePreAllocated: true }; chartOptions.legend.align = 'right'; chartOptions.legend.verticalAlign = 'middle'; chartOptions.legend.layout = 'vertical'; chartOptions.title = { text: '' // scatter plot no chart tile because both x and y axis are clearlly marked. }; chartOptions.xAxis = { title: { text: xAxisTitle }, minRange: -1, crosshair: true }; chartOptions.yAxis = { title: { text: yAxisTitle }, gridLineWidth: 0, tickWidth: 1, lineWidth: 1, crosshair: true, scrollbar: { enabled: true, showFull: false } }; chartOptions.tooltip = { hideDelay: 0, formatter: function formatter() { return '<b>' + this.point.colorLabel + '</b><br>' + 'sample: ' + this.point.name + '<br>' + 'x: ' + this.point.x.toPrecision(3) + '<br>' + 'y: ' + this.point.y.toPrecision(3); } }; chartOptions.plotOptions = { scatter: { marker: { radius: samplesLength > 10000 ? 1 : 2, opacity: 0.1 } }, series: { turboThreshold: 0, stickyTracking: false, boostThreshold: 1000 } }; return chartOptions; } function addSeriesToColumn(chart, chartType, sName, ycodeSeries, yIsCategorical, showDataLabel, showLegend, color) { var nNumberSeriese = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : undefined; var seriesOptions = { name: sName, type: chartType, data: ycodeSeries, maxPointWidth: 50, color: color, description: nNumberSeriese // use description to carry n=xx information }; if (!showLegend) { seriesOptions.showInLegend = false; } if (showDataLabel) { if (yIsCategorical) { seriesOptions.dataLabels = { enabled: true, formatter: function formatter() { return this.point.y.toPrecision(3) + '%'; } }; } else { // boxplot data label is not implemented in highchart, yet seriesOptions.dataLabels = { enabled: true, format: '{point.median}' }; } } chart.addSeries(seriesOptions, false); } function average(data) { var sum = data.reduce(function (a, b) { return a + b; }, 0); var avg = sum / data.length; return avg; } function standardDeviation(values, avg) { var squareDiffs = values.map(function (value) { var diff = value - avg; var sqrDiff = diff * diff; return sqrDiff; }); var avgSquareDiff = average(squareDiffs); var stdDev = Math.sqrt(avgSquareDiff); return stdDev; } module.exports = { chartOptions: chartOptions, standardDeviation: standardDeviation, average: average, columnChartOptions: columnChartOptions, columnChartFloat: columnChartFloat, scatterChart: scatterChart, addSeriesToColumn: addSeriesToColumn };