UNPKG

ml-spectra-fitting

Version:

Fit spectra using gaussian or lorentzian

70 lines 3.13 kB
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