Skip to content
Permalink
5383bcf3c7
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
executable file 1617 lines (1371 sloc) 55.7 KB
function VQI_GenomeBrowser(id, serviceURL) {
var divId = id;
var width = 1000;
var height = 20;
var margin = 50;
var bufferSpace = 20;
var trackHeight = 50;
var panExtent = [0, width];
var trackList = [];
var genomeData = [];
var chromosomes = [];
var thisObj = this;
var chrom_curr = "chr1";
var indexArray = {chr: 0, start: 1, end: 2, name: 3, type: 3, score: 4, strand: 5, options: 6, exonStarts: 9, exonEnds: 10};
var testdata;
var isready = false;
var zoomOnly = false;
var trackInfo = [];
trackInfo[0] = {name: "HG19", type: "bed", fileHandle: "upload1436481988"};
trackInfo[1] = {name: "Tile2 Content Snp", type: "bed", fileHandle: "upload1436411775"};
trackInfo[2] = {name: "cpg", type: "cpg", fileHandle: "upload1437097194,upload1437098473,upload1437098556"};
var serviceURL = serviceURL;
// $("#" + id).append("<div style='border : 1px solid; display : inline-block'>CPG:<input type='file' id='cpg'/>Shore:<input type='file' id='shore'/>Shelve:<input type='file' id='shelve'/><input id='submit' type='submit' /></div>");
// d3.select("#" + id).append("div").text("Chromosome: ")
// var select = d3.select("#" + id)
// .append("div")
// .append("select")
// .on("change", function (d) {
// graph(select.property("value"));
// });
//
// d3.select("#" + id).append("div").text("Start: ")
// var minNumber = d3.select("#" + id)
// .append("input")
// .attr("type", "number")
// .property("value", 0);
//
// d3.select("#" + id).append("div").text("End: ")
// var maxNumber = d3.select("#" + id)
// .append("input")
// .attr("type", "number")
// .property("value", 0);
// var graphButton = d3.select("#" + id)
// .append("input")
// .attr("type", "button")
// .attr("value", "Graph")
// .on("click", function () {
// graph(select.property("value"), minNumber.property("value"), maxNumber.property("value"))
// });
var navigateToRegion = function () {
var navigate = $("#" + divId + " #navigate").val();
navigate = navigate.split(/[:-]/);
if (navigate.length == 3){
var chrom = navigate[0].trim();
var chrom_start = Number(navigate[1].trim());
var chrom_end = Number(navigate[2].trim());
//Only need to set bounds if current chromosome is already graphed
if (chrom == chrom_curr)
{
setBounds(chrom_start, chrom_end);
}
else
{
graph(chrom, chrom_start, chrom_end);
}
}
else
{
browseToGene();
}
};
/*this.makeNavigationForm = function () {
var navigateBox = "<input type='text' name='navigate' id='navigate' size='30'>";
var navigateButton = "<input type='button' id='navigatebutton' value='Go To'>";
var form = "<form id='navigation_form'>" + navigateBox + navigateButton + "</form>";
$("#" + divId).append(form);
$("#" + divId + " #navigatebutton").on("click", navigateToRegion.bind(this));
};
this.makeNavigationForm();*/
var browseToGene = function () {
var geneName = $("#" + divId + " #navigate").val();
var genes = [geneName];
dataToPost = JSON.stringify(genes);
$.ajax({
url: vqi_url + 'serverside/web/VQService.php?service=gene-info-for-gene-symbol',
type: 'POST',
dataType: "json",
data: {
"genes": dataToPost
},
async: false
}).success(function (data) {
var thisGene = data.slice(1)[0];
var gene_chrom = thisGene[2];
var gene_start = thisGene[3];
var gene_end = thisGene[4];
thisObj.navigate(gene_chrom, gene_start, gene_end);
// objVQIResult.parseSNPAndSNP(data, true);
}).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
};
this.makeNavigationForm = function () {
var navigateBox = "<input type='text' name='navigate' id='navigate' size='30'>";
var navigateButton = "<input type='button' id='navigatebutton' value='Go To'>";
//var geneText = "Gene: <input type='text' name='geneName' id='geneName'>";
//var geneSearchButton = "<input type='button' id='genesearchbutton' value='Search'>";
var form = "<form id='navigation_form'>" + navigateBox + navigateButton + "</form>";
$("#" + divId).append(form);
//$("#" + divId + " #genesearchbutton").on("click", browseToGene.bind(this));
$("#" + divId + " #navigatebutton").on("click", navigateToRegion.bind(this));
};
this.makeNavigationForm();
var colocalize = function () {
var track1Name = $("#" + divId + " #track1").val();
var track2Name = $("#" + divId + " #track2").val();
var coloc_dist = $("#" + divId + " #coloc_dist").val();
if(track1Name === track2Name){
alert("Track1 and Track2 cannot be same for colocalization.");
return;
}
var data1 = this.getTrackByName(track1Name);
var data2 = this.getTrackByName(track2Name);
var dataToPost1 = [], dataToPost2 = [];
dataToPost1 = JSON.stringify(data1);
dataToPost2 = JSON.stringify(data2);
var data1Length = data1.length;
var data2Length = data2.length;
$.ajax({
url: vqi_url + 'serverside/web/VQService.php?service=coloc-bed-and-bed',
type: 'POST',
dataType: "json",
data: {
"bed1": dataToPost1,
"bed2": dataToPost2,
"coloc_dist": coloc_dist
},
async: false
}).success(function (data) {
var data1 = [];
var data2 = []
data = data.slice(1);
for (var i in data) {
data1.push(data[i].slice(0, 6));
data2.push(data[i].slice(6));
}
thisObj.addTrack(data1);
thisObj.addTrack(data2);
thisObj.getPValue(data1Length, data2Length, data1.length);
// objVQIResult.parseSNPAndSNP(data, true);
}).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
};
/**
*
* @author Pujan Joshi
* @since April 16, 2015
* @param {type} k1
* @param {type} k2
* @param {type} ob
* @returns {p-value}
*
* This method calls Yue's pvalue program and returns p-value result.
*/
this.getPValue = function (k1, k2, ob) {
$.ajax({
url: vqi_url + 'serverside/web/VQService.php?service=coloc-pvalue',
type: 'GET',
dataType: "text",
data: {
"K1": k1,
"K2": k2,
"OB": ob
},
async: true
}).success(function (data) {
console.log(data);
$("#pvalue_div").empty().append("p-value = " + data);
// alert("pvalue = " + data);
// objVQIResult.parseSNPAndSNP(data, true);
}).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
}
this.makeFormForColocalization = function () {
var track1Select = "Track1: <select name='track1' id='track1'>";
for (var i in trackList) {
var thisTrack = trackList[i];
var text = thisTrack['name'];
var value = thisTrack['name'];
track1Select += "<option value='" + value + "'>" + text + "</option>";
}
track1Select += "</select>";
var track2Select = " Track2: <select name='track2' id='track2'>";
for (var i in trackList) {
var thisTrack = trackList[i];
var text = thisTrack['name'];
var value = thisTrack['name'];
track2Select += "<option value='" + value + "'>" + text + "</option>";
}
track2Select += "</select>";
var distanceTextBox = "<input type=text name='coloc_dist' id='coloc_dist' value='100'>";
var colocalizeButton = "<input type='button' id='colocalize' value='colocalize'>";
var pValueDiv = "<div id='pvalue_div'></div>"
var form = "<form id='colocalization_form'>" + track1Select + track2Select + distanceTextBox + colocalizeButton + pValueDiv + "</form>";
$("#" + divId).append(form);
$("#" + divId + " #colocalize").on("click", colocalize.bind(this));
};
this.makeFormForColocalization();
var removeSelectedTracks = function () {
var tracknames = []
for (var i in trackList) {
if (graphRegion.selectAll("g").data([trackList[i]['name']], function (d) {
return d;
}).select("#check").node().checked)
{
tracknames.push(trackList[i]['name']);
}
}
for (var i in tracknames) {
removeTrack(tracknames[i]);
}
reorderTracks();
}
var removeTrack = function (removedTrackName) {
//var removedTrackName = $("#" + divId + " #removeTrack").val();
if (removedTrackName != null)
{
for (var i in trackList) {
var thisTrack = trackList[i];
if (thisTrack['name'] == removedTrackName) {
svg.selectAll("g").data([trackList[i]['name']], function (d) {
return d;
}).remove();
trackList.splice(i, 1);
break;
}
}
}
updateAllTracksSelectBoxes();
//graph(chrom_curr, xScale.domain()[0], xScale.domain()[1]);
};
/*this.makeFormForRemoveTrack = function () {
var removeTrackSelect = "Remove: <select name='removeTrack' id='removeTrack'>";
for (var i in trackList) {
var thisTrack = trackList[i];
var text = thisTrack['name'];
var value = thisTrack['name'];
removeTrackSelect += "<option value='" + value + "'>" + text + "</option>";
}
removeTrackSelect += "</select>";
var removeButton = "<input type='button' id='removetrackbutton' value='Remove Track'>";
var form = "<form id='removeTrack_form'>" + removeTrackSelect + removeButton + "</form>";
$("#" + divId).append(form);
$("#" + divId + " #removetrackbutton").on("click", removeTrack.bind(this));
};
this.makeFormForRemoveTrack();*/
this.getSelectedTrackNames = function(){
var tracknames = []
for (var i in trackList) {
if (graphRegion.selectAll("g").data([trackList[i]['name']], function (d) {
return d;
}).select("#check").node().checked)
{
tracknames.push(trackList[i]['name']);
}
}
return tracknames;
}
this.getSelectedTracks = function(){
tracknames = thisObj.getSelectedTrackNames();
tracks = [];
for (var i in tracknames) {
tracks.push(thisObj.getTrackByName(tracknames[i]));
}
return tracks;
}
var exportSelectedTracks = function () {
var tracknames = []
for (var i in trackList) {
if (graphRegion.selectAll("g").data([trackList[i]['name']], function (d) {
return d;
}).select("#check").node().checked)
{
tracknames.push(trackList[i]['name']);
}
}
for (var i in tracknames) {
exportTrack(tracknames[i]);
}
}
var exportTrack = function (track_name) {
// alert("here");
// var outputFile = window.prompt("What do you want to name your output file (Note: This won't have any effect on Safari)") || 'export';
// outputFile = outputFile.replace('.csv','') + '.txt'
//var track_name = $("#" + divId + " #exportTrack").val();
var track = thisObj.getTrackByName(track_name);
// console.log(track);
exportTrackToText(track, track_name);
}
/*this.makeFormForExportTrack = function () {
var exportTrackSelect = "Export: <select name='exportTrack' id='exportTrack'>";
for (var i in trackList) {
var thisTrack = trackList[i];
var text = thisTrack['name'];
var value = thisTrack['name'];
exportTrackSelect += "<option value='" + value + "'>" + text + "</option>";
}
exportTrackSelect += "</select>";
var exportButton = "<input type='button' id='exporttrackbutton' value='Export'>";
var form = "<form id='exportTrack_form'>" + exportTrackSelect + exportButton + "</form>";
$("#" + divId).append(form);
$("#" + divId + " #exporttrackbutton").on("click", exportTrack.bind(this));
}
this.makeFormForExportTrack();*/
this.makeSelectionForm = function () {
var removeButton = "<input type='button' id='removetrackbutton' value='Remove Track'>";
var exportButton = "<input type='button' id='exporttrackbutton' value='Export'>";
// var scoreButton = "<input type='button' id='scoreTracks' value='Score' onclick='VQI_ControlPanel.scoreButtonClicked()'>";
var mcScoreButton = "<input type='button' id='mcscoreTracks' value='MC System' onclick='VQI_ControlPanel.scoreButtonClicked()'>";
var entScoreButton = "<input type='button' id='entscoreTracks' value='EMT Score' onclick='VQI_ControlPanel.EMTScoreButtonClicked()'>";
var form = "<form id='selectionForm'>" + removeButton + exportButton + mcScoreButton + entScoreButton + "</form>";
$("#" + divId).append(form);
$("#" + divId + " #removetrackbutton").on("click", removeSelectedTracks.bind(this));
$("#" + divId + " #exporttrackbutton").on("click", exportSelectedTracks.bind(this));
};
this.makeSelectionForm();
var self = this;
this.svg = d3.select("#" + id)
.append("svg")
.attr("width", width + 2 * margin)
.attr("height", height + 2 * margin)
.style("border", "1px solid black");
var svg = this.svg;
var graphRegion = svg.append("g").attr("transform", "translate(" + margin + "," + margin + ")");
//set up scales and axis
var fullXScale = d3.scale.linear();
var xScale = d3.scale.linear();
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(10);
//x-axis
var xAxisSelection = graphRegion.append("g")
.call(xAxis)
.attr("class", "axis")
// .attr("transform", "translate(0," + (height + margin) + ")");
var zoom = d3.behavior.zoom();
var clipPath = graphRegion.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height)
.attr("y", -margin); //to make this work with all the transformations.
//set up tool tips
/*var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-20, 0])
.html(function (d) {
// if(/)
// if
var strand = "";
if (d.length > indexArray.strand) {
strand = " (" + d[indexArray.strand] + ")";
}
return "<span style='color:white; font-size:10pt; display:block; text-align:center'>" + d[indexArray.name] + strand + "</span>"
+ "<span style='color:white; font-size:10pt; display:block'>(" + d[indexArray.chr] + " : " + d[indexArray.start] + " - " + d[indexArray.end] + ")" + "</span>";
});
svg.call(tip);
d3.selectAll(".d3-tip").style({
"line-height": "1",
"font-weight": "bold",
"padding": "12px",
"background": "rgba(0, 0, 0, 0.8)",
"color": "#fff",
"border-radius": "2px"
});*/
var zoomed = function () {
zoom.translate([panLimit(), 0]);
//console.log(d3.event.scale);
//svg.selectAll("g.scalable").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ",1)");
//fast, scales as a group, but doesn't draw at large zooms
svg.selectAll("g.scalable").attr("transform", "translate(" + zoom.translate()[0] + ",0)scale(" + zoom.scale() + ",1)");
//slow, scales elements individually, draws at large zooms
//svg.selectAll("g.scalable").selectAll("*").attr("transform", "translate(" + zoom.translate()[0]+",0)scale(" + zoom.scale() + ",1)");
xAxisSelection.call(xAxis);
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"});
//console.log(zoom.scale());
//optmizedTrack();
if (! zoomOnly){
updateTrack();
}
//addOneTrack(testdata, "HG19", 'bed');
$("#" + divId + " #navigate").val(chrom_curr + ":" + Math.round(xScale.domain()[0]) + "-" + Math.round(xScale.domain()[1]));
};
var updateTrack = function(){
if (isready){
//console.log(trackList);
//setTimeout(testRemove(), 5000);
//testRemove();
var start = (Math.round(xScale.domain()[0])).toString();
var end = (Math.round(xScale.domain()[1])).toString();
// var xScale = d3.scale.linear()
// .domain([-3953, 249241810])
// .range([0,1000]);
var chrom = "chr1";
$.ajax({
url: serviceURL,
type: 'POST',
dataType: "json",
data: {
"getTrackData": "",
"fileHandles": [trackInfo[0].fileHandle,trackInfo[1].fileHandle,trackInfo[2].fileHandle],
"name": [trackInfo[0].name,trackInfo[1].name,trackInfo[2].name],
"chrom": chrom,
"start": start,
"end": end
}
}).success(function (returnData) {
//console.log(returnData);
var i = getTrackIndexByName("HG19");
trackList[i] = returnData["HG19"][0];
trackList[i]['name'] = "HG19";
trackList[i]['type'] = "bed";
//console.log(trackList);
addBEDTrack(returnData["HG19"][0], "HG19",returnData["HG19"][1]);
var i = getTrackIndexByName("Tile2 Content Snp");
trackList[i] = returnData["Tile2 Content Snp"];
trackList[i]['name'] = "Tile2 Content Snp";
trackList[i]['type'] = "bed";
//console.log(trackList);
addBEDTrack(returnData["Tile2 Content Snp"], "Tile2 Content Snp");
//console.log(trackList);
var i = getTrackIndexByName("cpg");
trackList[i] = returnData["cpg"];
trackList[i]['name'] = "cpg";
trackList[i]['type'] = "cpg";
//console.log(trackList);
addCpgTrack(returnData["cpg"], "cpg");
zoomOnly = true;
zoomed();
zoomOnly = false;
}).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
}
}
var testRemove = function(){
removeTrack("HG191");
reorderTracks();
//console.log(trackList);
}
var panLimit = function () {
var divisor = (width) / ((xScale.domain()[1] - xScale.domain()[0]) * zoom.scale());
minX = -(((xScale.domain()[0] - xScale.domain()[1]) * zoom.scale()) + (panExtent[1] - (panExtent[1] - (width / divisor)))),
maxX = -(((xScale.domain()[0] - xScale.domain()[1])) + (panExtent[1] - panExtent[0])) * divisor * zoom.scale();
tx = xScale.domain()[0] < panExtent[0] ?
minX :
xScale.domain()[1] > panExtent[1] ?
maxX :
zoom.translate()[0];
return tx;
}
this.navigate = function (chrom, chrom_start, chrom_end) {
graph(chrom, chrom_start, chrom_end);
};
var setBounds = function (min, max) {
//console.log(Number(min) + " "+ Number(max));
var xMin = Number(min) > panExtent[0] ? Number(min) : panExtent[0];
var xMax = Number(max) < panExtent[1] ? Number(max) : panExtent[1];
//console.log(xMin + " "+ xMax);
var initialZoom = 10000 //defines what will be considered a zoom scale of 1
var range = (panExtent[1] - panExtent[0]) / initialZoom
xScale.domain([panExtent[0], panExtent[0] + range])
.range([0, width]);
zoom.scaleExtent([1 / initialZoom, (panExtent[1] - panExtent[0]) / 50 / initialZoom]);
zoom.x(xScale).on("zoom", zoomed);
svg.call(zoom).on("dblclick.zoom", null);
var scale = (panExtent[1] - panExtent[0]) / (xMax - xMin) / initialZoom;
zoom.scale(scale);
//translates scale with regards to the middle of xMin and xMax
var divisor = (width) / ((xScale.domain()[1] - xScale.domain()[0]) * scale);
var minX = -(((xScale.domain()[0] - xScale.domain()[1]) * scale) + (panExtent[1] - (panExtent[1] - (width / divisor))));
var maxX = -(((xScale.domain()[0] - xScale.domain()[1])) + (panExtent[1] - panExtent[0])) * divisor * scale;
var midScale = d3.scale.linear()
.domain([panExtent[0] + (xMax - xMin) / 2, panExtent[1] - (xMax - xMin) / 2])
.range([minX, maxX]);
var zoomWidth = midScale((xMax + xMin) / 2);
zoom.translate([zoomWidth, 0])
.scale(scale);
zoomed();
// minNumber.property("value", xMin);
// maxNumber.property("value", xMax);
}
var setPanExtent = function (min, max) {
var mins = [];
var maxs = [];
if (min != null && max != null)
{
mins.push(Number(min));
maxs.push(Number(max));
}
for (var i in trackList) {
mins.push(d3.min(trackList[i], function (d) {
return Number(d[indexArray.start])
}));
maxs.push(d3.max(trackList[i], function (d) {
return Number(d[indexArray.end])
}));
}
min = d3.min(mins);
max = d3.max(maxs);
panExtent[0] = isNaN(min) ? 0 : min;
panExtent[1] = isNaN(max) ? width : max;
var distance = (panExtent[1] - panExtent[0]) / 10000
/*xScale.domain([0,distance])
.range([0,width]);*/
fullXScale = d3.scale.linear()
.domain([panExtent[0], panExtent[0] + distance])
.range([0, width]);
}
var graph = function (chromosome, min, max) {
var self = this;
chrom_curr = chromosome;
if (min == null || max == null) {
setBounds(panExtent[0], panExtent[1]);
}
else {
setBounds(Number(min), Number(max));
}
//console.log(trackList);
for (var i in trackList) {
addOneTrack(trackList[i], trackList[i]['name'], trackList[i]['type'], i);
}
//addOneTrack(trackList[2], trackList[2]['name'], trackList[2]['type'], 2);
}
var addOneTrack = function (data, name, type, i) {
i = Number(i);
var trackIndex;
if (!isNaN(i)) {
trackIndex = i;
} else {
trackIndex = trackList.length;
}
//check if min and max of whole graph needs to be readjusted
var min = d3.min(data, function (d) {
return Number(d[indexArray.start])
});
var max = d3.max(data, function (d) {
return Number(d[indexArray.start])
});
if (min < panExtent[0] || max > panExtent[1])
{
setPanExtent(min, max);
//console.log(trackList);
graph(chrom_curr);
}
var thisData = data.filter(function (d) {
return (d[indexArray.chr] === chrom_curr);
});
//console.log(thisData);
var trackCount = trackIndex + 1;
//name of track
name = name || "track-" + (trackIndex + 1);
if (type == 'cpg') {
initTrack(name);
addCpgTrack(thisData, name);
data['type'] = 'cpg';
} else {
// if (type == 'bed') {
initTrack(name);
addBEDTrack(thisData, name);
data['type'] = 'bed';
}
data['name'] = name;
clipPath.attr("height", Number(svg.attr("height")));
zoomed();
return data;
}
var reorderTracks = function () {
svg.attr("height", height + 2 * margin + trackList.length * (trackHeight + bufferSpace));
for (var i in trackList) {
graphRegion.selectAll("g").data([trackList[i]['name']], function (d) {
return d;
})
.attr("transform", "translate(" + 0 + "," + (margin + bufferSpace + i * (trackHeight + bufferSpace)) + ")");
}
}
var initTrack = function (name) {
graphRegion.selectAll("g").data([name], function (d) {
return d;
}).enter().append("g");
var trackGroup = graphRegion.selectAll("g").data([name], function (d) {
return d;
})
//.attr("transform", "translate(" + 0 + "," + thisY + ")");
//Just a line
trackGroup.selectAll("line").data([name], function (d) {
return d;
}).enter().append("line")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", width)
.attr("y2", 0)
.style("stroke", "blue")
.style("stroke-opacity" , 0.5);
trackGroup.selectAll("text").data([name], function (d) {
return d;
}).enter().append("text")
.attr("x", 0)
.attr("y", -trackHeight / 2 - bufferSpace / 2)
.attr("font-family", "sans-serif")
.attr("font-size", "12px")
.attr("fill", "red")
.text(name);
/* if (trackGroup.select("rect.remove").empty())
{
trackGroup.append("rect")
.attr("height", 10)
.attr("width", 10)
.attr("x", width + 10)
.attr("y", -5)
.attr("class", "remove")
.on('click', function(){removeTrack(name);});
}
if (trackGroup.select("rect.export").empty())
{
trackGroup.append("rect")
.attr("height", 10)
.attr("width", 10)
.attr("x", width + 30)
.attr("y", -5)
.attr("class", "export")
.on('click', function(){exportTrack(name);});
}*/
if (trackGroup.select(".checkbox").empty())
{
trackGroup.append("foreignObject")
.attr("width", 50)
.attr("height", 20)
.attr("x", width)
.attr("y", -10)
.attr("class", "checkbox")
.append("xhtml:div")
.html("<form><input type=checkbox id='check'/></form>")
.on("click", function () {
// console.log("clicked " + d + " -- " + i);
// console.log(trackGroup.select("#check").property('checked'));
xAxisSelection.call(xAxis);//I have no idea why it won't redraw the checkbox unless I call this
});
}
if (trackGroup.select("path.up").empty())
{
trackGroup.append("path")
.attr("transform", function (d) {
return "translate(" + -20 + "," + -10 + ")"
})
.attr("d", d3.svg.symbol().type(["triangle-up"]))
.attr("class", "up")
.on('click', function () {
var i = Number(getTrackIndexByName(name));
if (i > 0)
{
var temp = trackList[i];
trackList[i] = trackList[i - 1];
trackList[i - 1] = temp;
}
reorderTracks();
});
}
if (trackGroup.select("path.down").empty())
{
trackGroup.append("path")
.attr("transform", function (d) {
return "translate(" + -20 + "," + 10 + ")"
})
.attr("d", d3.svg.symbol().type(["triangle-down"]))
.attr("class", "down")
.on('click', function () {
var i = Number(getTrackIndexByName(name));
if (i < trackList.length - 1)
{
var temp = trackList[i];
trackList[i] = trackList[i + 1];
trackList[i + 1] = temp;
}
reorderTracks();
});
}
/*if (trackGroup.select("rect.drag").empty())
{
var drag = d3.behavior.drag()
//.origin(function() { return {x: 0, y: d3.transform(trackGroup.attr("transform")).translate[1] }})
.on("drag", function(){
trackGroup = graphRegion.selectAll("g").data([name], function(d){return d;})
.attr("transform", "translate(" + 0 + "," + Math.max(margin + trackHeight/2 - bufferSpace/2, Math.min(svg.attr("height") - 2* margin, d3.transform(trackGroup.attr("transform")).translate[1] + d3.event.y)) + ")");
//console.log(thisY + " " +d3.event.y);
});
trackGroup.append("rect")
.attr("height", trackHeight)
.attr("width", 10)
.attr("x", -20)
.attr("y", -trackHeight/2)
.attr("class", "drag")
.call(drag);
}*/
if (trackGroup.select("g.scalable").empty())
{
trackGroup.append("g")
.attr("clip-path", "url(#clip)")
.append("g")
.attr("class", "scalable");
}
}
var addCpgTrack = function (data, name) {
var trackScalableGroup = graphRegion.selectAll("g").data([name], function (d) {
return d;
}).select("g.scalable");
trackScalableGroup.selectAll("rect")
.data(data, function (d) {
return d;
})
.exit()
.remove();
trackScalableGroup.selectAll("rect")
.data(data, function (d) {
return d;
})
.enter()
.append("rect");
trackScalableGroup.selectAll("rect")
.style("fill-opacity", ".4")
.style("stroke", function (d) {
var type = d[indexArray.type];
return type == "cpg" ? "red" : type == "shore" ? "green" : "yellow"
})
.style("fill", function (d) {
var type = d[indexArray.type];
return type == "cpg" ? "red" : type == "shore" ? "green" : "yellow"
})
.style("vector-effect", "non-scaling-stroke")
//.attr("class", "scalable")
.attr("height", function (d) {
var type = d[indexArray.type];
return type == "cpg" ? 40 : type == "shore" ? 20 : 15
})
.attr("width", function (d) {
return fullXScale(d[indexArray.end]) - fullXScale(d[indexArray.start])
})
.attr("x", function (d) {
return fullXScale(d[indexArray.start])
})
.attr("y", function (d) {
var type = d[indexArray.type];
var offset = type == "cpg" ? -20 : type == "shore" ? -10 : -7.5;
return offset;//height / 2 + margin + offset
});
/*if(trackScalableGroup.select("rect").empty())
{
trackScalableGroup.append("rect")
.style("fill-opacity", ".4")
.style("stroke", "red")
.style("fill", "red")
.style("vector-effect", "non-scaling-stroke")
.attr("height", 40)
.attr("width", fullXScale(2000000) - fullXScale(1000000))
.attr("x", fullXScale(1000000))
.attr("y", height / 2 + margin);
}*/
$(trackScalableGroup.selectAll('*')[0]).tipsy({
gravity: 'n',
html: true,
follow: 'x',
title: function () {
var d = this.__data__;
var name = (d.length > indexArray.name) ? d[indexArray.name] : '';
return name + " (" + d[indexArray.chr] + " : " + d[indexArray.start] + " - " + d[indexArray.end] + ")";
}
});
}
var addBEDTrack = function (data, name, exons) {
testdata = data;
//console.log(data);
/**
* @author Pujan Joshi
* @since April 16, 2015
*
* if data is empty, we do not need to proceed. Trying to check for
* some records in empty array was causing error in this method.
*
*/
//console.log(data);
//console.log(name);
if (data.length === 0) {
return;
}
var trackHeight = 10;
var trackScalableGroup = graphRegion.selectAll("g").data([name], function (d) {
return d;
}).select("g.scalable");
//console.log(data[142]);
trackScalableGroup.selectAll("rect")
.data(data, function (d) {
return d;
})
.exit()
.remove();
trackScalableGroup.selectAll("rect")
.data(data, function (d) {
return d;
})
.enter()
.append("rect");
// console.log(data[1]);
var tracks = trackScalableGroup.selectAll("rect")
.data(data, function (d) {
return d;
})
.attr("x", function (d) {
return fullXScale(d[indexArray.start]);
})
.attr("y", function (d) {
return d[indexArray.score] > 0 ? -10 : d[indexArray.score] < 0 ? 0 : -5;
})
.attr("height", 10)
.attr("width", function (d) {
return fullXScale(d[indexArray.end]) - fullXScale(d[indexArray.start]);
})
.style("fill-opacity", "1")
.style("stroke", function (d) {
return d[indexArray.score] > 0 ? "red" : d[indexArray.score] < 0 ? "green" : "grey";
})
.style("fill", function (d) {
return d[indexArray.score] > 0 ? "red" : d[indexArray.score] < 0 ? "green" : "grey";
})
.style("vector-effect", "non-scaling-stroke")
.attr("class", "scalable")
/*.attr("x1", function (d) {
return fullXScale(d[indexArray.start]);
})
.attr("y1", function (d) {
return 0;
})
.attr("x2", function (d) {
return fullXScale(d[indexArray.end]);
})
.attr("y2", function (d) {
return 0;
})
.style("stroke", "black")
.style("stroke-width", "2px")
.attr("class", "scalable")*/
if (exons)
{
//console.log(exons[1]);
trackScalableGroup.selectAll("rect")
.data(data, function (d) {
return d;
})
.exit()
.remove();
trackScalableGroup.selectAll("rect")
.data(exons, function (d) {
return d;
})
.enter()
.append("rect");
trackScalableGroup.selectAll("rect")
.data(exons, function (d) {
return d;
})
.attr("x", function (d) {
return fullXScale(d[0]);
})
.attr("y", -10)
.attr("height", 20)
.attr("width", function (d) {
return fullXScale(d[1]) - fullXScale(d[0]);
})
.style("fill-opacity", ".8")
.style("stroke", "black")
.style("fill", "black")
.style("vector-effect", "non-scaling-stroke")
.attr("class", "scalable")
}
// //addHeightTrack(thisData, name);
// $(trackScalableGroup.selectAll('*')[0]).tipsy({
// gravity: 'n',
// html: true,
// follow: 'x',
// title: function () {
// var d = this.__data__;
// var name = (d.length > indexArray.name) ? d[indexArray.name] : '';
// return name + " (" + d[indexArray.chr] + " : " + d[indexArray.start] + " - " + d[indexArray.end] + ")";
// }
// });
}
/* var addHeightTrack = function (data, name) {
var bufferSpace = 10;
var trackHeight = 100;
var thisY = Number(svg.attr("height")) - margin + trackHeight / 2 + bufferSpace;
svg.attr("height", Number(svg.attr("height")) + trackHeight + bufferSpace);
var yScale = d3.scale.linear();
var yMin = d3.min(data, function (d) {
return isNaN(d[indexArray.score]) ? 0 : Number(d[indexArray.score])
}) - 1;
var yMax = d3.max(data, function (d) {
return isNaN(d[indexArray.score]) ? 0 : Number(d[indexArray.score])
}) + 1;
yScale.domain([yMin, yMax])
.range([thisY + trackHeight / 2, thisY - trackHeight / 2]);
var trackGroup = svg.select("g." + name);
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
var yAxisSelection = trackGroup.append("g")
.call(yAxis)
.attr("class", "axis " + name)
.attr("transform", "translate(" + margin + "," + 0 + ")");
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 trackScalableGroup = trackGroup.select("g.scalable");
if (trackScalableGroup.select("g.height").empty())
{
trackScalableGroup.append("g")
.attr("class", "height")
}
var trackHeightGroup = svg.select("g.height");
var lines = data.filter(function (d) {
return d[indexArray.score] == "";
});
var rects = data.filter(function (d) {
return !isNaN(d[indexArray.score]) && d[indexArray.score] != "";
});
trackHeightGroup.selectAll("rect")
.data(rects, function (d) {
return d;
})
.exit()
.remove();
trackHeightGroup.selectAll("rect")
.data(rects, function (d) {
return d;
})
.enter()
.append("rect");
trackHeightGroup.selectAll("rect")
.data(rects, function (d) {
return d;
})
.attr("x", function (d) {
return fullXScale(Number(d[indexArray.start]));
})
.attr("y", function (d) {
return d < 0 ? yScale(0) : yScale(d[indexArray.score]);
})
.attr("height", function (d) {
return Math.abs(yScale(d[indexArray.score]) - yScale(0));
})
.attr("width", function (d) {
return fullXScale(Number(d[indexArray.end])) - fullXScale(Number(d[indexArray.start]));
})
.style("fill-opacity", ".8")
.style("stroke", "gray")
.style("fill", "gray")
trackHeightGroup.selectAll("line")
.data(lines, function (d) {
return d;
})
.exit()
.remove();
trackHeightGroup.selectAll("line")
.data(lines, function (d) {
return d;
})
.enter()
.append("line");
trackHeightGroup.selectAll("line")
.data(lines, function (d) {
return d;
})
.attr("x1", function (d) {
return fullXScale(d[indexArray.start]);
})
.attr("y1", yScale(0))
.attr("x2", function (d) {
return fullXScale(d[indexArray.end]);
})
.attr("y2", yScale(0))
.style("stroke", "black")
.style("stroke-width", "2px")
}*/
this.addTrackFromDatabase = function(){
//console.log(trackList);
//setTimeout(testRemove(), 5000);
//testRemove();
// var xScale = d3.scale.linear()
// .domain([-3953, 249241810])
// .range([0,1000]);
var chrom = "chr1";
$.ajax({
url: serviceURL,
type: 'POST',
dataType: "json",
data: {
"getStartEndTrackData": "",
"fileHandles": [trackInfo[0].fileHandle,trackInfo[1].fileHandle,trackInfo[2].fileHandle],
"name": [trackInfo[0].name, trackInfo[1].name,trackInfo[2].name],
"chrom": chrom
}
}).success(function (returnData) {
//console.log(returnData);
thisObj.addTrack(returnData[0], "HG19", "bed");
thisObj.addTrack(returnData[1], "Tile2 Content Snp", "bed");
thisObj.addTrack(returnData[2], "cpg", "cpg");
isready = true;
updateTrack();
}).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
}
this.addTrack = function (data, name, type) {
// data['name'] = name;
if(data[0][0] != "chrom")
{
data.unshift(["chrom", "chrom_start", "chrom_end", "name", "score", "strand"])
}
data = addOneTrack(data, name, type);
trackList.push(data);
reorderTracks();
updateAllTracksSelectBoxes();
}
this.addTrackFile = function (dataFile, name, type, header) {
$.get(dataFile, function (data) {
var dataRows = thisObj.parseTrackFile(data, header);
//console.log(dataRows);
//testdata = dataRows;
thisObj.addTrack(dataRows, name, type);
});
}
this.setData = function (data) {
genomeData = data;
graph(chromosomes[0]);
}
this.getData = function () {
return genomeData;
}
/*var submitFile = function () {
genomeData = [];
chromosomes = [];
var file_dir = "./saved-data/";
file_dir = "../../../saved-data/";
var cpg = file_dir + "./CpG_site_hg19.txt";
var shoer = file_dir + "./shoer_hg19.txt";
var shelve = file_dir + "./shelve_hg19.txt";
//Will read the 3 files and place all data into genomeData
//as objects with attributes 'chromosome', 'start', 'end', 'type'
$.get(cpg, 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)
{
chromosomes.push(value[0]);
currentChromosome = value[0];
}
});
cpgData = cpgData.map(function (data) {
// return {"chromosome": data[0], "start": data[1], "end": data[2], "type": "cpg"}
return [data[0], data[1], data[2], "cpg"];
});
genomeData = genomeData.concat(cpgData);
});
$.get(shoer, 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([value[0], value[1], value[2], "shore"]);
shoreData.push([value[0], value[3], value[4], "shore"]);
// shoreData.push({"chromosome": value[0], "start": value[3], "end": value[4], "type": "shore"});
});
genomeData = genomeData.concat(shoreData);
});
$.get(shelve, 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([value[0], value[1], value[2], "shelve"]);
// shelveData.push({"chromosome": value[0], "start": value[1], "end": value[2], "type": "shelve"});
shelveData.push([value[0], value[3], value[4], "shelve"]);
// shelveData.push({"chromosome": value[0], "start": value[3], "end": value[4], "type": "shelve"});
});
genomeData = genomeData.concat(shelveData);
graph(chromosomes[0]);
});
}
d3.select("#" + id + " #submit").on("click", submitFile.bind(this));
// submitFile();*/
this.loadCPGFiles = function (cpg, shoer, shelf) {
genomeData = [];
chromosomes = [];
//Will read the 3 files and place all data into genomeData
//as objects with attributes 'chromosome', 'start', 'end', 'type'
$.get(cpg, 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)
{
chromosomes.push(value[0]);
currentChromosome = value[0];
}
});
cpgData = cpgData.map(function (data) {
return [data[0], data[1], data[2], "cpg"];
});
genomeData = genomeData.concat(cpgData);
});
$.get(shoer, 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([value[0], value[1], value[2], "shore"]);
shoreData.push([value[0], value[3], value[4], "shore"]);
// shoreData.push({"chromosome": value[0], "start": value[3], "end": value[4], "type": "shore"});
});
genomeData = genomeData.concat(shoreData);
});
$.get(shelf, 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([value[0], value[1], value[2], "shelve"]);
// shelveData.push({"chromosome": value[0], "start": value[1], "end": value[2], "type": "shelve"});
shelveData.push([value[0], value[3], value[4], "shelve"]);
// shelveData.push({"chromosome": value[0], "start": value[3], "end": value[4], "type": "shelve"});
});
genomeData = genomeData.concat(shelveData);
thisObj.addTrack(genomeData, "cpg", 'cpg');
});
}
this.parseTrackFile = function (data, header) {
var delimeter = "\t";
var thisData = new Array();
var txtContent = data.split(/\r\n|\r|\n/g);
var startRow = 0;
if (header) {
startRow = 1;
}
for (var i = startRow; i < txtContent.length; i++) {
var thisRow = txtContent[i].split(delimeter);
var thisObject = {};
thisObject = thisRow;
if (thisRow[0].indexOf("##") === 0) {
continue;
}
thisData.push(thisObject);
}
return thisData;
};
// this.makeFormForColocalization = function () {
// var track1Select = "<br>track1 <select name='track1' id='track1'>";
// for (var i in trackList) {
// var thisTrack = trackList[i];
// var text = thisTrack['name'];
// var value = thisTrack['name'];
// track1Select += "<option value='" + value + "'>" + text + "</option>";
// }
// track1Select += "</select>";
//
// var track2Select = "<br>track2 <select name='track2' id='track2'>";
// for (var i in trackList) {
// var thisTrack = trackList[i];
// var text = thisTrack['name'];
// var value = thisTrack['name'];
// track2Select += "<option value='" + value + "'>" + text + "</option>";
// }
// track2Select += "</select>";
//
//
// var colocalizeButton = "<br><input type='button' id='colocalize' value='colocalize'>";
// var form = "<form id='colocalization_form'>" + track1Select + track2Select + colocalizeButton + "</form>";
// $("#" + divId).append(form);
// $("#" + divId + " #colocalize").on("click", colocalize.bind(this));
// };
//
// var colocalize = function () {
// var track1Name = $("#" + divId + " #track1").val();
// var track2Name = $("#" + divId + " #track2").val();
//
// var data1 = this.getTrackByName(track1Name);
// var data2 = this.getTrackByName(track2Name);
//
// var dataToPost1 = [], dataToPost2 = [];
// dataToPost1 = JSON.stringify(data1);
// dataToPost2 = JSON.stringify(data2);
//
// $.ajax({
// url: vqi_url + 'serverside/web/VQService.php?service=coloc-bed-and-bed',
// type: 'POST',
// dataType: "json",
// data: {
// "bed1": dataToPost1,
// "bed2": dataToPost2
// },
// async: false
// }).success(function (data) {
// var data1 = [];
// var data2 = []
// data = data.slice(1);
// for (var i in data) {
// data1.push(data[i].slice(0, 3));
// data2.push(data[i].slice(3));
// }
// thisObj.addTrack(data1);
// thisObj.addTrack(data2);
//
//// objVQIResult.parseSNPAndSNP(data, true);
// }).error(function (req, status, error) {
// $("body").append(status + ": " + error);
// });
//
// };
this.getTrackByName = function (name) {
// console.log(name);
for (var i in trackList) {
var thisTrack = trackList[i];
if (thisTrack['name'] === name) {
return thisTrack;
}
}
};
var getTrackIndexByName = function (name) {
for (var i in trackList) {
var thisTrack = trackList[i];
if (thisTrack['name'] === name) {
return i;
}
}
};
var updateAllTracksSelectBoxes = function () {
var track1Select = $("#" + divId + " #track1");
updateSelectBoxWithTracks(track1Select.get(0));
var track2Select = $("#" + divId + " #track2");
updateSelectBoxWithTracks(track2Select.get(0));
/*var removeTrackSelect = $("#" + divId + " #removeTrack");
updateSelectBoxWithTracks(removeTrackSelect.get(0));
var exportTrackSelect = $("#" + divId + " #exportTrack");
updateSelectBoxWithTracks(exportTrackSelect.get(0));*/
}
var updateSelectBoxWithTracks = function (selectBox) {
selectBox = selectBox;
selectBox.options.length = 0;
var optionIndex = 0;
for (var i in trackList) {
var text = trackList[i]['name'];
var value = text;
selectBox.options[optionIndex++] = new Option(text, value);
}
};
var exportTrackToText = function (data, filename) {
temp = [];
//console.log(data[1].join("\t"));
// var header = ["CHROM", "CHROM_START", "CHROM_END", "NAME", "SCORE", "STRAND"];
// temp.push(header.join("\t"));
for (i in data)
{
if (data[i].constructor === Array)
{
var row = data[i].join("\t");
temp.push(row);
}
}
var txt = temp.join("\r\n");
var blob = new Blob([txt], {type: "text/csv;charset=utf-8"});
saveAs(blob, filename + ".txt");
}
function optmizedTrack(){
var myData;
var start = (Math.round(xScale.domain()[0])).toString();
var end = (Math.round(xScale.domain()[1])).toString();
// var xScale = d3.scale.linear()
// .domain([-3953, 249241810])
// .range([0,1000]);
$.ajax({
url: 'zoomAssist.php',
type: 'POST',
dataType: "json",
data: {
"start": start,
"end": end
}
}).success(function (data) {
myData = data;
//console.log(data);
d3.select(test2).select("svg")
.remove();
var svg2 = d3.select(test2)
.append("svg")
.attr("width", width + 2 * margin)
.attr("height", height + 2 * margin);
var graphR = svg2.append("g").attr("transform", "translate(" + margin + "," + margin + ")");
var tracks = graphR.selectAll("rect")
.data(myData)
.enter()
.append("rect")
.attr("fill", "gray")
.attr("x", function (d) {
return xScale(d.start);
})
.attr("y", 5)
.attr("height", 10)
.attr("width", function (d) {
// if (xScale(d.end) - xScale(d.start) < 1){
// return 1;
// }
// else return xScale(d.end) - xScale(d.start);
return Math.ceil(xScale(d.end) - xScale(d.start));
});
}).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
}
}