/**
* @param chartOptions.project
* morpheus.Project
* @param chartOptions.getVisibleTrackNames
* {Function}
*/
morpheus.ChartTool2 = function (chartOptions) {
var _this = this;
this.getVisibleTrackNames = chartOptions.getVisibleTrackNames;
this.project = chartOptions.project;
var project = this.project;
this.$el = $('
');
var formBuilder = new morpheus.FormBuilder({
vertical: true
});
this.formBuilder = formBuilder;
formBuilder.append({
name: 'chart_type',
type: 'select',
options: ['boxplot', 'row scatter', 'column scatter', 'row profile', 'column profile']
});
var rowOptions = [];
var columnOptions = [];
var numericRowOptions = [];
var numericColumnOptions = [];
var options = [];
var numericOptions = [];
var updateOptions = function () {
var dataset = project.getFullDataset();
rowOptions = [{
name: '(None)',
value: ''
}];
columnOptions = [{
name: '(None)',
value: ''
}];
numericRowOptions = [{
name: '(None)',
value: ''
}];
numericColumnOptions = [{
name: '(None)',
value: ''
}];
options = [{
name: '(None)',
value: ''
}];
numericOptions = [{
name: '(None)',
value: ''
}];
morpheus.MetadataUtil.getMetadataNames(dataset.getRowMetadata())
.forEach(
function (name) {
var dataType = morpheus.VectorUtil
.getDataType(dataset.getRowMetadata()
.getByName(name));
if (dataType === 'number'
|| dataType === '[number]') {
numericRowOptions.push({
name: name + ' (row)',
value: name + '_r'
});
}
rowOptions.push({
name: name + ' (row)',
value: name + '_r'
});
});
morpheus.MetadataUtil.getMetadataNames(dataset.getColumnMetadata())
.forEach(
function (name) {
var dataType = morpheus.VectorUtil
.getDataType(dataset.getColumnMetadata()
.getByName(name));
if (dataType === 'number'
|| dataType === '[number]') {
numericColumnOptions.push({
name: name + ' (column)',
value: name + '_c'
});
}
columnOptions.push({
name: name + ' (column)',
value: name + '_c'
});
});
options = options.concat(rowOptions.slice(1));
options = options.concat(columnOptions.slice(1));
numericOptions = numericOptions.concat(numericRowOptions.slice(1));
numericOptions = numericOptions.concat(numericColumnOptions.slice(1));
};
updateOptions();
formBuilder.append({
name: 'group_columns_by',
type: 'select',
options: options
});
formBuilder.append({
name: 'group_rows_by',
type: 'select',
options: options
});
formBuilder.append({
name: 'axis_label',
type: 'select',
options: rowOptions
});
formBuilder.append({
name: 'show_points',
type: 'checkbox',
value: true
});
formBuilder.append({
name: 'color',
type: 'select',
options: options
});
formBuilder.append({
name: 'size',
type: 'select',
options: numericOptions
});
function setVisibility() {
// 'boxplot', 'row scatter', 'column scatter', 'row profile', 'column profile'
var chartType = formBuilder.getValue('chart_type');
formBuilder.setVisible('group_rows_by', chartType === 'boxplot');
formBuilder.setVisible('group_columns_by', chartType === 'boxplot');
if (chartType !== 'boxplot') {
formBuilder.setOptions('axis_label',
(chartType === 'row scatter' || chartType === 'column profile') ? rowOptions : columnOptions,
true);
formBuilder.setOptions('color',
(chartType === 'row scatter' || chartType === 'column profile') ? columnOptions : rowOptions,
true);
formBuilder.setOptions('size',
(chartType === 'row scatter' || chartType === 'row profile') ? numericColumnOptions
: numericRowOptions, true);
} else {
formBuilder.setOptions('color', options, true);
formBuilder.setOptions('size', numericOptions, true);
}
formBuilder.setVisible('axis_label', chartType !== 'boxplot');
}
formBuilder.$form.find('select').on('change', function () {
setVisibility();
_this.draw();
});
formBuilder.$form.find('input').on('click', function () {
_this.draw();
});
setVisibility();
// chart types: boxplot, scatter
// add: tooltip, color, size, allow boxplot and scatter of attributes?
var draw = function () {
_.debounce(_this.draw(), 100);
};
var trackChanged = function () {
updateOptions();
setVisibility();
formBuilder.setOptions('group_columns_by', options, true);
formBuilder.setOptions('group_rows_by', options, true);
};
project.getColumnSelectionModel().on('selectionChanged.chart', draw);
project.getRowSelectionModel().on('selectionChanged.chart', draw);
project.on('trackChanged.chart', trackChanged);
this.$chart = this.$el.find('[name=chartDiv]');
var $dialog = $('');
var $configPane = this.$el.find('[name=configPane]');
formBuilder.$form.appendTo($configPane);
this.$el.appendTo($dialog);
$dialog.dialog({
close: function (event, ui) {
project.off('trackChanged.chart', trackChanged);
project.getRowSelectionModel().off('selectionChanged.chart', draw);
project.getColumnSelectionModel().off('selectionChanged.chart',
draw);
_this.$el.empty();
},
resizable: true,
height: 600,
width: 900
});
this.$dialog = $dialog;
this.draw();
};
morpheus.ChartTool2.getPlotlyDefaults = function () {
var layout = {
autosize: false,
paper_bgcolor: 'rgb(255,255,255)',
plot_bgcolor: 'rgb(229,229,229)',
showlegend: false,
margin: {
l: 80,
r: 0,
t: 10,
b: 14,
autoexpand: true
},
xaxis: {
zeroline: false,
titlefont: {
size: 12
},
gridcolor: 'rgb(255,255,255)',
showgrid: true,
showline: false,
showticklabels: true,
tickcolor: 'rgb(127,127,127)',
ticks: 'outside',
type: 'linear'
},
yaxis: {
zeroline: false,
titlefont: {
size: 12
},
gridcolor: 'rgb(255,255,255)',
showgrid: true,
showline: false,
showticklabels: true,
tickcolor: 'rgb(127,127,127)',
ticks: 'outside',
type: 'linear'
}
};
var config = {
showLink: false,
displaylogo: false,
staticPlot: false,
showHints: true,
modeBarButtonsToRemove: ['sendDataToCloud']
};
return {
layout: layout,
config: config
};
};
morpheus.ChartTool2.getVectorInfo = function (value) {
var field = value.substring(0, value.length - 2);
var isColumns = value.substring(value.length - 2) === '_c';
return {
field: field,
isColumns: isColumns
};
};
morpheus.ChartTool2.prototype = {
annotate: function (options) {
var _this = this;
var formBuilder = new morpheus.FormBuilder();
formBuilder.append({
name: 'annotation_name',
type: 'text',
required: true
});
formBuilder.append({
name: 'annotation_value',
type: 'text',
required: true
});
// formBuilder.append({
// name : 'annotate',
// type : 'radio',
// required : true,
// options : [ 'Rows', 'Columns', 'Rows And Columns' ],
// value : 'Rows'
// });
morpheus.FormBuilder
.showOkCancel({
title: 'Annotate Selection',
content: formBuilder.$form,
okCallback: function () {
var dataset = options.dataset;
var eventData = options.eventData;
var array = options.array;
var value = formBuilder.getValue('annotation_value');
var annotationName = formBuilder
.getValue('annotation_name');
// var annotate = formBuilder.getValue('annotate');
var isRows = true;
var isColumns = true;
var existingRowVector = null;
var rowVector = null;
if (isRows) {
existingRowVector = dataset.getRowMetadata()
.getByName(annotationName);
rowVector = dataset.getRowMetadata().add(
annotationName);
}
var existingColumnVector = null;
var columnVector = null;
if (isColumns) {
existingColumnVector = dataset.getColumnMetadata()
.getByName(annotationName);
columnVector = dataset.getColumnMetadata().add(
annotationName);
}
for (var p = 0, nselected = eventData.points.length; p < nselected; p++) {
var item = array[eventData.points[p].pointNumber];
if (isRows) {
if (_.isArray(item.row)) {
item.row.forEach(function (r) {
rowVector.setValue(r, value);
});
} else {
rowVector.setValue(item.row, value);
}
}
if (isColumns) {
columnVector.setValue(item.column, value);
}
}
if (isRows) {
morpheus.VectorUtil
.maybeConvertStringToNumber(rowVector);
_this.project.trigger('trackChanged', {
vectors: [rowVector],
render: existingRowVector != null ? []
: [morpheus.VectorTrack.RENDER.TEXT],
columns: false
});
}
if (isColumns) {
morpheus.VectorUtil
.maybeConvertStringToNumber(columnVector);
_this.project.trigger('trackChanged', {
vectors: [columnVector],
render: existingColumnVector != null ? []
: [morpheus.VectorTrack.RENDER.TEXT],
columns: true
});
}
}
});
},
_createScatter: function (options) {
var dataset = options.dataset;
var colorByVector = options.colorByVector;
var colorModel = options.colorModel;
var sizeByVector = options.sizeByVector;
var sizeFunction = options.sizeFunction;
var heatmap = this.heatmap;
var myPlot = options.myPlot;
var isColumnChart = options.isColumnChart;
// scatter
var x = [];
var y = [];
var text = [];
var color = colorByVector ? [] : '#1f78b4';
var size = sizeByVector ? [] : 6;
var array = [];
for (var j = 0, ncols = dataset.getColumnCount(); j < ncols; j++) {
y.push(dataset.getValue(options.rowIndexOne, j));
x.push(dataset.getValue(options.rowIndexTwo, j));
array.push({
row: [options.rowIndexOne, options.rowIndexTwo],
column: j
});
if (colorByVector) {
var colorByValue = colorByVector.getValue(j);
color.push(colorModel.getMappedValue(colorByVector,
colorByValue));
}
if (sizeByVector) {
var sizeByValue = sizeByVector.getValue(j);
size.push(sizeFunction(sizeByValue));
}
var obj = {
j: j
};
obj.toString = function () {
var trackNames = _this.getVisibleTrackNames(!isColumnChart);
var s = [];
for (var i = 0; i < trackNames.length; i++) {
var v = dataset.getColumnMetadata()
.getByName(trackNames[i]);
if (v) {
morpheus.HeatMapTooltipProvider.vectorToString(v,
this.j, s, '
');
}
}
return s.join('');
};
text.push(obj);
}
// TODO add R^2
var trace = {
x: x,
y: y,
marker: {
color: color,
size: size,
symbol: 'circle-open'
},
text: text,
mode: 'markers',
type: 'scatter' // scattergl
};
var selection = null;
var _this = this;
var config = $
.extend(
true,
{},
options.config,
{
modeBarButtonsToAdd: [[{
name: 'annotate',
title: 'Annotate Selection',
attr: 'dragmode',
val: 'annotate',
icon: {
'width': 1792,
'path': 'M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z',
'ascent': 1792,
'descent': 0
},
click: function () {
if (!selection) {
morpheus.FormBuilder
.showInModal({
title: 'Annotate Selection',
html: 'Please select points in the chart',
close: 'Close'
});
} else {
_this.annotate({
array: array,
eventData: selection,
dataset: dataset
});
}
}
}]]
});
Plotly.newPlot(myPlot, [trace], options.layout, config);
myPlot.on('plotly_selected', function (eventData) {
selection = eventData;
});
},
_createProfile: function (options) {
var dataset = options.dataset;
// only allow coloring by row
var colorByVector = options.colorByVector;
var colorModel = options.colorModel;
var sizeByVector = options.sizeByVector;
var sizeFunction = options.sizeFunction;
var axisLabelVector = options.axisLabelVector;
var isColumnChart = options.isColumnChart;
var heatmap = this.heatmap;
var myPlot = options.myPlot;
var traces = [];
var ticktext = [];
var tickvals = [];
console.log(dataset.getRowCount(), dataset.getColumnCount());
for (var j = 0, ncols = dataset.getColumnCount(); j < ncols; j++) {
ticktext.push(axisLabelVector != null ? axisLabelVector.getValue(j) : '' + j);
tickvals.push(j);
}
for (var i = 0, nrows = dataset.getRowCount(); i < nrows; i++) {
// each row is a new trace
var x = [];
var y = [];
var text = [];
var size = sizeByVector ? [] : 6;
var color = colorByVector ? colorModel.getMappedValue(colorByVector,
colorByVector.getValue(i)) : undefined;
for (var j = 0, ncols = dataset.getColumnCount(); j < ncols; j++) {
x.push(j);
y.push(dataset.getValue(i, j));
if (sizeByVector) {
var sizeByValue = sizeByVector.getValue(j);
size.push(sizeFunction(sizeByValue));
}
var obj = {
i: i,
j: j
};
obj.toString = function () {
var trackNames = _this.getVisibleTrackNames(!isColumnChart);
var s = [];
for (var i = 0; i < trackNames.length; i++) {
var v = dataset.getColumnMetadata()
.getByName(trackNames[i]);
if (v) {
morpheus.HeatMapTooltipProvider.vectorToString(v,
this.j, s, '
');
}
}
return s.join('');
};
text.push(obj);
}
var trace = {
x: x,
y: y,
name: colorByVector ? colorByVector.getValue(i) : '',
tickmode: 'array',
marker: {
size: size,
symbol: 'circle'
},
text: text,
mode: 'markers+lines',
type: 'scatter' // scattergl
};
traces.push(trace);
}
var selection = null;
var _this = this;
options.layout.xaxis.tickvals = tickvals;
options.layout.xaxis.ticktext = ticktext;
options.layout.xaxis.tickmode = 'array';
var config = $
.extend(
true,
{},
options.config,
{
modeBarButtonsToAdd: [[{
name: 'annotate',
title: 'Annotate Selection',
attr: 'dragmode',
val: 'annotate',
icon: {
'width': 1792,
'path': 'M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z',
'ascent': 1792,
'descent': 0
},
click: function () {
if (!selection) {
morpheus.FormBuilder
.showInModal({
title: 'Annotate Selection',
html: 'Please select points in the chart',
close: 'Close'
});
} else {
_this.annotate({
eventData: selection,
dataset: dataset
});
}
}
}]]
});
var $parent = $(myPlot).parent();
options.layout.width = $parent.width();
options.layout.height = this.$dialog.height() - 30;
Plotly.newPlot(myPlot, traces, options.layout, config);
myPlot.on('plotly_selected', function (eventData) {
selection = eventData;
});
function resize() {
var width = $parent.width();
var height = _this.$dialog.height() - 30;
Plotly.relayout(myPlot, {
width: width,
height: height
});
}
this.$dialog.on('dialogresize', resize);
$(myPlot).on('remove', function () {
_this.$dialog.off('dialogresize');
});
},
_createBoxPlot: function (options) {
var array = options.array; // array of items
var points = options.points;
var colorByVector = options.colorByVector;
var colorByGetter = options.colorByGetter;
var colorModel = options.colorModel;
var myPlot = options.myPlot;
var dataset = options.dataset;
var y = [];
var color = points && colorByVector ? [] : '#1f78b4';
var text = [];
var x = [];
var heatmap = this.heatmap;
var sizeFunction = options.sizeFunction;
var sizeByGetter = options.sizeByGetter;
var size = sizeFunction ? [] : 6;
var scale = d3.scale.linear().domain([0, 1]).range([-0.3, -1]);
for (var k = 0, nitems = array.length; k < nitems; k++) {
var item = array[k];
y.push(dataset.getValue(item.row, item.column));
if (points) {
x.push(scale(Math.random()));
if (colorByVector) {
var colorByValue = colorByGetter(item);
color.push(colorModel.getMappedValue(colorByVector,
colorByValue));
}
if (sizeFunction) {
var sizeByValue = sizeByGetter(item);
size.push(sizeFunction(sizeByValue));
}
var obj = {
row: item.row,
column: item.column
};
obj.toString = function () {
var s = [];
var trackNames = _this.getVisibleTrackNames(true);
for (var trackIndex = 0; trackIndex < trackNames.length; trackIndex++) {
var v = dataset.getColumnMetadata().getByName(
trackNames[trackIndex]);
if (v) {
morpheus.HeatMapTooltipProvider.vectorToString(v,
this.column, s, '
');
}
}
trackNames = _this.getVisibleTrackNames(false);
for (var trackIndex = 0; trackIndex < trackNames.length; trackIndex++) {
var v = dataset.getRowMetadata().getByName(
trackNames[trackIndex]);
if (v) {
morpheus.HeatMapTooltipProvider.vectorToString(v,
this.row, s, '
');
}
}
return s.join('');
};
text.push(obj);
}
}
var traces = [{
name: '',
y: y,
type: 'box',
boxpoints: false
}];
if (points) {
traces.push({
name: '',
x: x,
y: y,
hoverinfo: 'y+text',
mode: 'markers',
type: 'scatter',
text: text,
marker: {
symbol: 'circle-open',
size: size,
color: color
}
});
}
var selection = null;
var _this = this;
var config = $
.extend(
true,
{},
options.config,
{
modeBarButtonsToAdd: [[{
name: 'annotate',
title: 'Annotate Selection',
attr: 'dragmode',
val: 'annotate',
icon: {
'width': 1792,
'path': 'M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z',
'ascent': 1792,
'descent': 0
},
click: function () {
if (!selection) {
morpheus.FormBuilder
.showInModal({
title: 'Annotate Selection',
html: 'Please select points in the chart',
close: 'Close'
});
} else {
_this.annotate({
array: array,
eventData: selection,
dataset: dataset
});
}
}
}]]
});
Plotly.newPlot(myPlot, traces, options.layout, config);
myPlot.on('plotly_selected', function (eventData) {
selection = eventData;
});
},
draw: function () {
var _this = this;
this.$chart.empty();
var plotlyDefaults = morpheus.ChartTool2.getPlotlyDefaults();
var layout = plotlyDefaults.layout;
var config = plotlyDefaults.config;
var chartWidth = 400;
var chartHeight = 400;
var points = this.formBuilder.getValue('show_points');
var groupColumnsBy = this.formBuilder.getValue('group_columns_by');
var axisLabel = this.formBuilder.getValue('axis_label');
var colorBy = this.formBuilder.getValue('color');
var sizeBy = this.formBuilder.getValue('size');
var groupRowsBy = this.formBuilder.getValue('group_rows_by');
var chartType = this.formBuilder.getValue('chart_type');
var dataset = this.project.getSelectedDataset({
emptyToAll: false
});
this.dataset = dataset;
if (dataset.getRowCount() * dataset.getColumnCount() === 0) {
$('Please select rows and columns in the heat map.
')
.appendTo(this.$chart);
return;
}
if ((dataset.getRowCount() * dataset.getColumnCount()) > 100000) {
points = false;
}
var grid = [];
var rowIds = [undefined];
var columnIds = [undefined];
var items = [];
var heatmap = this.heatmap;
var colorByInfo = morpheus.ChartTool2.getVectorInfo(colorBy);
var sizeByInfo = morpheus.ChartTool2.getVectorInfo(sizeBy);
var colorModel = !colorByInfo.isColumns ? this.project.getRowColorModel()
: this.project.getColumnColorModel();
var axisLabelInfo = morpheus.ChartTool2.getVectorInfo(axisLabel);
var axisLabelVector = axisLabelInfo.isColumns ? dataset.getColumnMetadata().getByName(axisLabelInfo.field) : dataset.getRowMetadata().getByName(
axisLabelInfo.field);
var sizeByVector = sizeByInfo.isColumns ? dataset.getColumnMetadata().getByName(sizeByInfo.field) : dataset.getRowMetadata().getByName(
sizeByInfo.field);
var colorByVector = colorByInfo.isColumns ? dataset.getColumnMetadata().getByName(colorByInfo.field) : dataset.getRowMetadata().getByName(
colorByInfo.field);
var sizeByScale = null;
if (sizeByVector) {
var minMax = morpheus.VectorUtil.getMinMax(sizeByVector);
sizeByScale = d3.scale.linear().domain(
[minMax.min, minMax.max]).range([3, 16])
.clamp(true);
}
if (chartType === 'row profile' || chartType === 'column profile') {
var $chart = $('');
var myPlot = $chart[0];
$chart.appendTo(this.$chart);
if (chartType === 'column profile') {
dataset = new morpheus.TransposedDatasetView(dataset);
}
this
._createProfile({
isColumnChart: chartType === 'column profile',
axisLabelVector: axisLabelVector,
colorByVector: colorByVector,
colorModel: colorModel,
sizeByVector: sizeByVector,
sizeFunction: sizeByScale,
myPlot: myPlot,
dataset: dataset,
config: config,
layout: $
.extend(
true,
{},
layout,
{
showlegend: true,
width: chartWidth,
height: chartHeight,
margin: {
b: 80
},
yaxis: {},
xaxis: {}
})
});
}
if (chartType === 'row scatter' || chartType === 'column scatter') {
var transpose = chartType === 'column scatter';
if (transpose) {
dataset = new morpheus.TransposedDatasetView(dataset);
}
if (dataset.getRowCount() > 20) {
$('Maximum chart size exceeded.
')
.appendTo(this.$chart);
return;
}
// rowIndexOne is along rows of chart (y axis), rowIndexTwo along x
// axis
// draw grid
for (var rowIndexOne = 0, nrows = dataset.getRowCount(); rowIndexOne < nrows; rowIndexOne++) {
for (var rowIndexTwo = 0; rowIndexTwo < nrows; rowIndexTwo++) {
if (rowIndexOne > rowIndexTwo) {
continue;
}
var $chart = $('');
var myPlot = $chart[0];
$chart.appendTo(this.$chart);
if (rowIndexOne === rowIndexTwo) { // boxplot
var array = [];
for (var j = 0, ncols = dataset.getColumnCount(); j < ncols; j++) {
array.push({
row: rowIndexTwo,
column: j
});
}
this
._createBoxPlot({
array: array,
points: points,
colorByVector: colorByVector,
colorModel: colorModel,
colorByGetter: function (item) {
return colorByVector
.getValue(item.column);
},
sizeByGetter: function (item) {
return sizeByVector
.getValue(item.column);
},
sizeFunction: sizeByScale,
myPlot: myPlot,
dataset: dataset,
config: config,
transposed: isColumns,
layout: $
.extend(
true,
{},
layout,
{
width: chartWidth,
height: chartHeight,
margin: {
b: 80
},
xaxis: {
title: axisLabelVector == null ? ''
: axisLabelVector
.getValue(rowIndexTwo),
showticklabels: false
}
})
});
} else {
this
._createScatter({
isColumnChart: transpose,
rowIndexOne: rowIndexOne,
rowIndexTwo: rowIndexTwo,
colorByVector: colorByVector,
colorModel: colorModel,
colorByGetter: function (item) {
return colorByVector
.getValue(item.column);
},
sizeByVector: sizeByVector,
sizeFunction: sizeByScale,
myPlot: myPlot,
dataset: dataset,
config: config,
layout: $
.extend(
true,
{},
layout,
{
width: chartWidth,
height: chartHeight,
margin: {
b: 80
},
yaxis: {
title: axisLabelVector == null ? ''
: axisLabelVector
.getValue(rowIndexOne),
},
xaxis: {
title: axisLabelVector == null ? ''
: axisLabelVector
.getValue(rowIndexTwo)
}
})
});
}
}
}
} else if (chartType === 'boxplot') {
for (var i = 0, nrows = dataset.getRowCount(); i < nrows; i++) {
for (var j = 0, ncols = dataset.getColumnCount(); j < ncols; j++) {
items.push({
row: i,
column: j
});
}
}
var colorByInfo = morpheus.ChartTool2.getVectorInfo(colorBy);
var colorByVector = colorByInfo.isColumns ? dataset.getColumnMetadata()
.getByName(colorByInfo.field) : dataset.getRowMetadata()
.getByName(colorByInfo.field);
var colorModel = !colorByInfo.isColumns ? this.project
.getRowColorModel() : this.project.getColumnColorModel();
var colorByGetter = colorByInfo.isColumns ? function (item) {
return colorByVector.getValue(item.column);
} : function (item) {
return colorByVector.getValue(item.row);
};
var sizeByVector = sizeByInfo.isColumns ? dataset.getColumnMetadata()
.getByName(sizeByInfo.field) : dataset.getRowMetadata()
.getByName(sizeByInfo.field);
var sizeByGetter = sizeByInfo.isColumns ? function (item) {
return sizeByVector.getValue(item.column);
} : function (item) {
return sizeByVector.getValue(item.row);
};
var sizeByScale = null;
if (sizeByVector) {
var minMax = morpheus.VectorUtil.getMinMax(sizeByVector);
sizeByScale = d3.scale.linear().domain([minMax.min, minMax.max])
.range([3, 16]).clamp(true);
}
if (groupColumnsBy || groupRowsBy) {
var rowIdToArray = new morpheus.Map();
if (groupRowsBy) {
var groupRowsByInfo = morpheus.ChartTool2
.getVectorInfo(groupRowsBy);
var vector = groupRowsByInfo.isColumns ? dataset
.getColumnMetadata().getByName(groupRowsByInfo.field)
: dataset.getRowMetadata().getByName(
groupRowsByInfo.field);
var getter = groupRowsByInfo.isColumns ? function (item) {
return vector.getValue(item.column);
} : function (item) {
return vector.getValue(item.row);
};
for (var i = 0, nitems = items.length; i < nitems; i++) {
var item = items[i];
var value = getter(item);
var array = rowIdToArray.get(value);
if (array == undefined) {
array = [];
rowIdToArray.set(value, array);
}
array.push(item);
}
} else {
rowIdToArray.set(undefined, items);
}
if (groupColumnsBy) {
var name = groupColumnsBy.substring(0,
groupColumnsBy.length - 2);
var isColumns = groupColumnsBy
.substring(groupColumnsBy.length - 2) === '_c';
var vector = isColumns ? dataset.getColumnMetadata().getByName(
name) : dataset.getRowMetadata().getByName(name);
var getter = isColumns ? function (item) {
return vector.getValue(item.column);
} : function (item) {
return vector.getValue(item.row);
};
var columnIdToIndex = new morpheus.Map();
var rowIndex = 0;
rowIdToArray.forEach(function (array, id) {
grid[rowIndex] = [];
for (var i = 0, nitems = array.length; i < nitems; i++) {
var item = array[i];
var value = getter(item);
var columnIndex = columnIdToIndex.get(value);
if (columnIndex === undefined) {
columnIndex = columnIdToIndex.size();
columnIdToIndex.set(value, columnIndex);
}
if (grid[rowIndex][columnIndex] === undefined) {
grid[rowIndex][columnIndex] = [];
}
grid[rowIndex][columnIndex].push(item);
}
rowIds[rowIndex] = id;
rowIndex++;
});
columnIdToIndex.forEach(function (index, id) {
columnIds[index] = id;
});
} else {
var rowIndex = 0;
rowIdToArray.forEach(function (array, id) {
grid[rowIndex] = [array];
rowIds[rowIndex] = id;
rowIndex++;
});
}
} else {
grid = [[items]];
}
var gridRowCount = rowIds.length;
var gridColumnCount = columnIds.length;
for (var i = 0; i < gridRowCount; i++) {
var rowId = rowIds[i];
var yrange = [Number.MAX_VALUE, -Number.MAX_VALUE];
if (chartType === 'boxplot') {
for (var j = 0; j < gridColumnCount; j++) {
var array = grid[i][j];
if (array) {
for (var k = 0, nitems = array.length; k < nitems; k++) {
var item = array[k];
var value = dataset.getValue(item.row, item.column);
if (!isNaN(value)) {
yrange[0] = Math.min(yrange[0], value);
yrange[1] = Math.max(yrange[1], value);
}
}
}
}
// for now increase range by 1%
var span = yrange[1] - yrange[0];
var delta = (span * 0.01);
yrange[1] += delta;
yrange[0] -= delta;
}
for (var j = 0; j < gridColumnCount; j++) {
var array = grid[i][j];
var columnId = columnIds[j];
if (array) {
var $chart = $('');
$chart.appendTo(this.$chart);
var myPlot = $chart[0];
if (chartType === 'boxplot') {
this._createBoxPlot({
layout: $.extend(true, {}, layout, {
width: chartWidth,
height: chartHeight,
yaxis: {
range: yrange,
title: rowId,
},
xaxis: {
title: columnId,
showticklabels: false
}
}),
array: array,
points: points,
sizeByGetter: sizeByGetter,
sizeFunction: sizeByScale,
colorModel: colorModel,
colorByVector: colorByVector,
colorByGetter: colorByGetter,
myPlot: myPlot,
dataset: dataset,
config: config
});
}
}
}
}
}
}
};