/* GV - GeneValidator's JavaScript module Define a global GV (acronym for GeneValidator) object containing all GV associated methods: */ //define global GV object var GV; if (!GV) { GV = {}; } //GV module (function () { 'use strict'; /*global window:false, $:false, d3:false*/ // SHOW ALL PLOTS button GV.toggleAllPlots = function (btn) { if (window.chrome && (window.location.protocol === 'file:')){ $('#browseralert').modal(); } else { var plotBtns = $('.plot_btn'); if (plotBtns.length > 30){ $('#alert').modal(); } else { $('#spinner1').modal({ backdrop: 'static', keyboard: 'false' }); if (btn.status !== 'pressed'){ btn.status = 'pressed'; $('#show_all_plots').html('Hide All Charts'); GV.showAllPlots(); } else { btn.status = 'released'; $('#show_all_plots').html('Show All Charts'); GV.removeAllPlots(); } $('#spinner1').modal('hide'); // remove activity spinner } } }; //iterate over the plot_btns and add data to each childRow GV.showAllPlots = function () { $('.plot_btn').each (function(){ if (this.status !== 'pressed') { GV.addData(this, 'all'); } }); }; GV.removeAllPlots = function () { $('.tablesorter-childRow').each (function(){ $(this).remove(); }); $('.plot_btn').each (function(){ this.status = 'released'; }); }; GV.addData = function (source, val){ if (window.chrome && (window.location.protocol === 'file:')){ $('#browseralert').modal(); } else { var $currentRow = $(source).closest('tr'), target = $currentRow.attr("data-target"), $childRow = $('#mainrow' + target); if ($childRow.length && source.status !== 'pressed') { // if you click on another td... GV.emptyChildRow($currentRow, target, source); GV.addDataToChildRow($currentRow, target, val); } else if ($childRow.length === 0){ GV.createChildRow($currentRow, target, source); GV.addDataToChildRow($currentRow, target, val); } else if ($childRow.length) { GV.removeChildRow($currentRow, $childRow, source); } $('table').trigger('update'); } }; GV.toggleOverviewBtn = function () { if (window.chrome && (window.location.protocol === 'file:')){ $('#overview').remove(); } else { var jsonFile = $("#overview_btn").data('overviewjson'); $.getJSON(jsonFile, function( json ) { var overview = $('' + json.less + '
'); var full_overview = $('' + json.evaluation + '
'); if ( $('#overview_btn').hasClass('active')){ $('#overview_text').html(full_overview); $('#overview_btn').text('Show Less'); GV.addPlot(json.data, 'overview', json.type, json.title, json.footer, json.xtitle, json.ytitle); } else { $('#overview').find('svg').remove(); $('#overview_text').html(overview); $('#overview_btn').text('Show More'); } }); } }; GV.createChildRow = function ($currentRow, target, source) { var childRowHTML = '
'; $currentRow.addClass('tablesorter-hasChildRow'); $currentRow.after(childRowHTML); source.status = 'pressed'; }; GV.removeChildRow = function ($currentRow, $childRow, source) { $currentRow.removeClass('tablesorter-hasChildRow'); $childRow.remove(); source.status = 'released'; }; GV.emptyChildRow = function ($currentRow, target, source) { var targetId = '#' + target; var explanationId = '#' + target + 'explanation'; $(targetId).empty(); $(explanationId).remove(); GV.resetStatusOfOtherButtons($currentRow); source.status = 'pressed'; }; GV.resetStatusOfOtherButtons = function ($currentRow) { $currentRow.find('td').each (function(){ if (this.status == 'pressed') { this.status = 'released'; } }); $currentRow.find('.plot_btn').each (function(){ if (this.status == 'pressed') { this.status = 'released'; } }); }; GV.addDataToChildRow = function ($currentRow, target, val) { var file = $currentRow.attr("data-jsonFile"); $.getJSON(file, function( json ) { if (val === 'all'){ for (var i in json.validations){ if (json.validations[i].graphs !== undefined) { GV.generatePlotCommands(json.validations[i].graphs, target); } } } else { GV.addExplanation(target, json.validations[val]); if (json.validations[val].graphs !== undefined) { GV.generatePlotCommands(json.validations[val].graphs, target); } } }); }; GV.generatePlotCommands = function (graphs, target) { for (var g = 0; g < graphs.length; g++) { var graphData = graphs[g]; GV.addPlot(graphData.data, target, graphData.type, graphData.title, graphData.footer, graphData.xtitle, graphData.ytitle, graphData.aux1, graphData.aux2); } }; GV.addExplanation = function (target, jsonData) { var row = '#row' + target; var approach_html = '

