Skip to content

Commit 24f17ff

Browse files
authored
export fwhm instead of width between the inflection points if kind of shape is specified (#32)
* feat: add shape and lmOptions as options of joinBroadPeaks method * feat: export fwhm instead of width between the inflection points if kind of shape is specified Default behavior: the fwhm depends of the kind of shape in options. By default it returns the width between the inflection points
1 parent e03737c commit 24f17ff

File tree

6 files changed

+64
-62
lines changed

6 files changed

+64
-62
lines changed

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
"build": "rollup -c && cheminfo-build --entry src/index.js --root GSD",
1616
"eslint": "eslint src --cache",
1717
"eslint-fix": "npm run eslint -- --fix",
18-
"prepublishOnly": "rollup -c",
18+
"compile": "rollup -c",
19+
"prepublishOnly": "npm run compile",
1920
"test": "npm run test-coverage && npm run eslint",
2021
"test-only": "jest",
2122
"test-coverage": "jest --coverage"
@@ -61,6 +62,7 @@
6162
"eslint-plugin-prettier": "^3.1.4",
6263
"esm": "^3.2.25",
6364
"jest": "^26.6.3",
65+
"jest-matcher-deep-close-to": "^2.0.1",
6466
"mf-global": "^1.3.0",
6567
"ml-stat": "^1.3.3",
6668
"prettier": "^2.1.2",
@@ -70,6 +72,7 @@
7072
},
7173
"dependencies": {
7274
"ml-savitzky-golay-generalized": "2.0.2",
73-
"ml-spectra-fitting": "^0.5.0"
75+
"ml-spectra-fitting": "^0.6.0",
76+
"ml-peak-shape-generator": "^0.9.0"
7477
}
7578
}

