nmr-processing 9.1.0 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/lib/assignment/utils/getAssignment/buildAssignments.js.map +1 -1
  2. package/lib/index.d.ts +3 -2
  3. package/lib/index.js +1 -0
  4. package/lib/index.js.map +1 -1
  5. package/lib/prediction/{prediction1D.d.ts → Prediction1D.d.ts} +0 -0
  6. package/lib/prediction/{prediction1D.js → Prediction1D.js} +1 -1
  7. package/lib/prediction/Prediction1D.js.map +1 -0
  8. package/lib/prediction/predictAll.d.ts +1 -1
  9. package/lib/prediction/predictAll.js.map +1 -1
  10. package/lib/prediction/predictAllSpectra.js +2 -2
  11. package/lib/prediction/predictAllSpectra.js.map +1 -1
  12. package/lib/prediction/predictCOSY.d.ts +1 -1
  13. package/lib/prediction/predictCOSY.js.map +1 -1
  14. package/lib/prediction/predictCarbon.d.ts +1 -1
  15. package/lib/prediction/predictHMBC.d.ts +1 -1
  16. package/lib/prediction/predictHMBC.js.map +1 -1
  17. package/lib/prediction/predictHSQC.d.ts +1 -1
  18. package/lib/prediction/predictHSQC.js.map +1 -1
  19. package/lib/prediction/predictProton.d.ts +1 -1
  20. package/lib/prediction/utils/fetchPrediction.d.ts +1 -1
  21. package/lib/prediction/utils/getPredictions.d.ts +1 -1
  22. package/lib/prediction/utils/predict2D.d.ts +1 -1
  23. package/lib/prediction/utils/predict2D.js +1 -1
  24. package/lib/prediction/utils/predict2D.js.map +1 -1
  25. package/lib/signals/{jcoupling.d.ts → Jcoupling.d.ts} +0 -0
  26. package/lib/signals/{jcoupling.js → Jcoupling.js} +1 -1
  27. package/lib/signals/Jcoupling.js.map +1 -0
  28. package/lib/signals/NMRSignal1D.d.ts +1 -1
  29. package/lib/signals/addDummySignals.js +12 -7
  30. package/lib/signals/addDummySignals.js.map +1 -1
  31. package/lib/signals/optimization/defaultParameters.d.ts +1 -0
  32. package/lib/signals/optimization/defaultParameters.js +36 -0
  33. package/lib/signals/optimization/defaultParameters.js.map +1 -0
  34. package/lib/signals/optimization/directOptimization.d.ts +20 -0
  35. package/lib/signals/optimization/directOptimization.js +32 -0
  36. package/lib/signals/optimization/directOptimization.js.map +1 -0
  37. package/lib/signals/optimization/getInternalSignals.d.ts +54 -0
  38. package/lib/signals/optimization/getInternalSignals.js +150 -0
  39. package/lib/signals/optimization/getInternalSignals.js.map +1 -0
  40. package/lib/signals/optimization/getSumOfShapes.d.ts +4 -0
  41. package/lib/signals/optimization/getSumOfShapes.js +46 -0
  42. package/lib/signals/optimization/getSumOfShapes.js.map +1 -0
  43. package/lib/signals/optimization/signalsToPointXY.d.ts +9 -0
  44. package/lib/signals/optimization/signalsToPointXY.js +24 -0
  45. package/lib/signals/optimization/signalsToPointXY.js.map +1 -0
  46. package/lib/signals/optimizeSignals.d.ts +40 -0
  47. package/lib/signals/optimizeSignals.js +108 -0
  48. package/lib/signals/optimizeSignals.js.map +1 -0
  49. package/lib/signals/signalsJoin.d.ts +1 -1
  50. package/lib/signals/simulation/simulateXYPeaks.js +1 -1
  51. package/lib/signals/simulation/simulateXYPeaks.js.map +1 -1
  52. package/lib/xy/xyAutoPeaksPicking.d.ts +2 -2
  53. package/lib/xy/xyAutoPeaksPicking.js +2 -2
  54. package/lib/xy/xyAutoPeaksPicking.js.map +1 -1
  55. package/lib/xy/xyPeaksOptimization.js +2 -1
  56. package/lib/xy/xyPeaksOptimization.js.map +1 -1
  57. package/lib-esm/assignment/utils/getAssignment/buildAssignments.js.map +1 -1
  58. package/lib-esm/index.js +1 -0
  59. package/lib-esm/index.js.map +1 -1
  60. package/lib-esm/prediction/Prediction1D.js +2 -0
  61. package/lib-esm/prediction/Prediction1D.js.map +1 -0
  62. package/lib-esm/prediction/predictAll.js.map +1 -1
  63. package/lib-esm/prediction/predictAllSpectra.js +2 -2
  64. package/lib-esm/prediction/predictAllSpectra.js.map +1 -1
  65. package/lib-esm/prediction/predictCOSY.js.map +1 -1
  66. package/lib-esm/prediction/predictHMBC.js.map +1 -1
  67. package/lib-esm/prediction/predictHSQC.js.map +1 -1
  68. package/lib-esm/prediction/utils/predict2D.js +1 -1
  69. package/lib-esm/prediction/utils/predict2D.js.map +1 -1
  70. package/lib-esm/signals/Jcoupling.js +2 -0
  71. package/lib-esm/signals/Jcoupling.js.map +1 -0
  72. package/lib-esm/signals/addDummySignals.js +12 -7
  73. package/lib-esm/signals/addDummySignals.js.map +1 -1
  74. package/lib-esm/signals/optimization/defaultParameters.js +33 -0
  75. package/lib-esm/signals/optimization/defaultParameters.js.map +1 -0
  76. package/lib-esm/signals/optimization/directOptimization.js +25 -0
  77. package/lib-esm/signals/optimization/directOptimization.js.map +1 -0
  78. package/lib-esm/signals/optimization/getInternalSignals.js +146 -0
  79. package/lib-esm/signals/optimization/getInternalSignals.js.map +1 -0
  80. package/lib-esm/signals/optimization/getSumOfShapes.js +42 -0
  81. package/lib-esm/signals/optimization/getSumOfShapes.js.map +1 -0
  82. package/lib-esm/signals/optimization/signalsToPointXY.js +20 -0
  83. package/lib-esm/signals/optimization/signalsToPointXY.js.map +1 -0
  84. package/lib-esm/signals/optimizeSignals.js +104 -0
  85. package/lib-esm/signals/optimizeSignals.js.map +1 -0
  86. package/lib-esm/signals/simulation/simulateXYPeaks.js +1 -1
  87. package/lib-esm/signals/simulation/simulateXYPeaks.js.map +1 -1
  88. package/lib-esm/xy/xyAutoPeaksPicking.js +3 -3
  89. package/lib-esm/xy/xyAutoPeaksPicking.js.map +1 -1
  90. package/lib-esm/xy/xyPeaksOptimization.js +2 -1
  91. package/lib-esm/xy/xyPeaksOptimization.js.map +1 -1
  92. package/package.json +3 -2
  93. package/src/assignment/utils/getAssignment/buildAssignments.ts +1 -1
  94. package/src/index.ts +3 -2
  95. package/src/prediction/{prediction1D.ts → Prediction1D.ts} +0 -0
  96. package/src/prediction/predictAll.ts +1 -1
  97. package/src/prediction/predictAllSpectra.ts +2 -2
  98. package/src/prediction/predictCOSY.ts +1 -1
  99. package/src/prediction/predictCarbon.ts +1 -1
  100. package/src/prediction/predictHMBC.ts +1 -1
  101. package/src/prediction/predictHSQC.ts +1 -1
  102. package/src/prediction/predictProton.ts +1 -1
  103. package/src/prediction/utils/fetchPrediction.ts +1 -1
  104. package/src/prediction/utils/getPredictions.ts +1 -1
  105. package/src/prediction/utils/predict2D.ts +2 -2
  106. package/src/signal/signalJoinCouplings.ts +1 -1
  107. package/src/signals/{jcoupling.ts → Jcoupling.ts} +0 -0
  108. package/src/signals/NMRSignal1D.ts +1 -1
  109. package/src/signals/addDummySignals.ts +17 -7
  110. package/src/signals/optimization/defaultParameters.ts +45 -0
  111. package/src/signals/optimization/directOptimization.ts +49 -0
  112. package/src/signals/optimization/getInternalSignals.ts +287 -0
  113. package/src/signals/optimization/getSumOfShapes.ts +54 -0
  114. package/src/signals/optimization/signalsToPointXY.ts +37 -0
  115. package/src/signals/optimizeSignals.ts +173 -0
  116. package/src/signals/signalsJoin.ts +1 -1
  117. package/src/signals/signalsToXY.ts +1 -1
  118. package/src/signals/simulation/signalsToSpinSystem.ts +1 -1
  119. package/src/signals/simulation/simulateXYPeaks.ts +1 -2
  120. package/src/xy/xyAutoPeaksPicking.ts +10 -6
  121. package/src/xy/xyPeaksOptimization.ts +3 -1
  122. package/lib/prediction/prediction1D.js.map +0 -1
  123. package/lib/signals/jcoupling.js.map +0 -1
  124. package/lib-esm/prediction/prediction1D.js +0 -2
  125. package/lib-esm/prediction/prediction1D.js.map +0 -1
  126. package/lib-esm/signals/jcoupling.js +0 -2
  127. package/lib-esm/signals/jcoupling.js.map +0 -1
