Skip to content

Commit

Permalink
feat: use 2D data quadrants and reload assignment from JCAMP-DX (#1861)
Browse files Browse the repository at this point in the history
close: #1758 
* refactor: to use quandrants in 2D data

* feat: load jcamp with assignments

* chore: add filter for phase correction from camp

* chore: add test spectra with assignment
  • Loading branch information
jobo322 committed Nov 17, 2022
1 parent de4b9e1 commit 435e961
Show file tree
Hide file tree
Showing 23 changed files with 14,895 additions and 233 deletions.
226 changes: 53 additions & 173 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -80,7 +80,7 @@
"ml-stat": "^1.3.3",
"multiplet-analysis": "^2.0.0",
"nmr-correlation": "^2.3.3",
"nmr-load-save": "^0.4.8",
"nmr-load-save": "0.5.0",
"nmr-processing": "^9.2.0",
"nmredata": "^0.9.1",
"numeral": "^2.0.6",
Expand Down Expand Up @@ -133,4 +133,4 @@
"vite": "^3.2.2",
"vitest": "^0.24.4"
}
}
}
14,743 changes: 14,743 additions & 0 deletions public/data/acd/assignment.jdx

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions public/data/acd/jcampWithAssignment.json
@@ -0,0 +1,32 @@
{
"spectra": [
{
"data": {},
"source": {
"original": [],
"jcamp": null,
"jcampURL": "./data/acd/assignment.jdx"
},
"info": {
"nucleus": "1H",
"isFid": false,
"isComplex": true,
"dimension": 1,
"isFt": true,
"title": "1H TBI 293 K",
"solvent": "CD2Cl2",
"pulse": "zg30",
"experiment": "1d",
"temperature": 293,
"frequency": 300.202658313,
"type": "NMR SPECTRUM",
"probe": "5 mm TBI 1H/31P/D-BB Z-GRD Z8704/0003",
"acquisitionMode": 0,
"expno": 4,
"date": "2010-04-10T05:47:20.000Z"
}
}
],
"molecules": []
}

6 changes: 4 additions & 2 deletions src/component/2d/FooterBanner.tsx
Expand Up @@ -5,6 +5,7 @@ import { useContext, useMemo, Fragment } from 'react';
import { MF } from 'react-mf';

