ml-gsd
Version:
Global Spectral Deconvolution
104 lines • 3.43 kB
JavaScript
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