ml-spectra-fitting
Version:
Fit spectra using gaussian or lorentzian
70 lines • 3.13 kB
JavaScript
import { xMinMaxValues } from 'ml-spectra-processing';
import { getSumOfShapes } from "./shapes/getSumOfShapes.js";
import { getInternalPeaks } from "./util/internalPeaks/getInternalPeaks.js";
import { selectMethod } from "./util/selectMethod.js";
/**
* Fits a set of points to the sum of a set of bell functions.
*
* @param data - An object containing the x and y data to be fitted.
* @param peaks - A list of initial parameters to be optimized. e.g. coming from a peak picking [{x, y, width}].
* @param options - Options for optimize
* @returns - An object with fitting error and the list of optimized parameters { parameters: [ {x, y, width} ], error } if the kind of shape is pseudoVoigt mu parameter is optimized.
*/
export function optimize(data, peaks, options = {}) {
// rescale data
const temp = xMinMaxValues(data.y);
const minMaxY = { ...temp, range: temp.max - temp.min };
const internalPeaks = getInternalPeaks(peaks, minMaxY, options);
// need to rescale what is related to Y
const { baseline: shiftValue = minMaxY.min } = options;
const normalizedY = new Float64Array(data.y.length);
for (let i = 0; i < data.y.length; i++) {
normalizedY[i] = (data.y[i] - shiftValue) / minMaxY.range;
}
const nbParams = internalPeaks[internalPeaks.length - 1].toIndex + 1;
const minValues = new Float64Array(nbParams);
const maxValues = new Float64Array(nbParams);
const initialValues = new Float64Array(nbParams);
const gradientDifferences = new Float64Array(nbParams);
let index = 0;
for (const peak of internalPeaks) {
for (let i = 0; i < peak.parameters.length; i++) {
minValues[index] = peak.propertiesValues.min[i];
maxValues[index] = peak.propertiesValues.max[i];
initialValues[index] = peak.propertiesValues.init[i];
gradientDifferences[index] = peak.propertiesValues.gradientDifference[i];
index++;
}
}
const { algorithm, optimizationOptions } = selectMethod(options.optimization);
const sumOfShapes = getSumOfShapes(internalPeaks);
const fitted = algorithm({ x: data.x, y: normalizedY }, sumOfShapes, {
minValues,
maxValues,
initialValues,
gradientDifference: gradientDifferences,
...optimizationOptions,
});
const fittedValues = fitted.parameterValues;
const newPeaks = [];
for (const peak of internalPeaks) {
const { id, shape, parameters, fromIndex } = peak;
let newPeak = { x: 0, y: 0, shape };
if (id) {
newPeak = { ...newPeak, id };
}
newPeak.x = fittedValues[fromIndex];
newPeak.y = fittedValues[fromIndex + 1] * minMaxY.range + shiftValue;
for (let i = 2; i < parameters.length; i++) {
//@ts-expect-error should be fixed once
newPeak.shape[parameters[i]] = fittedValues[fromIndex + i];
}
newPeaks.push(newPeak);
}
return {
error: fitted.parameterError,
iterations: fitted.iterations,
peaks: newPeaks,
};
}
//# sourceMappingURL=index.js.map