nmr-processing 8.0.0 → 8.1.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.
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/peaks/NMRPeak1D.d.ts +0 -1
- package/lib/peaks/solventSuppression.d.ts +3 -0
- package/lib/peaks/solventSuppression.js +147 -0
- package/lib/peaks/solventSuppression.js.map +1 -0
- package/lib/peaks/util/jAnalyzer.d.ts +1 -1
- package/lib/ranges/rangesToXY.js +27 -3
- package/lib/ranges/rangesToXY.js.map +1 -1
- package/lib/signals/addDummySignals.d.ts +2 -0
- package/lib/signals/addDummySignals.js +56 -0
- package/lib/signals/addDummySignals.js.map +1 -0
- package/lib/signals/hackSignalsToXY.js +2 -48
- package/lib/signals/hackSignalsToXY.js.map +1 -1
- package/lib/signals/simulation/simulate1D.d.ts +1 -39
- package/lib/signals/simulation/simulate1D.js +13 -240
- package/lib/signals/simulation/simulate1D.js.map +1 -1
- package/lib/signals/simulation/simulateXYPeaks.d.ts +47 -0
- package/lib/signals/simulation/simulateXYPeaks.js +246 -0
- package/lib/signals/simulation/simulateXYPeaks.js.map +1 -0
- package/lib/utilities/getFrequency.d.ts +1 -1
- package/lib/utilities/getFrequency.js +4 -4
- package/lib/utilities/getFrequency.js.map +1 -1
- package/lib-esm/index.js +1 -1
- package/lib-esm/index.js.map +1 -1
- package/lib-esm/peaks/solventSuppression.js +140 -0
- package/lib-esm/peaks/solventSuppression.js.map +1 -0
- package/lib-esm/ranges/rangesToXY.js +27 -3
- package/lib-esm/ranges/rangesToXY.js.map +1 -1
- package/lib-esm/signals/addDummySignals.js +52 -0
- package/lib-esm/signals/addDummySignals.js.map +1 -0
- package/lib-esm/signals/hackSignalsToXY.js +2 -48
- package/lib-esm/signals/hackSignalsToXY.js.map +1 -1
- package/lib-esm/signals/simulation/simulate1D.js +14 -238
- package/lib-esm/signals/simulation/simulate1D.js.map +1 -1
- package/lib-esm/signals/simulation/simulateXYPeaks.js +239 -0
- package/lib-esm/signals/simulation/simulateXYPeaks.js.map +1 -0
- package/lib-esm/utilities/getFrequency.js +1 -1
- package/lib-esm/utilities/getFrequency.js.map +1 -1
- package/package.json +4 -2
- package/src/index.ts +1 -1
- package/src/peaks/NMRPeak1D.ts +0 -1
- package/src/peaks/solventSuppression.ts +186 -0
- package/src/peaks/util/jAnalyzer.ts +1 -1
- package/src/ranges/rangesToXY.ts +33 -4
- package/src/signals/addDummySignals.ts +77 -0
- package/src/signals/hackSignalsToXY.ts +2 -72
- package/src/signals/simulation/simulate1D.ts +14 -319
- package/src/signals/simulation/simulateXYPeaks.ts +332 -0
- package/src/utilities/getFrequency.ts +1 -1
- package/lib/constants/gyromagneticRatio.d.ts +0 -6
- package/lib/constants/gyromagneticRatio.js +0 -26
- package/lib/constants/gyromagneticRatio.js.map +0 -1
- package/lib-esm/constants/gyromagneticRatio.js +0 -23
- package/lib-esm/constants/gyromagneticRatio.js.map +0 -1
- package/src/constants/gyromagneticRatio.ts +0 -49
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import linearSumAssignment from 'linear-sum-assignment';
|
|
2
|
+
import { Matrix } from 'ml-matrix';
|
|
3
|
+
import { gaussianFct } from 'ml-peak-shape-generator';
|
|
4
|
+
import { xFindClosestIndex, xMaxValue } from 'ml-spectra-processing';
|
|
5
|
+
import { addDummySignals } from '../signals/addDummySignals';
|
|
6
|
+
import { signalsToSpinSystem } from '../signals/simulation/signalsToSpinSystem';
|
|
7
|
+
import { simulateXYPeaks } from '../signals/simulation/simulateXYPeaks';
|
|
8
|
+
import { splitSpinSystem } from '../signals/simulation/splitSpinSystem';
|
|
9
|
+
export function solventSuppression(peakList, solvent, options = {}) {
|
|
10
|
+
const peaks = [...peakList];
|
|
11
|
+
sortAscending(peaks);
|
|
12
|
+
const xValues = peaks.map((peak) => peak.x);
|
|
13
|
+
const { markSolventPeaks = false } = options;
|
|
14
|
+
let solventSignals = solvent; //addDummySignals(solvent);
|
|
15
|
+
// solventSignals = solventSignals.slice(0, solventSignals.findIndex((signal) => signal.delta > 400));
|
|
16
|
+
for (const solventSignal of solventSignals) {
|
|
17
|
+
const solventXYPeaks = solventSignal.peaks
|
|
18
|
+
? solventSignal.peaks
|
|
19
|
+
: getSolventPeaks(solventSignal);
|
|
20
|
+
sortAscending(solventXYPeaks);
|
|
21
|
+
let upIndex = xFindClosestIndex(xValues, solventXYPeaks[solventXYPeaks.length - 1].x + 1);
|
|
22
|
+
let lowIndex = xFindClosestIndex(xValues, solventXYPeaks[0].x - 1);
|
|
23
|
+
if (upIndex === lowIndex)
|
|
24
|
+
continue;
|
|
25
|
+
const nearPeaks = peaks.slice(lowIndex, upIndex + 1);
|
|
26
|
+
const amplitudeResiduals = [];
|
|
27
|
+
const deltaResiduals = [];
|
|
28
|
+
const positionResiduals = [];
|
|
29
|
+
for (let peak of nearPeaks) {
|
|
30
|
+
const shiftedSolventPeaks = getShiftedSolventPeaks(peak, solventSignal, solventXYPeaks);
|
|
31
|
+
const closestPeaks = getClosestPeaks(shiftedSolventPeaks, nearPeaks);
|
|
32
|
+
let deltaResidual = 0;
|
|
33
|
+
let amplitudeResidual = 0;
|
|
34
|
+
let positionResidual = 0;
|
|
35
|
+
for (let i = 0; i < closestPeaks.length; i++) {
|
|
36
|
+
amplitudeResidual += Math.abs(shiftedSolventPeaks[i].y - closestPeaks[i].y);
|
|
37
|
+
deltaResidual += Math.abs(shiftedSolventPeaks[i].x - closestPeaks[i].x);
|
|
38
|
+
}
|
|
39
|
+
if (closestPeaks.length === 0) {
|
|
40
|
+
deltaResidual = Number.MAX_SAFE_INTEGER;
|
|
41
|
+
amplitudeResidual = Number.MAX_SAFE_INTEGER;
|
|
42
|
+
positionResidual = Number.MAX_SAFE_INTEGER;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
positionResidual = gaussianFct(solventSignal.delta - peak.x, 0.5);
|
|
46
|
+
}
|
|
47
|
+
amplitudeResiduals.push(amplitudeResidual);
|
|
48
|
+
deltaResiduals.push(deltaResidual);
|
|
49
|
+
positionResiduals.push(positionResidual);
|
|
50
|
+
}
|
|
51
|
+
const maxAmplitude = xMaxValue(amplitudeResiduals);
|
|
52
|
+
const maxDelta = xMaxValue(deltaResiduals);
|
|
53
|
+
const maxPosition = xMaxValue(positionResiduals);
|
|
54
|
+
let minIndex = -1;
|
|
55
|
+
let minScore = Number.MAX_SAFE_INTEGER;
|
|
56
|
+
for (let i = 0; i < deltaResiduals.length; i++) {
|
|
57
|
+
const value = (amplitudeResiduals[i] / maxAmplitude +
|
|
58
|
+
deltaResiduals[i] / maxDelta +
|
|
59
|
+
(1 - positionResiduals[i]) / maxPosition) /
|
|
60
|
+
3;
|
|
61
|
+
if (minScore > value) {
|
|
62
|
+
minIndex = i;
|
|
63
|
+
minScore = value;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const shiftedSolventPeaks = getShiftedSolventPeaks(nearPeaks[minIndex], solventSignal, solventXYPeaks);
|
|
67
|
+
const diff = getDiffMatrix(shiftedSolventPeaks, nearPeaks);
|
|
68
|
+
const { rowAssignments, gain } = linearSumAssignment(diff, {
|
|
69
|
+
maximaze: false,
|
|
70
|
+
});
|
|
71
|
+
if (gain === -1)
|
|
72
|
+
return peaks;
|
|
73
|
+
if (markSolventPeaks) {
|
|
74
|
+
for (let index of rowAssignments) {
|
|
75
|
+
peaks[index + lowIndex].kind = 'solvent';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
rowAssignments.sort((a, b) => b - a);
|
|
80
|
+
for (let index of rowAssignments) {
|
|
81
|
+
peaks.splice(index + lowIndex, 1);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return peaks;
|
|
86
|
+
}
|
|
87
|
+
function getSolventPeaks(signal, options = {}) {
|
|
88
|
+
let signals = addDummySignals([signal]);
|
|
89
|
+
let spinSystem = signalsToSpinSystem(signals);
|
|
90
|
+
const { frequency = 400, maxClusterSize = 8 } = options;
|
|
91
|
+
spinSystem.clusters = splitSpinSystem(spinSystem, {
|
|
92
|
+
frequency,
|
|
93
|
+
maxClusterSize,
|
|
94
|
+
});
|
|
95
|
+
const peaks = simulateXYPeaks(spinSystem);
|
|
96
|
+
return peaks.filter((peak) => peak.x < 1000);
|
|
97
|
+
}
|
|
98
|
+
function getShiftedSolventPeaks(peak, solventSignal, solventXYPeaks) {
|
|
99
|
+
const shiftedSolventPeaks = JSON.parse(JSON.stringify(solventXYPeaks));
|
|
100
|
+
// shift x values of solventPeaks to center it to the current peak.
|
|
101
|
+
const deltaPPM = peak.x - solventSignal.delta;
|
|
102
|
+
const maxIntensity = shiftedSolventPeaks.reduce((max, current) => (current.y > max ? current.y : max), shiftedSolventPeaks[0].y);
|
|
103
|
+
for (let shiftedSolventPeak of shiftedSolventPeaks) {
|
|
104
|
+
shiftedSolventPeak.x += deltaPPM;
|
|
105
|
+
shiftedSolventPeak.y /= maxIntensity;
|
|
106
|
+
}
|
|
107
|
+
return shiftedSolventPeaks;
|
|
108
|
+
}
|
|
109
|
+
function getClosestPeaks(shiftedSolventPeaks, nearPeaks) {
|
|
110
|
+
const diff = getDiffMatrix(shiftedSolventPeaks, nearPeaks);
|
|
111
|
+
const { rowAssignments, gain } = linearSumAssignment(diff, {
|
|
112
|
+
maximaze: false,
|
|
113
|
+
});
|
|
114
|
+
if (gain === -1)
|
|
115
|
+
return [];
|
|
116
|
+
const assignmentPeaks = [];
|
|
117
|
+
let maxValue = Number.MIN_SAFE_INTEGER;
|
|
118
|
+
for (let index of rowAssignments) {
|
|
119
|
+
if (maxValue < nearPeaks[index].y)
|
|
120
|
+
maxValue = nearPeaks[index].y;
|
|
121
|
+
assignmentPeaks.push({ ...nearPeaks[index] });
|
|
122
|
+
}
|
|
123
|
+
assignmentPeaks.forEach((peak, i, arr) => (arr[i].y /= maxValue));
|
|
124
|
+
return assignmentPeaks;
|
|
125
|
+
}
|
|
126
|
+
function sortAscending(peaks) {
|
|
127
|
+
return peaks[0].x > peaks[1].x ? peaks.sort((a, b) => a.x - b.x) : peaks;
|
|
128
|
+
}
|
|
129
|
+
function getDiffMatrix(rows, columns) {
|
|
130
|
+
const nbColumns = columns.length;
|
|
131
|
+
const nbRows = rows.length;
|
|
132
|
+
const diff = new Matrix(nbRows, nbColumns);
|
|
133
|
+
for (let r = 0; r < nbRows; r++) {
|
|
134
|
+
for (let c = 0; c < nbColumns; c++) {
|
|
135
|
+
diff.set(r, c, Math.abs(rows[r].x - columns[c].x));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return diff;
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=solventSuppression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"solventSuppression.js","sourceRoot":"","sources":["../../src/peaks/solventSuppression.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,17 +7,26 @@ function checkForSignals(ranges) {
|
|
|
7
7
|
throw new Error('range has not signals');
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
|
+
const defaultFromTo = (nucleus = '') => {
|
|
11
|
+
switch (nucleus.toUpperCase()) {
|
|
12
|
+
case '13C':
|
|
13
|
+
return { from: -5, to: 206 };
|
|
14
|
+
default:
|
|
15
|
+
return { from: -0.5, to: 10.5 };
|
|
16
|
+
}
|
|
17
|
+
};
|
|
10
18
|
export function rangesToXY(ranges, options = {}) {
|
|
11
19
|
checkForSignals(ranges);
|
|
12
|
-
let { frequency = 400, lineWidth = 1,
|
|
20
|
+
let { frequency = 400, lineWidth = 1, nbPoints = 16 * 1024, shape = { kind: 'gaussian' }, } = options;
|
|
13
21
|
const addSpectrum = (a, b) => {
|
|
14
22
|
for (let i = 0; i < nbPoints; i++) {
|
|
15
23
|
a[i] += b[i];
|
|
16
24
|
}
|
|
17
25
|
};
|
|
26
|
+
const { from, to } = getFromTo(ranges, options);
|
|
18
27
|
const spectrumOptions = {
|
|
19
|
-
from,
|
|
20
28
|
to,
|
|
29
|
+
from,
|
|
21
30
|
nbPoints,
|
|
22
31
|
shape,
|
|
23
32
|
lineWidth,
|
|
@@ -77,7 +86,7 @@ function broadPeakOrMultipletSpectrum(signals, options = {}) {
|
|
|
77
86
|
return spectrumGenerator.getSpectrum();
|
|
78
87
|
}
|
|
79
88
|
function peaksOfMultiplet(delta, options) {
|
|
80
|
-
const { frequency, lineWidth, intensities = [1, 2, 5, 4, 5,
|
|
89
|
+
const { frequency, lineWidth, intensities = [1, 2, 5, 4, 5, 7, 5, 4, 5, 2, 1], } = options;
|
|
81
90
|
const lineWidthPpm = lineWidth / frequency;
|
|
82
91
|
const spaceBetweenPeaks = lineWidthPpm * 1.5;
|
|
83
92
|
const peaks = [];
|
|
@@ -104,4 +113,19 @@ function normalizeSpectrum(spectrum, signals, options = {}) {
|
|
|
104
113
|
}
|
|
105
114
|
}
|
|
106
115
|
}
|
|
116
|
+
function getFromTo(ranges, options) {
|
|
117
|
+
const { from: defaultFrom, to: defaultTo } = defaultFromTo(options.nucleus);
|
|
118
|
+
let rangesFrom = Number.MAX_SAFE_INTEGER;
|
|
119
|
+
let rangesTo = Number.MIN_SAFE_INTEGER;
|
|
120
|
+
for (const range of ranges) {
|
|
121
|
+
for (const signal of range.signals || []) {
|
|
122
|
+
if (rangesFrom > signal.delta)
|
|
123
|
+
rangesFrom = signal.delta;
|
|
124
|
+
if (rangesTo < signal.delta)
|
|
125
|
+
rangesTo = signal.delta;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const { from = Math.min(rangesFrom - 0.5, defaultFrom), to = Math.max(rangesTo + 0.5, defaultTo), } = options;
|
|
129
|
+
return { from, to };
|
|
130
|
+
}
|
|
107
131
|
//# sourceMappingURL=rangesToXY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rangesToXY.js","sourceRoot":"","sources":["../../src/ranges/rangesToXY.ts"],"names":[],"mappings":"AACA,OAAO,mBAAmB,MAAM,0BAA0B,CAAC;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGvD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAsC7D,SAAS,eAAe,CACtB,MAAkB;IAElB,KAAK,IAAI,KAAK,IAAI,MAAM,EAAE;QACxB,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;KAC9D;AACH,CAAC;
|
|
1
|
+
{"version":3,"file":"rangesToXY.js","sourceRoot":"","sources":["../../src/ranges/rangesToXY.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { couplingPatterns } from '../constants/couplingPatterns';
|
|
2
|
+
export function addDummySignals(signals) {
|
|
3
|
+
let newSignals = JSON.parse(JSON.stringify(signals));
|
|
4
|
+
signals.forEach((signal, s) => {
|
|
5
|
+
const { js: jCouplings = [], atoms: signalAssignment = [s] } = signal;
|
|
6
|
+
let { newCouplings, tempSignals } = checkCouplings(jCouplings, newSignals, signalAssignment);
|
|
7
|
+
if (tempSignals.length > 0)
|
|
8
|
+
newSignals.push(...tempSignals);
|
|
9
|
+
newSignals[s].js = newCouplings;
|
|
10
|
+
newSignals[s].atoms = signalAssignment;
|
|
11
|
+
});
|
|
12
|
+
return newSignals.sort((a, b) => a.delta - b.delta);
|
|
13
|
+
}
|
|
14
|
+
function checkCouplings(jCouplings, signals, signalAssignment) {
|
|
15
|
+
let newSignalAssignment = signals.length - 1;
|
|
16
|
+
let tempSignals = [];
|
|
17
|
+
const newCouplings = jCouplings.reduce((newCouplings, jCoupling) => {
|
|
18
|
+
const { atoms = [], multiplicity, coupling } = jCoupling;
|
|
19
|
+
if (atoms.length === 0) {
|
|
20
|
+
if (coupling && multiplicity) {
|
|
21
|
+
let tempCouplings = [];
|
|
22
|
+
const nbLinks = couplingPatterns.indexOf(multiplicity);
|
|
23
|
+
for (let i = 0; i < nbLinks; i++) {
|
|
24
|
+
newSignalAssignment++;
|
|
25
|
+
tempCouplings.push({
|
|
26
|
+
coupling,
|
|
27
|
+
atoms: [newSignalAssignment],
|
|
28
|
+
});
|
|
29
|
+
tempSignals.push(formatSignal(coupling, [newSignalAssignment], signalAssignment));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
newCouplings.push(jCoupling);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return newCouplings;
|
|
37
|
+
}, []);
|
|
38
|
+
return { newCouplings, tempSignals };
|
|
39
|
+
}
|
|
40
|
+
function formatSignal(coupling, newSignalAssignment, signalAssignment) {
|
|
41
|
+
return {
|
|
42
|
+
delta: 100000,
|
|
43
|
+
atoms: newSignalAssignment,
|
|
44
|
+
js: [
|
|
45
|
+
{
|
|
46
|
+
coupling,
|
|
47
|
+
atoms: signalAssignment,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=addDummySignals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addDummySignals.js","sourceRoot":"","sources":["../../src/signals/addDummySignals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAKjE,MAAM,UAAU,eAAe,CAAC,OAAsB;IACpD,IAAI,UAAU,GAAkB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAEpE,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QAC5B,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,EAAE,EAAE,KAAK,EAAE,gBAAgB,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC;QAEtE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,cAAc,CAChD,UAAU,EACV,UAAU,EACV,gBAAgB,CACjB,CAAC;QAEF,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;QAE5D,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,YAAY,CAAC;QAChC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,gBAAgB,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,cAAc,CACrB,UAAuB,EACvB,OAAsB,EACtB,gBAA0B;IAE1B,IAAI,mBAAmB,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7C,IAAI,WAAW,GAAkB,EAAE,CAAC;IACpC,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CACpC,CAAC,YAAY,EAAE,SAAS,EAAE,EAAE;QAC1B,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;QACzD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;YACtB,IAAI,QAAQ,IAAI,YAAY,EAAE;gBAC5B,IAAI,aAAa,GAAgB,EAAE,CAAC;gBACpC,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;gBACvD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,EAAE;oBAChC,mBAAmB,EAAE,CAAC;oBACtB,aAAa,CAAC,IAAI,CAAC;wBACjB,QAAQ;wBACR,KAAK,EAAE,CAAC,mBAAmB,CAAC;qBAC7B,CAAC,CAAC;oBACH,WAAW,CAAC,IAAI,CACd,YAAY,CAAC,QAAQ,EAAE,CAAC,mBAAmB,CAAC,EAAE,gBAAgB,CAAC,CAChE,CAAC;iBACH;aACF;iBAAM;gBACL,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;aAC9B;SACF;QACD,OAAO,YAAY,CAAC;IACtB,CAAC,EACD,EAAE,CACH,CAAC;IACF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AACvC,CAAC;AAED,SAAS,YAAY,CACnB,QAAgB,EAChB,mBAA6B,EAC7B,gBAA0B;IAE1B,OAAO;QACL,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,mBAAmB;QAC1B,EAAE,EAAE;YACF;gBACE,QAAQ;gBACR,KAAK,EAAE,gBAAgB;aACxB;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1,57 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { addDummySignals } from './addDummySignals';
|
|
2
2
|
import { signalsToXY } from './signalsToXY';
|
|
3
3
|
/**
|
|
4
4
|
* Create the xy object from an array of 1D signals.
|
|
5
5
|
* @param signals Array of signals with assigned or unassigned couplings.
|
|
6
6
|
*/
|
|
7
7
|
export function hackSignalsToXY(signals, options = {}) {
|
|
8
|
-
let newSignals =
|
|
9
|
-
signals.forEach((signal, s) => {
|
|
10
|
-
const { js: jCouplings = [], atoms: signalAssignment = [s] } = signal;
|
|
11
|
-
let { newCouplings, tempSignals } = checkCouplings(jCouplings, newSignals, signalAssignment);
|
|
12
|
-
if (tempSignals.length > 0)
|
|
13
|
-
newSignals.push(...tempSignals);
|
|
14
|
-
newSignals[s].js = newCouplings;
|
|
15
|
-
newSignals[s].atoms = signalAssignment;
|
|
16
|
-
});
|
|
8
|
+
let newSignals = addDummySignals(signals);
|
|
17
9
|
return signalsToXY(newSignals, options);
|
|
18
10
|
}
|
|
19
|
-
function checkCouplings(jCouplings, signals, signalAssignment) {
|
|
20
|
-
let newSignalAssignment = signals.length - 1;
|
|
21
|
-
let tempSignals = [];
|
|
22
|
-
const newCouplings = jCouplings.reduce((newCouplings, jCoupling) => {
|
|
23
|
-
const { atoms = [], multiplicity, coupling } = jCoupling;
|
|
24
|
-
if (atoms.length === 0) {
|
|
25
|
-
if (coupling && multiplicity) {
|
|
26
|
-
let tempCouplings = [];
|
|
27
|
-
const nbLinks = couplingPatterns.indexOf(multiplicity);
|
|
28
|
-
for (let i = 0; i < nbLinks; i++) {
|
|
29
|
-
newSignalAssignment++;
|
|
30
|
-
tempCouplings.push({
|
|
31
|
-
coupling,
|
|
32
|
-
atoms: [newSignalAssignment],
|
|
33
|
-
});
|
|
34
|
-
tempSignals.push(formatSignal(coupling, [newSignalAssignment], signalAssignment));
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
newCouplings.push(jCoupling);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return newCouplings;
|
|
42
|
-
}, []);
|
|
43
|
-
return { newCouplings, tempSignals };
|
|
44
|
-
}
|
|
45
|
-
function formatSignal(coupling, newSignalAssignment, signalAssignment) {
|
|
46
|
-
return {
|
|
47
|
-
delta: 100000,
|
|
48
|
-
atoms: newSignalAssignment,
|
|
49
|
-
js: [
|
|
50
|
-
{
|
|
51
|
-
coupling,
|
|
52
|
-
atoms: signalAssignment,
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
11
|
//# sourceMappingURL=hackSignalsToXY.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hackSignalsToXY.js","sourceRoot":"","sources":["../../src/signals/hackSignalsToXY.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hackSignalsToXY.js","sourceRoot":"","sources":["../../src/signals/hackSignalsToXY.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAsB,WAAW,EAAE,MAAM,eAAe,CAAC;AAEhE;;;GAGG;AAEH,MAAM,UAAU,eAAe,CAC7B,OAAsB,EACtB,UAA8B,EAAE;IAEhC,IAAI,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,OAAO,WAAW,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { SparseMatrix } from 'ml-sparse-matrix';
|
|
4
|
-
import { SpectrumGenerator } from 'spectrum-generator';
|
|
5
|
-
import getPauliMatrix from './getPauliMatrix';
|
|
6
|
-
const smallValue = 1e-2;
|
|
1
|
+
import { generateSpectrum } from 'spectrum-generator';
|
|
2
|
+
import { simulateXYPeaks } from './simulateXYPeaks';
|
|
7
3
|
/**
|
|
8
4
|
* This function simulates a one dimensional nmr spectrum. This function returns an array containing the relative intensities of the spectrum in the specified simulation window (from-to).
|
|
9
5
|
*/
|
|
@@ -12,241 +8,21 @@ export default function simulate1D(
|
|
|
12
8
|
* The SpinSystem object to be simulated
|
|
13
9
|
*/
|
|
14
10
|
spinSystem, options = {}) {
|
|
15
|
-
let { lineWidth = 1,
|
|
11
|
+
let { lineWidth = 1, frequency: frequencyMHz = 400, from = 0, to = 10, nbPoints = 1024, shape = {
|
|
16
12
|
kind: 'gaussian',
|
|
17
13
|
}, } = options;
|
|
18
14
|
let peakWidth = lineWidth / frequencyMHz;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
const xyPeaks = simulateXYPeaks(spinSystem, options);
|
|
16
|
+
return generateSpectrum(xyPeaks, {
|
|
17
|
+
generator: {
|
|
18
|
+
from,
|
|
19
|
+
to,
|
|
20
|
+
nbPoints,
|
|
21
|
+
},
|
|
22
|
+
peakOptions: {
|
|
23
|
+
shape,
|
|
24
|
+
width: peakWidth,
|
|
25
|
+
},
|
|
25
26
|
});
|
|
26
|
-
const chemicalShifts = spinSystem.chemicalShifts.slice();
|
|
27
|
-
for (let i = 0; i < chemicalShifts.length; i++) {
|
|
28
|
-
chemicalShifts[i] = chemicalShifts[i] * frequencyMHz;
|
|
29
|
-
}
|
|
30
|
-
const multiplicity = spinSystem.multiplicity;
|
|
31
|
-
for (const cluster of spinSystem.clusters) {
|
|
32
|
-
let clusterFake = cluster.map((cluster) => cluster < 0 ? -cluster - 1 : cluster);
|
|
33
|
-
let weight = 1;
|
|
34
|
-
let sumI = 0;
|
|
35
|
-
let frequencies = [];
|
|
36
|
-
let intensities = [];
|
|
37
|
-
if (cluster.length > maxClusterSize) {
|
|
38
|
-
// This is a single spin, but the cluster exceeds the maxClusterSize criteria
|
|
39
|
-
// we use the simple multiplicity algorithm
|
|
40
|
-
// Add the central peak. It will be split with every single J coupling.
|
|
41
|
-
let index = 0;
|
|
42
|
-
while (cluster[index++] < 0)
|
|
43
|
-
;
|
|
44
|
-
index = cluster[index - 1];
|
|
45
|
-
frequencies.push(-chemicalShifts[index]);
|
|
46
|
-
for (let i = 0; i < cluster.length; i++) {
|
|
47
|
-
if (cluster[i] < 0) {
|
|
48
|
-
let jc = spinSystem.couplingConstants.get(index, clusterFake[i]) / 2;
|
|
49
|
-
let currentSize = frequencies.length;
|
|
50
|
-
for (let j = 0; j < currentSize; j++) {
|
|
51
|
-
frequencies.push(frequencies[j] + jc);
|
|
52
|
-
frequencies[j] -= jc;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
frequencies.sort((a, b) => a - b);
|
|
57
|
-
sumI = frequencies.length;
|
|
58
|
-
weight = 1;
|
|
59
|
-
for (let i = 0; i < sumI; i++) {
|
|
60
|
-
intensities.push(1);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
const hamiltonian = getHamiltonian(chemicalShifts, spinSystem.couplingConstants, multiplicity, spinSystem.connectivity, clusterFake);
|
|
65
|
-
const hamSize = hamiltonian.rows;
|
|
66
|
-
// TODO: add support for sparse matrix in matrix types.
|
|
67
|
-
// @ts-expect-error sparse matrix not supported
|
|
68
|
-
const evd = new EVD(hamiltonian);
|
|
69
|
-
const V = evd.eigenvectorMatrix;
|
|
70
|
-
const diagB = evd.realEigenvalues;
|
|
71
|
-
const assignmentMatrix = new SparseMatrix(hamSize, hamSize);
|
|
72
|
-
const multLen = cluster.length;
|
|
73
|
-
weight = 0;
|
|
74
|
-
for (let n = 0; n < multLen; n++) {
|
|
75
|
-
const L = getPauliMatrix(multiplicity[clusterFake[n]]);
|
|
76
|
-
let temp = 1;
|
|
77
|
-
for (let j = 0; j < n; j++) {
|
|
78
|
-
temp *= multiplicity[clusterFake[j]];
|
|
79
|
-
}
|
|
80
|
-
const A = SparseMatrix.eye(temp);
|
|
81
|
-
temp = 1;
|
|
82
|
-
for (let j = n + 1; j < multLen; j++) {
|
|
83
|
-
temp *= multiplicity[clusterFake[j]];
|
|
84
|
-
}
|
|
85
|
-
const B = SparseMatrix.eye(temp);
|
|
86
|
-
const tempMat = A.kroneckerProduct(L.m).kroneckerProduct(B);
|
|
87
|
-
if (cluster[n] >= 0) {
|
|
88
|
-
assignmentMatrix.add(tempMat.mul(cluster[n] + 1));
|
|
89
|
-
weight++;
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
assignmentMatrix.add(tempMat.mul(cluster[n]));
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
let rhoip = Matrix.zeros(hamSize, hamSize);
|
|
96
|
-
assignmentMatrix.forEachNonZero((i, j, v) => {
|
|
97
|
-
if (v > 0) {
|
|
98
|
-
for (let k = 0; k < V.columns; k++) {
|
|
99
|
-
let element = V.get(j, k);
|
|
100
|
-
if (element !== 0) {
|
|
101
|
-
rhoip.set(i, k, rhoip.get(i, k) + element);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return v;
|
|
106
|
-
});
|
|
107
|
-
let rhoip2 = rhoip.clone();
|
|
108
|
-
assignmentMatrix.forEachNonZero((i, j, v) => {
|
|
109
|
-
if (v < 0) {
|
|
110
|
-
for (let k = 0; k < V.columns; k++) {
|
|
111
|
-
let element = V.get(j, k);
|
|
112
|
-
if (element !== 0) {
|
|
113
|
-
rhoip2.set(i, k, rhoip2.get(i, k) + element);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
return v;
|
|
118
|
-
});
|
|
119
|
-
const tV = V.transpose();
|
|
120
|
-
rhoip = tV.mmul(rhoip);
|
|
121
|
-
const sparseRhoip = new SparseMatrix(rhoip.to2DArray(), {
|
|
122
|
-
threshold: smallValue,
|
|
123
|
-
});
|
|
124
|
-
triuTimesAbs(sparseRhoip, smallValue);
|
|
125
|
-
rhoip2 = tV.mmul(rhoip2);
|
|
126
|
-
const sparseRhoip2 = new SparseMatrix(rhoip2.to2DArray(), {
|
|
127
|
-
threshold: smallValue,
|
|
128
|
-
});
|
|
129
|
-
sparseRhoip2.forEachNonZero((i, j, v) => {
|
|
130
|
-
return v;
|
|
131
|
-
});
|
|
132
|
-
triuTimesAbs(sparseRhoip2, smallValue);
|
|
133
|
-
sparseRhoip2.forEachNonZero((i, j, v) => {
|
|
134
|
-
let val = rhoip.get(i, j);
|
|
135
|
-
val = Math.min(Math.abs(val), Math.abs(v));
|
|
136
|
-
val *= val;
|
|
137
|
-
sumI += val;
|
|
138
|
-
let valFreq = diagB[i] - diagB[j];
|
|
139
|
-
let insertIn = binarySearch(frequencies, valFreq, (a, b) => a - b);
|
|
140
|
-
if (insertIn < 0) {
|
|
141
|
-
frequencies.splice(-1 - insertIn, 0, valFreq);
|
|
142
|
-
intensities.splice(-1 - insertIn, 0, val);
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
intensities[insertIn] += val;
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
const numFreq = frequencies.length;
|
|
150
|
-
if (numFreq > 0) {
|
|
151
|
-
weight /= sumI;
|
|
152
|
-
const diff = lineWidth / 64;
|
|
153
|
-
let valFreq = frequencies[0];
|
|
154
|
-
let inte = intensities[0];
|
|
155
|
-
let count = 1;
|
|
156
|
-
for (let i = 1; i < numFreq; i++) {
|
|
157
|
-
if (Math.abs(frequencies[i] - valFreq / count) < diff) {
|
|
158
|
-
inte += intensities[i];
|
|
159
|
-
valFreq += frequencies[i];
|
|
160
|
-
count++;
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
spectrumGenerator.addPeak({
|
|
164
|
-
x: -valFreq / count / frequencyMHz,
|
|
165
|
-
y: inte * weight,
|
|
166
|
-
});
|
|
167
|
-
valFreq = frequencies[i];
|
|
168
|
-
inte = intensities[i];
|
|
169
|
-
count = 1;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
spectrumGenerator.addPeak({
|
|
173
|
-
x: -valFreq / count / frequencyMHz,
|
|
174
|
-
y: inte * weight,
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return spectrumGenerator.getSpectrum();
|
|
179
|
-
}
|
|
180
|
-
function triuTimesAbs(A, val) {
|
|
181
|
-
A.forEachNonZero((i, j, v) => {
|
|
182
|
-
if (i > j)
|
|
183
|
-
return 0;
|
|
184
|
-
if (Math.abs(v) <= val)
|
|
185
|
-
return 0;
|
|
186
|
-
return v;
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Create a hamiltonian matrix for the given spinsystem
|
|
191
|
-
* @param {Array} chemicalShifts - An array containing the chemical shift in Hz
|
|
192
|
-
* @param {Array} couplingConstants - An array containing the coupling constants in Hz
|
|
193
|
-
* @param {Array} multiplicity - An array specifiying the multiplicities of each scalar coupling
|
|
194
|
-
* @param {Array} conMatrix - A one step connectivity matrix for the given spin system
|
|
195
|
-
* @param {Array} cluster - An binary array specifiying the spins to be considered for this hamiltonial
|
|
196
|
-
* @return {object}
|
|
197
|
-
*/
|
|
198
|
-
function getHamiltonian(chemicalShifts, couplingConstants, multiplicity, conMatrix, cluster) {
|
|
199
|
-
let hamSize = 1;
|
|
200
|
-
for (const element of cluster) {
|
|
201
|
-
hamSize *= multiplicity[element];
|
|
202
|
-
}
|
|
203
|
-
const clusterHam = new SparseMatrix(hamSize, hamSize);
|
|
204
|
-
for (let pos = 0; pos < cluster.length; pos++) {
|
|
205
|
-
let n = cluster[pos];
|
|
206
|
-
const L = getPauliMatrix(multiplicity[n]);
|
|
207
|
-
let A1, B1;
|
|
208
|
-
let temp = 1;
|
|
209
|
-
for (let i = 0; i < pos; i++) {
|
|
210
|
-
temp *= multiplicity[cluster[i]];
|
|
211
|
-
}
|
|
212
|
-
A1 = SparseMatrix.eye(temp);
|
|
213
|
-
temp = 1;
|
|
214
|
-
for (let i = pos + 1; i < cluster.length; i++) {
|
|
215
|
-
temp *= multiplicity[cluster[i]];
|
|
216
|
-
}
|
|
217
|
-
B1 = SparseMatrix.eye(temp);
|
|
218
|
-
const alpha = chemicalShifts[n];
|
|
219
|
-
const kronProd = A1.kroneckerProduct(L.z).kroneckerProduct(B1);
|
|
220
|
-
clusterHam.add(kronProd.mul(alpha));
|
|
221
|
-
for (let pos2 = 0; pos2 < cluster.length; pos2++) {
|
|
222
|
-
const k = cluster[pos2];
|
|
223
|
-
if (conMatrix.get(n, k) === 1) {
|
|
224
|
-
const S = getPauliMatrix(multiplicity[k]);
|
|
225
|
-
let A2, B2;
|
|
226
|
-
let temp = 1;
|
|
227
|
-
for (let i = 0; i < pos2; i++) {
|
|
228
|
-
temp *= multiplicity[cluster[i]];
|
|
229
|
-
}
|
|
230
|
-
A2 = SparseMatrix.eye(temp);
|
|
231
|
-
temp = 1;
|
|
232
|
-
for (let i = pos2 + 1; i < cluster.length; i++) {
|
|
233
|
-
temp *= multiplicity[cluster[i]];
|
|
234
|
-
}
|
|
235
|
-
B2 = SparseMatrix.eye(temp);
|
|
236
|
-
const kron1 = A1.kroneckerProduct(L.x)
|
|
237
|
-
.kroneckerProduct(B1)
|
|
238
|
-
.mmul(A2.kroneckerProduct(S.x).kroneckerProduct(B2));
|
|
239
|
-
kron1.add(A1.kroneckerProduct(L.y)
|
|
240
|
-
.kroneckerProduct(B1)
|
|
241
|
-
.mul(-1)
|
|
242
|
-
.mmul(A2.kroneckerProduct(S.y).kroneckerProduct(B2)));
|
|
243
|
-
kron1.add(A1.kroneckerProduct(L.z)
|
|
244
|
-
.kroneckerProduct(B1)
|
|
245
|
-
.mmul(A2.kroneckerProduct(S.z).kroneckerProduct(B2)));
|
|
246
|
-
clusterHam.add(kron1.mul(couplingConstants.get(n, k) / 2));
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
return clusterHam;
|
|
251
27
|
}
|
|
252
28
|
//# sourceMappingURL=simulate1D.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simulate1D.js","sourceRoot":"","sources":["../../../src/signals/simulation/simulate1D.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"simulate1D.js","sourceRoot":"","sources":["../../../src/signals/simulation/simulate1D.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAKtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;GAEG;AAEH,MAAM,CAAC,OAAO,UAAU,UAAU;AAChC;;GAEG;AACH,UAAsB,EACtB,UAA6B,EAAE;IAE/B,IAAI,EACF,SAAS,GAAG,CAAC,EACb,SAAS,EAAE,YAAY,GAAG,GAAG,EAC7B,IAAI,GAAG,CAAC,EACR,EAAE,GAAG,EAAE,EACP,QAAQ,GAAG,IAAI,EACf,KAAK,GAAG;QACN,IAAI,EAAE,UAAU;KACjB,GACF,GAAG,OAAO,CAAC;IAEZ,IAAI,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC;IAEzC,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAErD,OAAO,gBAAgB,CAAC,OAAO,EAAE;QAC/B,SAAS,EAAE;YACT,IAAI;YACJ,EAAE;YACF,QAAQ;SACT;QACD,WAAW,EAAE;YACX,KAAK;YACL,KAAK,EAAE,SAAS;SACjB;KACF,CAAC,CAAC;AACL,CAAC"}
|