mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Charts: Add clustered heatmap
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
define(['plugin/charts/forms/default'], function(config_default) {
|
||||
|
||||
return $.extend(true, {}, config_default, {
|
||||
title : 'Heat map',
|
||||
title : 'Heatmap',
|
||||
category : 'Others',
|
||||
query_limit : 1,
|
||||
query_limit : 1000,
|
||||
library : 'Custom',
|
||||
tag : 'div',
|
||||
keywords : 'small',
|
||||
zoomable : true,
|
||||
columns : {
|
||||
x : {
|
||||
title : 'Column labels',
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
// dependencies
|
||||
define(['plugin/charts/tools'], function(Tools) {
|
||||
|
||||
// widget
|
||||
return Backbone.View.extend({
|
||||
// initialize
|
||||
initialize: function(app, options) {
|
||||
this.app = app;
|
||||
this.chart = options.chart;
|
||||
},
|
||||
|
||||
// render
|
||||
render : function(canvas_id, groups) {
|
||||
// categories
|
||||
this.categories = Tools.makeUniqueCategories(groups);
|
||||
|
||||
// collect parameters
|
||||
this.canvas_id = canvas_id;
|
||||
this.data = groups[0].values;
|
||||
this.color_set = ['#ffffd9','#edf8b1','#c7e9b4','#7fcdbb','#41b6c4','#1d91c0','#225ea8','#253494','#081d58'];
|
||||
|
||||
// get limits
|
||||
this.zMax = d3.max(this.data, function(d) { return d.z; });
|
||||
|
||||
//
|
||||
// domains/scales
|
||||
//
|
||||
this.xScale = d3.scale.linear().domain([0, this.categories.array.x.length]);
|
||||
this.yScale = d3.scale.linear().domain([0, this.categories.array.y.length]);
|
||||
this.zScale = d3.scale.ordinal().domain([0, this.zMax]);
|
||||
|
||||
// create axis
|
||||
this.xAxis = d3.svg.axis().scale(this.xScale).orient('bottom');
|
||||
this.yAxis = d3.svg.axis().scale(this.yScale).orient('left');
|
||||
|
||||
// set ticks
|
||||
this.xAxis.tickValues(d3.range(this.xScale.domain()[0], this.xScale.domain()[1], 1));
|
||||
this.yAxis.tickValues(d3.range(this.yScale.domain()[0], this.yScale.domain()[1], 1));
|
||||
|
||||
// make categories
|
||||
this._makeTickFormat('x');
|
||||
this._makeTickFormat('y');
|
||||
|
||||
// refresh on window resize
|
||||
var self = this;
|
||||
$(window).on('resize', function () {
|
||||
self.redraw();
|
||||
});
|
||||
|
||||
// draw
|
||||
this.redraw();
|
||||
|
||||
// add zoom
|
||||
Tools.addZoom({
|
||||
xAxis : this.xAxis,
|
||||
yAxis : this.yAxis,
|
||||
redraw : function() { self.redraw() },
|
||||
svg : d3.select('#' + this.canvas_id)
|
||||
});
|
||||
|
||||
// return
|
||||
return true;
|
||||
},
|
||||
|
||||
// redraw
|
||||
redraw: function() {
|
||||
// get parameters
|
||||
var chart = this.chart;
|
||||
var data = this.data;
|
||||
var color_set = this.color_set;
|
||||
var self = this;
|
||||
|
||||
// get/reset container
|
||||
var container = $('#' + this.canvas_id);
|
||||
container.empty();
|
||||
|
||||
// set margin and heights
|
||||
var margin = {top: 20, right: 90, bottom: 90, left: 100},
|
||||
width = parseInt(container.width()) - margin.left - margin.right,
|
||||
height = parseInt(container.height()) - margin.top - margin.bottom;
|
||||
|
||||
//
|
||||
// set range
|
||||
//
|
||||
this.xScale.range([0, width]);
|
||||
this.yScale.range([height, 0]);
|
||||
this.zScale.range(color_set);
|
||||
|
||||
//
|
||||
// draw boxes
|
||||
//
|
||||
// get box properties
|
||||
var rowCount = this.yScale.domain()[1] - this.yScale.domain()[0],
|
||||
colCount = this.xScale.domain()[1] - this.xScale.domain()[0],
|
||||
boxWidth = Math.max(1, Math.floor(width / colCount)),
|
||||
boxHeight = Math.max(1, Math.floor(height / rowCount));
|
||||
|
||||
// box location
|
||||
function _locator(d) {
|
||||
return 'translate(' + self.xScale(d.x) + ',' + self.yScale(d.y+1) + ')';
|
||||
};
|
||||
|
||||
// box color
|
||||
function _color (d) {
|
||||
return self.zScale(d.z);
|
||||
};
|
||||
|
||||
//
|
||||
// create svg
|
||||
//
|
||||
var svg = d3.select('#' + this.canvas_id)
|
||||
.append('svg')
|
||||
.attr('width', width + margin.left + margin.right)
|
||||
.attr('height', height + margin.top + margin.bottom)
|
||||
.append('g')
|
||||
.attr('class', 'heatmap')
|
||||
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
||||
|
||||
// set background color
|
||||
var background = svg.append('rect')
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
.attr('fill', '#FFFFF8');
|
||||
|
||||
// clip path
|
||||
var clip = svg.append('clipPath')
|
||||
.attr('id', 'clip')
|
||||
.append('rect')
|
||||
.attr('x', 0)
|
||||
.attr('y', 0)
|
||||
.attr('width', width)
|
||||
.attr('height', height);
|
||||
|
||||
// create chart area
|
||||
var chartBody = svg.append('g')
|
||||
.attr('clip-path', 'url(#clip)');
|
||||
|
||||
// add boxes to chart area
|
||||
var boxes = chartBody.selectAll('g.box-group').data(data, function(d, i) {
|
||||
return d.x + '\0' + d.y;
|
||||
});
|
||||
var gEnter = boxes.enter().append('g')
|
||||
.attr('class', 'box-group');
|
||||
gEnter.append('rect')
|
||||
.attr('class','heat-box')
|
||||
.attr('fill', 'red');
|
||||
boxes.selectAll('rect')
|
||||
.attr('rx', 1)
|
||||
.attr('ry', 1)
|
||||
.attr('fill', _color)
|
||||
.attr('width', boxWidth)
|
||||
.attr('height', boxHeight)
|
||||
.attr('transform', _locator);
|
||||
boxes.exit().remove();
|
||||
|
||||
// draw x axis
|
||||
this.gxAxis = svg.append('g')
|
||||
.attr('class', 'x axis')
|
||||
.style('stroke-width', 1)
|
||||
.attr('transform', 'translate(0,' + height + ')')
|
||||
.call(this.xAxis);
|
||||
|
||||
// draw y axis
|
||||
this.gyAxis = svg.append('g')
|
||||
.attr('class', 'y axis')
|
||||
.style('stroke-width', 1)
|
||||
.call(this.yAxis);
|
||||
|
||||
// fix text
|
||||
var xFontSize = Math.min(boxWidth, 12);
|
||||
this.gxAxis.selectAll('text')
|
||||
.style({'font-size': xFontSize + 'px'})
|
||||
.attr('transform', function(d) {
|
||||
var y = -this.getBBox().height - 10;
|
||||
var x = -xFontSize + boxWidth/2;
|
||||
return 'rotate(-90)translate(' + y + ',' + x + ')';
|
||||
});
|
||||
|
||||
// fix text
|
||||
var yFontSize = Math.min(boxHeight, 12);
|
||||
this.gyAxis.selectAll('text')
|
||||
.style({'font-size': yFontSize + 'px'})
|
||||
.attr('y', -boxHeight/2);
|
||||
},
|
||||
|
||||
// create axes formatting
|
||||
_makeTickFormat: function(id) {
|
||||
var settings = this.chart.settings;
|
||||
var self = this;
|
||||
Tools.makeTickFormat({
|
||||
categories : self.categories.array[id],
|
||||
type : settings.get(id + '_axis_type'),
|
||||
precision : settings.get(id + '_axis_precision'),
|
||||
formatter : function(formatter) {
|
||||
if (formatter) {
|
||||
self[id + 'Axis'].tickFormat(function(value) {
|
||||
return formatter(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// handle error
|
||||
_handleError: function(err) {
|
||||
this.chart.state('failed', err);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
// dependencies
|
||||
define(['plugin/charts/tools'], function(Tools) {
|
||||
define(['plugin/charts/tools', 'plugin/charts/others/heatmap/heatmap-plugin'], function(Tools, HeatMap) {
|
||||
|
||||
// widget
|
||||
return Backbone.View.extend({
|
||||
@@ -14,6 +14,9 @@ return Backbone.View.extend({
|
||||
// backup chart
|
||||
this.chart = chart;
|
||||
|
||||
// create heatmap
|
||||
this.heatmap = new HeatMap(app, { chart : chart });
|
||||
|
||||
// distribute data groups on svgs and handle process
|
||||
var self = this;
|
||||
var plot = Tools.panelHelper({
|
||||
@@ -23,201 +26,9 @@ return Backbone.View.extend({
|
||||
chart : chart,
|
||||
request_dictionary : request_dictionary,
|
||||
render : function(canvas_id, groups) {
|
||||
return self.render(canvas_id, groups)
|
||||
return self.heatmap.render(canvas_id, groups)
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// render
|
||||
render : function(canvas_id, groups) {
|
||||
// categories
|
||||
this.categories = Tools.makeUniqueCategories(groups);
|
||||
|
||||
// collect parameters
|
||||
this.canvas_id = canvas_id;
|
||||
this.data = groups[0].values;
|
||||
this.color_set = ['#ffffd9','#edf8b1','#c7e9b4','#7fcdbb','#41b6c4','#1d91c0','#225ea8','#253494','#081d58'];
|
||||
|
||||
// get limits
|
||||
this.xMax = d3.max(this.data, function(d) { return d.x; });
|
||||
this.yMax = d3.max(this.data, function(d) { return d.y; });
|
||||
this.zMax = d3.max(this.data, function(d) { return d.z; });
|
||||
|
||||
//
|
||||
// domains/scales
|
||||
//
|
||||
this.xScale = d3.scale.linear().domain([0, this.xMax]);
|
||||
this.yScale = d3.scale.linear().domain([0, this.yMax]);
|
||||
this.zScale = d3.scale.ordinal().domain([0, this.zMax]);
|
||||
|
||||
// create axis
|
||||
this.xAxis = d3.svg.axis().scale(this.xScale).orient('bottom');
|
||||
this.yAxis = d3.svg.axis().scale(this.yScale).orient('left');
|
||||
|
||||
// set ticks
|
||||
this.xAxis.tickValues(d3.range(this.xScale.domain()[0], this.xScale.domain()[1], 1));
|
||||
this.yAxis.tickValues(d3.range(this.yScale.domain()[0], this.yScale.domain()[1], 1));
|
||||
|
||||
// make categories
|
||||
this._makeTickFormat('x');
|
||||
this._makeTickFormat('y');
|
||||
|
||||
// refresh on window resize
|
||||
var self = this;
|
||||
$(window).on('resize', function () {
|
||||
self.redraw();
|
||||
});
|
||||
|
||||
// draw
|
||||
this.redraw();
|
||||
|
||||
// add zoom
|
||||
Tools.addZoom({
|
||||
xAxis : this.xAxis,
|
||||
yAxis : this.yAxis,
|
||||
redraw : function() { self.redraw() },
|
||||
svg : d3.select('#' + this.canvas_id),
|
||||
discrete : true
|
||||
});
|
||||
|
||||
// return
|
||||
return true;
|
||||
},
|
||||
|
||||
// redraw
|
||||
redraw: function() {
|
||||
// get parameters
|
||||
var chart = this.options.chart;
|
||||
var type = this.options.type;
|
||||
var data = this.data;
|
||||
var color_set = this.color_set;
|
||||
var self = this;
|
||||
|
||||
// get/reset container
|
||||
var container = $('#' + this.canvas_id);
|
||||
container.empty();
|
||||
|
||||
// set margin and heights
|
||||
var margin = {top: 20, right: 90, bottom: 90, left: 100},
|
||||
width = parseInt(container.width()) - margin.left - margin.right,
|
||||
height = parseInt(container.height()) - margin.top - margin.bottom;
|
||||
|
||||
//
|
||||
// set range
|
||||
//
|
||||
this.xScale.range([0, width]);
|
||||
this.yScale.range([height, 0]);
|
||||
this.zScale.range(color_set);
|
||||
|
||||
//
|
||||
// draw boxes
|
||||
//
|
||||
// get box properties
|
||||
var rowCount = this.yScale.domain()[1] - this.yScale.domain()[0],
|
||||
colCount = this.xScale.domain()[1] - this.xScale.domain()[0],
|
||||
boxWidth = Math.max(1, Math.floor(width / colCount)),
|
||||
boxHeight = Math.max(1, Math.floor(height / rowCount));
|
||||
|
||||
// box location
|
||||
function _locator(d) {
|
||||
return 'translate(' + self.xScale(d.x) + ',' + self.yScale(d.y) + ')';
|
||||
};
|
||||
|
||||
// box color
|
||||
function _color (d) {
|
||||
return self.zScale(d.z);
|
||||
};
|
||||
|
||||
//
|
||||
// create svg
|
||||
//
|
||||
var svg = d3.select('#' + this.canvas_id)
|
||||
.append('svg')
|
||||
.attr('width', width + margin.left + margin.right)
|
||||
.attr('height', height + margin.top + margin.bottom)
|
||||
.append('g')
|
||||
.attr('class', 'heatmap')
|
||||
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
||||
|
||||
// clip path
|
||||
var clip = svg.append('clipPath')
|
||||
.attr('id', 'clip')
|
||||
.append('rect')
|
||||
.attr('x', 0)
|
||||
.attr('y', boxHeight)
|
||||
.attr('width', width)
|
||||
.attr('height', height);
|
||||
|
||||
// create chart area
|
||||
var chartBody = svg.append('g')
|
||||
.attr('clip-path', 'url(#clip)');
|
||||
|
||||
// add boxes to chart area
|
||||
var boxes = chartBody.selectAll('g.box-group').data(data, function(d, i) {
|
||||
return d.x + '\0' + d.y;
|
||||
});
|
||||
var gEnter = boxes.enter().append('g')
|
||||
.attr('class', 'box-group');
|
||||
gEnter.append('rect')
|
||||
.attr('class','heat-box')
|
||||
.attr('fill', 'red');
|
||||
boxes.selectAll('rect')
|
||||
.attr('rx', 2)
|
||||
.attr('ry', 2)
|
||||
.attr('fill', _color)
|
||||
.attr('width', boxWidth)
|
||||
.attr('height', boxHeight)
|
||||
.attr('transform', _locator);
|
||||
boxes.exit().remove();
|
||||
|
||||
// draw x axis
|
||||
this.gxAxis = svg.append('g')
|
||||
.attr('class', 'x axis')
|
||||
.style('stroke-width', 0)
|
||||
.attr('transform', 'translate(0,' + (height + margin.top + boxHeight) + ')')
|
||||
.call(this.xAxis);
|
||||
|
||||
// draw y axis
|
||||
this.gyAxis = svg.append('g')
|
||||
.attr('class', 'y axis')
|
||||
.style('stroke-width', 0)
|
||||
.call(this.yAxis);
|
||||
|
||||
// fix text
|
||||
var xFontSize = Math.min(boxWidth, 12);
|
||||
this.gxAxis.selectAll('text')
|
||||
.style({'font-family': 'Courier New', 'font-size': xFontSize + 'px'})
|
||||
.attr('transform', 'rotate(-90)')
|
||||
.attr('y', (boxWidth-xFontSize)/2);
|
||||
|
||||
// fix text
|
||||
var yFontSize = Math.min(boxHeight, 12);
|
||||
this.gyAxis.selectAll('text')
|
||||
.style({'font-family': 'Courier New', 'font-size': yFontSize + 'px'})
|
||||
.attr('y', -boxHeight/2 + boxHeight);
|
||||
},
|
||||
|
||||
// create axes formatting
|
||||
_makeTickFormat: function(id) {
|
||||
var settings = this.chart.settings;
|
||||
var self = this;
|
||||
Tools.makeTickFormat({
|
||||
categories : self.categories.array[id],
|
||||
type : settings.get(id + '_axis_type'),
|
||||
precision : settings.get(id + '_axis_precision'),
|
||||
formatter : function(formatter) {
|
||||
if (formatter) {
|
||||
self[id + 'Axis'].tickFormat(function(value) {
|
||||
return formatter(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// handle error
|
||||
_handleError: function(chart, err) {
|
||||
chart.state('failed', err);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
define(['plugin/charts/others/heatmap/config'], function(config_default) {
|
||||
|
||||
return $.extend(true, {}, config_default, {
|
||||
title : 'Clustered Heatmap',
|
||||
category : 'Data processing (requires \'charts\' tool from Toolshed)',
|
||||
execute : 'heatmap'
|
||||
});
|
||||
|
||||
});
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,37 @@
|
||||
// dependencies
|
||||
define(['plugin/charts/tools', 'plugin/charts/others/heatmap/heatmap-plugin'], function(Tools, HeatMap) {
|
||||
|
||||
// widget
|
||||
return Backbone.View.extend({
|
||||
// initialize
|
||||
initialize: function(app, options) {
|
||||
this.app = app;
|
||||
this.options = options;
|
||||
},
|
||||
|
||||
// render
|
||||
draw : function(process_id, chart, request_dictionary) {
|
||||
// backup chart
|
||||
this.chart = chart;
|
||||
|
||||
// create heatmap
|
||||
this.heatmap = new HeatMap(app, {
|
||||
chart : chart
|
||||
});
|
||||
|
||||
// distribute data groups on svgs and handle process
|
||||
var self = this;
|
||||
var plot = Tools.panelHelper({
|
||||
app : this.app,
|
||||
canvas_list : this.options.canvas_list,
|
||||
process_id : process_id,
|
||||
chart : chart,
|
||||
request_dictionary : request_dictionary,
|
||||
render : function(canvas_id, groups) {
|
||||
return self.heatmap.render(canvas_id, groups)
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -297,7 +297,7 @@ function makeTickFormat (options) {
|
||||
// add zoom handler
|
||||
function addZoom(options) {
|
||||
// scaleExtent
|
||||
var scaleExtent = 10;
|
||||
var scaleExtent = 100;
|
||||
|
||||
// parameters
|
||||
var yAxis = options.yAxis;
|
||||
@@ -306,7 +306,6 @@ function addZoom(options) {
|
||||
var yDomain = options.yDomain || yAxis.scale().domain;
|
||||
var redraw = options.redraw;
|
||||
var svg = options.svg;
|
||||
var discrete = options.discrete;
|
||||
|
||||
// scales
|
||||
var xScale = xAxis.scale();
|
||||
@@ -325,10 +324,6 @@ function addZoom(options) {
|
||||
|
||||
// fix domain
|
||||
function fixDomain(domain, boundary) {
|
||||
if (discrete) {
|
||||
domain[0] = Math.floor(domain[0]);
|
||||
domain[1] = Math.ceil(domain[1]);
|
||||
}
|
||||
domain[0] = Math.min(Math.max(domain[0], boundary[0]), boundary[1] - boundary[1]/scaleExtent);
|
||||
domain[1] = Math.max(boundary[0] + boundary[1]/scaleExtent, Math.min(domain[1], boundary[1]));
|
||||
return domain;
|
||||
|
||||
@@ -16,7 +16,8 @@ define(['plugin/charts/nvd3/bar/config',
|
||||
'plugin/charts/jqplot/line/config',
|
||||
'plugin/charts/jqplot/scatter/config',
|
||||
'plugin/charts/jqplot/boxplot/config',
|
||||
'plugin/charts/others/heatmap/config'
|
||||
'plugin/charts/others/heatmap/config',
|
||||
'plugin/charts/others/heatmap_cluster/config'
|
||||
], function(nvd3_bar,
|
||||
nvd3_bar_stacked,
|
||||
nvd3_bar_horizontal,
|
||||
@@ -34,7 +35,8 @@ define(['plugin/charts/nvd3/bar/config',
|
||||
jqplot_line,
|
||||
jqplot_scatter,
|
||||
jqplot_boxplot,
|
||||
others_heatmap
|
||||
others_heatmap,
|
||||
others_heatmap_cluster
|
||||
) {
|
||||
|
||||
// widget
|
||||
@@ -59,7 +61,8 @@ return Backbone.Model.extend(
|
||||
'jqplot_line' : jqplot_line,
|
||||
'jqplot_scatter' : jqplot_scatter,
|
||||
'jqplot_boxplot' : jqplot_boxplot,
|
||||
'others_heatmap' : others_heatmap
|
||||
'others_heatmap' : others_heatmap,
|
||||
'others_heatmap_cluster' : others_heatmap_cluster
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user