nmr-processing 7.1.0 → 7.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 (117) hide show
  1. package/lib/assignment/get13CAssignments.d.ts +3 -3
  2. package/lib/assignment/get13CAssignments.js.map +1 -1
  3. package/lib/assignment/get1HAssignments.d.ts +3 -3
  4. package/lib/assignment/get1HAssignments.js.map +1 -1
  5. package/lib/assignment/getAssignments.d.ts +81 -0
  6. package/lib/assignment/getAssignments.js +44 -0
  7. package/lib/assignment/getAssignments.js.map +1 -0
  8. package/lib/assignment/utils/buildAssignments.d.ts +4 -4
  9. package/lib/assignment/utils/buildAssignments.js.map +1 -1
  10. package/lib/assignment/utils/createMapPossibleAssignments.d.ts +2 -2
  11. package/lib/assignment/utils/exploreTreeRec.d.ts +3 -3
  12. package/lib/assignment/utils/exploreTreeRec.js.map +1 -1
  13. package/lib/assignment/utils/getAssignment/buildAssignments.d.ts +72 -0
  14. package/lib/assignment/utils/getAssignment/buildAssignments.js +205 -0
  15. package/lib/assignment/utils/getAssignment/buildAssignments.js.map +1 -0
  16. package/lib/assignment/utils/getAssignment/checkIDs.d.ts +23 -0
  17. package/lib/assignment/utils/getAssignment/checkIDs.js +57 -0
  18. package/lib/assignment/utils/getAssignment/checkIDs.js.map +1 -0
  19. package/lib/assignment/utils/getAssignment/createMapPossibleAssignment.d.ts +15 -0
  20. package/lib/assignment/utils/getAssignment/createMapPossibleAssignment.js +55 -0
  21. package/lib/assignment/utils/getAssignment/createMapPossibleAssignment.js.map +1 -0
  22. package/lib/assignment/utils/getAssignment/exploreTree.d.ts +22 -0
  23. package/lib/assignment/utils/getAssignment/exploreTree.js +93 -0
  24. package/lib/assignment/utils/getAssignment/exploreTree.js.map +1 -0
  25. package/lib/assignment/utils/getAssignment/formatData.d.ts +14 -0
  26. package/lib/assignment/utils/getAssignment/formatData.js +20 -0
  27. package/lib/assignment/utils/getAssignment/formatData.js.map +1 -0
  28. package/lib/assignment/utils/getAssignment/getIntegrationOfAttachedProtons.d.ts +3 -0
  29. package/lib/assignment/utils/getAssignment/getIntegrationOfAttachedProtons.js +14 -0
  30. package/lib/assignment/utils/getAssignment/getIntegrationOfAttachedProtons.js.map +1 -0
  31. package/lib/assignment/utils/getAssignment/getTargetsAndCorrelations.d.ts +18 -0
  32. package/lib/assignment/utils/getAssignment/getTargetsAndCorrelations.js +37 -0
  33. package/lib/assignment/utils/getAssignment/getTargetsAndCorrelations.js.map +1 -0
  34. package/lib/assignment/utils/getAssignment/getWorkFlow.d.ts +19 -0
  35. package/lib/assignment/utils/getAssignment/getWorkFlow.js +52 -0
  36. package/lib/assignment/utils/getAssignment/getWorkFlow.js.map +1 -0
  37. package/lib/assignment/utils/getAssignment/groupCarbonTargetByIntegrationZone.d.ts +7 -0
  38. package/lib/assignment/utils/getAssignment/groupCarbonTargetByIntegrationZone.js +43 -0
  39. package/lib/assignment/utils/getAssignment/groupCarbonTargetByIntegrationZone.js.map +1 -0
  40. package/lib/assignment/utils/getAssignment/isSpectraData1D.d.ts +2 -0
  41. package/lib/assignment/utils/getAssignment/isSpectraData1D.js +8 -0
  42. package/lib/assignment/utils/getAssignment/isSpectraData1D.js.map +1 -0
  43. package/lib/assignment/utils/getAssignment/partialScore.d.ts +13 -0
  44. package/lib/assignment/utils/getAssignment/partialScore.js +221 -0
  45. package/lib/assignment/utils/getAssignment/partialScore.js.map +1 -0
  46. package/lib/assignment/utils/getAssignment/searchIndices.d.ts +6 -0
  47. package/lib/assignment/utils/getAssignment/searchIndices.js +21 -0
  48. package/lib/assignment/utils/getAssignment/searchIndices.js.map +1 -0
  49. package/lib/assignment/utils/partialScore.d.ts +2 -2
  50. package/lib/index.d.ts +1 -0
  51. package/lib/index.js +1 -0
  52. package/lib/index.js.map +1 -1
  53. package/lib/peaks/peaksToRanges.js +1 -0
  54. package/lib/peaks/peaksToRanges.js.map +1 -1
  55. package/lib/prediction/utils/predict2D.d.ts +0 -2
  56. package/lib/prediction/utils/predict2D.js.map +1 -1
  57. package/lib-esm/assignment/get13CAssignments.js.map +1 -1
  58. package/lib-esm/assignment/get1HAssignments.js.map +1 -1
  59. package/lib-esm/assignment/getAssignments.js +37 -0
  60. package/lib-esm/assignment/getAssignments.js.map +1 -0
  61. package/lib-esm/assignment/utils/buildAssignments.js.map +1 -1
  62. package/lib-esm/assignment/utils/exploreTreeRec.js.map +1 -1
  63. package/lib-esm/assignment/utils/getAssignment/buildAssignments.js +198 -0
  64. package/lib-esm/assignment/utils/getAssignment/buildAssignments.js.map +1 -0
  65. package/lib-esm/assignment/utils/getAssignment/checkIDs.js +48 -0
  66. package/lib-esm/assignment/utils/getAssignment/checkIDs.js.map +1 -0
  67. package/lib-esm/assignment/utils/getAssignment/createMapPossibleAssignment.js +51 -0
  68. package/lib-esm/assignment/utils/getAssignment/createMapPossibleAssignment.js.map +1 -0
  69. package/lib-esm/assignment/utils/getAssignment/exploreTree.js +89 -0
  70. package/lib-esm/assignment/utils/getAssignment/exploreTree.js.map +1 -0
  71. package/lib-esm/assignment/utils/getAssignment/formatData.js +16 -0
  72. package/lib-esm/assignment/utils/getAssignment/formatData.js.map +1 -0
  73. package/lib-esm/assignment/utils/getAssignment/getIntegrationOfAttachedProtons.js +10 -0
  74. package/lib-esm/assignment/utils/getAssignment/getIntegrationOfAttachedProtons.js.map +1 -0
  75. package/lib-esm/assignment/utils/getAssignment/getTargetsAndCorrelations.js +33 -0
  76. package/lib-esm/assignment/utils/getAssignment/getTargetsAndCorrelations.js.map +1 -0
  77. package/lib-esm/assignment/utils/getAssignment/getWorkFlow.js +50 -0
  78. package/lib-esm/assignment/utils/getAssignment/getWorkFlow.js.map +1 -0
  79. package/lib-esm/assignment/utils/getAssignment/groupCarbonTargetByIntegrationZone.js +41 -0
  80. package/lib-esm/assignment/utils/getAssignment/groupCarbonTargetByIntegrationZone.js.map +1 -0
  81. package/lib-esm/assignment/utils/getAssignment/isSpectraData1D.js +4 -0
  82. package/lib-esm/assignment/utils/getAssignment/isSpectraData1D.js.map +1 -0
  83. package/lib-esm/assignment/utils/getAssignment/partialScore.js +214 -0
  84. package/lib-esm/assignment/utils/getAssignment/partialScore.js.map +1 -0
  85. package/lib-esm/assignment/utils/getAssignment/searchIndices.js +17 -0
  86. package/lib-esm/assignment/utils/getAssignment/searchIndices.js.map +1 -0
  87. package/lib-esm/index.js +1 -0
  88. package/lib-esm/index.js.map +1 -1
  89. package/lib-esm/peaks/peaksToRanges.js +1 -0
  90. package/lib-esm/peaks/peaksToRanges.js.map +1 -1
  91. package/lib-esm/prediction/utils/predict2D.js.map +1 -1
  92. package/package.json +2 -1
  93. package/src/assignment/get13CAssignments.ts +2 -2
  94. package/src/assignment/get1HAssignments.ts +2 -2
  95. package/src/assignment/getAssignments.ts +149 -0
  96. package/src/assignment/utils/buildAssignments.ts +4 -4
  97. package/src/assignment/utils/createMapPossibleAssignments.ts +2 -2
  98. package/src/assignment/utils/exploreTreeRec.ts +5 -5
  99. package/src/assignment/utils/getAssignment/buildAssignments.ts +339 -0
  100. package/src/assignment/utils/getAssignment/checkIDs.ts +76 -0
  101. package/src/assignment/utils/getAssignment/createMapPossibleAssignment.ts +85 -0
  102. package/src/assignment/utils/getAssignment/data/correlations.js +713 -0
  103. package/src/assignment/utils/getAssignment/data/predictions.js +34 -0
  104. package/src/assignment/utils/getAssignment/exploreTree.ts +171 -0
  105. package/src/assignment/utils/getAssignment/formatData.ts +35 -0
  106. package/src/assignment/utils/getAssignment/getIntegrationOfAttachedProtons.ts +16 -0
  107. package/src/assignment/utils/getAssignment/getTargetsAndCorrelations.ts +63 -0
  108. package/src/assignment/utils/getAssignment/getWorkFlow.ts +72 -0
  109. package/src/assignment/utils/getAssignment/groupCarbonTargetByIntegrationZone.ts +55 -0
  110. package/src/assignment/utils/getAssignment/isSpectraData1D.ts +7 -0
  111. package/src/assignment/utils/getAssignment/partialScore.ts +308 -0
  112. package/src/assignment/utils/getAssignment/searchIndices.ts +19 -0
  113. package/src/assignment/utils/partialScore.ts +2 -2
  114. package/src/index.ts +1 -0
  115. package/src/ml-tree-set.d.ts +1 -1
  116. package/src/peaks/peaksToRanges.ts +1 -0
  117. package/src/prediction/utils/predict2D.ts +0 -2
