Skip to content

Commit 3b11b29

Browse files
feat: change peaks shape
1 parent f25c8a3 commit 3b11b29

4 files changed

Lines changed: 76 additions & 53 deletions

File tree

src/component/modal/EditPeakShapeModal.tsx

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { DialogFooter } from '@blueprintjs/core';
2+
import styled from '@emotion/styled';
23
import { yupResolver } from '@hookform/resolvers/yup';
34
import type { Peak1D } from '@zakodium/nmr-types';
45
import { useState } from 'react';
56
import { useForm } from 'react-hook-form';
7+
import { Button } from 'react-science/ui';
68
import * as Yup from 'yup';
79

810
import { useDispatch } from '../context/DispatchContext.js';
9-
import ActionButtons from '../elements/ActionButtons.js';
1011
import type { LabelStyle } from '../elements/Label.js';
1112
import Label from '../elements/Label.js';
1213
import { NumberInput2Controller } from '../elements/NumberInput2Controller.js';
@@ -17,6 +18,14 @@ import { useActiveNucleusTab } from '../hooks/useActiveNucleusTab.js';
1718
import { usePanelPreferences } from '../hooks/usePanelPreferences.js';
1819
import { formatNumber } from '../utility/formatNumber.js';
1920

21+
22+
const FooterContainer = styled.div`
23+
display: flex;
24+
justify-content: flex-end;
25+
gap: 5px;
26+
`;
27+
28+
2029
type Shape = NonNullable<Peak1D['shape']>;
2130

2231
type Kind =
@@ -40,9 +49,9 @@ function getValues(peak: Peak1D, kind: Kind): Shape {
4049
const shapeData =
4150
(shape?.kind || '').toLocaleLowerCase() !== kind
4251
? {
43-
...getKindDefaultValues(kind),
44-
...(shape?.fwhm && { fwhm: shape?.fwhm }),
45-
}
52+
...getKindDefaultValues(kind),
53+
...(shape?.fwhm && { fwhm: shape?.fwhm }),
54+
}
4655
: shape;
4756

4857
return shapeData as Shape;
@@ -104,17 +113,23 @@ function InnerEditPeakShapeModal(props: Required<EditPeakShapeModalProps>) {
104113
resolver: yupResolver(validation(kind)) as any,
105114
});
106115

