class SavitzkyGolayFilter {
constructor(windowSize, polynomialOrder) {
this.windowSize = windowSize
this.polynomialOrder = polynomialOrder
this.data = []
this.coefficients = this.computeCoefficients()
}
computeCoefficients() {
const halfWindowSize = Math.floor(this.windowSize / 2)
const A = math.zeros(this.windowSize, this.polynomialOrder + 1)
for (let i = -halfWindowSize; i <= halfWindowSize; i++) {
for (let j = 0; j <= this.polynomialOrder; j++) {
A.set([i + halfWindowSize, j], Math.pow(i, j))
}
}
const ATA = math.multiply(math.transpose(A), A)
const ATA_inv = math.inv(ATA)
const ATA_inv_AT = math.multiply(ATA_inv, math.transpose(A))
return ATA_inv_AT
}
update(value) {
this.data.push(value);
if (this.data.length < this.windowSize) {
return null;
}
if (this.data.length > this.windowSize) {
this.data.shift();
}
const dataMatrix = math.transpose(math.matrix([this.data]));
const y = math.multiply(this.coefficients, dataMatrix);
return y.toArray()[0][0]
}
}