@@ -0,0 +1,339 @@
1
+ import treeSet from 'ml-tree-set';
2
+ import { Values } from 'nmr-correlation';
3
+ import { Molecule } from 'openchemlib';
4
+ import { getConnectivityMatrix } from 'openchemlib-utils';
5
+
6
+ import {
7
+ NMRSignal1D,
8
+ PredictCarbonOptions,
9
+ PredictProtonOptions,
10
+ } from '../../..';
11
+ import { predictCarbon } from '../../../prediction/predictCarbon';
12
+ import { predictProton } from '../../../prediction/predictProton';
13
+ import { MakeMandatory } from '../../../utilities/MakeMandatory';
14
+ import { StoreAssignments } from '../buildAssignments';
15
+
16
+ import { SpectraDataWithIds } from './checkIDs';
17
+ import {
18
+ createMapPossibleAssignment,
19
+ MapPossibleAssignments,
20
+ } from './createMapPossibleAssignment';
21
+ import { AssignmentSolution, exploreTree } from './exploreTree';
22
+ import { TargetsByAtomType } from './getTargetsAndCorrelations';
23
+ import { isSpectraData1D } from './isSpectraData1D';
24
+ import { searchIndices } from './searchIndices';
25
+
26
+ const comparator = (a: AssignmentSolution, b: AssignmentSolution) => {
27
+ return b.score - a.score;
28
+ };
29
+
30
+ const predictor = { H: predictProton, C: predictCarbon };
31
+
32
+ export type AtomTypes = 'H' | 'C';
33
+ export type CurrentAtoms = Array<AtomTypes>;
34
+ export interface Partial {
35
+ [key: string]: Array<string | null>;
36
+ }
37
+
38
+ export interface DiaIDPeerPossibleAssignment {
39
+ [key: string]: string[];
40
+ }
41
+
42
+ export interface RestrictionByCS {
43
+ chemicalShiftRestriction: boolean;
44
+ tolerance: { [key: string]: number };
45
+ useChemicalShiftScore: boolean;
46
+ }
47
+
48
+ export interface BuildAssignmentInput {
49
+ spectra: SpectraDataWithIds[];
50
+ molecule: Molecule;
51
+ restrictionByCS: RestrictionByCS;
52
+ timeout: number;
53
+ minScore: number;
54
+ nbAllowedUnAssigned?: { [key: string]: number };
55
+ maxSolutions: number;
56
+ correlations: Values;
57
+ assignmentOrder: Array<Array<AtomTypes>>;
58
+ predictions: {
59
+ H?: NMRSignal1D[];
60
+ C?: NMRSignal1D[];
61
+ };
62
+ predictionOptions: {
63
+ H?: PredictProtonOptions;
64
+ C?: PredictCarbonOptions;
65
+ };
66
+ targets: TargetsByAtomType;
67
+ }
68
+
69
+ type NMRSignal1DFromPrediction = MakeMandatory<
70
+ NMRSignal1D,
71
+ 'nbAtoms' | 'diaIDs' | 'atoms'
72
+ >;
73
+
74
+ function checkNMRSignal1D(
75
+ signals: NMRSignal1D[],
76
+ ): asserts signals is NMRSignal1DFromPrediction[] {
77
+ const keys: Array<'nbAtoms' | 'diaIDs' | 'atoms'> = [
78
+ 'nbAtoms',
79
+ 'diaIDs',
80
+ 'atoms',
81
+ ];
82
+ for (const signal of signals) {
83
+ for (let key of keys) {
84
+ if (!signal[key]) throw new Error(`property ${key} does not exist`);
85
+ }
86
+ }
87
+ }
88
+
89
+ export interface Prediction extends NMRSignal1DFromPrediction {
90
+ diaIDIndex: number;
91
+ allHydrogens: number;
92
+ protonsCount: number;
93
+ pathLength: number[];
94
+ }
95
+
96
+ export interface Predictions {
97
+ [key: string]: Prediction;
98
+ }
99
+
100
+ export interface PredictionsByAtomType {
101
+ [key: string]: Predictions;
102
+ }
103
+
104
+ export interface InfoByAtomType {
105
+ [key: string]: {
106
+ nSources: number;
107
+ currentIndex: number;
108
+ nbAllowedUnAssigned: number;
109
+ };
110
+ }
111
+
112
+ export const getAllHydrogens = {
113
+ C: (m: Molecule, i: number) => m.getAllHydrogens(i),
114
+ H: () => 1,
115
+ };
116
+
117
+ export async function buildAssignments(props: BuildAssignmentInput) {
118
+ const {
119
+ spectra,
120
+ molecule,
121
+ restrictionByCS,
122
+ timeout,
123
+ minScore,
124
+ nbAllowedUnAssigned = {},
125
+ maxSolutions,
126
+ correlations,
127
+ assignmentOrder,
128
+ predictionOptions,
129
+ predictions: inputPrediction = {},
130
+ targets,
131
+ } = props;
132
+
133
+ let date = new Date();
134
+ let timeStart = date.getTime();
135
+ let lowerBoundScore = minScore;
136
+
137
+ let store: StoreAssignments = {
138
+ solutions: new treeSet(comparator),
139
+ nSolutions: 0,
140
+ };
141
+
142
+ const pathLengthMatrix = getConnectivityMatrix(molecule, {
143
+ pathLength: true,
144
+ });
145
+
146
+ let infoByAtomType: InfoByAtomType = {};
147
+ const predictions: PredictionsByAtomType = {};
148
+ let possibleAssignmentMap: MapPossibleAssignments = {};
149
+ let diaIDPeerPossibleAssignment: DiaIDPeerPossibleAssignment = {};
150
+
151
+ for (const atomTypesToPredict of assignmentOrder) {
152
+ for (const atomType of atomTypesToPredict) {
153
+ const options = predictionOptions[atomType];
154
+ const predictedSignals = inputPrediction[atomType];
155
+ let { joinedSignals } = predictedSignals
156
+ ? { joinedSignals: predictedSignals }
157
+ : await predictor[atomType](molecule, options);
158
+
159
+ checkNMRSignal1D(joinedSignals);
160
+
161
+ if (!predictions[atomType]) predictions[atomType] = {};
162
+ for (let prediction of joinedSignals) {
163
+ const diaID = prediction.diaIDs[0];
164
+ const index = prediction.atoms[0];
165
+ const allHydrogens = getAllHydrogens[atomType](molecule, index);
166
+ predictions[atomType][diaID] = {
167
+ ...prediction,
168
+ diaIDIndex: index,
169
+ allHydrogens: prediction.nbAtoms * allHydrogens,
170
+ protonsCount: allHydrogens,
171
+ pathLength: pathLengthMatrix[index] as number[],
172
+ };
173
+ }
174
+ infoByAtomType[atomType] = {
175
+ nSources: joinedSignals.length,
176
+ currentIndex: 0,
177
+ nbAllowedUnAssigned: nbAllowedUnAssigned[atomType] || 0,
178
+ };
179
+ }
180
+
181
+ possibleAssignmentMap = createMapPossibleAssignment(possibleAssignmentMap, {
182
+ restrictionByCS,
183
+ predictions,
184
+ targets,
185
+ });
186
+
187
+ diaIDPeerPossibleAssignment = {};
188
+ for (const atomType in possibleAssignmentMap) {
189
+ diaIDPeerPossibleAssignment[atomType] = Object.keys(
190
+ possibleAssignmentMap[atomType],
191
+ );
192
+ }
193
+
194
+ let sourceOfPartials = getSourceOfPartials(
195
+ store,
196
+ infoByAtomType,
197
+ atomTypesToPredict,
198
+ );
199
+
200
+ store = {
201
+ solutions: new treeSet(comparator),
202
+ nSolutions: 0,
203
+ };
204
+
205
+ for (let partial of sourceOfPartials) {
206
+ exploreTree(
207
+ {
208
+ currentAtomTypes: atomTypesToPredict,
209
+ restrictionByCS,
210
+ timeout,
211
+ timeStart,
212
+ targets,
213
+ predictions,
214
+ correlations,
215
+ maxSolutions,
216
+ lowerBoundScore,
217
+ possibleAssignmentMap,
218
+ diaIDPeerPossibleAssignment,
219
+ },
220
+ infoByAtomType,
221
+ partial,
222
+ store,
223
+ );
224
+ }
225
+ }
226
+ return annotateSpectraData({
227
+ store,
228
+ spectra,
229
+ diaIDPeerPossibleAssignment,
230
+ targets,
231
+ });
232
+ }
233
+
234
+ interface AnnotateSpectraDataInput {
235
+ store: StoreAssignments;
236
+ spectra: SpectraDataWithIds[];
237
+ targets: TargetsByAtomType;
238
+ diaIDPeerPossibleAssignment: DiaIDPeerPossibleAssignment;
239
+ }
240
+
241
+ function annotateSpectraData(input: AnnotateSpectraDataInput) {
242
+ const { store, spectra, diaIDPeerPossibleAssignment, targets } = input;
243
+ const { solutions } = store;
244
+ const mapSignalId: any = {};
245
+ const atomTypes = Object.keys(targets) as AtomTypes[];
246
+ for (const atomType of atomTypes) {
247
+ const targetByAtomType = targets[atomType];
248
+ for (const targetId in targetByAtomType) {
249
+ let target = targetByAtomType[targetId];
250
+ for (const link of target.link) {
251
+ const signalId = link.signal.id;
252
+ if (mapSignalId[signalId]) continue;
253
+ mapSignalId[link.signal.id] = searchIndices(signalId, spectra);
254
+ }
255
+ }
256
+ }
257
+
258
+ const result = [];
259
+ for (let solution of solutions.elements) {
260
+ const spectraResult = JSON.parse(
261
+ JSON.stringify(spectra),
262
+ ) as SpectraDataWithIds[];
263
+ const { assignment, score } = solution;
264
+ const atomTypes = Object.keys(assignment) as AtomTypes[];
265
+ for (const atomType of atomTypes) {
266
+ const targetByAtomType = targets[atomType];
267
+ const assignmentPeerAtomType = assignment[atomType];
268
+ for (let index = 0; index < assignmentPeerAtomType.length; index++) {
269
+ const targetID = assignmentPeerAtomType[index];
270
+
271
+ if (targetID === '*' || !targetID) continue;
272
+
273
+ const target = targetByAtomType[targetID];
274
+ const diaId = diaIDPeerPossibleAssignment[atomType][index];
275
+
276
+ for (let link of target.link) {
277
+ const { spectrumIndex, elementIndex, signalIndex } =
278
+ mapSignalId[link.signal.id];
279
+ const spectrum = spectraResult[spectrumIndex];
280
+
281
+ if (isSpectraData1D(spectrum)) {
282
+ let { ranges } = spectrum;
283
+ let range = ranges[elementIndex];
284
+ let signal = range.signals[signalIndex];
285
+ if (!signal.diaIDs) signal.diaIDs = [];
286
+ signal.diaIDs.push(diaId);
287
+ } else {
288
+ const axis = link.axis as 'x' | 'y';
289
+ const signal = spectrum.zones[elementIndex].signals[signalIndex];
290
+ if (!signal[axis].diaIDs) signal[axis].diaIDs = [];
291
+ signal[axis].diaIDs?.push(diaId);
292
+ }
293
+ }
294
+ }
295
+ }
296
+ result.push({
297
+ score,
298
+ assignment: spectraResult,
299
+ });
300
+ }
301
+ return result;
302
+ }
303
+
304
+ function getSourceOfPartials(
305
+ store: StoreAssignments,
306
+ infoByAtomType: InfoByAtomType,
307
+ currentAtoms: CurrentAtoms,
308
+ ) {
309
+ return store.nSolutions > 0
310
+ ? store.solutions.elements.map((e) => {
311
+ let currentAssignment = e.assignment;
312
+ for (const atom of currentAtoms) {
313
+ currentAssignment[atom] = fillPartial(infoByAtomType[atom].nSources);
314
+ }
315
+ return currentAssignment;
316
+ })
317
+ : initializePartials(infoByAtomType, currentAtoms);
318
+ }
319
+
320
+ function initializePartials(
321
+ infoByAtomType: InfoByAtomType,
322
+ currentAtoms: CurrentAtoms,
323
+ ) {
324
+ const partial: Partial = {};
325
+ const atomsType = Object.keys(infoByAtomType) as CurrentAtoms;
326
+ for (const atom of atomsType) {
327
+ const value = currentAtoms.includes(atom) ? null : '*';
328
+ partial[atom] = fillPartial(infoByAtomType[atom].nSources, value);
329
+ }
330
+ return [partial];
331
+ }
332
+
333
+ function fillPartial(nSources: number, value: string | null = null) {
334
+ const partial: Array<string | null> = new Array(nSources);
335
+ for (let i = 0; i < nSources; i++) {
336
+ partial[i] = value;
337
+ }
338
+ return partial;
339
+ }
@@ -0,0 +1,76 @@
1
+ import type { NMRRange, NMRSignal1D, NMRSignal2D, NMRZone } from '../../..';
2
+ import { MakeMandatory } from '../../../utilities/MakeMandatory';
3
+ import type {
4
+ SpectraData,
5
+ SpectraData1D,
6
+ SpectraData2D,
7
+ } from '../../getAssignments';
8
+ import generateID from '../generateID';
9
+
10
+ import { isSpectraData1D } from './isSpectraData1D';
11
+
12
+ export type NMRSignal1DWithId = MakeMandatory<NMRSignal1D, 'id'>;
13
+ export type NMRSignal2DWithId = MakeMandatory<NMRSignal2D, 'id'>;
14
+
15
+ export interface NMRZoneWithIds extends Omit<NMRZone, 'signals' | 'id'> {
16
+ id: string;
17
+ signals: Array<NMRSignal2DWithId>;
18
+ }
19
+
20
+ export interface NMRRangeWithIds extends Omit<NMRRange, 'id' | 'signals'> {
21
+ id: string;
22
+ signals: Array<NMRSignal1DWithId>;
23
+ }
24
+
25
+ export interface SpectraData1DWithIds extends Omit<SpectraData1D, 'ranges'> {
26
+ ranges: NMRRangeWithIds[];
27
+ }
28
+ export interface SpectraData2DWithIds extends Omit<SpectraData2D, 'zones'> {
29
+ zones: NMRZoneWithIds[];
30
+ }
31
+
32
+ export type SpectraDataWithIds = SpectraData1DWithIds | SpectraData2DWithIds;
33
+
34
+ export function checkIDs(input: SpectraData[] = []): SpectraDataWithIds[] {
35
+ let inputClone = JSON.parse(JSON.stringify(input)) as SpectraData[];
36
+ let spectra: SpectraDataWithIds[] = [];
37
+ for (const spectraData of inputClone) {
38
+ const { info, id } = spectraData;
39
+ if (isSpectraData1D(spectraData)) {
40
+ let data = addIDs(spectraData.ranges) as NMRRangeWithIds[];
41
+ for (const element of data) {
42
+ const { integration } = element;
43
+ for (let signal of element.signals || []) {
44
+ if (!signal.integration) signal.integration = integration;
45
+ }
46
+ }
47
+ spectra.push({ id, info, ranges: data });
48
+ } else {
49
+ let data = addIDs(spectraData.zones) as NMRZoneWithIds[];
50
+ spectra.push({ id, info, zones: data });
51
+ }
52
+ }
53
+ return spectra;
54
+ }
55
+
56
+ export function hasIDs(
57
+ data: NMRRange[] | NMRZone[],
58
+ ): asserts data is NMRRangeWithIds[] | NMRZoneWithIds[] {
59
+ for (const element of data) {
60
+ if (!element.id) throw new Error('A range/zone has not an ID');
61
+ for (let signal of element.signals || []) {
62
+ if (!signal.id) throw new Error('A signal has not an ID');
63
+ }
64
+ }
65
+ }
66
+
67
+ export function addIDs(data: NMRRange[] | NMRZone[]) {
68
+ for (const element of data) {
69
+ if (!element.id) element.id = generateID();
70
+ for (let signal of element.signals || []) {
71
+ if (!signal.id) signal.id = generateID();
72
+ }
73
+ }
74
+ hasIDs(data);
75
+ return data;
76
+ }
@@ -0,0 +1,85 @@
1
+ import { getCorrelationDelta } from 'nmr-correlation';
2
+
3
+ import { PossibleAssignmentMap } from '../createMapPossibleAssignments';
4
+
5
+ import {
6
+ AtomTypes,
7
+ PredictionsByAtomType,
8
+ RestrictionByCS,
9
+ } from './buildAssignments';
10
+ import { TargetsByAtomType } from './getTargetsAndCorrelations';
11
+
12
+ export interface PossibleAssignments {
13
+ [key: string]: string[];
14
+ }
15
+ export interface MapPossibleAssignments {
16
+ [key: string]: PossibleAssignmentMap;
17
+ }
18
+ export interface CreateMapPossibleAssignmentOptions {
19
+ restrictionByCS: RestrictionByCS;
20
+ predictions: PredictionsByAtomType;
21
+ targets: TargetsByAtomType;
22
+ }
23
+ export function createMapPossibleAssignment(
24
+ expandMap: MapPossibleAssignments,
25
+ props: CreateMapPossibleAssignmentOptions,
26
+ ) {
27
+ const { restrictionByCS, predictions, targets } = props;
28
+
29
+ const { tolerance: toleranceCS, chemicalShiftRestriction } = restrictionByCS;
30
+
31
+ const atomTypes = Object.keys(predictions) as AtomTypes[];
32
+
33
+ for (const atomType of atomTypes) {
34
+ let errorAbs = toleranceCS[atomType];
35
+ let predictionByAtomType = predictions[atomType];
36
+ let targetByAtomType = targets[atomType];
37
+ if (!expandMap[atomType]) expandMap[atomType] = {};
38
+ for (const diaID in predictionByAtomType) {
39
+ let prediction = predictionByAtomType[diaID];
40
+ expandMap[atomType][diaID] = [];
41
+
42
+ if (targetByAtomType) {
43
+ for (const targetID in targetByAtomType) {
44
+ let target = targetByAtomType[targetID];
45
+ const { nbAtoms, protonsCount: protonsCountFromPrediction } =
46
+ prediction;
47
+ const { integration, protonsCount } = target;
48
+
49
+ const couldBeAssigned = !integration
50
+ ? true
51
+ : atomType === 'H'
52
+ ? nbAtoms - integration < 1
53
+ : protonsCount.length > 0
54
+ ? protonsCount.some(
55
+ (count: number) => protonsCountFromPrediction === count,
56
+ )
57
+ : true;
58
+ if (couldBeAssigned) {
59
+ if (
60
+ !chemicalShiftRestriction ||
61
+ typeof prediction.delta === 'undefined'
62
+ ) {
63
+ // Chemical shift is not a restriction
64
+ expandMap[atomType][diaID].push(targetID);
65
+ } else {
66
+ let targetDelta = getCorrelationDelta(target);
67
+ if (targetDelta === undefined) {
68
+ throw new Error(`Correlation has not delta`);
69
+ }
70
+ let distAfterLimit = Math.abs(
71
+ prediction.delta - targetDelta - errorAbs,
72
+ );
73
+
74
+ if (distAfterLimit < 4 * errorAbs) {
75
+ expandMap[atomType][diaID].push(targetID);
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+ expandMap[atomType][diaID].push('*');
82
+ }
83
+ }
84
+ return expandMap;
85
+ }