kde.js (1505B)
1 import { nrd0 } from "./bandwidth.js"; 2 export const kde = ({ samples, outputLength, weight, kernelWidth, }) => { 3 let xWidth = kernelWidth ?? nrd0(samples); 4 samples = samples.filter((v) => Number.isFinite(v)); 5 const len = samples.length; 6 if (len === 0 || xWidth === 0) 7 return { usedWidth: xWidth, xs: [], ys: [] }; 8 const smin = samples[0]; 9 const srange = samples[len - 1] - smin; 10 const wantedWidth = ((outputLength - 1) * xWidth) / (srange + 2 * xWidth); 11 const width = Math.max(1, Math.floor(wantedWidth)); 12 const stepsInside = outputLength - 1 - 2 * width; 13 const dx = srange / stepsInside; 14 xWidth = width * dx; 15 const min = smin - xWidth; 16 const ysum = Array(outputLength + 2 * width).fill(0); 17 const dxInv = 1 / dx; 18 samples.forEach((x) => { 19 const off = x - min; 20 const index = Math.floor(off * dxInv); 21 const leftWeight = off - index * dx; 22 const rightWeight = dx - leftWeight; 23 ysum[width + index + 1] += rightWeight; 24 ysum[width + index + 2] += leftWeight; 25 }); 26 const normalizer = weight / (xWidth * xWidth); 27 const xs = Array(outputLength) 28 .fill(0) 29 .map((_, i) => min + i * dx); 30 let dy = 0; 31 let y = 0; 32 const ys = xs.map((_, i) => { 33 const ddy = ysum[i] - 2 * ysum[i + width] + ysum[i + 2 * width]; 34 dy += ddy; 35 y += dy; 36 return normalizer * y; 37 }); 38 return { usedWidth: xWidth, xs, ys }; 39 }; 40 //# sourceMappingURL=kde.js.map