import { get1DDataXY } from '../../data/data1d/Spectrum1D/get1DDataXY';
import { Data2D } from '../../data/types/data2d';
import { BrushContext } from '../EventsTrackers/BrushTracker';
import { MouseContext } from '../EventsTrackers/MouseTracker';
import { useChartData } from '../context/ChartContext';
Expand Down Expand Up @@ -227,8 +228,9 @@ function FooterBanner({ layout, data1D }) {

const getZValue = () => {
if (trackID === LAYOUT.CENTER_2D) {
const { maxX, maxY, minX, minY, z } = data[activeSpectrum.index]
.data as any;
const { maxX, maxY, minX, minY, z } = (
data[activeSpectrum.index].data as Data2D
).rr as any;

const xStep = (maxX - minX) / (z[0].length - 1);
const yStep = (maxY - minY) / (z.length - 1);
Expand Down
2 changes: 1 addition & 1 deletion src/component/2d/fid/FidCanvas.tsx
Expand Up @@ -102,7 +102,7 @@ export function FidCanvas() {
}

function getImageData(spectrum: Datum2D) {
const matrix = matrixZPivotRescale(spectrum.data.z, {
const matrix = matrixZPivotRescale(spectrum.data.re.z, {
max: 255,
ArrayConstructor: Int16Array,
});
Expand Down
Expand Up @@ -15,7 +15,7 @@ function Spectrum2DHistogram({
data,
}: Spectrum2DHistogramProps) {
const processedData = useMemo(() => {
return processSnapPlot('2D', data, yLogBase);
return processSnapPlot('2D', data.rr, yLogBase);
}, [data]);

return (
Expand Down
@@ -1,12 +1,12 @@
import { xyReduce } from 'ml-spectra-processing';

import { Data1D } from '../../../../../data/types/data1d';
import { Data2D } from '../../../../../data/types/data2d';
import { MinMaxContent } from '../../../../../data/types/data2d/Data2D';
import { calculateSanPlot } from '../../../../../data/utilities/calculateSanPlot';

export function processSnapPlot<T extends '1D' | '2D'>(
dimension: T,
data: T extends '1D' ? Data1D : Data2D,
data: T extends '1D' ? Data1D : MinMaxContent,
yLogBase: number,
) {
const sanResult = calculateSanPlot(dimension, data);
Expand Down
6 changes: 3 additions & 3 deletions src/component/reducer/actions/DomainActions.ts
Expand Up @@ -87,7 +87,7 @@ function get2DDomain(state: State) {
const spectrum =
data.find((datum) => datum.id === activeSpectrum?.id) || null;
if (spectrum?.info.isFid) {
const { minX, maxX, minY, maxY } = (spectrum as Datum2D).data;
const { minX, maxX, minY, maxY } = (spectrum as Datum2D).data.rr;
xArray = [minX, maxX];
yArray = [minY, maxY];
} else {
Expand All @@ -100,7 +100,7 @@ function get2DDomain(state: State) {
datum.info.isFt,
) as Array<Datum2D>
).flatMap((datum: Datum2D) => {
return [datum.data.minX, datum.data.maxX];
return [datum.data.rr.minX, datum.data.rr.maxX];
});

yArray = (
Expand All @@ -111,7 +111,7 @@ function get2DDomain(state: State) {
d.info.isFt,
) as Array<Datum2D>
).flatMap((datum: Datum2D) => {
return [datum.data.minY, datum.data.maxY];
return [datum.data.rr.minY, datum.data.rr.maxY];
});
} catch (error) {
// TODO: handle error
Expand Down
5 changes: 4 additions & 1 deletion src/component/reducer/actions/SpectrumsActions.ts
Expand Up @@ -185,10 +185,13 @@ function addMissingProjectionHandler(draft, action) {

if (activeSpectrum?.id) {
const { index } = activeSpectrum;
const datum2D = state.data[index];
const info = datum2D.info;
for (let n of nucleus) {
const datum1D = getMissingProjection(
state.data[index],
datum2D.data.rr,
n,
info,
draft.usedColors,
);
draft.data.push(datum1D);
Expand Down
2 changes: 1 addition & 1 deletion src/component/reducer/actions/ZonesActions.ts
Expand Up @@ -68,7 +68,7 @@ function handleAutoZonesDetection(draft: Draft<State>, detectionOptions) {
function handleAutoSpectraZonesDetection(draft: Draft<State>) {
for (const datum of draft.data) {
if (datum.info.dimension === 2) {
const { minX, maxX, minY, maxY } = (datum as Datum2D).data;
const { minX, maxX, minY, maxY } = (datum as Datum2D).data.rr;
const detectionOptions = {
selectedZone: { fromX: minX, toX: maxX, fromY: minY, toY: maxY },
thresholdFactor: 1,
Expand Down
3 changes: 1 addition & 2 deletions src/data/SpectraManager.ts
Expand Up @@ -42,8 +42,7 @@ export function addJcamp(output, jcamp, options, usedColors) {
const name = options?.display?.name;
const { spectra: spectraIn } = processJcamp(jcamp, {
name,
noContours: true,
xy: true,
noContour: true,
keepRecordsRegExp: /.*/,
profiling: true,
});
Expand Down
4 changes: 2 additions & 2 deletions src/data/data2d/Processing2D.ts
@@ -1,6 +1,6 @@
import { Conrec } from 'ml-conrec';

import { Data2D } from '../types/data2d';
import { MinMaxContent } from '../types/data2d/Data2D';
import { calculateSanPlot } from '../utilities/calculateSanPlot';

export const defaultContourOptions = {
Expand Down Expand Up @@ -40,7 +40,7 @@ export default class Processing2D {

this.conrec = new Conrec(minMax.z, { xs, ys, swapAxes: false });

const sanResult = calculateSanPlot('2D', minMax as Data2D);
const sanResult = calculateSanPlot('2D', minMax as MinMaxContent);
this.median = sanResult.positive;

this.minMax = minMax;
Expand Down
9 changes: 5 additions & 4 deletions src/data/data2d/Spectrum2D/contours.ts
@@ -1,6 +1,7 @@
import { Conrec } from 'ml-conrec';

import { Data2D, Datum2D } from '../../types/data2d';
import { Datum2D } from '../../types/data2d';
import { MinMaxContent } from '../../types/data2d/Data2D';
import { calculateSanPlot } from '../../utilities/calculateSanPlot';

interface Level {
Expand Down Expand Up @@ -172,21 +173,21 @@ function drawContours(
return getContours(zoom, {
negative,
nbLevels: numberOfNegativeLayer,
data: datum.data,
data: datum.data.rr,
});
}

return getContours(zoom, {
nbLevels: numberOfPositiveLayer,
data: datum.data,
data: datum.data.rr,
});
}

interface ContoursCalcOptions {
negative?: boolean;
timeout?: number;
nbLevels: number;
data: Data2D;
data: MinMaxContent;
}

function getContours(zoomLevel, options: ContoursCalcOptions) {
Expand Down
26 changes: 14 additions & 12 deletions src/data/data2d/Spectrum2D/getMissingProjection.ts
Expand Up @@ -2,41 +2,43 @@ import { zoneToX } from 'ml-spectra-processing';

import { UsedColors } from '../../../types/UsedColors';
import { initiateDatum1D } from '../../data1d/Spectrum1D';
import { Datum2D } from '../../types/data2d/Datum2D';
import { Info2D } from '../../types/data2d';
import { MinMaxContent } from '../../types/data2d/Data2D';

/**
* calculate the missing projection
*/

export function getMissingProjection(
datum: Datum2D,
datum: MinMaxContent,
nucleus: string,
datumInfo: Info2D,
usedColors: UsedColors,
) {
let index = datum.info.nucleus.indexOf(nucleus);
let index = datumInfo.nucleus.indexOf(nucleus);
// temporary because nucleus was undefined;
if (index === -1) index = 0;

let info = {
nucleus: datum.info.nucleus[index], // 1H, 13C, 19F, ...
nucleus: datumInfo.nucleus[index], // 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,
};

let from = index === 0 ? datum.data.minX : datum.data.minY;
let to = index === 0 ? datum.data.maxX : datum.data.maxY;
let nbPoints = index === 0 ? datum.data.z[0].length : datum.data.z.length;
let from = index === 0 ? datum.minX : datum.minY;
let to = index === 0 ? datum.maxX : datum.maxY;
let nbPoints = index === 0 ? datum.z[0].length : datum.z.length;
let projection = new Float64Array(nbPoints);
if (index === 1) {
for (let i = 0; i < datum.data.z.length; i++) {
for (let j = 0; j < datum.data.z[0].length; j++) {
projection[i] += datum.data.z[i][j];
for (let i = 0; i < datum.z.length; i++) {
for (let j = 0; j < datum.z[0].length; j++) {
projection[i] += datum.z[i][j];
}
}
} else {
for (let i = 0; i < datum.data.z[0].length; i++) {
for (const z of datum.data.z) {
for (let i = 0; i < datum.z[0].length; i++) {
for (const z of datum.z) {
projection[i] += z[i];
}
}
Expand Down
18 changes: 6 additions & 12 deletions src/data/data2d/Spectrum2D/getSlice.ts
Expand Up @@ -14,7 +14,7 @@ interface SlicePosition {
}

export function getSlice(spectrum: Datum2D, position: SlicePosition) {
const data = spectrum.data;
const data = spectrum.data.rr;
const xStep = (data.maxX - data.minX) / (data.z[0].length - 1);
const yStep = (data.maxY - data.minY) / (data.z.length - 1);
const xIndex = Math.floor((position.x - data.minX) / xStep);
Expand All @@ -31,10 +31,7 @@ export function getSlice(spectrum: Datum2D, position: SlicePosition) {
};

let dataX = {
x: zoneToX(
{ from: spectrum.data.minX, to: spectrum.data.maxX },
spectrum.data.z[0].length,
),
x: zoneToX({ from: data.minX, to: data.maxX }, spectrum.data.z[0].length),
re: new Float64Array(spectrum.data.z[0].length),
};

Expand All @@ -50,15 +47,12 @@ export function getSlice(spectrum: Datum2D, position: SlicePosition) {
};

let dataY = {
x: zoneToX(
{ from: spectrum.data.minY, to: spectrum.data.maxY },
spectrum.data.z.length,
),
re: new Float64Array(spectrum.data.z.length),
x: zoneToX({ from: data.minY, to: data.maxY }, data.z.length),
re: new Float64Array(data.z.length),
};

let index = spectrum.data.z.length - 1;
for (let i = 0; i < spectrum.data.z.length; i++) {
let index = data.z.length - 1;
for (let i = 0; i < data.z.length; i++) {
dataY.re[i] += spectrum.data.z[index--][xIndex];
}
const horizontal = initiateDatum1D({ info: infoX, data: dataX }, {});
Expand Down
6 changes: 1 addition & 5 deletions src/data/data2d/Spectrum2D/initiateDatum2D.ts
Expand Up @@ -37,11 +37,7 @@ export function initiateDatum2D(options: any, usedColors = {}): Datum2D {
datum.originalInfo = datum.info;
datum.meta = { ...options.meta };
datum.data = {
z: [],
minX: 0,
minY: 0,
maxX: 0,
maxY: 0,
rr: { z: [], minX: 0, minY: 0, maxX: 0, maxY: 0 },
...options.data,
};
datum.originalData = datum.data;
Expand Down
2 changes: 1 addition & 1 deletion src/data/data2d/Spectrum2D/zones/getDetectionZones.ts
Expand Up @@ -65,7 +65,7 @@ function autoZonesDetection(data, options) {

function getSubMatrix(datum, selectedZone) {
const { fromX, toX, fromY, toY } = selectedZone;
const data = datum.data;
const data = datum.data.rr;
const xStep = (data.maxX - data.minX) / (data.z[0].length - 1);
const yStep = (data.maxY - data.minY) / (data.z.length - 1);
let xIndexFrom = Math.max(Math.floor((fromX - data.minX) / xStep), 0);
Expand Down
6 changes: 4 additions & 2 deletions src/data/data2d/filter2d/shiftX.ts
Expand Up @@ -10,8 +10,10 @@ export const name = 'Shift 2D X';
*/

export function apply(datum2D: Datum2D, shiftValue = 0) {
datum2D.data.minX += shiftValue;
datum2D.data.maxX += shiftValue;
for (const key in datum2D.data) {
datum2D.data[key].minX += shiftValue;
datum2D.data[key].maxX += shiftValue;
}
}

export function isApplicable() {
Expand Down
6 changes: 4 additions & 2 deletions src/data/data2d/filter2d/shiftY.ts
Expand Up @@ -8,8 +8,10 @@ export const name = 'Shift 2D Y';
* @param {number} [shiftValue=0]
*/
export function apply(datum2D: Datum2D, shiftValue = 0) {
datum2D.data.minY += shiftValue;
datum2D.data.maxY += shiftValue;
for (const key in datum2D.data) {
datum2D.data[key].minY += shiftValue;
datum2D.data[key].maxY += shiftValue;
}
}

export function isApplicable() {
Expand Down
4 changes: 3 additions & 1 deletion src/data/types/data2d/Data2D.ts
@@ -1,4 +1,4 @@
export interface Data2D {
export interface MinMaxContent {
z: Array<Array<number>>;
minX: number;
minY: number;
Expand All @@ -7,3 +7,5 @@ export interface Data2D {
maxY: number;
maxZ: number;
}

export type Data2D = Record<string, MinMaxContent>;

0 comments on commit 435e961

Please sign in to comment.