nmr-processing 3.3.4 → 5.0.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 (109) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/lib/assignment/get13CAssignments.d.ts +35 -0
  3. package/lib/assignment/get13CAssignments.js +54 -0
  4. package/lib/assignment/get13CAssignments.js.map +1 -0
  5. package/lib/assignment/get1HAssignments.d.ts +42 -0
  6. package/lib/assignment/get1HAssignments.js +55 -0
  7. package/lib/assignment/get1HAssignments.js.map +1 -0
  8. package/lib/assignment/utils/buildAssignments.d.ts +33 -0
  9. package/lib/assignment/utils/buildAssignments.js +93 -0
  10. package/lib/assignment/utils/buildAssignments.js.map +1 -0
  11. package/lib/assignment/utils/createMapPossibleAssignments.d.ts +15 -0
  12. package/lib/assignment/utils/createMapPossibleAssignments.js +51 -0
  13. package/lib/assignment/utils/createMapPossibleAssignments.js.map +1 -0
  14. package/lib/assignment/utils/exploreTreeRec.d.ts +22 -0
  15. package/lib/assignment/utils/exploreTreeRec.js +77 -0
  16. package/lib/assignment/utils/exploreTreeRec.js.map +1 -0
  17. package/lib/assignment/utils/generateID.d.ts +1 -0
  18. package/lib/assignment/utils/generateID.js +13 -0
  19. package/lib/assignment/utils/generateID.js.map +1 -0
  20. package/lib/assignment/utils/partialScore.d.ts +16 -0
  21. package/lib/assignment/utils/partialScore.js +91 -0
  22. package/lib/assignment/utils/partialScore.js.map +1 -0
  23. package/lib/index.d.ts +2 -5
  24. package/lib/index.js +2 -5
  25. package/lib/index.js.map +1 -1
  26. package/lib/peaks/peaksFilterImpurities.js +1 -1
  27. package/lib/peaks/peaksFilterImpurities.js.map +1 -1
  28. package/lib/peaks/peaksToRanges.js +11 -17
  29. package/lib/peaks/peaksToRanges.js.map +1 -1
  30. package/lib/peaks/util/determineRealTop.js +3 -2
  31. package/lib/peaks/util/determineRealTop.js.map +1 -1
  32. package/lib/peaks/util/jAnalyzer.js +33 -35
  33. package/lib/peaks/util/jAnalyzer.js.map +1 -1
  34. package/lib/ranges/rangesToXY.d.ts +2 -2
  35. package/lib/ranges/rangesToXY.js +10 -2
  36. package/lib/ranges/rangesToXY.js.map +1 -1
  37. package/lib/signals/signals2DToZ.d.ts +2 -2
  38. package/lib/signals/signalsToXY.d.ts +2 -2
  39. package/lib/signals/simulation/simulate1D.d.ts +4 -3
  40. package/lib/signals/simulation/simulate1D.js.map +1 -1
  41. package/lib/types/NMRPeak1D.d.ts +2 -9
  42. package/lib/types/NMRRange.d.ts +1 -0
  43. package/lib/types/NMRSignal1D.d.ts +1 -0
  44. package/lib/types/NMRSignal2D.d.ts +3 -4
  45. package/lib/types/NMRZone.d.ts +4 -3
  46. package/lib/xy/xyAutoPeaksPicking.d.ts +4 -60
  47. package/lib/xy/xyAutoPeaksPicking.js +3 -3
  48. package/lib/xy/xyAutoPeaksPicking.js.map +1 -1
  49. package/lib/xyz/xyzAutoPeaksPicking.js +4 -2
  50. package/lib/xyz/xyzAutoPeaksPicking.js.map +1 -1
  51. package/lib-esm/assignment/get13CAssignments.js +47 -0
  52. package/lib-esm/assignment/get13CAssignments.js.map +1 -0
  53. package/lib-esm/assignment/get1HAssignments.js +48 -0
  54. package/lib-esm/assignment/get1HAssignments.js.map +1 -0
  55. package/lib-esm/assignment/utils/buildAssignments.js +86 -0
  56. package/lib-esm/assignment/utils/buildAssignments.js.map +1 -0
  57. package/lib-esm/assignment/utils/createMapPossibleAssignments.js +47 -0
  58. package/lib-esm/assignment/utils/createMapPossibleAssignments.js.map +1 -0
  59. package/lib-esm/assignment/utils/exploreTreeRec.js +73 -0
  60. package/lib-esm/assignment/utils/exploreTreeRec.js.map +1 -0
  61. package/lib-esm/assignment/utils/generateID.js +10 -0
  62. package/lib-esm/assignment/utils/generateID.js.map +1 -0
  63. package/lib-esm/assignment/utils/partialScore.js +87 -0
  64. package/lib-esm/assignment/utils/partialScore.js.map +1 -0
  65. package/lib-esm/index.js +2 -5
  66. package/lib-esm/index.js.map +1 -1
  67. package/lib-esm/peaks/peaksFilterImpurities.js +1 -1
  68. package/lib-esm/peaks/peaksFilterImpurities.js.map +1 -1
  69. package/lib-esm/peaks/peaksToRanges.js +11 -17
  70. package/lib-esm/peaks/peaksToRanges.js.map +1 -1
  71. package/lib-esm/peaks/util/determineRealTop.js +4 -3
  72. package/lib-esm/peaks/util/determineRealTop.js.map +1 -1
  73. package/lib-esm/peaks/util/jAnalyzer.js +33 -35
  74. package/lib-esm/peaks/util/jAnalyzer.js.map +1 -1
  75. package/lib-esm/ranges/rangesToXY.js +10 -2
  76. package/lib-esm/ranges/rangesToXY.js.map +1 -1
  77. package/lib-esm/signals/simulation/simulate1D.js.map +1 -1
  78. package/lib-esm/xy/xyAutoPeaksPicking.js +3 -3
  79. package/lib-esm/xy/xyAutoPeaksPicking.js.map +1 -1
  80. package/lib-esm/xyz/xyzAutoPeaksPicking.js +4 -2
  81. package/lib-esm/xyz/xyzAutoPeaksPicking.js.map +1 -1
  82. package/package.json +4 -4
  83. package/src/assignment/get13CAssignments.ts +100 -0
  84. package/src/assignment/get1HAssignments.ts +116 -0
  85. package/src/assignment/utils/buildAssignments.ts +155 -0
  86. package/src/assignment/utils/createMapPossibleAssignments.ts +76 -0
  87. package/src/assignment/utils/exploreTreeRec.ts +138 -0
  88. package/src/assignment/utils/generateID.ts +11 -0
  89. package/src/assignment/utils/partialScore.ts +128 -0
  90. package/src/index.ts +3 -6
  91. package/src/peaks/peaksFilterImpurities.ts +1 -1
  92. package/src/peaks/peaksToRanges.ts +11 -17
  93. package/src/peaks/util/determineRealTop.ts +4 -6
  94. package/src/peaks/util/jAnalyzer.ts +34 -36
  95. package/src/ranges/rangesToXY.ts +14 -7
  96. package/src/signals/signals2DToZ.ts +2 -2
  97. package/src/signals/signalsToXY.ts +2 -2
  98. package/src/signals/simulation/simulate1D.ts +4 -3
  99. package/src/types/NMRPeak1D.ts +3 -9
  100. package/src/types/NMRRange.ts +1 -0
  101. package/src/types/NMRSignal1D.ts +1 -0
  102. package/src/types/NMRSignal2D.ts +4 -4
  103. package/src/types/NMRZone.ts +4 -3
  104. package/src/types/ml-spectra-processing/index.d.ts +8 -8
  105. package/src/types/ml-tree-set/index.d.ts +18 -0
  106. package/src/types/openchemlib-utils/index..d.ts +2 -2
  107. package/src/xy/xyAutoPeaksPicking.ts +19 -58
  108. package/src/xyz/xyzAutoPeaksPicking.ts +4 -2
  109. package/src/types/ml-gsd/index.d.ts +0 -164
