ideogram
Version:
Chromosome visualization with D3.js
89 lines (75 loc) • 2.58 kB
JavaScript
/**
* @fileoverview Methods to create and handle a brush on a chromosome.
*
* Ideogram.js enables users to display a box around part of a chromosome
* that represents a "currently selected" region. The user can move this
* box like a sliding window, e.g. by clicking and dragging the mouse.
*
* For background, see:
* https://github.com/d3/d3-brush
*/
import * as d3selection from 'd3-selection';
// See https://github.com/d3/d3/issues/2733
import {event as currentEvent} from 'd3-selection';
import * as d3brush from 'd3-brush';
import {scaleLinear} from 'd3-scale';
import {max} from 'd3-array';
var d3 = Object.assign({}, d3brush, d3selection);
d3.scaleLinear = scaleLinear;
d3.max = max;
/**
* Custom event handler, fired upon dragging sliding window on chromosome
*/
function onBrushMove() {
call(this.onBrushMoveCallback);
}
/**
* Creates a sliding window along a chromosome
*
* @param from Genomic start coordinate, in base pairs
* @param to Genomic end coordinate, in base pairs
*/
function createBrush(from, to) {
var ideo = this,
width = ideo.config.chrWidth + 6.5,
length = ideo.config.chrHeight,
chr = ideo.chromosomesArray[0],
chrLengthBp = chr.bands[chr.bands.length - 1].bp.stop,
x0, x1,
xOffset = this._layout.getMargin().left,
xScale = d3.scaleLinear()
.domain([0, d3.max(chr.bands, function(band) {
return band.bp.stop;
})]).range([xOffset, d3.max(chr.bands, function(band) {
return band.px.stop;
}) + xOffset]);
if (typeof from === 'undefined') {
from = Math.floor(chrLengthBp / 10);
}
if (typeof right === 'undefined') {
to = Math.ceil(from * 2);
}
x0 = ideo.convertBpToPx(chr, from);
x1 = ideo.convertBpToPx(chr, to);
ideo.selectedRegion = {from: from, to: to, extent: (to - from)};
ideo.brush = d3.brushX()
.extent([[xOffset, 0], [length + xOffset, width]])
.on('brush', onBrushMove);
var yTranslate = this._layout.getChromosomeSetYTranslate(0);
var yOffset = yTranslate + (ideo.config.chrWidth - width) / 2;
d3.select(ideo.selector).append('g')
.attr('class', 'brush')
.attr('transform', 'translate(0, ' + yOffset + ')')
.call(ideo.brush)
.call(ideo.brush.move, [x0, x1]);
function onBrushMove() {
var extent = currentEvent.selection.map(xScale.invert),
from = Math.floor(extent[0]),
to = Math.ceil(extent[1]);
ideo.selectedRegion = {from: from, to: to, extent: (to - from)};
if (ideo.onBrushMove) {
ideo.onBrushMoveCallback();
}
}
}
export {onBrushMove, createBrush};