Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
616 changes: 282 additions & 334 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@
"@hookform/resolvers": "^5.2.2",
"@tanstack/react-form": "^1.29.1",
"@tanstack/react-table": "^8.21.3",
"@zakodium/nmr-types": "^0.5.11",
"@zakodium/nmrium-core": "^0.7.16",
"@zakodium/nmrium-core-plugins": "^0.7.21",
"@zakodium/nmr-types": "^0.5.12",
"@zakodium/nmrium-core": "^0.7.19",
"@zakodium/nmrium-core-plugins": "^0.7.24",
"@zakodium/pdnd-esm": "^1.0.2",
"@zip.js/zip.js": "^2.8.26",
"cheminfo-font": "^1.27.0",
Expand All @@ -98,7 +98,7 @@
"ml-spectra-processing": "^14.28.1",
"ml-tree-similarity": "^2.2.0",
"nmr-correlation": "2.3.3",
"nmr-processing": "^22.10.1",
"nmr-processing": "^22.11.0",
"numeral": "^2.0.6",
"openchemlib": "^9.22.0",
"openchemlib-utils": "^8.15.0",
Expand Down
17 changes: 12 additions & 5 deletions src/component/1d/BrushTracker1D.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ export function BrushTracker1D({ children }: Required<PropsWithChildren>) {
'matrixGeneration',
activeTab,
);
const { defaultPeakShape } = usePanelPreferences('peaks', activeTab);

