Skip to content
Permalink
Browse files

Shift+Drag to select a region, then click on region to zoom

  • Loading branch information
csw11004 committed Sep 13, 2015
1 parent b175432 commit a4616f0855f5bf6f9beaf7131c92ae60985c753f
Showing with 179 additions and 42 deletions.
  1. +179 −42 VQI_GenomeBrowser.js
@@ -13,6 +13,8 @@ function VQI_GenomeBrowser(id, serviceURL) {

var panExtent = [0, width];

var initialZoom = 1 //defines what will be considered a zoom scale of 1

var trackList = [];

var genomeData = [];
@@ -24,7 +26,6 @@ function VQI_GenomeBrowser(id, serviceURL) {

var testdata;
var isready = false;
var zoomOnly = false;
var waitTime;
var loadCount = 0;

@@ -390,7 +391,7 @@ function VQI_GenomeBrowser(id, serviceURL) {
.append("svg")
.attr("width", width + 2 * margin)
.attr("height", height + 2 * margin)
.style("border", "1px solid black");
.style("border", "1px solid black")

var svg = this.svg;

@@ -400,6 +401,8 @@ function VQI_GenomeBrowser(id, serviceURL) {

var xScale = d3.scale.linear();

var fullXScale = d3.scale.linear();

var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
@@ -412,6 +415,67 @@ function VQI_GenomeBrowser(id, serviceURL) {

var zoom = d3.behavior.zoom();


var rubberbanding = false;
var rubberbandingX;
svg.on("mousedown", function() {
svg.selectAll("rect.selection").remove();
if(d3.event.shiftKey){
d3.event.preventDefault();
zoom.on("zoom",null);
svg.call(zoom);
rubberbanding = true;
var p = d3.mouse(this);
// create rubber band selector

if(p[0] > margin && p[0] < margin + width)
{
svg.append( "rect")
.attr({
class : "selection",
x : p[0],
y : 0,
width : 0,
height : height + 2 * margin + trackList.length * (trackHeight + bufferSpace)
})
.style("fill-opacity", ".2")
.on("mousedown", navigateToRegion);
}
rubberbandingX = p[0];
}
})
.on("mousemove", function() {
// rubber band selector
var s = svg.select("rect.selection");

if(!s.empty() && rubberbanding) {
d3.event.preventDefault();
// get cursor coordinate
var p = d3.mouse(this);
// get rubber band selector coordinate and size
newX = Math.min(Math.max(p[0] , margin), width + margin);
var c = {
x : Math.min(newX, rubberbandingX),
width : Math.abs(newX - rubberbandingX)
};

s.attr(c);
}
})
.on("mouseup", function() {
// remove rubber band selector
zoom.on("zoom",zoomed);
svg.call(zoom).on("dblclick.zoom", null);
rubberbanding = false;

var s = svg.select("rect.selection");
if(!s.empty()){
$("#" + divId + " #navigate").val(chrom_curr + ":"
+ Math.round(xScale.invert(parseInt(s.attr("x"))-margin)) + "-"
+ Math.round(xScale.invert(parseInt(s.attr("x")) + parseInt(s.attr("width")) - margin)));
}
});

var clipPath = graphRegion.append("clipPath")
.attr("id", "clip")
.append("rect")
@@ -421,6 +485,8 @@ function VQI_GenomeBrowser(id, serviceURL) {

var zoomed = function () {

svg.selectAll("rect.selection").remove();

zoom.translate([panLimit(), 0]);

for(i in trackList)
@@ -440,13 +506,12 @@ function VQI_GenomeBrowser(id, serviceURL) {
"font-family": "sans-serif",
"font-size": "11px"});

if (! zoomOnly){
if (waitTime != undefined)
{
clearTimeout(waitTime);
}
waitTime = setTimeout(updateTrack, 100);
}
if (waitTime != undefined)
{
clearTimeout(waitTime);
}
waitTime = setTimeout(updateTrack, 100);

$("#" + divId + " #navigate").val(chrom_curr + ":" + Math.round(xScale.domain()[0]) + "-" + Math.round(xScale.domain()[1]));
};

@@ -521,25 +586,24 @@ function VQI_GenomeBrowser(id, serviceURL) {
};

var setBounds = function (min, max) {
panExtent[0] = 0;
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]);

var prevTranslate = zoom.translate();
var prevScale = zoom.scale();

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);

zoom.scale(scale)

//translates scale with regards to the middle of xMin and xMax
var divisor = (width) / ((xScale.domain()[1] - xScale.domain()[0]) * scale);
@@ -552,12 +616,18 @@ function VQI_GenomeBrowser(id, serviceURL) {

var zoomWidth = midScale((xMax + xMin) / 2);

zoom.translate([zoomWidth, 0])
.scale(scale);
//transitions start from the previous transition, so I make a transition that first zooms
//to the current view in no time, then another transition that zooms to the desired view
svg.transition()
.duration(0)
.call(zoom.translate(prevTranslate).scale(prevScale).event)
.each("end", function(){
svg.transition()
.duration(1000)
.call(zoom.scale(scale).translate([zoomWidth, 0]).event)
})

zoomOnly = true;
zoomed();
zoomOnly = false;
}

var setPanExtent = function (min, max) {
@@ -586,7 +656,11 @@ function VQI_GenomeBrowser(id, serviceURL) {
panExtent[0] = isNaN(min) ? 0 : min;
panExtent[1] = isNaN(max) ? width : max;

var distance = (panExtent[1] - panExtent[0]) / 10000
var distance = (panExtent[1] - panExtent[0]) / initialZoom;

fullXScale = d3.scale.linear()
.domain([panExtent[0], panExtent[0] + distance])
.range([0, width]);
}

var graph = function (chromosome, min, max) {
@@ -647,7 +721,7 @@ function VQI_GenomeBrowser(id, serviceURL) {
var reorderTracks = function () {
svg.attr("height", height + 2 * margin + trackList.length * (trackHeight + bufferSpace));
for (var i in trackList) {
trackList[i].group.attr("transform", "translate(" + 0 + "," + (margin + bufferSpace + i * (trackHeight + bufferSpace)) + ")");
trackList[i].group.transition().attr("transform", "translate(" + 0 + "," + (margin + bufferSpace + i * (trackHeight + bufferSpace)) + ")");
}
}

@@ -1031,9 +1105,19 @@ function VQI_GenomeBrowser(id, serviceURL) {
var shelveFileHandle = tempHandles[1];
var shoreFileHandle = tempHandles[2];
var data;
var redrawCutoff = 1000;

var getScale = function(){
if(zoom.scale() < redrawCutoff)
return fullXScale;
else
return xScale;
}

var drawTrack = function(data)
{
var thisScale = getScale();

trackGroup.selectAll("rect")
.data(data, function (d) {
return d;
@@ -1065,10 +1149,10 @@ function VQI_GenomeBrowser(id, serviceURL) {
return type == "cpg" ? 40 : type == "shore" ? 20 : 15
})
.attr("width", function (d) {
return xScale(d[indexArray.end]) - xScale(d[indexArray.start])
return thisScale(d[indexArray.end]) - thisScale(d[indexArray.start])
})
.attr("x", function (d) {
return xScale(d[indexArray.start])
return thisScale(d[indexArray.start])
})
.attr("y", function (d) {
var type = d[indexArray.type];
@@ -1179,14 +1263,35 @@ function VQI_GenomeBrowser(id, serviceURL) {
});
}

var previousScale = 1;
this.zoomed = function() {
trackGroup.selectAll("rect")
.attr("width", function (d) {
return xScale(d[indexArray.end]) - xScale(d[indexArray.start])
})
.attr("x", function (d) {
return xScale(d[indexArray.start])
});
var thisScale = getScale();
if(zoom.scale() < redrawCutoff)
{
if(previousScale > redrawCutoff)
{
trackGroup.selectAll("rect")
.attr("width", function (d) {
return thisScale(d[indexArray.end]) - thisScale(d[indexArray.start])
})
.attr("x", function (d) {
return thisScale(d[indexArray.start])
});
}
trackGroup.attr("transform", "translate(" + zoom.translate()[0] + ",0)scale(" + zoom.scale() + ",1)");
}
else
{
trackGroup.attr("transform", null);
trackGroup.selectAll("rect")
.attr("width", function (d) {
return thisScale(d[indexArray.end]) - thisScale(d[indexArray.start])
})
.attr("x", function (d) {
return thisScale(d[indexArray.start])
});
}
previousScale = zoom.scale();
}

this.getData = function(){
@@ -1201,13 +1306,23 @@ function VQI_GenomeBrowser(id, serviceURL) {
this.fileHandle = fileHandle;
var tempHandles = fileHandle.split(",");
var data;
var redrawCutoff = 1000;

var getScale = function(){
if(zoom.scale() < redrawCutoff)
return fullXScale;
else
return xScale;
}

var drawTrack = function(data, exons)
{
if (data.length === 0) {
return;
}

var thisScale = getScale();

var trackHeight = 10;

trackGroup.selectAll("rect")
@@ -1229,14 +1344,14 @@ function VQI_GenomeBrowser(id, serviceURL) {
return d;
})
.attr("x", function (d) {
return xScale(d[indexArray.start]);
return thisScale(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 xScale(d[indexArray.end]) - xScale(d[indexArray.start]);
return thisScale(d[indexArray.end]) - thisScale(d[indexArray.start]);
})
.style("fill-opacity", "1")
.style("stroke", function (d) {
@@ -1271,12 +1386,12 @@ function VQI_GenomeBrowser(id, serviceURL) {
return d;
})
.attr("x", function (d) {
return xScale(d[indexArray.start]);
return thisScale(d[indexArray.start]);
})
.attr("y", -10)
.attr("height", 20)
.attr("width", function (d) {
return xScale(d[indexArray.end]) - xScale(d[indexArray.start]);
return thisScale(d[indexArray.end]) - thisScale(d[indexArray.start]);
})
.style("fill-opacity", ".8")
.style("stroke", "black")
@@ -1383,17 +1498,39 @@ function VQI_GenomeBrowser(id, serviceURL) {
}
).error(function (req, status, error) {
$("body").append(status + ": " + error);
});
});
this.zoomed();
}

var previousScale = 1;
this.zoomed = function() {
trackGroup.selectAll("rect")
.attr("width", function (d) {
return xScale(d[indexArray.end]) - xScale(d[indexArray.start])
})
.attr("x", function (d) {
return xScale(d[indexArray.start])
});
var thisScale = getScale();
if(zoom.scale() < redrawCutoff)
{
if(previousScale > redrawCutoff)
{
trackGroup.selectAll("rect")
.attr("width", function (d) {
return thisScale(d[indexArray.end]) - thisScale(d[indexArray.start])
})
.attr("x", function (d) {
return thisScale(d[indexArray.start])
});
}
trackGroup.attr("transform", "translate(" + zoom.translate()[0] + ",0)scale(" + zoom.scale() + ",1)");
}
else
{
trackGroup.attr("transform", null);
trackGroup.selectAll("rect")
.attr("width", function (d) {
return thisScale(d[indexArray.end]) - thisScale(d[indexArray.start])
})
.attr("x", function (d) {
return thisScale(d[indexArray.start])
});
}
previousScale = zoom.scale();
}

this.getData = function(){
@@ -1480,7 +1617,7 @@ function VQI_GenomeBrowser(id, serviceURL) {
this.updateTrack = function(){
if(faFile)
{
if( zoom.scale() >= (panExtent[1] - panExtent[0]) / 100 / 10000)
if( zoom.scale() >= (panExtent[1] - panExtent[0]) / 100/ initialZoom)
{
var offset;
for(var i = 0; i < faiData.length; i++)

0 comments on commit a4616f0

Please sign in to comment.
You can’t perform that action at this time.