Approach: ' + jsonData.approach + '

'; var explanation_html = '

Explanation: ' + jsonData.explanation + '

'; var conclusion_html = '

Conclusion: ' + jsonData.conclusion + '

'; var explain = $(''); $(row).prepend(explain); }; // Functions that produce the plots in D3 GV.addPlot = function (jsonData, target, type, title, footer, xtitle, ytitle, aux1, aux2) { var legend; if (footer === '') { legend = []; } else { legend = footer.split(';'); } switch(type) { case 'scatter': GV.plot_scatter(jsonData, target, title, footer, xtitle, ytitle, aux1, aux2); break; case 'bars': GV.plot_bars(jsonData, target, title, legend, xtitle, ytitle, aux1); break; case 'simplebars': GV.plot_simple_bars(jsonData, target, title, legend, xtitle, ytitle); break; case 'lines': if (aux2 !== null) { aux2 = aux2.split(','); } GV.plot_lines(jsonData, target, title, legend, xtitle, ytitle, aux1, aux2); break; case 'align': if (aux2 !== null) { aux2 = aux2.split(','); } GV.plot_align(jsonData, target, title, legend, xtitle, ytitle, aux1, aux2); break; default: break; } }; GV.color_beautification = function (color) { switch(color){ case 'red': return d3.rgb(189,54,47); case 'blue': return d3.rgb(58,135,173); case 'green': return d3.rgb(70,136,71); case 'yellow': return d3.rgb(255,255,51); case 'orange': return d3.rgb(248,148,6); case 'violet': return d3.rgb(153,0,153); case 'gray': return d3.rgb(160,160,160); default: return color; } }; // bars plot GV.plot_bars = function (alldata, target, title, footer, xTitle, yTitle, bar) { var margin = {top: 70, right: 50, bottom: 75, left: 50}, width = 600 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var svg = d3.select("#".concat(target)).append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); svg.append("text") .attr("x", (width / 2)) .attr("y", -45) .attr("text-anchor", "middle") .style("font-size", "16px") .text(title); var padding = 100; var flattened_data = [].concat.apply([], alldata); var yMax = d3.max(flattened_data, function(d) { return d.value; }) + 3; var y = d3.scale.linear() .domain([0, yMax + yMax/10]) .range([height, 0]); var xMin = d3.min(flattened_data, function(d) { return d.key; }); if (bar !== undefined){ xMin = Math.min(xMin, bar); } var xMax = d3.max(flattened_data, function(d) { return d.key; }); if (bar !== undefined){ xMax = Math.max(xMax, bar); } var x = d3.scale.linear() .domain([xMin-padding, xMax+padding]) .range([13, width]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(8); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(d3.format("d")) .ticks(8); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .append("text") .attr("class", "label") .attr("x", (width-xTitle.length)/2-50) .attr("y", 35) .style("text-anchor", "start") .text(xTitle); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("class", "label") .attr("transform", "rotate(-90)") .attr("x", -(height+yTitle.length)/2-50) .attr("y", -40) .style("text-anchor", "start") .text(yTitle); alldata.map( function(data) { svg.selectAll(".bar") .data(data) .enter().append("rect") .attr("x", function(d) { return x(d.key); }) .attr("width", 6) .attr("y", function(d) { return y(d.value); }) .attr("height", function(d) { return height - y(d.value); }) .attr("fill", function(d) { if (d.main === true) return GV.color_beautification("red"); return GV.color_beautification("blue");}); }); if (bar !== undefined){ svg.append("rect") .attr("x", x(bar)) .attr("width", 4) .attr("y", y(yMax + yMax/10)) .style("opacity",0.6) .attr("height", height - y(yMax + yMax/8)) .attr("fill", GV.color_beautification("black")); svg.append("text") .attr("transform", "rotate(-90)") .attr("x", -yMax/10 - 35) .attr("y", x(bar) - 5) .text("query"); } var offset = 0; var total_len = 0; for (var i = 0; i < footer.length; i++) { var array = footer[i].split(","); total_len = total_len + array[0].length*8 + 15; } for (var j = 0; j < footer.length; j++) { var footer_array = footer[j].split(","); svg.append("rect") .attr("x", (width-total_len)/2 + offset) .attr("y", -30) .attr("width", 10) .attr("height", 10) .style("fill", GV.color_beautification(footer_array[1].replace(/\s+/g, ''))); svg.append("text") .attr("x", (width-total_len)/2 + offset + 15) .attr("y", -20) .text(footer_array[0]); offset = offset + footer_array[0].length*8 + 15; } }; // bars plot GV.plot_simple_bars = function (alldata, target, title, footer, xTitle, yTitle) { var margin = {top: 70, right: 50, bottom: 75, left: 50}, width = 600 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var svg = d3.select("#".concat(target)).append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); svg.append("text") .attr("x", (width / 2)) .attr("y", -45) .attr("text-anchor", "middle") .style("font-size", "16px") .text(title); var padding = 0; var flattened_data = [].concat.apply([], alldata); var yMax = d3.max(flattened_data, function(d) { return d.value; }) + 3; var y = d3.scale.linear() .domain([0, yMax]) .range([height, 0]); var xMin = d3.min(flattened_data, function(d) { return d.key; }); var xMax = d3.max(flattened_data, function(d) { return d.key; }); var x = d3.scale.linear() .domain([xMin-padding, xMax+padding]) .range([13, width]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(8); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(d3.format("d")) .ticks(8); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .append("text") .attr("class", "label") .attr("x", (width-xTitle.length)/2-50) .attr("y", 35) .style("text-anchor", "start") .text(xTitle); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("class", "label") .attr("transform", "rotate(-90)") .attr("x", -(height+yTitle.length)/2-50) .attr("y", -40) .style("text-anchor", "start") .text(yTitle); alldata.map( function(data) { svg.selectAll(".bar") .data(data) .enter().append("rect") .attr("x", function(d) { return x(d.key); }) .attr("width", 6) .attr("y", function(d) { return y(d.value); }) .attr("height", function(d) { return height - y(d.value); }) .attr("fill", function(d) { if (d.main === true) return GV.color_beautification("red"); return GV.color_beautification("blue");}); }); }; // scatter plot // ecuation of the line: slope * x + yLine GV.plot_scatter = function (data, target, title, footer, xTitle, yTitle, yLine, slope) { var margin = {top: 50, right: 30, bottom: 75, left: 50}, width = 500 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var x = d3.scale.linear() .range([0, width]); var y = d3.scale.linear() .range([height, 0]); var color = d3.scale.category10(); var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(8); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(d3.format("d")) .ticks(8); var svg = d3.select("#".concat(target)).append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); svg.append("text") .attr("x", (width / 2)) .attr("y", -25) .attr("text-anchor", "middle") .style("font-size", "16px") .text(title); svg.append("text") .attr("x", (width / 2)) .attr("y", height+ 55) .attr("text-anchor", "middle") .style("font-size", "12px") .text(footer); var xMax = d3.max(data, function(d) { return d.x; }); var xMin = d3.min(data, function(d) { return d.x; }); var yMax = d3.max(data, function(d) { return d.y; }); var yMin = d3.min(data, function(d) { return d.y; }); x.domain(d3.extent(data, function(d) { return d.x; })).nice(); y.domain(d3.extent(data, function(d) { return d.y; })).nice(); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .append("text") .attr("class", "label") .attr("x", (width-xTitle.length)/2-50) .attr("y", 35) .style("text-anchor", "start") .text(xTitle); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("class", "label") .attr("transform", "rotate(-90)") .attr("x", -(height+yTitle.length)/2-50) .attr("y", -40) .style("text-anchor", "start") .text(yTitle); svg.selectAll(".dot") .data(data) .enter().append("circle") .attr("r", 2) .attr("cx", function(d) { return x(d.x); }) .attr("cy", function(d) { return y(d.y); }) .style("fill", function() { return GV.color_beautification("red"); }) .style("opacity",0.6); if ((slope !== undefined && slope !== "") && (yLine !== undefined && yLine !== "")){ yLine = parseFloat(yLine.replace(",", ".")); var xMaxValue = xMax; var yMaxValue = yLine + slope * xMax; if (yMaxValue > yMax){ xMaxValue = (yMax-yLine)/slope; yMaxValue = yMax; } if (yMaxValue < yMin){ xMaxValue = (yMin-yLine)/slope; yMaxValue = yMin; } var xMinValue = xMin; var yMinValue = yLine + slope * xMin; if (yMinValue > yMax){ xMinValue = (yMax-yLine)/slope; yMinValue = yMin; } if (yMinValue < yMin){ xMinValue = (yMin-yLine)/slope; yMinValue = yMin; } svg.append("line") .attr("x1", x(xMinValue)) .attr("y1", y(yMinValue)) .attr("x2", x(xMaxValue)) .attr("y2", y(yMaxValue)) .attr("stroke-width", 2) .attr("stroke", "black"); } }; // line plot // maximum 80 lines GV.plot_lines = function (data, target, title, footer, xTitle, yTitle, no_lines, yValues) { var margin = {top: 70, right: 50, bottom: 75, left: 50}, width = 600 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var x = d3.scale.linear() .range([0, width]); var y = d3.scale.linear() .range([height, 0]); var color = d3.scale.category10(); var xAxis = ''; if (title === 'Open Reading Frames in all 6 Frames') { xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(0); } else { xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(5); } var yAxis = d3.svg.axis() .scale(y) .orient("left") .ticks(5); var svg = d3.select("#".concat(target)).append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); svg.append("text") .attr("x", (width / 2)) .attr("y", -35) .attr("text-anchor", "middle") .style("font-size", "16px") .text(title); var idx = -1; x.domain([0, d3.max(data, function(d) { return d.stop; })]); y.domain(d3.extent(data, function(d) { return d.y; })).nice(); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + (height + height/no_lines) + ")") .call(xAxis) .append("text") .attr("class", "label") .attr("x", (width-xTitle.length)/2-50) .attr("y", 35) .style("text-anchor", "start") .text(xTitle); if (yValues !== null){ svg.append("g") .attr("class", "y axis") .call(yAxis.ticks(yValues.length) .tickFormat(function() { idx = idx + 1; return yValues[idx]; })) .append("text") .attr("class", "label") .attr("transform", "rotate(-90)") .attr("x", -(height+yTitle.length)/2-50) .attr("y", -40) .style("text-anchor", "start") .text(yTitle); } else { svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("class", "label") .attr("transform", "rotate(-90)") .attr("x", -(height+yTitle.length)/2) .attr("y", -40) .style("text-anchor", "start") .text(yTitle); } svg.selectAll(".dot") .data(data) .enter().append("line") .attr("x1", function(d) { return x(d.start); }) .attr("y1", function(d) { return y(d.y); }) .attr("x2", function(d) { return x(d.stop); }) .attr("x2", function(d) { return x(d.stop); }) .attr("y2", function(d) { return y(d.y); }) .attr("stroke-width", function(d) { if (d.dotted === undefined) { if (d.color == "red" ) { return height/no_lines/2.5; } else { return height/no_lines; } } else { return height/no_lines/5; } }) .style("stroke-dasharray", function(d) { if (d.dotted === undefined) return ("0, 0"); return ("2, 6");}) .attr("stroke", function(d) { return GV.color_beautification(d.color); }); // add legend var legend = svg.append("g") .attr("class", "legend") .attr("height", 100) .attr("width", 100) .attr('transform', 'translate(-20,50)'); var offset = 40; var total_len = 0; for (var i = 0; i < footer.length; i++) { var array = footer[i].split(","); total_len = total_len + array[0].length*8 + 15; } for (var j = 0; j < footer.length; j++) { var footer_array = footer[j].split(","); svg.append("rect") .attr("x", (width-total_len)/2 + offset) .attr("y", -30) .attr("width", 10) .attr("height", 10) .style("fill", GV.color_beautification(footer_array[1].replace(/\s+/g, ''))); svg.append("text") .attr("x", (width-total_len)/2 + offset + 15) .attr("y", -20) .text(footer_array[0]); offset = offset + footer_array[0].length*8 + 15; } }; // line plot // maximum 80 lines GV.plot_align = function (data, target, title, footer, xTitle, yTitle, no_lines, yValues) { var margin = {top: 75, right: 50, bottom: 75, left: 150}, width = 600 - margin.left - margin.right, height = 300 - margin.top - margin.bottom; var x = d3.scale.linear() .range([0, width]); var y = d3.scale.linear() .range([height, 0]); var color = d3.scale.category10(); var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(5); var yAxis = d3.svg.axis() .scale(y) .orient("left") .ticks(5); var svg = d3.select("#".concat(target)).append("svg") .style("vertical-align", "top") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); svg.append("text") .attr("x", (width / 2)) .attr("y", -35) .attr("text-anchor", "middle") .style("font-size", "16px") .text(title); var idx = -1; x.domain([0, d3.max(data, function(d) { return d.stop; })]); y.domain(d3.extent(data, function(d) { return d.y; })).nice(); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + (height+height/no_lines) + ")") .call(xAxis) .append("text") .attr("class", "label") .attr("x", (width-xTitle.length)/2-50) .attr("y", 35) .style("text-anchor", "start") .text(xTitle); if (yValues !== null){ svg.append("g") .attr("class", "y axis") .call(yAxis.ticks(yValues.length) .tickFormat(function() { idx = idx + 1; return yValues[idx]; })) .append("text") .attr("class", "label") .attr("transform", "rotate(-90)") .attr("x", -(height+yTitle.length)/2-50) .attr("y", -40) .style("text-anchor", "start") .text(yTitle); } else { svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("class", "label") .attr("transform", "rotate(-90)") .attr("x", -(height+yTitle.length)/2-50) .attr("y", -40) .style("text-anchor", "start") .text(yTitle); } svg.selectAll(".dot") .data(data) .enter().append("line") .attr("x1", function(d) { return x(d.start); }) .attr("y1", function(d) { return y(d.y); }) .attr("x2", function(d) { return x(d.stop); }) .attr("y2", function(d) { return y(d.y); }) .attr("stroke-width", function(d) { if (d.height == -1) return height/no_lines; return (height/no_lines * d.height) ; }) .attr("stroke", function(d) { return GV.color_beautification(d.color); }); var offset = 0; var total_len = 0; for (var i = 0; i < footer.length; i++) { var array = footer[i].split(","); total_len = total_len + array[0].length*8 + 15; } for (var j = 0; j < footer.length; j++) { var footer_array = footer[j].split(","); svg.append("rect") .attr("x", (width-total_len)/2 + offset) .attr("y", -30) .attr("width", 10) .attr("height", 10) .style("fill", GV.color_beautification(footer_array[1].replace(/\s+/g, ''))); svg.append("text") .attr("x", (width-total_len)/2 + offset + 15) .attr("y", -20) .text(footer_array[0]); offset = offset + footer_array[0].length*8 + 15; } }; }());