Last active
August 29, 2015 14:15
-
-
Save florin-chelaru/160e8b84795603961b9f to your computer and use it in GitHub Desktop.
My Track with Negative Values (Epiviz 3)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
epiviz.Config.SETTINGS.chartTypes.push('epiviz.plugins.charts.MyTrackType'); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by Florin Chelaru ( florinc [at] umd [dot] edu ) | |
* Date: 4/17/14 | |
* Time: 7:13 PM | |
*/ | |
goog.provide('epiviz.plugins.charts.MyTrackType'); | |
/** | |
* @param {epiviz.Config} config | |
* @extends {epiviz.ui.charts.TrackType} | |
* @constructor | |
*/ | |
epiviz.plugins.charts.MyTrackType = function(config) { | |
// Call superclass constructor | |
epiviz.ui.charts.TrackType.call(this, config); | |
}; | |
/* | |
* Copy methods from upper class | |
*/ | |
epiviz.plugins.charts.MyTrackType.prototype = epiviz.utils.mapCopy(epiviz.ui.charts.TrackType.prototype); | |
epiviz.plugins.charts.MyTrackType.constructor = epiviz.plugins.charts.MyTrackType; | |
/** | |
* @param {string} id | |
* @param {jQuery} container The div where the chart will be drawn | |
* @param {epiviz.ui.charts.VisualizationProperties} properties | |
* @returns {epiviz.plugins.charts.MyTrack} | |
*/ | |
epiviz.plugins.charts.MyTrackType.prototype.createNew = function(id, container, properties) { | |
return new epiviz.plugins.charts.MyTrack(id, container, properties); | |
}; | |
/** | |
* @returns {string} | |
*/ | |
epiviz.plugins.charts.MyTrackType.prototype.typeName = function() { | |
return 'epiviz.plugins.charts.MyTrack'; | |
}; | |
/** | |
* @returns {string} | |
*/ | |
epiviz.plugins.charts.MyTrackType.prototype.chartName = function() { | |
return 'My Track'; | |
}; | |
/** | |
* @returns {string} | |
*/ | |
epiviz.plugins.charts.MyTrackType.prototype.chartHtmlAttributeName = function() { | |
return 'mytrack'; | |
}; | |
/** | |
* @returns {function(epiviz.measurements.Measurement): boolean} | |
*/ | |
epiviz.plugins.charts.MyTrackType.prototype.measurementsFilter = function() { return function(m) { return m.type() == epiviz.measurements.Measurement.Type.FEATURE; }; }; | |
epiviz.plugins.charts.MyTrackType.prototype.customSettingsDefs = function() { | |
return epiviz.ui.charts.TrackType.prototype.customSettingsDefs.call(this).concat([ | |
new epiviz.ui.charts.CustomSetting( | |
'base-at-zero', | |
epiviz.ui.charts.CustomSetting.Type.BOOLEAN, | |
false, | |
'Base at zero') | |
]); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by Florin Chelaru ( florinc [at] umd [dot] edu ) | |
* Date: 4/17/14 | |
* Time: 6:03 PM | |
*/ | |
goog.provide('epiviz.plugins.charts.MyTrack'); | |
/** | |
* @param id | |
* @param {jQuery} container | |
* @param {epiviz.ui.charts.VisualizationProperties} properties | |
* @extends {epiviz.ui.charts.Track} | |
* @constructor | |
*/ | |
epiviz.plugins.charts.MyTrack = function(id, container, properties) { | |
// Call superclass constructor | |
epiviz.ui.charts.Track.call(this, id, container, properties); | |
this._initialize(); | |
}; | |
/* | |
* Copy methods from upper class | |
*/ | |
epiviz.plugins.charts.MyTrack.prototype = epiviz.utils.mapCopy(epiviz.ui.charts.Track.prototype); | |
epiviz.plugins.charts.MyTrack.constructor = epiviz.plugins.charts.MyTrack; | |
/** | |
* @param {epiviz.datatypes.GenomicRange} [range] | |
* @param {epiviz.datatypes.GenomicData} [data] | |
* @param {number} [slide] | |
* @param {number} [zoom] | |
* @returns {Array.<epiviz.ui.charts.ChartObject>} The objects drawn | |
*/ | |
epiviz.plugins.charts.MyTrack.prototype.draw = function(range, data, slide, zoom) { | |
epiviz.ui.charts.Track.prototype.draw.call(this, range, data, slide, zoom); | |
// If data is defined, then the base class sets this._lastData to data. | |
// If it isn't, then we'll use the data from the last draw call. | |
// Same with this._lastRange and range. | |
data = this._lastData; | |
range = this._lastRange; | |
this._svg.selectAll('.midline').remove(); | |
var baseAtZero = this.customSettingsValues()['base-at-zero']; | |
// If data is not defined, there is nothing to draw | |
if (!data || !range) { return []; } | |
// Using D3, compute a function that maps base-pair locations to chart pixel coordinates | |
var xScale = d3.scale.linear() | |
.domain([range.start(), range.end()]) | |
.range([0, this.width() - this.margins().left() - this.margins().right()]); | |
// Compute the minimum maximum values of values to be plotted on the Y axis: | |
// Iterate throught all measurements that the chart is supposed to draw and find | |
// default minimum and maximum values. | |
var minY, maxY; | |
data.measurements().forEach(function(m) { | |
if (minY == undefined || m.minValue() < minY) { | |
minY = m.minValue(); | |
} | |
if (maxY == undefined || m.maxValue() > maxY) { | |
maxY = m.maxValue(); | |
} | |
}); | |
// Now create a function that maps measurement values to chart pixel coordinates | |
var yScale = d3.scale.linear() | |
.domain([minY, maxY]) | |
.range([this.height() - this.margins().top() - this.margins().bottom(), 0]); | |
if (baseAtZero) { | |
this._svg.append('line') | |
.attr('class', 'midline') | |
.attr('x1', this.margins().left()) | |
.attr('x2', this.width() - this.margins().right()) | |
.attr('y1', yScale(0) + this.margins().top()) | |
.attr('y2', yScale(0) + this.margins().top()) | |
.style('stroke', '#444444') | |
.style('shape-rendering', 'crispEdges'); | |
} | |
// Draw x and y axes | |
var xTicks = 10, yTicks = 5; | |
this._clearAxes(); | |
this._drawAxes(xScale, yScale, xTicks, yTicks); | |
// Create an array of items to be drawn | |
/** @type {Array.<epiviz.ui.charts.ChartObject>} */ | |
var items = []; | |
data.foreach(function(m, dataSeries, i) { | |
for (var j = 0; j < dataSeries.size(); ++j) { | |
/** @type {epiviz.datatypes.GenomicData.ValueItem} */ | |
var valueItem = dataSeries.get(j); | |
// Check that the current item overlaps the requested draw range; if not, skip it. | |
if (valueItem.rowItem.start() > range.end() || valueItem.rowItem.end() < range.start()) { continue; } | |
items.push(new epiviz.ui.charts.ChartObject( | |
sprintf('item-%s-%s', i, valueItem.globalIndex), // an id that uniquely identifies this object | |
valueItem.rowItem.start(), // start location of current item | |
valueItem.rowItem.end(), // end location of current item | |
[valueItem.value], // the Y value for the current object | |
i, // series index | |
[[valueItem]], | |
[m], // measurement | |
'item' // css class | |
)); | |
} | |
}); | |
var itemsGroup = this._svg.select('.items'); | |
if (itemsGroup.empty()) { | |
itemsGroup = this._svg.append('g').attr('class', 'items'); | |
} | |
itemsGroup.attr('transform', 'translate(' + this.margins().left() + ', ' + this.margins().top() + ')'); | |
var selection = itemsGroup.selectAll('.item') | |
.data(items, function(uiObj) { return uiObj.id; }); | |
var self = this; | |
selection | |
.enter() | |
.append('rect') | |
.attr('class', function(uiObj) { return uiObj.cssClasses; }) | |
.style('fill', function(uiObj) { return self.colors().get(uiObj.seriesIndex); }) | |
.attr('x', function(uiObj) { return xScale(uiObj.start); }) | |
.attr('width', function(uiObj) { return Math.max(2, xScale(uiObj.end + 1) - xScale(uiObj.start)); }) | |
.attr('y', function(uiObj) { | |
var val = uiObj.values[0]; | |
if (!baseAtZero || val >= 0) { | |
return yScale(val); | |
} | |
return yScale(0); | |
}) | |
.attr('height', function(uiObj) { | |
var val = uiObj.values[0]; | |
if (!baseAtZero) { | |
return yScale(minY) - yScale(val); | |
} | |
return Math.abs(yScale(0) - yScale(val)); | |
}) | |
.style('opacity', '0') | |
.on('mouseout', function () { self._unhover.notify(new epiviz.ui.charts.VisEventArgs(self.id())); }) | |
.on('mouseover', function (b) { self._hover.notify(new epiviz.ui.charts.VisEventArgs(self.id(), b)); }) | |
.on('click', function(b) { | |
self._deselect.notify(new epiviz.ui.charts.VisEventArgs(self.id())); | |
self._select.notify(new epiviz.ui.charts.VisEventArgs(self.id(), b)); | |
d3.event.stopPropagation(); | |
}); | |
selection | |
.transition() | |
.duration(500) | |
.style('fill', function(uiObj) { return self.colors().get(uiObj.seriesIndex); }) | |
.attr('x', function(uiObj) { return xScale(uiObj.start); }) | |
.attr('width', function(uiObj) { return Math.max(2, xScale(uiObj.end + 1) - xScale(uiObj.start)); }) | |
.attr('y', function(uiObj) { | |
var val = uiObj.values[0]; | |
if (!baseAtZero || val >= 0) { | |
return yScale(val); | |
} | |
return yScale(0); | |
}) | |
.attr('height', function(uiObj) { | |
var val = uiObj.values[0]; | |
if (!baseAtZero) { | |
return yScale(minY) - yScale(val); | |
} | |
return Math.abs(yScale(0) - yScale(val)); | |
}) | |
.style('opacity', '1'); | |
selection | |
.exit() | |
.transition() | |
.duration(500) | |
.style('opacity', '0') | |
.remove(); | |
return items; | |
}; | |
/** | |
* @returns {string} | |
*/ | |
epiviz.plugins.charts.MyTrack.prototype.chartTypeName = function() { return 'epiviz.plugins.charts.MyTrack'; }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment