Skip to content

Commit a939d0c

Browse files
committed
feat!: add setShape n addMissingShape function
* chore(addMissingShape): add test case remove appendShapeAndFWHM, setShape is the equivalent function close: #104
1 parent 36a2b4c commit a939d0c

File tree

8 files changed

+222
-14
lines changed

8 files changed

+222
-14
lines changed

src/gsd.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import {
1010
} from 'ml-spectra-processing';
1111

1212
import { GSDPeak } from './GSDPeak';
13-
import { appendShapeAndFWHM } from './utils/appendShapeAndFWHM';
1413
import { optimizeTop } from './utils/optimizeTop';
14+
import { setShape } from './utils/setShape';
1515

1616
export interface GSDOptions {
1717
/**
@@ -274,5 +274,5 @@ export function gsd(data: DataXY, options: GSDOptions = {}): GSDPeak[] {
274274
return a.x - b.x;
275275
});
276276

277-
return appendShapeAndFWHM(peaks, { shape });
277+
return setShape(peaks, { shape });
278278
}

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ export * from './post/optimizePeaks';
33
export * from './post/optimizePeaksWithLogs';
44
export * from './post/joinBroadPeaks';
55
export * from './post/broadenPeaks';
6-
export * from './utils/appendShapeAndFWHM';
6+
export * from './utils/setShape';
7+
export * from './utils/addMissingShape';
78
export * from './GSDBroadenPeak';
89
export * from './GSDPeak';
910
export * from './GSDPeakOptimized';

src/post/joinBroadPeaks.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { OptimizationOptions } from 'ml-spectra-fitting';
33

44
import { GSDPeak } from '../GSDPeak';
55
import { GSDPeakOptimized } from '../GSDPeakOptimized';
6-
import { appendShapeAndFWHM } from '../utils/appendShapeAndFWHM';
6+
import { addMissingShape } from '../utils/addMissingShape';
77

88
import { optimizePeaks } from './optimizePeaks';
99

@@ -32,8 +32,11 @@ export interface JoinBroadPeaksOptions {
3232
* This function tries to join the peaks that seems to belong to a broad signal in a single broad peak.
3333
*/
3434

35+
export interface GSDPeakWithOptionalShape extends Omit<GSDPeak, 'shape'> {
36+
shape?: Shape1D;
37+
}
3538
export function joinBroadPeaks(
36-
peakList: GSDPeak[],
39+
peakList: GSDPeakWithOptionalShape[],
3740
options: JoinBroadPeaksOptions = {},
3841
): GSDPeak[] {
3942
let {
@@ -47,7 +50,7 @@ export function joinBroadPeaks(
4750
let maxI = 0;
4851
let count = 1;
4952
const broadLines: GSDPeakOptimized[] = [];
50-
const peaks = appendShapeAndFWHM(peakList, { shape });
53+
const peaks = addMissingShape(peakList, { shape });
5154

5255
if (peaks.length < 2) return peaks;
5356

src/post/optimizePeaksWithLogs.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { optimize } from 'ml-spectra-fitting';
44
import { xGetFromToIndex } from 'ml-spectra-processing';
55

66
import { GSDPeakOptimized } from '../GSDPeakOptimized';
7-
import { appendShapeAndFWHM } from '../utils/appendShapeAndFWHM';
7+
import { addMissingShape } from '../utils/addMissingShape';
88
import { groupPeaks } from '../utils/groupPeaks';
99

1010
import { OptimizePeaksOptions } from './optimizePeaks';
@@ -45,7 +45,7 @@ export function optimizePeaksWithLogs(
4545
groups.forEach((peakGroup) => {
4646
const start = Date.now();
4747
// In order to make optimization we will add fwhm and shape on all the peaks
48-
const peaks = appendShapeAndFWHM(peakGroup, { shape });
48+
const peaks = addMissingShape(peakGroup, { shape });
4949

5050
const firstPeak = peaks[0];
5151
const lastPeak = peaks[peaks.length - 1];
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import { toMatchCloseTo } from 'jest-matcher-deep-close-to';
2+
import { getShape1D } from 'ml-peak-shape-generator';
3+
4+
import { addMissingShape } from '../addMissingShape';
5+
6+
expect.extend({ toMatchCloseTo });
7+
8+
describe('addMissingShape', () => {
9+
it('gaussian shape', () => {
10+
let result = addMissingShape([
11+
{
12+
x: 5,
13+
y: 10,
14+
width: 5,
15+
index: 1,
16+
},
17+
{
18+
x: 10,
19+
y: 10,
20+
width: 10,
21+
index: 2,
22+
},
23+
{
24+
x: 30,
25+
y: 10,
26+
width: 15,
27+
index: 3,
28+
shape: { kind: 'lorentzian', fwhm: 5.8870501125773735 * 3 },
29+
},
30+
]);
31+
expect(result).toMatchCloseTo([
32+
{
33+
x: 5,
34+
y: 10,
35+
width: 5,
36+
index: 1,
37+
shape: { kind: 'gaussian', fwhm: 5.8870501125773735 },
38+
},
39+
{
40+
x: 10,
41+
y: 10,
42+
width: 10,
43+
index: 2,
44+
shape: { kind: 'gaussian', fwhm: 5.8870501125773735 * 2 },
45+
},
46+
{
47+
x: 30,
48+
y: 10,
49+
width: 15,
50+
index: 3,
51+
shape: { kind: 'lorentzian', fwhm: 5.8870501125773735 * 3 },
52+
},
53+
]);
54+
});
55+
it('lorentzian shape', () => {
56+
let result = addMissingShape(
57+
[
58+
{
59+
x: 5,
60+
y: 10,
61+
width: 5,
62+
index: 1,
63+
inflectionPoints: {
64+
from: { x: 0, index: 0 },
65+
to: { x: 0, index: 0 },
66+
},
67+
},
68+
{
69+
x: 10,
70+
y: 10,
71+
width: 10,
72+
index: 2,
73+
inflectionPoints: {
74+
from: { x: 0, index: 0 },
75+
to: { x: 0, index: 0 },
76+
},
77+
shape: { kind: 'pseudoVoigt', fwhm: 8.660254037844386 * 2, mu: 0.5 },
78+
},
79+
{
80+
x: 30,
81+
y: 10,
82+
width: 15,
83+
index: 3,
84+
inflectionPoints: {
85+
from: { x: 0, index: 0 },
86+
to: { x: 0, index: 0 },
87+
},
88+
},
89+
],
90+
{ shape: { kind: 'lorentzian' } },
91+
);
92+
expect(result).toMatchCloseTo([
93+
{
94+
x: 5,
95+
y: 10,
96+
width: 5,
97+
index: 1,
98+
shape: { kind: 'lorentzian', fwhm: 8.660254037844386 },
99+
inflectionPoints: { from: { x: 0, index: 0 }, to: { x: 0, index: 0 } },
100+
},
101+
{
102+
x: 10,
103+
y: 10,
104+
width: 10,
105+
index: 2,
106+
shape: { kind: 'pseudoVoigt', fwhm: 8.660254037844386 * 2, mu: 0.5 },
107+
inflectionPoints: { from: { x: 0, index: 0 }, to: { x: 0, index: 0 } },
108+
},
109+
{
110+
x: 30,
111+
y: 10,
112+
width: 15,
113+
index: 3,
114+
shape: { kind: 'lorentzian', fwhm: 8.660254037844386 * 3 },
115+
inflectionPoints: { from: { x: 0, index: 0 }, to: { x: 0, index: 0 } },
116+
},
117+
]);
118+
});
119+
it('pseudovoigt shape', () => {
120+
let result = addMissingShape(
121+
[
122+
{
123+
x: 5,
124+
y: 10,
125+
width: 5,
126+
index: 1,
127+
inflectionPoints: {
128+
from: { x: 0, index: 0 },
129+
to: { x: 0, index: 0 },
130+
},
131+
},
132+
{
133+
x: 5,
134+
y: 10,
135+
width: 5,
136+
index: 1,
137+
inflectionPoints: {
138+
from: { x: 0, index: 0 },
139+
to: { x: 0, index: 0 },
140+
},
141+
shape: { kind: 'gaussian' },
142+
},
143+
],
144+
{ shape: { kind: 'pseudoVoigt', mu: 0.5 } },
145+
);
146+
expect(result).toMatchCloseTo([
147+
{
148+
x: 5,
149+
y: 10,
150+
width: 5,
151+
index: 1,
152+
shape: { kind: 'pseudoVoigt', fwhm: 5.443525056288687, mu: 0.5 },
153+
inflectionPoints: { from: { x: 0, index: 0 }, to: { x: 0, index: 0 } },
154+
},
155+
{
156+
x: 5,
157+
y: 10,
158+
width: 5,
159+
index: 1,
160+
inflectionPoints: {
161+
from: { x: 0, index: 0 },
162+
to: { x: 0, index: 0 },
163+
},
164+
shape: {
165+
kind: 'gaussian',
166+
fwhm: getShape1D({ kind: 'gaussian' }).widthToFWHM(5),
167+
},
168+
},
169+
]);
170+
});
171+
});

src/utils/__tests__/appendShapeAndFWHM.test.ts renamed to src/utils/__tests__/setShape.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { toMatchCloseTo } from 'jest-matcher-deep-close-to';
22

3-
import { appendShapeAndFWHM } from '../appendShapeAndFWHM';
3+
import { setShape } from '../setShape';
44

55
expect.extend({ toMatchCloseTo });
66

7-
describe('appendShapeAndFWHM', () => {
7+
describe('setShape', () => {
88
it('gaussian shape', () => {
9-
let result = appendShapeAndFWHM([
9+
let result = setShape([
1010
{
1111
x: 5,
1212
y: 10,
@@ -51,7 +51,7 @@ describe('appendShapeAndFWHM', () => {
5151
]);
5252
});
5353
it('lorentzian shape', () => {
54-
let result = appendShapeAndFWHM(
54+
let result = setShape(
5555
[
5656
{
5757
x: 5,
@@ -114,7 +114,7 @@ describe('appendShapeAndFWHM', () => {
114114
]);
115115
});
116116
it('pseudovoigt shape', () => {
117-
let result = appendShapeAndFWHM(
117+
let result = setShape(
118118
[
119119
{
120120
x: 5,

src/utils/addMissingShape.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { getShape1D, Shape1D } from 'ml-peak-shape-generator';
2+
3+
/**
4+
* add missing property if it does not exist in the peak,
5+
* if shape exists but fwhm doesn't, it will be calculated from peak.width
6+
*/
7+
8+
export function addMissingShape<T extends { width: number; shape?: Shape1D }>(
9+
peaks: T[],
10+
options: { shape?: Shape1D } = {},
11+
): (T & { shape: Shape1D })[] {
12+
const { shape = { kind: 'gaussian' } } = options;
13+
let shapeInstance = getShape1D(shape);
14+
return peaks.map((peak) => {
15+
if (hasShape(peak)) {
16+
if (!('fwhm' in peak.shape)) {
17+
const shapeInstance = getShape1D(peak.shape);
18+
peak.shape.fwhm = shapeInstance.widthToFWHM(peak.width);
19+
}
20+
return peak;
21+
}
22+
return {
23+
...peak,
24+
shape: { fwhm: shapeInstance.widthToFWHM(peak.width), ...shape },
25+
};
26+
});
27+
}
28+
29+
function hasShape<T extends { width: number; shape?: Shape1D }>(
30+
peak,
31+
): peak is T & { width: number; shape: Shape1D } {
32+
return 'shape' in peak;
33+
}

src/utils/appendShapeAndFWHM.ts renamed to src/utils/setShape.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { getShape1D, Shape1D } from 'ml-peak-shape-generator';
44
* Append 2 properties to the peaks, shape and fwhm
55
*/
66

7-
export function appendShapeAndFWHM<T extends { width: number }>(
7+
export function setShape<T extends { width: number }>(
88
peaks: T[],
99
options: {
1010
/**

0 commit comments

Comments
 (0)