nmr-processing 9.4.1 → 9.4.2-pre.1684301205

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 (128) hide show
  1. package/lib/constants/MultiplicityPatterns.d.ts +1 -0
  2. package/lib/constants/MultiplicityPatterns.js +3 -1
  3. package/lib/constants/MultiplicityPatterns.js.map +1 -1
  4. package/lib/constants/couplingPatterns.d.ts +1 -0
  5. package/lib/constants/couplingPatterns.js +5 -1
  6. package/lib/constants/couplingPatterns.js.map +1 -1
  7. package/lib/index.d.ts +6 -1
  8. package/lib/index.js +6 -1
  9. package/lib/index.js.map +1 -1
  10. package/lib/multiplicity/checkMultiplet.d.ts +1 -0
  11. package/lib/multiplicity/checkMultiplet.js +13 -0
  12. package/lib/multiplicity/checkMultiplet.js.map +1 -0
  13. package/lib/multiplicity/checkMultiplicity.d.ts +1 -0
  14. package/lib/multiplicity/checkMultiplicity.js +17 -0
  15. package/lib/multiplicity/checkMultiplicity.js.map +1 -0
  16. package/lib/multiplicity/findMultiplet.d.ts +1 -0
  17. package/lib/multiplicity/findMultiplet.js +12 -0
  18. package/lib/multiplicity/findMultiplet.js.map +1 -0
  19. package/lib/multiplicity/joinPatterns.d.ts +3 -0
  20. package/lib/{utilities → multiplicity}/joinPatterns.js +2 -2
  21. package/lib/multiplicity/joinPatterns.js.map +1 -0
  22. package/lib/multiplicity/splitPatterns.js.map +1 -0
  23. package/lib/multiplicity/translateMultiplet.d.ts +1 -0
  24. package/lib/multiplicity/translateMultiplet.js +14 -0
  25. package/lib/multiplicity/translateMultiplet.js.map +1 -0
  26. package/lib/ranges/rangesToACS.js +1 -0
  27. package/lib/ranges/rangesToACS.js.map +1 -1
  28. package/lib/signal/signalJoinCouplings.d.ts +5 -0
  29. package/lib/signal/signalJoinCouplings.js +7 -6
  30. package/lib/signal/signalJoinCouplings.js.map +1 -1
  31. package/lib/signal/signalMultiplicityPattern.d.ts +3 -1
  32. package/lib/signal/signalMultiplicityPattern.js +6 -2
  33. package/lib/signal/signalMultiplicityPattern.js.map +1 -1
  34. package/lib/utilities/normalizeNucleus.d.ts +1 -0
  35. package/lib/utilities/normalizeNucleus.js +22 -0
  36. package/lib/utilities/normalizeNucleus.js.map +1 -0
  37. package/lib/utilities/nucleusMap.d.ts +5 -0
  38. package/lib/utilities/nucleusMap.js +22 -0
  39. package/lib/utilities/nucleusMap.js.map +1 -0
  40. package/lib/utilities/resurrectRange.js +1 -1
  41. package/lib/utilities/resurrectRange.js.map +1 -1
  42. package/lib/utilities/selectACSPattern.d.ts +1 -0
  43. package/lib/utilities/selectACSPattern.js +14 -0
  44. package/lib/utilities/selectACSPattern.js.map +1 -0
  45. package/lib/xyz/Data2D.d.ts +7 -0
  46. package/lib/xyz/Data2D.js +3 -0
  47. package/lib/xyz/Data2D.js.map +1 -0
  48. package/lib/xyz/util/formatZone.d.ts +2 -1
  49. package/lib/xyz/util/formatZone.js.map +1 -1
  50. package/lib/xyz/util/padData.d.ts +10 -0
  51. package/lib/xyz/util/padData.js +38 -0
  52. package/lib/xyz/util/padData.js.map +1 -0
  53. package/lib/xyz/xyzAutoSignalsPicking.d.ts +84 -0
  54. package/lib/xyz/xyzAutoSignalsPicking.js +193 -0
  55. package/lib/xyz/xyzAutoSignalsPicking.js.map +1 -0
  56. package/lib/xyz/xyzAutoZonesPicking.d.ts +0 -22
  57. package/lib/xyz/xyzAutoZonesPicking.js +2 -214
  58. package/lib/xyz/xyzAutoZonesPicking.js.map +1 -1
  59. package/lib-esm/constants/MultiplicityPatterns.js +3 -1
  60. package/lib-esm/constants/MultiplicityPatterns.js.map +1 -1
  61. package/lib-esm/constants/couplingPatterns.js +4 -0
  62. package/lib-esm/constants/couplingPatterns.js.map +1 -1
  63. package/lib-esm/index.js +6 -1
  64. package/lib-esm/index.js.map +1 -1
  65. package/lib-esm/multiplicity/checkMultiplet.js +9 -0
  66. package/lib-esm/multiplicity/checkMultiplet.js.map +1 -0
  67. package/lib-esm/multiplicity/checkMultiplicity.js +13 -0
  68. package/lib-esm/multiplicity/checkMultiplicity.js.map +1 -0
  69. package/lib-esm/multiplicity/findMultiplet.js +8 -0
  70. package/lib-esm/multiplicity/findMultiplet.js.map +1 -0
  71. package/lib-esm/{utilities → multiplicity}/joinPatterns.js +3 -3
  72. package/lib-esm/multiplicity/joinPatterns.js.map +1 -0
  73. package/lib-esm/multiplicity/splitPatterns.js.map +1 -0
  74. package/lib-esm/multiplicity/translateMultiplet.js +10 -0
  75. package/lib-esm/multiplicity/translateMultiplet.js.map +1 -0
  76. package/lib-esm/ranges/rangesToACS.js +1 -0
  77. package/lib-esm/ranges/rangesToACS.js.map +1 -1
  78. package/lib-esm/signal/signalJoinCouplings.js +7 -6
  79. package/lib-esm/signal/signalJoinCouplings.js.map +1 -1
  80. package/lib-esm/signal/signalMultiplicityPattern.js +6 -2
  81. package/lib-esm/signal/signalMultiplicityPattern.js.map +1 -1
  82. package/lib-esm/utilities/normalizeNucleus.js +18 -0
  83. package/lib-esm/utilities/normalizeNucleus.js.map +1 -0
  84. package/lib-esm/utilities/nucleusMap.js +19 -0
  85. package/lib-esm/utilities/nucleusMap.js.map +1 -0
  86. package/lib-esm/utilities/resurrectRange.js +1 -1
  87. package/lib-esm/utilities/resurrectRange.js.map +1 -1
  88. package/lib-esm/utilities/selectACSPattern.js +10 -0
  89. package/lib-esm/utilities/selectACSPattern.js.map +1 -0
  90. package/lib-esm/xyz/Data2D.js +2 -0
  91. package/lib-esm/xyz/Data2D.js.map +1 -0
  92. package/lib-esm/xyz/util/formatZone.js.map +1 -1
  93. package/lib-esm/xyz/util/padData.js +31 -0
  94. package/lib-esm/xyz/util/padData.js.map +1 -0
  95. package/lib-esm/xyz/xyzAutoSignalsPicking.js +163 -0
  96. package/lib-esm/xyz/xyzAutoSignalsPicking.js.map +1 -0
  97. package/lib-esm/xyz/xyzAutoZonesPicking.js +2 -188
  98. package/lib-esm/xyz/xyzAutoZonesPicking.js.map +1 -1
  99. package/package.json +1 -1
  100. package/src/constants/MultiplicityPatterns.ts +4 -1
  101. package/src/constants/couplingPatterns.ts +9 -0
  102. package/src/index.ts +7 -1
  103. package/src/multiplicity/checkMultiplet.ts +11 -0
  104. package/src/multiplicity/checkMultiplicity.ts +21 -0
  105. package/src/multiplicity/findMultiplet.ts +8 -0
  106. package/src/{utilities → multiplicity}/joinPatterns.ts +9 -3
  107. package/src/multiplicity/translateMultiplet.ts +11 -0
  108. package/src/ranges/rangesToACS.ts +1 -0
  109. package/src/signal/signalJoinCouplings.ts +12 -5
  110. package/src/signal/signalMultiplicityPattern.ts +9 -2
  111. package/src/utilities/normalizeNucleus.ts +24 -0
  112. package/src/utilities/nucleusMap.ts +40 -0
  113. package/src/utilities/resurrectRange.ts +1 -1
  114. package/src/utilities/selectACSPattern.ts +10 -0
  115. package/src/xyz/Data2D.ts +7 -0
  116. package/src/xyz/util/formatZone.ts +2 -1
  117. package/src/xyz/util/padData.ts +37 -0
  118. package/src/xyz/xyzAutoSignalsPicking.ts +309 -0
  119. package/src/xyz/xyzAutoZonesPicking.ts +2 -276
  120. package/lib/utilities/joinPatterns.d.ts +0 -1
  121. package/lib/utilities/joinPatterns.js.map +0 -1
  122. package/lib/utilities/splitPatterns.js.map +0 -1
  123. package/lib-esm/utilities/joinPatterns.js.map +0 -1
  124. package/lib-esm/utilities/splitPatterns.js.map +0 -1
  125. /package/lib/{utilities → multiplicity}/splitPatterns.d.ts +0 -0
  126. /package/lib/{utilities → multiplicity}/splitPatterns.js +0 -0
  127. /package/lib-esm/{utilities → multiplicity}/splitPatterns.js +0 -0
  128. /package/src/{utilities → multiplicity}/splitPatterns.ts +0 -0
