server update, add endpoints

server update (server_convolution.ts)
add endpoints of peaks detection, valleys detection, vertices (including peaks and valleys) detection, outliers detection
This commit is contained in:
raymond 2025-09-10 04:09:20 +00:00
parent 4cd58e04d4
commit e8e0e6de2a
3 changed files with 1932 additions and 175 deletions

View file

@ -99,6 +99,9 @@ function applyBoundary1D(signal: number[], padding: number, boundary: string): n
* @param options - Convolution options (mode, boundary)
* @returns Convolution result with metadata
*/
/**
* [CORRECTED] Performs 1D convolution between signal and kernel
*/
export function convolve1D(
signal: number[],
kernel: number[],
@ -107,40 +110,54 @@ export function convolve1D(
validateArray(signal, 'Signal');
validateArray(kernel, 'Kernel');
const { mode = 'same', boundary = 'reflect' } = options;
// Flip kernel for convolution (not correlation)
const { mode = 'full', boundary = 'zero' } = options;
const flippedKernel = [...kernel].reverse();
const signalLen = signal.length;
const kernelLen = flippedKernel.length;
let result: number[] = [];
let paddedSignal = signal;
// Apply boundary conditions based on mode
if (mode === 'same' || mode === 'full') {
const padding = mode === 'same' ? Math.floor(kernelLen / 2) : kernelLen - 1;
paddedSignal = applyBoundary1D(signal, padding, boundary);
}
// Perform convolution
const outputLength = mode === 'full' ? signalLen + kernelLen - 1 :
mode === 'same' ? signalLen :
signalLen - kernelLen + 1;
const result: number[] = new Array(outputLength);
const startIdx = mode === 'valid' ? 0 :
mode === 'same' ? Math.floor(kernelLen / 2) : 0;
const halfKernelLen = Math.floor(kernelLen / 2);
for (let i = 0; i < outputLength; i++) {
let sum = 0;
for (let j = 0; j < kernelLen; j++) {
const signalIdx = startIdx + i + j;
if (signalIdx >= 0 && signalIdx < paddedSignal.length) {
sum += paddedSignal[signalIdx] * flippedKernel[j];
let signalIdx: number;
switch (mode) {
case 'full':
signalIdx = i - j;
break;
case 'same':
signalIdx = i - halfKernelLen + j;
break;
case 'valid':
signalIdx = i + j;
break;
}
// Handle boundary conditions
if (signalIdx >= 0 && signalIdx < signalLen) {
sum += signal[signalIdx] * flippedKernel[j];
} else if (boundary !== 'zero' && (mode === 'full' || mode === 'same')) {
// This is a simplified boundary handler for the logic. Your more complex handler can be used here.
let boundaryIdx = signalIdx;
if (signalIdx < 0) {
boundaryIdx = boundary === 'reflect' ? -signalIdx -1 : -signalIdx;
} else if (signalIdx >= signalLen) {
boundaryIdx = boundary === 'reflect' ? 2 * signalLen - signalIdx - 1 : 2 * signalLen - signalIdx - 2;
}
boundaryIdx = Math.max(0, Math.min(signalLen - 1, boundaryIdx));
sum += signal[boundaryIdx] * flippedKernel[j];
}
// If boundary is 'zero', we add nothing, which is correct.
}
result.push(sum);
result[i] = sum;
}
return {