src/__tests__/broadNMR.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe('Global spectra deconvolution NMR spectra', () => {
2121
},
2222
},
2323
);
24-
joinBroadPeaks(result, { width: 0.25 });
24+
joinBroadPeaks(result, { width: 0.25, shape: { kind: 'lorentzian' } });
2525
expect(result).toHaveLength(14);
2626
result.forEach((peak) => {
2727
if (Math.abs(peak.x - 4.31) < 0.01) {

src/__tests__/simple.js

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import { toMatchCloseTo } from 'jest-matcher-deep-close-to';
2+
13
import { gsd } from '..';
24

5+
expect.extend({ toMatchCloseTo });
6+
37
describe('Simple test cases', () => {
48
let x = [];
59
let y = [];
@@ -49,24 +53,27 @@ describe('Simple test cases', () => {
4953
},
5054
);
5155

52-
expect(peaks).toStrictEqual([
53-
{
54-
base: 1.2434539324230613,
55-
index: 15,
56-
left: {
57-
index: 13,
58-
x: 13,
56+
expect(peaks).toMatchCloseTo(
57+
[
58+
{
59+
base: 1.2434539324230613,
60+
index: 15,
61+
left: {
62+
index: 13,
63+
x: 13,
64+
},
65+
right: {
66+
index: 16,
67+
x: 16,
68+
},
69+
soft: false,
70+
width: 3,
71+
x: 15,
72+
y: 5,
5973
},
60-
right: {
61-
index: 16,
62-
x: 16,
63-
},
64-
soft: false,
65-
width: 3,
66-
x: 15,
67-
y: 5,
68-
},
69-
]);
74+
],
75+
2,
76+
);
7077
});
7178

7279
it('gsd realtop', () => {
@@ -83,23 +90,26 @@ describe('Simple test cases', () => {
8390
},
8491
},
8592
);
86-
expect(peaks).toStrictEqual([
87-
{
88-
base: 1.2434539324230613,
89-
index: 15,
90-
left: {
91-
index: 13,
92-
x: 13,
93-
},
94-
right: {
95-
index: 16,
96-
x: 16,
93+
expect(peaks).toMatchCloseTo(
94+
[
95+
{
96+
base: 1.2434539324230613,
97+
index: 15,
98+
left: {
99+
index: 13,
100+
x: 13,
101+
},
102+
right: {
103+
index: 16,
104+
x: 16,
105+
},
106+
soft: false,
107+
width: 3,
108+
x: 14.5,
109+
y: 4.006546067576939,
97110
},
98-
soft: false,
99-
width: 3,
100-
x: 14.5,
101-
y: 4.006546067576939,
102-
},
103-
]);
111+
],
112+
2,
113+
);
104114
});
105115
});

src/gsd.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { inflectionPointsWidthToFWHM } from 'ml-peak-shape-generator';
12
import SG from 'ml-savitzky-golay-generalized';
23

34
/**
@@ -28,6 +29,7 @@ export function gsd(data, options = {}) {
2829
windowSize: 9,
2930
polynomial: 3,
3031
},
32+
shape = {},
3133
smoothY = true,
3234
heightFactor = 0,
3335
broadRatio = 0.0,
@@ -198,11 +200,14 @@ export function gsd(data, options = {}) {
198200

199201
if (possible !== -1) {
200202
if (Math.abs(yData[minddY[j]]) > minMaxRatio * maxY) {
203+
let width = Math.abs(intervalR[possible].x - intervalL[possible].x);
201204
signals.push({
202205
index: minddY[j],
203206
x: frequency,
204207
y: (yData[minddY[j]] + yCorrection.b) / yCorrection.m,
205-
width: Math.abs(intervalR[possible].x - intervalL[possible].x), // widthCorrection
208+
width: shape.kind
209+
? inflectionPointsWidthToFWHM(width, shape.kind, shape.options)
210+
: width, // widthCorrection
206211
soft: broadMask[j],
207212
});
208213

src/post/joinBroadPeaks.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { optimize } from 'ml-spectra-fitting';
44
* This function try to join the peaks that seems to belong to a broad signal in a single broad peak.
55
* @param {Array} peakList - A list of initial parameters to be optimized. e.g. coming from a peak picking [{x, y, width}].
66
* @param {object} [options = {}] -
7-
* @param {number} [options.width] - width limit to join peaks.
7+
* @param {number} options.width - width limit to join peaks.
88
*/
99
export function joinBroadPeaks(peakList, options = {}) {
10-
let width = options.width;
10+
let { shape = { kind: 'gaussian' }, width, lmOptions = {} } = options;
1111
let broadLines = [];
1212
// Optimize the possible broad lines
1313
let max = 0;
@@ -48,7 +48,7 @@ export function joinBroadPeaks(peakList, options = {}) {
4848
),
4949
},
5050
],
51-
{ kind: 'lorentzian' },
51+
{ shape, lmOptions },
5252
);
5353
let { peaks: peak } = fitted;
5454
peak[0].index = Math.floor(

src/post/optimizePeaks.js

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { optimize } from 'ml-spectra-fitting';
22

3-
const kindSupported = ['gaussian', 'lorentzian', 'pseudovoigt'];
4-
53
/**
64
* Optimize the position (x), max intensity (y), full width at half maximum (width)
75
* and the ratio of gaussian contribution (mu) if it's required. It supports three kind of shapes: gaussian, lorentzian and pseudovoigt
@@ -16,9 +14,11 @@ const kindSupported = ['gaussian', 'lorentzian', 'pseudovoigt'];
1614

1715
export function optimizePeaks(data, peakList, options = {}) {
1816
const {
19-
functionName = 'gaussian',
2017
factorWidth = 1,
2118
joinPeaks = true,
19+
shape = {
20+
kind: 'gaussian',
21+
},
2222
optimizationOptions = {
2323
damping: 1.5,
2424
maxIterations: 100,
@@ -28,8 +28,6 @@ export function optimizePeaks(data, peakList, options = {}) {
2828

2929
let { x, y } = data;
3030

31-
checkFuncName(functionName, optimizationOptions);
32-
3331
let lastIndex = [0];
3432
let groups = groupPeaks(peakList, factorWidth, joinPeaks);
3533

@@ -48,7 +46,7 @@ export function optimizePeaks(data, peakList, options = {}) {
4846
);
4947
if (sampling.x.length > 5) {
5048
let { peaks: optPeaks } = optimize(sampling, peaks, {
51-
kind: functionName,
49+
shape,
5250
lmOptions: optimizationOptions,
5351
});
5452
for (let j = 0; j < optPeaks.length; j++) {
@@ -69,7 +67,7 @@ export function optimizePeaks(data, peakList, options = {}) {
6967

7068
if (sampling.x.length > 5) {
7169
let fitResult = optimize(sampling, [peaks], {
72-
kind: functionName,
70+
shape,
7371
lmOptions: optimizationOptions,
7472
});
7573
let { peaks: optPeaks } = fitResult;
@@ -177,17 +175,3 @@ function groupPeaks(peakList, nL, joinPeaks) {
177175
}
178176
return groups;
179177
}
180-
181-
function checkFuncName(functionName, optimizationOptions) {
182-
let kind = functionName.toLowerCase().replace(/[^a-z]/g, '');
183-
let isSupported = kindSupported.some((ks) => ks === kind);
184-
if (isSupported) {
185-
optimizationOptions.kind = kind;
186-
} else {
187-
throw new Error(
188-
`Kind of function unsupported. Just these kind are supported: ${kindSupported.join(
189-
', ',
190-
)}`,
191-
);
192-
}
193-
}

0 commit comments

Comments
 (0)