UNPKG

ml-gsd

Version:
104 lines 3.43 kB
import { sgg } from 'ml-savitzky-golay-generalized'; import { xIsEquallySpaced, xIsMonotonic, xMinMaxValues, xNoiseStandardDeviation, } from 'ml-spectra-processing'; import { autoAlgorithm } from "./algorithms/autoAlgorithm.js"; import { firstDerivative } from "./algorithms/firstDerivative.js"; import { secondDerivative } from "./algorithms/secondDerivative.js"; import { optimizeTop } from "./utils/optimizeTop.js"; /** * Global spectra deconvolution * @param data - Object data with x and y arrays. Values in x has to be growing * @param options * @param {number} [options.broadRatio = 0.00] - If `broadRatio` is higher than 0, then all the peaks which second derivative * smaller than `broadRatio * maxAbsSecondDerivative` will be marked with the soft mask equal to true. */ export function gsd(data, options = {}) { let { noiseLevel } = options; const { sgOptions = { windowSize: 9, polynomial: 3, }, smoothY = false, maxCriteria = true, minMaxRatio = 0.00025, realTopDetection = false, peakDetectionAlgorithm = 'second', } = options; const { x } = data; let { y } = data; if (xIsMonotonic(x) !== 1) { throw new Error('GSD only accepts monotone increasing x values'); } //rescale; y = y.slice(); // If the max difference between delta x is less than 5%, then, // we can assume it to be equally spaced variable const isEquallySpaced = xIsEquallySpaced(x); if (noiseLevel === undefined) { if (isEquallySpaced) { const noiseInfo = xNoiseStandardDeviation(y); if (maxCriteria) { noiseLevel = noiseInfo.median + 1.5 * noiseInfo.sd; } else { noiseLevel = -noiseInfo.median + 1.5 * noiseInfo.sd; } } else { noiseLevel = 0; } } else if (!maxCriteria) { noiseLevel *= -1; } if (!maxCriteria) { for (let i = 0; i < y.length; i++) { y[i] *= -1; } } if (noiseLevel !== undefined) { for (let i = 0; i < y.length; i++) { if (y[i] < noiseLevel) { y[i] = noiseLevel; } } } const xValue = isEquallySpaced ? x[1] - x[0] : x; const yData = smoothY ? sgg(y, xValue, { ...sgOptions, derivative: 0, }) : y; const { min: minY, max: maxY } = xMinMaxValues(yData); if (minY > maxY || minY === maxY) return []; const dY = sgg(y, xValue, { ...sgOptions, derivative: 1, }); const ddY = sgg(y, xValue, { ...sgOptions, derivative: 2, }); const yThreshold = minY + (maxY - minY) * minMaxRatio; const dX = x[1] - x[0]; const peakData = { x, y, yData, dY, ddY, dX, yThreshold }; let peaks = []; if (peakDetectionAlgorithm === 'first') { peaks = firstDerivative(peakData); } else if (peakDetectionAlgorithm === 'second') { peaks = secondDerivative(peakData); } else { peaks = autoAlgorithm(peakData); } if (realTopDetection) { optimizeTop({ x, y: yData }, peaks); } peaks.forEach((peak) => { if (!maxCriteria) { peak.y *= -1; peak.ddY = peak.ddY * -1; } }); peaks.sort((a, b) => { return a.x - b.x; }); return peaks; } //# sourceMappingURL=gsd.js.map