diff --git a/VQI_GenomeBrowser.js b/VQI_GenomeBrowser.js index 0fd3164..550ffc3 100644 --- a/VQI_GenomeBrowser.js +++ b/VQI_GenomeBrowser.js @@ -1,73 +1,72 @@ function VQI_GenomeBrowser(id){ - this.div_id = id; + var div_id = id; - this.width = 1000; + var width = 1000; - this.height = 100; + var height = 100; - this.margin = 50; + var margin = 50; - this.genomeData = []; + var genomeData = []; - this.chromosomes = []; + var chromosomes = []; $("#" + id).append("
CPG:Shore:Shelve:
"); - d3.select("#" + id + " #submit").on("click", this.submitFile.bind(this)); d3.select("#" + id).append("div").text("Chromosome: ") - this.select = d3.select("#" + id) + var select = d3.select("#" + id) .append("div") .append("select") .on("change", function(d) { - self.graph(self.select.property("value")); + graph(select.property("value")); }); d3.select("#" + id).append("div").text("Start: ") - this.minNumber = d3.select("#" + id) + var minNumber = d3.select("#" + id) .append("input") .attr("type","number") .property("value",0); d3.select("#" + id).append("div").text("End: ") - this.maxNumber = d3.select("#" + id) + var maxNumber = d3.select("#" + id) .append("input") .attr("type","number") .property("value",0); var self = this; - this.graphButton = d3.select("#" + id) + var graphButton = d3.select("#" + id) .append("input") .attr("type","button") .attr("value","Graph") .on("click", function(){ - self.graph(self.select.property("value"),self.minNumber.property("value"),self.maxNumber.property("value")) + graph(select.property("value"),minNumber.property("value"),maxNumber.property("value")) }); - this.svg = d3.select("#" + id) + var svg = d3.select("#" + id) .append("svg") - .attr("width", this.width + 2 * this.margin) - .attr("height", this.height + 2 * this.margin); + .attr("width", width + 2 * margin) + .attr("height", height + 2 * margin); //set up scales and axis - this.xScale = d3.scale.linear(); + var xScale = d3.scale.linear(); - this.xAxis = d3.svg.axis() - .scale(this.xScale) + var xAxis = d3.svg.axis() + .scale(xScale) .orient("bottom") .ticks(10); - this.xAxisSelection = this.svg.append("g") - .call(this.xAxis) + var xAxisSelection = svg.append("g") + .call(xAxis) .attr("class", "axis") - .attr("transform", "translate(0,"+ (this.height + this.margin) + ")"); + .attr("transform", "translate(0,"+ (height + margin) + ")"); - this.zoom = d3.behavior.zoom(); + var zoom = d3.behavior.zoom(); //set up tool tips - this.tip = d3.tip() + var tip = d3.tip() .attr('class', 'd3-tip') .offset([-20, 0]) .html(function(d) { @@ -75,7 +74,7 @@ function VQI_GenomeBrowser(id){ + "(" + d.start + " - " + d.end + ")"+ ""; }); - this.svg.call(this.tip); + svg.call(tip); d3.selectAll(".d3-tip").style({ "line-height": "1", @@ -85,189 +84,187 @@ function VQI_GenomeBrowser(id){ "color": "#fff", "border-radius": "2px" }); -} - -VQI_GenomeBrowser.prototype = new VQI_Publisher(); - - -VQI_GenomeBrowser.prototype.zoomed = function() { - var self = this; - - self.xAxisSelection.call(self.xAxis); - - self.svg.selectAll("rect") - .attr("width", function (d) {return self.xScale(d.end) - self.xScale(d.start)}) - .attr("x", function(d) {return self.xScale(d.start)}) - - self.minNumber.property("value", self.xScale.domain()[0]); - self.maxNumber.property("value", self.xScale.domain()[1]); - - d3.selectAll(".axis path, .axis line").style({ - "fill": "none", - "stroke": "black", - "shape-rendering": "crispEdges"}); - - d3.selectAll(".axis text").style({ - "font-family": "sans-serif", - "font-size": "11px"}); -} + var zoomed = function() { + xAxisSelection.call(xAxis); + + svg.selectAll("rect") + .attr("width", function (d) {return xScale(d.end) - xScale(d.start)}) + .attr("x", function(d) {return xScale(d.start)}) -VQI_GenomeBrowser.prototype.graph = function(chromosome , min , max){ - //Graphs the current chromosome. If min and max are specified, graph only in that range. - //Otherwise, graphs the whole chromosome + minNumber.property("value", xScale.domain()[0]); + maxNumber.property("value", xScale.domain()[1]); - var self = this; + d3.selectAll(".axis path, .axis line").style({ + "fill": "none", + "stroke": "black", + "shape-rendering": "crispEdges"}); - var currentData; - var xMax = 0; - var xMin = 0; - - //Populates drop down list with different chromosomes - self.select.selectAll("option") - .data(self.chromosomes) - .enter() - .append("option") - .attr("value", function (d) { return d; }) - .text(function (d) { return d; }) - - //Gets relevant data and calculates min/max if needed - if(min == null || max == null) - { - currentData = self.genomeData.filter(function(d) {return d.chromosome == chromosome}); - - xMax = d3.max(currentData, function(d) {return d.end}); - xMin = d3.min(currentData, function(d) {return d.start}); - self.minNumber.property("value", xMin); - self.maxNumber.property("value", xMax); - } - else - { - currentData = self.genomeData.filter(function(d) {return d.chromosome == chromosome && d.start >= min && d.end <= max}); - xMax = Number(max); - xMin = Number(min); + d3.selectAll(".axis text").style({ + "font-family": "sans-serif", + "font-size": "11px"}); } - self.xScale.domain([xMin - (xMax - xMin) * 1/10, xMax + (xMax - xMin) * 1/10]) - .range([self.margin, self.width + self.margin]); - - self.xAxisSelection.call(self.xAxis); - - self.zoom.x(self.xScale) - .on("zoom", self.zoomed.bind(self)); - - self.svg.call(self.zoom); - - d3.selectAll(".axis path, .axis line").style({ - "fill": "none", - "stroke": "black", - "shape-rendering": "crispEdges"}); - - d3.selectAll(".axis text").style({ - "font-family": "sans-serif", - "font-size": "11px"}); - - //Just a line - self.svg.append("line") - .attr("x1",self.margin) - .attr("y1",self.height/2 + self.margin + 20) - .attr("x2",self.width+self.margin) - .attr("y2",self.height/2 + self.margin + 20) - .style("stroke", "blue"); - - self.svg.selectAll("rect") - .data(currentData) - .exit() - .remove(); - - self.svg.selectAll("rect") - .data(currentData) - .enter() - .append("rect"); - - self.svg.selectAll("rect") - .style("fill-opacity", ".4") - .style("stroke", function (d) { return d.type == "cpg" ? "red" : d.type == "shore" ? "green" : "yellow"}) - .style("fill", function (d) { return d.type == "cpg" ? "red" : d.type == "shore" ? "green" : "yellow"}) - .attr("height", function (d) { return d.type == "cpg" ? 40 : d.type == "shore" ? 20 : 15}) - .attr("width", function (d) {return self.xScale(d.end) - self.xScale(d.start)}) - .attr("x", function(d) {return self.xScale(d.start)}) - .attr("y", function (d) { var offset = d.type == "cpg" ? 0 : d.type == "shore" ? 10 : 12.5; - return self.height/2 + self.margin + offset}) - .on('mouseover', self.tip.show) - .on('mouseout', self.tip.hide); -} + var graph = function(chromosome , min , max){ + //Graphs the current chromosome. If min and max are specified, graph only in that range. + //Otherwise, graphs the whole chromosome + var self = this; + + var currentData; + var xMax = 0; + var xMin = 0; + + //Populates drop down list with different chromosomes + select.selectAll("option") + .data(chromosomes) + .enter() + .append("option") + .attr("value", function (d) { return d; }) + .text(function (d) { return d; }) + + //Gets relevant data and calculates min/max if needed + if(min == null || max == null) + { + currentData = genomeData.filter(function(d) {return d.chromosome == chromosome}); + + xMax = d3.max(currentData, function(d) {return d.end}); + xMin = d3.min(currentData, function(d) {return d.start}); + minNumber.property("value", xMin); + maxNumber.property("value", xMax); + } + else + { + currentData = genomeData.filter(function(d) {return d.chromosome == chromosome && d.start >= min && d.end <= max}); + xMax = Number(max); + xMin = Number(min); + } + + xScale.domain([xMin - (xMax - xMin) * 1/10, xMax + (xMax - xMin) * 1/10]) + .range([margin, width + margin]); + + xAxisSelection.call(xAxis); + + zoom.x(xScale) + .on("zoom", zoomed.bind(self)); + + svg.call(zoom); + + d3.selectAll(".axis path, .axis line").style({ + "fill": "none", + "stroke": "black", + "shape-rendering": "crispEdges"}); + + d3.selectAll(".axis text").style({ + "font-family": "sans-serif", + "font-size": "11px"}); + + //Just a line + svg.append("line") + .attr("x1",margin) + .attr("y1",height/2 + margin + 20) + .attr("x2",width+margin) + .attr("y2",height/2 + margin + 20) + .style("stroke", "blue"); + + svg.selectAll("rect") + .data(currentData) + .exit() + .remove(); + + svg.selectAll("rect") + .data(currentData) + .enter() + .append("rect"); + + svg.selectAll("rect") + .style("fill-opacity", ".4") + .style("stroke", function (d) { return d.type == "cpg" ? "red" : d.type == "shore" ? "green" : "yellow"}) + .style("fill", function (d) { return d.type == "cpg" ? "red" : d.type == "shore" ? "green" : "yellow"}) + .attr("height", function (d) { return d.type == "cpg" ? 40 : d.type == "shore" ? 20 : 15}) + .attr("width", function (d) {return xScale(d.end) - xScale(d.start)}) + .attr("x", function(d) {return xScale(d.start)}) + .attr("y", function (d) { var offset = d.type == "cpg" ? 0 : d.type == "shore" ? 10 : 12.5; + return height/2 + margin + offset}) + .on('mouseover', tip.show) + .on('mouseout', tip.hide); + } -VQI_GenomeBrowser.prototype.setData = function(data){ - this.genomeData = data; - this.graph(); -} + var setData = function(data){ + genomeData = data; + graph(chromosomes[0]); + } -VQI_GenomeBrowser.prototype.getData = function(){ - return this.genomeData; -} + var getData = function(){ + return genomeData; + } -VQI_GenomeBrowser.prototype.submitFile = function(){ - var self = this; - self.genomeData = []; - self.chromosomes = []; + var submitFile = function(){ + genomeData = []; + chromosomes = []; - //Will read the 3 files and place all data into genomeData - //as objects with attributes 'chromosome', 'start', 'end', 'type' + //Will read the 3 files and place all data into genomeData + //as objects with attributes 'chromosome', 'start', 'end', 'type' - $.get($("#" + self.div_id + " #cpg").val().split('\\').pop(), function(data){ - var cpgData = data.trim().split("\n"); - $.each(cpgData , function(index , value){ - cpgData[index] = cpgData[index].trim().split("\t").map(function(item) { - return isNaN(Number(item)) ? item : Number(item); + $.get($("#" + div_id + " #cpg").val().split('\\').pop(), function(data){ + var cpgData = data.trim().split("\n"); + $.each(cpgData , function(index , value){ + cpgData[index] = cpgData[index].trim().split("\t").map(function(item) { + return isNaN(Number(item)) ? item : Number(item); + }); }); - }); - //get all unique chromosomes - var currentChromosome = ""; - $.each(cpgData , function(index , value){ - if(value[0] != currentChromosome) - { - self.chromosomes.push(value[0]); - currentChromosome = value[0]; - } - }); + //get all unique chromosomes + var currentChromosome = ""; + $.each(cpgData , function(index , value){ + if(value[0] != currentChromosome) + { + chromosomes.push(value[0]); + currentChromosome = value[0]; + } + }); - cpgData = cpgData.map(function(data){ - return {"chromosome" : data[0], "start" : data[1], "end" : data[2], "type" : "cpg"} + cpgData = cpgData.map(function(data){ + return {"chromosome" : data[0], "start" : data[1], "end" : data[2], "type" : "cpg"} + }); + genomeData = genomeData.concat(cpgData); }); - self.genomeData = self.genomeData.concat(cpgData); - }); - $.get($("#" + self.div_id + " #shore").val().split('\\').pop(), function(data){ - var tempShoreData = data.trim().split("\n"); - $.each(tempShoreData , function(index , value){ - tempShoreData[index] = tempShoreData[index].trim().split("\t").map(function(item) { - return isNaN(Number(item)) ? item : Number(item); + $.get($("#" + div_id + " #shore").val().split('\\').pop(), function(data){ + var tempShoreData = data.trim().split("\n"); + $.each(tempShoreData , function(index , value){ + tempShoreData[index] = tempShoreData[index].trim().split("\t").map(function(item) { + return isNaN(Number(item)) ? item : Number(item); + }); }); + var shoreData = []; + $.each(tempShoreData , function(index , value){ + shoreData.push({"chromosome" : value[0], "start" : value[1], "end" : value[2], "type" : "shore"}); + shoreData.push({"chromosome" : value[0], "start" : value[3], "end" : value[4], "type" : "shore"}); + }); + genomeData = genomeData.concat(shoreData); }); - var shoreData = []; - $.each(tempShoreData , function(index , value){ - shoreData.push({"chromosome" : value[0], "start" : value[1], "end" : value[2], "type" : "shore"}); - shoreData.push({"chromosome" : value[0], "start" : value[3], "end" : value[4], "type" : "shore"}); - }); - self.genomeData = self.genomeData.concat(shoreData); - }); - $.get($("#" + self.div_id + " #shelve").val().split('\\').pop(), function(data){ - var tempShelveData = data.trim().split("\n"); - $.each(tempShelveData , function(index , value){ - tempShelveData[index] = tempShelveData[index].trim().split("\t").map(function(item) { - return isNaN(Number(item)) ? item : Number(item); + $.get($("#" + div_id + " #shelve").val().split('\\').pop(), function(data){ + var tempShelveData = data.trim().split("\n"); + $.each(tempShelveData , function(index , value){ + tempShelveData[index] = tempShelveData[index].trim().split("\t").map(function(item) { + return isNaN(Number(item)) ? item : Number(item); + }); }); + var shelveData = []; + $.each(tempShelveData , function(index , value){ + shelveData.push({"chromosome" : value[0], "start" : value[1], "end" : value[2], "type" : "shelve"}); + shelveData.push({"chromosome" : value[0], "start" : value[3], "end" : value[4], "type" : "shelve"}); + }); + genomeData = genomeData.concat(shelveData); + graph(chromosomes[0]); }); - var shelveData = []; - $.each(tempShelveData , function(index , value){ - shelveData.push({"chromosome" : value[0], "start" : value[1], "end" : value[2], "type" : "shelve"}); - shelveData.push({"chromosome" : value[0], "start" : value[3], "end" : value[4], "type" : "shelve"}); - }); - self.genomeData = self.genomeData.concat(shelveData); - self.graph(self.chromosomes[0]); - }); + } + + d3.select("#" + id + " #submit").on("click", submitFile.bind(this)); + } + +VQI_GenomeBrowser.prototype = new VQI_Publisher(); +