@@ -0,0 +1,287 @@
1
+ import { DataXY } from 'cheminfo-types';
2
+ import { getShape1D, Shape1D, Shape1DInstance } from 'ml-peak-shape-generator';
3
+ import { xyFindClosestPoint } from 'ml-spectra-processing';
4
+
5
+ import { MakeMandatory } from '../../utilities/MakeMandatory';
6
+ import { Jcoupling } from '../Jcoupling';
7
+ import { Signal } from '../optimizeSignals';
8
+
9
+ import { defaultParameters } from './defaultParameters';
10
+ import { signalsToPointXY } from './signalsToPointXY';
11
+
12
+ const properties = ['init', 'min', 'max', 'gradientDifference'];
13
+
14
+ export interface InternalSignal {
15
+ shape: Shape1D;
16
+ shapeFct: Shape1DInstance;
17
+ signal: MakeMandatory<Signal, 'js' | 'intensity'>;
18
+ parameters: string[];
19
+ propertiesValues: Record<string, number[]>;
20
+ fromIndex: number;
21
+ toIndex: number;
22
+ fromIndexCoupling: number;
23
+ toIndexCoupling: number;
24
+ }
25
+ export type Parameter = 'delta' | 'intensity' | 'fwhm' | 'mu' | 'coupling';
26
+
27
+ export type ParametersFromOptions = Record<
28
+ Parameter,
29
+ Record<
30
+ string,
31
+ | number
32
+ | ((options?: {
33
+ signal?: Signal;
34
+ shape?: Shape1D;
35
+ index?: number;
36
+ jCoupling?: Jcoupling;
37
+ }) => number)
38
+ >
39
+ >;
40
+ export interface GetInternalSignalsOptions {
41
+ /**
42
+ * Initial line width in Hz
43
+ * @default 1
44
+ */
45
+ lineWidth?: number;
46
+ /**
47
+ * frequency
48
+ */
49
+ frequency: number;
50
+ baseline?: number;
51
+ shape?: Shape1D;
52
+ parameters?: ParametersFromOptions;
53
+ }
54
+
55
+ export type Shape1DWithFWHM = Omit<Shape1D, 'fwhm'> & { fwhm: number };
56
+ export function getInternalSignals(
57
+ data: DataXY,
58
+ signals: Signal[],
59
+ minMaxY: Record<string, number>,
60
+ options: GetInternalSignalsOptions,
61
+ ) {
62
+ let index = 0;
63
+ let internalSignals = [];
64
+ const {
65
+ shape: shapeAsOption = { kind: 'gaussian' },
66
+ baseline: shiftValue = minMaxY.min,
67
+ lineWidth = 1,
68
+ frequency,
69
+ } = options;
70
+
71
+ const normalizedSignals = normalizeSignals({
72
+ signals,
73
+ data,
74
+ shiftValue,
75
+ frequency,
76
+ range: minMaxY.range,
77
+ });
78
+
79
+ for (const signal of normalizedSignals) {
80
+ const { shape = { ...shapeAsOption } } = signal;
81
+
82
+ if (!shape.fwhm) {
83
+ shape.fwhm = lineWidth;
84
+ }
85
+
86
+ shape.fwhm /= frequency;
87
+ const shapeFct = getShape1D(shape);
88
+
89
+ const parameters: Parameter[] = [
90
+ 'delta',
91
+ 'intensity',
92
+ ...shapeFct.getParameters(),
93
+ ];
94
+
95
+ const propertiesValues: Record<string, number[]> = {
96
+ min: [],
97
+ max: [],
98
+ init: [],
99
+ gradientDifference: [],
100
+ };
101
+
102
+ for (const parameter of parameters) {
103
+ for (const property of properties) {
104
+ propertiesValues[property].push(
105
+ getPropertyValue({
106
+ signal,
107
+ frequency,
108
+ parameter,
109
+ property,
110
+ minMaxY,
111
+ shapeFct,
112
+ }),
113
+ );
114
+ }
115
+ }
116
+
117
+ for (const jCoupling of signal.js || []) {
118
+ for (const property of properties) {
119
+ const parameter = 'coupling' as Parameter;
120
+ let generalParameterValue =
121
+ options?.parameters?.[parameter]?.[property];
122
+ if (generalParameterValue) {
123
+ if (typeof generalParameterValue === 'number') {
124
+ propertiesValues[property].push(
125
+ getNormalizedValue(
126
+ generalParameterValue,
127
+ parameter,
128
+ property,
129
+ minMaxY,
130
+ frequency,
131
+ options.baseline,
132
+ ),
133
+ );
134
+ } else {
135
+ let value = generalParameterValue({ jCoupling });
136
+ propertiesValues[property].push(
137
+ getNormalizedValue(
138
+ value,
139
+ parameter,
140
+ property,
141
+ minMaxY,
142
+ frequency,
143
+ options.baseline,
144
+ ),
145
+ );
146
+ }
147
+ }
148
+ if (!defaultParameters[parameter]) {
149
+ throw new Error(`No default parameter for ${parameter}`);
150
+ }
151
+ const defaultParameterValues = defaultParameters[parameter][property];
152
+ propertiesValues[property].push(defaultParameterValues({ jCoupling }));
153
+ }
154
+ }
155
+
156
+ const fromIndex = index;
157
+ const toIndex = fromIndex + parameters.length - 1;
158
+
159
+ const fromIndexCoupling = toIndex + 1;
160
+ const toIndexCoupling = fromIndexCoupling + signal.js.length - 1;
161
+
162
+ index += toIndexCoupling - fromIndex + 1;
163
+ internalSignals.push({
164
+ shape: shape as Shape1DWithFWHM,
165
+ shapeFct,
166
+ signal,
167
+ parameters,
168
+ propertiesValues,
169
+ fromIndex,
170
+ toIndex,
171
+ fromIndexCoupling,
172
+ toIndexCoupling,
173
+ });
174
+ }
175
+
176
+ return internalSignals;
177
+ }
178
+
179
+ function normalizeSignals<T extends Signal>(options: {
180
+ signals: T[];
181
+ data: DataXY;
182
+ shiftValue: number;
183
+ frequency: number;
184
+ range: number;
185
+ }) {
186
+ const { signals, data, frequency, shiftValue, range } = options;
187
+
188
+ const getMaxIntensity = (signal: Signal) => {
189
+ const peaks = signalsToPointXY([signal], { frequency, maxClusterSize: 1 });
190
+ const biggestPeak = peaks.reduce(
191
+ (biggest, peak) => (peak.y > biggest.y ? peak : biggest),
192
+ peaks[0],
193
+ );
194
+ const { y: maxIntensity } = xyFindClosestPoint(data, biggestPeak.x);
195
+ return maxIntensity;
196
+ };
197
+
198
+ return signals.map((signal) => {
199
+ const { intensity = getMaxIntensity(signal) } = signal;
200
+ return {
201
+ ...signal,
202
+ js: signal.js || [],
203
+ intensity: (intensity - shiftValue) / range,
204
+ };
205
+ });
206
+ }
207
+
208
+ function getPropertyValue(options: {
209
+ signal: Signal;
210
+ parameter: Parameter;
211
+ property: string;
212
+ minMaxY: Record<string, number>;
213
+ shapeFct: Shape1DInstance;
214
+ frequency: number;
215
+ baseline?: number;
216
+ parameters?: ParametersFromOptions;
217
+ }) {
218
+ const { signal, frequency, parameter, property, minMaxY, shapeFct } = options;
219
+
220
+ // check if the property is specified in the signal
221
+ let propertyValue = signal?.parameters?.[parameter]?.[property];
222
+ if (propertyValue) {
223
+ return getNormalizedValue(
224
+ propertyValue,
225
+ parameter,
226
+ property,
227
+ minMaxY,
228
+ frequency,
229
+ options.baseline,
230
+ );
231
+ }
232
+
233
+ // check if there are some global option, it could be a number or a callback
234
+
235
+ let generalParameterValue = options?.parameters?.[parameter]?.[property];
236
+ if (generalParameterValue) {
237
+ if (typeof generalParameterValue === 'number') {
238
+ return getNormalizedValue(
239
+ generalParameterValue,
240
+ parameter,
241
+ property,
242
+ minMaxY,
243
+ frequency,
244
+ options.baseline,
245
+ );
246
+ } else {
247
+ let value = generalParameterValue(signal);
248
+ return getNormalizedValue(
249
+ value,
250
+ parameter,
251
+ property,
252
+ minMaxY,
253
+ frequency,
254
+ options.baseline,
255
+ );
256
+ }
257
+ }
258
+
259
+ // we just need to take the default parameters
260
+ if (!defaultParameters[parameter]) {
261
+ throw new Error(`No default parameter for ${parameter}`);
262
+ }
263
+ const defaultParameterValues = defaultParameters[parameter][property];
264
+ return defaultParameterValues({ signal, shape: shapeFct });
265
+ }
266
+
267
+ function getNormalizedValue(
268
+ value: number,
269
+ parameter: keyof ParametersFromOptions,
270
+ property: string,
271
+ minMaxY: Record<string, number>,
272
+ frequency: number,
273
+ baseline?: number,
274
+ ) {
275
+ if (parameter === 'intensity') {
276
+ if (property === 'gradientDifference') {
277
+ return value;
278
+ } else {
279
+ return baseline !== undefined
280
+ ? (value - baseline) / minMaxY.range
281
+ : (value - minMaxY.min) / minMaxY.range;
282
+ }
283
+ } else if (parameter === 'fwhm') {
284
+ return value / frequency;
285
+ }
286
+ return value;
287
+ }
@@ -0,0 +1,54 @@
1
+ import { InternalSignal } from './getInternalSignals';
2
+ import { signalsToPointXY, SignalsToPointXYOptions } from './signalsToPointXY';
3
+
4
+ export type SumOfShapes = (parameters: number[]) => (x: number) => number;
5
+
6
+ const defaultSimulationOptions: Partial<SignalsToPointXYOptions> = {
7
+ maxClusterSize: 1,
8
+ };
9
+ export function getSumOfShapes(
10
+ internalSignals: InternalSignal[],
11
+ options: SignalsToPointXYOptions,
12
+ ) {
13
+ const simulationOptions = { ...defaultSimulationOptions, ...options };
14
+ return function sumOfShapes(parameters: number[]) {
15
+ const peaks: any = [];
16
+ for (const internalSignal of internalSignals) {
17
+ const delta = parameters[internalSignal.fromIndex];
18
+ const intensity = parameters[internalSignal.fromIndex + 1];
19
+ for (let i = 2; i < internalSignal.parameters.length; i++) {
20
+ //@ts-expect-error Not simply to solve the issue
21
+ internalSignal.shapeFct[internalSignal.parameters[i]] =
22
+ parameters[internalSignal.fromIndex + i];
23
+ }
24
+ const couplings = internalSignal.signal.js;
25
+ for (let i = 0; i < couplings.length; i++) {
26
+ couplings[i].coupling =
27
+ parameters[internalSignal.fromIndexCoupling + i];
28
+ }
29
+ const currentPeaks = signalsToPointXY(
30
+ [
31
+ {
32
+ delta,
33
+ js: couplings,
34
+ },
35
+ ],
36
+ simulationOptions,
37
+ );
38
+
39
+ peaks.push(
40
+ ...currentPeaks.map((peak) => {
41
+ return { intensity, shape: internalSignal.shapeFct, ...peak };
42
+ }),
43
+ );
44
+ }
45
+ return (currentX: number) => {
46
+ let totalY = 0;
47
+ for (let peak of peaks) {
48
+ const { x, y, intensity, shape } = peak;
49
+ totalY += y * intensity * shape.fct(currentX - x);
50
+ }
51
+ return totalY;
52
+ };
53
+ };
54
+ }
@@ -0,0 +1,37 @@
1
+ import { NMRSignal1D } from '../NMRSignal1D';
2
+ import { addDummySignals } from '../addDummySignals';
3
+ import { signalsToSpinSystem } from '../simulation/signalsToSpinSystem';
4
+ import { simulateXYPeaks } from '../simulation/simulateXYPeaks';
5
+ import { splitSpinSystem } from '../simulation/splitSpinSystem';
6
+
7
+ export interface SignalsToPointXYOptions {
8
+ frequency: number;
9
+ maxClusterSize?: number;
10
+ }
11
+
12
+ export function signalsToPointXY(
13
+ signals: NMRSignal1D[],
14
+ options: SignalsToPointXYOptions,
15
+ ) {
16
+ const { frequency, maxClusterSize = 1 } = options;
17
+ const completeSignalSet = addDummySignals(signals);
18
+
19
+ const spinSystem = signalsToSpinSystem(completeSignalSet);
20
+ spinSystem.clusters = splitSpinSystem(spinSystem, {
21
+ frequency,
22
+ maxClusterSize,
23
+ });
24
+ const pointsXY = simulateXYPeaks(spinSystem, options).filter(
25
+ (point) => point.x < 1000,
26
+ );
27
+
28
+ const maxIntensity = pointsXY.reduce(
29
+ (max, peak) => (peak.y > max ? peak.y : max),
30
+ Number.MIN_SAFE_INTEGER,
31
+ );
32
+
33
+ for (const point of pointsXY) {
34
+ point.y /= maxIntensity;
35
+ }
36
+ return pointsXY;
37
+ }
@@ -0,0 +1,173 @@
1
+ import { v4 } from '@lukeed/uuid';
2
+ import { DataXY } from 'cheminfo-types';
3
+ import { levenbergMarquardt } from 'ml-levenberg-marquardt';
4
+ import { getShape1D, Shape1D } from 'ml-peak-shape-generator';
5
+ import { xMinMaxValues } from 'ml-spectra-processing';
6
+
7
+ import { NMRPeak1D } from '../peaks/NMRPeak1D';
8
+
9
+ import { NMRSignal1D } from './NMRSignal1D';
10
+ import { directOptimization } from './optimization/directOptimization';
11
+ import {
12
+ getInternalSignals,
13
+ ParametersFromOptions,
14
+ Shape1DWithFWHM,
15
+ } from './optimization/getInternalSignals';
16
+ import { getSumOfShapes } from './optimization/getSumOfShapes';
17
+ import {
18
+ signalsToPointXY,
19
+ SignalsToPointXYOptions,
20
+ } from './optimization/signalsToPointXY';
21
+
22
+ const defaultLMOptimizationOptions = {
23
+ damping: 1.5,
24
+ maxIterations: 100,
25
+ errorTolerance: 1e-8,
26
+ };
27
+
28
+ const defaultDirectOptimizationOptions = {
29
+ iterations: 25,
30
+ };
31
+
32
+ type ParametersFromSignal = Record<string, Record<string, number>>;
33
+
34
+ export interface Signal extends NMRSignal1D {
35
+ intensity?: number;
36
+ shape?: Shape1D;
37
+ parameters?: ParametersFromSignal;
38
+ }
39
+
40
+ export interface NMRPeak1DFull extends NMRPeak1D {
41
+ id: string;
42
+ shape: Shape1DWithFWHM;
43
+ width: number;
44
+ }
45
+
46
+ export interface OptimizeSignalsOptions {
47
+ /**
48
+ * Initial line width in Hz
49
+ * @default 1
50
+ */
51
+ lineWidth?: number;
52
+ baseline?: number;
53
+ shape?: Shape1D;
54
+ parameters?: ParametersFromOptions;
55
+ optimization?: any;
56
+ simulation: SignalsToPointXYOptions;
57
+ }
58
+
59
+ export function optimizeSignals(
60
+ data: DataXY,
61
+ signals: Signal[],
62
+ options: OptimizeSignalsOptions,
63
+ ) {
64
+ const {
65
+ optimization = {},
66
+ simulation: simulationOptions,
67
+ ...restOptions
68
+ } = options;
69
+ let temp = xMinMaxValues(data.y);
70
+ const minMaxY = { ...temp, range: temp.max - temp.min };
71
+
72
+ const internalSignals = getInternalSignals(data, signals, minMaxY, {
73
+ frequency: simulationOptions.frequency,
74
+ ...restOptions,
75
+ });
76
+ const { baseline: shiftValue = minMaxY.min } = options;
77
+ let normalizedY = new Float64Array(data.y.length);
78
+ for (let i = 0; i < data.y.length; i++) {
79
+ normalizedY[i] = (data.y[i] - shiftValue) / minMaxY.range;
80
+ }
81
+
82
+ const nbParams =
83
+ internalSignals[internalSignals.length - 1].toIndexCoupling + 1;
84
+ const minValues = new Float64Array(nbParams);
85
+ const maxValues = new Float64Array(nbParams);
86
+ const initialValues = new Float64Array(nbParams);
87
+ const gradientDifferences = new Float64Array(nbParams);
88
+ let index = 0;
89
+ for (const internalSignal of internalSignals) {
90
+ for (let i = 0; i < internalSignal.parameters.length; i++) {
91
+ minValues[index] = internalSignal.propertiesValues.min[i];
92
+ maxValues[index] = internalSignal.propertiesValues.max[i];
93
+ initialValues[index] = internalSignal.propertiesValues.init[i];
94
+ gradientDifferences[index++] =
95
+ internalSignal.propertiesValues.gradientDifference[i];
96
+ }
97
+ for (
98
+ let i = internalSignal.parameters.length;
99
+ i < internalSignal.parameters.length + internalSignal.signal.js.length;
100
+ i++
101
+ ) {
102
+ minValues[index] = internalSignal.propertiesValues.min[i];
103
+ maxValues[index] = internalSignal.propertiesValues.max[i];
104
+ initialValues[index] = internalSignal.propertiesValues.init[i];
105
+ gradientDifferences[index++] =
106
+ internalSignal.propertiesValues.gradientDifference[i];
107
+ }
108
+ }
109
+ const sumOfShapes = getSumOfShapes(internalSignals, simulationOptions);
110
+
111
+ const { kind, options: optimizationOptions } = optimization;
112
+
113
+ const [algorithm, defaultOptimizationOptions] =
114
+ kind === 'direct'
115
+ ? [directOptimization, defaultDirectOptimizationOptions]
116
+ : [levenbergMarquardt, defaultLMOptimizationOptions];
117
+
118
+ let fitted = algorithm({ x: data.x, y: normalizedY }, sumOfShapes, {
119
+ minValues,
120
+ maxValues,
121
+ initialValues,
122
+ gradientDifference: gradientDifferences,
123
+ ...defaultOptimizationOptions,
124
+ ...optimizationOptions,
125
+ });
126
+
127
+ const fittedValues = fitted.parameterValues;
128
+ const newSignals = [];
129
+
130
+ for (const internalSignal of internalSignals) {
131
+ const { fromIndexCoupling } = internalSignal;
132
+ const js = internalSignal.signal.js.map((jCoupling, i) => {
133
+ jCoupling.coupling = fittedValues[fromIndexCoupling + i];
134
+ return jCoupling;
135
+ });
136
+
137
+ const delta = fittedValues[internalSignal.fromIndex];
138
+ const pointXYs = signalsToPointXY([{ delta, js }], simulationOptions);
139
+
140
+ const intensity =
141
+ fittedValues[internalSignal.fromIndex + 1] * minMaxY.range + shiftValue;
142
+
143
+ const newPeaks: NMRPeak1DFull[] = [];
144
+ for (const { x, y } of pointXYs) {
145
+ const peak = {
146
+ id: v4(),
147
+ x,
148
+ y: intensity * y,
149
+ width: 0,
150
+ shape: { ...internalSignal.shape },
151
+ };
152
+ for (let i = 2; i < internalSignal.parameters.length; i++) {
153
+ //@ts-expect-error should be fixed once
154
+ peak.shape[internalSignal.parameters[i]] =
155
+ fittedValues[internalSignal.fromIndex + i];
156
+ }
157
+
158
+ peak.shape.fwhm *= simulationOptions.frequency;
159
+ peak.width = getShape1D(peak.shape).fwhmToWidth(peak.shape.fwhm);
160
+ newPeaks.push(peak);
161
+ }
162
+
163
+ newSignals.push({
164
+ delta,
165
+ js,
166
+ shape: { ...newPeaks[0].shape },
167
+ intensity,
168
+ peaks: newPeaks,
169
+ });
170
+ }
171
+
172
+ return newSignals;
173
+ }
@@ -6,8 +6,8 @@ import { signalJoinCouplings } from '../signal/signalJoinCouplings';
6
6
  import type { SignalJoinCouplingsOptions } from '../signal/signalJoinCouplings';
