bar and whisker: adding min and max
This commit is contained in:
parent
dc98787e1e
commit
fe99517cb3
@ -8,7 +8,7 @@ const actions = {
|
||||
disk: []
|
||||
});
|
||||
|
||||
const newData = ['cpu'].reduce((sum, key) => {
|
||||
const newData = ['cpu', 'mem'].reduce((sum, key) => {
|
||||
const item = {
|
||||
...action.payload.stats[key],
|
||||
when: action.payload.when
|
||||
|
@ -32,6 +32,8 @@ module.exports = React.createClass({
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
barPercentage: 1.0,
|
||||
categoryPercentage: 1.0,
|
||||
}],
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
|
@ -5,7 +5,8 @@ const React = require('react');
|
||||
const colors = {
|
||||
user: 'rgb(255, 99, 132)',
|
||||
sys: 'rgb(255, 159, 64)',
|
||||
perc: 'rgba(54, 74, 205, 0.2)'
|
||||
perc: 'rgba(54, 74, 205, 0.2)',
|
||||
alt: 'rgba(245, 93, 93, 0.2)'
|
||||
};
|
||||
|
||||
module.exports = ({
|
||||
@ -16,6 +17,7 @@ module.exports = ({
|
||||
return {
|
||||
label: key,
|
||||
backgroundColor: colors[key],
|
||||
altBackgroundColor: colors['alt'],
|
||||
data: buildArray(windowSize).map((v, i) => ((data[i] || {})[key] || { firstQuartile: 0, thirdQuartile: 0, median: 0, max: 0, min: 0 }))
|
||||
};
|
||||
});
|
||||
|
221
spikes/graphs-matrix/chartjs-whiskers/client/element.whisker.js
Normal file
221
spikes/graphs-matrix/chartjs-whiskers/client/element.whisker.js
Normal file
@ -0,0 +1,221 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function(Chart) {
|
||||
|
||||
var globalOpts = Chart.defaults.global;
|
||||
|
||||
globalOpts.elements.rectangle = {
|
||||
backgroundColor: globalOpts.defaultColor,
|
||||
borderWidth: 0,
|
||||
borderColor: globalOpts.defaultColor,
|
||||
borderSkipped: 'bottom'
|
||||
};
|
||||
|
||||
function isVertical(bar) {
|
||||
return bar._view.width !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get the bounds of the bar regardless of the orientation
|
||||
* @private
|
||||
* @param bar {Chart.Element.Rectangle} the bar
|
||||
* @return {Bounds} bounds of the bar
|
||||
*/
|
||||
function getBarBounds(bar) {
|
||||
var vm = bar._view;
|
||||
var x1, x2, y1, y2;
|
||||
|
||||
if (isVertical(bar)) {
|
||||
// vertical
|
||||
var halfWidth = vm.width / 2;
|
||||
x1 = vm.x - halfWidth;
|
||||
x2 = vm.x + halfWidth;
|
||||
y1 = Math.min(vm.y, vm.base);
|
||||
y2 = Math.max(vm.y, vm.base);
|
||||
} else {
|
||||
// horizontal bar
|
||||
var halfHeight = vm.height / 2;
|
||||
x1 = Math.min(vm.x, vm.base);
|
||||
x2 = Math.max(vm.x, vm.base);
|
||||
y1 = vm.y - halfHeight;
|
||||
y2 = vm.y + halfHeight;
|
||||
}
|
||||
|
||||
return {
|
||||
left: x1,
|
||||
top: y1,
|
||||
right: x2,
|
||||
bottom: y2
|
||||
};
|
||||
}
|
||||
|
||||
Chart.elements.Whisker = Chart.Element.extend({
|
||||
draw: function() {
|
||||
var ctx = this._chart.ctx;
|
||||
var vm = this._view;
|
||||
|
||||
var halfWidth = vm.width / 2,
|
||||
leftX = vm.x - halfWidth,
|
||||
rightX = vm.x + halfWidth,
|
||||
top = vm.base - (vm.base - vm.y),
|
||||
halfStroke = vm.borderWidth / 2;
|
||||
|
||||
// Canvas doesn't allow us to stroke inside the width so we can
|
||||
// adjust the sizes to fit if we're setting a stroke on the line
|
||||
if (vm.borderWidth) {
|
||||
leftX += halfStroke;
|
||||
rightX -= halfStroke;
|
||||
top += halfStroke;
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = vm.backgroundColor;
|
||||
ctx.strokeStyle = vm.borderColor;
|
||||
ctx.lineWidth = vm.borderWidth;
|
||||
|
||||
// Corner points, from bottom-left to bottom-right clockwise
|
||||
// | 1 2 |
|
||||
// | 0 3 |
|
||||
var corners = [
|
||||
[leftX, vm.base],
|
||||
[leftX, top],
|
||||
[rightX, top],
|
||||
[rightX, vm.base]
|
||||
];
|
||||
|
||||
// Find first (starting) corner with fallback to 'bottom'
|
||||
var borders = ['bottom', 'left', 'top', 'right'];
|
||||
var startCorner = borders.indexOf(vm.borderSkipped, 0);
|
||||
if (startCorner === -1) {
|
||||
startCorner = 0;
|
||||
}
|
||||
|
||||
function cornerAt(index) {
|
||||
return corners[(startCorner + index) % 4];
|
||||
}
|
||||
|
||||
// Draw rectangle from 'startCorner'
|
||||
var corner = cornerAt(0);
|
||||
ctx.moveTo(corner[0], corner[1]);
|
||||
|
||||
for (var i = 1; i < 4; i++) {
|
||||
corner = cornerAt(i);
|
||||
ctx.lineTo(corner[0], corner[1]);
|
||||
}
|
||||
|
||||
ctx.fill();
|
||||
if (vm.borderWidth) {
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.closePath();
|
||||
|
||||
// Median line
|
||||
ctx.beginPath();
|
||||
|
||||
ctx.moveTo(leftX, vm.median);
|
||||
ctx.lineTo(rightX, vm.median);
|
||||
ctx.lineWidth = 2;
|
||||
|
||||
// set line color
|
||||
ctx.strokeStyle = 'rgb(54, 74, 205)';
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
|
||||
// Top Whisker
|
||||
// if (smaller than 5px then do not draw)
|
||||
if (vm.median - vm.maxV > 10) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo((rightX - leftX) / 2 + leftX, vm.median - 1);
|
||||
ctx.lineTo((rightX - leftX) / 2 + leftX, vm.maxV);
|
||||
ctx.lineWidth = 2;
|
||||
ctx.strokeStyle = 'rgb(245, 93, 93)';
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
ctx.beginPath();
|
||||
ctx.arc((rightX - leftX) / 2 + leftX, vm.maxV, 3, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = 'rgb(245, 93, 93)';
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
// Bottom Whisker
|
||||
// if (smaller than 5px then do not draw)
|
||||
if (vm.minV - vm.median > 10) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo((rightX - leftX) / 2 + leftX, vm.median + 1);
|
||||
ctx.lineTo((rightX - leftX) / 2 + leftX, vm.minV);
|
||||
ctx.lineWidth = 2;
|
||||
ctx.strokeStyle = 'rgb(245, 93, 93)';
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
ctx.beginPath();
|
||||
ctx.arc((rightX - leftX) / 2 + leftX, vm.minV, 3, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = 'rgb(245, 93, 93)';
|
||||
ctx.fill();
|
||||
}
|
||||
},
|
||||
height: function() {
|
||||
var vm = this._view;
|
||||
return vm.base - vm.y;
|
||||
},
|
||||
inRange: function(mouseX, mouseY) {
|
||||
var inRange = false;
|
||||
|
||||
if (this._view) {
|
||||
var bounds = getBarBounds(this);
|
||||
inRange = mouseX >= bounds.left && mouseX <= bounds.right && mouseY >= bounds.top && mouseY <= bounds.bottom;
|
||||
}
|
||||
|
||||
return inRange;
|
||||
},
|
||||
inLabelRange: function(mouseX, mouseY) {
|
||||
var me = this;
|
||||
if (!me._view) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var inRange = false;
|
||||
var bounds = getBarBounds(me);
|
||||
|
||||
if (isVertical(me)) {
|
||||
inRange = mouseX >= bounds.left && mouseX <= bounds.right;
|
||||
} else {
|
||||
inRange = mouseY >= bounds.top && mouseY <= bounds.bottom;
|
||||
}
|
||||
|
||||
return inRange;
|
||||
},
|
||||
inXRange: function(mouseX) {
|
||||
var bounds = getBarBounds(this);
|
||||
return mouseX >= bounds.left && mouseX <= bounds.right;
|
||||
},
|
||||
inYRange: function(mouseY) {
|
||||
var bounds = getBarBounds(this);
|
||||
return mouseY >= bounds.top && mouseY <= bounds.bottom;
|
||||
},
|
||||
getCenterPoint: function() {
|
||||
var vm = this._view;
|
||||
var x, y;
|
||||
if (isVertical(this)) {
|
||||
x = vm.x;
|
||||
y = (vm.y + vm.base) / 2;
|
||||
} else {
|
||||
x = (vm.x + vm.base) / 2;
|
||||
y = vm.y;
|
||||
}
|
||||
|
||||
return {x: x, y: y};
|
||||
},
|
||||
getArea: function() {
|
||||
var vm = this._view;
|
||||
return vm.width * Math.abs(vm.y - vm.base);
|
||||
},
|
||||
tooltipPosition: function() {
|
||||
var vm = this._view;
|
||||
return {
|
||||
x: vm.x,
|
||||
y: vm.y
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
};
|
@ -1,4 +1,8 @@
|
||||
const whiskerElement = require('./element.whisker');
|
||||
|
||||
module.exports = function(Chart) {
|
||||
whiskerElement(Chart);
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
Chart.defaults.whisker = {
|
||||
@ -27,7 +31,7 @@ module.exports = function(Chart) {
|
||||
|
||||
Chart.controllers.whisker = Chart.DatasetController.extend({
|
||||
|
||||
dataElementType: Chart.Element.extend(Chart.elements.Rectangle.prototype),
|
||||
dataElementType: Chart.elements.Whisker,
|
||||
|
||||
initialize: function(chart, datasetIndex) {
|
||||
Chart.DatasetController.prototype.initialize.call(this, chart, datasetIndex);
|
||||
@ -81,9 +85,12 @@ module.exports = function(Chart) {
|
||||
datasetLabel: dataset.label,
|
||||
|
||||
// Appearance
|
||||
median: reset ? scaleBase : me.medianValue(me.index, index),
|
||||
maxV: reset ? scaleBase : me.maxValue(me.index, index),
|
||||
minV: reset ? scaleBase : me.minValue(me.index, index),
|
||||
base: reset ? scaleBase : me.boxBottomValue(me.index, index),
|
||||
width: me.calculateBarWidth(ruler),
|
||||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
|
||||
backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.getValueAtIndexOrDefault(me.stddev(me.index, index) > 3 ? dataset.altBackgroundColor : dataset.backgroundColor, index, rectangleElementOptions.backgroundColor),
|
||||
borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleElementOptions.borderSkipped,
|
||||
borderColor: custom.borderColor ? custom.borderColor : helpers.getValueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor),
|
||||
borderWidth: custom.borderWidth ? custom.borderWidth : helpers.getValueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth)
|
||||
@ -92,6 +99,45 @@ module.exports = function(Chart) {
|
||||
rectangle.pivot();
|
||||
},
|
||||
|
||||
stddev: function(datasetIndex, index) {
|
||||
var me = this;
|
||||
var obj = me.getDataset().data[index];
|
||||
var value = Number(obj.stddev);
|
||||
|
||||
console.log('stddev >>', value);
|
||||
return value;
|
||||
},
|
||||
|
||||
minValue: function(datasetIndex, index) {
|
||||
var me = this;
|
||||
var meta = me.getMeta();
|
||||
var yScale = me.getScaleForId(meta.yAxisID);
|
||||
var obj = me.getDataset().data[index];
|
||||
var value = Number(obj.min);
|
||||
|
||||
return yScale.getPixelForValue(value);
|
||||
},
|
||||
|
||||
maxValue: function(datasetIndex, index) {
|
||||
var me = this;
|
||||
var meta = me.getMeta();
|
||||
var yScale = me.getScaleForId(meta.yAxisID);
|
||||
var obj = me.getDataset().data[index];
|
||||
var value = Number(obj.max);
|
||||
|
||||
return yScale.getPixelForValue(value);
|
||||
},
|
||||
|
||||
medianValue: function(datasetIndex, index) {
|
||||
var me = this;
|
||||
var meta = me.getMeta();
|
||||
var yScale = me.getScaleForId(meta.yAxisID);
|
||||
var obj = me.getDataset().data[index];
|
||||
var value = Number(obj.median);
|
||||
|
||||
return yScale.getPixelForValue(value);
|
||||
},
|
||||
|
||||
boxBottomValue: function(datasetIndex, index) {
|
||||
var me = this;
|
||||
var meta = me.getMeta();
|
||||
|
11
spikes/graphs-matrix/chartjs-whiskers/local.txt
Normal file
11
spikes/graphs-matrix/chartjs-whiskers/local.txt
Normal file
@ -0,0 +1,11 @@
|
||||
OldCpuSpeed=2712
|
||||
NewCpuSpeedCount=0
|
||||
NewCpuSpeed=0
|
||||
RollingAverage=1000
|
||||
RollingAverageIsFromV27=1
|
||||
ComputerGUID=7fe43060180dc17e1be44afd3c056d72
|
||||
CPUHours=1
|
||||
RollingStartTime=0
|
||||
Affinity=100
|
||||
ThreadsPerTest=4
|
||||
Pid=0
|
@ -15,7 +15,7 @@ const getCPU = (fn) => {
|
||||
};
|
||||
|
||||
const getPerc = (fn) => {
|
||||
async.timesSeries(10, (n, next) => {
|
||||
async.timesSeries(20, (n, next) => {
|
||||
osutils.cpuUsage((p) => {
|
||||
const percentage = p * 100;
|
||||
next(null, percentage);
|
||||
@ -27,7 +27,8 @@ const getPerc = (fn) => {
|
||||
median: statistics.median(sample),
|
||||
thirdQuartile: statistics.quantile(sample, 0.75),
|
||||
max: statistics.max(sample),
|
||||
min: statistics.min(sample)
|
||||
min: statistics.min(sample),
|
||||
stddev: statistics.sampleStandardDeviation(sample)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user