@@ -0,0 +1,309 @@
1
+ import { v4 as generateID } from '@lukeed/uuid';
2
+ import * as convolution from 'ml-matrix-convolution';
3
+ import * as matrixPeakFinders from 'ml-matrix-peaks-finder';
4
+ import type { Peak2D } from 'ml-matrix-peaks-finder';
5
+ import simpleClustering from 'ml-simple-clustering';
6
+
7
+ import { addMissingIDs } from '../peaks/util/addMissingIDs';
8
+ import { determineRealTop } from '../peaks/util/determineRealTop';
9
+ import { getKernel } from '../peaks/util/getKernel';
10
+ import type { GetKernelOptions } from '../peaks/util/getKernel';
11
+ import * as PeakOptimizer from '../peaks/util/peakOptimizer';
12
+ import { MakeMandatory } from '../utilities/MakeMandatory';
13
+
14
+ import { Data2D } from './Data2D';
15
+ import type { NMRSignal2D } from './NMRSignal2D';
16
+ import { padData } from './util/padData';
17
+
18
+ const smallFilter = [
19
+ [0, 0, 1, 2, 2, 2, 1, 0, 0],
20
+ [0, 1, 4, 7, 7, 7, 4, 1, 0],
21
+ [1, 4, 5, 3, 0, 3, 5, 4, 1],
22
+ [2, 7, 3, -12, -23, -12, 3, 7, 2],
23
+ [2, 7, 0, -23, -40, -23, 0, 7, 2],
24
+ [2, 7, 3, -12, -23, -12, 3, 7, 2],
25
+ [1, 4, 5, 3, 0, 3, 5, 4, 1],
26
+ [0, 1, 3, 7, 7, 7, 3, 1, 0],
27
+ [0, 0, 1, 2, 2, 2, 1, 0, 0],
28
+ ];
29
+
30
+ export interface XYZAutoSignalsPickingOptions {
31
+ /**
32
+ * max number of points in any dimension to pad the input data, this is needed to avoid lost peaks when the input matrix is too small.
33
+ * @default 14
34
+ */
35
+ sizeToPad?: number;
36
+ /**
37
+ * If it's true, try to find the real maximum for each bidimensional peak.
38
+ * @default true
39
+ */
40
+ realTopDetection?: boolean;
41
+ /**
42
+ * positive value filter small peaks by intensity
43
+ * @default 0.5
44
+ */
45
+ thresholdFactor?: number;
46
+ /**
47
+ * specify the nuclei of each dimension
48
+ * @default ['1H','1H']
49
+ */
50
+ nuclei?: string[];
51
+ /**
52
+ * specify the frequency for each dimension.
53
+ */
54
+ observedFrequencies: number[] | Float64Array;
55
+ /**
56
+ * If it's true, it try to ajust the shift and add missing cross peaks, useful only for homonuclear data.
57
+ * @default false
58
+ */
59
+ enhanceSymmetry?: boolean;
60
+ /**
61
+ * If it's true, peaks with less than a specific percentage (maxPercentCutOff) of the maximum intensity will be removed.
62
+ * @default true;
63
+ */
64
+ clean?: boolean;
65
+ /**
66
+ * percentage of maximum intensity as cutoff for small peaks.
67
+ * @default 0.03
68
+ */
69
+ maxPercentCutOff?: number;
70
+ /**
71
+ * Specify the minimum distance in Hz for each dimension to join peaks in a signal.
72
+ * @default [24,24]
73
+ */
74
+ tolerances?: number[];
75
+ /**
76
+ * If it is true, the convolution will be forced by FFT
77
+ * @default true
78
+ */
79
+ convolutionByFFT?: boolean;
80
+ /**
81
+ * kernel options to calculate a laplacianOfGaussian kernel with a specify size.
82
+ */
83
+ kernel?: GetKernelOptions;
84
+ }
85
+
86
+ export type NMRSignal2DWithID<T extends Peak2D = Peak2D> = MakeMandatory<
87
+ NMRSignal2D<T>,
88
+ 'id'
89
+ >;
90
+
91
+ export function xyzAutoSignalsPicking(
92
+ spectraData: Data2D,
93
+ options: XYZAutoSignalsPickingOptions,
94
+ ) {
95
+ let {
96
+ sizeToPad = 14,
97
+ realTopDetection = true,
98
+ thresholdFactor = 0.5,
99
+ nuclei = ['1H', '1H'],
100
+ observedFrequencies,
101
+ enhanceSymmetry = false,
102
+ clean = true,
103
+ maxPercentCutOff = 0.03,
104
+ tolerances = [24, 24],
105
+ convolutionByFFT = true,
106
+ kernel: kernelOptions,
107
+ } = options;
108
+
109
+ if (
110
+ !Array.isArray(observedFrequencies) &&
111
+ !ArrayBuffer.isView(observedFrequencies)
112
+ ) {
113
+ throw new Error('observedFrequencies is mandatory');
114
+ }
115
+
116
+ thresholdFactor = thresholdFactor === 0 ? 1 : Math.abs(thresholdFactor);
117
+
118
+ let nbPoints = spectraData.z[0].length;
119
+ let nbSubSpectra = spectraData.z.length;
120
+
121
+ if (nbSubSpectra < sizeToPad) {
122
+ spectraData = padData(spectraData, { width: sizeToPad });
123
+ nbPoints = spectraData.z[0].length;
124
+ nbSubSpectra = spectraData.z.length;
125
+ }
126
+
127
+ let absoluteData = new Float64Array(nbPoints * nbSubSpectra);
128
+ let originalData = new Float64Array(nbPoints * nbSubSpectra);
129
+
130
+ for (let iSubSpectra = 0; iSubSpectra < nbSubSpectra; iSubSpectra++) {
131
+ let spectrum = spectraData.z[iSubSpectra];
132
+ for (let iCol = 0; iCol < nbPoints; iCol++) {
133
+ let index = iSubSpectra * nbPoints + iCol;
134
+ absoluteData[index] = Math.abs(spectrum[iCol]);
135
+ originalData[index] = spectrum[iCol]; //@todo pensar si se puede evitar originalData
136
+ }
137
+ }
138
+
139
+ const kernel = kernelOptions ? getKernel(kernelOptions) : smallFilter;
140
+
141
+ let convolutedSpectrum = convolutionByFFT
142
+ ? convolution.fft(absoluteData, kernel, {
143
+ rows: nbSubSpectra,
144
+ cols: nbPoints,
145
+ })
146
+ : convolution.direct(absoluteData, kernel, {
147
+ rows: nbSubSpectra,
148
+ cols: nbPoints,
149
+ });
150
+
151
+ let peaksMC1 = matrixPeakFinders.findPeaks2DRegion(absoluteData, {
152
+ originalData,
153
+ filteredData: convolutedSpectrum,
154
+ rows: nbSubSpectra,
155
+ cols: nbPoints,
156
+ nStdDev: thresholdFactor,
157
+ });
158
+
159
+ if (clean) {
160
+ // Remove peaks with less than x% of the intensity of the highest peak
161
+ peaksMC1 = PeakOptimizer.clean(peaksMC1, maxPercentCutOff);
162
+ }
163
+
164
+ let signals = createSignals2D(addMissingIDs(peaksMC1), {
165
+ nRows: nbSubSpectra,
166
+ nCols: nbPoints,
167
+ minX: spectraData.minX,
168
+ maxX: spectraData.maxX,
169
+ minY: spectraData.minY,
170
+ maxY: spectraData.maxY,
171
+ absoluteData,
172
+ originalData,
173
+ tolerances,
174
+ nuclei,
175
+ observedFrequencies,
176
+ realTopDetection,
177
+ });
178
+
179
+ if (enhanceSymmetry) {
180
+ signals = PeakOptimizer.enhanceSymmetry(signals);
181
+ }
182
+
183
+ return signals;
184
+ }
185
+
186
+ /**
187
+ * This function converts a set of 2D-peaks in 2D-signals. Each signal could be composed
188
+ * of many 2D-peaks, and it has some additional information related to the NMR spectrum.
189
+ * @private
190
+ */
191
+
192
+ export interface CreateSignals2DOptions {
193
+ nCols: number;
194
+ nRows: number;
195
+ absoluteData: number[] | Float64Array;
196
+ originalData: number[] | Float64Array;
197
+ observedFrequencies: number[] | Float64Array;
198
+ tolerances: number[];
199
+ nuclei: string[];
200
+ realTopDetection: boolean;
201
+ minY: number;
202
+ maxY: number;
203
+ minX: number;
204
+ maxX: number;
205
+ }
206
+
207
+ function createSignals2D<T extends Peak2D>(
208
+ peaks: T[],
209
+ options: CreateSignals2DOptions,
210
+ ) {
211
+ let {
212
+ nCols,
213
+ nRows,
214
+ absoluteData,
215
+ originalData,
216
+ observedFrequencies,
217
+ tolerances,
218
+ nuclei,
219
+ realTopDetection,
220
+ minY,
221
+ maxY,
222
+ minX,
223
+ maxX,
224
+ } = options;
225
+
226
+ let [nucleusX, nucleusY] = nuclei;
227
+ let [toleranceX, toleranceY] = tolerances;
228
+ let [observeFrequencyX, observeFrequencyY] = observedFrequencies;
229
+
230
+ let dy = (maxY - minY) / (nRows - 1);
231
+ let dx = (maxX - minX) / (nCols - 1);
232
+
233
+ if (realTopDetection) {
234
+ peaks = determineRealTop(peaks, {
235
+ nCols,
236
+ absoluteData,
237
+ originalData,
238
+ minX,
239
+ maxX,
240
+ minY,
241
+ maxY,
242
+ });
243
+ }
244
+
245
+ for (let i = peaks.length - 1; i >= 0; i--) {
246
+ let { x, y } = peaks[i];
247
+ peaks[i].x = minX + dx * x;
248
+ peaks[i].y = minY + dy * y;
249
+ peaks[i].minX = minX + dx * peaks[i].minX;
250
+ peaks[i].minY = minY + dy * peaks[i].minY;
251
+ peaks[i].maxX = minX + dx * peaks[i].maxX;
252
+ peaks[i].maxY = minY + dy * peaks[i].maxY;
253
+
254
+ // Still having problems to correctly detect peaks on those areas. So I'm removing everything there.
255
+ }
256
+ // The connectivity matrix is an square and symmetric matrix, so we'll only store the upper diagonal in an
257
+ // array like form
258
+ let connectivity = [];
259
+ for (let i = 0; i < peaks.length; i++) {
260
+ for (let j = i; j < peaks.length; j++) {
261
+ if (
262
+ Math.abs(peaks[i].x - peaks[j].x) * observeFrequencyX < toleranceX &&
263
+ Math.abs(peaks[i].y - peaks[j].y) * observeFrequencyY < toleranceY
264
+ ) {
265
+ // 24*24Hz We cannot distinguish peaks with less than 20 Hz of separation
266
+ connectivity.push(1);
267
+ } else {
268
+ connectivity.push(0);
269
+ }
270
+ }
271
+ }
272
+ let clusters = simpleClustering(connectivity);
273
+
274
+ let signals: NMRSignal2DWithID<T>[] = [];
275
+ if (clusters) {
276
+ for (const cluster of clusters) {
277
+ let signal: any = {
278
+ id: generateID(),
279
+ x: {
280
+ delta: 0,
281
+ nucleus: nucleusX,
282
+ resolution: dx,
283
+ },
284
+ y: {
285
+ delta: 0,
286
+ nucleus: nucleusY,
287
+ resolution: dy,
288
+ },
289
+ };
290
+ let peaks2D: T[] = [];
291
+ let sumZ = 0;
292
+
293
+ for (let jPeak = 0; jPeak < cluster.length; jPeak++) {
294
+ if (cluster[jPeak] === 1) {
295
+ peaks2D.push(peaks[jPeak]);
296
+ signal.x.delta += peaks[jPeak].x * peaks[jPeak].z;
297
+ signal.y.delta += peaks[jPeak].y * peaks[jPeak].z;
298
+ sumZ += peaks[jPeak].z;
299
+ }
300
+ }
301
+
302
+ signal.x.delta /= sumZ;
303
+ signal.y.delta /= sumZ;
304
+ signal.peaks = peaks2D;
305
+ signals.push(signal as NMRSignal2DWithID<T>);
306
+ }
307
+ }
308
+ return signals;
309
+ }
@@ -1,33 +1,10 @@
1
- import { v4 as generateID } from '@lukeed/uuid';
2
- import { Matrix } from 'ml-matrix';
3
- import * as convolution from 'ml-matrix-convolution';
4
- import * as matrixPeakFinders from 'ml-matrix-peaks-finder';
5
- import type { Peak2D } from 'ml-matrix-peaks-finder';
6
- import simpleClustering from 'ml-simple-clustering';
7
-
8
- import { addMissingIDs } from '../peaks/util/addMissingIDs';
9
- import { determineRealTop } from '../peaks/util/determineRealTop';
10
- import { getKernel } from '../peaks/util/getKernel';
1
+ import { xyzAutoSignalsPicking } from '..';
11
2
  import type { GetKernelOptions } from '../peaks/util/getKernel';