7
7
  import type { MakeMandatory } from '../utilities/MakeMandatory';
8
8
 
9
+ import type { Jcoupling } from './Jcoupling';
9
10
  import type { NMRSignal1D } from './NMRSignal1D';
10
- import type { Jcoupling } from './jcoupling';
11
11
 
12
12
  export interface SignalsJoinOptions {
13
13
  /**
@@ -4,8 +4,8 @@ import { xSequentialFill } from 'ml-spectra-processing';
4
4
 
5
5
  import type { MakeMandatory } from '../utilities/MakeMandatory';
6
6
 
7
+ import type { Jcoupling } from './Jcoupling';
7
8
  import type { NMRSignal1D } from './NMRSignal1D';
8
- import type { Jcoupling } from './jcoupling';
9
9
  import { signalsToSpinSystem } from './simulation/signalsToSpinSystem';
10
10
  import simulate1D from './simulation/simulate1D';
11
11
  import { splitSpinSystem } from './simulation/splitSpinSystem';
@@ -2,8 +2,8 @@ import { Matrix } from 'ml-matrix';
2
2
  import simpleClustering from 'ml-simple-clustering';
3
3
 
4
4
  import type { MakeMandatory } from '../../utilities/MakeMandatory';
5
+ import type { Jcoupling } from '../Jcoupling';
5
6
  import type { NMRSignal1D } from '../NMRSignal1D';
6
- import type { Jcoupling } from '../jcoupling';
7
7
  import type { SpinSystem } from '../spinSystem';
8
8
 
9
9
  interface Ids {
@@ -207,7 +207,6 @@ export function simulateXYPeaks(
207
207
  }
208
208
 
209
209
  const numFreq = frequencies.length;
210
-
211
210
  if (numFreq > 0) {
212
211
  weight /= sumI;
213
212
  const diff = lineWidth / 64;
@@ -237,7 +236,7 @@ export function simulateXYPeaks(
237
236
  }
238
237
  }
239
238
 
240
- return xyPeaks;
239
+ return xyPeaks.filter((peak) => peak.x < 1000);
241
240
  }
242
241
 
243
242
  function triuTimesAbs(A: SparseMatrix, val: number) {
@@ -8,7 +8,9 @@ import {
8
8
  OptimizePeaksOptions,
9
9
  JoinBroadPeaksOptions,
10
10
  GSDPeakOptimizedID,
11
+ setShape,
11
12
  } from 'ml-gsd';
13
+ import { Shape1D } from 'ml-peak-shape-generator';
12
14
  import {
13
15
  xyExtract,
14
16
  xNoiseSanPlot,
@@ -77,12 +79,13 @@ export interface OptionsXYAutoPeaksPicking extends Partial<GetPeakListOptions> {
77
79
  frequency: number;
78
80
  }
79
81
 
80
- export type NMRPeak1DWithID = MakeMandatory<NMRPeak1D, 'id'>;
82
+ type GSDPeakShapeID = GSDPeakID & { shape: Shape1D };
83
+ export type NMRPeak1DWithShapeID = MakeMandatory<NMRPeak1D, 'id' | 'shape'>;
81
84
 
82
85
  export function xyAutoPeaksPicking(
83
86
  data: DataXY,
84
87
  options: OptionsXYAutoPeaksPicking,
85
- ): NMRPeak1DWithID[] {
88
+ ): NMRPeak1DWithShapeID[] {
86
89
  const {
87
90
  from,
88
91
  to,
@@ -177,8 +180,7 @@ function getPeakList(data: DataXY, options: GetPeakListOptions) {
177
180
  realTopDetection,
178
181
  } = options;
179
182
 
180
- let peakList = gsd(data, {
181
- shape,
183
+ const peaks = gsd(data, {
182
184
  sgOptions,
183
185
  maxCriteria,
184
186
  minMaxRatio,
@@ -187,6 +189,8 @@ function getPeakList(data: DataXY, options: GetPeakListOptions) {
187
189
  realTopDetection,
188
190
  });
189
191
 
192
+ const peakList = setShape(peaks, { output: peaks, shape });
193
+
190
194
  const newPeaks = broadWidth
191
195
  ? joinBroadPeaks(peakList, {
192
196
  broadRatio,
@@ -226,8 +230,8 @@ function getCutOff(data: number[] | Float64Array, options: OptionsGetCutOff) {
226
230
  }
227
231
 
228
232
  function toNMRPeak1DStructure(
229
- peak: GSDPeakID | GSDPeakOptimizedID,
230
- ): NMRPeak1DWithID {
233
+ peak: GSDPeakShapeID | GSDPeakOptimizedID,
234
+ ): NMRPeak1DWithShapeID {
231
235
  const { id, shape, x, y, width } = peak;
232
236
  return {
233
237
  id,
@@ -10,6 +10,7 @@ export interface XYPeaksOptimizationOptions extends OptimizePeaksOptions {
10
10
  */
11
11
  frequency: number;
12
12
  }
13
+
13
14
  export function xyPeaksOptimization<T extends PeakXYWidth>(
14
15
  data: DataXY,
15
16
  peaks: T[],
@@ -18,8 +19,9 @@ export function xyPeaksOptimization<T extends PeakXYWidth>(
18
19
  const { frequency } = options;
19
20
  const newPeaks = convertWidthToPPM(peaks, { frequency });
20
21
  const optimizedPeaks = optimizePeaks(data, newPeaks, options);
21
- return convertWidthToHz(optimizedPeaks, {
22
+ const result = convertWidthToHz(optimizedPeaks, {
22
23
  frequency,
23
24
  output: optimizedPeaks,
24
25
  });
26
+ return result;
25
27
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"prediction1D.js","sourceRoot":"","sources":["../../src/prediction/prediction1D.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"jcoupling.js","sourceRoot":"","sources":["../../src/signals/jcoupling.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=prediction1D.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prediction1D.js","sourceRoot":"","sources":["../../src/prediction/prediction1D.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=jcoupling.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jcoupling.js","sourceRoot":"","sources":["../../src/signals/jcoupling.ts"],"names":[],"mappings":""}