Comparing version 9.0.0 to 9.0.1
# Changelog | ||
### [9.0.1](https://www.github.com/mljs/global-spectral-deconvolution/compare/v9.0.0...v9.0.1) (2021-11-23) | ||
### Bug Fixes | ||
* update PSG n spectra-fitting ([#70](https://www.github.com/mljs/global-spectral-deconvolution/issues/70)) ([ac23217](https://www.github.com/mljs/global-spectral-deconvolution/commit/ac23217cc1c73f513b772661ad2712b727fa02e7)) | ||
## [9.0.0](https://www.github.com/mljs/global-spectral-deconvolution/compare/v8.0.0...v9.0.0) (2021-11-18) | ||
@@ -4,0 +11,0 @@ |
@@ -27,3 +27,2 @@ import type { DataXY } from 'cheminfo-types'; | ||
export interface Peak1D { | ||
index?: number; | ||
x: number; | ||
@@ -35,7 +34,3 @@ y: number; | ||
} | ||
export interface LastType { | ||
x: number; | ||
index: number; | ||
} | ||
export interface GSDOptions { | ||
export interface IGSDOptions { | ||
noiseLevel?: number; | ||
@@ -55,3 +50,3 @@ sgOptions?: { | ||
} | ||
export declare function gsd(data: DataXY, options?: GSDOptions): Peak1D[]; | ||
export declare function gsd(data: DataXY, options?: IGSDOptions): Peak1D[]; | ||
//# sourceMappingURL=gsd.d.ts.map |
@@ -121,6 +121,11 @@ import { getShape1D } from 'ml-peak-shape-generator'; | ||
} | ||
let widthProcessor = getShape1D(shape).widthToFWHM; | ||
let signals = []; | ||
let widthToFWHM = getShape1D(shape).widthToFWHM; | ||
let lastK = -1; | ||
let possible, frequency, distanceJ, minDistance, gettingCloser; | ||
let possible; | ||
let frequency; | ||
let distanceJ; | ||
let minDistance; | ||
let gettingCloser; | ||
const peaks = []; | ||
const indexes = []; | ||
for (const minddYIndex of minddY) { | ||
@@ -151,4 +156,4 @@ frequency = xData[minddYIndex]; | ||
let width = Math.abs(intervalR[possible].x - intervalL[possible].x); | ||
signals.push({ | ||
index: minddYIndex, | ||
indexes.push(minddYIndex); | ||
peaks.push({ | ||
x: frequency, | ||
@@ -159,3 +164,3 @@ y: maxCriteria | ||
width: width, | ||
fwhm: widthProcessor(width), | ||
fwhm: widthToFWHM(width), | ||
shape, | ||
@@ -167,8 +172,8 @@ }); | ||
if (realTopDetection) { | ||
determineRealTop(signals, xData, yData); | ||
determineRealTop({ peaks, x: xData, y: yData, indexes }); | ||
} | ||
signals.sort((a, b) => { | ||
peaks.sort((a, b) => { | ||
return a.x - b.x; | ||
}); | ||
return signals; | ||
return peaks; | ||
} | ||
@@ -214,6 +219,11 @@ const isEqualSpaced = (x) => { | ||
}; | ||
const determineRealTop = (peakList, x, y) => { | ||
let alpha, beta, gamma, p, currentPoint; | ||
for (const peak of peakList) { | ||
currentPoint = peak.index; // peakList[j][2]; | ||
const determineRealTop = (options) => { | ||
const { peaks, x, y, indexes } = options; | ||
let alpha; | ||
let beta; | ||
let gamma; | ||
let p; | ||
for (let i = 0; i < peaks.length; i++) { | ||
const peak = peaks[i]; | ||
let currentPoint = indexes[i]; | ||
// The detected peak could be moved 1 or 2 units to left or right. | ||
@@ -253,4 +263,2 @@ if (y[currentPoint - 1] >= y[currentPoint - 2] && | ||
p = (0.5 * (alpha - gamma)) / (alpha - 2 * beta + gamma); | ||
// console.log(alpha, beta, gamma, `p: ${p}`); | ||
// console.log(x[currentPoint]+" "+tmp+" "+currentPoint); | ||
peak.x = x[currentPoint] + (x[currentPoint] - x[currentPoint - 1]) * p; | ||
@@ -257,0 +265,0 @@ peak.y = |
@@ -7,3 +7,3 @@ import type { Peak1D } from '../gsd'; | ||
*/ | ||
interface BroadenPeaksOptions { | ||
export interface IBroadenPeaksOptions { | ||
/** | ||
@@ -19,4 +19,3 @@ * @default 2 | ||
} | ||
export declare function broadenPeaks(peakList: Peak1D[], options?: BroadenPeaksOptions): Peak1D[]; | ||
export {}; | ||
export declare function broadenPeaks(peakList: Peak1D[], options?: IBroadenPeaksOptions): Peak1D[]; | ||
//# sourceMappingURL=broadenPeaks.d.ts.map |
import type { DataXY } from 'cheminfo-types'; | ||
import type { Shape1D } from 'ml-peak-shape-generator'; | ||
import type { IOptimizationOptions } from 'ml-spectra-fitting'; | ||
import type { Peak1D } from '../gsd'; | ||
/** | ||
* This function try to join the peaks that seems to belong to a broad signal in a single broad peak. | ||
* @param {Array} peaks - A list of initial parameters to be optimized. e.g. coming from a peak picking [{x, y, width}]. | ||
* @param {object} [options = {}] - options | ||
* @param {number} [options.width=0.25] - width limit to join peaks. | ||
* @param {object} [options.shape={}] - it's specify the kind of shape used to fitting. | ||
* @param {string} [options.shape.kind = 'gaussian'] - kind of shape; lorentzian, gaussian and pseudovoigt are supported. | ||
* @param {object} [options.optimization = {}] - it's specify the kind and options of the algorithm use to optimize parameters. | ||
* @param {string} [options.optimization.kind = 'lm'] - kind of algorithm. By default it's levenberg-marquardt. | ||
* @param {number} [options.optimization.options.timeout = 10] - maximum time running before break in seconds. | ||
* @param {object} [options.optimization.options = {}] - options for the specific kind of algorithm. | ||
* @param peaks - A list of initial parameters to be optimized. e.g. coming from a peak picking [{x, y, width}]. | ||
*/ | ||
@@ -21,15 +14,26 @@ interface GetSoftMaskOptions { | ||
}; | ||
/** | ||
* broadRatio | ||
* @default 0.0025 | ||
*/ | ||
broadRatio: number; | ||
} | ||
interface OptionsType extends Partial<GetSoftMaskOptions> { | ||
width?: number; | ||
export interface IJoinBroadPeaksOptions extends Partial<GetSoftMaskOptions> { | ||
/** | ||
* width limit to join peaks. | ||
* @default 0.25 | ||
*/ | ||
broadWidth?: number; | ||
/** | ||
* it's specify the kind of shape used to fitting. | ||
*/ | ||
shape?: Shape1D; | ||
optimization?: { | ||
kind: string; | ||
timeout: number; | ||
}; | ||
mask?: boolean[]; | ||
/** | ||
* it's specify the kind and options of the algorithm use to optimize parameters. | ||
*/ | ||
optimization?: IOptimizationOptions; | ||
broadMask?: boolean[]; | ||
} | ||
export declare function joinBroadPeaks(data: DataXY, peakList: Peak1D[], options?: OptionsType): Peak1D[]; | ||
export declare function joinBroadPeaks(data: DataXY, peakList: Peak1D[], options?: IJoinBroadPeaksOptions): Peak1D[]; | ||
export {}; | ||
//# sourceMappingURL=joinBroadPeaks.d.ts.map |
@@ -5,7 +5,6 @@ import SG from 'ml-savitzky-golay-generalized'; | ||
export function joinBroadPeaks(data, peakList, options = {}) { | ||
let { mask, shape = { kind: 'gaussian' }, optimization = { kind: 'lm', timeout: 10 }, sgOptions = { | ||
let { broadMask, shape = { kind: 'gaussian' }, optimization = { kind: 'lm', options: { timeout: 10 } }, sgOptions = { | ||
windowSize: 9, | ||
polynomial: 3, | ||
}, broadRatio = 0.0025, } = options; | ||
let { width = 0.25 } = options; | ||
}, broadRatio = 0.0025, broadWidth = 0.25, } = options; | ||
let max = 0; | ||
@@ -16,10 +15,10 @@ let maxI = 0; | ||
const peaks = JSON.parse(JSON.stringify(peakList)); | ||
const broadMask = !mask | ||
const mask = !broadMask | ||
? getSoftMask(data, peaks, { sgOptions, broadRatio }) | ||
: mask; | ||
if (broadMask.length !== peaks.length) { | ||
: broadMask; | ||
if (mask.length !== peaks.length) { | ||
throw new Error('mask length does not match the length of peaksList'); | ||
} | ||
for (let i = peaks.length - 1; i >= 0; i--) { | ||
if (broadMask[i]) { | ||
if (mask[i]) { | ||
broadLines.push(peaks.splice(i, 1)[0]); | ||
@@ -36,3 +35,3 @@ } | ||
for (let i = 1; i < broadLines.length; i++) { | ||
if (Math.abs(broadLines[i - 1].x - broadLines[i].x) < width) { | ||
if (Math.abs(broadLines[i - 1].x - broadLines[i].x) < broadWidth) { | ||
candidates.x.push(broadLines[i].x); | ||
@@ -39,0 +38,0 @@ candidates.y.push(broadLines[i].y); |
import type { DataXY } from 'cheminfo-types'; | ||
import type { Shape1D } from 'ml-peak-shape-generator'; | ||
import type { IOptimizationOptions } from 'ml-spectra-fitting'; | ||
import type { Peak1D } from '../gsd'; | ||
@@ -10,3 +11,3 @@ /** | ||
*/ | ||
interface OptimizePeaksOptions { | ||
export interface IOptimizePeaksOptions { | ||
/** | ||
@@ -29,22 +30,5 @@ * times of width to group peaks. | ||
*/ | ||
optimization?: { | ||
/** | ||
* kind of algorithm. By default it's levenberg-marquardt. | ||
* @default 'lm' | ||
*/ | ||
kind: string; | ||
/** | ||
* options for the specific kind of algorithm. | ||
*/ | ||
options: { | ||
/** | ||
* maximum time running before break in seconds. | ||
* @default 10 | ||
*/ | ||
timeout: number; | ||
}; | ||
}; | ||
optimization?: IOptimizationOptions; | ||
} | ||
export declare function optimizePeaks(data: DataXY, peakList: Peak1D[], options?: OptimizePeaksOptions): Peak1D[]; | ||
export {}; | ||
export declare function optimizePeaks(data: DataXY, peakList: Peak1D[], options?: IOptimizePeaksOptions): Peak1D[]; | ||
//# sourceMappingURL=optimizePeaks.d.ts.map |
@@ -27,3 +27,2 @@ import type { DataXY } from 'cheminfo-types'; | ||
export interface Peak1D { | ||
index?: number; | ||
x: number; | ||
@@ -35,7 +34,3 @@ y: number; | ||
} | ||
export interface LastType { | ||
x: number; | ||
index: number; | ||
} | ||
export interface GSDOptions { | ||
export interface IGSDOptions { | ||
noiseLevel?: number; | ||
@@ -55,3 +50,3 @@ sgOptions?: { | ||
} | ||
export declare function gsd(data: DataXY, options?: GSDOptions): Peak1D[]; | ||
export declare function gsd(data: DataXY, options?: IGSDOptions): Peak1D[]; | ||
//# sourceMappingURL=gsd.d.ts.map |
@@ -127,6 +127,11 @@ "use strict"; | ||
} | ||
let widthProcessor = (0, ml_peak_shape_generator_1.getShape1D)(shape).widthToFWHM; | ||
let signals = []; | ||
let widthToFWHM = (0, ml_peak_shape_generator_1.getShape1D)(shape).widthToFWHM; | ||
let lastK = -1; | ||
let possible, frequency, distanceJ, minDistance, gettingCloser; | ||
let possible; | ||
let frequency; | ||
let distanceJ; | ||
let minDistance; | ||
let gettingCloser; | ||
const peaks = []; | ||
const indexes = []; | ||
for (const minddYIndex of minddY) { | ||
@@ -157,4 +162,4 @@ frequency = xData[minddYIndex]; | ||
let width = Math.abs(intervalR[possible].x - intervalL[possible].x); | ||
signals.push({ | ||
index: minddYIndex, | ||
indexes.push(minddYIndex); | ||
peaks.push({ | ||
x: frequency, | ||
@@ -165,3 +170,3 @@ y: maxCriteria | ||
width: width, | ||
fwhm: widthProcessor(width), | ||
fwhm: widthToFWHM(width), | ||
shape, | ||
@@ -173,8 +178,8 @@ }); | ||
if (realTopDetection) { | ||
determineRealTop(signals, xData, yData); | ||
determineRealTop({ peaks, x: xData, y: yData, indexes }); | ||
} | ||
signals.sort((a, b) => { | ||
peaks.sort((a, b) => { | ||
return a.x - b.x; | ||
}); | ||
return signals; | ||
return peaks; | ||
} | ||
@@ -221,6 +226,11 @@ exports.gsd = gsd; | ||
}; | ||
const determineRealTop = (peakList, x, y) => { | ||
let alpha, beta, gamma, p, currentPoint; | ||
for (const peak of peakList) { | ||
currentPoint = peak.index; // peakList[j][2]; | ||
const determineRealTop = (options) => { | ||
const { peaks, x, y, indexes } = options; | ||
let alpha; | ||
let beta; | ||
let gamma; | ||
let p; | ||
for (let i = 0; i < peaks.length; i++) { | ||
const peak = peaks[i]; | ||
let currentPoint = indexes[i]; | ||
// The detected peak could be moved 1 or 2 units to left or right. | ||
@@ -260,4 +270,2 @@ if (y[currentPoint - 1] >= y[currentPoint - 2] && | ||
p = (0.5 * (alpha - gamma)) / (alpha - 2 * beta + gamma); | ||
// console.log(alpha, beta, gamma, `p: ${p}`); | ||
// console.log(x[currentPoint]+" "+tmp+" "+currentPoint); | ||
peak.x = x[currentPoint] + (x[currentPoint] - x[currentPoint - 1]) * p; | ||
@@ -264,0 +272,0 @@ peak.y = |
@@ -7,3 +7,3 @@ import type { Peak1D } from '../gsd'; | ||
*/ | ||
interface BroadenPeaksOptions { | ||
export interface IBroadenPeaksOptions { | ||
/** | ||
@@ -19,4 +19,3 @@ * @default 2 | ||
} | ||
export declare function broadenPeaks(peakList: Peak1D[], options?: BroadenPeaksOptions): Peak1D[]; | ||
export {}; | ||
export declare function broadenPeaks(peakList: Peak1D[], options?: IBroadenPeaksOptions): Peak1D[]; | ||
//# sourceMappingURL=broadenPeaks.d.ts.map |
import type { DataXY } from 'cheminfo-types'; | ||
import type { Shape1D } from 'ml-peak-shape-generator'; | ||
import type { IOptimizationOptions } from 'ml-spectra-fitting'; | ||
import type { Peak1D } from '../gsd'; | ||
/** | ||
* This function try to join the peaks that seems to belong to a broad signal in a single broad peak. | ||
* @param {Array} peaks - A list of initial parameters to be optimized. e.g. coming from a peak picking [{x, y, width}]. | ||
* @param {object} [options = {}] - options | ||
* @param {number} [options.width=0.25] - width limit to join peaks. | ||
* @param {object} [options.shape={}] - it's specify the kind of shape used to fitting. | ||
* @param {string} [options.shape.kind = 'gaussian'] - kind of shape; lorentzian, gaussian and pseudovoigt are supported. | ||
* @param {object} [options.optimization = {}] - it's specify the kind and options of the algorithm use to optimize parameters. | ||
* @param {string} [options.optimization.kind = 'lm'] - kind of algorithm. By default it's levenberg-marquardt. | ||
* @param {number} [options.optimization.options.timeout = 10] - maximum time running before break in seconds. | ||
* @param {object} [options.optimization.options = {}] - options for the specific kind of algorithm. | ||
* @param peaks - A list of initial parameters to be optimized. e.g. coming from a peak picking [{x, y, width}]. | ||
*/ | ||
@@ -21,15 +14,26 @@ interface GetSoftMaskOptions { | ||
}; | ||
/** | ||
* broadRatio | ||
* @default 0.0025 | ||
*/ | ||
broadRatio: number; | ||
} | ||
interface OptionsType extends Partial<GetSoftMaskOptions> { | ||
width?: number; | ||
export interface IJoinBroadPeaksOptions extends Partial<GetSoftMaskOptions> { | ||
/** | ||
* width limit to join peaks. | ||
* @default 0.25 | ||
*/ | ||
broadWidth?: number; | ||
/** | ||
* it's specify the kind of shape used to fitting. | ||
*/ | ||
shape?: Shape1D; | ||
optimization?: { | ||
kind: string; | ||
timeout: number; | ||
}; | ||
mask?: boolean[]; | ||
/** | ||
* it's specify the kind and options of the algorithm use to optimize parameters. | ||
*/ | ||
optimization?: IOptimizationOptions; | ||
broadMask?: boolean[]; | ||
} | ||
export declare function joinBroadPeaks(data: DataXY, peakList: Peak1D[], options?: OptionsType): Peak1D[]; | ||
export declare function joinBroadPeaks(data: DataXY, peakList: Peak1D[], options?: IJoinBroadPeaksOptions): Peak1D[]; | ||
export {}; | ||
//# sourceMappingURL=joinBroadPeaks.d.ts.map |
@@ -11,7 +11,6 @@ "use strict"; | ||
function joinBroadPeaks(data, peakList, options = {}) { | ||
let { mask, shape = { kind: 'gaussian' }, optimization = { kind: 'lm', timeout: 10 }, sgOptions = { | ||
let { broadMask, shape = { kind: 'gaussian' }, optimization = { kind: 'lm', options: { timeout: 10 } }, sgOptions = { | ||
windowSize: 9, | ||
polynomial: 3, | ||
}, broadRatio = 0.0025, } = options; | ||
let { width = 0.25 } = options; | ||
}, broadRatio = 0.0025, broadWidth = 0.25, } = options; | ||
let max = 0; | ||
@@ -22,10 +21,10 @@ let maxI = 0; | ||
const peaks = JSON.parse(JSON.stringify(peakList)); | ||
const broadMask = !mask | ||
const mask = !broadMask | ||
? getSoftMask(data, peaks, { sgOptions, broadRatio }) | ||
: mask; | ||
if (broadMask.length !== peaks.length) { | ||
: broadMask; | ||
if (mask.length !== peaks.length) { | ||
throw new Error('mask length does not match the length of peaksList'); | ||
} | ||
for (let i = peaks.length - 1; i >= 0; i--) { | ||
if (broadMask[i]) { | ||
if (mask[i]) { | ||
broadLines.push(peaks.splice(i, 1)[0]); | ||
@@ -42,3 +41,3 @@ } | ||
for (let i = 1; i < broadLines.length; i++) { | ||
if (Math.abs(broadLines[i - 1].x - broadLines[i].x) < width) { | ||
if (Math.abs(broadLines[i - 1].x - broadLines[i].x) < broadWidth) { | ||
candidates.x.push(broadLines[i].x); | ||
@@ -45,0 +44,0 @@ candidates.y.push(broadLines[i].y); |
import type { DataXY } from 'cheminfo-types'; | ||
import type { Shape1D } from 'ml-peak-shape-generator'; | ||
import type { IOptimizationOptions } from 'ml-spectra-fitting'; | ||
import type { Peak1D } from '../gsd'; | ||
@@ -10,3 +11,3 @@ /** | ||
*/ | ||
interface OptimizePeaksOptions { | ||
export interface IOptimizePeaksOptions { | ||
/** | ||
@@ -29,22 +30,5 @@ * times of width to group peaks. | ||
*/ | ||
optimization?: { | ||
/** | ||
* kind of algorithm. By default it's levenberg-marquardt. | ||
* @default 'lm' | ||
*/ | ||
kind: string; | ||
/** | ||
* options for the specific kind of algorithm. | ||
*/ | ||
options: { | ||
/** | ||
* maximum time running before break in seconds. | ||
* @default 10 | ||
*/ | ||
timeout: number; | ||
}; | ||
}; | ||
optimization?: IOptimizationOptions; | ||
} | ||
export declare function optimizePeaks(data: DataXY, peakList: Peak1D[], options?: OptimizePeaksOptions): Peak1D[]; | ||
export {}; | ||
export declare function optimizePeaks(data: DataXY, peakList: Peak1D[], options?: IOptimizePeaksOptions): Peak1D[]; | ||
//# sourceMappingURL=optimizePeaks.d.ts.map |
{ | ||
"name": "ml-gsd", | ||
"version": "9.0.0", | ||
"version": "9.0.1", | ||
"description": "Global Spectra Deconvolution", | ||
@@ -75,3 +75,3 @@ "main": "./lib/index.js", | ||
"rimraf": "^3.0.2", | ||
"spectrum-generator": "^6.0.0", | ||
"spectrum-generator": "^6.0.1", | ||
"ts-jest": "^27.0.7", | ||
@@ -83,7 +83,7 @@ "typescript": "^4.4.4", | ||
"cheminfo-types": "^0.8.0", | ||
"ml-peak-shape-generator": "^3.0.2", | ||
"ml-peak-shape-generator": "^3.0.3", | ||
"ml-savitzky-golay-generalized": "2.0.3", | ||
"ml-spectra-fitting": "^3.0.0", | ||
"ml-spectra-fitting": "^3.0.1", | ||
"ml-spectra-processing": "^6.8.0" | ||
} | ||
} |
@@ -28,3 +28,3 @@ import { readFileSync } from 'fs'; | ||
{ | ||
width: 0.25, | ||
broadWidth: 0.25, | ||
broadRatio: 0.0025, | ||
@@ -31,0 +31,0 @@ shape: { kind: 'lorentzian' }, |
@@ -45,6 +45,7 @@ import CC from 'chemcalc'; | ||
}); | ||
const gaussian = new Gaussian(); | ||
expect(result[0].x).toBeCloseTo(69.938, 1); | ||
expect(result[0].y).toBeCloseTo(max, 2); | ||
expect(result[0].fwhm).toBeCloseTo(0.01, 4); | ||
expect(result[0].width).toBeCloseTo(Gaussian.fwhmToWidth(0.01), 4); | ||
expect(result[0].width).toBeCloseTo(gaussian.fwhmToWidth(0.01), 4); | ||
@@ -51,0 +52,0 @@ expect(result[1].x).toBeCloseTo(71.935, 2); |
@@ -29,3 +29,2 @@ import type { DataXY, DoubleArray } from 'cheminfo-types'; | ||
export interface Peak1D { | ||
index?: number; | ||
x: number; | ||
@@ -37,3 +36,4 @@ y: number; | ||
} | ||
export interface LastType { | ||
interface LastType { | ||
x: number; | ||
@@ -43,3 +43,3 @@ index: number; | ||
export interface GSDOptions { | ||
export interface IGSDOptions { | ||
noiseLevel?: number; | ||
@@ -60,3 +60,3 @@ sgOptions?: { | ||
export function gsd(data: DataXY, options: GSDOptions = {}): Peak1D[] { | ||
export function gsd(data: DataXY, options: IGSDOptions = {}): Peak1D[] { | ||
let { | ||
@@ -202,12 +202,13 @@ noiseLevel, | ||
let widthProcessor = getShape1D(shape).widthToFWHM; | ||
let widthToFWHM = getShape1D(shape).widthToFWHM; | ||
let signals: Peak1D[] = []; | ||
let lastK = -1; | ||
let possible: number, | ||
frequency: number, | ||
distanceJ: number, | ||
minDistance: number, | ||
gettingCloser: boolean; | ||
let possible: number; | ||
let frequency: number; | ||
let distanceJ: number; | ||
let minDistance: number; | ||
let gettingCloser: boolean; | ||
const peaks: Peak1D[] = []; | ||
const indexes: number[] = []; | ||
for (const minddYIndex of minddY) { | ||
@@ -239,4 +240,4 @@ frequency = xData[minddYIndex]; | ||
let width = Math.abs(intervalR[possible].x - intervalL[possible].x); | ||
signals.push({ | ||
index: minddYIndex, | ||
indexes.push(minddYIndex); | ||
peaks.push({ | ||
x: frequency, | ||
@@ -247,3 +248,3 @@ y: maxCriteria | ||
width: width, | ||
fwhm: widthProcessor(width), | ||
fwhm: widthToFWHM(width), | ||
shape, | ||
@@ -256,10 +257,10 @@ }); | ||
if (realTopDetection) { | ||
determineRealTop(signals, xData, yData); | ||
determineRealTop({ peaks, x: xData, y: yData, indexes }); | ||
} | ||
signals.sort((a, b) => { | ||
peaks.sort((a, b) => { | ||
return a.x - b.x; | ||
}); | ||
return signals; | ||
return peaks; | ||
} | ||
@@ -308,14 +309,16 @@ | ||
}; | ||
const determineRealTop = ( | ||
peakList: Peak1D[], | ||
x: DoubleArray, | ||
y: DoubleArray, | ||
): void => { | ||
let alpha: number, | ||
beta: number, | ||
gamma: number, | ||
p: number, | ||
currentPoint: number; | ||
for (const peak of peakList) { | ||
currentPoint = peak.index as number; // peakList[j][2]; | ||
const determineRealTop = (options: { | ||
peaks: Peak1D[]; | ||
x: DoubleArray; | ||
y: DoubleArray; | ||
indexes: number[]; | ||
}): void => { | ||
const { peaks, x, y, indexes } = options; | ||
let alpha: number; | ||
let beta: number; | ||
let gamma: number; | ||
let p: number; | ||
for (let i = 0; i < peaks.length; i++) { | ||
const peak = peaks[i]; | ||
let currentPoint = indexes[i]; | ||
// The detected peak could be moved 1 or 2 units to left or right. | ||
@@ -362,4 +365,2 @@ if ( | ||
p = (0.5 * (alpha - gamma)) / (alpha - 2 * beta + gamma); | ||
// console.log(alpha, beta, gamma, `p: ${p}`); | ||
// console.log(x[currentPoint]+" "+tmp+" "+currentPoint); | ||
peak.x = x[currentPoint] + (x[currentPoint] - x[currentPoint - 1]) * p; | ||
@@ -366,0 +367,0 @@ peak.y = |
@@ -8,3 +8,3 @@ import type { Peak1D } from '../gsd'; | ||
*/ | ||
interface BroadenPeaksOptions { | ||
export interface IBroadenPeaksOptions { | ||
/** | ||
@@ -27,3 +27,3 @@ * @default 2 | ||
peakList: Peak1D[], | ||
options: BroadenPeaksOptions = {}, | ||
options: IBroadenPeaksOptions = {}, | ||
): Peak1D[] { | ||
@@ -30,0 +30,0 @@ const { factor = 2, overlap = false } = options; |
@@ -5,2 +5,3 @@ import type { DataXY } from 'cheminfo-types'; | ||
import { optimize } from 'ml-spectra-fitting'; | ||
import type { IOptimizationOptions } from 'ml-spectra-fitting'; | ||
import { xFindClosestIndex } from 'ml-spectra-processing'; | ||
@@ -12,11 +13,3 @@ | ||
* This function try to join the peaks that seems to belong to a broad signal in a single broad peak. | ||
* @param {Array} peaks - A list of initial parameters to be optimized. e.g. coming from a peak picking [{x, y, width}]. | ||
* @param {object} [options = {}] - options | ||
* @param {number} [options.width=0.25] - width limit to join peaks. | ||
* @param {object} [options.shape={}] - it's specify the kind of shape used to fitting. | ||
* @param {string} [options.shape.kind = 'gaussian'] - kind of shape; lorentzian, gaussian and pseudovoigt are supported. | ||
* @param {object} [options.optimization = {}] - it's specify the kind and options of the algorithm use to optimize parameters. | ||
* @param {string} [options.optimization.kind = 'lm'] - kind of algorithm. By default it's levenberg-marquardt. | ||
* @param {number} [options.optimization.options.timeout = 10] - maximum time running before break in seconds. | ||
* @param {object} [options.optimization.options = {}] - options for the specific kind of algorithm. | ||
* @param peaks - A list of initial parameters to be optimized. e.g. coming from a peak picking [{x, y, width}]. | ||
*/ | ||
@@ -29,10 +22,24 @@ | ||
}; | ||
/** | ||
* broadRatio | ||
* @default 0.0025 | ||
*/ | ||
broadRatio: number; | ||
} | ||
interface OptionsType extends Partial<GetSoftMaskOptions> { | ||
width?: number; | ||
export interface IJoinBroadPeaksOptions extends Partial<GetSoftMaskOptions> { | ||
/** | ||
* width limit to join peaks. | ||
* @default 0.25 | ||
*/ | ||
broadWidth?: number; | ||
/** | ||
* it's specify the kind of shape used to fitting. | ||
*/ | ||
shape?: Shape1D; | ||
optimization?: { kind: string; timeout: number }; | ||
mask?: boolean[]; | ||
/** | ||
* it's specify the kind and options of the algorithm use to optimize parameters. | ||
*/ | ||
optimization?: IOptimizationOptions; | ||
broadMask?: boolean[]; | ||
} | ||
@@ -43,8 +50,8 @@ | ||
peakList: Peak1D[], | ||
options: OptionsType = {}, | ||
options: IJoinBroadPeaksOptions = {}, | ||
): Peak1D[] { | ||
let { | ||
mask, | ||
broadMask, | ||
shape = { kind: 'gaussian' }, | ||
optimization = { kind: 'lm', timeout: 10 }, | ||
optimization = { kind: 'lm', options: { timeout: 10 } }, | ||
sgOptions = { | ||
@@ -55,4 +62,4 @@ windowSize: 9, | ||
broadRatio = 0.0025, | ||
broadWidth = 0.25, | ||
} = options; | ||
let { width = 0.25 } = options; | ||
@@ -64,7 +71,7 @@ let max = 0; | ||
const peaks: Peak1D[] = JSON.parse(JSON.stringify(peakList)); | ||
const broadMask = !mask | ||
const mask = !broadMask | ||
? getSoftMask(data, peaks, { sgOptions, broadRatio }) | ||
: mask; | ||
: broadMask; | ||
if (broadMask.length !== peaks.length) { | ||
if (mask.length !== peaks.length) { | ||
throw new Error('mask length does not match the length of peaksList'); | ||
@@ -74,3 +81,3 @@ } | ||
for (let i: number = peaks.length - 1; i >= 0; i--) { | ||
if (broadMask[i]) { | ||
if (mask[i]) { | ||
broadLines.push(peaks.splice(i, 1)[0]); | ||
@@ -89,3 +96,3 @@ } | ||
for (let i = 1; i < broadLines.length; i++) { | ||
if (Math.abs(broadLines[i - 1].x - broadLines[i].x) < width) { | ||
if (Math.abs(broadLines[i - 1].x - broadLines[i].x) < broadWidth) { | ||
candidates.x.push(broadLines[i].x); | ||
@@ -92,0 +99,0 @@ candidates.y.push(broadLines[i].y); |
@@ -5,2 +5,3 @@ import type { DataXY } from 'cheminfo-types'; | ||
import { optimize } from 'ml-spectra-fitting'; | ||
import type { IOptimizationOptions } from 'ml-spectra-fitting'; | ||
import { xGetFromToIndex } from 'ml-spectra-processing'; | ||
@@ -18,3 +19,3 @@ | ||
*/ | ||
interface OptimizePeaksOptions { | ||
export interface IOptimizePeaksOptions { | ||
/** | ||
@@ -37,19 +38,3 @@ * times of width to group peaks. | ||
*/ | ||
optimization?: { | ||
/** | ||
* kind of algorithm. By default it's levenberg-marquardt. | ||
* @default 'lm' | ||
*/ | ||
kind: string; | ||
/** | ||
* options for the specific kind of algorithm. | ||
*/ | ||
options: { | ||
/** | ||
* maximum time running before break in seconds. | ||
* @default 10 | ||
*/ | ||
timeout: number; | ||
}; | ||
}; | ||
optimization?: IOptimizationOptions; | ||
} | ||
@@ -60,3 +45,3 @@ | ||
peakList: Peak1D[], | ||
options: OptimizePeaksOptions = {}, | ||
options: IOptimizePeaksOptions = {}, | ||
): Peak1D[] { | ||
@@ -75,3 +60,3 @@ const { | ||
}, | ||
}: OptimizePeaksOptions = options; | ||
}: IOptimizePeaksOptions = options; | ||
@@ -116,10 +101,6 @@ if (data.x[0] > data.x[1]) { | ||
if (currentRange.x.length > 5) { | ||
let { peaks: optimizedPeaks }: { peaks: Peak1D[] } = optimize( | ||
currentRange, | ||
peaks, | ||
{ | ||
shape, | ||
optimization, | ||
}, | ||
); | ||
let { peaks: optimizedPeaks } = optimize(currentRange, peaks, { | ||
shape, | ||
optimization, | ||
}); | ||
results = results.concat(optimizedPeaks); | ||
@@ -126,0 +107,0 @@ // eslint-disable-next-line curly |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
6496317
63509
Updatedml-spectra-fitting@^3.0.1