Skip to content

Commit

Permalink
fix: check symmetry first for manual range picking (#2339)
Browse files Browse the repository at this point in the history
* chore: add test case for detectSignal function
Merge coupling based on a tolerance
  • Loading branch information
jobo322 committed May 9, 2023
1 parent 34c41b5 commit 0886f50
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 21 deletions.
7 changes: 6 additions & 1 deletion src/component/modal/MultipletAnalysisModal.tsx
Expand Up @@ -155,8 +155,13 @@ export default function MultipletAnalysisModal({
try {
const result = analyseMultiplet(analysesProps, {
frequency: info.originFrequency,
minimalResolution: 0.3,
maxTestedJ: 17,
takeBestPartMultiplet: true,
symmetrizeEachStep: true,
correctVerticalOffset: true,
symmetrizeEachStep: false,
decreasingJvalues: true,
makeShortCutForSpeed: true,
debug: true,
});
setCalcFinished(true);
Expand Down
35 changes: 35 additions & 0 deletions src/data/data1d/Spectrum1D/ranges/__tests__/detectSignal.test.ts
@@ -0,0 +1,35 @@
import { describe, it, expect } from 'vitest';

import detectSignal from '../detectSignal';
import { rangesToXY } from 'nmr-processing';

describe('lineBroadening', () => {
it('simple x, re, im to 1 Hz exp.', () => {
const from = 0.98;
const to = 1.02;
const frequency = 400;
const { x, y: re } = rangesToXY(
[
{
from,
to,
signals: [
{
delta: 1,
multiplicity: 't',
js: [{ coupling: 7.2, multiplicity: 't' }],
},
],
},
],
{ from: from - 0.02, to: to + 0.02, nbPoints: 512, frequency },
);
const result = detectSignal(
{ x: new Float64Array(x), re },
{ from, to, frequency },
);
expect(result?.multiplicity).toBe('t');
expect(result?.delta).toBeCloseTo(1, 3);
expect(result?.js[0].coupling).toBeCloseTo(7.2, 2);
});
});
71 changes: 51 additions & 20 deletions src/data/data1d/Spectrum1D/ranges/detectSignal.ts
@@ -1,6 +1,6 @@
import { xGetFromToIndex } from 'ml-spectra-processing';
import { analyseMultiplet } from 'multiplet-analysis';
import { xyAutoPeaksPicking } from 'nmr-processing';
import { signalJoinCouplings, xyAutoPeaksPicking } from 'nmr-processing';

export const MAX_LENGTH = 2048;

Expand All @@ -24,39 +24,70 @@ export default function detectSignal(
!checkMaxLength ||
(checkMaxLength && toIndex - fromIndex <= MAX_LENGTH)
) {
const data = {
const dataRoi = {
x: x.slice(fromIndex, toIndex),
y: re.slice(fromIndex, toIndex),
};

const result = analyseMultiplet(data, {
const result = analyseMultiplet(dataRoi, {
frequency,
minimalResolution: 0.3,
maxTestedJ: 17,
checkSymmetryFirst: true,
takeBestPartMultiplet: true,
symmetrizeEachStep: true,
correctVerticalOffset: true,
symmetrizeEachStep: false,
decreasingJvalues: true,
makeShortCutForSpeed: true,
});

if (result && result.chemShift === undefined) return;

const signal = {
multiplicity: result.js.map((j) => j.multiplicity).join(''),
const { delta, js } = joinCouplings(result);

let cs = 0;
let area = 0;
for (let i = 0; i < dataRoi.x.length; i++) {
cs += dataRoi.x[i] * dataRoi.y[i];
area += dataRoi.y[i];
}
cs /= area;

const peakList =
js.length === 0 ? xyAutoPeaksPicking(dataRoi, { frequency }) : [];

return {
multiplicity:
js.length > 0
? js.map((j) => j.multiplicity).join('')
: Math.abs(cs - delta) / cs < 1e-3
? peakList.length === 1
? 's'
: 'm'
: 'm',
kind: 'signal',
delta: result.chemShift,
js: result.js,
delta: cs,
js,
diaIDs: [],
};

if (result.js.length === 0) {
const { x: xData } = data;
const { chemShift: delta } = result;
const peakList = xyAutoPeaksPicking(data, { frequency });
const deltaX = xData[0] - xData[1];
const peaks = peakList.filter(
(peak) => peak.x < delta - deltaX && peak.x > delta + deltaX,
);
if (peaks.length === 1) signal.multiplicity = 's';
}
return signal;
} else {
throw new Error(`length of signal should not exceed ${MAX_LENGTH} points`);
}
}

function joinCouplings(result: any) {
const { chemShift: delta, js } = result;
return {
delta,
js:
js.length > 1
? signalJoinCouplings(
{
delta,
js,
},
{ tolerance: 0.6, ignoreDiaIDs: true },
).js
: js,
};
}

0 comments on commit 0886f50

Please sign in to comment.