diff --git a/src/data/data2d/Spectrum2D/getSlice.ts b/src/data/data2d/Spectrum2D/getSlice.ts index 1f676eb87..9db8ee747 100644 --- a/src/data/data2d/Spectrum2D/getSlice.ts +++ b/src/data/data2d/Spectrum2D/getSlice.ts @@ -1,6 +1,12 @@ -import type { NmrData1D, NmrData2DFid, NmrData2DFt } from 'cheminfo-types'; +import type { + NmrData1D, + NmrData2D, + NmrData2DFid, + NmrData2DFt, +} from 'cheminfo-types'; import { zoneToX } from 'ml-spectra-processing'; import type { Spectrum1D, Spectrum2D } from 'nmr-load-save'; +import { Info2D } from 'nmr-processing'; import { TraceDirection } from '../../../component/reducer/Reducer'; import { initiateDatum1D } from '../../data1d/Spectrum1D'; @@ -15,6 +21,12 @@ interface SlicePosition { y: number; } +const BASE_INFO = { + isFid: false, + isComplex: false, // if isComplex is true that mean it contains real/ imaginary x set, if not hid re/im button . + dimension: 1, +}; + interface SliceOptions { sliceType?: 'real' | 'imaginary' | 'both'; } @@ -26,69 +38,61 @@ export function getSlice( ): Record | undefined { const { sliceType = 'real' } = options; const { data: spectraData, info } = spectrum; - const realData = info.isFid - ? (spectraData as NmrData2DFid).re - : (spectraData as NmrData2DFt).rr; - const imaginaryData = info.isFid - ? (spectraData as NmrData2DFid).im - : (spectraData as NmrData2DFt).ir; - const xLength = realData.z[0].length; - const yLength = realData.z.length; + const real = getRealData(spectraData, info); + const imaginary = getImaginaryData(spectraData, info); + + const xLength = real.z[0].length; + const yLength = real.z.length; - const xStep = (realData.maxX - realData.minX) / (xLength - 1); - const yStep = (realData.maxY - realData.minY) / (yLength - 1); - const xIndex = Math.floor((position.x - realData.minX) / xStep); - const yIndex = Math.floor((position.y - realData.minY) / yStep); + const xStep = (real.maxX - real.minX) / (xLength - 1); + const yStep = (real.maxY - real.minY) / (yLength - 1); + const xIndex = Math.floor((position.x - real.minX) / xStep); + const yIndex = Math.floor((position.y - real.minY) / yStep); - if (xIndex < 0 || xIndex >= realData.z[0].length) return; - if (yIndex < 0 || yIndex >= realData.z.length) return; + if (xIndex < 0 || xIndex >= real.z[0].length) return; + if (yIndex < 0 || yIndex >= real.z.length) return; const infoX = { nucleus: info.nucleus[0], // 1H, 13C, 19F, ... - isFid: false, - isComplex: false, // if isComplex is true that mean it contains real/ imaginary x set, if not hid re/im button . - dimension: 1, + ...BASE_INFO, }; const infoY = { nucleus: info.nucleus[1], // 1H, 13C, 19F, ... - isFid: false, - isComplex: false, // if isComplex is true that mean it contains real/ imaginary x set, if not hid re/im button . - dimension: 1, - }; - - const dataX: NmrData1D = { - x: zoneToX({ from: realData.minX, to: realData.maxX }, xLength), - re: new Float64Array(xLength), + ...BASE_INFO, }; - const dataY: NmrData1D = { - x: zoneToX({ from: realData.minY, to: realData.maxY }, yLength), - re: new Float64Array(yLength), - }; + const dataX = initiateData(real.minX, real.maxX, xLength); + const dataY = initiateData(real.minY, real.maxY, yLength); if (['real', 'both'].includes(sliceType)) { for (let i = 0; i < xLength; i++) { - dataX.re[i] += realData.z[yIndex][i]; + dataX.re[i] += real.z[yIndex][i]; } for (let i = 0; i < yLength; i++) { - dataY.re[i] += realData.z[i][xIndex]; + dataY.re[i] += real.z[i][xIndex]; } } - if (imaginaryData && ['imaginary', 'both'].includes(sliceType)) { + if (imaginary && ['imaginary', 'both'].includes(sliceType)) { infoX.isComplex = true; - infoY.isComplex = true; dataX.im = new Float64Array(xLength); - dataY.im = new Float64Array(yLength); - for (let i = 0; i < xLength; i++) { - dataX.im[i] += imaginaryData.z[yIndex][i]; + dataX.im[i] += imaginary.z[yIndex][i]; } - for (let i = 0; i < yLength; i++) { - dataY.im[i] += imaginaryData.z[i][xIndex]; + //FT spectra vertical slicing should use ri instead of ir + const imaginaryVerticalData = getImaginaryData(spectraData, info, { + ftObjectKey: 'ri', + }); + + if (imaginaryVerticalData) { + infoY.isComplex = true; + for (let i = 0; i < yLength; i++) { + dataY.im = new Float64Array(yLength); + dataY.im[i] += imaginaryVerticalData.z[i][xIndex]; + } } } @@ -96,3 +100,29 @@ export function getSlice( const vertical = initiateDatum1D({ info: infoY, data: dataY }); return { horizontal, vertical }; } + +function initiateData(from: number, to: number, length: number): NmrData1D { + return { + x: zoneToX({ from, to }, length), + re: new Float64Array(length), + }; +} + +function getRealData(data: NmrData2D, info: Info2D) { + if (info.isFid) { + return (data as NmrData2DFid).re; + } + return (data as NmrData2DFt).rr; +} +function getImaginaryData( + data: NmrData2D, + info: Info2D, + options: { ftObjectKey?: 'ir' | 'ri' } = {}, +) { + if (info.isFid) { + return (data as NmrData2DFid).im; + } + const { ftObjectKey = 'ir' } = options; + + return (data as NmrData2DFt)?.[ftObjectKey]; +}