const { logger } = useLogger();
const scaleState = useScaleChecked();
const convertToPPM = usePixelToPPMConverter();
Expand Down Expand Up @@ -205,12 +207,14 @@ export function BrushTracker1D({ children }: Required<PropsWithChildren>) {
});
break;
}
case options.peakPicking.id:
case options.peakPicking.id: {
const { startX, endX } = brushData;
dispatch({
type: 'ADD_PEAKS',
payload: brushData,
payload: { startX, endX, defaultPeakShape },
});
break;
}
case options.databaseRangesSelection.id:
propagateEvent();
break;
Expand Down Expand Up @@ -304,6 +308,7 @@ export function BrushTracker1D({ children }: Required<PropsWithChildren>) {
logger,
dispatchPreferences,
activeTab,
defaultPeakShape,
openAnalysisModal,
width,
height,
Expand Down Expand Up @@ -420,13 +425,14 @@ export function BrushTracker1D({ children }: Required<PropsWithChildren>) {
switch (keyModifiers) {
case primaryKeyIdentifier: {
switch (selectedTool) {
case 'peakPicking':
case 'peakPicking': {
const { x } = event;
dispatch({
type: 'ADD_PEAK',
payload: event,
payload: { x, defaultPeakShape },
});
break;

}
case 'integral':
dispatch({
type: 'CUT_INTEGRAL',
Expand Down Expand Up @@ -494,6 +500,7 @@ export function BrushTracker1D({ children }: Required<PropsWithChildren>) {
},
[
activeTab,
defaultPeakShape,
dispatch,
dispatchPreferences,
getModifiersKey,
Expand Down
9 changes: 8 additions & 1 deletion src/component/header/AutoPeakPickingOptionPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import { useToaster } from '../context/ToasterContext.js';
import Label from '../elements/Label.js';
import { NumberInput2Controller } from '../elements/NumberInput2Controller.js';
import { Select2Controller } from '../elements/Select2Controller.js';
import { useActiveNucleusTab } from '../hooks/useActiveNucleusTab.ts';
import {
MIN_AREA_POINTS,
useCheckPointsNumberInWindowArea,
} from '../hooks/useCheckPointsNumberInWindowArea.js';
import { usePanelPreferences } from '../hooks/usePanelPreferences.ts';

import { headerLabelStyle } from './Header.js';
import { HeaderWrapper } from './HeaderWrapper.js';
Expand Down Expand Up @@ -60,6 +62,8 @@ export function AutoPeakPickingOptionPanel() {
const dispatch = useDispatch();
const pointsNumber = useCheckPointsNumberInWindowArea();
const toaster = useToaster();
const nucleus = useActiveNucleusTab();
const { defaultPeakShape } = usePanelPreferences('peaks', nucleus);
const {
handleSubmit,
formState: { isValid },
Expand All @@ -74,7 +78,10 @@ export function AutoPeakPickingOptionPanel() {
if (pointsNumber > MIN_AREA_POINTS) {
dispatch({
type: 'AUTO_PEAK_PICKING',
payload: values,
payload: {
options: values,
defaultPeakShape,
},
});
} else {
toaster.show({
Expand Down
60 changes: 41 additions & 19 deletions src/component/modal/EditPeakShapeModal.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { DialogFooter } from '@blueprintjs/core';
import styled from '@emotion/styled';
import { yupResolver } from '@hookform/resolvers/yup';
import type { Peak1D } from '@zakodium/nmr-types';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { Button } from 'react-science/ui';
import * as Yup from 'yup';

import { useDispatch } from '../context/DispatchContext.js';
import ActionButtons from '../elements/ActionButtons.js';
import type { LabelStyle } from '../elements/Label.js';
import Label from '../elements/Label.js';
import { NumberInput2Controller } from '../elements/NumberInput2Controller.js';
Expand All @@ -17,6 +18,12 @@ import { useActiveNucleusTab } from '../hooks/useActiveNucleusTab.js';
import { usePanelPreferences } from '../hooks/usePanelPreferences.js';
import { formatNumber } from '../utility/formatNumber.js';

const FooterContainer = styled.div`
display: flex;
justify-content: flex-end;
gap: 5px;
`;

type Shape = NonNullable<Peak1D['shape']>;

type Kind =
Expand Down Expand Up @@ -55,7 +62,7 @@ function validation(kind: Kind) {
});
}

const KINDS: Array<{ label: string; value: Kind }> = [
export const PEAKS_SHAPES: Array<{ label: string; value: Kind }> = [
{
value: 'gaussian',
label: 'Gaussian',
Expand Down Expand Up @@ -104,17 +111,19 @@ function InnerEditPeakShapeModal(props: Required<EditPeakShapeModalProps>) {
resolver: yupResolver(validation(kind)) as any,
});

function changePeakShapeHandler(values: any) {
dispatch({
type: 'CHANGE_PEAK_SHAPE',
payload: {
id: peak.id,
shape: {
...values,
function changePeakShapeHandler(applyToAll = false) {
void handleSubmit((values) => {
dispatch({
type: 'CHANGE_PEAK_SHAPE',
payload: {
id: !applyToAll ? peak.id : undefined,
shape: {
...values,
},
},
},
});
onCloseDialog();
});
onCloseDialog();
})();
}

function handleChangeKind({ value }: { value: Kind }) {
Expand All @@ -135,7 +144,7 @@ function InnerEditPeakShapeModal(props: Required<EditPeakShapeModalProps>) {
<>
<Label title="Kind:" style={labelStyle}>
<Select2
items={KINDS}
items={PEAKS_SHAPES}
selectedItemValue={kind}
onItemSelect={handleChangeKind}
/>
Expand Down Expand Up @@ -163,12 +172,25 @@ function InnerEditPeakShapeModal(props: Required<EditPeakShapeModalProps>) {
</>
</StyledDialogBody>
<DialogFooter>
<ActionButtons
style={{ flexDirection: 'row-reverse', margin: 0 }}
onDone={() => handleSubmit(changePeakShapeHandler)()}
doneLabel="Save"
onCancel={() => onCloseDialog?.()}
/>
<FooterContainer>
<Button
variant="outlined"
intent="danger"
onClick={() => onCloseDialog?.()}
>
Cancel
</Button>
<Button intent="primary" onClick={() => changePeakShapeHandler()}>
Apply
</Button>
<Button
intent="success"
data-action="apply"
onClick={() => changePeakShapeHandler(true)}
>
Apply to all
</Button>
</FooterContainer>
</DialogFooter>
</StandardDialog>
);
Expand Down
44 changes: 19 additions & 25 deletions src/component/panels/PeaksPanel/PeaksPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { usePreferences } from '../../context/PreferencesContext.js';
import { useToaster } from '../../context/ToasterContext.js';
import { useAlert } from '../../elements/Alert.js';
import { useActiveSpectrumPeaksViewState } from '../../hooks/useActiveSpectrumPeaksViewState.js';
import useCheckExperimentalFeature from '../../hooks/useCheckExperimentalFeature.js';
import { useFormatNumberByNucleus } from '../../hooks/useFormatNumberByNucleus.js';
import useSpectrum from '../../hooks/useSpectrum.js';
import { booleanToString } from '../../utility/booleanToString.js';
Expand Down Expand Up @@ -47,7 +46,6 @@ function PeaksPanelInner(props: PeaksPanelInnerProps) {
const dispatch = useDispatch();
const alert = useAlert();
const toaster = useToaster();
const isExperimental = useCheckExperimentalFeature();

const settingRef = useRef<SettingsRef | null>(null);

Expand Down Expand Up @@ -129,6 +127,25 @@ function PeaksPanelInner(props: PeaksPanelInnerProps) {
peaksViewState;

const leftButtons: ToolbarItemProps[] = [
{
disabled,
icon: <SvgNmrPeaks />,
tooltip: `${booleanToString(!showPeaksShapes)} peaks shapes`,
onClick: () => toggleViewProperty('showPeaksShapes'),
active: showPeaksShapes,
},
{
disabled,
icon: <SvgNmrFt />,
tooltip: `${booleanToString(!showPeaksSum)} peaks sum`,
onClick: () => toggleViewProperty('showPeaksSum'),
active: showPeaksSum,
},
{
icon: <FaThinkPeaks />,
tooltip: 'Optimize peaks',
onClick: optimizePeaksHandler,
},
{
disabled,
icon: <SvgNmrPeaks />,
Expand All @@ -146,29 +163,6 @@ function PeaksPanelInner(props: PeaksPanelInnerProps) {
},
];

if (isExperimental) {
leftButtons.unshift(
{
disabled,
icon: <SvgNmrPeaks />,
tooltip: `${booleanToString(!showPeaksShapes)} peaks shapes`,
onClick: () => toggleViewProperty('showPeaksShapes'),
active: showPeaksShapes,
},
{
disabled,
icon: <SvgNmrFt />,
tooltip: `${booleanToString(!showPeaksSum)} peaks sum`,
onClick: () => toggleViewProperty('showPeaksSum'),
active: showPeaksSum,
},
{
icon: <FaThinkPeaks />,
tooltip: 'Optimize peaks',
onClick: optimizePeaksHandler,
},
);
}
Comment thread
hamed-musallam marked this conversation as resolved.
return (
<TablePanel isFlipped={isFlipped}>
{!isFlipped && (
Expand Down
82 changes: 73 additions & 9 deletions src/component/panels/PeaksPanel/PeaksPreferences.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { forwardRef, memo, useCallback, useMemo } from 'react';
import { useForm } from 'react-hook-form';
import { useForm, useWatch } from 'react-hook-form';

import { usePreferences } from '../../context/PreferencesContext.js';
import { fieldLabelStyle } from '../../elements/FormatField.tsx';
import { GroupPane } from '../../elements/GroupPane.tsx';
import Label from '../../elements/Label.tsx';
import { NumberInput2Controller } from '../../elements/NumberInput2Controller.tsx';
import { Select2Controller } from '../../elements/Select2Controller.tsx';
import useNucleus from '../../hooks/useNucleus.js';
import { usePanelPreferencesByNuclei } from '../../hooks/usePanelPreferences.js';
import { PEAKS_SHAPES } from '../../modal/EditPeakShapeModal.tsx';
import { getUniqueNuclei } from '../../utility/getUniqueNuclei.js';
import type { NucleusPreferenceField } from '../extra/preferences/NucleusPreferences.js';
import { NucleusPreferences } from '../extra/preferences/NucleusPreferences.js';
Expand Down Expand Up @@ -101,17 +107,75 @@ export default memo(
});

useSettingImperativeHandle(ref, handleSubmit, saveHandler);
const currentPreferences = useWatch({ control, name: 'nuclei' });

return (
<PreferencesContainer>
{nuclei?.map((n) => (
<NucleusPreferences
control={control}
key={n}
nucleus={n}
fields={formatFields}
/>
))}
{nuclei?.map((n) => {
const kind = currentPreferences?.[n].defaultPeakShape?.kind;
return (
<NucleusPreferences
control={control}
key={n}
nucleus={n}
fields={formatFields}
renderBottom={() => (
<GroupPane
text="Default peak shape"
style={{ header: { color: '#005d9e' } }}
>
<Label title="Kind:" style={fieldLabelStyle}>
<Select2Controller
items={PEAKS_SHAPES}
control={control}
name={`nuclei.${n}.defaultPeakShape.kind`}
/>
</Label>

<Label title="FWHM:" style={fieldLabelStyle}>
<NumberInput2Controller
min={0}
control={control}
name={`nuclei.${n}.defaultPeakShape.fwhm`}
controllerProps={{
rules: { required: true },
defaultValue: 1,
}}
/>
</Label>

{kind === 'pseudoVoigt' && (
<Label title="Mu:" style={fieldLabelStyle}>
<NumberInput2Controller
min={0}
control={control}
name={`nuclei.${n}.defaultPeakShape.mu`}
controllerProps={{
rules: { required: true },
defaultValue: 0.5,
}}
/>
</Label>
)}
{kind === 'generalizedLorentzian' && (
<Label title="Gamma:" style={fieldLabelStyle}>
<NumberInput2Controller
min={-1}
max={2}
control={control}
name={`nuclei.${n}.defaultPeakShape.gamma`}
controllerProps={{
rules: { required: true },
defaultValue: 0.5,
}}
/>
</Label>
)}
</GroupPane>
)}
/>
);
})}
</PreferencesContainer>
);
}),
Expand Down
Loading
Loading