ml-peak-shape-generator
Advanced tools
Comparing version 0.10.2 to 0.11.0
# Changelog | ||
## [0.11.0](https://www.github.com/mljs/peak-shape-generator/compare/v0.10.2...v0.11.0) (2020-12-10) | ||
### Features | ||
* add getShapeFct ([6792fd7](https://www.github.com/mljs/peak-shape-generator/commit/6792fd71a194a34ad50c689f1b3ed3be1e915b23)) | ||
* add getShapeGenerator function ([ba19753](https://www.github.com/mljs/peak-shape-generator/commit/ba19753360f29448a6eb83f08b740bc6c741668a)) | ||
* interval option to calculate the shape values ([8ad11d9](https://www.github.com/mljs/peak-shape-generator/commit/8ad11d9e1c247811d55881adc5af5bd430d7f8b0)) | ||
* It is possible to have differents fwhm for gaussian and lorentzian contributions in pseudo voigt shape ([a5658a4](https://www.github.com/mljs/peak-shape-generator/commit/a5658a483bd0953eda074dfa89f556802b75c759)) | ||
* refactor and added getArea static function ([240b792](https://www.github.com/mljs/peak-shape-generator/commit/240b792cecf315db8cc3585ac0890c4b578b8eda)) | ||
### Bug Fixes | ||
* convertion between with between inflection points and FWHM ([3f6657d](https://www.github.com/mljs/peak-shape-generator/commit/3f6657da4f31e21aa5e0a5fa5fd9297c08e489ab)) | ||
### [0.10.2](https://www.github.com/mljs/peak-shape-generator/compare/v0.10.1...v0.10.2) (2020-11-16) | ||
@@ -4,0 +20,0 @@ |
609
lib/index.js
@@ -5,341 +5,418 @@ 'use strict'; | ||
var hash = require('object-hash'); | ||
var erfinv = require('compute-erfinv'); | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var hash__default = /*#__PURE__*/_interopDefaultLegacy(hash); | ||
var erfinv__default = /*#__PURE__*/_interopDefaultLegacy(erfinv); | ||
const GAUSSIAN = 1; | ||
const LORENTZIAN = 2; | ||
const PSEUDO_VOIGT = 3; | ||
const GAUSSIAN_EXP_FACTOR = -4 * Math.LN2; | ||
const ROOT_PI_OVER_LN2 = Math.sqrt(Math.PI / Math.LN2); | ||
const ROOT_THREE = Math.sqrt(3); | ||
const ROOT_2LN2 = Math.sqrt(2 * Math.LN2); | ||
const ROOT_2LN2_MINUS_ONE = Math.sqrt(2 * Math.LN2) - 1; | ||
function getKind(kind) { | ||
if (typeof kind !== 'string') return kind; | ||
switch (kind.toLowerCase().replace(/[^a-z]/g, '')) { | ||
case 'gaussian': | ||
return GAUSSIAN; | ||
case 'lorentzian': | ||
return LORENTZIAN; | ||
case 'pseudovoigt': | ||
return PSEUDO_VOIGT; | ||
default: | ||
throw new Error(`Unknown kind: ${kind}`); | ||
class Gaussian { | ||
/** | ||
* @param {object} [options = {}] | ||
* @param {number} [options.height=x] Define the height of the peak, by default area=1 (normalized) | ||
* @param {number} [options.fwhm = 500] - Full Width at Half Maximum in the number of points in FWHM. | ||
* @param {number} [options.sd] - Standard deviation, if it's defined options.fwhm will be ignored and the value will be computed sd * Math.sqrt(8 * Math.LN2); | ||
*/ | ||
constructor(options = {}) { | ||
this.fwhm = options.sd | ||
? Gaussian.widthToFWHM(2 * options.sd) | ||
: options.fwhm | ||
? options.fwhm | ||
: 500; | ||
this.height = | ||
options.height === undefined | ||
? Math.sqrt(-GAUSSIAN_EXP_FACTOR / Math.PI) / this.fwhm | ||
: options.height; | ||
} | ||
} | ||
/** | ||
* Calculate a gaussian shape | ||
* @param {object} [options = {}] | ||
* @param {number} [options.factor = 6] - Number of time to take fwhm to calculate length. Default covers 99.99 % of area. | ||
* @param {number} [options.length = fwhm * factor + 1] - total number of points to calculate | ||
* @return {Float64Array} y values | ||
*/ | ||
/** | ||
* Compute the value of Full Width at Half Maximum (FWHM) of a specific shape from the width between the inflection points. | ||
* @param {number} width - Width between the inflection points | ||
* @param {number|string} [kind = 1] kind may be 'gaussian', 'lorentzian' or 'pseudovoigt' or their corresponding number | ||
* @param {*} options - options | ||
* @param {number} [options.mu = 0.5] - ratio of gaussian contribution. It is used if the kind = 3 or pseudovoigt. | ||
*/ | ||
getData(options = {}) { | ||
let { length, factor = this.getFactor() } = options; | ||
function inflectionPointsWidthToFWHM( | ||
width, | ||
kind = GAUSSIAN, | ||
options = {}, | ||
) { | ||
let { mu = 0.5 } = options; | ||
if (!length) { | ||
length = Math.min(Math.ceil(this.fwhm * factor), Math.pow(2, 25) - 1); | ||
if (length % 2 === 0) length++; | ||
} | ||
if (typeof kind === 'string') kind = getKind(kind); | ||
switch (kind) { | ||
case 1: | ||
return Math.sqrt(2 * Math.LN2) * width; | ||
case 2: | ||
return width; | ||
case 3: | ||
return width * (mu * (Math.sqrt(2 * Math.LN2) - 1) + 1); | ||
default: | ||
throw new Error(`Unknown shape kind: ${kind}`); | ||
const center = (length - 1) / 2; | ||
const data = new Float64Array(length); | ||
for (let i = 0; i <= center; i++) { | ||
data[i] = this.fct(i - center) * this.height; | ||
data[length - 1 - i] = data[i]; | ||
} | ||
return data; | ||
} | ||
} | ||
/** | ||
* Return a parameterized function of a gaussian shape (see README for equation). | ||
* @param {Number} x - center of the lorentzian function. | ||
* @param {Number} y - height of the lorentzian shape curve. | ||
* @param {Number} width - full width at half maximum (FWHM) of the lorentzian function. | ||
* @param {Number} t - x value to calculate. | ||
* @returns {Number} - the y value of gaussian with the current parameters. | ||
*/ | ||
/** | ||
* Return a parameterized function of a gaussian shape (see README for equation). | ||
* @param {number} x - x value to calculate. | ||
* @returns {number} - the y value of gaussian with the current parameters. | ||
*/ | ||
fct(x) { | ||
return Gaussian.fct(x, this.fwhm); | ||
} | ||
function gaussianFct(x, y, width, t) { | ||
return y * Math.exp(-4 * Math.LN2 * Math.pow((t - x) / width, 2)); | ||
} | ||
/** | ||
* Calculate the number of times FWHM allows to reach a specific area coverage | ||
* @param {number} [area=0.9999] | ||
* @returns {number} | ||
*/ | ||
getFactor(area = 0.9999) { | ||
return Math.sqrt(2) * erfinv__default['default'](area); | ||
} | ||
/** | ||
* Calculate a normalized gaussian shape | ||
* @param {object} [options = {}] | ||
* @param {Number} [options.height = 1] - maximum value of the curve. | ||
* @param {Number} [options.normalized = false] - If it's true the area under the curve will be equal to one, ignoring height option. | ||
* @param {number} [options.fwhm = 500] - number of points in Full Width at Half Maximum, Standard deviation will be computed as fwhm / 2 / sqrt(2 ln(2)) | ||
* @param {number} [options.sd] - Standard deviation, if it's defined fwhm parameter will be ignored. | ||
* @param {number} [options.factor = 4] - Number of time to take fwhm to calculate length. Default covers 99.99 % of area. | ||
* @param {number} [options.length = fwhm * factor + 1] - total number of points to calculate | ||
* @return {object} - {fwhm, data<Float64Array>} - An object with the number of points at half maximum and the array of y values covering the 99.99 % of the area. | ||
*/ | ||
/** | ||
* Calculate the area of the shape. | ||
* @returns {number} - returns the area. | ||
*/ | ||
function gaussian(options = {}) { | ||
let { | ||
height = 1, | ||
length, | ||
factor = 4, | ||
fwhm = 500, | ||
sd, | ||
normalized = false, | ||
} = options; | ||
if (sd) { | ||
fwhm = inflectionPointsWidthToFWHM(2 * sd); | ||
getArea() { | ||
return Gaussian.getArea(this.fwhm, { height: this.height }); | ||
} | ||
if (!length) { | ||
length = Math.ceil(fwhm * factor); | ||
if (length % 2 === 0) length++; | ||
/** | ||
* set a new full width at half maximum | ||
* @param {number} fwhm - full width at half maximum | ||
*/ | ||
setFWHM(fwhm) { | ||
this.fwhm = fwhm; | ||
} | ||
const center = (length - 1) / 2; | ||
const data = new Float64Array(length); | ||
let intensity = normalized | ||
? Math.sqrt((4 * Math.LN2) / Math.PI) / fwhm | ||
: height; | ||
for (let i = 0; i <= center; i++) { | ||
data[i] = gaussianFct(center, intensity, fwhm, i); | ||
data[length - 1 - i] = data[i]; | ||
/** | ||
* set a new height | ||
* @param {number} height - The maximal intensity of the shape. | ||
*/ | ||
setHeight(height) { | ||
this.height = height; | ||
} | ||
return { data, fwhm }; | ||
} | ||
/** | ||
* Return a parameterized function of a lorentzian shape (see README for equation) | ||
* @param {Number} x - center of the lorentzian function. | ||
* @param {Number} y - height of the lorentzian shape curve. | ||
* @param {Number} width - full width at half maximum (FWHM) of the lorentzian function. | ||
* @param {Number} t - x value to calculate. | ||
* @returns {Number} - the y value of lorentzian with the current parameters. | ||
* Return a parameterized function of a gaussian shape (see README for equation). | ||
* @param {number} x - x value to calculate. | ||
* @param {number} fwhm - full width half maximum | ||
* @returns {number} - the y value of gaussian with the current parameters. | ||
*/ | ||
function lorentzianFct(x, y, width, t) { | ||
const squareWidth = width * width; | ||
return (y * squareWidth) / (4 * Math.pow(t - x, 2) + squareWidth); | ||
} | ||
Gaussian.fct = function fct(x, fwhm = 500) { | ||
return Math.exp(GAUSSIAN_EXP_FACTOR * Math.pow(x / fwhm, 2)); | ||
}; | ||
/** | ||
* Calculate a lorentzian shape | ||
* @param {object} [options = {}] | ||
* @param {Number} [options.height] - maximum value of the curve. | ||
* @param {Number} [options.normalized] - If it's true the area under the curve will be equal to one, ignoring height option. | ||
* @param {number} [options.fwhm = 500] - number of points in Full Width at Half Maximum. | ||
* @param {number} [options.factor = Math.tan(Math.PI * (0.9999 - 0.5))] - Number of time to take fwhm to calculate length. Default covers 99.99 % of area. | ||
* @param {number} [options.length = fwhm * factor + 1] - total number of points to calculate | ||
* @return {object} - {fwhm, data<Float64Array>} - An object with the number of points at half maximum and the array of y values covering the 99.99 % of the area. | ||
* Compute the value of Full Width at Half Maximum (FWHM) of a specific shape from the width between the inflection points. | ||
* @param {number} width - Width between the inflection points | ||
* @returns {number} fwhm | ||
*/ | ||
function lorentzian(options = {}) { | ||
let { | ||
height = 1, | ||
length, | ||
factor = Math.ceil(2 * Math.tan(Math.PI * (0.9999 - 0.5))), | ||
fwhm = 500, | ||
normalized = false, | ||
} = options; | ||
Gaussian.widthToFWHM = function widthToFWHM(width) { | ||
//https://mathworld.wolfram.com/GaussianFunction.html | ||
return width * ROOT_2LN2; | ||
}; | ||
if (!length) { | ||
length = Math.ceil(fwhm * factor); | ||
if (length % 2 === 0) length++; | ||
} | ||
const center = (length - 1) / 2; | ||
const data = new Float64Array(length); | ||
const intensity = normalized ? 2 / Math.PI / fwhm : height; | ||
for (let i = 0; i <= center; i++) { | ||
data[i] = lorentzianFct(center, intensity, fwhm, i); | ||
data[length - 1 - i] = data[i]; | ||
} | ||
return { data, fwhm }; | ||
} | ||
/** | ||
* Return a parameterized function of a linear combination of Gaussian and Lorentzian shapes (see README for equation). | ||
* @param {Number} x - center of the lorentzian function. | ||
* @param {Number} y - height of the lorentzian shape curve. | ||
* @param {Number} width - full width at half maximum (FWHM) of the lorentzian function. | ||
* @param {Number} mu - ratio of gaussian contribution. | ||
* @param {Number} t - x value to calculate. | ||
* @returns {Number} - the y value of a pseudo voigt with the current parameters. | ||
* Compute the value of width between the inflection points of a specific shape from Full Width at Half Maximum (FWHM). | ||
* @param {number} fwhm - Full Width at Half Maximum. | ||
* @returns {number} width | ||
*/ | ||
Gaussian.fwhmToWidth = function fwhmToWidth(fwhm) { | ||
return fwhm / ROOT_2LN2; | ||
}; | ||
function pseudovoigtFct(x, y, width, mu, t) { | ||
const squareWidth = width * width; | ||
return ( | ||
y * | ||
(((1 - mu) * squareWidth) / (4 * Math.pow(t - x, 2) + squareWidth) + | ||
mu * Math.exp(-4 * Math.LN2 * Math.pow((t - x) / width, 2))) | ||
); | ||
} | ||
/** | ||
* Calculate a linear combination of gaussian and lorentzian function width an same full width at half maximum | ||
* @param {object} [options = {}] | ||
* @param {Number} [options.height = 1] - maximum value of the curve. | ||
* @param {Number} [options.normalized = false] - If it's true the area under the curve will be equal to one, ignoring height option. | ||
* @param {number} [options.fwhm = 1000] - number of points in Full Width at Half Maximum, Standard deviation for gaussian contribution will be computed as fwhm / 2 / sqrt(2 ln(2)) | ||
* @param {number} [options.mu = 0.5] - ratio of gaussian contribution. | ||
* @param {number} [options.factor = Math.tan(Math.PI * (0.9999 - 0.5))] - Number of time to take fwhm to calculate length. Default covers 99.99 % of area. | ||
* @param {number} [options.length = fwhm * factor + 1] - total number of points to calculate | ||
* @return {object} - {fwhm, data<Float64Array>} - An object with the number of points at half maximum and the array of y values covering the 99.99 % of the area. | ||
* Calculate the area of a specific shape. | ||
* @param {number} fwhm - Full width at half maximum. | ||
* @param {object} [options = {}] - options. | ||
* @param {number} [options.height = 1] - Maximum y value of the shape. | ||
* @returns {number} - returns the area of the specific shape and parameters. | ||
*/ | ||
function pseudoVoigt(options = {}) { | ||
let { | ||
height = 1, | ||
normalized = false, | ||
length, | ||
factor = Math.ceil(2 * Math.tan(Math.PI * (0.9999 - 0.5))), | ||
fwhm = 1000, | ||
mu = 0.5, | ||
} = options; | ||
Gaussian.getArea = function (fwhm, options = {}) { | ||
let { height = 1 } = options; | ||
return (height * ROOT_PI_OVER_LN2 * fwhm) / 2; | ||
}; | ||
if (!length) { | ||
length = Math.ceil(fwhm * factor); | ||
if (length % 2 === 0) length++; | ||
class Lorentzian { | ||
/** | ||
* @param {object} [options = {}] | ||
* @param {number} [options.height=x] Define the height of the peak, by default area=1 (normalized) | ||
* @param {number} [options.fwhm = 500] - Full Width at Half Maximum in the number of points in FWHM. | ||
* @param {number} [options.sd] - Standard deviation, if it's defined options.fwhm will be ignored and the value will be computed sd * Math.sqrt(8 * Math.LN2); | ||
*/ | ||
constructor(options = {}) { | ||
this.fwhm = options.fwhm === undefined ? 500 : options.fwhm; | ||
this.height = | ||
options.height === undefined ? 2 / Math.PI / this.fwhm : options.height; | ||
} | ||
/** | ||
* Calculate a lorentzian shape | ||
* @param {object} [options = {}] | ||
* @param {number} [options.factor = Math.tan(Math.PI * (0.9999 - 0.5))] - Number of time to take fwhm to calculate length. Default covers 99.99 % of area. | ||
* @param {number} [options.length = fwhm * factor + 1] - total number of points to calculate | ||
* @return {Float64Array} y values | ||
*/ | ||
getData(options = {}) { | ||
let { length, factor = this.getFactor() } = options; | ||
const center = (length - 1) / 2; | ||
if (!length) { | ||
length = Math.min(Math.ceil(this.fwhm * factor), Math.pow(2, 25) - 1); | ||
if (length % 2 === 0) length++; | ||
} | ||
let intensity = normalized | ||
? 1 / | ||
((mu / Math.sqrt((4 * Math.LN2) / Math.PI)) * fwhm + | ||
((1 - mu) * fwhm * Math.PI) / 2) | ||
: height; | ||
const center = (length - 1) / 2; | ||
const data = new Float64Array(length); | ||
for (let i = 0; i <= center; i++) { | ||
data[i] = this.fct(i - center) * this.height; | ||
data[length - 1 - i] = data[i]; | ||
} | ||
return data; | ||
} | ||
let data = new Float64Array(length); | ||
for (let i = 0; i <= center; i++) { | ||
data[i] = pseudovoigtFct(center, intensity, fwhm, mu, i); | ||
data[length - 1 - i] = data[i]; | ||
/** | ||
* Return a parameterized function of a lorentzian shape (see README for equation). | ||
* @param {number} x - x value to calculate. | ||
* @returns {number} - the y value of lorentzian with the current parameters. | ||
*/ | ||
fct(x) { | ||
return Lorentzian.fct(x, this.fwhm); | ||
} | ||
return { data, fwhm }; | ||
/** | ||
* Calculate the number of times FWHM allows to reach a specific area coverage | ||
* @param {number} [area=0.9999] | ||
* @returns {number} | ||
*/ | ||
getFactor(area = 0.9999) { | ||
return 2 * Math.tan(Math.PI * (area - 0.5)); | ||
} | ||
/** | ||
* Calculate the area of the shape. | ||
* @returns {number} - returns the area. | ||
*/ | ||
getArea() { | ||
return Lorentzian.getArea(this.fwhm, { height: this.height }); | ||
} | ||
/** | ||
* set a new full width at half maximum | ||
* @param {number} fwhm - full width at half maximum | ||
*/ | ||
setFWHM(fwhm) { | ||
this.fwhm = fwhm; | ||
} | ||
/** | ||
* set a new height | ||
* @param {number} height - The maximal intensity of the shape. | ||
*/ | ||
setHeight(height) { | ||
this.height = height; | ||
} | ||
} | ||
/** | ||
* Generate a shape of the specified kind | ||
* @param {number|string} [kind = 1] kind may be 'gaussian', 'lorentzian' or 'pseudovoigt' or their corresponding number | ||
* @param {object} [options = {}] | ||
* @param {number} [options.fwhm = 500] - number of points in Full Width at Half Maximum, Standard deviation will be computed as fwhm / 2 / sqrt(2 ln(2)) | ||
* @param {number} [options.factor = 3] - factor of standard deviation to increase the window size, the vector size is 2 * factor * sd | ||
* @param {number} [options.length = fwhm * factor + 1] - total number of points to calculate | ||
* @return {object} - {fwhm, data<Float64Array>} - An object with the number of points at half maximum and the array of y values covering the 99.99 % of the area. | ||
* Return a parameterized function of a gaussian shape (see README for equation). | ||
* @param {number} x - x value to calculate. | ||
* @param {number} fwhm - full width half maximum | ||
* @returns {number} - the y value of gaussian with the current parameters. | ||
*/ | ||
Lorentzian.fct = function fct(x, fwhm) { | ||
const squareFWHM = fwhm * fwhm; | ||
return squareFWHM / (4 * Math.pow(x, 2) + squareFWHM); | ||
}; | ||
function getShape(kind = GAUSSIAN, options = {}) { | ||
kind = getKind(kind); | ||
switch (kind) { | ||
case 1: | ||
return gaussian(options); | ||
case 2: | ||
return lorentzian(options); | ||
case 3: | ||
return pseudoVoigt(options); | ||
default: | ||
throw new Error(`Unknown shape kind: ${kind}`); | ||
} | ||
} | ||
/** | ||
* Compute the value of width between the inflection points of a specific shape from Full Width at Half Maximum (FWHM). | ||
* @param {number} [fwhm] - Full Width at Half Maximum. | ||
* @returns {number} width between the inflection points | ||
*/ | ||
Lorentzian.fwhmToWidth = function fwhmToWidth(fwhm) { | ||
return fwhm / ROOT_THREE; | ||
}; | ||
/** | ||
* Compute the value of Full Width at Half Maximum (FWHM) of a specific shape from the width between the inflection points. | ||
* @param {number} [width] Width between the inflection points | ||
* @returns {number} fwhm | ||
*/ | ||
Lorentzian.widthToFWHM = function widthToFWHM(width) { | ||
//https://mathworld.wolfram.com/LorentzianFunction.html | ||
return width * ROOT_THREE; | ||
}; | ||
/** | ||
* Calculate the area of a specific shape. | ||
* @param {number} fwhm - Full width at half maximum. | ||
* @param {number|string} [kind = 1] - number of points in Full Width at Half Maximum, Standard deviation will be computed as fwhm / 2 / sqrt(2 ln(2)) | ||
* @param {*} [options = {}] - options. | ||
* @param {number} [options.height = 1] - Maximum y value of the shape. | ||
* @param {number} [options.mu = 0.5] - ratio of gaussian contribution. It is used if the kind = 3 or pseudovoigt. | ||
* @returns {number} - returns the area of the specific shape and parameters. | ||
*/ | ||
Lorentzian.getArea = function (fwhm, options = {}) { | ||
let { height = 1 } = options; | ||
function getArea(fwhm, kind = GAUSSIAN, options = {}) { | ||
let { height = 1, mu = 0.5 } = options; | ||
return (height * Math.PI * fwhm) / 2; | ||
}; | ||
kind = getKind(kind); | ||
switch (kind) { | ||
case 1: | ||
return (height * Math.sqrt(Math.PI / Math.LN2) * fwhm) / 2; | ||
case 2: | ||
return (height * Math.PI * fwhm) / 2; | ||
case 3: | ||
return ( | ||
(fwhm * | ||
height * | ||
(mu * Math.sqrt(Math.PI / Math.LN2) + (1 - mu) * Math.PI)) / | ||
2 | ||
); | ||
default: | ||
throw new Error(`Unknown shape kind: ${kind}`); | ||
} | ||
} | ||
class PseudoVoigt { | ||
/** | ||
* @param {object} [options={}] | ||
* @param {number} [options.height=x] Define the height of the peak, by default area=1 (normalized) | ||
* @param {number} [options.fwhm=500] - Full Width at Half Maximum in the number of points in FWHM. | ||
* @param {number} [options.mu=0.5] - ratio of gaussian contribution. | ||
*/ | ||
/** | ||
* Allows to generate and cache shapes | ||
* | ||
*/ | ||
class PeakShapeGenerator { | ||
constructor(options = {}) { | ||
const { cacheSize = 20 } = options; | ||
this.cache = []; | ||
this.cacheSize = cacheSize; | ||
this.mu = options.mu === undefined ? 0.5 : options.mu; | ||
this.fwhm = options.fwhm === undefined ? 500 : options.fwhm; | ||
this.height = | ||
options.height === undefined | ||
? 1 / | ||
((this.mu / Math.sqrt(-GAUSSIAN_EXP_FACTOR / Math.PI)) * this.fwhm + | ||
((1 - this.mu) * this.fwhm * Math.PI) / 2) | ||
: options.height; | ||
} | ||
getShape(kind, options) { | ||
let uuid = hash__default['default']({ kind, options }); | ||
if (this.cache[uuid]) return this.cache[uuid]; | ||
const shape = getShape(kind, options); | ||
if (Object.keys(this.cache) < this.cacheSize) { | ||
this.cache[uuid] = shape; | ||
/** | ||
* Calculate a linear combination of gaussian and lorentzian function width an same full width at half maximum | ||
* @param { object } [options = {}] | ||
* @param { number } [options.factor = 2 * Math.tan(Math.PI * (0.9999 - 0.5))] - Number of time to take fwhm in the calculation of the length.Default covers 99.99 % of area. | ||
* @param { number } [options.length = fwhm * factor + 1] - total number of points to calculate | ||
* @return { object } - { fwhm, data<Float64Array>} - An with the number of points at half maximum and the array of y values covering the 99.99 % of the area. | ||
*/ | ||
getData(options = {}) { | ||
let { length, factor = this.getFactor() } = options; | ||
if (!length) { | ||
length = Math.ceil(this.fwhm * factor); | ||
if (length % 2 === 0) length++; | ||
} | ||
return shape; | ||
const center = (length - 1) / 2; | ||
let data = new Float64Array(length); | ||
for (let i = 0; i <= center; i++) { | ||
data[i] = this.fct(i - center) * this.height; | ||
data[length - 1 - i] = data[i]; | ||
} | ||
return data; | ||
} | ||
/** | ||
* Return a parameterized function of a linear combination of Gaussian and Lorentzian shapes where the full width at half maximum are the same for both kind of shapes (see README for equation). | ||
* @param {number} [x] x value to calculate. | ||
* @returns {number} - the y value of a pseudo voigt with the current parameters. | ||
*/ | ||
fct(x) { | ||
return PseudoVoigt.fct(x, this.fwhm, this.mu); | ||
} | ||
/** | ||
* Calculate the number of times FWHM allows to reach a specific area coverage | ||
* @param {number} [area=0.9999] | ||
* @returns {number} | ||
*/ | ||
getFactor(area = 0.9999) { | ||
return 2 * Math.tan(Math.PI * (area - 0.5)); | ||
} | ||
/** | ||
* Calculate the area of the shape. | ||
* @returns {number} - returns the area. | ||
*/ | ||
getArea() { | ||
return PseudoVoigt.getArea(this.fwhm, { height: this.height, mu: this.mu }); | ||
} | ||
/** | ||
* set a new full width at half maximum | ||
* @param {number} fwhm - full width at half maximum | ||
*/ | ||
setFWHM(fwhm) { | ||
this.fwhm = fwhm; | ||
} | ||
/** | ||
* set a new height | ||
* @param {number} height - The maximal intensity of the shape. | ||
*/ | ||
setHeight(height) { | ||
this.height = height; | ||
} | ||
/** | ||
* set a new mu | ||
* @param {number} mu - ratio of gaussian contribution. | ||
*/ | ||
setMu(mu) { | ||
this.mu = mu; | ||
} | ||
} | ||
/** | ||
* Return a parameterized function of a gaussian shape (see README for equation). | ||
* @param {number} x - x value to calculate. | ||
* @param {number} fwhm - full width half maximum | ||
* @param {number} [mu=0.5] - ratio of gaussian contribution. | ||
* @returns {number} - the y value of gaussian with the current parameters. | ||
*/ | ||
PseudoVoigt.fct = function fct(x, fwhm, mu = 0.5) { | ||
return (1 - mu) * Lorentzian.fct(x, fwhm) + mu * Gaussian.fct(x, fwhm); | ||
}; | ||
/** | ||
* Compute the value of width between the inflection points of a specific shape from Full Width at Half Maximum (FWHM). | ||
* @param {number} fwhm - Full Width at Half Maximum. | ||
* @param {number|string} [kind = 1] kind may be 'gaussian', 'lorentzian' or 'pseudovoigt' or their corresponding number | ||
* @param {*} options - options | ||
* @param {number} [options.mu = 0.5] - ratio of gaussian contribution. It is used if the kind = 3 or pseudovoigt. | ||
* @returns {number} width between the inflection points | ||
*/ | ||
PseudoVoigt.fwhmToWidth = function fwhmToWidth(fwhm) { | ||
return fwhm / (this.mu * ROOT_2LN2_MINUS_ONE + 1); | ||
}; | ||
function fwhmToInflectionPointsWidth( | ||
fwhm, | ||
kind = GAUSSIAN, | ||
options = {}, | ||
) { | ||
let { mu = 0.5 } = options; | ||
/** | ||
* Calculate the area of a specific shape. | ||
* @param {number} fwhm - Full width at half maximum. | ||
* @param {*} [options = {}] - options. | ||
* @param {number} [options.height = 1] - Maximum y value of the shape. | ||
* @param {number} [options.mu = 0.5] - ratio of gaussian contribution. | ||
* @returns {number} - returns the area of the specific shape and parameters. | ||
*/ | ||
PseudoVoigt.getArea = function (fwhm, options = {}) { | ||
let { height = 1, mu = 0.5 } = options; | ||
if (typeof kind === 'string') kind = getKind(kind); | ||
switch (kind) { | ||
case 1: | ||
return fwhm / Math.sqrt(2 * Math.LN2); | ||
case 2: | ||
return fwhm; | ||
case 3: | ||
return fwhm / (mu * (Math.sqrt(2 * Math.LN2) - 1) + 1); | ||
return (fwhm * height * (mu * ROOT_PI_OVER_LN2 + (1 - mu) * Math.PI)) / 2; | ||
}; | ||
function getShapeGenerator(options) { | ||
let { kind = 'Gaussian', options: shapeOptions } = options; | ||
switch (kind.toLowerCase().replace(/[^a-z]/g, '')) { | ||
case 'gaussian': | ||
return new Gaussian(shapeOptions); | ||
case 'lorentzian': | ||
return new Lorentzian(shapeOptions); | ||
case 'pseudovoigt': | ||
return new PseudoVoigt(shapeOptions); | ||
default: | ||
throw new Error(`Unknown shape kind: ${kind}`); | ||
throw new Error(`Unknown kind: ${kind}`); | ||
} | ||
} | ||
exports.GAUSSIAN = GAUSSIAN; | ||
exports.LORENTZIAN = LORENTZIAN; | ||
exports.PSEUDO_VOIGT = PSEUDO_VOIGT; | ||
exports.PeakShapeGenerator = PeakShapeGenerator; | ||
exports.fwhmToInflectionPointsWidth = fwhmToInflectionPointsWidth; | ||
exports.gaussian = gaussian; | ||
exports.gaussianFct = gaussianFct; | ||
exports.getArea = getArea; | ||
exports.getKind = getKind; | ||
exports.getShape = getShape; | ||
exports.inflectionPointsWidthToFWHM = inflectionPointsWidthToFWHM; | ||
exports.lorentzian = lorentzian; | ||
exports.lorentzianFct = lorentzianFct; | ||
exports.pseudoVoigt = pseudoVoigt; | ||
exports.pseudovoigtFct = pseudovoigtFct; | ||
exports.Gaussian = Gaussian; | ||
exports.Lorentzian = Lorentzian; | ||
exports.PseudoVoigt = PseudoVoigt; | ||
exports.getShapeGenerator = getShapeGenerator; |
{ | ||
"name": "ml-peak-shape-generator", | ||
"version": "0.10.2", | ||
"version": "0.11.0", | ||
"description": "", | ||
@@ -43,15 +43,16 @@ "main": "lib/index.js", | ||
"@babel/plugin-transform-modules-commonjs": "^7.12.1", | ||
"eslint": "^7.12.1", | ||
"eslint": "^7.15.0", | ||
"eslint-config-cheminfo": "^5.2.2", | ||
"eslint-plugin-import": "^2.22.1", | ||
"eslint-plugin-jest": "^24.1.0", | ||
"eslint-plugin-prettier": "^3.1.4", | ||
"eslint-plugin-jest": "^24.1.3", | ||
"eslint-plugin-prettier": "^3.2.0", | ||
"esm": "^3.2.25", | ||
"jest": "^26.6.3", | ||
"jest-matcher-deep-close-to": "^2.0.1", | ||
"prettier": "^2.1.2", | ||
"rollup": "^2.33.1" | ||
"prettier": "^2.2.1", | ||
"rollup": "^2.34.2" | ||
}, | ||
"dependencies": { | ||
"object-hash": "^2.0.3" | ||
"compute-erfinv": "^3.0.1" | ||
} | ||
} |
@@ -1,12 +0,4 @@ | ||
export * from './gaussian'; | ||
export * from './lorentzian'; | ||
export * from './pseudoVoigt'; | ||
export * from './getShape'; | ||
export * from './getArea'; | ||
export * from './util/getKind'; | ||
export * from './PeakShapeGenerator'; | ||
export * from './shapes/gaussianFct'; | ||
export * from './shapes/lorentzianFct'; | ||
export * from './shapes/pseudovoigtFct'; | ||
export * from './fwhmToInflectionPointsWidth'; | ||
export * from './inflectionPointsWidthToFWHM'; | ||
export * from './classes/Gaussian'; | ||
export * from './classes/Lorentzian'; | ||
export * from './classes/PseudoVoigt'; | ||
export * from './util/getShapeGenerator'; |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
40236
738
11
11
1
+ Addedcompute-erfinv@^3.0.1
+ Addedcompute-array-constructors@1.0.1(transitive)
+ Addedcompute-array-dtype@1.0.1(transitive)
+ Addedcompute-dtype@1.0.0(transitive)
+ Addedcompute-erfinv@3.0.1(transitive)
+ Addedcompute-indexspace@1.0.1(transitive)
+ Addedcompute-polynomial@1.1.0(transitive)
+ Addedconst-max-uint32@1.0.2(transitive)
+ Addedconst-pinf-float64@1.0.0(transitive)
+ Addeddstructs-array-constructors@1.0.2(transitive)
+ Addeddstructs-array-dtype@1.0.2(transitive)
+ Addeddstructs-cast-arrays@1.0.3(transitive)
+ Addeddstructs-matrix@2.1.2(transitive)
+ Addedobject-keys@1.1.1(transitive)
+ Addedregex-regex@1.0.0(transitive)
+ Addedtype-name@1.1.02.0.2(transitive)
+ Addedutils-copy@1.1.1(transitive)
+ Addedutils-copy-error@1.0.1(transitive)
+ Addedutils-deep-get@1.0.0(transitive)
+ Addedutils-deep-set@1.0.1(transitive)
+ Addedutils-indexof@1.0.0(transitive)
+ Addedutils-regex-from-string@1.0.0(transitive)
+ Addedvalidate.io-array@1.0.6(transitive)
+ Addedvalidate.io-array-like@1.0.2(transitive)
+ Addedvalidate.io-boolean-primitive@1.0.0(transitive)
+ Addedvalidate.io-buffer@1.0.2(transitive)
+ Addedvalidate.io-contains@1.0.0(transitive)
+ Addedvalidate.io-function@1.0.2(transitive)
+ Addedvalidate.io-integer@1.0.5(transitive)
+ Addedvalidate.io-integer-primitive@1.0.0(transitive)
+ Addedvalidate.io-matrix-like@1.0.2(transitive)
+ Addedvalidate.io-nan@1.0.3(transitive)
+ Addedvalidate.io-nan-primitive@1.0.0(transitive)
+ Addedvalidate.io-nonnegative-integer@1.0.0(transitive)
+ Addedvalidate.io-nonnegative-integer-array@1.0.1(transitive)
+ Addedvalidate.io-number@1.0.3(transitive)
+ Addedvalidate.io-number-primitive@1.0.0(transitive)
+ Addedvalidate.io-number-primitive-array@1.0.0(transitive)
+ Addedvalidate.io-object@1.0.4(transitive)
+ Addedvalidate.io-string-primitive@1.0.1(transitive)
+ Addedvalidate.io-typed-array-like@1.0.1(transitive)
- Removedobject-hash@^2.0.3
- Removedobject-hash@2.2.0(transitive)