Skip to content
Permalink
04490e92dd
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 1378 lines (1163 sloc) 46.1 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 waitTime;
var loadCount = 0;
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;
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();
}
};
var addRecentTrack = function(){
var track = $("#" + divId + " #RecentTracks").val();
for (i in trackList){
if (trackList[i]['name'] == track){
return;
}
}
for (i in trackInfo){
if (trackInfo[i].name == track){
self.addOneTrackFromDatabase(trackInfo[i].fileHandle,track,trackInfo[i].type);
break;
}
}
}
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);
}).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 form = "<form id='navigation_form'>" + navigateBox + navigateButton + "</form>";
$("#" + divId).append(form);
$("#" + 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);
}).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);
}).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) {
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();
};
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) {
var track = thisObj.getTrackByName(track_name);
exportTrackToText(track, track_name);
}
this.makeUploadForm = function() {
var fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.addEventListener('change', function (e) {
var file = fileInput.files[0];
var textType = /text.*/;
if (file.type.match(textType)) {
var reader = new FileReader();
reader.onload = function (e) {
var Data = reader.result;
uploadFile(Data);
}
reader.readAsText(file);
} else {
alert("File not supported!");
}
});
var f = document.createElement("form");
f.innerHTML = "Add track by uploading file: ";
f.appendChild(fileInput);
$("#" + divId).append(f);
}
this.makeUploadForm();
this.makeRecentTrackForm = function (){
var trackSelect = "Recent tracks: <select name='RecentTracks' id='RecentTracks'>";
for (var i in trackInfo) {
var thisTrack = trackInfo[i];
var text = thisTrack.name;
var value = thisTrack.name;
trackSelect += "<option value='" + value + "'>" + text + "</option>";
}
trackSelect += "</select>";
var addTrackButton = "<input type='button' id='addTrackButton' value='Add Track'>";
var form = "<form id='colocalization_form'>" + trackSelect + addTrackButton + "</form>";
$("#" + divId).append(form);
$("#" + divId + " #addTrackButton").on("click", addRecentTrack.bind(this));
}
this.makeRecentTrackForm();
this.makeSelectionForm = function () {
var removeButton = "<input type='button' id='removetrackbutton' value='Remove Track'>";
var exportButton = "<input type='button' id='exporttrackbutton' value='Export'>";
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")
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.
var zoomed = function () {
zoom.translate([panLimit(), 0]);
//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("rect")
.attr("width", function (d) {
return xScale(d[indexArray.end]) - xScale(d[indexArray.start])
})
.attr("x", function (d) {
return xScale(d[indexArray.start])
});
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"});
if (! zoomOnly){
//updateTrack();
if (waitTime != undefined)
{
clearTimeout(waitTime);
}
waitTime = setTimeout(updateTrack, 100);
}
$("#" + divId + " #navigate").val(chrom_curr + ":" + Math.round(xScale.domain()[0]) + "-" + Math.round(xScale.domain()[1]));
};
var uploadFile = function(data,name,genome){
//var rows = data.split("\n");
headerArray = ["CHROM","CHROM_START","CHROM_END","GENESYMBOL","SCORE","STRAND"];
for (i in headerArray) {
indexArray[headerArray[i]] = i;
}
$.ajax({
url: serviceURL,
type: 'POST',
dataType: "json",
data: {
"header": headerArray,
"indexArray": indexArray,
"upload": data
}
}).success(function (data) {
var CurrentFileHandle = data;
var trackName = CurrentFileHandle;
if(name !== undefined){
var trackName = name+" "+genome;
}
trackInfo.push({name: trackName, type: "bed", fileHandle: CurrentFileHandle});
updateRecentTrackDropDown();
self.addOneTrackFromDatabase(CurrentFileHandle,trackName,"bed");
}).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
}
this.uploadFileFromServer = function(data,name,genome){
var temp = [];
for (i in data) {
temp.push(data[i].join('\t'));
}
trackData = temp.join('\n');
uploadFile(trackData,name,genome);
}
var updateTrack = function(){
if (isready){
var start = (Math.round(xScale.domain()[0])).toString();
var end = (Math.round(xScale.domain()[1])).toString();
var chrom = chrom_curr;
var fileHandles = [];
var name = [];
for (i in trackList) {
for(j in trackInfo){
if(trackInfo[j].name == trackList[i].name){
fileHandles.push(trackInfo[j].fileHandle);
break;
}
}
name.push(trackList[i].name);
}
$.ajax({
url: serviceURL,
type: 'POST',
dataType: "json",
data: {
"getTrackData": "",
"fileHandles": fileHandles,
"name": name,
"chrom": chrom,
"start": start,
"end": end
}
}).success(function (returnData) {
for (i in trackList){
var name = trackList[i]['name'];
var type = trackList[i]['type'];
if(returnData[name] != undefined){
trackList[i] = returnData[name];
trackList[i]['name'] = name;
trackList[i]['type'] = type;
if (name == "HG19"){
addBEDTrack(returnData[name][0], name, returnData[name][1]);
}
else if (name == "cpg"){
addCpgTrack(returnData[name], name);
}
else{
addBEDTrack(returnData[name], name);
}
}
}
zoomOnly = true;
zoomed();
zoomOnly = false;
}).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
}
}
var testRemove = function(){
removeTrack("HG191");
reorderTracks();
}
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) {
var xMin = Number(min) > panExtent[0] ? Number(min) : panExtent[0];
var xMax = Number(max) < panExtent[1] ? Number(max) : panExtent[1];
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);
zoomOnly = true;
zoomed();
zoomOnly = false;
}
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
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));
}
for (var i in trackList) {
addOneTrack(trackList[i], trackList[i]['name'], trackList[i]['type'], i);
}
}
var addOneTrack = function (data, name, type, i) {
//console.log("addonetrack");
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);
graph(chrom_curr);
}
var thisData = data.filter(function (d) {
return (d[indexArray.chr] === chrom_curr);
});
var trackCount = trackIndex + 1;
//name of track
name = name || "track-" + (trackIndex + 1);
if (type == 'cpg') {
initTrack(name);
addCpgTrack(thisData, name);
data['type'] = 'cpg';
} else {
initTrack(name);
addBEDTrack(thisData, name);
data['type'] = 'bed';
}
data['name'] = name;
//console.log(data);
clipPath.attr("height", Number(svg.attr("height")));
zoomOnly = true;
zoomed();
zoomOnly = false;
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;
})
//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(".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 () {
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("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 xScale(d[indexArray.end]) - xScale(d[indexArray.start])
})
.attr("x", function (d) {
return xScale(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
})
.on("mouseenter", function(){console.log("mouseenter")})
.on("mouseleave", function(){console.log("mouseleave")})
addTooltip(trackScalableGroup.selectAll("rect")
.filter(function (d) {
return d[indexArray.type] == "cpg";}), name, "cpg");
addTooltip(trackScalableGroup.selectAll("rect")
.filter(function (d) {
return d[indexArray.type] == "shore";}), name, "shore");
addTooltip(trackScalableGroup.selectAll("rect")
.filter(function (d) {
return d[indexArray.type] == "shelve";}), name, "shelve");
/*$(trackScalableGroup.selectAll("rect")[0]).mousemove(function(event){
$(this).mouseenter();
});*/
}
var addBEDTrack = function (data, name, exons) {
testdata = 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.
*
*/
if (data.length === 0) {
return;
}
var trackHeight = 10;
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");
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")
addTooltip(trackScalableGroup.selectAll("rect")
.data(data, function (d) {
return d;}), name, "gene")
if (exons)
{
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[indexArray.start]);
})
.attr("y", -10)
.attr("height", 20)
.attr("width", function (d) {
return fullXScale(d[indexArray.end]) - fullXScale(d[indexArray.start]);
})
.style("fill-opacity", ".8")
.style("stroke", "black")
.style("fill", "black")
.style("vector-effect", "non-scaling-stroke")
.attr("class", "scalable")
addTooltip(trackScalableGroup.selectAll("rect")
.data(exons, function (d) {
return d;}), name, "exon")
}
}
var addTooltip = function(selection, name, type)
{
var start = (Math.round(xScale.domain()[0])).toString();
var end = (Math.round(xScale.domain()[1])).toString();
var scale = (end - start)/1000;
var fileHandle = '';
if(type == "cpg"){
fileHandle = 'upload1437097194';
}
else if(type == "shelve"){
fileHandle = 'upload1437098473';
}
else if (type == "shore"){
fileHandle = 'upload1437098556';
}
else if (name == "HG19"){
fileHandle = 'upload1436481988';
}
else {
for(i in trackInfo){
if(name == trackInfo[i].name){
fileHandle = trackInfo[i].fileHandle;
break;
}
}
}
selection.each(
function(d){
$(this).qtip({
content: {
text: function(event, api) {
var min,max;
min = d[indexArray.start];
max = d[indexArray.end];
$.ajax({
url: serviceURL,
type: 'POST',
dataType: "json",
data: {
"loadTooltip": "",
"chrom": chrom_curr,
"trackName" : name,
"type" : type,
"min" : min,
"max": max,
'fileHandle': fileHandle
}
})
.then(function(content) {
// Set the tooltip content upon successful retrieval
api.set('content.text', content);
}, function(xhr, status, error) {
// Upon failure... set the tooltip content to the status and error value
api.set('content.text', status + ': ' + error);
});
}
},
position: {
my: 'top center',
at: 'top center',
target: 'mouse',
adjust: {
mouse: true, // Can be omitted (e.g. default behaviour)
y: 10
}
}
})
});
selection.each(function(){
var selected = $(this);
var hoverTimeout = 0;
$(this).mousemove(function(event) {
clearTimeout(hoverTimeout);
hoverTimeout = setTimeout(function(){
var pixelWidth = (xScale.domain()[1] - xScale.domain()[0])/1000
var min = (event.pageX - 59) * pixelWidth + xScale.domain()[0];
var max = (event.pageX - 58) * pixelWidth + xScale.domain()[0];
$.ajax({
url: serviceURL,
type: 'POST',
dataType: "json",
data: {
"loadTooltip": "",
"chrom": chrom_curr,
"trackName" : name,
"type" : type,
"min" : min,
"max": max,
'fileHandle': fileHandle
}
})
.then(function(content) {
// Set the tooltip content upon successful retrieval
selected.qtip('option', 'content.text', content);
}, function(xhr, status, error) {
// Upon failure... set the tooltip content to the status and error value
selected.qtip('option', 'content.text', status + ': ' + error);
});
} , 200);
});
});
}
this.addTrackFromDatabase = function(){
var chrom = "chr1";
var fileHandles = [];
var name = [];
for (i in trackInfo) {
fileHandles.push(trackInfo[i].fileHandle);
name.push(trackInfo[i].name);
}
$.ajax({
url: serviceURL,
type: 'POST',
dataType: "json",
data: {
"getStartEndTrackData": "",
"fileHandles": fileHandles,
"name": name,
"chrom": chrom
}
}).success(function (returnData) {
for (i in trackInfo){
thisObj.addTrack(returnData[i], trackInfo[i].name, trackInfo[i].type);
}
isready = true;
updateTrack();
}).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
}
this.addOneTrackFromDatabase = function(fileHandle,name,type){
var chrom = "chr1";
$.ajax({
url: serviceURL,
type: 'POST',
dataType: "json",
data: {
"getStartEndTrackData": "",
"fileHandles": [fileHandle],
"name": [name],
"chrom": chrom
}
}).success(function (returnData) {
thisObj.addTrack(returnData[0], name, type);
isready = true;
updateTrack();
}).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
}
this.addTrack = function (data, name, type) {
if(data[0][0] != "chrom")
{
data.unshift(["chrom", "chrom_start", "chrom_end", "name", "score", "strand"])
}
data = addOneTrack(data, name, type);
//console.log("addtrack");
trackList.push(data);
reorderTracks();
updateAllTracksSelectBoxes();
}
this.addTrackFile = function (dataFile, name, type, header) {
$.get(dataFile, function (data) {
var dataRows = thisObj.parseTrackFile(data, header);
thisObj.addTrack(dataRows, name, type);
});
}
this.setData = function (data) {
genomeData = data;
graph(chromosomes[0]);
}
this.getData = function () {
return genomeData;
}
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([value[0], value[1], value[2], "shore"]);
shoreData.push([value[0], value[3], value[4], "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([value[0], value[3], value[4], "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.getTrackByName = function (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 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 updateRecentTrackDropDown = function () {
var trackSelect = $("#" + divId + " #RecentTracks");
selectBox = trackSelect.get(0);
selectBox.options.length = 0;
var optionIndex = 0;
for (var i in trackInfo) {
var text = trackInfo[i].name;
var value = text;
selectBox.options[optionIndex++] = new Option(text, value);
}
};
var exportTrackToText = function (data, filename) {
temp = [];
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();
$.ajax({
url: 'zoomAssist.php',
type: 'POST',
dataType: "json",
data: {
"start": start,
"end": end
}
}).success(function (data) {
myData = 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) {
return Math.ceil(xScale(d.end) - xScale(d.start));
});
}).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
}
}