12
- import * as PeakOptimizer from '../peaks/util/peakOptimizer';
13
3
  import { MakeMandatory } from '../utilities/MakeMandatory';
14
4
 
15
- import type { NMRSignal2D } from './NMRSignal2D';
16
5
  import { NMRZone } from './NMRZone';
17
6
  import { formatZones } from './util/formatZone';
18
7
 
19
- const smallFilter = [
20
- [0, 0, 1, 2, 2, 2, 1, 0, 0],
21
- [0, 1, 4, 7, 7, 7, 4, 1, 0],
22
- [1, 4, 5, 3, 0, 3, 5, 4, 1],
23
- [2, 7, 3, -12, -23, -12, 3, 7, 2],
24
- [2, 7, 0, -23, -40, -23, 0, 7, 2],
25
- [2, 7, 3, -12, -23, -12, 3, 7, 2],
26
- [1, 4, 5, 3, 0, 3, 5, 4, 1],
27
- [0, 1, 3, 7, 7, 7, 3, 1, 0],
28
- [0, 0, 1, 2, 2, 2, 1, 0, 0],
29
- ];
30
-
31
8
  export interface Data2D {
32
9
  z: number[][] | Float64Array[];
33
10
  minX: number;
@@ -91,263 +68,12 @@ export interface XYZAutoZonesPickingOptions {
91
68
  */
92
69
  kernel?: GetKernelOptions;
93
70
  }
94
-
95
- export type NMRSignal2DWithID<T extends Peak2D = Peak2D> = MakeMandatory<
96
- NMRSignal2D<T>,
97
- 'id'
98
- >;
99
71
  export type NMRZoneWithID = MakeMandatory<NMRZone, 'id'>;
100
72
 
101
73
  export function xyzAutoZonesPicking(
102
74
  spectraData: Data2D,
103
75
  options: XYZAutoZonesPickingOptions,
104
76
  ): NMRZoneWithID[] {
105
- let {
106
- sizeToPad = 14,
107
- realTopDetection = true,
108
- thresholdFactor = 0.5,
109
- nuclei = ['1H', '1H'],
110
- observedFrequencies,
111
- enhanceSymmetry = false,
112
- clean = true,
113
- maxPercentCutOff = 0.03,
114
- tolerances = [24, 24],
115
- convolutionByFFT = true,
116
- kernel: kernelOptions,
117
- } = options;
118
-
119
- if (
120
- !Array.isArray(observedFrequencies) &&
121
- !ArrayBuffer.isView(observedFrequencies)
122
- ) {
123
- throw new Error('observedFrequencies is mandatory');
124
- }
125
-
126
- thresholdFactor = thresholdFactor === 0 ? 1 : Math.abs(thresholdFactor);
127
-
128
- let nbPoints = spectraData.z[0].length;
129
- let nbSubSpectra = spectraData.z.length;
130
-
131
- if (nbSubSpectra < sizeToPad) {
132
- spectraData = padData(spectraData, { width: sizeToPad });
133
- nbPoints = spectraData.z[0].length;
134
- nbSubSpectra = spectraData.z.length;
135
- }
136
-
137
- let absoluteData = new Float64Array(nbPoints * nbSubSpectra);
138
- let originalData = new Float64Array(nbPoints * nbSubSpectra);
139
-
140
- for (let iSubSpectra = 0; iSubSpectra < nbSubSpectra; iSubSpectra++) {
141
- let spectrum = spectraData.z[iSubSpectra];
142
- for (let iCol = 0; iCol < nbPoints; iCol++) {
143
- let index = iSubSpectra * nbPoints + iCol;
144
- absoluteData[index] = Math.abs(spectrum[iCol]);
145
- originalData[index] = spectrum[iCol]; //@todo pensar si se puede evitar originalData
146
- }
147
- }
148
-
149
- const kernel = kernelOptions ? getKernel(kernelOptions) : smallFilter;
150
-
151
- let convolutedSpectrum = convolutionByFFT
152
- ? convolution.fft(absoluteData, kernel, {
153
- rows: nbSubSpectra,
154
- cols: nbPoints,
155
- })
156
- : convolution.direct(absoluteData, kernel, {
157
- rows: nbSubSpectra,
158
- cols: nbPoints,
159
- });
160
-
161
- let peaksMC1 = matrixPeakFinders.findPeaks2DRegion(absoluteData, {
162
- originalData,
163
- filteredData: convolutedSpectrum,
164
- rows: nbSubSpectra,
165
- cols: nbPoints,
166
- nStdDev: thresholdFactor,
167
- });
168
-
169
- if (clean) {
170
- // Remove peaks with less than x% of the intensity of the highest peak
171
- peaksMC1 = PeakOptimizer.clean(peaksMC1, maxPercentCutOff);
172
- }
173
-
174
- let signals = createSignals2D(addMissingIDs(peaksMC1), {
175
- nRows: nbSubSpectra,
176
- nCols: nbPoints,
177
- minX: spectraData.minX,
178
- maxX: spectraData.maxX,
179
- minY: spectraData.minY,
180
- maxY: spectraData.maxY,
181
- absoluteData,
182
- originalData,
183
- tolerances,
184
- nuclei,
185
- observedFrequencies,
186
- realTopDetection,
187
- });
188
-
189
- if (enhanceSymmetry) {
190
- signals = PeakOptimizer.enhanceSymmetry(signals);
191
- }
192
-
77
+ const signals = xyzAutoSignalsPicking(spectraData, options);
193
78
  return formatZones(signals);
194
79
  }
195
-
196
- /**
197
- * This function converts a set of 2D-peaks in 2D-signals. Each signal could be composed
198
- * of many 2D-peaks, and it has some additional information related to the NMR spectrum.
199
- * @private
200
- */
201
-
202
- export interface CreateSignals2DOptions {
203
- nCols: number;
204
- nRows: number;
205
- absoluteData: number[] | Float64Array;
206
- originalData: number[] | Float64Array;
207
- observedFrequencies: number[] | Float64Array;
208
- tolerances: number[];
209
- nuclei: string[];
210
- realTopDetection: boolean;
211
- minY: number;
212
- maxY: number;
213
- minX: number;
214
- maxX: number;
215
- }
216
-
217
- function createSignals2D<T extends Peak2D>(
218
- peaks: T[],
219
- options: CreateSignals2DOptions,
220
- ) {
221
- let {
222
- nCols,
223
- nRows,
224
- absoluteData,
225
- originalData,
226
- observedFrequencies,
227
- tolerances,
228
- nuclei,
229
- realTopDetection,
230
- minY,
231
- maxY,
232
- minX,
233
- maxX,
234
- } = options;
235
-
236
- let [nucleusX, nucleusY] = nuclei;
237
- let [toleranceX, toleranceY] = tolerances;
238
- let [observeFrequencyX, observeFrequencyY] = observedFrequencies;
239
-
240
- let dy = (maxY - minY) / (nRows - 1);
241
- let dx = (maxX - minX) / (nCols - 1);
242
-
243
- if (realTopDetection) {
244
- peaks = determineRealTop(peaks, {
245
- nCols,
246
- absoluteData,
247
- originalData,
248
- minX,
249
- maxX,
250
- minY,
251
- maxY,
252
- });
253
- }
254
-
255
- for (let i = peaks.length - 1; i >= 0; i--) {
256
- let { x, y } = peaks[i];
257
- peaks[i].x = minX + dx * x;
258
- peaks[i].y = minY + dy * y;
259
- peaks[i].minX = minX + dx * peaks[i].minX;
260
- peaks[i].minY = minY + dy * peaks[i].minY;
261
- peaks[i].maxX = minX + dx * peaks[i].maxX;
262
- peaks[i].maxY = minY + dy * peaks[i].maxY;
263
-
264
- // Still having problems to correctly detect peaks on those areas. So I'm removing everything there.
265
- }
266
- // The connectivity matrix is an square and symmetric matrix, so we'll only store the upper diagonal in an
267
- // array like form
268
- let connectivity = [];
269
- for (let i = 0; i < peaks.length; i++) {
270
- for (let j = i; j < peaks.length; j++) {
271
- if (
272
- Math.abs(peaks[i].x - peaks[j].x) * observeFrequencyX < toleranceX &&
273
- Math.abs(peaks[i].y - peaks[j].y) * observeFrequencyY < toleranceY
274
- ) {
275
- // 24*24Hz We cannot distinguish peaks with less than 20 Hz of separation
276
- connectivity.push(1);
277
- } else {
278
- connectivity.push(0);
279
- }
280
- }
281
- }
282
- let clusters = simpleClustering(connectivity);
283
-
284
- let signals: NMRSignal2DWithID<T>[] = [];
285
- if (clusters) {
286
- for (const cluster of clusters) {
287
- let signal: any = {
288
- id: generateID(),
289
- x: {
290
- delta: 0,
291
- nucleus: nucleusX,
292
- resolution: dx,
293
- },
294
- y: {
295
- delta: 0,
296
- nucleus: nucleusY,
297
- resolution: dy,
298
- },
299
- };
300
- let peaks2D: T[] = [];
301
- let sumZ = 0;
302
-
303
- for (let jPeak = 0; jPeak < cluster.length; jPeak++) {
304
- if (cluster[jPeak] === 1) {
305
- peaks2D.push(peaks[jPeak]);
306
- signal.x.delta += peaks[jPeak].x * peaks[jPeak].z;
307
- signal.y.delta += peaks[jPeak].y * peaks[jPeak].z;
308
- sumZ += peaks[jPeak].z;
309
- }
310
- }
311
-
312
- signal.x.delta /= sumZ;
313
- signal.y.delta /= sumZ;
314
- signal.peaks = peaks2D;
315
- signals.push(signal as NMRSignal2DWithID<T>);
316
- }
317
- }
318
- return signals;
319
- }
320
-
321
- function padData(spectraData: Data2D, options: { width: number }) {
322
- let { minX, maxX, minY, maxY } = spectraData;
323
-
324
- const width = options.width;
325
-
326
- let nbPoints = spectraData.z[0].length;
327
- let nbSubSpectra = spectraData.z.length;
328
-
329
- let yInterval = (maxY - minY) / (nbSubSpectra - 1);
330
- let xInterval = (maxX - minX) / (nbPoints - 1);
331
-
332
- let yDiff = width - nbSubSpectra;
333
- let xDiff = Math.max(width - nbPoints, 0);
334
- if (xDiff % 2) xDiff++;
335
- if (yDiff % 2) yDiff++;
336
-
337
- let xOffset = xDiff / 2;
338
- let yOffset = yDiff / 2;
339
- let newMatrix = Matrix.zeros(nbSubSpectra + yDiff, nbPoints + xDiff);
340
- for (let i = 0; i < nbSubSpectra; i++) {
341
- for (let j = 0; j < nbPoints; j++) {
342
- newMatrix.set(i + yOffset, j + xOffset, spectraData.z[i][j]);
343
- }
344
- }
345
-
346
- return {
347
- z: newMatrix.to2DArray(),
348
- minX: minX - xOffset * xInterval,
349
- maxX: maxX + xOffset * xInterval,
350
- minY: minY - yOffset * yInterval,
351
- maxY: maxY + yOffset * yInterval,
352
- };
353
- }
@@ -1 +0,0 @@
1
- export declare function joinPatterns(patterns: string[]): string;
@@ -1 +0,0 @@
1
- {"version":3,"file":"joinPatterns.js","sourceRoot":"","sources":["../../src/utilities/joinPatterns.ts"],"names":[],"mappings":";;;AAAA,oEAAiE;AACjE,gEAA6D;AAE7D,SAAgB,YAAY,CAAC,QAAkB;IAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE;QAC3C,IAAI,KAAK,CAAC,+BAAc,CAAC,OAAO,CAAC,CAAC,EAAE;YAClC,MAAM,IAAI,KAAK,CACb,WAAW,OAAO,cAAc,MAAM,CAAC,IAAI,CAAC,+BAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CACxE,CAAC;SACH;QACD,OAAO,GAAG,GAAG,+BAAc,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEN,IAAI,CAAC,mCAAgB,CAAC,GAAG,CAAC,EAAE;QAC1B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;KACrD;IAED,OAAO,mCAAgB,CAAC,GAAG,CAAC,CAAC;AAC/B,CAAC;AAfD,oCAeC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"splitPatterns.js","sourceRoot":"","sources":["../../src/utilities/splitPatterns.ts"],"names":[],"mappings":";;;AAAA,4EAAyE;AAEzE,IAAI,gBAAgB,GAAa,EAAE,CAAC;AACpC,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,2CAAoB,EAAE;IAC1D,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC;CAC/C;AACD,gBAAgB,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,SAAgB,aAAa,CAAC,SAAiB;IAC7C,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3D,IAAI,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,SAAS,CAAC,CAAC;AACrB,CAAC;AAND,sCAMC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"joinPatterns.js","sourceRoot":"","sources":["../../src/utilities/joinPatterns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,MAAM,UAAU,YAAY,CAAC,QAAkB;IAC7C,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE;QAC3C,IAAI,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,EAAE;YAClC,MAAM,IAAI,KAAK,CACb,WAAW,OAAO,cAAc,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CACxE,CAAC;SACH;QACD,OAAO,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEN,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE;QAC1B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;KACrD;IAED,OAAO,gBAAgB,CAAC,GAAG,CAAC,CAAC;AAC/B,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"splitPatterns.js","sourceRoot":"","sources":["../../src/utilities/splitPatterns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEzE,IAAI,gBAAgB,GAAa,EAAE,CAAC;AACpC,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,oBAAoB,EAAE;IAC1D,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC;CAC/C;AACD,gBAAgB,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,IAAI,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3D,IAAI,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,SAAS,CAAC,CAAC;AACrB,CAAC"}