ml-savitzky-golay-generalized
Advanced tools
Comparing version 2.0.3 to 3.0.0
260
lib/index.js
@@ -1,140 +0,134 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const is_any_array_1 = require("is-any-array"); | ||
/** | ||
* Apply Savitzky Golay algorithm | ||
* @param {array} [ys] Array of y values | ||
* @param {array|number} [xs] Array of X or deltaX | ||
* @param {object} [options={}] | ||
* @param {number} [options.windowSize=9] | ||
* @param {number} [options.derivative=0] | ||
* @param {number} [options.polynomial=3] | ||
* @return {array} Array containing the new ys (same length) | ||
* @param [ys] Array of y values | ||
* @param [xs] Array of X or deltaX | ||
* @return Array containing the new ys (same length) | ||
*/ | ||
function SavitzkyGolay(ys, xs, options = {}) { | ||
let { windowSize = 9, derivative = 0, polynomial = 3 } = options; | ||
if (windowSize % 2 === 0 || windowSize < 5 || !Number.isInteger(windowSize)) { | ||
throw new RangeError( | ||
'Invalid window size (should be odd and at least 5 integer number)', | ||
); | ||
} | ||
if (windowSize > ys.length) { | ||
throw new RangeError( | ||
`Window size is higher than the data length ${windowSize}>${ys.length}`, | ||
); | ||
} | ||
if (derivative < 0 || !Number.isInteger(derivative)) { | ||
throw new RangeError('Derivative should be a positive integer'); | ||
} | ||
if (polynomial < 1 || !Number.isInteger(polynomial)) { | ||
throw new RangeError('Polynomial should be a positive integer'); | ||
} | ||
if (polynomial >= 6) { | ||
// eslint-disable-next-line no-console | ||
console.warn( | ||
'You should not use polynomial grade higher than 5 if you are' + | ||
' not sure that your data arises from such a model. Possible polynomial oscillation problems', | ||
); | ||
} | ||
let half = Math.floor(windowSize / 2); | ||
let np = ys.length; | ||
let ans = new Array(np); | ||
let weights = fullWeights(windowSize, polynomial, derivative); | ||
let hs = 0; | ||
let constantH = true; | ||
if (Array.isArray(xs)) { | ||
constantH = false; | ||
} else { | ||
hs = Math.pow(xs, derivative); | ||
} | ||
//For the borders | ||
for (let i = 0; i < half; i++) { | ||
let wg1 = weights[half - i - 1]; | ||
let wg2 = weights[half + i + 1]; | ||
let d1 = 0; | ||
let d2 = 0; | ||
for (let l = 0; l < windowSize; l++) { | ||
d1 += wg1[l] * ys[l]; | ||
d2 += wg2[l] * ys[np - windowSize + l]; | ||
let { windowSize = 9, derivative = 0, polynomial = 3 } = options; | ||
if (windowSize % 2 === 0 || windowSize < 5 || !Number.isInteger(windowSize)) { | ||
throw new RangeError('Invalid window size (should be odd and at least 5 integer number)'); | ||
} | ||
if (constantH) { | ||
ans[half - i - 1] = d1 / hs; | ||
ans[np - half + i] = d2 / hs; | ||
} else { | ||
hs = getHs(xs, half - i - 1, half, derivative); | ||
ans[half - i - 1] = d1 / hs; | ||
hs = getHs(xs, np - half + i, half, derivative); | ||
ans[np - half + i] = d2 / hs; | ||
if (!(0, is_any_array_1.isAnyArray)(ys)) { | ||
throw new TypeError('Y values must be an array'); | ||
} | ||
} | ||
//For the internal points | ||
let wg = weights[half]; | ||
for (let i = windowSize; i <= np; i++) { | ||
let d = 0; | ||
for (let l = 0; l < windowSize; l++) d += wg[l] * ys[l + i - windowSize]; | ||
if (!constantH) hs = getHs(xs, i - half - 1, half, derivative); | ||
ans[i - half - 1] = d / hs; | ||
} | ||
return ans; | ||
if (typeof xs === 'undefined') { | ||
throw new TypeError('X must be defined'); | ||
} | ||
if (windowSize > ys.length) { | ||
throw new RangeError(`Window size is higher than the data length ${windowSize}>${ys.length}`); | ||
} | ||
if (derivative < 0 || !Number.isInteger(derivative)) { | ||
throw new RangeError('Derivative should be a positive integer'); | ||
} | ||
if (polynomial < 1 || !Number.isInteger(polynomial)) { | ||
throw new RangeError('Polynomial should be a positive integer'); | ||
} | ||
if (polynomial >= 6) { | ||
// eslint-disable-next-line no-console | ||
console.warn('You should not use polynomial grade higher than 5 if you are' + | ||
' not sure that your data arises from such a model. Possible polynomial oscillation problems'); | ||
} | ||
let half = Math.floor(windowSize / 2); | ||
let np = ys.length; | ||
let ans = new Float64Array(np); | ||
let weights = fullWeights(windowSize, polynomial, derivative); | ||
let hs = 0; | ||
let constantH = true; | ||
if ((0, is_any_array_1.isAnyArray)(xs)) { | ||
constantH = false; | ||
} | ||
else { | ||
hs = Math.pow(xs, derivative); | ||
} | ||
//For the borders | ||
for (let i = 0; i < half; i++) { | ||
let wg1 = weights[half - i - 1]; | ||
let wg2 = weights[half + i + 1]; | ||
let d1 = 0; | ||
let d2 = 0; | ||
for (let l = 0; l < windowSize; l++) { | ||
d1 += wg1[l] * ys[l]; | ||
d2 += wg2[l] * ys[np - windowSize + l]; | ||
} | ||
if (constantH) { | ||
ans[half - i - 1] = d1 / hs; | ||
ans[np - half + i] = d2 / hs; | ||
} | ||
else { | ||
hs = getHs(xs, half - i - 1, half, derivative); | ||
ans[half - i - 1] = d1 / hs; | ||
hs = getHs(xs, np - half + i, half, derivative); | ||
ans[np - half + i] = d2 / hs; | ||
} | ||
} | ||
//For the internal points | ||
let wg = weights[half]; | ||
for (let i = windowSize; i <= np; i++) { | ||
let d = 0; | ||
for (let l = 0; l < windowSize; l++) | ||
d += wg[l] * ys[l + i - windowSize]; | ||
if (!constantH) { | ||
hs = getHs(xs, i - half - 1, half, derivative); | ||
} | ||
ans[i - half - 1] = d / hs; | ||
} | ||
return ans; | ||
} | ||
exports.default = SavitzkyGolay; | ||
function getHs(h, center, half, derivative) { | ||
let hs = 0; | ||
let count = 0; | ||
for (let i = center - half; i < center + half; i++) { | ||
if (i >= 0 && i < h.length - 1) { | ||
hs += h[i + 1] - h[i]; | ||
count++; | ||
let hs = 0; | ||
let count = 0; | ||
for (let i = center - half; i < center + half; i++) { | ||
if (i >= 0 && i < h.length - 1) { | ||
hs += h[i + 1] - h[i]; | ||
count++; | ||
} | ||
} | ||
} | ||
return Math.pow(hs / count, derivative); | ||
return Math.pow(hs / count, derivative); | ||
} | ||
function GramPoly(i, m, k, s) { | ||
let Grampoly = 0; | ||
if (k > 0) { | ||
Grampoly = | ||
((4 * k - 2) / (k * (2 * m - k + 1))) * | ||
(i * GramPoly(i, m, k - 1, s) + s * GramPoly(i, m, k - 1, s - 1)) - | ||
(((k - 1) * (2 * m + k)) / (k * (2 * m - k + 1))) * | ||
GramPoly(i, m, k - 2, s); | ||
} else { | ||
if (k === 0 && s === 0) { | ||
Grampoly = 1; | ||
} else { | ||
Grampoly = 0; | ||
function gramPoly(i, m, k, s) { | ||
let Grampoly = 0; | ||
if (k > 0) { | ||
Grampoly = | ||
((4 * k - 2) / (k * (2 * m - k + 1))) * | ||
(i * gramPoly(i, m, k - 1, s) + s * gramPoly(i, m, k - 1, s - 1)) - | ||
(((k - 1) * (2 * m + k)) / (k * (2 * m - k + 1))) * | ||
gramPoly(i, m, k - 2, s); | ||
} | ||
} | ||
return Grampoly; | ||
else { | ||
if (k === 0 && s === 0) { | ||
Grampoly = 1; | ||
} | ||
else { | ||
Grampoly = 0; | ||
} | ||
} | ||
return Grampoly; | ||
} | ||
function GenFact(a, b) { | ||
let gf = 1; | ||
if (a >= b) { | ||
for (let j = a - b + 1; j <= a; j++) { | ||
gf *= j; | ||
function genFact(a, b) { | ||
let gf = 1; | ||
if (a >= b) { | ||
for (let j = a - b + 1; j <= a; j++) { | ||
gf *= j; | ||
} | ||
} | ||
} | ||
return gf; | ||
return gf; | ||
} | ||
function Weight(i, t, m, n, s) { | ||
let sum = 0; | ||
for (let k = 0; k <= n; k++) { | ||
//console.log(k); | ||
sum += | ||
(2 * k + 1) * | ||
(GenFact(2 * m, k) / GenFact(2 * m + k + 1, k + 1)) * | ||
GramPoly(i, m, k, 0) * | ||
GramPoly(t, m, k, s); | ||
} | ||
return sum; | ||
function weight(i, t, m, n, s) { | ||
let sum = 0; | ||
for (let k = 0; k <= n; k++) { | ||
sum += | ||
(2 * k + 1) * | ||
(genFact(2 * m, k) / genFact(2 * m + k + 1, k + 1)) * | ||
gramPoly(i, m, k, 0) * | ||
gramPoly(t, m, k, s); | ||
} | ||
return sum; | ||
} | ||
/** | ||
* | ||
* @private | ||
* @param m Number of points | ||
@@ -145,13 +139,12 @@ * @param n Polynomial grade | ||
function fullWeights(m, n, s) { | ||
let weights = new Array(m); | ||
let np = Math.floor(m / 2); | ||
for (let t = -np; t <= np; t++) { | ||
weights[t + np] = new Array(m); | ||
for (let j = -np; j <= np; j++) { | ||
weights[t + np][j + np] = Weight(j, t, np, n, s); | ||
let weights = new Array(m); | ||
let np = Math.floor(m / 2); | ||
for (let t = -np; t <= np; t++) { | ||
weights[t + np] = new Float64Array(m); | ||
for (let j = -np; j <= np; j++) { | ||
weights[t + np][j + np] = weight(j, t, np, n, s); | ||
} | ||
} | ||
} | ||
return weights; | ||
return weights; | ||
} | ||
/*function entropy(data,h,options){ | ||
@@ -181,3 +174,2 @@ var trend = SavitzkyGolay(data,h,trendOptions); | ||
*/ | ||
module.exports = SavitzkyGolay; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "ml-savitzky-golay-generalized", | ||
"version": "2.0.3", | ||
"version": "3.0.0", | ||
"description": "Savitzky–Golay filter in Javascript", | ||
"main": "lib/index.js", | ||
"module": "src/index.js", | ||
"module": "lib-esm/index.js", | ||
"types": "lib/index.d.ts", | ||
"files": [ | ||
"lib", | ||
"src" | ||
"src", | ||
"lib-esm" | ||
], | ||
"scripts": { | ||
"check-types": "tsc --noEmit", | ||
"clean": "rimraf lib lib-esm", | ||
"eslint": "eslint src", | ||
"eslint-fix": "npm run eslint -- --fix", | ||
"prepublishOnly": "rollup -c", | ||
"test": "npm run test-coverage && npm run eslint", | ||
"prepack": "npm run tsc", | ||
"prettier": "prettier --check src", | ||
"prettier-write": "prettier --write src", | ||
"test": "npm run test-coverage && npm run eslint && npm run check-types", | ||
"test-coverage": "jest --coverage", | ||
"test-only": "jest" | ||
"test-only": "jest", | ||
"tsc": "npm run clean && npm run tsc-cjs && npm run tsc-esm", | ||
"tsc-cjs": "tsc --project tsconfig.cjs.json", | ||
"tsc-esm": "tsc --project tsconfig.esm.json" | ||
}, | ||
@@ -41,14 +50,18 @@ "repository": { | ||
"devDependencies": { | ||
"@babel/plugin-transform-modules-commonjs": "^7.9.0", | ||
"@types/jest": "^25.2.1", | ||
"eslint": "^6.8.0", | ||
"eslint-config-cheminfo": "^3.0.0", | ||
"eslint-plugin-import": "^2.20.2", | ||
"eslint-plugin-jest": "^23.8.2", | ||
"eslint-plugin-prettier": "^3.1.3", | ||
"jest": "^25.3.0", | ||
"prettier": "^2.0.4", | ||
"rollup": "^2.6.1" | ||
"@types/jest": "^27.0.2", | ||
"eslint": "^7.32.0", | ||
"eslint-config-cheminfo-typescript": "^9.0.0", | ||
"eslint-plugin-import": "^2.25.2", | ||
"eslint-plugin-jest": "^25.0.5", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"jest": "^27.2.5", | ||
"prettier": "^2.4.1", | ||
"rimraf": "^3.0.2", | ||
"ts-jest": "^27.0.5", | ||
"typescript": "^4.4.4" | ||
}, | ||
"dependencies": {} | ||
"dependencies": { | ||
"cheminfo-types": "^0.9.1", | ||
"is-any-array": "^2.0.0" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
34679
12
561
2
11
2
+ Addedcheminfo-types@^0.9.1
+ Addedis-any-array@^2.0.0
+ Addedcheminfo-types@0.9.1(transitive)
+ Addedis-any-array@2.0.1(transitive)