107-
function changePeakShapeHandler(values: any) {
108-
dispatch({
109-
type: 'CHANGE_PEAK_SHAPE',
110-
payload: {
111-
id: peak.id,
112-
shape: {
113-
...values,
116+
function changePeakShapeHandler(applyToAll = false) {
117+
118+
void handleSubmit((values) => {
119+
120+
dispatch({
121+
type: 'CHANGE_PEAK_SHAPE',
122+
payload: {
123+
id: !applyToAll ? peak.id : undefined,
124+
shape: {
125+
...values,
126+
},
114127
},
115-
},
116-
});
117-
onCloseDialog();
128+
});
129+
onCloseDialog();
130+
131+
})();
132+
118133
}
119134

120135
function handleChangeKind({ value }: { value: Kind }) {
@@ -162,13 +177,18 @@ function InnerEditPeakShapeModal(props: Required<EditPeakShapeModalProps>) {
162177
)}
163178
</>
164179
</StyledDialogBody>
165-
<DialogFooter>
166-
<ActionButtons
167-
style={{ flexDirection: 'row-reverse', margin: 0 }}
168-
onDone={() => handleSubmit(changePeakShapeHandler)()}
169-
doneLabel="Save"
170-
onCancel={() => onCloseDialog?.()}
171-
/>
180+
<DialogFooter >
181+
<FooterContainer >
182+
<Button variant="outlined" intent="danger" onClick={() => onCloseDialog?.()}>
183+
Cancel
184+
</Button>
185+
<Button intent="primary" onClick={() => changePeakShapeHandler()}>
186+
Apply
187+
</Button>
188+
<Button intent="success" data-action="apply" onClick={() => changePeakShapeHandler(true)} >
189+
Apply to all
190+
</Button>
191+
</FooterContainer>
172192
</DialogFooter>
173193
</StandardDialog>
174194
);

src/component/panels/PeaksPanel/PeaksPanel.tsx

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { usePreferences } from '../../context/PreferencesContext.js';
1111
import { useToaster } from '../../context/ToasterContext.js';
1212
import { useAlert } from '../../elements/Alert.js';
1313
import { useActiveSpectrumPeaksViewState } from '../../hooks/useActiveSpectrumPeaksViewState.js';
14-
import useCheckExperimentalFeature from '../../hooks/useCheckExperimentalFeature.js';
1514
import { useFormatNumberByNucleus } from '../../hooks/useFormatNumberByNucleus.js';
1615
import useSpectrum from '../../hooks/useSpectrum.js';
1716
import { booleanToString } from '../../utility/booleanToString.js';
@@ -47,7 +46,6 @@ function PeaksPanelInner(props: PeaksPanelInnerProps) {
4746
const dispatch = useDispatch();
4847
const alert = useAlert();
4948
const toaster = useToaster();
50-
const isExperimental = useCheckExperimentalFeature();
5149

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

@@ -129,6 +127,25 @@ function PeaksPanelInner(props: PeaksPanelInnerProps) {
129127
peaksViewState;
130128

131129
const leftButtons: ToolbarItemProps[] = [
130+
{
131+
disabled,
132+
icon: <SvgNmrPeaks />,
133+
tooltip: `${booleanToString(!showPeaksShapes)} peaks shapes`,
134+
onClick: () => toggleViewProperty('showPeaksShapes'),
135+
active: showPeaksShapes,
136+
},
137+
{
138+
disabled,
139+
icon: <SvgNmrFt />,
140+
tooltip: `${booleanToString(!showPeaksSum)} peaks sum`,
141+
onClick: () => toggleViewProperty('showPeaksSum'),
142+
active: showPeaksSum,
143+
},
144+
{
145+
icon: <FaThinkPeaks />,
146+
tooltip: 'Optimize peaks',
147+
onClick: optimizePeaksHandler,
148+
},
132149
{
133150
disabled,
134151
icon: <SvgNmrPeaks />,
@@ -143,32 +160,10 @@ function PeaksPanelInner(props: PeaksPanelInnerProps) {
143160
displayingMode === 'spread' ? 'Top of the peak' : 'Top of the spectrum',
144161
onClick: toggleDisplayingMode,
145162
active: displayingMode === 'spread',
146-
},
163+
}
164+
147165
];
148166

149-
if (isExperimental) {
150-
leftButtons.unshift(
151-
{
152-
disabled,
153-
icon: <SvgNmrPeaks />,
154-
tooltip: `${booleanToString(!showPeaksShapes)} peaks shapes`,
155-
onClick: () => toggleViewProperty('showPeaksShapes'),
156-
active: showPeaksShapes,
157-
},
158-
{
159-
disabled,
160-
icon: <SvgNmrFt />,
161-
tooltip: `${booleanToString(!showPeaksSum)} peaks sum`,
162-
onClick: () => toggleViewProperty('showPeaksSum'),
163-
active: showPeaksSum,
164-
},
165-
{
166-
icon: <FaThinkPeaks />,
167-
tooltip: 'Optimize peaks',
168-
onClick: optimizePeaksHandler,
169-
},
170-
);
171-
}
172167
return (
173168
<TablePanel isFlipped={isFlipped}>
174169
{!isFlipped && (

src/component/reducer/actions/PeaksActions.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ type AutoPeaksPickingAction = ActionType<
4646
type ChangePeaksShapeAction = ActionType<
4747
'CHANGE_PEAK_SHAPE',
4848
{
49-
id: string;
49+
id?: string;
5050
shape: Peak1D['shape'];
5151
}
5252
>;
@@ -92,9 +92,9 @@ function handleAddPeak(draft: Draft<State>, action: AddPeakAction) {
9292
y: candidatePeak.y,
9393
width: 1,
9494
shape: {
95-
kind: 'generalizedLorentzian',
95+
kind: 'pseudoVoigt',
9696
fwhm: 1,
97-
gamma: 0.5,
97+
mu: 0.5,
9898
},
9999
};
100100
spectrum.peaks.values.push(...mapPeaks([peak], spectrum));
@@ -121,9 +121,9 @@ function handleAddPeaks(draft: Draft<State>, action: AddPeaksAction) {
121121
y: peak.y,
122122
width: 1,
123123
shape: {
124-
kind: 'generalizedLorentzian',
124+
kind: 'pseudoVoigt',
125125
fwhm: 1,
126-
gamma: 0.5,
126+
mu: 0.5,
127127
},
128128
};
129129
spectrum.peaks.values.push(newPeak);
@@ -204,6 +204,14 @@ function handleChangePeakShape(
204204
const spectrum = getSpectrum(draft);
205205
if (!isSpectrum1D(spectrum)) return;
206206

207+
if (!id) {
208+
spectrum.peaks.values = spectrum.peaks.values.map((peak) => ({
209+
...peak,
210+
shape,
211+
}));
212+
return;
213+
}
214+
207215
const peakIndex = spectrum.peaks.values.findIndex((peak) => peak.id === id);
208216
if (peakIndex !== -1) {
209217
spectrum.peaks.values[peakIndex].shape = shape;

src/data/data1d/Spectrum1D/peaks/autoPeakPicking.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function autoPeakPicking(
4141
frequency,
4242
direction,
4343
sensitivity: 100,
44-
shape: { kind: 'lorentzian' },
44+
shape: { kind: 'pseudoVoigt', mu: 0.5, fwhm: 1 },
4545
noiseLevel: noise * noiseFactor,
4646
minMaxRatio, // Threshold to determine if a given peak should be considered as a noise
4747
realTopDetection: true,

0 commit comments

Comments
 (0)