@@ -0,0 +1,116 @@
1
+ import { Molecule } from 'openchemlib';
2
+ import { addDiastereotopicMissingChirality } from 'openchemlib-utils';
3
+
4
+ import { NMRRange } from '..';
5
+ import {
6
+ predictProton,
7
+ PredictProtonOptions,
8
+ } from '../prediction/predictProton';
9
+ import { MakeMandatory } from '../types/MakeMandatory';
10
+ import type { NMRSignal1D } from '../types/NMRSignal1D';
11
+
12
+ import { buildAssignments, RestrictionByCS } from './utils/buildAssignments';
13
+ import generateID from './utils/generateID';
14
+
15
+ export type NMRSignal1DWithAtomsAndDiaIDs = MakeMandatory<
16
+ NMRSignal1D,
17
+ 'atoms' | 'diaIDs' | 'nbAtoms'
18
+ >;
19
+
20
+ function checkAtomsAndDiaIDs(
21
+ signals: NMRSignal1D[],
22
+ ): asserts signals is NMRSignal1DWithAtomsAndDiaIDs[] {
23
+ for (const signal of signals) {
24
+ if (!signal.atoms) throw new Error('signal has not atoms property');
25
+ if (!signal.diaIDs) throw new Error('signal has not diaIDs property');
26
+ if (!signal.nbAtoms) throw new Error('signal has not nbAtoms property');
27
+ }
28
+ }
29
+
30
+ export type NMRRangeWithIntegration = MakeMandatory<NMRRange, 'integration'>;
31
+
32
+ function checkForIntegration(
33
+ ranges: NMRRange[],
34
+ ): asserts ranges is NMRRangeWithIntegration[] {
35
+ for (let range of ranges) {
36
+ if (range.integration === undefined) {
37
+ throw new Error('ranges has not integration property');
38
+ }
39
+ }
40
+ }
41
+
42
+ export interface Get1HAssignmentsOptions {
43
+ restrictionByCS?: Partial<RestrictionByCS>;
44
+ /**
45
+ * min score to accept an assignment
46
+ * @default 1
47
+ */
48
+ minScore?: number;
49
+ /**
50
+ * maximal number of assignments to return
51
+ * @default 10
52
+ */
53
+ maxSolutions?: number;
54
+ /**
55
+ * number of allowed unassignment signals
56
+ * @default 0
57
+ */
58
+ nbAllowedUnAssigned?: number;
59
+ /**
60
+ * time limit in miliseconds to finish the assignment procedure.
61
+ * @default 6000
62
+ */
63
+ timeout?: number;
64
+ /**
65
+ * prediction options
66
+ */
67
+ predictionOptions?: PredictProtonOptions;
68
+ }
69
+
70
+ export interface Targets {
71
+ [key: string]: NMRRangeWithIntegration;
72
+ }
73
+
74
+ export async function get1HAssignments(
75
+ ranges: NMRRange[],
76
+ molecule: Molecule,
77
+ options: Get1HAssignmentsOptions = {},
78
+ ) {
79
+ let {
80
+ restrictionByCS,
81
+ minScore = 1,
82
+ maxSolutions = 10,
83
+ nbAllowedUnAssigned = 0,
84
+ timeout = 6000,
85
+ predictionOptions = {},
86
+ } = options;
87
+
88
+ if (!molecule) {
89
+ throw new Error('It is needed a OCL molecule instance to assign');
90
+ }
91
+
92
+ molecule.addImplicitHydrogens();
93
+ addDiastereotopicMissingChirality(molecule);
94
+
95
+ const { joinedSignals } = await predictProton(molecule, predictionOptions);
96
+
97
+ checkForIntegration(ranges);
98
+ checkAtomsAndDiaIDs(joinedSignals);
99
+
100
+ const targets: Targets = {};
101
+ for (const range of ranges) {
102
+ const { id = generateID() } = range;
103
+ targets[id] = JSON.parse(JSON.stringify(range));
104
+ }
105
+
106
+ return buildAssignments({
107
+ restrictionByCS,
108
+ timeout,
109
+ minScore,
110
+ nbAllowedUnAssigned,
111
+ maxSolutions,
112
+ targets,
113
+ joinedSignals,
114
+ useIntegrationRestriction: true,
115
+ });
116
+ }
@@ -0,0 +1,155 @@
1
+ import treeSet from 'ml-tree-set';
2
+
3
+ import {
4
+ Targets,
5
+ NMRSignal1DWithAtomsAndDiaIDs,
6
+ } from '../get1HAssignments';
7
+
8
+ import { createMapPossibleAssignments } from './createMapPossibleAssignments';
9
+ import { exploreTreeRec } from './exploreTreeRec';
10
+ import type { SolutionAssignment } from './exploreTreeRec';
11
+
12
+ const comparator = (a: SolutionAssignment, b: SolutionAssignment) => {
13
+ return b.score - a.score;
14
+ };
15
+
16
+ export interface RestrictionByCS {
17
+ chemicalShiftRestriction: boolean;
18
+ tolerance: number;
19
+ useChemicalShiftScore: boolean;
20
+ }
21
+
22
+ export interface BuildAssignmentsProps {
23
+ restrictionByCS?: Partial<RestrictionByCS>;
24
+ timeout: number;
25
+ minScore: number;
26
+ useIntegrationRestriction: boolean;
27
+ nbAllowedUnAssigned: number;
28
+ maxSolutions: number;
29
+ targets: Targets;
30
+ joinedSignals: NMRSignal1DWithAtomsAndDiaIDs[];
31
+ }
32
+
33
+ export interface Signals1DAssignment extends NMRSignal1DWithAtomsAndDiaIDs {
34
+ diaIDIndex: number;
35
+ allHydrogens: number;
36
+ error?: number;
37
+ }
38
+
39
+ export interface Predictions1Dassignments {
40
+ [key: string]: Signals1DAssignment;
41
+ }
42
+
43
+ export interface StoreAssignments1D {
44
+ solutions: treeSet;
45
+ nSolutions: number;
46
+ }
47
+
48
+ export async function buildAssignments(props: BuildAssignmentsProps) {
49
+ const {
50
+ restrictionByCS = {},
51
+ useIntegrationRestriction,
52
+ timeout,
53
+ minScore,
54
+ nbAllowedUnAssigned,
55
+ maxSolutions,
56
+ targets,
57
+ joinedSignals,
58
+ } = props;
59
+
60
+ const {
61
+ tolerance = 1,
62
+ useChemicalShiftScore = false,
63
+ chemicalShiftRestriction = true,
64
+ } = restrictionByCS;
65
+
66
+ let date = new Date();
67
+ let timeStart = date.getTime();
68
+
69
+ let store: StoreAssignments1D = {
70
+ solutions: new treeSet(comparator),
71
+ nSolutions: 0,
72
+ };
73
+
74
+ let nSources = joinedSignals.length;
75
+ const predictions: Predictions1Dassignments = {};
76
+
77
+ for (let prediction of joinedSignals) {
78
+ const diaID = prediction.diaIDs[0];
79
+ const index = prediction.atoms[0];
80
+ predictions[diaID] = {
81
+ ...prediction,
82
+ diaIDIndex: index,
83
+ allHydrogens: prediction.nbAtoms,
84
+ };
85
+ }
86
+
87
+ const possibleAssignmentMap = createMapPossibleAssignments({
88
+ restrictionByCS: {
89
+ tolerance,
90
+ useChemicalShiftScore,
91
+ chemicalShiftRestriction,
92
+ },
93
+ useIntegrationRestriction,
94
+ predictions,
95
+ targets,
96
+ });
97
+
98
+ const diaIDPeerPossibleAssignment = Object.keys(possibleAssignmentMap);
99
+
100
+ let partial = fillPartial(nSources);
101
+
102
+ store = {
103
+ solutions: new treeSet(comparator),
104
+ nSolutions: 0,
105
+ };
106
+
107
+ exploreTreeRec(
108
+ {
109
+ nSources,
110
+ restrictionByCS: {
111
+ tolerance,
112
+ useChemicalShiftScore,
113
+ chemicalShiftRestriction,
114
+ },
115
+ timeout,
116
+ timeStart,
117
+ targets,
118
+ predictions,
119
+ maxSolutions,
120
+ lowerBoundScore: minScore,
121
+ nbAllowedUnAssigned,
122
+ possibleAssignmentMap,
123
+ diaIDPeerPossibleAssignment,
124
+ useIntegrationRestriction,
125
+ },
126
+ 0,
127
+ partial,
128
+ store,
129
+ );
130
+
131
+ const assignments = [];
132
+ for (const solution of store.solutions.elements) {
133
+ const { assignment, score } = solution;
134
+ const currentAssignment = JSON.parse(JSON.stringify(targets));
135
+ for (let i = 0; i < assignment.length; i++) {
136
+ let range = currentAssignment[assignment[i]];
137
+ if (!range.diaIDs) range.diaIDs = [];
138
+ if (assignment[i]) range.diaIDs.push(diaIDPeerPossibleAssignment[i]);
139
+ }
140
+ assignments.push({
141
+ score,
142
+ assignment: Object.values(currentAssignment),
143
+ });
144
+ }
145
+
146
+ return assignments;
147
+ }
148
+
149
+ function fillPartial(nSources: number, value = null) {
150
+ const partial = new Array(nSources);
151
+ for (let i = 0; i < nSources; i++) {
152
+ partial[i] = value;
153
+ }
154
+ return partial;
155
+ }
@@ -0,0 +1,76 @@
1
+ import { MakeMandatory } from '../../types/MakeMandatory';
2
+ import type { Targets } from '../get1HAssignments';
3
+
4
+ import type { RestrictionByCS, Predictions1Dassignments } from './buildAssignments';
5
+
6
+ type RestrictionByCSMandatory = MakeMandatory<
7
+ RestrictionByCS,
8
+ 'chemicalShiftRestriction' | 'tolerance' | 'useChemicalShiftScore'
9
+ >;
10
+
11
+ interface CreateMapPossibleAssignments {
12
+ predictions: Predictions1Dassignments;
13
+ restrictionByCS: RestrictionByCSMandatory;
14
+ targets: Targets;
15
+ useIntegrationRestriction: boolean;
16
+ }
17
+
18
+ export interface PossibleAssignmentMap {
19
+ [key: string]: string[];
20
+ }
21
+ export function createMapPossibleAssignments(
22
+ props: CreateMapPossibleAssignments,
23
+ ) {
24
+ const { restrictionByCS, predictions, targets, useIntegrationRestriction } =
25
+ props;
26
+
27
+ const { tolerance: toleranceCS, chemicalShiftRestriction } = restrictionByCS;
28
+
29
+ let errorAbs = Math.abs(toleranceCS);
30
+ const expandMap: PossibleAssignmentMap = {};
31
+ for (const diaID in predictions) {
32
+ let prediction = predictions[diaID];
33
+ if (prediction.error) prediction.error = Math.abs(prediction.error);
34
+ expandMap[diaID] = [];
35
+
36
+ if (targets) {
37
+ for (const targetID in targets) {
38
+ let target = targets[targetID];
39
+ const { nbAtoms } = prediction;
40
+ const { integration } = target;
41
+
42
+ const couldBeAssigned = useIntegrationRestriction
43
+ ? integration > 0
44
+ ? nbAtoms - integration < 1
45
+ : true
46
+ : true;
47
+
48
+ if (couldBeAssigned) {
49
+ if (
50
+ !chemicalShiftRestriction ||
51
+ typeof prediction.delta === 'undefined'
52
+ ) {
53
+ // Chemical shift is not a restriction
54
+ expandMap[diaID].push(targetID);
55
+ } else {
56
+ let error = errorAbs;
57
+ if (prediction.error) {
58
+ error = Math.max(error, prediction.error);
59
+ }
60
+ const delta =
61
+ target.signals && target.signals.length > 0
62
+ ? target.signals[0].delta
63
+ : (target.to + target.from) / 2;
64
+
65
+ let distAfterLimit = Math.abs(prediction.delta - delta - errorAbs);
66
+ if (distAfterLimit < 4 * errorAbs) {
67
+ expandMap[diaID].push(targetID);
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
73
+ expandMap[diaID].push('*');
74
+ }
75
+ return expandMap;
76
+ }
@@ -0,0 +1,138 @@
1
+ import type { Targets } from '../get1HAssignments';
2
+
3
+ import type {
4
+ RestrictionByCS,
5
+ StoreAssignments1D,
6
+ Predictions1Dassignments,
7
+ } from './buildAssignments';
8
+ import type { PossibleAssignmentMap } from './createMapPossibleAssignments';
9
+ import { partialScore } from './partialScore';
10
+
11
+ export interface ExploreTreeRecProps {
12
+ nSources: number;
13
+ restrictionByCS: RestrictionByCS;
14
+ timeout: number;
15
+ timeStart: number;
16
+ maxSolutions: number;
17
+ targets: Targets;
18
+ useIntegrationRestriction: boolean;
19
+ predictions: Predictions1Dassignments;
20
+ lowerBoundScore: number;
21
+ nbAllowedUnAssigned: number;
22
+ possibleAssignmentMap: PossibleAssignmentMap;
23
+ diaIDPeerPossibleAssignment: string[];
24
+ }
25
+ export function exploreTreeRec(
26
+ props: ExploreTreeRecProps,
27
+ currentIndex: number,
28
+ partial: Array<string | null>,
29
+ store: StoreAssignments1D,
30
+ ) {
31
+ const {
32
+ nSources,
33
+ restrictionByCS,
34
+ timeout,
35
+ timeStart,
36
+ maxSolutions,
37
+ targets,
38
+ predictions,
39
+ lowerBoundScore,
40
+ nbAllowedUnAssigned,
41
+ possibleAssignmentMap,
42
+ useIntegrationRestriction,
43
+ diaIDPeerPossibleAssignment,
44
+ } = props;
45
+
46
+ const currentDate = new Date();
47
+ if (currentDate.getTime() - timeStart > timeout) {
48
+ new Error('timeout expired');
49
+ return store;
50
+ }
51
+
52
+ const diaID = diaIDPeerPossibleAssignment[currentIndex];
53
+ const possibleAssignments = possibleAssignmentMap[diaID];
54
+ for (let targetID of possibleAssignments) {
55
+ partial[currentIndex] = targetID;
56
+ let score = partialScore(partial, {
57
+ useIntegrationRestriction,
58
+ diaIDPeerPossibleAssignment,
59
+ nbAllowedUnAssigned,
60
+ restrictionByCS,
61
+ predictions,
62
+ targets,
63
+ });
64
+
65
+ if (score === 0) {
66
+ if (targetID === '*') {
67
+ partial[currentIndex] = null;
68
+ }
69
+ continue;
70
+ }
71
+
72
+ if (currentIndex === nSources - 1 && score >= lowerBoundScore) {
73
+ addSolution(store, { predictions, partial, score, maxSolutions });
74
+ } else if (currentIndex < nSources - 1) {
75
+ exploreTreeRec(
76
+ {
77
+ nSources,
78
+ restrictionByCS,
79
+ timeout,
80
+ timeStart,
81
+ maxSolutions,
82
+ targets,
83
+ predictions,
84
+ lowerBoundScore,
85
+ nbAllowedUnAssigned,
86
+ possibleAssignmentMap,
87
+ useIntegrationRestriction,
88
+ diaIDPeerPossibleAssignment,
89
+ },
90
+ currentIndex + 1,
91
+ JSON.parse(JSON.stringify(partial)),
92
+ store,
93
+ );
94
+ }
95
+ }
96
+ }
97
+
98
+ export interface SolutionAssignment {
99
+ assignment: string[];
100
+ score: number;
101
+ }
102
+
103
+ interface AddSolutionProps {
104
+ score: number;
105
+ maxSolutions: number;
106
+ partial: Array<string | null>;
107
+ predictions: Predictions1Dassignments;
108
+ }
109
+
110
+ function addSolution(store: StoreAssignments1D, props: AddSolutionProps) {
111
+ let { score, maxSolutions, partial, predictions } = props;
112
+ score /= doubleAssignmentPenalty(partial, predictions);
113
+ store.nSolutions++;
114
+ let solution: SolutionAssignment = {
115
+ assignment: JSON.parse(JSON.stringify(partial)),
116
+ score: score,
117
+ };
118
+
119
+ if (store.nSolutions >= maxSolutions) {
120
+ if (solution.score > store.solutions.last().score) {
121
+ store.solutions.pollLast();
122
+ store.solutions.add(solution);
123
+ }
124
+ } else {
125
+ store.solutions.add(solution);
126
+ store.nSolutions++;
127
+ }
128
+ }
129
+
130
+ function doubleAssignmentPenalty(
131
+ partial: Array<string | null>,
132
+ predictions: Predictions1Dassignments,
133
+ ) {
134
+ const nbSources = Object.keys(predictions).length;
135
+ let assignments = new Set(partial);
136
+ let nbDoubleAssignment = nbSources - assignments.size;
137
+ return nbDoubleAssignment > 0 ? 2 * nbDoubleAssignment : 1;
138
+ }
@@ -0,0 +1,11 @@
1
+ const BASE62 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
2
+
3
+ const LENGTH = 8;
4
+
5
+ export default function generateID() {
6
+ let id = '';
7
+ for (let i = 0; i < LENGTH; i++) {
8
+ id += BASE62.charAt(Math.floor(Math.random() * 62));
9
+ }
10
+ return id;
11
+ }
@@ -0,0 +1,128 @@
1
+ import { Targets } from '../get1HAssignments';
2
+
3
+ import type {
4
+ Predictions1Dassignments,
5
+ RestrictionByCS,
6
+ } from './buildAssignments';
7
+
8
+ interface PartialScoreOptions {
9
+ restrictionByCS: RestrictionByCS;
10
+ /**
11
+ * number of allowed unassignment signals
12
+ * @default 0
13
+ */
14
+ useIntegrationRestriction: boolean;
15
+ nbAllowedUnAssigned: number;
16
+ diaIDPeerPossibleAssignment: string[];
17
+ predictions: Predictions1Dassignments;
18
+ targets: Targets;
19
+ }
20
+
21
+ export function partialScore(
22
+ partial: Array<string | null>,
23
+ options: PartialScoreOptions,
24
+ ) {
25
+ const {
26
+ useIntegrationRestriction,
27
+ diaIDPeerPossibleAssignment,
28
+ nbAllowedUnAssigned,
29
+ restrictionByCS,
30
+ predictions,
31
+ targets,
32
+ } = options;
33
+ const { useChemicalShiftScore } = restrictionByCS;
34
+ let countStars = 0;
35
+ let totalPartial = partial.length;
36
+ let partialInverse: {
37
+ [key: string]: string[];
38
+ } = {};
39
+ let activeDomainOnPrediction: number[] = [];
40
+
41
+ for (let i = 0; i < partial.length; i++) {
42
+ const targetID = partial[i];
43
+ if (targetID && targetID !== '*') {
44
+ activeDomainOnPrediction.push(i);
45
+ if (!partialInverse[targetID]) {
46
+ partialInverse[targetID] = [];
47
+ }
48
+ partialInverse[targetID].push(diaIDPeerPossibleAssignment[i]);
49
+ }
50
+ if (targetID === '*') countStars++;
51
+ }
52
+ if (countStars > nbAllowedUnAssigned) return 0;
53
+
54
+ const activeDomainOnTarget = Object.keys(partialInverse);
55
+
56
+ if (activeDomainOnTarget.length === 0) {
57
+ return 0;
58
+ }
59
+
60
+ if (useIntegrationRestriction) {
61
+ for (let targetID of activeDomainOnTarget) {
62
+ let targetToSource = partialInverse[targetID];
63
+ let total = 0;
64
+ for (const diaID of targetToSource) {
65
+ const prediction = predictions[diaID];
66
+ total += prediction.allHydrogens;
67
+ }
68
+
69
+ const { integration } = targets[targetID];
70
+ if (total - integration >= 0.5) {
71
+ return 0;
72
+ }
73
+ }
74
+ }
75
+
76
+ //chemical shift score
77
+ let chemicalShiftScore = useChemicalShiftScore
78
+ ? chemicalShiftScoring(partial, options)
79
+ : 1;
80
+
81
+ const penaltyByStarts = countStars / totalPartial;
82
+
83
+ return chemicalShiftScore - penaltyByStarts;
84
+ }
85
+
86
+ function chemicalShiftScoring(
87
+ partial: Array<string | null>,
88
+ options: PartialScoreOptions,
89
+ ) {
90
+ const { tolerance } = options.restrictionByCS;
91
+ const { diaIDPeerPossibleAssignment, predictions, targets } = options;
92
+
93
+ let chemicalShiftScore = 0;
94
+ let count = 0;
95
+ for (let index = 0; index < partial.length; index++) {
96
+ const targetID = partial[index];
97
+ if (targetID && targetID !== '*') {
98
+ count++;
99
+ let diaID = diaIDPeerPossibleAssignment[index];
100
+ let source = predictions[diaID];
101
+ let target = targets[targetID];
102
+ let error = tolerance;
103
+ if (source.error) {
104
+ error = Math.max(source.error, tolerance);
105
+ }
106
+ if (typeof source.delta === 'undefined') {
107
+ // Chemical shift is not a restriction
108
+ chemicalShiftScore += 1;
109
+ } else {
110
+ const delta =
111
+ target.signals && target.signals.length > 0
112
+ ? target.signals[0].delta
113
+ : (target.to + target.from) / 2;
114
+ let diff = Math.abs(source.delta - delta);
115
+ if (diff < error) {
116
+ chemicalShiftScore += 1;
117
+ } else {
118
+ diff = Math.abs(diff - error);
119
+ chemicalShiftScore += (-0.25 / error) * diff + 1;
120
+ }
121
+ }
122
+ }
123
+ }
124
+ if (count > 0) {
125
+ chemicalShiftScore /= count;
126
+ }
127
+ return chemicalShiftScore;
128
+ }
package/src/index.ts CHANGED
@@ -1,9 +1,3 @@
1
- /**
2
- * @typedef {Object} DataXY
3
- * @property {Array<Number>} x Array of x values
4
- * @property {Array<Number>} y Array of y values
5
- */
6
-
7
1
  export * from './constants/gyromagneticRatio';
8
2
  export * from './constants/impurities';
9
3
  export * from './constants/couplingPatterns';
@@ -17,6 +11,9 @@ export * from './prediction/predictHSQC';
17
11
  export * from './prediction/predictHMBC';
18
12
  export * from './prediction/predictAll';
19
13
 
14
+ export * from './assignment/get1HAssignments';
15
+ export * from './assignment/get13CAssignments';
16
+
20
17
  export * from './ranges/rangesToACS';
21
18
  export * from './ranges/rangesToXY';
22
19
 
@@ -66,7 +66,7 @@ function checkImpurity(
66
66
  while (i--) {
67
67
  j = peakList.length;
68
68
  while (j--) {
69
- tolerance = error + peakList[j].shape.width;
69
+ tolerance = error + peakList[j].width;
70
70
  difference = Math.abs(impurity[i].shift - peakList[j].x);
71
71
  if (difference < tolerance) {
72
72
  // && (impurity[i].multiplicity === '' || (impurity[i].multiplicity.indexOf(peakList[j].multiplicity)) { // some impurities has multiplicities like 'bs' but at presents it is unsupported