Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

d2-charts-api

Package Overview
Dependencies
Maintainers
1
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

d2-charts-api - npm Package Compare versions

Comparing version 27.0.9 to 27.0.10

504

lib/config/adapters/dhis_highcharts/addTrendLines.js

@@ -6,25 +6,20 @@ 'use strict';

});
exports.REGRESSION_TYPE_LINEAR = undefined;
exports.default = function (series, isStacked) {
exports.default = function (regressionType, series, isStacked) {
var newSeries = [];
if (isStacked) {
return [].concat(_toConsumableArray(series), [Object.assign({}, DEFAULT_TRENDLINE, {
data: getRegressionData((0, _getStackedData2.default)(series, true))
})]);
newSeries.push.apply(newSeries, _toConsumableArray(series).concat([Object.assign({}, getRegressionObj((0, _getStackedData2.default)(series), regressionType))]));
} else {
var newSeries = [];
series.forEach(function (seriesObj) {
newSeries.push(seriesObj, Object.assign({}, DEFAULT_TRENDLINE, {
color: getDarkerColor(seriesObj.color),
data: getRegressionData(seriesObj.data)
newSeries.push(seriesObj, Object.assign({}, getRegressionObj(seriesObj.data, regressionType), {
name: seriesObj.name + ' (trend)',
color: getDarkerColor(seriesObj.color)
}));
});
}
return newSeries;
}
return newSeries;
};
var _jqplot_regression = require('../../../util/regression/jqplot_regression');
var _d3Color = require('d3-color');

@@ -40,6 +35,4 @@

var REGRESSION_TYPE_LINEAR = exports.REGRESSION_TYPE_LINEAR = 'LINEAR';
var DEFAULT_TRENDLINE = {
type: 'line',
type: 'spline',
name: 'Trend',

@@ -50,2 +43,3 @@ dashStyle: 'solid',

marker: {
enabled: false,
symbol: 'circle',

@@ -56,24 +50,476 @@ radius: 2

function getAdaptedRegressionData(data) {
return data.map(function (array) {
return array[1];
function getColor(colors, index) {
return colors[index] || getColor(colors, index - colors.length);
}
function getDarkerColor(color) {
return (0, _d3Color.rgb)(color).darker(0.5).toString();
}
function getRegressionData(data) {
return data.map(function (value, index) {
return [index, value];
});
}
function getRegressionData(data, isClean) {
var adaptedRegressionData = getAdaptedRegressionData((0, _jqplot_regression.fitData)(data).data);
var i = 0;
function getRegressionObj(data, regressionType) {
// LINEAR:
// - decimalPlaces (default = 2)
// LOESS:
// - loessSmooth (default = 25)
// POLYNOMIAL:
// - order (default = 2)
// - extrapolate (default = 0)
return isClean ? adaptedRegressionData : data.map(function (value, index) {
return value === null ? value : adaptedRegressionData[i++];
var regression = void 0;
var regressionTypeOptions = {};
switch (regressionType) {
case 'LINEAR':
// linear(data, decimalPlaces)
regression = linear(getRegressionData(data));
regressionTypeOptions.type = 'line';
break;
case 'POLYNOMIAL':
// polynomial(data, order, extrapolate)
regression = polynomial(getRegressionData(data), 2, 0);
break;
case 'LOESS':
// loess(data, smoothing)
regression = loess(getRegressionData(data), 0.25);
break;
};
return Object.assign({}, DEFAULT_TRENDLINE, regressionTypeOptions, {
data: regression.points
});
}
function getColor(colors, index) {
return colors[index] || getColor(colors, index - colors.length);
// Code extracted from https://github.com/Tom-Alexander/regression-js/
function gaussianElimination(a, o) {
var maxrow = 0,
tmp = 0,
n = a.length - 1,
x = new Array(o);
for (var i = 0; i < n; i++) {
maxrow = i;
for (var j = i + 1; j < n; j++) {
if (Math.abs(a[i][j]) > Math.abs(a[i][maxrow])) {
maxrow = j;
}
}
for (var k = i; k < n + 1; k++) {
tmp = a[k][i];
a[k][i] = a[k][maxrow];
a[k][maxrow] = tmp;
}
for (var _j = i + 1; _j < n; _j++) {
for (var _k = n; _k >= i; _k--) {
a[_k][_j] -= a[_k][i] * a[i][_j] / a[i][i];
}
}
}
for (var _j2 = n - 1; _j2 >= 0; _j2--) {
tmp = 0;
for (var _k2 = _j2 + 1; _k2 < n; _k2++) {
tmp += a[_k2][_j2] * x[_k2];
}
x[_j2] = (a[n][_j2] - tmp) / a[_j2][_j2];
}
return x;
}
function getDarkerColor(color) {
return (0, _d3Color.rgb)(color).darker(0.5).toString();
// Code extracted from https://github.com/Tom-Alexander/regression-js/
// Human readable formulas:
//
// N * Σ(XY) - Σ(X)
// intercept = ---------------------
// N * Σ(X^2) - Σ(X)^2
//
// correlation = N * Σ(XY) - Σ(X) * Σ (Y) / √ ( N * Σ(X^2) - Σ(X) ) * ( N * Σ(Y^2) - Σ(Y)^2 ) ) )
function linear(data, decimalPlaces) {
var sum = [0, 0, 0, 0, 0],
results = [],
N = data.length;
for (var _n = 0, len = data.length; _n < len; _n++) {
if (data[_n]['x'] != null) {
data[_n][0] = data[_n].x;
data[_n][1] = data[_n].y;
}
if (data[_n][1] != null) {
sum[0] += data[_n][0]; // Σ(X)
sum[1] += data[_n][1]; // Σ(Y)
sum[2] += data[_n][0] * data[_n][0]; // Σ(X^2)
sum[3] += data[_n][0] * data[_n][1]; // Σ(XY)
sum[4] += data[_n][1] * data[_n][1]; // Σ(Y^2)
} else {
N -= 1;
}
}
var gradient = (N * sum[3] - sum[0] * sum[1]) / (N * sum[2] - sum[0] * sum[0]);
var intercept = sum[1] / N - gradient * sum[0] / N;
// let correlation = (N * sum[3] - sum[0] * sum[1]) / Math.sqrt((N * sum[2] - sum[0] * sum[0]) * (N * sum[4] - sum[1] * sum[1]));
for (var i = 0, _len = data.length; i < _len; i++) {
var coorY = data[i][0] * gradient + intercept;
if (decimalPlaces) {
coorY = parseFloat(coorY.toFixed(decimalPlaces));
}
var coordinate = [data[i][0], coorY];
results.push(coordinate);
}
results.sort(function (a, b) {
if (a[0] > b[0]) {
return 1;
}
if (a[0] < b[0]) {
return -1;
}
return 0;
});
var string = 'y = ' + Math.round(gradient * 100) / 100 + 'x + ' + Math.round(intercept * 100) / 100;
return {
equation: [gradient, intercept],
points: results,
string: string
};
}
// Code extracted from https://github.com/Tom-Alexander/regression-js/
function logarithmic(data) {
var sum = [0, 0, 0, 0],
results = [],
mean = 0;
for (var _n2 = 0, len = data.length; _n2 < len; _n2++) {
if (data[_n2].x != null) {
data[_n2][0] = data[_n2].x;
data[_n2][1] = data[_n2].y;
}
if (data[_n2][1] != null) {
sum[0] += Math.log(data[_n2][0]);
sum[1] += data[_n2][1] * Math.log(data[_n2][0]);
sum[2] += data[_n2][1];
sum[3] += Math.pow(Math.log(data[_n2][0]), 2);
}
}
var B = (n * sum[1] - sum[2] * sum[0]) / (n * sum[3] - sum[0] * sum[0]);
var A = (sum[2] - B * sum[0]) / n;
for (var i = 0, _len2 = data.length; i < _len2; i++) {
var coordinate = [data[i][0], A + B * Math.log(data[i][0])];
results.push(coordinate);
}
results.sort(function (a, b) {
if (a[0] > b[0]) {
return 1;
}
if (a[0] < b[0]) {
return -1;
}
return 0;
});
var string = 'y = ' + Math.round(A * 100) / 100 + ' + ' + Math.round(B * 100) / 100 + ' ln(x)';
return {
equation: [A, B],
points: results,
string: string
};
}
// Code extracted from https://github.com/Tom-Alexander/regression-js/
function power(data) {
var sum = [0, 0, 0, 0],
results = [];
for (var _n3 = 0, len = data.length; _n3 < len; _n3++) {
if (data[_n3].x != null) {
data[_n3][0] = data[_n3].x;
data[_n3][1] = data[_n3].y;
}
if (data[_n3][1] != null) {
sum[0] += Math.log(data[_n3][0]);
sum[1] += Math.log(data[_n3][1]) * Math.log(data[_n3][0]);
sum[2] += Math.log(data[_n3][1]);
sum[3] += Math.pow(Math.log(data[_n3][0]), 2);
}
}
var B = (n * sum[1] - sum[2] * sum[0]) / (n * sum[3] - sum[0] * sum[0]);
var A = Math.pow(Math.E, (sum[2] - B * sum[0]) / n);
for (var i = 0, _len3 = data.length; i < _len3; i++) {
var coordinate = [data[i][0], A * Math.pow(data[i][0], B)];
results.push(coordinate);
}
results.sort(function (a, b) {
if (a[0] > b[0]) {
return 1;
}
if (a[0] < b[0]) {
return -1;
}
return 0;
});
var string = 'y = ' + Math.round(A * 100) / 100 + 'x^' + Math.round(B * 100) / 100;
return {
equation: [A, B],
points: results,
string: string
};
}
// Code extracted from https://github.com/Tom-Alexander/regression-js/
function polynomial(data, order, extrapolate) {
if (typeof order == 'undefined') {
order = 2;
}
var lhs = [],
rhs = [],
results = [],
a = 0,
b = 0,
k = order + 1;
for (var i = 0; i < k; i++) {
for (var l = 0, len = data.length; l < len; l++) {
if (data[l].x != null) {
data[l][0] = data[l].x;
data[l][1] = data[l].y;
}
if (data[l][1] != null) {
a += Math.pow(data[l][0], i) * data[l][1];
}
}
lhs.push(a);
a = 0;
var c = [];
for (var j = 0; j < k; j++) {
for (var _l = 0, _len4 = data.length; _l < _len4; _l++) {
if (data[_l][1]) {
b += Math.pow(data[_l][0], i + j);
}
}
c.push(b);
b = 0;
}
rhs.push(c);
}
rhs.push(lhs);
var equation = gaussianElimination(rhs, k);
var resultLength = data.length + extrapolate;
var step = data[data.length - 1][0] - data[data.length - 2][0];
for (var _i = 0, _len5 = resultLength; _i < _len5; _i++) {
var answer = 0,
x = 0;
if (typeof data[_i] !== 'undefined') {
x = data[_i][0];
} else {
x = data[data.length - 1][0] + (_i - data.length) * step;
}
for (var w = 0; w < equation.length; w++) {
answer += equation[w] * Math.pow(x, w);
}
results.push([x, answer]);
}
results.sort(function (a, b) {
if (a[0] > b[0]) {
return 1;
}
if (a[0] < b[0]) {
return -1;
}
return 0;
});
var string = 'y = ';
for (var _i2 = equation.length - 1; _i2 >= 0; _i2--) {
if (_i2 > 1) {
string += Math.round(equation[_i2] * 100) / 100 + 'x^' + _i2 + ' + ';
} else if (_i2 == 1) {
string += Math.round(equation[_i2] * 100) / 100 + 'x' + ' + ';
} else {
string += Math.round(equation[_i2] * 100) / 100;
}
}
return {
equation: equation,
points: results,
string: string
};
}
// @author: Ignacio Vazquez
// Based on
// - http://commons.apache.org/proper/commons-math/download_math.cgi LoesInterpolator.java
// - https://gist.github.com/avibryant/1151823
function loess(data, bandwidth) {
bandwidth = bandwidth || 0.25;
var xval = data.map(function (pair) {
return pair[0];
});
var distinctX = array_unique(xval);
if (2 / distinctX.length > bandwidth) {
bandwidth = Math.min(2 / distinctX.length, 1);
console.warn("updated bandwith to " + bandwidth);
}
var yval = data.map(function (pair) {
return pair[1];
});
function array_unique(values) {
var o = {},
i = void 0,
l = values.length,
r = [];
for (i = 0; i < l; i += 1) {
o[values[i]] = values[i];
}
for (i in o) {
r.push(o[i]);
}
return r;
}
function tricube(x) {
var tmp = 1 - x * x * x;
return tmp * tmp * tmp;
}
var res = [];
var left = 0;
var right = Math.floor(bandwidth * xval.length) - 1;
for (var i in xval) {
var x = xval[i];
if (i > 0) {
if (right < xval.length - 1 && xval[right + 1] - xval[i] < xval[i] - xval[left]) {
left++;
right++;
}
}
//console.debug("left: "+left + " right: " + right );
var edge = void 0;
if (xval[i] - xval[left] > xval[right] - xval[i]) {
edge = left;
} else {
edge = right;
}
var denom = Math.abs(1.0 / (xval[edge] - x));
var sumWeights = 0;
var sumX = 0,
sumXSquared = 0,
sumY = 0,
sumXY = 0;
var k = left;
while (k <= right) {
var xk = xval[k];
var yk = yval[k];
var dist = void 0;
if (k < i) {
dist = x - xk;
} else {
dist = xk - x;
}
var w = tricube(dist * denom);
var xkw = xk * w;
sumWeights += w;
sumX += xkw;
sumXSquared += xk * xkw;
sumY += yk * w;
sumXY += yk * xkw;
k++;
}
var meanX = sumX / sumWeights;
//console.debug(meanX);
var meanY = sumY / sumWeights;
var meanXY = sumXY / sumWeights;
var meanXSquared = sumXSquared / sumWeights;
var beta = void 0;
if (meanXSquared == meanX * meanX) {
beta = 0;
} else {
beta = (meanXY - meanX * meanY) / (meanXSquared - meanX * meanX);
}
var alpha = meanY - beta * meanX;
res[i] = beta * x + alpha;
}
//console.debug(res);
return {
equation: "",
points: xval.map(function (x, i) {
return [x, res[i]];
}),
string: ""
};
}
//# sourceMappingURL=addTrendLines.js.map

5

lib/config/adapters/dhis_highcharts/index.js

@@ -74,4 +74,5 @@ 'use strict';

// DHIS2-1243 add trend lines after sorting
if (layout.regressionType === _addTrendLines.REGRESSION_TYPE_LINEAR) {
config.series = (0, _addTrendLines2.default)(config.series, isStacked);
// trend line on pie and gauge does not make sense
if (layout.type !== CHART_TYPE_GAUGE && layout.type !== CHART_TYPE_PIE && layout.regressionType !== 'NONE') {
config.series = (0, _addTrendLines2.default)(layout.regressionType, config.series, isStacked);
}

@@ -78,0 +79,0 @@

{
"name": "d2-charts-api",
"version": "27.0.9",
"version": "27.0.10",
"description": "DHIS2 charts api",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -1,9 +0,6 @@

import { fitData } from '../../../util/regression/jqplot_regression';
import { rgb } from 'd3-color';
import getStackedData from './getStackedData';
export const REGRESSION_TYPE_LINEAR = 'LINEAR';
const DEFAULT_TRENDLINE = {
type: 'line',
type: 'spline',
name: 'Trend',

@@ -14,2 +11,3 @@ dashStyle: 'solid',

marker: {
enabled: false,
symbol: 'circle',

@@ -20,11 +18,31 @@ radius: 2

function getAdaptedRegressionData(data) {
return data.map(array => array[1]);
}
export default function (regressionType, series, isStacked) {
const newSeries = [];
function getRegressionData(data, isClean) {
const adaptedRegressionData = getAdaptedRegressionData(fitData(data).data);
let i = 0;
if (isStacked) {
newSeries.push(
...series,
Object.assign(
{},
getRegressionObj(getStackedData(series), regressionType),
)
);
}
else {
series.forEach(seriesObj => {
newSeries.push(
seriesObj,
Object.assign(
{},
getRegressionObj(seriesObj.data, regressionType),
{
name: seriesObj.name + ' (trend)',
color: getDarkerColor(seriesObj.color),
}
)
);
});
}
return isClean ? adaptedRegressionData : data.map((value, index) => value === null ? value : adaptedRegressionData[i++]);
return newSeries;
}

@@ -40,23 +58,435 @@

export default function (series, isStacked) {
if (isStacked) {
return [
...series,
Object.assign({}, DEFAULT_TRENDLINE, {
data: getRegressionData(getStackedData(series, true))
})
];
function getRegressionData(data) {
return data.map((value, index) => {
return [index, value];
});
}
function getRegressionObj(data, regressionType) {
// LINEAR:
// - decimalPlaces (default = 2)
// LOESS:
// - loessSmooth (default = 25)
// POLYNOMIAL:
// - order (default = 2)
// - extrapolate (default = 0)
let regression;
let regressionTypeOptions = {};
switch (regressionType) {
case 'LINEAR':
// linear(data, decimalPlaces)
regression = linear(getRegressionData(data));
regressionTypeOptions.type = 'line';
break;
case 'POLYNOMIAL':
// polynomial(data, order, extrapolate)
regression = polynomial(getRegressionData(data), 2, 0);
break;
case 'LOESS':
// loess(data, smoothing)
regression = loess(getRegressionData(data), 0.25);
break;
};
return Object.assign(
{},
DEFAULT_TRENDLINE,
regressionTypeOptions,
{
data: regression.points
}
);
}
// Code extracted from https://github.com/Tom-Alexander/regression-js/
function gaussianElimination(a, o) {
let maxrow = 0, tmp = 0, n = a.length - 1, x = new Array(o);
for (let i = 0; i < n; i++) {
maxrow = i;
for (let j = i + 1; j < n; j++) {
if (Math.abs(a[i][j]) > Math.abs(a[i][maxrow])) {
maxrow = j;
}
}
for (let k = i; k < n + 1; k++) {
tmp = a[k][i];
a[k][i] = a[k][maxrow];
a[k][maxrow] = tmp;
}
for (let j = i + 1; j < n; j++) {
for (let k = n; k >= i; k--) {
a[k][j] -= a[k][i] * a[i][j] / a[i][i];
}
}
}
else {
const newSeries = [];
series.forEach(seriesObj => {
newSeries.push(seriesObj, Object.assign({}, DEFAULT_TRENDLINE, {
color: getDarkerColor(seriesObj.color),
data: getRegressionData(seriesObj.data)
}));
});
for (let j = n - 1; j >= 0; j--) {
tmp = 0;
return newSeries;
for (let k = j + 1; k < n; k++) {
tmp += a[k][j] * x[k];
}
x[j] = (a[n][j] - tmp) / a[j][j];
}
return (x);
}
// Code extracted from https://github.com/Tom-Alexander/regression-js/
// Human readable formulas:
//
// N * Σ(XY) - Σ(X)
// intercept = ---------------------
// N * Σ(X^2) - Σ(X)^2
//
// correlation = N * Σ(XY) - Σ(X) * Σ (Y) / √ ( N * Σ(X^2) - Σ(X) ) * ( N * Σ(Y^2) - Σ(Y)^2 ) ) )
function linear(data, decimalPlaces) {
let sum = [0, 0, 0, 0, 0], results = [], N = data.length;
for (let n = 0, len = data.length; n < len; n++) {
if (data[n]['x'] != null) {
data[n][0] = data[n].x;
data[n][1] = data[n].y;
}
if (data[n][1] != null) {
sum[0] += data[n][0]; // Σ(X)
sum[1] += data[n][1]; // Σ(Y)
sum[2] += data[n][0] * data[n][0]; // Σ(X^2)
sum[3] += data[n][0] * data[n][1]; // Σ(XY)
sum[4] += data[n][1] * data[n][1]; // Σ(Y^2)
} else {
N -= 1;
}
}
let gradient = (N * sum[3] - sum[0] * sum[1]) / (N * sum[2] - sum[0] * sum[0]);
let intercept = (sum[1] / N) - (gradient * sum[0]) / N;
// let correlation = (N * sum[3] - sum[0] * sum[1]) / Math.sqrt((N * sum[2] - sum[0] * sum[0]) * (N * sum[4] - sum[1] * sum[1]));
for (let i = 0, len = data.length; i < len; i++) {
let coorY = data[i][0] * gradient + intercept;
if (decimalPlaces) {
coorY = parseFloat(coorY.toFixed(decimalPlaces));
}
let coordinate = [data[i][0], coorY];
results.push(coordinate);
}
results.sort((a, b) => {
if (a[0] > b[0]) { return 1; }
if (a[0] < b[0]) { return -1; }
return 0;
});
let string = 'y = ' + Math.round(gradient * 100) / 100 + 'x + ' + Math.round(intercept * 100) / 100;
return {
equation: [gradient, intercept],
points: results,
string: string
};
}
// Code extracted from https://github.com/Tom-Alexander/regression-js/
function logarithmic(data) {
let sum = [0, 0, 0, 0], results = [], mean = 0;
for (let n = 0, len = data.length; n < len; n++) {
if (data[n].x != null) {
data[n][0] = data[n].x;
data[n][1] = data[n].y;
}
if (data[n][1] != null) {
sum[0] += Math.log(data[n][0]);
sum[1] += data[n][1] * Math.log(data[n][0]);
sum[2] += data[n][1];
sum[3] += Math.pow(Math.log(data[n][0]), 2);
}
}
let B = (n * sum[1] - sum[2] * sum[0]) / (n * sum[3] - sum[0] * sum[0]);
let A = (sum[2] - B * sum[0]) / n;
for (let i = 0, len = data.length; i < len; i++) {
let coordinate = [data[i][0], A + B * Math.log(data[i][0])];
results.push(coordinate);
}
results.sort((a, b) => {
if (a[0] > b[0]) { return 1; }
if (a[0] < b[0]) { return -1; }
return 0;
});
let string = 'y = ' + Math.round(A * 100) / 100 + ' + ' + Math.round(B * 100) / 100 + ' ln(x)';
return {
equation: [A, B],
points: results,
string: string
};
}
// Code extracted from https://github.com/Tom-Alexander/regression-js/
function power(data) {
let sum = [0, 0, 0, 0], results = [];
for (let n = 0, len = data.length; n < len; n++) {
if (data[n].x != null) {
data[n][0] = data[n].x;
data[n][1] = data[n].y;
}
if (data[n][1] != null) {
sum[0] += Math.log(data[n][0]);
sum[1] += Math.log(data[n][1]) * Math.log(data[n][0]);
sum[2] += Math.log(data[n][1]);
sum[3] += Math.pow(Math.log(data[n][0]), 2);
}
}
let B = (n * sum[1] - sum[2] * sum[0]) / (n * sum[3] - sum[0] * sum[0]);
let A = Math.pow(Math.E, (sum[2] - B * sum[0]) / n);
for (let i = 0, len = data.length; i < len; i++) {
let coordinate = [data[i][0], A * Math.pow(data[i][0] , B)];
results.push(coordinate);
}
results.sort((a,b) => {
if (a[0] > b[0]) { return 1; }
if (a[0] < b[0]) { return -1; }
return 0;
});
let string = 'y = ' + Math.round(A * 100) / 100 + 'x^' + Math.round(B * 100) / 100;
return {
equation: [A, B],
points: results,
string: string
};
}
// Code extracted from https://github.com/Tom-Alexander/regression-js/
function polynomial(data, order, extrapolate) {
if (typeof order == 'undefined') {
order = 2;
}
let lhs = [], rhs = [], results = [], a = 0, b = 0, k = order + 1;
for (let i = 0; i < k; i++) {
for (let l = 0, len = data.length; l < len; l++) {
if (data[l].x != null) {
data[l][0] = data[l].x;
data[l][1] = data[l].y;
}
if (data[l][1] != null) {
a += Math.pow(data[l][0], i) * data[l][1];
}
}
lhs.push(a);
a = 0;
let c = [];
for (let j = 0; j < k; j++) {
for (let l = 0, len = data.length; l < len; l++) {
if (data[l][1]) {
b += Math.pow(data[l][0], i + j);
}
}
c.push(b);
b = 0;
}
rhs.push(c);
}
rhs.push(lhs);
let equation = gaussianElimination(rhs, k);
let resultLength = data.length + extrapolate;
let step = data[data.length - 1][0] - data[data.length - 2][0];
for (let i = 0, len = resultLength; i < len; i++) {
let answer = 0, x = 0;
if (typeof data[i] !== 'undefined') {
x = data[i][0];
} else {
x = data[data.length - 1][0] + (i - data.length) * step;
}
for (let w = 0; w < equation.length; w++) {
answer += equation[w] * Math.pow(x, w);
}
results.push([x, answer]);
}
results.sort((a,b) => {
if (a[0] > b[0]) { return 1; }
if (a[0] < b[0]) { return -1; }
return 0;
});
let string = 'y = ';
for (let i = equation.length-1; i >= 0; i--) {
if (i > 1) {
string += Math.round(equation[i] * 100) / 100 + 'x^' + i + ' + ';
}
else if (i == 1) {
string += Math.round(equation[i] * 100) / 100 + 'x' + ' + ';
}
else {
string += Math.round(equation[i] * 100) / 100;
}
}
return {
equation: equation,
points: results,
string: string
};
}
// @author: Ignacio Vazquez
// Based on
// - http://commons.apache.org/proper/commons-math/download_math.cgi LoesInterpolator.java
// - https://gist.github.com/avibryant/1151823
function loess(data, bandwidth) {
bandwidth = bandwidth || 0.25 ;
let xval = data.map(pair => { return pair[0]; });
let distinctX = array_unique(xval);
if (2 / distinctX.length > bandwidth) {
bandwidth = Math.min(2 / distinctX.length, 1);
console.warn("updated bandwith to " + bandwidth);
}
let yval = data.map(pair => { return pair[1]; });
function array_unique(values) {
let o = {}, i, l = values.length, r = [];
for (i = 0; i < l; i += 1) {
o[values[i]] = values[i];
}
for (i in o) {
r.push(o[i]);
}
return r;
}
function tricube(x) {
let tmp = 1 - x * x * x;
return tmp * tmp * tmp;
}
let res = [];
let left = 0;
let right = Math.floor(bandwidth * xval.length) - 1;
for (let i in xval) {
let x = xval[i];
if (i > 0) {
if (right < xval.length - 1 &&
xval[right+1] - xval[i] < xval[i] - xval[left]) {
left++;
right++;
}
}
//console.debug("left: "+left + " right: " + right );
let edge;
if (xval[i] - xval[left] > xval[right] - xval[i]) {
edge = left;
}
else {
edge = right;
}
let denom = Math.abs(1.0 / (xval[edge] - x));
let sumWeights = 0;
let sumX = 0, sumXSquared = 0, sumY = 0, sumXY = 0;
let k = left;
while (k <= right) {
let xk = xval[k];
let yk = yval[k];
let dist;
if (k < i) {
dist = (x - xk);
} else {
dist = (xk - x);
}
let w = tricube(dist * denom);
let xkw = xk * w;
sumWeights += w;
sumX += xkw;
sumXSquared += xk * xkw;
sumY += yk * w;
sumXY += yk * xkw;
k++;
}
let meanX = sumX / sumWeights;
//console.debug(meanX);
let meanY = sumY / sumWeights;
let meanXY = sumXY / sumWeights;
let meanXSquared = sumXSquared / sumWeights;
let beta;
if (meanXSquared == meanX * meanX) {
beta = 0;
}
else {
beta = (meanXY - meanX * meanY) / (meanXSquared - meanX * meanX);
}
let alpha = meanY - beta * meanX;
res[i] = beta * x + alpha;
}
//console.debug(res);
return {
equation: "" ,
points: xval.map((x,i) => { return [x, res[i]]; }),
string: ""
};
}

@@ -14,3 +14,3 @@ import objectClean from 'd2-utilizr/lib/objectClean';

import getTrimmedConfig from './getTrimmedConfig';
import addTrendLines, { REGRESSION_TYPE_LINEAR } from './addTrendLines';
import addTrendLines from './addTrendLines';

@@ -80,4 +80,5 @@ export const CHART_TYPE_PIE = 'pie';

// DHIS2-1243 add trend lines after sorting
if (layout.regressionType === REGRESSION_TYPE_LINEAR) {
config.series = addTrendLines(config.series, isStacked);
// trend line on pie and gauge does not make sense
if (layout.type !== CHART_TYPE_GAUGE && layout.type !== CHART_TYPE_PIE && layout.regressionType !== 'NONE') {
config.series = addTrendLines(layout.regressionType, config.series, isStacked);
}

@@ -84,0 +85,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc