ml-spectra-fitting
Advanced tools
Comparing version 0.11.0 to 0.12.0
# Changelog | ||
## [0.12.0](https://www.github.com/mljs/spectra-fitting/compare/v0.11.0...v0.12.0) (2021-01-13) | ||
### Features | ||
* remove twice declaration ([bb8d013](https://www.github.com/mljs/spectra-fitting/commit/bb8d013e22c89b79fafaa0fefa2fe341b5d2fdc4)) | ||
* use gradientDifference from peak too ([#48](https://www.github.com/mljs/spectra-fitting/issues/48)) ([fb81ac2](https://www.github.com/mljs/spectra-fitting/commit/fb81ac235fa73ee8814ecd65bf40353e8a54f53b)) | ||
* x search space depending on peak width ([#45](https://www.github.com/mljs/spectra-fitting/issues/45)) ([63375d3](https://www.github.com/mljs/spectra-fitting/commit/63375d33805983e2288718d5763364111a08bb0e)) | ||
## [0.11.0](https://www.github.com/mljs/spectra-fitting/compare/v0.10.0...v0.11.0) (2020-12-20) | ||
@@ -4,0 +13,0 @@ |
168
lib/index.js
@@ -116,4 +116,9 @@ 'use strict'; | ||
const STATE_MAX = 2; | ||
const STATE_GS = 3; | ||
const STATE_GRADIENT_DIFFERENCE = 3; | ||
const X = 0; | ||
const Y = 1; | ||
const WIDTH = 2; | ||
const MU = 3; | ||
const keys = ['x', 'y', 'width', 'mu']; | ||
@@ -129,4 +134,7 @@ /** | ||
* @param {object} [options.optimization.kind = 'lm'] - kind of algorithm. By default it's levenberg-marquardt. | ||
* @param {object} [options.optimization.options = {}] - options for the specific kind of algorithm. | ||
* @param {number} [options.optimization.options.timeout] - maximum time running before break in seconds. | ||
* @param {object} [options.optimization.options = {}] - options for the specific kind of algorithm. | ||
* @param {number} [options.optimization.options.damping=1.5] | ||
* @param {number} [options.optimization.options.maxIterations=100] | ||
* @param {number} [options.optimization.options.errorTolerance=1e-8] | ||
* @returns {object} - A 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. | ||
@@ -142,2 +150,17 @@ */ | ||
let { | ||
minFactorWidth = 0.25, | ||
maxFactorWidth = 4, | ||
minFactorX = 2, | ||
maxFactorX = 2, | ||
minFactorY = 0, | ||
maxFactorY = 1.5, | ||
minMuValue = 0, | ||
maxMuValue = 1, | ||
xGradientDifference, | ||
yGradientDifference = 1e-3, | ||
widthGradientDifference, | ||
muGradientDifference = 0.01, | ||
} = optimization; | ||
peaks = JSON.parse(JSON.stringify(peaks)); | ||
@@ -177,21 +200,33 @@ | ||
const getValueOptions = { | ||
maxY, | ||
minFactorX, | ||
maxFactorX, | ||
minFactorY, | ||
maxFactorY, | ||
minMuValue, | ||
maxMuValue, | ||
minFactorWidth, | ||
maxFactorWidth, | ||
xGradientDifference, | ||
yGradientDifference, | ||
widthGradientDifference, | ||
muGradientDifference, | ||
}; | ||
let nbShapes = peaks.length; | ||
let pInit = new Float64Array(nbShapes * nbParams); | ||
let pMin = new Float64Array(nbShapes * nbParams); | ||
let pMax = new Float64Array(nbShapes * nbParams); | ||
let pInit = new Float64Array(nbShapes * nbParams); | ||
let gradientDifference = new Float64Array(nbShapes * nbParams); | ||
let deltaX = Math.abs(data.x[0] - data.x[1]); | ||
for (let i = 0; i < nbShapes; i++) { | ||
let peak = peaks[i]; | ||
for (let s = 0; s < nbParams; s++) { | ||
pInit[i + s * nbShapes] = getValue(s, peak, STATE_INIT, deltaX, maxY); | ||
pMin[i + s * nbShapes] = getValue(s, peak, STATE_MIN, deltaX, maxY); | ||
pMax[i + s * nbShapes] = getValue(s, peak, STATE_MAX, deltaX, maxY); | ||
pInit[i + s * nbShapes] = getValue(s, peak, STATE_INIT, getValueOptions); | ||
pMin[i + s * nbShapes] = getValue(s, peak, STATE_MIN, getValueOptions); | ||
pMax[i + s * nbShapes] = getValue(s, peak, STATE_MAX, getValueOptions); | ||
gradientDifference[i + s * nbShapes] = getValue( | ||
s, | ||
peak, | ||
STATE_GS, | ||
deltaX, | ||
maxY, | ||
STATE_GRADIENT_DIFFERENCE, | ||
getValueOptions, | ||
); | ||
@@ -219,51 +254,78 @@ } | ||
} | ||
return result; | ||
} | ||
function getValue(parameterIndex, peak, key, dt, maxY) { | ||
let value; | ||
switch (parameterIndex) { | ||
case 0: | ||
value = | ||
key === STATE_INIT | ||
? peak.x | ||
: key === STATE_GS | ||
? dt / 1000 | ||
: key === STATE_MIN | ||
? peak.x - dt | ||
: peak.x + dt; | ||
break; | ||
case 1: | ||
value = | ||
key === STATE_INIT | ||
? peak.y / maxY | ||
: key === STATE_GS | ||
? 1e-3 | ||
: key === STATE_MIN | ||
? 0 | ||
: 1.5; | ||
break; | ||
case 2: | ||
value = | ||
key === STATE_INIT | ||
? peak.width | ||
: key === STATE_GS | ||
? dt / 1000 | ||
: key === STATE_MIN | ||
? peak.width / 4 | ||
: peak.width * 4; | ||
break; | ||
function getValue(parameterIndex, peak, state, options) { | ||
let maxY = options.maxY; | ||
switch (state) { | ||
case STATE_INIT: | ||
switch (parameterIndex) { | ||
case X: | ||
return peak.x; | ||
case Y: | ||
return peak.y / maxY; | ||
case WIDTH: | ||
return peak.width; | ||
case MU: | ||
return peak.mu || 0.5; | ||
default: | ||
throw new Error('The parameter is not supported'); | ||
} | ||
case STATE_GRADIENT_DIFFERENCE: | ||
switch (parameterIndex) { | ||
case X: | ||
return peak.xGradientDifference !== undefined | ||
? peak.xGradientDifference | ||
: options.xGradientDifference !== undefined | ||
? options.xGradientDifference | ||
: peak.width / 2e3; | ||
case Y: | ||
return peak.yGradientDifference !== undefined | ||
? peak.yGradientDifference | ||
: options.yGradientDifference; | ||
case WIDTH: | ||
return peak.widthGradientDifference !== undefined | ||
? peak.widthGradientDifference | ||
: options.widthGradientDifference !== undefined | ||
? options.widthGradientDifference | ||
: peak.width / 2e3; | ||
case MU: | ||
return peak.muGradientDifference !== undefined | ||
? peak.muGradientDifference | ||
: options.muGradientDifference; | ||
default: | ||
throw new Error('The parameter is not supported'); | ||
} | ||
case STATE_MIN: | ||
switch (parameterIndex) { | ||
case X: | ||
return peak.x - peak.width * options.minFactorX; | ||
case Y: | ||
return (peak.y / maxY) * options.minFactorY; | ||
case WIDTH: | ||
return peak.width * options.minFactorWidth; | ||
case MU: | ||
return options.minMuValue; | ||
default: | ||
throw new Error('The parameter is not supported'); | ||
} | ||
case STATE_MAX: | ||
switch (parameterIndex) { | ||
case X: | ||
return peak.x + peak.width * options.maxFactorX; | ||
case Y: | ||
return (peak.y / maxY) * options.maxFactorY; | ||
case WIDTH: | ||
return peak.width * options.maxFactorWidth; | ||
case MU: | ||
return options.maxMuValue; | ||
default: | ||
throw new Error('The parameter is not supported'); | ||
} | ||
default: | ||
value = | ||
key === STATE_INIT | ||
? 0.5 | ||
: key === STATE_GS | ||
? 0.01 | ||
: key === STATE_MIN | ||
? 0 | ||
: 1; | ||
throw Error('the state is not supported'); | ||
} | ||
return value; | ||
} | ||
exports.optimize = optimize; |
{ | ||
"name": "ml-spectra-fitting", | ||
"version": "0.11.0", | ||
"version": "0.12.0", | ||
"description": "Fit spectra using gaussian or lorentzian", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -39,3 +39,2 @@ import { optimize } from '../index'; | ||
let yData = sumOfGaussians(pTrue); | ||
let result = optimize( | ||
@@ -71,5 +70,5 @@ { x, y: x.map((i) => yData(i)) }, | ||
]; | ||
let yData = sumOfGaussianLorentzians(pTrue); | ||
let func = sumOfGaussianLorentzians(pTrue); | ||
let result = optimize( | ||
{ x, y: x.map(yData) }, | ||
{ x, y: x.map(func) }, | ||
[ | ||
@@ -76,0 +75,0 @@ { x: 0.1, y: 0.0009, width: (xFactor * nbPoints) / 6 }, |
168
src/index.js
@@ -11,4 +11,9 @@ import getMaxValue from 'ml-array-max'; | ||
const STATE_MAX = 2; | ||
const STATE_GS = 3; | ||
const STATE_GRADIENT_DIFFERENCE = 3; | ||
const X = 0; | ||
const Y = 1; | ||
const WIDTH = 2; | ||
const MU = 3; | ||
const keys = ['x', 'y', 'width', 'mu']; | ||
@@ -24,4 +29,7 @@ /** | ||
* @param {object} [options.optimization.kind = 'lm'] - kind of algorithm. By default it's levenberg-marquardt. | ||
* @param {object} [options.optimization.options = {}] - options for the specific kind of algorithm. | ||
* @param {number} [options.optimization.options.timeout] - maximum time running before break in seconds. | ||
* @param {object} [options.optimization.options = {}] - options for the specific kind of algorithm. | ||
* @param {number} [options.optimization.options.damping=1.5] | ||
* @param {number} [options.optimization.options.maxIterations=100] | ||
* @param {number} [options.optimization.options.errorTolerance=1e-8] | ||
* @returns {object} - A 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. | ||
@@ -37,2 +45,17 @@ */ | ||
let { | ||
minFactorWidth = 0.25, | ||
maxFactorWidth = 4, | ||
minFactorX = 2, | ||
maxFactorX = 2, | ||
minFactorY = 0, | ||
maxFactorY = 1.5, | ||
minMuValue = 0, | ||
maxMuValue = 1, | ||
xGradientDifference, | ||
yGradientDifference = 1e-3, | ||
widthGradientDifference, | ||
muGradientDifference = 0.01, | ||
} = optimization; | ||
peaks = JSON.parse(JSON.stringify(peaks)); | ||
@@ -72,21 +95,33 @@ | ||
const getValueOptions = { | ||
maxY, | ||
minFactorX, | ||
maxFactorX, | ||
minFactorY, | ||
maxFactorY, | ||
minMuValue, | ||
maxMuValue, | ||
minFactorWidth, | ||
maxFactorWidth, | ||
xGradientDifference, | ||
yGradientDifference, | ||
widthGradientDifference, | ||
muGradientDifference, | ||
}; | ||
let nbShapes = peaks.length; | ||
let pInit = new Float64Array(nbShapes * nbParams); | ||
let pMin = new Float64Array(nbShapes * nbParams); | ||
let pMax = new Float64Array(nbShapes * nbParams); | ||
let pInit = new Float64Array(nbShapes * nbParams); | ||
let gradientDifference = new Float64Array(nbShapes * nbParams); | ||
let deltaX = Math.abs(data.x[0] - data.x[1]); | ||
for (let i = 0; i < nbShapes; i++) { | ||
let peak = peaks[i]; | ||
for (let s = 0; s < nbParams; s++) { | ||
pInit[i + s * nbShapes] = getValue(s, peak, STATE_INIT, deltaX, maxY); | ||
pMin[i + s * nbShapes] = getValue(s, peak, STATE_MIN, deltaX, maxY); | ||
pMax[i + s * nbShapes] = getValue(s, peak, STATE_MAX, deltaX, maxY); | ||
pInit[i + s * nbShapes] = getValue(s, peak, STATE_INIT, getValueOptions); | ||
pMin[i + s * nbShapes] = getValue(s, peak, STATE_MIN, getValueOptions); | ||
pMax[i + s * nbShapes] = getValue(s, peak, STATE_MAX, getValueOptions); | ||
gradientDifference[i + s * nbShapes] = getValue( | ||
s, | ||
peak, | ||
STATE_GS, | ||
deltaX, | ||
maxY, | ||
STATE_GRADIENT_DIFFERENCE, | ||
getValueOptions, | ||
); | ||
@@ -114,49 +149,76 @@ } | ||
} | ||
return result; | ||
} | ||
function getValue(parameterIndex, peak, key, dt, maxY) { | ||
let value; | ||
switch (parameterIndex) { | ||
case 0: | ||
value = | ||
key === STATE_INIT | ||
? peak.x | ||
: key === STATE_GS | ||
? dt / 1000 | ||
: key === STATE_MIN | ||
? peak.x - dt | ||
: peak.x + dt; | ||
break; | ||
case 1: | ||
value = | ||
key === STATE_INIT | ||
? peak.y / maxY | ||
: key === STATE_GS | ||
? 1e-3 | ||
: key === STATE_MIN | ||
? 0 | ||
: 1.5; | ||
break; | ||
case 2: | ||
value = | ||
key === STATE_INIT | ||
? peak.width | ||
: key === STATE_GS | ||
? dt / 1000 | ||
: key === STATE_MIN | ||
? peak.width / 4 | ||
: peak.width * 4; | ||
break; | ||
function getValue(parameterIndex, peak, state, options) { | ||
let maxY = options.maxY; | ||
switch (state) { | ||
case STATE_INIT: | ||
switch (parameterIndex) { | ||
case X: | ||
return peak.x; | ||
case Y: | ||
return peak.y / maxY; | ||
case WIDTH: | ||
return peak.width; | ||
case MU: | ||
return peak.mu || 0.5; | ||
default: | ||
throw new Error('The parameter is not supported'); | ||
} | ||
case STATE_GRADIENT_DIFFERENCE: | ||
switch (parameterIndex) { | ||
case X: | ||
return peak.xGradientDifference !== undefined | ||
? peak.xGradientDifference | ||
: options.xGradientDifference !== undefined | ||
? options.xGradientDifference | ||
: peak.width / 2e3; | ||
case Y: | ||
return peak.yGradientDifference !== undefined | ||
? peak.yGradientDifference | ||
: options.yGradientDifference; | ||
case WIDTH: | ||
return peak.widthGradientDifference !== undefined | ||
? peak.widthGradientDifference | ||
: options.widthGradientDifference !== undefined | ||
? options.widthGradientDifference | ||
: peak.width / 2e3; | ||
case MU: | ||
return peak.muGradientDifference !== undefined | ||
? peak.muGradientDifference | ||
: options.muGradientDifference; | ||
default: | ||
throw new Error('The parameter is not supported'); | ||
} | ||
case STATE_MIN: | ||
switch (parameterIndex) { | ||
case X: | ||
return peak.x - peak.width * options.minFactorX; | ||
case Y: | ||
return (peak.y / maxY) * options.minFactorY; | ||
case WIDTH: | ||
return peak.width * options.minFactorWidth; | ||
case MU: | ||
return options.minMuValue; | ||
default: | ||
throw new Error('The parameter is not supported'); | ||
} | ||
case STATE_MAX: | ||
switch (parameterIndex) { | ||
case X: | ||
return peak.x + peak.width * options.maxFactorX; | ||
case Y: | ||
return (peak.y / maxY) * options.maxFactorY; | ||
case WIDTH: | ||
return peak.width * options.maxFactorWidth; | ||
case MU: | ||
return options.maxMuValue; | ||
default: | ||
throw new Error('The parameter is not supported'); | ||
} | ||
default: | ||
value = | ||
key === STATE_INIT | ||
? 0.5 | ||
: key === STATE_GS | ||
? 0.01 | ||
: key === STATE_MIN | ||
? 0 | ||
: 1; | ||
throw Error('the state is not supported'); | ||
} | ||
return value; | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
36768
695