StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics
https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
410 lines
10 KiB
410 lines
10 KiB
4 years ago
|
'use strict';
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
|
||
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
||
|
|
||
|
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||
|
|
||
|
var _d2 = require('d3');
|
||
|
|
||
|
var _d3 = _interopRequireDefault(_d2);
|
||
|
|
||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
|
||
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||
|
|
||
|
/**
|
||
|
* Default config.
|
||
|
*/
|
||
|
|
||
|
var defaults = {
|
||
|
// target element or selector to contain the svg
|
||
|
target: '#chart',
|
||
|
|
||
|
// width of chart
|
||
|
width: 400,
|
||
|
|
||
|
// height of chart
|
||
|
height: 400,
|
||
|
|
||
|
// margin
|
||
|
margin: { top: 15, right: 0, bottom: 35, left: 60 },
|
||
|
|
||
|
// enable axis, when disabled margin is removed
|
||
|
axis: true,
|
||
|
|
||
|
// axis padding
|
||
|
axisPadding: 5,
|
||
|
|
||
|
// number of x-axis ticks
|
||
|
xTicks: 5,
|
||
|
|
||
|
// number of y-axis ticks
|
||
|
yTicks: 3,
|
||
|
|
||
|
// size of axis ticks
|
||
|
tickSize: 5,
|
||
|
|
||
|
// tick formatter
|
||
|
tickFormat: null,
|
||
|
|
||
|
// line interpolation
|
||
|
interpolate: 'basis',
|
||
|
|
||
|
// color range from 'cold' to 'hot'
|
||
|
color: ['rgb(0, 180, 240)', 'rgb(243, 42, 100)'],
|
||
|
|
||
|
// color interpolation function
|
||
|
colorInterpolate: _d3.default.interpolateHcl,
|
||
|
|
||
|
// opacity range for the domain 0-N
|
||
|
opacityRange: [0.10, 1],
|
||
|
|
||
|
// gap size
|
||
|
gap: 1,
|
||
|
|
||
|
// bin type: 'circle', 'rect'
|
||
|
type: 'rect',
|
||
|
|
||
|
// axis type: linear, time
|
||
|
axisType: 'linear',
|
||
|
|
||
|
// mouseover callback for tooltips or value display
|
||
|
mouseover: function mouseover(_) {},
|
||
|
|
||
|
// mouseout callback for tooltips or value display
|
||
|
mouseout: function mouseout(_) {}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Zero margin.
|
||
|
*/
|
||
|
|
||
|
var zeroMargin = { top: 0, right: 0, bottom: 0, left: 0 };
|
||
|
|
||
|
/**
|
||
|
* Heatmap.
|
||
|
*/
|
||
|
|
||
|
var Heatmap = function () {
|
||
|
|
||
|
/**
|
||
|
* Construct with the given `config`.
|
||
|
*/
|
||
|
|
||
|
function Heatmap(config) {
|
||
|
_classCallCheck(this, Heatmap);
|
||
|
|
||
|
this.set(config);
|
||
|
if (!this.axis) this.margin = zeroMargin;
|
||
|
this.init();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set configuration options.
|
||
|
*/
|
||
|
|
||
|
_createClass(Heatmap, [{
|
||
|
key: 'set',
|
||
|
value: function set(config) {
|
||
|
Object.assign(this, defaults, config);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Dimensions without margin.
|
||
|
*/
|
||
|
|
||
|
}, {
|
||
|
key: 'dimensions',
|
||
|
value: function dimensions() {
|
||
|
var width = this.width;
|
||
|
var height = this.height;
|
||
|
var margin = this.margin;
|
||
|
|
||
|
var w = width - margin.left - margin.right;
|
||
|
var h = height - margin.top - margin.bottom;
|
||
|
return [w, h];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initialize the chart.
|
||
|
*/
|
||
|
|
||
|
}, {
|
||
|
key: 'init',
|
||
|
value: function init() {
|
||
|
var target = this.target;
|
||
|
var width = this.width;
|
||
|
var height = this.height;
|
||
|
var margin = this.margin;
|
||
|
var axisPadding = this.axisPadding;
|
||
|
var interpolate = this.interpolate;
|
||
|
var axis = this.axis;
|
||
|
var tickSize = this.tickSize;
|
||
|
var xTicks = this.xTicks;
|
||
|
var yTicks = this.yTicks;
|
||
|
var axisType = this.axisType;
|
||
|
var tickFormat = this.tickFormat;
|
||
|
var color = this.color;
|
||
|
var colorInterpolate = this.colorInterpolate;
|
||
|
var opacityRange = this.opacityRange;
|
||
|
|
||
|
var _dimensions = this.dimensions();
|
||
|
|
||
|
var _dimensions2 = _slicedToArray(_dimensions, 2);
|
||
|
|
||
|
var w = _dimensions2[0];
|
||
|
var h = _dimensions2[1];
|
||
|
|
||
|
|
||
|
this.chart = _d3.default.select(target).attr('width', width).attr('height', height).append('g').attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
|
||
|
|
||
|
if (axisType == 'time') {
|
||
|
this.x = _d3.default.time.scale().range([0, w]);
|
||
|
} else {
|
||
|
this.x = _d3.default.scale.linear().range([0, w]);
|
||
|
}
|
||
|
|
||
|
this.y = _d3.default.scale.linear().range([h, 0]);
|
||
|
|
||
|
this.opacity = _d3.default.scale.linear().range(opacityRange);
|
||
|
|
||
|
this.color = _d3.default.scale.linear().range(color).interpolate(colorInterpolate);
|
||
|
|
||
|
if (!axis) return;
|
||
|
|
||
|
this.xAxis = _d3.default.svg.axis().orient('bottom').scale(this.x).ticks(xTicks).tickPadding(8).tickSize(tickSize);
|
||
|
|
||
|
this.yAxis = _d3.default.svg.axis().orient('left').scale(this.y).ticks(yTicks).tickPadding(8).tickSize(tickSize).tickFormat(tickFormat);
|
||
|
|
||
|
this.chart.append('g').attr('class', 'x axis').attr('transform', 'translate(0, ' + (h + axisPadding) + ')').call(this.xAxis);
|
||
|
|
||
|
this.chart.append('g').attr('class', 'y axis').attr('transform', 'translate(' + -axisPadding + ', 0)').call(this.yAxis);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Prepate domains for subsequent render methods.
|
||
|
*/
|
||
|
|
||
|
}, {
|
||
|
key: 'prepare',
|
||
|
value: function prepare(data, options) {
|
||
|
var x = this.x;
|
||
|
var y = this.y;
|
||
|
|
||
|
|
||
|
var yMin = _d3.default.min(data, function (d) {
|
||
|
return _d3.default.min(d.bins, function (d) {
|
||
|
return d.bin;
|
||
|
});
|
||
|
});
|
||
|
var yMax = _d3.default.max(data, function (d) {
|
||
|
return d.bins[d.bins.length - 1].bin;
|
||
|
});
|
||
|
var yStep = yMax / data[0].bins.length;
|
||
|
|
||
|
x.domain(_d3.default.extent(data, function (d) {
|
||
|
return d.bin;
|
||
|
}));
|
||
|
y.domain([yMin, yMax + yStep]);
|
||
|
|
||
|
this.yStep = yStep;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render axis.
|
||
|
*/
|
||
|
|
||
|
}, {
|
||
|
key: 'renderAxis',
|
||
|
value: function renderAxis(data, options) {
|
||
|
var chart = this.chart;
|
||
|
var xAxis = this.xAxis;
|
||
|
var yAxis = this.yAxis;
|
||
|
|
||
|
|
||
|
var c = options.animate ? chart.transition() : chart;
|
||
|
|
||
|
c.select('.x.axis').call(xAxis);
|
||
|
c.select('.y.axis').call(yAxis);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render bins.
|
||
|
*/
|
||
|
|
||
|
}, {
|
||
|
key: 'renderBuckets',
|
||
|
value: function renderBuckets(data) {
|
||
|
var chart = this.chart;
|
||
|
var x = this.x;
|
||
|
var y = this.y;
|
||
|
var color = this.color;
|
||
|
var opacity = this.opacity;
|
||
|
var gap = this.gap;
|
||
|
var type = this.type;
|
||
|
var yStep = this.yStep;
|
||
|
|
||
|
var _dimensions3 = this.dimensions();
|
||
|
|
||
|
var _dimensions4 = _slicedToArray(_dimensions3, 2);
|
||
|
|
||
|
var w = _dimensions4[0];
|
||
|
var h = _dimensions4[1];
|
||
|
|
||
|
// max count
|
||
|
|
||
|
var zMax = _d3.default.max(data, function (d) {
|
||
|
return _d3.default.max(d.bins, function (d) {
|
||
|
return d.count;
|
||
|
});
|
||
|
});
|
||
|
|
||
|
// color domain
|
||
|
color.domain([0, zMax]);
|
||
|
opacity.domain([0, zMax]);
|
||
|
|
||
|
// bin dimensions
|
||
|
var bw = w / data.length;
|
||
|
var bh = h / data[0].bins.length;
|
||
|
|
||
|
var col = chart.selectAll('.column').data(data);
|
||
|
|
||
|
// enter
|
||
|
col.enter().append('g').attr('class', 'column');
|
||
|
|
||
|
// update
|
||
|
col.attr('transform', function (d, i) {
|
||
|
return 'translate(' + x(d.bin) + ', 0)';
|
||
|
});
|
||
|
|
||
|
// exit
|
||
|
col.exit().remove();
|
||
|
|
||
|
switch (type) {
|
||
|
case 'rect':
|
||
|
this.renderBinRect(col, bw, bh, gap, yStep);
|
||
|
break;
|
||
|
case 'circle':
|
||
|
this.renderBinCircle(col, bw / 2, gap, yStep);
|
||
|
break;
|
||
|
default:
|
||
|
throw new Error('invalid .type ' + type);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render circular bin.
|
||
|
*/
|
||
|
|
||
|
}, {
|
||
|
key: 'renderBinCircle',
|
||
|
value: function renderBinCircle(col, radius, gap, yStep) {
|
||
|
var opacity = this.opacity;
|
||
|
var color = this.color;
|
||
|
var y = this.y;
|
||
|
var mouseover = this.mouseover;
|
||
|
var mouseout = this.mouseout;
|
||
|
|
||
|
|
||
|
var bin = col.selectAll('.bin').data(function (d) {
|
||
|
return d.bins;
|
||
|
});
|
||
|
|
||
|
// enter
|
||
|
bin.enter().append('circle').attr('class', 'bin');
|
||
|
|
||
|
// update
|
||
|
bin.style('fill', function (d) {
|
||
|
return color(d.count);
|
||
|
}).style('fill-opacity', function (d) {
|
||
|
return opacity(d.count);
|
||
|
}).attr('r', radius - gap).attr('cx', radius).attr('cy', function (d) {
|
||
|
return y(d.bin + yStep) + radius;
|
||
|
});
|
||
|
|
||
|
bin.on('mouseover', mouseover).on('mouseleave', mouseout);
|
||
|
|
||
|
// exit
|
||
|
bin.exit().remove();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render rectangular bin.
|
||
|
*/
|
||
|
|
||
|
}, {
|
||
|
key: 'renderBinRect',
|
||
|
value: function renderBinRect(col, bw, bh, gap, yStep) {
|
||
|
var opacity = this.opacity;
|
||
|
var color = this.color;
|
||
|
var y = this.y;
|
||
|
var mouseover = this.mouseover;
|
||
|
var mouseout = this.mouseout;
|
||
|
|
||
|
|
||
|
var bin = col.selectAll('.bin').data(function (d) {
|
||
|
return d.bins;
|
||
|
});
|
||
|
|
||
|
// enter
|
||
|
bin.enter().append('rect').attr('class', 'bin');
|
||
|
|
||
|
// update
|
||
|
bin.style('fill', function (d) {
|
||
|
return color(d.count);
|
||
|
}).style('fill-opacity', function (d) {
|
||
|
return opacity(d.count);
|
||
|
}).attr('width', bw - gap).attr('height', bh - gap).attr('x', 0).attr('y', function (d) {
|
||
|
return y(d.bin + yStep);
|
||
|
});
|
||
|
|
||
|
bin.on('mouseover', mouseover).on('mouseleave', mouseout);
|
||
|
|
||
|
// exit
|
||
|
bin.exit().remove();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render the chart against the given `data`.
|
||
|
*
|
||
|
* Data shape is N bins by M bins. The top level bins array
|
||
|
* forms the x-axis while the nested .bins is the y-axis. The number
|
||
|
* of bins in each axis should be pre-defined to the desired size,
|
||
|
* as this library does not compute histograms for you.
|
||
|
*
|
||
|
* [{ bin: X, bins: [{ bin: Y, count: Z }] }]
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
}, {
|
||
|
key: 'render',
|
||
|
value: function render(data) {
|
||
|
var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
|
||
|
var axis = this.axis;
|
||
|
|
||
|
this.prepare(data, options);
|
||
|
if (axis) this.renderAxis(data, options);
|
||
|
this.renderBuckets(data, options);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Update the chart against the given `data`.
|
||
|
*/
|
||
|
|
||
|
}, {
|
||
|
key: 'update',
|
||
|
value: function update(data) {
|
||
|
this.render(data, {
|
||
|
animate: true
|
||
|
});
|
||
|
}
|
||
|
}]);
|
||
|
|
||
|
return Heatmap;
|
||
|
}();
|
||
|
|
||
|
exports.default = Heatmap;
|