From 3c1d1476e52f546c8973380b91ae7afb00a6f2ff Mon Sep 17 00:00:00 2001 From: jobo322 Date: Fri, 5 Jun 2026 22:42:34 -0500 Subject: [PATCH 1/8] =?UTF-8?q?feat:=20enhance=20peak=20optimization=20pro?= =?UTF-8?q?cess=20with=20additional=20iterations=20and=20parameters=20chor?= =?UTF-8?q?e:=20increase=20the=20limit=20for=20peak=20optimization=20to=20?= =?UTF-8?q?15=E2=80=A8fix:=20do=20not=20overwrite=20fwhm=20with=20default?= =?UTF-8?q?=20shape=20values?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit new version of ml-gsd contain the fix chore: update ml-gsd to 14.1.0 --- package.json | 2 +- src/component/1d/peaks/usePeakShapesPath.ts | 5 +- .../panels/PeaksPanel/PeaksPanel.tsx | 4 +- .../data1d/Spectrum1D/peaks/optimizePeaks.ts | 78 ++++++++++++++++++- 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 79d66d625..a5d1c0b7a 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "ml-array-mean": "^2.0.0", "ml-array-median": "^2.0.0", "ml-conrec": "^6.0.0", - "ml-gsd": "^14.0.1", + "ml-gsd": "^14.1.0", "ml-signal-processing": "^2.2.1", "ml-spectra-processing": "^14.29.0", "ml-tree-similarity": "^2.2.0", diff --git a/src/component/1d/peaks/usePeakShapesPath.ts b/src/component/1d/peaks/usePeakShapesPath.ts index 303f81184..548a7add2 100644 --- a/src/component/1d/peaks/usePeakShapesPath.ts +++ b/src/component/1d/peaks/usePeakShapesPath.ts @@ -29,12 +29,13 @@ export function usePeakShapesPath(spectrum: Spectrum1D) { const frequency = spectrum.info.originFrequency; let pathSeries: DataXY | null = null; + switch (target) { case 'peakShape': { const { peak } = options; pathSeries = peakToXY(peak, { frequency, - nbPoints: 1024, + nbPoints: Math.ceil(width * 3), from: peak.x - (peak.width / frequency) * 9, to: peak.x + (peak.width / frequency) * 9, }); @@ -46,7 +47,7 @@ export function usePeakShapesPath(spectrum: Spectrum1D) { frequency, nbPoints: Math.trunc(width), from: xDomain[0], - to: xDomain[1], + to:xDomain[1], }); break; } diff --git a/src/component/panels/PeaksPanel/PeaksPanel.tsx b/src/component/panels/PeaksPanel/PeaksPanel.tsx index 0b19199ee..fc7348cf1 100644 --- a/src/component/panels/PeaksPanel/PeaksPanel.tsx +++ b/src/component/panels/PeaksPanel/PeaksPanel.tsx @@ -111,11 +111,11 @@ function PeaksPanelInner(props: PeaksPanelInnerProps) { const filterPeaks = peaks.values.filter((peak) => isInRange(peak.x, { from, to }), ); - if (filterPeaks.length <= 4) { + if (filterPeaks.length <= 15) { dispatch({ type: 'OPTIMIZE_PEAKS', payload: { peaks: filterPeaks } }); } else { toaster.show({ - message: 'optimization can be done on no more than 4 peaks', + message: 'optimization can be done on no more than 15 peaks', intent: 'danger', }); } diff --git a/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts b/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts index 486d13586..43b500c05 100644 --- a/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts +++ b/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts @@ -31,10 +31,86 @@ export function optimizePeaks( x = x.subarray(fromIndex, ToIndex); re = re.subarray(fromIndex, ToIndex); - const newPeaks = xyPeaksOptimization({ x, y: re }, peaks, { + let newPeaks = xyPeaksOptimization({ x, y: re }, peaks, { frequency, groupingFactor: 3, + optimization: { kind: 'lm', options: { maxIterations: 20 } }, + parameters: { + fwhm: { + optimize: true, + min: (peak) => (peak.shape?.fwhm ?? 0) / 3, + max: (peak) => (peak.shape?.fwhm ?? 0) * 3, + }, + mu: { optimize: false }, + x: { optimize: false }, + y: { + optimize: true, + min: 0, + init: (peak) => peak.y * 0.8, + }, + } }); + + newPeaks = xyPeaksOptimization({ x, y: re }, newPeaks, { + frequency, + groupingFactor: 3, + optimization: { kind: 'lm', options: { maxIterations: 20, } }, + parameters: { + fwhm: { + optimize: true, + min: (peak) => (peak.shape?.fwhm ?? 0) / 3, + max: (peak) => (peak.shape?.fwhm ?? 0) * 3, + }, + mu: { optimize: true }, + x: { optimize: false }, + y: { + optimize: true, + min: 0, + }, + } + }); + + + newPeaks = xyPeaksOptimization({ x, y: re }, newPeaks, { + frequency, + groupingFactor: 4, + optimization: { kind: 'lm', options: { maxIterations: 20, } }, + parameters: { + fwhm: { + optimize: true, + min: (peak) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak) => (peak.shape?.fwhm ?? 0) * 2, + }, + mu: { + optimize: false, + }, + x: { optimize: true }, + y: { optimize: true, + min: 0, + }, + } + }); + + newPeaks = xyPeaksOptimization({ x, y: re }, newPeaks, { + frequency, + groupingFactor: 3, + optimization: { kind: 'lm', options: { maxIterations: 10 } }, + parameters: { + fwhm: { + optimize: true, + min: (peak) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak) => (peak.shape?.fwhm ?? 0) * 2, + }, + mu: { + optimize: true, + }, + x: { optimize: true }, + y: { optimize: true, + min: 0, + }, + } + }); + return mapPeaks(spectrum.peaks.values.concat(newPeaks), spectrum, { checkIsExisting: false, }); From d4abd5f9bb17537a4eef5bbcd21e87a8e503ba86 Mon Sep 17 00:00:00 2001 From: jobo322 Date: Mon, 8 Jun 2026 23:04:14 -0500 Subject: [PATCH 2/8] chore: add pseudoVoigtTCH as possible shape --- src/component/modal/EditPeakShapeModal.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/component/modal/EditPeakShapeModal.tsx b/src/component/modal/EditPeakShapeModal.tsx index 788cc0e10..41ebb3514 100644 --- a/src/component/modal/EditPeakShapeModal.tsx +++ b/src/component/modal/EditPeakShapeModal.tsx @@ -31,7 +31,8 @@ type Kind = | 'lorentzian' | 'pseudoVoigt' | 'generalizedLorentzian' - | 'lorentzianDispersive'; + | 'lorentzianDispersive' + | 'pseudoVoigtTCH'; function getKindDefaultValues(kind: Kind) { return { From 8e36172259cec4f378b4c49dd9d38c4365ac3cfa Mon Sep 17 00:00:00 2001 From: jobo322 Date: Tue, 9 Jun 2026 22:50:46 -0500 Subject: [PATCH 3/8] fix: avoid referencing in manual peak picking --- src/component/reducer/actions/PeaksActions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/reducer/actions/PeaksActions.ts b/src/component/reducer/actions/PeaksActions.ts index 5c1e13a05..50f378901 100644 --- a/src/component/reducer/actions/PeaksActions.ts +++ b/src/component/reducer/actions/PeaksActions.ts @@ -102,7 +102,7 @@ function handleAddPeak(draft: Draft, action: AddPeakAction) { x: candidatePeak.x, y: candidatePeak.y, width: 1, - shape: defaultPeakShape, + shape: structuredClone(defaultPeakShape), }; spectrum.peaks.values.push(...mapPeaks([peak], spectrum)); } @@ -131,7 +131,7 @@ function handleAddPeaks(draft: Draft, action: AddPeaksAction) { x: peak.x, y: peak.y, width: 1, - shape: defaultPeakShape, + shape: structuredClone(defaultPeakShape), }; spectrum.peaks.values.push(newPeak); } From b1f899bd84978e76d819fe4d0ef53fd3c59fdeb1 Mon Sep 17 00:00:00 2001 From: jobo322 Date: Wed, 10 Jun 2026 09:39:07 -0500 Subject: [PATCH 4/8] chore(defaultShape): use shallow copy due it is a flat object --- src/component/reducer/actions/PeaksActions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/component/reducer/actions/PeaksActions.ts b/src/component/reducer/actions/PeaksActions.ts index 50f378901..359e3fb28 100644 --- a/src/component/reducer/actions/PeaksActions.ts +++ b/src/component/reducer/actions/PeaksActions.ts @@ -102,7 +102,7 @@ function handleAddPeak(draft: Draft, action: AddPeakAction) { x: candidatePeak.x, y: candidatePeak.y, width: 1, - shape: structuredClone(defaultPeakShape), + shape: { ...defaultPeakShape }, }; spectrum.peaks.values.push(...mapPeaks([peak], spectrum)); } @@ -131,7 +131,7 @@ function handleAddPeaks(draft: Draft, action: AddPeaksAction) { x: peak.x, y: peak.y, width: 1, - shape: structuredClone(defaultPeakShape), + shape: { ...defaultPeakShape }, }; spectrum.peaks.values.push(newPeak); } From bdb942ea563407cc75ddcb4171d7b60e426e3b9d Mon Sep 17 00:00:00 2001 From: jobo322 Date: Thu, 11 Jun 2026 09:04:30 -0500 Subject: [PATCH 5/8] chore: update deps --- package-lock.json | 76 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2f07b10f1..0dd0f2784 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "ml-array-mean": "^2.0.0", "ml-array-median": "^2.0.0", "ml-conrec": "^6.0.0", - "ml-gsd": "^14.0.1", + "ml-gsd": "^14.1.0", "ml-signal-processing": "^2.2.1", "ml-spectra-processing": "^14.29.0", "ml-tree-similarity": "^2.2.0", @@ -9244,18 +9244,27 @@ } }, "node_modules/ml-gsd": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/ml-gsd/-/ml-gsd-14.0.1.tgz", - "integrity": "sha512-cvWt1TpZL+JJ0Gk+BfR5R8ovXdYAhS3tWrFNXduQLQr6krMlncPFFM1j2FwfqD/iAt80yhIlCS2gr54uev+X9w==", + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/ml-gsd/-/ml-gsd-14.1.0.tgz", + "integrity": "sha512-63kVpc2TceWTatbzZJHHTuR8wV1p9B9uWDHzOHqhfza2icfgz5rsONib5xWdUeN+9PCq4eosjky/aYRxjt8yow==", "license": "MIT", "dependencies": { "cheminfo-types": "^1.15.0", - "ml-peak-shape-generator": "^4.2.0", + "ml-peak-shape-generator": "^5.1.0", "ml-savitzky-golay-generalized": "^5.0.0", - "ml-spectra-fitting": "^6.0.1", + "ml-spectra-fitting": "^6.1.0", "ml-spectra-processing": "^14.28.1" } }, + "node_modules/ml-gsd/node_modules/ml-peak-shape-generator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ml-peak-shape-generator/-/ml-peak-shape-generator-5.1.0.tgz", + "integrity": "sha512-W2Vx/+R65zyr/B13p5TLyqwjTgIzwR0xtjRyQ2ZSxDHdVaXxb6m+ajyyaHJqGG5mYzeqi97nGvpklhz0jrsbrg==", + "license": "MIT", + "dependencies": { + "cheminfo-types": "^1.15.0" + } + }, "node_modules/ml-hash-table": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ml-hash-table/-/ml-hash-table-1.0.0.tgz", @@ -9441,18 +9450,27 @@ } }, "node_modules/ml-spectra-fitting": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ml-spectra-fitting/-/ml-spectra-fitting-6.0.1.tgz", - "integrity": "sha512-Izfi1ibuWsmnEivpoMK7GAEe16vHOL1V+4tIcL/YIsPuaUGvG1ydgmAOnkGxbYecM1QFgK1E3ZDFn0i2S9pzeA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ml-spectra-fitting/-/ml-spectra-fitting-6.1.0.tgz", + "integrity": "sha512-qCILP7xEU2sowZGoEalmxMdISM2LZSmwYXjxJYP4sqNRYRFA1Jxv84WnxwMTiNPNIa+wREhajmZamfuMm1blSQ==", "license": "MIT", "dependencies": { "cheminfo-types": "^1.7.2", "ml-direct": "^1.0.0", "ml-levenberg-marquardt": "^5.0.0", - "ml-peak-shape-generator": "^4.1.4", + "ml-peak-shape-generator": "^5.1.0", "ml-spectra-processing": "^14.2.0" } }, + "node_modules/ml-spectra-fitting/node_modules/ml-peak-shape-generator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ml-peak-shape-generator/-/ml-peak-shape-generator-5.1.0.tgz", + "integrity": "sha512-W2Vx/+R65zyr/B13p5TLyqwjTgIzwR0xtjRyQ2ZSxDHdVaXxb6m+ajyyaHJqGG5mYzeqi97nGvpklhz0jrsbrg==", + "license": "MIT", + "dependencies": { + "cheminfo-types": "^1.15.0" + } + }, "node_modules/ml-spectra-processing": { "version": "14.29.0", "resolved": "https://registry.npmjs.org/ml-spectra-processing/-/ml-spectra-processing-14.29.0.tgz", @@ -9575,9 +9593,9 @@ } }, "node_modules/nmr-processing": { - "version": "22.12.0", - "resolved": "https://registry.npmjs.org/nmr-processing/-/nmr-processing-22.12.0.tgz", - "integrity": "sha512-sq8gh3g8mDadVFo+GhjqIdigOKxxg37kNHwOvLitqjAO5/50uBTTwNWm12ZBC87mYSMkGPGlvTSYhRSB7rccjA==", + "version": "22.13.0", + "resolved": "https://registry.npmjs.org/nmr-processing/-/nmr-processing-22.13.0.tgz", + "integrity": "sha512-udS0fxLjJgojI382/6LZvBGLs+z+edoiULrqNjHYCQdFCgsEp6JYBNnHABY29myvXGN9ml17Clhc/qLaUJDe3w==", "license": "CC-BY-NC-SA-4.0", "dependencies": { "binary-search": "^1.3.6", @@ -9589,13 +9607,13 @@ "ml-airpls": "^2.2.0", "ml-convolution": "^2.0.0", "ml-direct": "^1.0.0", - "ml-gsd": "^14.0.0", + "ml-gsd": "^14.1.0", "ml-hclust": "^4.0.0", "ml-levenberg-marquardt": "^5.0.1", "ml-matrix": "^6.12.2", "ml-matrix-convolution": "^2.0.0", "ml-matrix-peaks-finder": "^2.0.0", - "ml-peak-shape-generator": "^4.2.0", + "ml-peak-shape-generator": "^5.1.0", "ml-regression-base": "^4.0.1", "ml-regression-exponential": "^3.0.2", "ml-regression-polynomial": "^4.0.0", @@ -9611,7 +9629,7 @@ "numeral": "^2.0.6", "openchemlib": "^9.22.0", "openchemlib-utils": "^8.15.0", - "spectrum-generator": "^8.2.0" + "spectrum-generator": "^8.2.1" } }, "node_modules/nmr-processing/node_modules/ml-matrix-convolution": { @@ -9633,6 +9651,15 @@ "ml-matrix-convolution": "^2.0.0" } }, + "node_modules/nmr-processing/node_modules/ml-peak-shape-generator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ml-peak-shape-generator/-/ml-peak-shape-generator-5.1.0.tgz", + "integrity": "sha512-W2Vx/+R65zyr/B13p5TLyqwjTgIzwR0xtjRyQ2ZSxDHdVaXxb6m+ajyyaHJqGG5mYzeqi97nGvpklhz0jrsbrg==", + "license": "MIT", + "dependencies": { + "cheminfo-types": "^1.15.0" + } + }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -11770,15 +11797,24 @@ "license": "CC0-1.0" }, "node_modules/spectrum-generator": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/spectrum-generator/-/spectrum-generator-8.2.0.tgz", - "integrity": "sha512-j//msAj0z7ubdhXPzFk7OHeHdZivLY+8DAccSPQESNy/tR6Nmf8wjVHhtlCzs7r46+uFmc6Zf72kpjwvu3UBmQ==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/spectrum-generator/-/spectrum-generator-8.2.1.tgz", + "integrity": "sha512-gbF55gpP6crd/MUjF7GiNbtpgKCKZig9yIxQkFQT34DYH0i3boKr001ANs5zs83QA3Buzu7LqcsEVB+Kt9vrIw==", "license": "MIT", "dependencies": { - "ml-peak-shape-generator": "^4.2.0", + "ml-peak-shape-generator": "^5.1.0", "ml-spectra-processing": "^14.28.1" } }, + "node_modules/spectrum-generator/node_modules/ml-peak-shape-generator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ml-peak-shape-generator/-/ml-peak-shape-generator-5.1.0.tgz", + "integrity": "sha512-W2Vx/+R65zyr/B13p5TLyqwjTgIzwR0xtjRyQ2ZSxDHdVaXxb6m+ajyyaHJqGG5mYzeqi97nGvpklhz0jrsbrg==", + "license": "MIT", + "dependencies": { + "cheminfo-types": "^1.15.0" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", From 4c365f6ab747b2be3f4ccfaa5a6ca68ab9af8e67 Mon Sep 17 00:00:00 2001 From: jobo322 Date: Thu, 11 Jun 2026 10:02:29 -0500 Subject: [PATCH 6/8] feat: enhance peak optimization with staged processing and improved parameters --- .../data1d/Spectrum1D/peaks/optimizePeaks.ts | 155 +++++++++++------- 1 file changed, 95 insertions(+), 60 deletions(-) diff --git a/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts b/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts index 43b500c05..f396d6cd7 100644 --- a/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts +++ b/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts @@ -1,7 +1,7 @@ import type { Peak1D } from '@zakodium/nmr-types'; import type { Spectrum1D } from '@zakodium/nmrium-core'; import { xFindClosestIndex } from 'ml-spectra-processing'; -import { mapPeaks, xyPeaksOptimization } from 'nmr-processing'; +import { mapPeaks, xyPeaksOptimizationByStages } from 'nmr-processing'; interface OptimizePeaksOptions { from: number; @@ -31,85 +31,120 @@ export function optimizePeaks( x = x.subarray(fromIndex, ToIndex); re = re.subarray(fromIndex, ToIndex); - let newPeaks = xyPeaksOptimization({ x, y: re }, peaks, { - frequency, - groupingFactor: 3, - optimization: { kind: 'lm', options: { maxIterations: 20 } }, + const newPeaks = xyPeaksOptimizationByStages({ x, y: re }, peaks, + { + frequency, groupingFactor: 10,stages: + [ + { + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 1e-3 }, + }, parameters: { - fwhm: { - optimize: true, - min: (peak) => (peak.shape?.fwhm ?? 0) / 3, - max: (peak) => (peak.shape?.fwhm ?? 0) * 3, - }, + fwhm: { + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, + }, mu: { optimize: false }, x: { optimize: false }, y: { optimize: true, - min: 0, - init: (peak) => peak.y * 0.8, - }, - } - }); + init: (peak: any) => peak.y * 0.8, + }, + }, + }, + { - newPeaks = xyPeaksOptimization({ x, y: re }, newPeaks, { - frequency, - groupingFactor: 3, - optimization: { kind: 'lm', options: { maxIterations: 20, } }, + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 5e-4 }, + }, parameters: { - fwhm: { - optimize: true, - min: (peak) => (peak.shape?.fwhm ?? 0) / 3, - max: (peak) => (peak.shape?.fwhm ?? 0) * 3, - }, - mu: { optimize: true }, + fwhm: { + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, + }, + mu: { optimize: false }, x: { optimize: false }, y: { - optimize: true, - min: 0, - }, - } - }); - + optimize: true, + }, + }, + }, + { - newPeaks = xyPeaksOptimization({ x, y: re }, newPeaks, { - frequency, - groupingFactor: 4, - optimization: { kind: 'lm', options: { maxIterations: 20, } }, + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 1e-5 }, + }, parameters: { fwhm: { - optimize: true, - min: (peak) => (peak.shape?.fwhm ?? 0) / 2, - max: (peak) => (peak.shape?.fwhm ?? 0) * 2, - }, - mu: { - optimize: false, + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, }, - x: { optimize: true }, - y: { optimize: true, - min: 0, + mu: { optimize: true }, + x: { optimize: false }, + y: { + optimize: true, }, - } - }); + }, + }, + { - newPeaks = xyPeaksOptimization({ x, y: re }, newPeaks, { - frequency, - groupingFactor: 3, - optimization: { kind: 'lm', options: { maxIterations: 10 } }, + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 5e-4 }, + }, parameters: { fwhm: { - optimize: true, - min: (peak) => (peak.shape?.fwhm ?? 0) / 2, - max: (peak) => (peak.shape?.fwhm ?? 0) * 2, + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 3, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 3, }, - mu: { - optimize: true, + mu: { optimize: true }, + x: { optimize: true }, + y: { optimize: true }, + }, + }, + { + + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 1e-4 }, + }, + parameters: { + fwhm: { + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, }, - x: { optimize: true }, - y: { optimize: true, - min: 0, + mu: { optimize: false }, + x: { optimize: true }, + y: { optimize: true }, + }, + }, + { + + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 1e-8 }, + }, + parameters: { + fwhm: { + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, }, - } - }); + mu: { optimize: true }, + x: { optimize: true }, + y: { optimize: true }, + }, + }, + ]}); + return mapPeaks(spectrum.peaks.values.concat(newPeaks), spectrum, { checkIsExisting: false, From ac1a4c62212b36e0d55422c8304dea707a174869 Mon Sep 17 00:00:00 2001 From: jobo322 Date: Thu, 11 Jun 2026 10:05:40 -0500 Subject: [PATCH 7/8] chore: update @zakodium/nmr-types and ml-peak-shape-generator to latest versions --- package-lock.json | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0dd0f2784..90192b507 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3900,16 +3900,25 @@ "license": "MIT" }, "node_modules/@zakodium/nmr-types": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/@zakodium/nmr-types/-/nmr-types-0.5.12.tgz", - "integrity": "sha512-aAYP4DTncj6PamSnSsFa8HOyE5lHT6pGtk4fAyTmMRJIvlZrK8qoQdEz4lulfhPwkPiPB6ameKm/QK8F8f4kxg==", + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/@zakodium/nmr-types/-/nmr-types-0.5.14.tgz", + "integrity": "sha512-TEgAajDAvfGSafwQBCEesrfDJVpTq7bfRnkorLKXiflNLJzjpsIk68sgm3NfVuo7Dv7d0kTmgNAbKk0gpX66bQ==", "license": "CC-BY-NC-SA-4.0", "dependencies": { - "ml-peak-shape-generator": "^4.2.0", + "ml-peak-shape-generator": "^5.1.0", "ml-signal-processing": "^2.2.1", "ml-spectra-processing": "^14.28.1" } }, + "node_modules/@zakodium/nmr-types/node_modules/ml-peak-shape-generator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ml-peak-shape-generator/-/ml-peak-shape-generator-5.1.0.tgz", + "integrity": "sha512-W2Vx/+R65zyr/B13p5TLyqwjTgIzwR0xtjRyQ2ZSxDHdVaXxb6m+ajyyaHJqGG5mYzeqi97nGvpklhz0jrsbrg==", + "license": "MIT", + "dependencies": { + "cheminfo-types": "^1.15.0" + } + }, "node_modules/@zakodium/nmrium-core": { "version": "0.7.24", "resolved": "https://registry.npmjs.org/@zakodium/nmrium-core/-/nmrium-core-0.7.24.tgz", From 5b64c68dd1bd7b9ba40eba60aa165e6a17fc6302 Mon Sep 17 00:00:00 2001 From: jobo322 Date: Fri, 12 Jun 2026 05:57:22 -0500 Subject: [PATCH 8/8] chore: fix prettier --- src/component/1d/peaks/usePeakShapesPath.ts | 4 +- .../data1d/Spectrum1D/peaks/optimizePeaks.ts | 209 +++++++++--------- 2 files changed, 104 insertions(+), 109 deletions(-) diff --git a/src/component/1d/peaks/usePeakShapesPath.ts b/src/component/1d/peaks/usePeakShapesPath.ts index 548a7add2..6c935f897 100644 --- a/src/component/1d/peaks/usePeakShapesPath.ts +++ b/src/component/1d/peaks/usePeakShapesPath.ts @@ -29,7 +29,7 @@ export function usePeakShapesPath(spectrum: Spectrum1D) { const frequency = spectrum.info.originFrequency; let pathSeries: DataXY | null = null; - + switch (target) { case 'peakShape': { const { peak } = options; @@ -47,7 +47,7 @@ export function usePeakShapesPath(spectrum: Spectrum1D) { frequency, nbPoints: Math.trunc(width), from: xDomain[0], - to:xDomain[1], + to: xDomain[1], }); break; } diff --git a/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts b/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts index f396d6cd7..057b512c1 100644 --- a/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts +++ b/src/data/data1d/Spectrum1D/peaks/optimizePeaks.ts @@ -31,120 +31,115 @@ export function optimizePeaks( x = x.subarray(fromIndex, ToIndex); re = re.subarray(fromIndex, ToIndex); - const newPeaks = xyPeaksOptimizationByStages({ x, y: re }, peaks, - { - frequency, groupingFactor: 10,stages: - [ + const newPeaks = xyPeaksOptimizationByStages({ x, y: re }, peaks, { + frequency, + groupingFactor: 10, + stages: [ { - optimization: { - kind: 'lm', - options: { maxIterations: 20, errorTolerance: 1e-3 }, - }, - parameters: { - fwhm: { - optimize: true, - min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, - max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 1e-3 }, + }, + parameters: { + fwhm: { + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, + }, + mu: { optimize: false }, + x: { optimize: false }, + y: { + optimize: true, + init: (peak: any) => peak.y * 0.8, + }, + }, }, - mu: { optimize: false }, - x: { optimize: false }, - y: { - optimize: true, - init: (peak: any) => peak.y * 0.8, - }, - }, - }, - { - - optimization: { - kind: 'lm', - options: { maxIterations: 20, errorTolerance: 5e-4 }, - }, - parameters: { - fwhm: { - optimize: true, - min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, - max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, - }, - mu: { optimize: false }, - x: { optimize: false }, - y: { - optimize: true, - }, - }, - }, - { - - optimization: { - kind: 'lm', - options: { maxIterations: 20, errorTolerance: 1e-5 }, - }, - parameters: { - fwhm: { - optimize: true, - min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, - max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, + { + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 5e-4 }, + }, + parameters: { + fwhm: { + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, + }, + mu: { optimize: false }, + x: { optimize: false }, + y: { + optimize: true, + }, + }, }, - mu: { optimize: true }, - x: { optimize: false }, - y: { - optimize: true, + { + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 1e-5 }, + }, + parameters: { + fwhm: { + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, + }, + mu: { optimize: true }, + x: { optimize: false }, + y: { + optimize: true, + }, + }, }, - }, - }, - { - - optimization: { - kind: 'lm', - options: { maxIterations: 20, errorTolerance: 5e-4 }, - }, - parameters: { - fwhm: { - optimize: true, - min: (peak: any) => (peak.shape?.fwhm ?? 0) / 3, - max: (peak: any) => (peak.shape?.fwhm ?? 0) * 3, + { + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 5e-4 }, + }, + parameters: { + fwhm: { + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 3, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 3, + }, + mu: { optimize: true }, + x: { optimize: true }, + y: { optimize: true }, + }, }, - mu: { optimize: true }, - x: { optimize: true }, - y: { optimize: true }, - }, - }, - { - - optimization: { - kind: 'lm', - options: { maxIterations: 20, errorTolerance: 1e-4 }, - }, - parameters: { - fwhm: { - optimize: true, - min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, - max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, + { + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 1e-4 }, + }, + parameters: { + fwhm: { + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, + }, + mu: { optimize: false }, + x: { optimize: true }, + y: { optimize: true }, + }, }, - mu: { optimize: false }, - x: { optimize: true }, - y: { optimize: true }, - }, - }, - { - - optimization: { - kind: 'lm', - options: { maxIterations: 20, errorTolerance: 1e-8 }, - }, - parameters: { - fwhm: { - optimize: true, - min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, - max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, + { + optimization: { + kind: 'lm', + options: { maxIterations: 20, errorTolerance: 1e-8 }, + }, + parameters: { + fwhm: { + optimize: true, + min: (peak: any) => (peak.shape?.fwhm ?? 0) / 2, + max: (peak: any) => (peak.shape?.fwhm ?? 0) * 2, + }, + mu: { optimize: true }, + x: { optimize: true }, + y: { optimize: true }, + }, }, - mu: { optimize: true }, - x: { optimize: true }, - y: { optimize: true }, - }, - }, - ]}); - + ], + }); return mapPeaks(spectrum.peaks.values.concat(newPeaks), spectrum, { checkIsExisting: false,