Skip to content

Commit 5f8bd71

Browse files
feat: auto zones detection core function
1 parent 6c34e59 commit 5f8bd71

File tree

2 files changed

+145
-0
lines changed

2 files changed

+145
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Spectrum2D } from "@zakodium/nmrium-core";
2+
import { isFt2DSpectrum } from "./isSpectrum2D";
3+
import { mapZones } from "nmr-processing";
4+
import { getDetectionZones } from "./getDetectionZones";
5+
import { Zone } from "@zakodium/nmr-types";
6+
7+
export function detectZones(spectrum: Spectrum2D) {
8+
9+
if (!isFt2DSpectrum(spectrum)) return;
10+
11+
const { data } = spectrum;
12+
13+
const { rr: { minX, maxX, minY, maxY } } = data;
14+
const detectionOptions = {
15+
selectedZone: { fromX: minX, toX: maxX, fromY: minY, toY: maxY },
16+
thresholdFactor: 1,
17+
maxPercentCutOff: 0.03,
18+
};
19+
20+
const zones = getDetectionZones(spectrum, detectionOptions);
21+
spectrum.zones.values = mapZones(zones as Zone[], spectrum);
22+
23+
24+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import type { Spectrum2D } from '@zakodium/nmrium-core';
2+
import { xyzAutoZonesPicking } from 'nmr-processing';
3+
4+
export interface DetectionZonesOptions {
5+
selectedZone: {
6+
fromX: number;
7+
fromY: number;
8+
toX: number;
9+
toY: number;
10+
};
11+
thresholdFactor: number;
12+
maxPercentCutOff: number;
13+
tolerances?: number[];
14+
convolutionByFFT?: boolean;
15+
enhanceSymmetry?: boolean;
16+
}
17+
18+
/**
19+
*
20+
* @param {object} options
21+
* @param {object} options.selectedZone
22+
* @param {number} options.selectedZone.fromX
23+
* @param {number} options.selectedZone.fromY
24+
* @param {number} options.selectedZone.toX
25+
* @param {number} options.selectedZone.toY
26+
* @param {number} options.thresholdFactor
27+
* @param {boolean} options.convolutionByFFT
28+
*/
29+
export function getDetectionZones(
30+
spectrum: Spectrum2D,
31+
options: DetectionZonesOptions,
32+
) {
33+
let dataMatrix = {};
34+
const { selectedZone } = options;
35+
if (selectedZone) {
36+
options.enhanceSymmetry = false;
37+
dataMatrix = getSubMatrix(spectrum, selectedZone);
38+
} else {
39+
dataMatrix = spectrum.data;
40+
}
41+
42+
return autoZonesDetection(dataMatrix, {
43+
...options,
44+
info: spectrum.info,
45+
});
46+
}
47+
48+
function autoZonesDetection(data: any, options: any) {
49+
const {
50+
clean,
51+
tolerances,
52+
thresholdFactor,
53+
maxPercentCutOff,
54+
convolutionByFFT,
55+
info: { nucleus: nuclei, originFrequency },
56+
} = options;
57+
58+
const { enhanceSymmetry = nuclei[0] === nuclei[1] } = options;
59+
60+
const zones = xyzAutoZonesPicking(data, {
61+
nuclei,
62+
tolerances,
63+
observedFrequencies: originFrequency,
64+
thresholdFactor,
65+
realTopDetection: true,
66+
clean,
67+
maxPercentCutOff,
68+
enhanceSymmetry,
69+
convolutionByFFT,
70+
});
71+
72+
return zones;
73+
}
74+
75+
function getSubMatrix(datum: any, selectedZone: any) {
76+
const { fromX, toX, fromY, toY } = selectedZone;
77+
const data = datum.data.rr;
78+
const xStep = (data.maxX - data.minX) / (data.z[0].length - 1);
79+
const yStep = (data.maxY - data.minY) / (data.z.length - 1);
80+
let xIndexFrom = Math.max(Math.floor((fromX - data.minX) / xStep), 0);
81+
let yIndexFrom = Math.max(Math.floor((fromY - data.minY) / yStep), 0);
82+
let xIndexTo = Math.min(
83+
Math.floor((toX - data.minX) / xStep),
84+
data.z[0].length - 1,
85+
);
86+
let yIndexTo = Math.min(
87+
Math.floor((toY - data.minY) / yStep),
88+
data.z.length - 1,
89+
);
90+
91+
if (xIndexFrom > xIndexTo) [xIndexFrom, xIndexTo] = [xIndexTo, xIndexFrom];
92+
if (yIndexFrom > yIndexTo) [yIndexFrom, yIndexTo] = [yIndexTo, yIndexFrom];
93+
94+
const dataMatrix: any = {
95+
z: [],
96+
maxX: data.minX + xIndexTo * xStep,
97+
minX: data.minX + xIndexFrom * xStep,
98+
maxY: data.minY + yIndexTo * yStep,
99+
minY: data.minY + yIndexFrom * yStep,
100+
};
101+
let maxZ = Number.MIN_SAFE_INTEGER;
102+
let minZ = Number.MAX_SAFE_INTEGER;
103+
104+
const nbXPoints = xIndexTo - xIndexFrom + 1;
105+
106+
for (let j = yIndexFrom; j < yIndexTo; j++) {
107+
const row = new Float32Array(nbXPoints);
108+
let xIndex = xIndexFrom;
109+
for (let i = 0; i < nbXPoints; i++) {
110+
row[i] = data.z[j][xIndex++];
111+
}
112+
for (const rowValue of row) {
113+
if (maxZ < rowValue) maxZ = rowValue;
114+
if (minZ > rowValue) minZ = rowValue;
115+
}
116+
dataMatrix.z.push(Array.from(row));
117+
}
118+
dataMatrix.minZ = minZ;
119+
dataMatrix.maxZ = maxZ;
120+
return dataMatrix;
121+
}

0 commit comments

Comments
 (0)